未分類

今回は流行り物のRustをやってみました。Web Assembly(以下wasm)を使うとweb上でも出来る!JavaScriptより速い!と巷で噂なのですが、実際のところどうなんだろうと言う話です。

お題はバブルソートで、JavaScriptで実施した場合と、wasmにしたRustで実施した場合の両方で時間を比較してみました。結果はこんな感じです(以下は画像ですが、動かしたい人はこちら。JavaScript+wasmなのでクライアント側で動きます)。

かかった時間が縦軸なので、あれあれ?JavaScriptの方が速い!というのが結論になってしまいました。原因は最後まで分からず、chromeのJavaScriptエンジンが速いだけなのかなぁと予想しています。以下では、調べた結果などを載せておきます。

未分類

なぜそんな説明をするのか?

そろそろLuxeritasからの移行を考えているからです。公開した以上どこかでメンテナンスをやめるなら、引き継ぎ可能な状態にしようという意味合いです。

どうして移行したいのか?

改変パッチの配布が面倒だからです。配布物に含まれるコードはGPLなのにminifyしたソースしか含んでいなかったり、各ファイルのライセンスが明確ではありません。通常GPLならminifyする前のソースを要求し、そのソースは再配布も堂々とできるのですが、これだけしっかり配布している中それらソースをどこにも置いていません。サイトを読む限りGPLについても独自の見解をお持ちのようで、弁護士を頼んで云々とあり、正直あんまり関わりたくありません。

本来であればパッチ配布などという形態にしなくても、gitリポジトリごとどこかに置いてもらえば、こちらもフォークして修正して公開できるわけです。あとはプルリクエスト出したりと健全な活動で取り込まれれば私の作業はなくなるし、リジェクトされても他の人がフォークしたものに取り込むのは容易なわけで、いずれにしても私の作業はかなり楽になります。極めつけが先のminifyソースなのですが…これは実際の作業で実感してもらうべきですね。

未分類

UI系JavaScriptの記事なら動かせてもいいなぁと思って実験してみました。

カスタムHTMLブロックを使う

以下のVueのサンプルコードを動かしてみる。

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-5">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>
</div>
<script type="text/javascript">
var app5 = new Vue({
  el: '#app-5',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})
</script>

これをカスタムHTMLブロックに貼り付けた結果が以下。

{{ message }}

結果

動いてるみたい。

未分類

背景

最近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
$ 手作業でライセンスの貼り付け

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