Movable TypeでBlurHashのハッシュ値を出力できるようにするプラグインです。

mt-plugin-BlurHash

以下のように、画像にダウンロードを待つ間にプレイスホルダー的にぼやけた画像を表示ことができるようになります。ぼやけた画像は1画像あたり30文字程度に圧縮されているのでHTMLと一緒にドキュメントに埋め込んでレスポンスとして返して、JavaScriptでcanvas要素で表示させるというやり方になっています。(疑似的に3G回線程度の速度でアクセスした状態にして動画を収録しています)

使い方

プラグインをインストールするとmt:AssetBlurHashタグが使えるようになります。以下のようなテンプレートで、画像のアセットのあるコンテキストでmt:AssetBlurHashを使ってハッシュ値を書き出します。

ハッシュ値を画像にするのはウェブページの場合にはJavaScriptを使うことになりますが、「読み込むだけで表示してくれるJavaScript」のようなものは用意されていないので、自分で用意する必要があります。そこはちょっと面倒ではありますが、デコードするライブラリはnpmでインストールすることはできるので、プラグインのデモに含まれている以下の程度の簡単なJavaScript(TypeScript)で表示することができます。

サポートしている環境

  • Movable Type 7

利用可能なImageDriver

  • ImageMagick
  • GraphicsMagick
  • Imager

ユーザー体験的にどうなのか?

個人的な意見としては、ぼやっと表示されることで確かに雰囲気はでるものの、正直なところこれだけで大きくユーザー体験が改善されるかというとちょっと分からないなと思っています。(しかしデータをとったら、きちんと体験が改善されているという結果がでるという可能性も大いにあると思いますが)
とはいえ、そこまで確かなものでもないとしても、表現の選択肢の一つとして持っておくにはよいものかなと思っています。

こんな感じで動くMovable Typeのプラグインです。

プラグインについて

先日、MovableType.netのブロックエディタをソフトウェア版のMovable Typeでも利用できるようになるプラグインのα版が公開されました。

このプラグインでは、「指定されたURLからOpen Graph Protocolを中心としたメタ情報を取得して、ブログカードと呼ばれるような見た目のリンクを生成する」というブロックタイプをブロックエディタに追加します。

エディタで生成されたブログカードをそのまま使うこともできますが、さらにカスタマイズして、メタ情報を使ってMTMLで任意のHTMLを書き出すこともできます。

mt-plugin-mtbe-OGPEmbed

筆者について

筆者はこの記事を書いている時点で、Movable Typeとブロックエディタの開発メンバーです。

このウェブサイト(blog.taaas.jp)の記事は個人の意見であり公開しているのは個人的なプロジェクトで、この記事のプラグインについても個人的なものではありますが、今回のプラグインはα版が未公開の時期から準備されてはいて製品との関連も強いため、念のため明示しておきます。

簡単な使い方

インストールするとMTブロックエディタに「OGPEmbed」のボタンが追加されるので、そこからブロックを追加して、URLを指定するとブログカードが挿入されます。

公開側では、単純にmt:ContentFieldValueで書き出した場合にはHTMLのみが書き出されます。書き出されるデータにはCSSは含まれないので、サイト毎に指定する必要があります。標準のCSSは以下のようなものです。

MTMLによるブログカードの生成

単純にmt:ContentFieldValueで書き出す他に、MTMLで書き出すこともできます。標準の出力と同じブロクカードは以下のMTMLで得ることができます。

mt:Varでは以下の情報を利用することができます。

  • meta{icon} : link[rel="icon"]またはlink[rel="shortcut"]
  • meta{ogType} : meta[property="og:type"]
  • meta{ogTitle} : meta[property="og:title"]またはtitle
  • meta{ogDescription} : meta[property="og:description"]またはmeta[name="description"]
  • meta[ogImage} : meta[property="og:image"](複数ある場合には最初の要素)
  • meta{ogImageWidth} : meta[property="og:image:width"]
  • meta{ogImageHeight} : meta[property="og:image:height"]
  • meta{ogUrl} : meta[property="og:url"]またはlink[rel="canonical"]
  • meta{ogSiteName} : meta[property="og:site_name"]

この記事について

この記事は Movable Type Advent Calendar 2020 の25日目の記事です。皆様お疲れさまでした。それでは良いお年を!

Movable Typeで動画の挿入をサポートするプラグインです。

ウェブサーバーに動画変換機能を入れることなく、ブラウザ上で動画をH.264のMP4に変換してMovable Typeへアップロードし、簡単にvideo要素で挿入できるようにします。

少し長い説明

一般的な公開サイトだと動画を挿入するときにはYouTubeを利用することが多いですが、非公開のサイトであったり、ごく短い動画であったりする場合には動画もMovable Typeで管理できると便利なことがあると思います。

2020年も終わりになるこのタイミングだと今更ではありますが、H.264のMP4の動画をvideo要素で埋め込めばほぼ全てのウェブブラウザで表示できるので、(転送量や帯域が問題にならないという条件がそろっていれば)ウェブサイトで動画を表示することは難しいことではありません。

また例えば、「ウェブマニュアルで動作を説明したい」というような場合にはGIFアニメーションが利用されることがありますが、その場合ある程度以上の解像度でスムーズに動くような内容にするとファイルが大きくなりすぎたり、コントロールの表示もできないので伝わりづらいという問題もありますが、短いMP4の動画にすることで解決できる場合もあります。

ただこれまで、ウェブサイトで動画を公開するのは以下の2点の難しさがあったと思います。

  • H.264のMP4の動画を簡単に用意するのが難しい
    • サーバー上で変換させるのは準備が...
    • ユーザー側でアプリで変換してもらうような運用はちょっと...
  • video要素で埋め込むのが難しい

このプラグインを使うと、これらの問題を解消して簡単に動画をアップロードして埋め込むことができるようになります。

制限事項

転送量や帯域の問題は解決しません

ビットレートの最適化や、ネットワーク環境に応じた動画をダウンロードさせるような賢いことはやらないので、大きなファイルサイズの動画は大きいままです。転送量や帯域の制限のある環境では特に、問題のないことを確認して利用する必要があります。

長い動画での利用には向いていません

このプラグインではウェブブラウザで同期的に、アップロード前に変換します。前述の通りそもそも大きなサイズの動画には向かないのですが、変換の実行にも時間がかかるため、長い動画の変換には向いていません。

使い方

インストール

リリース一覧からダウロードして、通常のMTのプラグインと同じようにインストールします。

埋め込みHTMLのカスタマイズ

埋め込みHTMLをMTMLでカスタマイズできます。

初期値のMTMLは以下の通りです。

利用するサイト、親のサイト、あるいはシステムレベルのテンプレートモジュールで、「VideoUploader::as_html」という名前のテンプレートを作成するとその内容が使われます。
例えば、動画の幅を640に固定したい場合には以下のように書くことができます。

Movable Type 7のr.4607以降では「改行を変換」の改善が行われ(r.4607ではそれに伴いpre要素で問題がありましたが、r.4608で修正されています)、r.4608ではUseTraditionalTransformerという環境変数が追加されるという形で「改行を変換」に関する選択肢が増えています。

今回作成したCheckHtmlTextTransformプラグインを使うと事前に変化を確認することができ、UseTraditionalTransformerを利用するべきかどうかを確認したり、アップデートに伴い修正が必要なデータを特定したりすることができます。

mt-plugin-CheckHtmlTextTransform/releases

Movable Typeのブロックエディタでブロックの並べ替えを行うときに、デフォルトだとブロックのタイプしか表示されておらず同じタイプのブロックの区別ができないので、概要を表示することのできるプラグインを作成しました。

https://github.com/usualoma/mt-plugin-ShowExcerptForSortBlock

  • テキスト系のブロックでは先頭の20文字
  • 画像系の場合は幅100pxにリサイズされた画像

という内容で、以下のように表示されるはずです。screenshot.jpg

tl;dr;

  • CSSでは同じセレクタを繰り返し指定でき、繰り返した分だけ詳細度が上がるので、「!important宣言」の変わりに利用できる(という邪悪なコンセプト)

具体例

「!important宣言」を使ったCSS
クラス名の繰り返しで置き換えたCSS

実用性

これは邪悪なコンセプトではあるのですが、以下のようなケースでは意外と実用性もあるかもしれません。

「!important宣言」よりもファイルサイズを小さくできるケース

例えば以下のような規約でCSSを書いているとして、(BEMを採用しているような想定です)

  • セレクタにIDは利用しない
  • 「!important宣言」は利用しない
  • 詳細度は深くしない

その中でユーティリティ的なクラス名を用意する場合、詳細度はクラス名を2回指定すれば標準の指定よりも高くなるので、「!important宣言」を使うよりも短い表記にすることができます。

「!important宣言」を使ったCSS
クラス名の繰り返しで置き換えたCSS

AMP対応で「!important宣言」を置き換えるケース

  • 既存のサイトをコストを掛けずにAMP対応したい
  • CSSは小さいので style[amp-custom] に入れてしまうことができそう
  • 「!important宣言」が使われている

という場合、AMPでは「!important宣言」の利用は禁止なので何かしらの対応が必要になりますが、クラス名の繰り返しに置き換えることで問題を解決できるかもしれません。

複数の優先度に分けたいケース

「!important宣言」では宣言ありとなしの2つの分け方しかありませんでしたが、クラス名の繰り返しを利用した場合には以下のような分け方もできます。

  • 普通 : 1回指定
  • やや優先 : 2回指定
  • 最優先 : 3回指定

新しい複雑さを呼び込むだけな気もしますが、うまいことルールを作ることができるのであれば、これが活きることもあるかもしれません。

SASSによる実装

sass-mixin-importantというモジュールを作りました。これを使うと以下のようにシンプルな記述でこの記事の方法を実現できます。

入力
出力

Cpanel::JSON::XSをロードしただけなのに

  • 投稿日:
  • by
  • カテゴリ:

tl; dr

Cpanel::JSON::XSをロードするとJSON::PP::Booleanに「""」のoverloadが追加される。

通常の文字列化では、素のJSON::PP::Booleanと同様に0または1になるということで影響はないが「overload::Method($obj, q{""})」のようなチェックを行っていた場合に動作が変わることがある。

サンプルコード

https://github.com/usualoma/trick-json-pp-booleanにサンプルコードがあります。

問題と原因

以下のようなテストがあった時に、

通常は成功するのですが、モジュールの依存関係でどこかでCpanel::JSON::XSがロードされていると失敗するという状況が発生しました。

原因はTest::More::is_deeplyが内部で「overload::Method($obj, q{""})」を使って文字列化可能か判断している部分があり、そこで挙動が変わっているというものでした。

以下のように書けば(expectedであるJSON::PP::true側も同じ挙動で変換されるため)どちらでも大丈夫です。

libmysqlclient.so.18はいかにしてlibz.so.1を壊したか

  • 投稿日:
  • by
  • カテゴリ:

追記(2020年5月6日)

以下の挙動は5.7.28で確認をしていましたが、5.7.30で修正されています。

結論

同じシンボルをGLOBALで公開している複数の共有ライブラリをdlopenを使って動的にロードした場合に、解決されるシンボルがファイル間で前後することがある。

ということが原因のようです。

サンプルコード

https://github.com/usualoma/break-zlibにサンプルコードがあります。

発生した問題

以下のようなDockerfileで環境を構築したときに

「(perlでImage::Magickを使って)PNG画像のサムネイルが生成できない」という問題が発生し、条件を絞り込んでいくとどうも「DBD::mysqlをImage::Magickよりも先に読み込んだ場合に生成できなくなる」ということが分かりました。ポイントは、

  • MySQL Yum Repositoryのmysql-community-libs-compatでlibmysqlclient.so.18をインストールしている
  • libmysqlclient.so.18にリンクされた共有ライブラリを動的な環境で読み込んでいる

というころにあるようです。

この環境では、以下のようにDBD::mysqlを先に読み込んだ場合には失敗し、後に読み込んだ場合には成功します。

さらに(識者からの助言をもらいつつ)もう少し追っていくと、PNG画像の読み込み時のgzipの初期化に失敗していることが分かりました。

以下のように、zlibを直接呼び出すperlモジュールでも問題が発生します。

発生条件

色々試した結果、https://github.com/usualoma/break-zlib/tree/master/srcにあるようなコードで、

  • libmysqlclient.so.18にリンクした共有ライブラリを作成
  • libz.so.1にリンクした共有ライブラリを作成
  • それらを、libmysqlclient ->libz の順に動的にロードする

というやり方で発生させることができました。

以下のようにLD_PRELOAD使った場合には発生しなかったので「ロードの順序」だけではなく、「動的にロードすること」が条件になりそうです。

発生した理由

$ ldd /usr/lib64/mysql/libmysqlclient.so.18

の結果にlibz.so.1が含まれてもいるのですが、

$ readelf -Ws /usr/lib64/mysql/libmysqlclient.so.18.1.0

の結果にも「inflateReset」のようなlibzのシンボルがGLOBALとして含まれており、結果としてlibzの共有ライブラリとして利用できるようになっているようです。

gdbでブレークポイントを設定して見ていったところ、

  • inflateReset2は、libz.so.1のもの
  • その中で呼ばれるinflateResetは、libmysqlclient.so.18のもの

というようになっていて、それぞれに含まれるzlibのバージョンの差異によりエラーが発生しているようでした。

mysql.specを見る限り、WITH_EMBEDDED_SHARED_LIBRARYは明示的に1を指定しているようなので、libzを含むところまでは意図してやっていそうでしたが、GLOBALになっている理由はよく分かりませんでした。(mysql-community-libsからインストールされる/usr/lib64/mysql/libmysqlclient.so.20.3.15には、libzが含まれているものGLOBALではありませんでした。)

感想

mysql-community-libs-compatをインストールすると依存関係でmysql-community-libsが入り、/usr/lib64/mysql/libmysqlclient.soがlibmysqlclient.so.20を指すようになるので、MySQL Yum Repositoryとしてはlibmysqlclient.so.20を推奨っぽいので、可能な場合にはそちらにリンクしたモジュールをビルドし直した方がいいのかもしれません。

ビルドをしたくない場合、CentOSのパッケージで済まそうとすると基本的にはlibmysqlclient.so.18にリンクされていて上の状況は割と発生しそうな気がするので、その場合にはlibz.so.1を先にロードしてあげたりするなどの対応が必要かもしれません。

Squooshでアップロード時に画像を最適化する

  • 投稿日:
  • by
  • カテゴリ:

tl;dr;

こんな感じで動くMovable Typeのプラグインです。

Squooshとは

Google Chrome Labsからリリースされている、サーバーを介さずブラウザだけで画像の最適化を行うことのできるツールです。

https://squoosh.app/

Squooshは基本的には外部との連携をサポートしていないのですが、GithubにClient-side APIというプルリクエストがあったので、これを現在の最新版に適用しつつ少し改造して、外部からAPI経由で呼び出して利用できるようにしています。(IE11とEdgeでは動作させることができませんでしたが。)

プラグインについて

動作

プラグインをインストールすると、アセットとして画像をアップロードしようとした際にSquooshが開かれるようになります。右側のペインで最適化の設定を行い、「アップロード」のボタンをクリックすると、変換された結果がアップロードされます。

「画像をアップロードする際にSquooshを適用する」のチェックを外してアップロードすると、Squooshを適用せずにそのままアップロードすることができます。

mt-plugin-squoosh-each-upload.png

またSquooshの適用する場合、アップロード時にファイル名を変更することができます。「IMG_1234.jpg」のような名前のファイルを、公開時には異なるファイル名にしたいことがあると思いますが、そういったケースでも事前にローカル環境でファイル名を変更しておくことなく、アップロード時にファイル名を指定することができます。

mt-plugin-Squoosh-rename.png

設定

システムのプラグイン設定で、Squooshをデフォルトで有効にするかどうかを指定することができます。

mt-plugin-Squoosh-system-config.png

またユーザー設定で、自分の好みに合わせてデフォルトで有効にするかどうかを指定することができます。

mt-plugin-Squoosh-per-user.png

動作するMTのバージョン

  • Movable Type 7

動作するブラウザ

  • Google Chrome
  • Firefox
  • Safari

リサイズ等を自動で行いたい場合

「指定した大きさへ自動でリサイズ」のようなことはこのプラグインではできないので、その場合にはImageUploadUtilityのようなプラグインを利用するとよいと思います。(ImageUploadUtility Proならウォーターマーク自動合成などの処理もできるようです。)

最適化を自動で行いたい場合

自動での最適化はこのプラグインではできないので、その場合にはLightFileのような画像軽量化サービスを利用するとよいと思います。

この記事について

この記事は Movable Type Advent Calendar 2019 の25日目の記事です。今年も無事完走できたようでほっとしました。参加された方、また楽しみに待っていただいた方、皆様お疲れさまでした。Advent Calendarを作成していただいた西山さん、ありがとうございました。それでは良いお年を!

tl;dr;

MTAppjQueryを使っている場合にはuser.jsに以下のような記述を追加すると、A要素の中にDIV要素をいれてもリッチテキストエディタに変更されてしまうというトラブルを回避できます。

どんな問題か

HTML5ではA要素に入れられる内容が結構幅広くなっているので、DIV要素も入れらるようになっているのですが、Movable Type(r.4603以下)のリッチテキストではソースモードで入れたとしても消されてしまったりという問題があります。

具体的には、ソースモードなどから以下のようなHTMLを入力した時に、WYSIWYGモードに戻して保存するとA要素が消えるなどの症状が発生します。

<a href="#"><div>contents</div></a>

ポイントは2点あって、それらが合わさって意図しない書き換えが発生しています。

  • A要素の中にDIV要素を入れることが正しくないと認識されてしまう。
  • A要素がトップレベルにあると、最上位の要素としてP要素が補完されてしまう。

これらを回避するのが上の設定です。

「forced_root_block: false」をすると最上位のP要素の補完がなくなるので、それが好ましくない場合には設定の方を以下のようにした上で、

記事を書くときに、以下のように「A要素を最上位にせずにDIV要素で囲む」などの運用でカバーすることもできると思います。

<div><a href="#"><div>contents</div></a></div>