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を先にロードしてあげたりするなどの対応が必要かもしれません。