未分類

背景

最近Dockerを使った記事を書くにあたり、シンタックスハイライターの対応言語が足りてないことに気付きました。シンタックスハイライターを実装しているのは、WordPressテーマのLuxeritasなのですが、このシンタックスハイライターに使われているprism.jsではもっと大量の言語に対応しています。そこで、今回必要になった、YAMLファイル(docker-compose.yml)、Dockerfile、 iniファイル(php.iniで欲しくなる)の3つの言語に簡単に対応してみました。

Luxeritasのコード解析

簡単とはいえ、説明書があるわけではないので、Luxeritasのコード解析をしないと、どこを修正していいか分かりません。調べてみたところ、大まかにいかの流れでシンタックスハイライターが動いています。

  1. シンタックスハイライターが扱える言語とその言語を表す文字列のリスト(wpfunc.php)を元にシンタックスハイライターの言語選択画面でリストアップする
  2. 記事のDB保存時にユーザーが選んだ言語を表す文字列を個々のコードブロックに紐づけて保存する
  3. 記事の表示時は、シンタックスハイライターを以下のように表示する
    1. コードブロックに紐付けられた言語を表す文字列と、先のリスト (wpfunc.php) を照合して、言語を確認(loadinline.php)
    2. その言語が複数の言語で構成されていればそれらを追加し、記事内で必要な言語のリストを作る(loadinline.php)
    3. 必要な言語のリストを元に、必要なprism.jsのファイルを特定し、最小限の組み合わせでJavaScriptファイルを合成(minify)してクライアントに返す
    4. クライアント側ではprism.jsの機能により、自動的に各言語はparseされてハイライトされていく

言語の追加

今回追加する言語は、複数の言語で構成される言語ではないので(例えばHTMLの中にJavaScriptが入るとか)、 シンタックスハイライターが扱える言語とその言語を表す文字列のリストに必要な言語を追加し、その言語に必要なprism.jsの部品を追加すれば完成です。

シンタックスハイライターが扱える言語の追加

wpfunc.php

diff --git a/inc/wpfunc.php b/inc/wpfunc.php
index fac76e8..7039e66 100644
--- a/inc/wpfunc.php
+++ b/inc/wpfunc.php
@@ -1970,6 +1970,9 @@ function thk_syntax_highlighter_list() {
                'highlight_sql'         => 'SQL',
                'highlight_vbnet'       => 'VB.NET',
                'highlight_vim'         => 'Vim',
+               'highlight_yaml'        => 'YAML',
+               'highlight_docker'      => 'Docker',
+               'highlight_ini'         => 'Ini',
        );
 }
 endif;

必要なprism.jsの部品を追加

今回は現在の最新リリースである、prism.js v1.16.0を取得し、その中からcomponents/prism-言語名.min.jsとなっているファイルを抽出し、必要な言語をLuxeritasパッケージ内にjs/prism/言語名.jsというファイルで配置しました。

パッチ

以下にまとめてあります。

未分類

ルクセリタスのコード表示部分をいじり、パス表示を追加してみました。

diff --git a/js/luxe-blocks.js b/js/luxe-blocks.js
index 47d3ce8..a6e77ef 100644
--- a/js/luxe-blocks.js
+++ b/js/luxe-blocks.js
@@ -4411,6 +4411,10 @@ window.addEventListener("DOMContentLoaded", function() {
         language: {
           type: "string",
           default: ""
+        },
+        filename: {
+          type: "string",
+          default: ""
         }
       },
       supports: {
@@ -4464,45 +4468,66 @@ window.addEventListener("DOMContentLoaded", function() {
             value: ""
           }];
         return Object.keys(luxeHighlighterList).forEach(function(e) {
-          c.push({
-            label: this[e],
-            value: e
-          })
-        }, luxeHighlighterList), l.push(s(d.SelectControl, {
-          label: u("Code Language", "luxeritas"),
-          value: a,
-          options: c,
-          onChange: function(e) {
-            return n({
-              language: e
-            })
-          }
-        })), t = s("p", null, u("* The theme can be changed from the CSS tab of Luxeritas menu.", "luxeritas")), [s(p.InspectorControls, {
-          key: "syntaxHighlighterInspectorControls"
-        }, s(d.PanelBody, {
-          title: u("Settings")
-        }, l, t)), s("div", {
-          className: r + " wp-block-code"
-        }, s(p.PlainText, {
-          value: i,
-          onChange: function(e) {
-            return n({
-              content: e
+            c.push({
+              label: this[e],
+              value: e
             })
-          },
-          placeholder: u("To the right, choose a code language from the block settings.", "luxeritas"),
-          "aria-label": u("Syntax Highlighter", "luxeritas")
-        }))]
+          }, luxeHighlighterList), l.push(s(d.SelectControl, {
+            label: u("Code Language", "luxeritas"),
+            value: a,
+            options: c,
+            onChange: function(e) {
+              return n({
+                language: e,
+                filename: o.filename
+              })
+            }
+          })),
+          l.push(s(d.TextControl, {
+            label: u("File Name", "luxeritas"),
+            value: o.filename,
+            onChange: function(e) {
+              return n({
+                language: a,
+                filename: e
+              })
+            }
+          })), t = s("p", null, u("* The theme can be changed from the CSS tab of Luxeritas menu.", "luxeritas")), [s(p.InspectorControls, {
+            key: "syntaxHighlighterInspectorControls"
+          }, s(d.PanelBody, {
+            title: u("Settings")
+          }, l, t)), s("div", {
+            className: r + " wp-block-code"
+          }, s(p.PlainText, {
+            value: i,
+            onChange: function(e) {
+              return n({
+                content: e
+              })
+            },
+            placeholder: u("To the right, choose a code language from the block settings.", "luxeritas"),
+            "aria-label": u("Syntax Highlighter", "luxeritas")
+          }))]
       },
       save: function(e) {
         var t = e.attributes,
           o = t.content,
           n = t.language.replace("highlight_", "");
-        return "" != n ? s("pre", {
-          className: "line-numbers language-" + n
-        }, s("code", {
-          className: "language-" + n
-        }, o)) : s("pre", null, s("code", null, o))
+        var obj;
+        if ("" != n) {
+          var pre = {
+            className: "line-numbers language-" + n,
+          };
+          if (t.filename) {
+            pre["data-label"] = t.filename;
+          }
+          obj = s("pre", pre, s("code", {
+            className: "language-" + n
+          }, o));
+        } else {
+          obj = s("pre", null, s("code", null, o));
+        }
+        return obj;
       }
     })
   }(),
diff --git a/languages/admin/luxeritas-ja-luxe-blocks.json b/languages/admin/luxeritas-ja-luxe-blocks.json
index 4d04781..8381a3c 100644
--- a/languages/admin/luxeritas-ja-luxe-blocks.json
+++ b/languages/admin/luxeritas-ja-luxe-blocks.json
@@ -200,6 +200,9 @@
                        "Code Language": [
                                "言語"
                        ],
+                       "File Name" : [
+                               "ファイル名"
+                       ],
                        "* The theme can be changed from the CSS tab of Luxeritas menu.": [
                                "※ テーマ(見た目)は Luxeritas メニューの CSS タブから変更できます。"
                        ],

luxe-blocks.jsはminifyされてたので、以下で整形してから編集してdiffを取っています。

$ npx js-beautify -s 2 luxe-blocks.js >luxe-blocks.js.new
$ mv luxe-blocks.js.new luxe-blocks.js

編集後は以下でminifyして使っています。

$ npx -p uglify-js uglifyjs luxe-blocks.js -c --output luxe-blocks.js.new
$ mv luxe-blocks.js.new luxe-blocks.js
$ 手作業でライセンスの貼り付け

上記作業はパッチにして以下にまとめてあります。

未分類

前提

  • dockerが使える
  • Visual Studio codeが使える
  • x-debugを使用する

docker

docker-compose.yml

version: "3.1"
services:
  wordpress:
    build: .
    restart: always
    ports:
      - 80:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - ./wordpress:/var/www/html
      - ./php.ini:/usr/local/etc/php/php.ini

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - ./db:/var/lib/mysql

(編集)2021/5/26 不要なvolumeの記述を削除

Dockerfile

FROM wordpress:php7.3
RUN pecl install xdebug \
  && docker-php-ext-enable xdebug

(編集)2021/5/26 誤ったWORKDIR設定を削除

ビルド時に以下のようなメッセージ(タイミングや環境によって異なる)が出るはずなので、これをphp.iniに追加する。

zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so

php.ini

post_max_size = 50M
upload_max_filesize = 50M
memory_limit = 256M
[xdebug]
xdebug.remote_enable=1
xdebug.remote_autostart=1
; ホスト側のIP
; host.docker.internalはdockerのhostマシンのIPを解決してくれます。
; hostマシン以外のIP/WindowとMAC以外の場合は適宜IPを調べて設定してください。
xdebug.remote_host=host.docker.internal
; 空いているport番号
xdebug.remote_port=9000
; xdebugの出力するログの場所。今回は適当に/tmp配下に。
xdebug.remote_log=/tmp/xdebug.log
; Dockerイメージビルド時のメッセージをコピペして追記
zend_extension=?

(追記)2021/5/26 xdebugのバージョンが2から3に上がったらしく、3になると設定変数の名前が大きく変わっている。ほぼ同じ内容を3にしてみた。

post_max_size = 50M
upload_max_filesize = 50M
memory_limit = 256M
[xdebug]
xdebug.mode=debug
xdebug.start_with_request=yes
; ホスト側のIP
; host.docker.internalはdockerのhostマシンのIPを解決してくれます。
; hostマシン以外のIP/WindowとMAC以外の場合は適宜IPを調べて設定してください。
xdebug.client_host=host.docker.internal
; 空いているport番号
xdebug.client_port=9000
; xdebugの出力するログの場所。今回は適当に/tmp配下に。
xdebug.log=/tmp/xdebug.log
; Dockerイメージビルド時のメッセージをコピペして追記
zend_extension=?

https://xdebug.org/docs/upgrade_guide/ja

Visual Studio code

.vscode/launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "pathMappings": {
                // {docker上のdocument root}:{ローカルのdocument root}
                "/var/www/html":"/path/to/wordpress"
            }
        }
    ]
}

参考サイト

未分類

今まではデフォルトのTwentyTwentyを使ってました。

個人的に特に不満はなかったのですが、まあいろいろやってみないとねってことで、テーマ変更にチャレンジしました。

基準は技術ブログで使えそうなテーマ。最初は検索でCoCoonとかがよく引っかかってたのですが、何かピンと来ない。何かみんな同じに見えるんですよね。

少し毛色の違うやつ…と探して海外のを見に行くと…出るわ出るわtechnologyがキーワードに入っててもトロピカルだったり、何か全然普通のテーマばかり。そしてfreeというキーワードも無視されてほとんど有料。押しの強い彼らに良いものを尋ねてはいけないようです。

初心に帰って、そう、Qiitaとかに近い使い勝手のtheme!と探してて見つけたのがコレ。Luxeritasです。

  • 目次が自動で入るらしい
  • カワイイ

ということで、とりあえず変えてみました。

未分類

まるっとプランで今回ドメインも借りてるわけですが、普通にWordPress(以下WP)を入れると、最初はHTTPでした。借りてるドメインではなく、VALUE-SERVERのサブドメインで、HTTPでアクセスする形ということです。

誰も見てないだろうし、何も守るものもないわけですが、一応認証してるサイトなので、いつまでもHTTPというわけにも行きません。そこで、このWPも借りてるドメインで、HTTPSでアクセスする形に対応してみました。

対応と言っても何をしたわけではなく、ブラウザのアドレスバーのスキームとホスト名部分を変えただけです。

ところが

普通にHTTPSでアクセスしてみると、スタイルシートの適用が全くされてない素のHTMLが表示されています。

よくよく見るとHTMLからリンクされているCSSなどが根こそぎHTTP + VALUE-SERVERのサブドメインになっています。chromeは優秀なのかこれを良しとせずエラーで弾き、GETしないため素のHTMLが表示されたというわけです。

PHPはよく知らないので結構探しましたが、WPはURLを2つ持っており、それをリンク先生成時のアドレスに使用しているため、 そうなっているようです。管理画面でいうと、設定の、

  • WordPress アドレス
  • サイトアドレス

です。これらはファイルではなく、Databaseのwp_optionsテーブルに保管されていました。

解決

なので、管理画面からこれらのURLをhttpsの所定のURLに書き換えることにより、リンク先のURLもその下のURLになり、無事スタイルも適用されました。

でもなんでアクセスされたURLが分かっているのに、わざわざ固定のURLからリンク先を生成しているのか?やや不思議な気持ちです。まあ負荷分散とかした際にリクエストURLが消えてしまうとかセキュリティ上の理由とかなんでしょうね。いずれにしても設定で出来るのではなく強制なのが気持ち悪いところです。