BETA

正規表現でカラーコードの場合のみダブルクーテーションを外すJavaScriptを書く

投稿日:2019-08-03
最終更新:2019-08-03
※この記事は外部サイト(https://labor.ewigleere.net/2019/08/03/js-...)からのクロス投稿です

個人的ニーズがあったのでやってみました。

前提

現在、arm-band/kiribi_ususamaで、ejsの変数とScssで共通の値を使用したいと考え、1つのYAMLファイル(commonvar.yml)に記述する方法を採用しています。

commonvar.ymlはヘッダの高さやメインカラーなどを記述しています。

color: "#333"  
bg-color: "#fff"  
main-color: "#00f"  
navbar-height: 80px  

ejsにcommonvar.ymlの内容を渡すために、gulp-ejsを使用して以下のようなタスクを組んでいます(簡略化のために途中関係のないところは省略したり修正したりしています)。

gulp.task('ejs', () => {  
    const strOrigin = fs.readFileSync(FILEPATH + 'commonvar.yml', { encoding: 'UTF-8' })  
    const commonVar = yaml.parse(strOrigin)  
    return gulp.src(${SRC_EJS_PATH}/**/*.ejs)  
    .pipe(plumber())  
    .pipe(data((file) => {  
        return { 'filename': file.path }  
    }))  
    .pipe(ejs({ commonVar }))  
    .pipe(rename({ extname: '.html' }))  
    .pipe(gulp.dest(DIST_HTML_PATH))  
})  

fs.readFileSyncを利用してファイルを読み込み、yamlとしてパースしてcommonVarに代入。.pipe(ejs({ commonVar }))でejsに渡す、と。

一方、Scssは直接渡す方法がなさそうなので、以下のようにしています。

gulp.task('yaml2sass', done => {  
    const strOrigin = fs.readFileSync(FILEPATH + 'commonvar.yml', { encoding: 'UTF-8' })  
    let strDist = ''  
    let strArray = strOrigin.split("\n")  
    for(let i = 0; i < strArray.length; i++) {  
        if(!(i === strArray.length - 1 && strArray[i].length === 0)) { //最後の空行以外  
            strDist += `$${strArray[i]};\n` //`$VARIABLE-NAME: VALUE;`と最初に`$`、最後に`;`を付ける形にする  
        }  
    }  
    strDist = strDist.replace(/\"/g, '') //ダブルクォーテーションを外す  
    fs.writeFileSync(`${SRC_SCSS_PATH}/_var.scss`, strDist) //`_var.scss`として出力  
    done()  
})  

commonvar.ymlをテキストファイルとして読み込み、Scssの構文に(無理やり)変換し、scssファイルとして出力、と。もっと上手い方法があれば良いのですが……。

経緯

ここまでの前提を基に、今回は以下のようなニーズを満たしたいと考えました。

  1. キービジュアルで使うキャッチコピー的なテキストが存在、かつ1文字ずつspanタグを付与したい(ejsでfor文で回す)
  2. Scssで一文字ずつエフェクトを付けたい(animation-delayを1.のspanごとにずらしたいので、Scssで文字数カウント(str-length)をしたい)

そこで、「commonvar.ymlにキャッチコピーを記述しておけば、両方で使えるのではないか?」と考えたわけです。

color: "#333"  
bg-color: "#fff"  
main-color: "#3dfa7a"  
navbar-height: 80px  
catch1: "\"オブジェクト\"を制する者は、"  
catch2: "JavaScriptを制する!"  

例えばこんな感じで、catch1, catch2を追加したわけです。

ただ、このままだとダブルクォーテーションは全て外されてしまうので、Scss側でcatch1, catch2は構文エラーになってしまいます。

そこで、yaml2sassタスクの中のダブルクォーテーションを外す処理をなくして、commonvar.ymlのカラーコードのダブルクォーテーションを外してしまえば良さそうです。

color: #333  
bg-color: #fff  
main-color: #3dfa7a  
navbar-height: 80px  
catch1: "\"オブジェクト\"を制する者は、"  
catch2: "JavaScriptを制する!"  

しかし、これではejsタスクでカラーコードが上手く認識されず、theme-colorが空文字列になってしまいました。

課題

前置きが長くなりました。やっと本題です。

ここまでの経緯を踏まえて、この課題を解決するためにcommonvar.ymlのうち、「値がカラーコードであるもののみダブルクォーテーションを外す」ようにyaml2sassタスクの中の処理を変更することにしました。

ということで、修正した結果が以下のコードとなります。

//元のコード  
    strDist = strDist.replace(/\"/g, '')  
//今回修正したコード  
    strDist = strDist.replace(/\"#([\da-fA-F]{6}|[\da-fA-F]{3})\"/g, function() {  
        return arguments[0].replace(/\"/g, '')  
    })  

コールバック関数はtestmatchにはなさそうだったので、replaceを二段構えにする形となりました。

外側のreplaceの第一引数が正規表現で(前後にダブルクーテーション付きの)カラーコードを判定している部分。

条件にマッチした場合にコールバック関数に入り、内側のarguments[0]にマッチした部分の文字列が入っています。

そのため、arguments[0]のダブルクォーテーションを外せば、課題で上げた「値がカラーコードであるもののみダブルクォーテーションを外す」という処理が実現できます。

ということで、これでテストプログラムを書いてOKだったので、採用。無事にニーズを満たすことができました。

参考

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

アルム=バンドのQrunch

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!