前提
現在、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文字ずつ
span
タグを付与したい(ejsでfor
文で回す) - 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, '')
})
コールバック関数はtest
やmatch
にはなさそうだったので、replace
を二段構えにする形となりました。
外側のreplace
の第一引数が正規表現で(前後にダブルクーテーション付きの)カラーコードを判定している部分。
条件にマッチした場合にコールバック関数に入り、内側のarguments[0]
にマッチした部分の文字列が入っています。
そのため、arguments[0]
のダブルクォーテーションを外せば、課題で上げた「値がカラーコードであるもののみダブルクォーテーションを外す」という処理が実現できます。
ということで、これでテストプログラムを書いてOKだったので、採用。無事にニーズを満たすことができました。