🎨

Sassで定義したカラー変数をWordPressのカラーパレットに自動反映する

2022/09/05に公開

こんにちは。一応2021年4月からエンジニアになった、たいきです!

今回は初記事ということで、WordPressのカスタマイズについて個人的に「イケてる」と思ったコードが書けたのでその紹介と解説をしてみたいと思います。

記事の流れはこんな感じです!

今回、実現させたかったこと

WordPressのブロックエディタのフォント色や背景色選択にデフォルトのカラーパレットがありますが、そのデフォルトの色を独自の組み合わせにカスタマイズすることがあると思います(僕は初めてやりましたw)

↑今回これを普通にカスタマイズしてみたのですが、WordPressのfunctions.phpとSassのカラー変数、CSSのスタイル記述と色を変えるたびにそれぞれコードを書き換えないといけなかったんです。(詳しくは下記のサイトを参考にしました。)

https://yosiakatsuki.net/blog/gutenberg-editor-color-palette/
  
そんななか職場の先輩から「そんなのSassの変数だけ変えれば反映されるようにできるよ、やってみ」と課題を与えてもらいました。

ということで今回、実現させたかったことは以下です。

functions.phpとCSSのそれぞれを更新しなくてもSassのカラー変数だけを更新すれば自動でカラーパレットが更新されるようにする。

通常のカラーカスタマイズのコードをおさらい

まず、通常のカラーパレットをカスタマイズする場合のコードを書いてみます。

// functions.php
function editor_color_palette(){
  add_theme_support('editor-color-palette', array(
    [
      'name' => 'primary',
      'slug'  =>  'primary',
      'color'  =>  '#4169e1'
    ],
    // ↑色を増やすごとにこの記述を増やす
    [
      'name' => 'secondary',
      'slug'  =>  'secondary',
      'color'  =>  '#778899'
    ],
    [
      'name' => 'wraning',
      'slug'  =>  'warning',
      'color'  =>  '#dc143c'
    ],
    [
      'name' => 'accent',
      'slug'  =>  'accent',
      'color'  =>  '#ffff00'
    ],
  ));
}

add_action('after_setup_theme',  'editor_color_palette');

↑各カラーを配列として登録するため、使用する色が増えるほどコードは長くなっていきます。

// _variables.scss
$colors:(
  primary: #4169e1,
  secondary: #778899,
  wraning: #dc143c,
  accent: #ffff00
);

$font-family: ~~~~~~~
// style.scss
// primary
.has-primary-color {
  color: map-get($colors, primary);
}
.has-primary-background-color {
  background-color: map-get($colors, primary);
}

// secondary
.has-secondary-color {
  color: map-get($colors, secondary);
}
.has-secondary-background-color {
  background-color: map-get($colors, secondary);
}
// この繰り返し
// wraning
.has~~~~~
・・・・・・・・・
・・・・・・・・・

// accent
~~~~~~~~

scssでも変数を使う場合は、カラーの変数宣言部分に記述を追加、スタイリング部分のscssファイルにはhas-○○-colorクラスとhas-○○-background-colorクラスに対してのスタイルの記述を増やし続ける形になります。
(※has-○○-colorなどはWordPressが自動で生成するクラス名です)

1つめの改善点(Sass)

まず最初にできそうな改善点としてscssファイル内の同じ記述の追加部分が考えられます。

これに関しては特段変わったことはなく、Sassの@each構文を使ってみました。

https://sass-lang.com/documentation/at-rules/control/each

// style.scss
@each $key, $color in $colors {
  .has-#{$key}-color {
    color: $color;
  }
  .has-#{$key}-background-color {
    background-color: $color;
  }
}

scssで全く同じ記述を繰り返していたので、_variables.scss内で定義していた変数colors内のcolor名をkeyに、カラーコードを$colorに格納し繰り返すように記載しています。

この書き方により、カラーパターンを増やしたい際は_variables.scssに色を追加するだけでいいことになります。

…と、ここまでは普通に簡単といいますか、誰でもやるような実装だと思います。

問題は親和性がないこのSassとWordPressで使用されているPHPをどう連結させて今回の目的を達成するか。ですよね?

ここから先は、WordPressというよりはPHPを使っての実装になりますが、頑張ってみたいと思います。

PHPを駆使してSass変数を取り込んでみる

現状書いているこのコード、黄色の配列部分は同じことを繰り返し書いているため繰り返しやループ文、または別にカラーパターンを配列として用意できれば問題なさそうだと考えました。

// functions.php
function editor_color_palette(){
  add_theme_support('editor-color-palette', array(
    [
      'name' => 'primary',
      'slug'  =>  'primary',
      'color'  =>  '#4169e1'
    ],
    // ↑色を増やすごとにこの記述を増やす
    [
      'name' => 'secondary',
      'slug'  =>  'secondary',
      'color'  =>  '#778899'
    ],
    [
      'name' => 'wraning',
      'slug'  =>  'warning',
      'color'  =>  '#dc143c'
    ],
    [
      'name' => 'accent',
      'slug'  =>  'accent',
      'color'  =>  '#ffff00'
    ],
  ));
}

add_action('after_setup_theme',  'editor_color_palette');

そこで考えた方法としては

1.PHPでSassの_variables.scssの中身を文字列として読み込む
2.読み込んだ文字列からカラー変数部分($colors)のみを取り出す
3.絞り込んだ文字列をPHPの配列に変換し、現在セットしている配列と置き換える

これらが上手くいけば実現できるのではないかと考えました。

1.PHPでSassの_variables.scssの中身を文字列として読み込む

これはこの様に書いてみました。

// functions.php
$str = file_get_contents(plugin_dir_path(__FILE__) . 'assets/scss/_variables.scss');

file_get_contents()関数で_variables.scssのファイル内をすべて文字列として取得して変数$strに格納しています。

ちなみにplugin_dir_pathを使っているのは、僕がプラグインを自作にてこのコードを書いているので_variables.scssファイルまでのパスがプラグイン内にあるためこのような記述をしています。

テーマ内のscssファイルを置く場合などは記述は随時変更してください。

また、このとき少し詰まった部分ですがファイルまでのパスではなくURLを使ってしまうとSSLの設定によってはfile_get_contentsでファイルを読み込めないエラーが発生する可能性があるのでパスで書くことをおすすめします。

https://www.php.net/manual/ja/function.file-get-contents.php

2. 読み込んだ文字列からカラー変数部分($colors)のみを取り出す

ここから少し難易度が上がります。

// functions.php
$str = file_get_contents(plugin_dir_path(__FILE__) . 'assets/scss/_variables.scss');

preg_match('/\$colors\:\((.*?)\);/s', $str, $m);

たぶん、まだWordPressを勉強始めたばかりの方には、この時点で????ってなってる人がいると思いますw

がんばって解説してみます。

上のコード内の黄色部分は正規表現を使っており、preg_match()関数で先ほど文字列として取得した変数str内に指定した正規表現とマッチングする文字列パターンを見つけて、変数mに配列として格納しています。

https://www.php.net/manual/ja/function.preg-match.php

正規表現やpreg_match()関数の詳細については今回は割愛しますが(正規表現については別の記事で書くかも)結果として変数mにはstr内の「$colors:(」で始まり「);」で終わる文字列を完全マッチング、または一部マッチングなどにわけて配列として格納されています。

なぜ、このようなマッチング処理が必要かというと、_variables.scssにcolors意外にもfontなど様々な変数を定義している場合、そのすべてを文字列として一度読み込んでいる状態になっているので$colors:で始まるなどのマッチング処理を行うことでカラー変数のみを取得することができます。

そして結果から言うと$m[1]には下の黄色部分のみが文字列として格納されている状態になります。

// 変数$str
$colors:(
  primary: #4169e1,
  secondary: #778899,
  wraning: #dc143c,
  accent: #ffff00
);

$font-family: ~~~~~~~

m[0]だとcolors~の部分なども含まれてしまいます。

ここまで来れば、PHPの配列に変換できそうな気がしてきませんか?

3.絞り込んだ文字列をPHPの配列に変換し、現在セットしている配列と置き換える

そろそろ大詰めです。

// functions.php
$str = file_get_contents(plugin_dir_path(__FILE__) . 'assets/scss/_variables.scss');

preg_match('/\$colors\:\((.*?)\);/s', $str, $m); 

foreach (explode("\n", trim($m[1])) as $line) { // $m[1]をtrimして\n(改行部分)で区切って配列化して$lineに
   $line = str_replace(',', '', trim($line));  // $lineをtrim後、カンマがあれば消して$lineに再代入
   $ary = explode(':', $line);  // $line内を「:」で区切って配列化し$aryに格納
   $colors[] = [                      // 新しい配列$colorsを定義し連想配列でname,slug,colorに$aryの中を代入
     'name' => $ary[0],
     'slug' => $ary[0],
     'color' => $ary[1],
   ];
}

上記の一行一行で何をやってるかはコメントアウトに書いていますが、変数aryを定義した時点ではary[0]にはscssのcolor名が、$ary[1]にはカラーコードが格納されている状態になります。

そのためそれを新たに定義した配列$colorsにname,slug,colorと連想配列として格納することで、どうでしょう? 初めに作りたかった記述になっています。

ちなみに今回使った関数trim(),explode(),str_replace()についてはコチラ↓
https://www.php.net/manual/ja/function.trim.php

https://www.php.net/manual/ja/function.explode.php

https://www.php.net/manual/ja/function.str-replace.php

まとめ

よって最終的に完成したコードはこうなります。

// style.scss
@each $key, $color in $colors {
  .has-#{$key}-color {
    color: $color;
  }
  .has-#{$key}-background-color {
    background-color: $color;
  }
}
// functions.php
function editor_color_palette(){
  $str = file_get_contents(plugin_dir_path(__FILE__) . 'assets/scss/_variables.scss');
  preg_match('/\$colors\:\((.*?)\);/s', $str, $m); 
  foreach (explode("\n", trim($m[1])) as $line) {
    $line = str_replace(',', '', trim($line));
    $ary = explode(':', $line);
    $colors[] = [
      'name' => $ary[0],
      'slug' => $ary[0],
      'color' => $ary[1],
    ];
  }

  add_theme_support('editor-color-palette', $colors);
}

 add_action('after_setup_theme',  $colors);
// _variables.scss
$colors:(
  primary: #4169e1,
  secondary: #778899,
  wraning: #dc143c,
  accent: #ffff00
);

$font-family: ~~~~~~~

これで、カラーパレットへの色の追加や変更は_variable.scssのみ変更すれば即反映される形になりました。

「いや、こんな面倒なことしなくてもたまに色変えるくらいそれぞれに記述すれば早いじゃん」

そう思った方もいるでしょう。ただ、このちょっとした自動化が成せたとき、僕はプログラムを書くことに悦びを覚えます。

正直、このコード書けたときはちょっと興奮しましたww

Discussion