MTMLとJavaScriptで、Movable TypeをHeadless CMSとして使う

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

Headless CMSとMovable TypeとData API

Headless CMSを簡単に説明すると、「コンテンツをグラフィカルな表現で閲覧するための機能をもたない、データを管理するためのバックエンド側の機能のみを提供するCMS。一般的にコンテンツの公開はAPIを通じて行われ、CMSとは切り離された方法でグラフィカルな表現に変換される。」といったところでしょうか。(英語版Wikipediaにはページはあったのですが、やや偏っている印象もあったので引用はしませんでした。)デバイスの多様化に伴い、数年前からよく聞くようになってきたCMSのトレンドの一つだと思います。

MTはテンプレートを書いてファイルとして書き出すのが基本なので、これを「グラフィカルな表現に変換する機能」すると、その面から見たときはHeadless CMSではないと考えるのが妥当だと思います。

しかし一方で、MTではData APIというRESTfulなAPIを使ってコンテンツを取り出すこともできるので、これを使えばMTをHeadless CMSと考える(Headless CMSとして使う)こともできると思います。

この記事では、

  • Data APIを利用して
  • しかしJavaScriptなどのプログラムを意識することなく
  • 馴染みのあるMTタグを使って
  • MTをHeadless CMSとして使う

ということを実現できるツールを紹介します。

MT Data API React

MT Data API Reactは、Data APIで取得したデータをMTタグで書いたテンプレートでHTMLに変換して表示することのできるツールです。

以下のURLで試すことができます。「ブログのエンドポイント」に試したいブログのData APIのエンドポイントを入れれば、そのデータでブラウザ上で対話的に動作を確認することができます。

https://usualoma.github.io/mt-data-api-react/docs/playground.ja.html

「開発環境」タブの手順で「SFTPでテンプレートを更新して確認」や、「開発環境」のタブの手順で「本番環境では軽量化のために書き出したテンプレートを利用する」といったこともできます。

特徴

MTタグを書くだけで簡単に設置できる

これが最大の特徴ですが、JavaScriptを1行も書くことなくMTタグを書くだけで設置できます。

「JavaScriptを使ってAPIで取得したデータを表示する」というのもシンプルな作業ではあるのですが、実際にやるとなると「Data APIの仕様を理解する」という学習は必要になります。またJavaScriptを使うので安易に実装するとXSSなどの脆弱性に繋がる可能性があります。

MovableTypeにある程度なれている場合には、MTタグを使ってHTMLを構築するのは容易なはずなので、新しい学習のコストや脆弱性のリスクなしに、簡単に設置することができます。

ただこの部分には課題もあり、現状では使えるタグは少ないので、「サイト全体を構築する」ということはまだ難しい状態です。

JSはそれほど重くない

読み込みに必要なJSは、圧縮した状態で90KBほどです(2019年12月現在)。軽いとはいえないサイズですが、利便性とのトレードオフで考えれば許容できるサイトも多いのではないかと思います。

用途

外部のサイトへの埋め込み

メインのサイトの表示としてではなく、外部のサイトへの埋め込みの用途として利用できると思います。

  • 「新製品の特設サイト」と「コーポレートサイト」を別のMT、別の組織で管理している
  • 「コーポレートサイト」でも「新製品」のニュースを表示したいが、デザインは「コーポレートサイト」の方で管理したい

というケースで、従来であれば「JSON形式でファイル書き出してからAJAXで読み込んで表示」という手順になったと思いますが、これを(内容を示し合わせた)JSONファイルを書き出したりすることなく、表示する側で柔軟に管理できるようになります。

Rubyの関数オブジェクト

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

tl;dr;

基本的には以下のページで説明されているとおりだと思います。

この記事は、これらを少し長めのコードで試してみたものです。

関数オブジェクトを取得

Object#methodで取得できるとのことで、まずは試してみました。

以下のことが分かりました。

  • トップレベルでのメソッド定義はmodule Kernelにプライベートメソッドとして追加される
    • トップレベルのselfであるmainで呼べるようになる
  • method(:hello) (つまり self.method(:hello) で)トップレベルの hello をオブジェクトとして取得できる
  • 定義したクラスのメソッドも instance.method(:hello) で取得できる

レシーバの確認

Object#methodから返ってくるのはclass Methodのオブジェクトで、「メソッドの実体(名前でなく)とレシーバの組を封入します」とのことなので、どのような意味か確認しました。

Object#methodを呼んだ際のレシーバが、暗黙のレシーバであるselfとして封入されていそうです。

Procはどうなっているか?

暗黙のレシーバの確認をしていて、そういえばProcだどどうなんだろうと思って調べてみました。

Procは「ブロックをコンテキスト(ローカル変数のスコープやスタックフ レーム)とともにオブジェクト化した手続きオブジェクトです」とのことなので、selfへの参照も含まれるということだと思います。

class UnboundMethodの存在

ここまで忘れていましたが、Module#instance_methodを使うと、レシーバをもたないオブジェクトを取得することができるようです。

Module#instance_method に「バインドできるのは、 生成元のクラスかそのサブクラスのインスタンスのみです。」とあるとおり、確かにサブクラスでもないObjectをbindしようとしたらTypeErrorになりました。

まとめ

  • Object#methodで関数オブジェクトを取得できる
  • 関数オブジェクト(MethodやProc)はレシーバの情報ももっていて、オブジェクトをcallした場合にはそれが暗黙のレシーバとして使われる
    • レシーバをもたないclass UnboundMethodもあるが、UnboundMethod#bindしないと呼べない

ということのようです。

これは何か?

iOSの「ショートカットアプリ」用のショートカットをサーバー側で生成して、iPhoneからはQRコードを読むだけでインストールできるようにする、Movable Typeのプラグインです。

ShortcutsApp

このプラグインを使って生成したショートカットでは「Data APIのURL」のような設定が最初から埋め込まれているので、iPhone側では何も設定することなく利用することができます。(「Webサービスのパスワード」も埋め込むことができますが、暗号化はされません。その辺りの問題については以前の「iOS12のショートカットアプリとMovable TypeのData API」のサンプルの記事の「サンプルを利用する場合の注意事項」参照してください)

使い方

プラグインのZIPファイルをダウンロードして、Movable Typeへインストールすると利用できるようになります。設定は特に必要ありません。

インストールすると左側のメニューに「ツール > ショートカット.app」が追加され、メニューをクリックすると利用できるショートカットの一覧が表示されます。一覧からは、「インストールボタンのクリック -> iOS端末でQRコードを読み込み -> 表示された画面からインストール」の流れでiOS端末にショートカットをインストールすることができます。

管理者ユーザーでアクセスしている場合には、一覧のインストールボタンの左側にユーザーアカウントの選択肢が表示されます。「パスワードを埋め込む」を選択した場合には、ここで選択したユーザーのWebサービスパスワードが埋め込まれたショートカットを用意できます。これを使うと「管理者ユーザーが代理でMT上で操作を行い、ショートカットの利用者にはメールでインストール用のURLを送る」というような運用をすることができます。

同梱されているショートカット

以下の2つのショートカットが同梱されています。

写真を投稿

「写真」アプリのシェアボタンから、ショートカットを選択するとそのまま記事を投稿できます。以前の記事の「iOS12のショートカットアプリとMovable TypeのData API」のサンプルで紹介したショートカットと同じものです。

「パスワードを埋め込む」を選択していない場合には、投稿時にWebサービスのパスワードの入力が必要になります。

再構築

すべてのテンプレートを再構築します。

システムコンテキストからインストールした場合にはMovable Type 内のすべてのサイトが、サイトのコンテキストでインストールした場合にはそのサイトが、それぞれ再構築されます。

Siriに再構築をお願いすることもできます。

ショートカットの追加

ショートカットは、「テーマ」のように後から追加することもできるようになっています。

ショートカットの書き出しファイルの仕様は以前の記事でも触れたのですが、アプリから書き出されるバイナリファイルをXML形式に変換して編集することが可能です。また、以前の記事の時点からの新しい発見もあって、「ショートカットアプリには、XML形式を再びバイナリに戻して読み込ませる必要がある」かと思っていたところ必ずしもそうではなく「shortcuts://import-shortcut というURLを使った場合には、XML形式のまま読み込ませることができる」ということが分かりました。このプラグインではこの方法を利用して、ショートカットをMTMLを使ったテンプレートで管理しています。バイナリ形式に戻す必要がないため(XMLファイルさえ生成できればよいので)、インストール先のサーバー環境を選ばずに動作するようになっています。

具体的なカスタマイズの手順

手順は以下の通りです。

  1. iOSのショートカットアプリでショートカットを作成する
  2. ファイルとして書き出す
  3. XML形式に変換する
  4. ショートカットの定義(プラグイン独自の shortcut.yaml )を書く
  5. プラグイン内のshortcutsディレクトリの下に入れる

1が非常につらい作業(ショートカットアプリ内で、GUIでかつ限りられた機能だけでのプログラミング)ではありますが、他は特に難しいことはないと思います。基本的にはテーマを追加するのと同じような手順です。

XML形式への変換

Macであれば以下のコマンドが利用できます。

plutil -convert xml1 -o MT用テンプレート.tmpl 書き出したファイル.shortcut

またはDockerを利用できる環境であれば、以下のコマンドが利用できます。

docker run -it --rm -v $PWD:/files usualoma/libplist plistutil -i /files/書き出したファイル.shortcut -o /files/MT用テンプレート.xml.shortcut

shortcut.yamlを書く

ショートカットの定義をshortcut.yamlに書きます。テーマでのtheme.yamlのようなもので、主なキーの意味は以下の通りです。

  • id : ショートカットのID
  • label : MTの管理画面上での名前
  • version : バージョン
  • name : インストール先のショートカットアプリでの名前
  • description : ショートカットの説明
  • install_instruction : インストールの手順などの説明文
  • view : 利用可能なコンテキスト(system、website、blog)
  • template : ショートカットのテンプレートのファイル
  • expires_in : インストール用URLの有効期限の秒数

同梱されているショートカットを雛形にすると簡単かもしれません。

トラブルシューティング

写真の投稿ができない

iOSの問題だと思うのですが、時々ショートカットが正常にインストールできないことがあり、「写真の情報を取得できない」という問題が発生することがあります。この問題は「インストール前に写真アプリを開いておく」ということで発生確率を下げることができそうなのですが、それでも発生することが稀にあります。

発生した場合には、インストールしたショートカットを一度削除して、インストールし直すという手順で修正されると思います。

まとめ

「写真アプリからのシェア操作で投稿できる」というのはなかなか新鮮な体験だと思うので、ぜひ試してもらえればと思います。

またこのプラグインの例ではでは「写真のアップロードから、記事の作成と公開」まで行っていますが、もっとシンプルに「写真をアップローロドするだけ」というようなショートカットも実際の運用では便利だったりすると思うので、ショートカットアプリとData APIを連携は考え方しだいで、いろいろと面白いことができそうな気がします。

この記事について

この記事は Movable Type Advent Calendar 2018 の10日目の記事です。

Happy Holidays!

発生する条件

php.iniで以下のように設定されている時に、multipart/form-dataでUTF-8の内容をPOSTすると文字化けすることがある。(application/x-www-form-urlencodedでは文字化けしない)

mbstring.encoding_translation = On
mbstring.http_input = auto
mbstring.internal_encoding = UTF-8

どんな流れで発生しているか?

PHPではPOST時のハンドラをMIMEタイプ毎に登録する仕組みになっているようで、mbstringでは以下の場所でapplication/x-www-form-urlencodedとmultipart/form-dataで別々のハンドラが登録されている。

https://github.com/php/php-src/blob/master/ext/mbstring/mbstring.c#L680-L681

application/x-www-form-urlencodedの場合はmbstring内でリクエストのボディ全体から文字コードを判定するため、期待した通りUTF-8として扱われる

multipart/form-dataの場合は以下の場所で文字コードの判別が行われるが、

https://github.com/php/php-src/blob/master/main/rfc1867.c#L427-L429

判別対象のデータが例えば以下のようなヘッダー行なので、

Content-Disposition: form-data; name="name"

「mbstring.http_input = auto」 => 「ASCII,UTF-8」だとASCIIだと判定されてしまい。その下に続く内容もASCIIとして「ASCII -> UTF-8」で変換が行われてしまう。

回避方法

以下のような方法がある。

  • 「mbstring.http_input = UTF-8」にする
  • フォーム要素に「multipart/form-data」をつけない
  • 全ての項目のname属性にマルチバイトの文字を入れる

以下のようなフォームであれば文字化けしない。

<form enctype="multipart/form-data" method="POST">
<input name="📛" value="天野" />
</form>

この記事について

iOS12で利用できるようになったショートカットアプリは、自分の好みの「手順」をSiriから呼び出せるようにしたりホーム画面にショートカットを作ったりできるというものですが、その中でどうやら「手順」としてウェブAPIへのリクエストをなかなか自由にできるらしいという話を聞いたので、それならばということで、Movable TypeのData APIとの連携を試してみました。

この記事では、実際の運用でありえそうなパターンとして以下の3つのサンプルを紹介します。

  • 写真を選択して記事を作成
    • 写真は複数選択が可能で、記事には写真を撮影した際の位置情報が付与されます。
  • Evernoteから記事を作成
  • コンテンツタイプとしてURLを収集

それぞれのパターンについて、項目の下の方にエクスポートした「.shortcut」へのリンクを置きました。iOS12でショートカットアプリをインストールしてあれば、実際にショートカットを試してみることもできます。(動画では実行時にパスワードが表示されてしまっていますが、「.shortcut」からインストールされるバージョンでは実行しただけでは表示されないように修正されています。)

対象になるMTのバージョン

コンテンツタイプを利用するサンプルではMT7が必要です。それ以外のサンプルはMT6でも動作します。

写真を選択して記事を作成

ショートカットアプリを使うと「共有シート」に項目を追加して、選択した写真を「ショートカット」に渡すことができるようになります。

このサンプルではそれを使って、以下の操作で記事を作成できるようにしてみました。

  1. 写真を選択(複数可)
  2. シェアボタンから、登録したショートカットを選択
  3. タイトルと本文を指定

写真はアセットとしてアップロードされ、記事の本文に挿入されます。(カスタムフィールド版もあります)写真に位置情報が含まれている場合には、緯度と経度も投稿情報に含まれます。

MTへ画像を投稿.shortcut

カスタムフィールド版

カスタムフィールド版では、「記事」に対して以下のようなベースネームを持つフィールドが設定されていることを想定しています。

  • image
  • latitude
  • longitude

1枚目の画像がimageのフィールドに入り、2枚目以降の画像は本文に挿入されます。

MTへ画像を投稿(カスタムフィールド版).shortcut

Evernoteから記事を作成

メモアプリや編集アプリからデータを受け取り、MTで記事を作成するパターンです。ここではEvernoteと連携させています。

Evernoteでは普通に書くとh2、h3などの細かい指定はできないため、以下のような形で置き換えるようにしています。

  • 太字 -> h3
  • リスト -> そのまま
  • その他 -> divなどは削除し、極力シンプルなHTMLになるようにする

変換結果がやや不安定なので、このサンプルは現実的に使い物になるかどうかはやや微妙です。Markdownの編集アプリからそのままMarkdownとして投稿などの方が現実的かもしれません。

EvernoteからMTへ投稿.shortcut

コンテンツタイプとしてURLを収集

スマートフォンからアクションすると考えると、「記事」よりも細かい(「ソーシャルブックマークに追加」程度の)粒度でなにかできるとよい場合もあると思います。このサンプルでは、以下のようなフローで記事作成を行うための「URLの収集」をショートカットでできるようにしてみました。

  • 記事にするURLをスマートフォンで収集しておく
  • 後で収集したURLを組み合わせて「まとめページ」をつくる

こういった場合には、MT7のコンテンツタイプが使えそうです。

  • URL
  • タイトル
  • og:image
  • 埋め込みHTML

といったフィールドをもつコンテンツタイプを作り、ここにデータを貯めていきます。「タイトル」「og:image」はショートカットの中で自動で取得します。「埋め込みHTML」はURLがTwitterの場合にのみ、oembedのAPIを使って自動で取得します。(少し拡張すれば、YouTubeなどoembedのAPIを提供している他のサービスでも取得できるようになります)

URLをMTへ保存.shortcut

管理画面の方は以下のような雰囲気です。

ref-page-type.png
「参照ページ」コンテンツタイプ
a-ref-page.png
参照ページの編集
curation-page-type.png
「まとめページ」コンテンツタイプ
a-curation-page.png
まとめページの編集

サンプルの紹介は以上になります。

サンプルを利用する場合の注意事項

これらのショートカットアプリではWebアプリのパスワードを利用するのですが、「テキストデータ」としてしか保存する方法が見つからなかったので、「ショートカット」を開くと確認できる状態で保存されます。一応、通常の使用では表示されないように工夫はしているのですが、アプリから開くと容易に表示可能です。特に強い権限を持つユーザーで利用する場合には注意が必要です。(「iCloudキーチェーン」が使えるとよさそうなのですが、それはまだできないようで。)

「ショートカット」の可能性

ショートカットアプリで作成した「ショートカット」は共有のために書き出すことができるのですが、書き出されるファイルは(バイナリの)plist形式なので、少し手を加えることでテキストエディタで編集することもできます。Macであれば以下のようなコマンドを実行することで編集が可能です。(Linuxにも同様の結果を得ることができるコマンドがあります)

テキストとして編集できることにより、例えば以下のようなことができるようになります。

  • エンドポイントの設定の埋め込み
  • ユーザーIDやパスワードの埋め込み
  • メッセージの多言語化

これらを利用することで、例えばリテラシーの高くないユーザーに対しても「(編集済みの)ショートカットを受け取ってインストールするだけで、エンドポイントやパスワードを設定しなくても利用できる」というようにすることができそうです。

まとめ

これはなかなか面白いものだと思います。上のサンプルよりもっとシンプルなものでも、例えば「アセットの一括アップロード」だけでも十分に役立ちそうなので、MTを使っているならば(特別にマッチするような運用ではなくても)普通に便利に使えるような気がしています。 パスワードをそのまま埋め込まざるを得ないなど、現状としては課題もありますが、それらは今後のアップデートを(あまり期待せずに)待ちたいと思います。