<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>blog.taaas.jp</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/" />
    <link rel="self" type="application/atom+xml" href="https://blog.taaas.jp/atom.xml" />
    <id>tag:blog.taaas.jp,2013-04-13://2</id>
    <updated>2025-12-24T22:14:56Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type</generator>

<entry>
    <title>🤶 10倍速いMovable Typeの再構築ツールをください 🧑‍🎄</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/10x-faster-rebuild-tool/" />
    <id>tag:blog.taaas.jp,2025://2.208</id>

    <published>2025-12-24T21:20:45Z</published>
    <updated>2025-12-24T22:14:56Z</updated>

    <summary>この記事は何か？Movable Typeの再構築（静的なファイルの生成）の高速化...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>この記事は何か？</h3><p>Movable Typeの再構築（静的なファイルの生成）の高速化に関する個人的な実験の記録です。</p><p>筆者の天野はMovable Typeの開発にエンジニアとして参加しており、開発元のシックス・アパートにも所属していますが、この記事で触れられているコードや結果については全て個人として実験した記録になります。</p><h3>比較対象</h3><p>今回はざっくりとした比較なので、ウェブブラウザのインターフェイスから再構築操作をした結果の処理時間をベースとします。「処理時間: 33秒」となっているので、ここからざっくり10倍速くできるかどうかを試します。</p><p><img src="https://blog.taaas.jp/CleanShot%202025-12-14%20at%2014.27.48%402x.jpg" alt="" width="834" height="627" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><p>対象のデータは以下のスクリプトで投入しています。</p><script src="https://gist.github.com/usualoma/91b5d1137a47c8ee60f3c774ca8c80ab.js"></script><ul>
<li>1500文字程度の内容で365記事</li>
<li>12カテゴリ</li>
</ul><p>コンテンツタイプの方が最適化のしがいがありそうですが、手を広げると実装が大変なので最初のベンチマークとしてはこんなところかなと思います。</p><p>docker composeで起動した環境上での比較なので、DB（mysql）も全て同じ端末上で動作している状態です。</p><h3>アプローチ</h3><p>以下のアプローチで高速化を試みます。3点目についてはややチートっぽさがありますが、「互換性を切り捨てれば高速化できる」という面は往々にしてあるので、こういった試みの中では妥当な選択肢であると思います。</p><ul>
<li>Rustで実装する</li>
<li>複数スレッドで処理する</li>
<li>コストのかかる互換性は維持しない</li>
</ul><h3>Rustで実装する</h3><p>実行速度を優先すると2025年ではRustかGoあたりが有力な選択肢と思われますが、現状だと速度面やAIによる生成の効率など、公開されている調査結果を見るとRustが若干リードしているようなので、Rustを選びました。</p><p>またRustの方がWebAssemblyとの親和性が高く、ウェブブラウザ上やクラウドのエッジ上でも利用できる可能性があるというのも、特にMTとの関連では強みとなりそうです。</p><p>ウェブブラウザやエッジのランタイムだとTypeScriptという選択肢もあったりもします。MTのような使い方を踏まえるとTypeScriptの動的に拡張しやすいという点もとても魅力的なのですが、文字列操作が主な内容だと最速を目指すのは難しいと予想されるため、今回は選択肢に入れませんでした。</p><h3>rust-mtml-parser</h3><p>実は Rust にした理由はもう一つありまして、MTMLのパースは以前（今見たら3年前でした）書いた <a class="mt-rich-text-editor-embed-inline" href="https://github.com/usualoma/rust-mtml-parser" target="_blank" rel="noopener noreferrer" style="display: inline-block;"><img src="https://github.com/fluidicon.png" class="mt-rich-text-editor-embed-inline__icon" style="height: calc(1em * 1.3); width: auto; vertical-align: text-top; margin-right: 0.2em;" contenteditable="false" draggable="true"></a><span class="mt-rich-text-editor-embed-inline__title"><a class="mt-rich-text-editor-embed-inline" href="https://github.com/usualoma/rust-mtml-parser" target="_blank" rel="noopener noreferrer" style="display: inline-block;">GitHub - usualoma/rust-mtml-parser</a></span> というものを作っていて、これを使うと MTMLからASTを生成できるので、これを使いたいというのがありました。</p><p>上でも触れましたが、RustからはWebAssemblyを経由してnpmに変換する手段が用意されており、このパッケージもnpmのパッケージとして利用できるようにしています。以下は、npmパッケージを使ったパースと、パース結果のシリアライズ（整形）の実行例です。</p><script src="https://gist.github.com/usualoma/c6a97aa83696cf08a14041d1aec29f0b.js"></script><h3>rust-mtml-builder</h3><p>今回実装したのは、そのパーサーを使ってパースした結果から、MTタグを評価して静的ファイルに書き出す部分です。以下がリポジトリです。（一部の実装しか含まれていませんが、理由は後ほど説明します）</p><p><a class="mt-rich-text-editor-embed-inline" href="https://github.com/usualoma/rust-mtml-builder" target="_blank" rel="noopener noreferrer" style="display: inline-block;"><img src="https://github.com/fluidicon.png" class="mt-rich-text-editor-embed-inline__icon" style="height: calc(1em * 1.3); width: auto; vertical-align: text-top; margin-right: 0.2em;"></a><span class="mt-rich-text-editor-embed-inline__title"><a class="mt-rich-text-editor-embed-inline" href="https://github.com/usualoma/rust-mtml-builder" target="_blank" rel="noopener noreferrer" style="display: inline-block;">GitHub - usualoma/rust-mtml-builder</a></span></p><h3>実装のポイント</h3><p>作業のほとんどはそれぞれのMTタグを実装していくだけなので、そこに関しては特にポイントはありません。実装が進んで細かいチューニングの段階に入れば、書き込み時の文字列処理で低レベルな最適化が入ってくると思いますが、今回はそこまではやっていません。</p><p>再構築の（もしくはSSGのような機能一般での）処理のボトルネックは多くの場合「SQLの問い合わせ回数」と「ファイルの読み書きのIO待ち」なので、それらの点の解消が性能を向上させるためのポイントになります。</p><h3>結果</h3><p>今回作成したのはコマンドラインのツールなので、ウェブブウラウザからの実行と比較するのはフェアではないのですが、まあざっくりなのでよしとして、以下のような結果になりました。</p><script src="https://gist.github.com/usualoma/fbb086756fa0f7e669e0ca1a056e0fdd.js"></script><p>2秒以内で完了するようになりました。realと比べてuserやsysが大きいところから、マルチスレッドが使えていることが分かります。（この環境では10コアを利用しています）</p><p>なんちゃっての実装もあるので、作り込めば処理が複雑化して重くなる部分もあると思われるものの、一方で最適化も行っていないので、（多数のコアが使える環境であれば）10倍程度の高速化は十分に達成できそうだなという感触を得ることができました。</p><p>ちなみに並列化しないと（1コアのみを利用）以下のような結果ですが、それでも5倍程度は達成できそうです。</p><script src="https://gist.github.com/usualoma/e16d07a67e1025c8133062c3ceeac186.js"></script><h3>なぜ一部の実装しか含まれていないか？</h3><p>リポジトリにAGENT.mdが含まれていることが分かるように、例によって実装には生成AIを利用しています。</p><p>今回やってみて、（使ったのは GPT-5.2ですが、おそらくそれに限らず多くの）AIはMTタグの挙動をすでに良く知っているので互換性のある実装をさらっと進めることができ、特に面倒なMTタグの実装の部分では大きな力を発揮できることが分かりました。</p><p>しかしここで、MTの本体はかつてはGPL（MITやBSDではない）で公開されていた時代もあるものの、現在はソースは公開されているもののオープンソースのライセンスではないという状況があります。</p><p>AIによって生成されたコードが内容的に似ているかというと、似てはいないように見えました。MTタグの仕様は定義されているので、単純にそれを満たすように実装してもそのようなコードになると思われる内容ではあります。しかしそのようなものであったとしてもなお、「こんな内容がさっとできてこれを公開してもいいのか（あるいは、それがGPL時代のコードから学ばれたものだと仮定しても、それを翻案したものがMITなどで公開されてもいいのか）」という点から見て、公開して差し支えのないものという確信が持てなかったため、タグの実装の公開は控えることにしました。</p><p>自分が書ける以上の内容のコードが生成されること、内容を理解していないコードを公開すること、など、来年以降ますますそのような状況に直面することが多くなると思われますが、あらためて、なかなか考えさせらる機会となりました。</p><h3>この記事について</h3><p>この記事は<a href="https://adventar.org/calendars/11355" target="_blank" title="">Movable Type Advent Calendar 2025</a>の25日目の記事です！</p><p>今年も11月には<a href="https://www.mt-tokyo.net/mtddc2025/" target="_blank" title="">MTDDC Meetup TOKYO 2025</a>に参加ささせていただいて、直接いろいろな人と話ができて楽しかったです。（MT9のフィードバックをいただけるのはこれからだということが分かった）</p><p>そしてアドベントカレンダーでいつも通りの年末感で締めくくることができました。今年もお世話になりました。</p><p>それではみなさん良いお年をお迎えください！</p><p>（この記事はMT9を使って書かれています）</p>トフは<a href="//www.sixapart.jp/" rel="nofollow">シックス・アパート</a>の公式キャラクターです。<a rel="license" href="//creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> の下でライセンスされており、オリジナルは <a href="//www.sixapart.jp/about/toph.html" rel="nofollow">シックス・アパートのウェブサイト</a>で入手可能です。
]]>
        
    </content>
</entry>

<entry>
    <title>TophCheer - リッチテキストエディタの編集中にトフが応援してくれるMovable Typeプラグイン </title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/mt-plugin-TophCheer/" />
    <id>tag:blog.taaas.jp,2025://2.207</id>

    <published>2025-12-03T00:07:29Z</published>
    <updated>2025-12-10T23:55:17Z</updated>

    <summary>これは何か？ CMSの管理画面というのは基本的に無機質なものです。必須項目への入...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これは何か？</h3>
<p>CMSの管理画面というのは基本的に無機質なものです。必須項目への入力を忘れれば「入力してください」と素っ気なく怒られ、頑張って記事を書いたとしても誰も褒めてくれません。SNSのメッセージ入力画面などはあれほど背中を押してくれるのに。</p>
<p>これはMovable Type 9に搭載された新しいリッチテキストエディタ（MTRichTextEditor）に、<a href="http://tophlove.jp/" target="_blank" title="">トフ</a>が編集を応援してくれる機能を追加して編集中の気持ちを少しでも上げようと試みるMovable Typeプラグインです。</p>
<div data-mt-rich-text-editor-embed-object="">
<script type="module">
        if (!document.querySelector("#mt-rich-text-editor-embed-card-style")) {
            const style = document.createElement("style");
            style.id = "mt-rich-text-editor-embed-card-style";
            style.textContent = `
.mt-rich-text-editor-embed-card {
  margin: 10px;
  padding: 10px;
  border: 1px solid #eee;
  border-radius: 5px;
  display: flex;
  text-decoration: none;
}
.mt-rich-text-editor-embed-card:hover {
  border-color: #ccc;
}
.mt-rich-text-editor-embed-card__image img {
  max-width: 200px;
  max-height: 200px;
  margin-right: 10px;
}
.mt-rich-text-editor-embed-card__text {
  line-height: 1.5
}
.mt-rich-text-editor-embed-card__title {
  color: initial;
  font-weight: bold;
}
.mt-rich-text-editor-embed-card__description {
  margin-top: 5px;
  color: initial;
  text-decoration: none;
}
.mt-rich-text-editor-embed-card__site-name {
  margin-top: 5px;
  font-size: 80%;
  color: gray;
  display: flex;
  align-items: center;
}
.mt-rich-text-editor-embed-card__icon {
  max-width: 13px;
  max-height: 13px;
  margin-right: 5px;
}
`;
            document.head.appendChild(style);
        }
    </script><a class="mt-rich-text-editor-embed-card" href="https://github.com/usualoma/mt-plugin-TophCheer">
<div class="mt-rich-text-editor-embed-card__image"><img src="https://opengraph.githubassets.com/27d71400dd2ff768fb8e979aff05b842032f87151b84ac29dcb0beef3638fa81/usualoma/mt-plugin-TophCheer"></div>
<div class="mt-rich-text-editor-embed-card__text">
<div class="mt-rich-text-editor-embed-card__title">GitHub - usualoma/mt-plugin-TophCheer</div>
<div class="mt-rich-text-editor-embed-card__description">Contribute to usualoma/mt-plugin-TophCheer development by creating an account on GitHub.</div>
<div class="mt-rich-text-editor-embed-card__site-name"><img src="https://github.com/fluidicon.png" class="mt-rich-text-editor-embed-card__icon">
github.com
</div>
</div>
</a>
</div>
<div data-mt-rich-text-editor-embed-object=""><iframe width="640" height="375" src="https://www.youtube.com/embed/wtkjcnUuSk0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" title="mt-plugin-TophCheer"></iframe></div>
<h3>追加される機能</h3>
<ul>
<li>ステータスバーの領域でトフが跳ねて応援してくれます</li>
<li>行を追加するたびに文字数をカウントして応援してくれます</li>
<li>内容を踏まえてOpenAIのAPIを使ってメッセージを考えて応援してくれます</li>
</ul>
<h3>追加されない機能</h3>
<ul>
<li>トフは応援するだけで、記事を書いてはくれません</li>
</ul>
<h3>設定</h3>
<p>以下の項目を設定できます。</p>
<ul>
<li>Secret Key</li>
<li>モデル</li>
<li>システムプロンプト</li>
</ul>
<p><img data-mt-asset-id="307" src="https://blog.taaas.jp/assets_c/2025/12/CleanShot%202025-12-02%20at%2020.27.02%402x-thumb-900xauto-307.jpg" width="900" height="720" alt="" class="asset asset-image" style="display: block"></p>
<h3>実装の概要</h3>
<p>MTRichTextEditor がインストールされている環境だと、ステータスバーに表示するアイテムのための <code>MTRichTextEditor.Component.StatusbarItemElement</code> をグローバルで参照できます。これは <code>HTMLElement</code>を継承しいているので、これをさらに継承したクラスを定義してカスタム要素として定義することで、ステータスバーに表示するアイテムを追加できます。</p>
<h3>
<script src="https://gist.github.com/usualoma/1f0965389372798bac129d73086748c8.js"></script>AIエージェントに任せたプラグインの作り方
</h3>
<p><a href="https://movabletype.github.io/mt-rich-text-editor/developer-guide/" target="_blank" title="">MTRichTextEditor 開発者向けガイド</a> と <a href="https://github.com/movabletype/mt-rich-text-editor-example-plugins/" target="_self" title="">サンプルプラグイン</a> があるので、それをエージェントに伝えてからコーディングを依頼すれば、それだけで割と動くものが出てきます。</p>
<p><img data-mt-asset-id="304" src="https://blog.taaas.jp/assets_c/2025/12/CleanShot%202025-12-02%20at%2020.14.16%402x-thumb-900xauto-304.jpg" width="900" height="430" alt="" class="asset asset-image" style="display: block"></p>
<h3>この記事について</h3>
<p>この記事は<a href="https://adventar.org/calendars/11355" target="_blank" title="">Movable Type Advent Calendar 2025</a>の3日目の記事です！</p>
<h3>トフについて</h3>
<p>トフは<a href="//www.sixapart.jp/" rel="nofollow">シックス・アパート</a>の公式キャラクターです。<a rel="license" href="//creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> の下でライセンスされており、オリジナルは <a href="//www.sixapart.jp/about/toph.html" rel="nofollow">シックス・アパートのウェブサイト</a>で入手可能です。</p>]]>
        
    </content>
</entry>

<entry>
    <title>Movable Typeのブロックエディタのカスタムブロックの開発ツール</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/mt-custom-block-builder/" />
    <id>tag:blog.taaas.jp,2024://2.173</id>

    <published>2024-12-25T11:30:30Z</published>
    <updated>2025-05-20T07:29:54Z</updated>

    <summary>これは何か？カスタムブロックは非常に拡張性が高いのですが、「入力フォーム兼テンプ...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これは何か？</h3><p>カスタムブロックは非常に拡張性が高いのですが、「入力フォーム兼テンプレートとなるHTMLはブロックエディタで用意する」「挿入するカスタムスクリプトはHTML形式で、style要素やscript要素を混ぜたものになる」というところで、ローカル環境で開発がやややりにくいところがあったので、その問題を解決するべく開発ツールを作ってみました。</p><h3>以前のものとの違い</h3><p>カスタムブロックの開発ツールの用意は以前も試みたことがあり、そのときにはVSCodeの拡張機能として「MT Custom Block Editor」というものを作っていました。（<a href="https://blog.taaas.jp/mt/vscode-mt-custom-block-editor/">記事はここ</a>です）これはVSCodeとの連携の試みとしては面白かったのですが、VSCodeに強く結びついてしまうため他のcliツールとの連携が逆に難しくなる面がありました。</p><p>そのような折、去年から今年にかけていくつか出したnpmをベースにしたツールが意外と興味をもってもらえたのもあり、こちらのアプローチに変えてみようと思い、以前のVSCode版とは違うものとして作りました。</p><p>こんな感じで動きます。</p><iframe width="640" height="480" src="https://www.youtube.com/embed/NsXejoHIjOU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="mt-custom-block-builder"></iframe><pre>npm create @usualoma/mt-custom-block</pre><p>このコマンドで雛形を作成できて、動画のサンプルのカスタムブロックも最初から入っています。</p><p>.jsonのファイル自体は、ゼロからつくるよりも一回MTで簡単な設定をしてから書き出すほうが楽だと思います。そこをベースにして、このツールでは主に以下のデータを更新できます。</p><ul>
<li>アイコン</li>
<li>JavaScript または TypeScript
<ul>
<li>.tsというファイル名で保存すると勝手にトランスパイルします</li>
<li>script[type=module]で挿入されるので、DOMContentLoadedを明示的に書く必要はありません</li>
</ul>
</li>
<li>入力フォーム兼テンプレートとなるHTML</li>
</ul><p>上の2つはエディタから、一番下はブラウザから更新します。（ブラウザの保存ボタンでちゃんとファイルも更新されます）</p><p>デモ動画をみてもらうとなんとなく分かりますが、エディタでTypeScriptを変更して保存するとブラウザの方も自動でリロードされ、TypeScript（カスタムスクリプト）の実行結果をすぐに確認できます。カスタムブロックの作成で一番手間がかかるのがここだと思うので、ここですぐに反映されるのは嬉しいのではないでしょうか。</p><p>データとしては本来、カスタムスクリプトにはlink要素やstyle要素を書くこともできるのですが、そのあたりはJavaScriptで動的に対応できるので、このツールでは割り切ってJavaScriptのみで動かすようにしています。</p><h3>注意事項</h3><p>ビルドのプロセスを経ることで、意図せずにJavaScriptを大きくなってしまいがちである点には注意が必要です。大きくなるとCMSのシステム側への負荷も大きくなるのでご注意ください。script[type=module]で読み込まれるので、ブラウザ上でのimportも普通に使えるのでnpmのモジュールの読み込みはcdnからの直接の読み込みなどを利用するのがおすすめです。</p><h3>この記事について</h3><p>この記事は<a href="https://adventar.org/calendars/10274" target="_blank" rel="noopener">Movable Type Advent Calendar 2024</a>の25日目の記事です！</p><p>今年はMTDDC Meetup TOKYO 2024にも参加ささせていただいて直接いろいろな人と話ができ、そしてこのアドベントカレンダーでいつも通りの年末感も味わうことができました。どちらも主催者であった西山さんをはじめ、関係者のみなさん、ありがとうございました。おつかれさました。</p><p>それではみなさん良いお年を！</p>]]>
        
    </content>
</entry>

<entry>
    <title>ShortcutIcon - 管理画面のfaviconを好きな画像に差し替えるMovable Typeプラグイン </title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/mt-plugin-shortcuticon/" />
    <id>tag:blog.taaas.jp,2024://2.172</id>

    <published>2024-12-11T20:24:25Z</published>
    <updated>2024-12-11T19:34:22Z</updated>

    <summary>これは何か？Movable Typeの管理画面のfaviconを自分の好きな画像...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これは何か？</h3><p>Movable Typeの管理画面のfaviconを自分の好きな画像に差し替えるプラグインです。画像はウェブブラウザに保存されます。</p><p><a href="https://github.com/usualoma/mt-plugin-ShortcutIcon" target="_blank" rel="noopener">mt-plugin-ShortcutIcon</a></p><iframe width="640" height="360" src="https://www.youtube.com/embed/kiGexZFKMdE?si=Ljibrwxm7rBybNGi" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe><h3>対応ウェブブラウザ</h3><ul>
<li>Google Chrome : 任意の画像を設定できます</li>
<li>Firefox : SVGやPNGは設定できますが、JPEGは設定できません</li>
<li>Safari : 設定されません</li>
</ul><h3>開発の動機</h3><p><a href="https://www.npmjs.com/package/@usualoma/mt-plugin-builder" target="_blank" rel="noopener">@usualoma/mt-plugin-builder</a>を使って何ができるかをもう少し考えたくて、「ウェブブラウザだけでできること」というテーマで作りました。</p><h3>仕組み</h3><p>ユーザーが指定した画像を<a href="https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API" target="_blank" rel="noopener">IndexedDB</a>に保存して、ページ表示の切り替わりごとに読み出して<a href="https://developer.mozilla.org/ja/docs/Web/API/URL/createObjectURL_static" target="_blank" rel="noopener">URL.createObjectURL</a>を使ってURLを生成して、link[rel="shortcut icon"] を作成してheadに挿入するという動作をしています。</p><h3>誰のためのものか？</h3><p>faviconを設定するだけなら画像のリソースもプラグインに含んでしまえばよく、そうすればユーザー毎に設定せずともインストールしたMT全体で差し替えることができます。</p><p>しかしここで、「制作会社のユーザー」と「クライアントのユーザー」で考えると、クライアントのユーザーは複数のサイトのMTを使うわけではないのでMTのデフォルトでよく（むしろそれが自然）、制作会社のユーザーは複数のサイトのMTを使うのでfaviconで「どのサイトのMTか？」を区別できるとよかったりすると思います。そのようなわけで意外と「ユーザーが自分の好きなfaviconを設定できる」という機能にも需要があるのではないかと思っています。</p><h3>この記事について</h3><p>この記事は<a href="https://adventar.org/calendars/10274" target="_blank" rel="noopener">Movable Type Advent Calendar 2024</a>の12日目の記事です！</p>]]>
        
    </content>
</entry>

<entry>
    <title>HonoのJSXでPolyglotなSVGからQuineでイルミネーション</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/hono/jsx-polyglot-svg-quine/" />
    <id>tag:blog.taaas.jp,2024://2.171</id>

    <published>2024-12-05T20:30:47Z</published>
    <updated>2024-12-05T20:44:47Z</updated>

    <summary>こんにちは。OSS珍百景として紹介されたPRの作者の天野です。OSS観光名所 -...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Hono" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<p>こんにちは。OSS珍百景として紹介されたPRの作者の天野です。</p><blockquote class="twitter-tweet"><p lang="ja" dir="ltr">OSS観光名所 - honojs/hono 2022/2/20 #109<a href="https://twitter.com/usualoma?ref_src=twsrc%5Etfw">@usualoma</a> さんのIntroduce RegExpRouter<br><br>Honoの特徴である「速さ」を象徴するRegExpRouter(ルーティングをひとつの正規表現にして一発でマッチさせる)が導入された記念すべきもの。<a href="https://t.co/MLxqHB3MOg">https://t.co/MLxqHB3MOg</a></p>&mdash; Yusuke Wada (@yusukebe) <a href="https://twitter.com/yusukebe/status/1862413142304989260?ref_src=twsrc%5Etfw">November 29, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><p>今年は以下のあたりを中心にHonoにコミットしました</p><ul>
<li><a href="https://github.com/honojs/hono/releases/tag/v3.12.0">v3.12.0</a></li>
<ul>
<li>CSRF Protection Middleware</li>
<li>css Helper</li>
</ul>
<li><a href="https://github.com/honojs/hono/releases/tag/v4.0.0">v4.0.0</a>
<ul>
<li>Client Components</li>
</ul>
</li>
<li><a href="https://github.com/honojs/hono/releases/tag/v4.5.0">v4.5.0</a>
<ul>
<li>Combine Middleware</li>
<li>React 19 Compatibility</li>
</ul>
</li>
</ul><p>この記事ではこれらの機能の実現に使った内部の機能に触れつつ、PolyglotなSVGを使ってHonoのJSXの表現力を試してみたいと思います。</p><h3>できたもの</h3><p><a href="https://github.com/usualoma/hono-polyglot-svg" target="_blank" rel="noopener">hono-polyglot-svg</a>ができました。以下のSVG画像ファイルはそのまま出力するとオリジナルのHonoのアイコン画像が表示されますが、HonoのJSXを経由すると、色を変えつつ自分自身を出力するQuineなSVG画像として出力されます。</p><script src="https://gist.github.com/usualoma/2db4efa20f95c39c52b8483f09dd574b.js?short_path=d273595"></script><ul>
<li>http://localhost:3000/static/hono.svg : そのまま出力</li>
<li>http://localhost:3000/static/hono.svg?eval=1 : JSXで処理して出力</li>
</ul><p>です。以下のような結果になります。</p><iframe width="400" height="408" style="display: block; margin: auto" src="https://www.youtube.com/embed/nK9iUzIiMNg" title="HonoのJSXでPolyglotなSVGからQuineでイルミネーション" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe><h3>解説</h3><h4>コールバックから書き換える</h4><p>HonoのJSXの文字列化では、要素の属性値や内容として<span style="background-color: rgb(236, 240, 241);"><em>Promise&lt;string | String&gt;</em></span>を返すことができ、<span style="background-color: rgb(236, 240, 241);"><em>use</em></span>を使うことなしに<em><span style="background-color: rgb(236, 240, 241);">async</span></em>な関数コンポーネントから簡単に文字列の結果を出力することができます。さらにここで<span style="background-color: rgb(236, 240, 241);"><em>String</em></span>に対して<span style="background-color: rgb(236, 240, 241);"><em>isEscaped</em></span>や<span style="background-color: rgb(236, 240, 241);"><em>callbacks</em></span>を指定することで、出力される際の挙動をコントロールすることができます。</p><p>この特殊な<span style="background-color: rgb(236, 240, 241);"><em>String</em></span>を作成するためには、通常は"hono/utils/html"からエクスポートされている<span style="background-color: rgb(236, 240, 241);"><em>raw()</em></span>を使いますが、使わずに作成することもできます（内部の構造は今後変更される可能性もあるので、推奨はされませんが）。</p><script src="https://gist.github.com/usualoma/1d3ab59ef5a207a81d095acff6772192.js"></script><p><span style="background-color: rgb(236, 240, 241);"><em>callbacks</em></span>に指定した関数が呼び出されるタイミングは、単純な文字列化以外にも<span style="background-color: rgb(236, 240, 241);"><em>renderToReadableStream()</em></span>を使ってレスポンスを返す前後のタイミングなど、いくつかあるのですが、ここでは深入りせず単純な文字列化を前提とします。以下のようにして<span style="background-color: rgb(236, 240, 241);"><em>callbacks</em></span>に指定した関数で渡された<span style="background-color: rgb(236, 240, 241);"><em>buffer</em></span>の値を変更すると、出力結果を書き換えることができます。</p><script src="https://gist.github.com/usualoma/760bde6765b976d920d6bae19c4c564e.js"></script><p>これが今回の、処理するたびにSVG画像の色が変わる挙動の仕組みです。Honoに実装された機能の中では「css Helper」でのstyle要素の埋め込みや、「React 19 Compatibility」でのtitle要素のhoistingで使われています。</p><h4>（無駄に）Combine Middlewareを使う</h4><p>「同じパスのURL」でありながら「処理方法（クエリストリングで指定）によって結果が変わる」ということを表現したかったので、Combine Middlewareの<span style="background-color: rgb(236, 240, 241);"><em>some()</em></span>を無駄に使って宣言的に書いてみました。以下のように書くと「evalが指定されたときにのみ<span style="background-color: rgb(236, 240, 241);"><em>evalSvgMiddleware</em></span>を適用する」という挙動になります。</p><script src="https://gist.github.com/usualoma/ce181244dc2e6652f7ff0c796e79aa26.js"></script><p>今回の例だと無理矢理感がありますが、hono.devの<a href="https://hono.dev/docs/middleware/builtin/combine" target="_blank" rel="noopener">ドキュメント</a>では認証と組み合わせた実用的な例も紹介されています。</p><p>解説は以上になります。</p><h3>今年の振り返り</h3><p>さて今年といえばHonoにとっては<a href="https://hono.connpass.com/event/319062/" target="_blank" rel="noopener">Hono Conference 2024 - Our first step</a>の開催が一番のイベントだったと思います。（参加レポート書いてなかったですが。）コミッターの方やコメントをしてくれる方の顔を見られて、どんな話し方をするのかを知ることができたのは嬉しかったです。議論が円滑に進むかどうかはまた別の話だとしても、「GitHubのコメントが当人の声で再生できるようになる」というのは、やはりよいものだと思いました。</p><h3>この記事について</h3><p>これは&nbsp;<a href="https://qiita.com/advent-calendar/2024/hono" target="_blank" rel="noopener">Hono Advent Calendar 2024</a> のシリーズ 1の6日目の記事です。シリーズ 2もあるようなので、引き続きよろしくお願いします！</p><iframe width="560" height="315" style="display: block; margin: auto" src="https://www.youtube.com/embed/sUsYeIJKQpU?si=md8MnKeoggXP7gzS" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]>
        
    </content>
</entry>

<entry>
    <title>prettierで整形できて、minifyして書き出せる、MTML</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/jsx-to-mtml/" />
    <id>tag:blog.taaas.jp,2023://2.168</id>

    <published>2023-12-24T21:00:00Z</published>
    <updated>2023-12-24T21:11:58Z</updated>

    <summary>こんにちは、天野と申します。Movable Typeの開発に参加しています。今日...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<p>こんにちは、天野と申します。Movable Typeの開発に参加しています。</p><p>今日はMTML（Movable Type Markup Language）の話です。</p><h3>MTMLを気持ちよく編集したい</h3><p>公開される記事の典型的なMTMLは以下のようなものになります。</p><script src="https://gist.github.com/usualoma/7c3fadd05a33b3b2662733d23a08d699.js"></script><p>HTMLの属性の中にMTタグが入っていますが、「カスタム要素の入ったHTML」と思ってみれば特別見にくいものでもないと思います。VSCodeに<a href="https://marketplace.visualstudio.com/items?itemName=usualoma.language-mtml" target="_blank" rel="noopener">MTML</a>の拡張を入れれば、属性の中にも色がついて見やすくなります。</p><p><img src="https://blog.taaas.jp/mt/mtml-extension.jpg" alt="" width="900" height="374" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><p>ただMTMLはやはり独自のマークアップ言語で一般的なツールではパースできないので「自動整形ができない」「対応するタグで閉じられているか編集時に検証できない」という問題があります。上のGistの内容だと「<span class="pl-kos">&lt;/</span><span class="pl-ent">titl</span><span class="pl-kos">&gt;</span>」となっていてHTMLが壊れていますし、「encde_html」となっている箇所もあります。また「&lt;mt:EntryTitle&gt;」というのは「encode_html」を付け忘れていると思われます。</p><p>とういところで、「JSXで書ければ整形も検証も一般的なツールでできるのになぁ」というのを思ったのです。</p><p>MTMLとJSXの関係については以前も<a href="https://usualoma.github.io/mt-data-api-react/docs/playground.html" target="_blank" rel="noopener">mt-data-api-react</a> としてPoC的なことをやったことがあります。これは「既存のMTMLをそのままで、DataAPIから取得したデータでフロントエンドでレンダリングする」というテーマでした。今回はそれとは異なり「JSXを書いて、それをMTが処理できるMTMLに変換する」というものです。</p><p>JSXに馴染みのない方はここまで読んでnot for meだなと感じるかもしれませんが、この話はそうでもないのでもう少し読み進めてください。以下は前出のMTMLを書き換えたものですが、ほぼほぼXMLとして違和感はないだろうと思います。（ないということで話を進めます。）またこれはJSXとしてもValidであり、これを処理することができます。</p><script src="https://gist.github.com/usualoma/e3d68e800bd264e9cdb0f2b7b1b19a64.js"></script><p>Reactを書いている方は「JSXとしてもValid」というところで「Validかもしれないけど（TSXでは）型のエラーが出るよね」という話になってくると思いますが、JSXをReactでないJSXの処理系で型を付ければこれもいけます。</p><p>説明が長くなってきたので結果を見てみると、今回作ったmt-jsx-templateというコマンドで処理すると以下のような結果になります。</p><script src="https://gist.github.com/usualoma/a3a37bceec1786b253a08877137afad0.js"></script><p>JSXで整形やバリデーションができる上に、つまるところJSXからMTMLへのトランスパイルになるので、その過程でMTMLをminifyして書き出すことができるのです。</p><p>実装部分は、<a href="https://github.com/honojs/hono" target="_blank" rel="noopener">hono</a>というOSSのプロジェクトでJSXの処理系を実装したことがあったので、そこから一部をコピーしつつひとまず形にしました。</p><p>ちなみにTypeScriptで型も付けられるので、<span>「encoee_html」もちゃんとエラーにできます。またトランスパイルのついでに「&lt;$mt:EntryTitle$&gt;」に自動で（デフォルトで）encode_htmlをつけることもできます。これは、結構いいんじゃないでしょうか。</span></p><h3>JSXになればできること</h3><p>JSXになると、自分でパースの努力をしなくてよくなるので「使われているCSSのクラス名を収集する」ということもやりやすくなります。（今までのテンプレートでも正規表現で収集すれば実用上十分な精度でできたと思いますが。）「JSXで書いてトランスパイルする」という処理が作業フローに組み込まれるのであれば、そのついでに「CSSのフレームワークから必要なCSSを抽出して最小限のCSSを作成する」というのもやろうかという話になってくると思います。</p><p>以下が、MasterCSSを使ったサイトのJSXテンプレートからクラス名を抽出して、使われているCSSのみを出力するイメージです。</p><script src="https://gist.github.com/usualoma/968cb2d1f7d2936c36f2b7e7a8988fd8.js"></script><p>このMTMLのclassを解析して、<a href="https://css.master.co/" target="_blank" rel="noopener">MasterCSS</a>を使って以下のCSSを出力することができます。</p><script src="https://gist.github.com/usualoma/5cc7f81307dde5fd179238a100ea0fdc.js"></script><p>フロントエンドに関しては、2023年においてはウェブサイトを運用する際には何らかのビルド作業が入っていることが多いと思いますが、MTMLや（MTMLの内容を踏まえた上での）CSSもビルドするようになってもいいのかもしれません。MTのプラグイン（主にPerl）でビルドできればよいようにも思いますが、プラグインだとサーバー上で動作させることになり制限があることも多いので、作業環境の方が自由に環境を作れるというのもあり、これはこれでよいアプローチだと思います。</p><p>「ここまでやるならJamstackで生成した方が素直じゃないか？」という指摘があっても否めない気もします。とはいえまあ、上と同じ理由で運用環境は自由にならないこともあるのでMTを使ううえではMTMLの開発効率が上がるのはよいことだと思います。</p><h3>プレビューもしたい</h3><p>「JSXでパースできる」ということは、mt:Entriesやmt:EntryTtileのモックを作ってあげれば、JSXを直接文字列化してテンプレートの出力結果も確認できそうです。これになってくると上で出たmt-data-api-reactとも近い話になってくるのですが。これをやるには時間が足りなかったのでやっていませんが、後はモックを頑張って作りさえすれば、プレビューできるというところまで来ていると思います。</p><h3>今回作成したもの</h3><p><a href="https://www.npmjs.com/package/mt-jsx-template">mt-jsx-template</a>です。</p><p><code>$ npx mt-jsx-template ファイル名</code></p><p>だけですぐに動かせます。また標準入力からも読み込めますので、動くことだけ確認したい場合には以下のコマンドを実行すれば変換された結果を見ることができます。</p><p style="overflow-wrap: anywhere;"><code>$ curl https://gist.githubusercontent.com/usualoma/e3d68e800bd264e9cdb0f2b7b1b19a64/raw/7c0b05a92e95f01f4e317d8c7ab46cb118296b66/entry.mtml.tsx | npx mt-jsx-template</code></p><p>TSXを書いて実際に型の付くことを確認したい場合には以下のようにプロジェクトにインストールして、tsconfig.jsonを設定してもらえば好きなエディタで動作させることができます。</p><p><code>$ npm install --save-dev mt-jsx-template</code></p><p><img src="https://blog.taaas.jp/mt/mt-jsx-template-screenshot.jpg" alt="" width="900" height="609" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><p>属性値の型も定義されているので、補完が効いたり、マニュアルを参照できたりします。</p><p><img src="https://blog.taaas.jp/tsx-mtml-prop.jpg" alt="" width="900" height="417" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><p><span>これは、結構いいんじゃないでしょうか！</span></p><h3>この記事について</h3><p>この記事は <a href="https://adventar.org/calendars/8999" target="_blank" rel="noopener">Movable Type Advent Calendar 2023</a> の25日目の記事です。皆様お疲れさまでした。それでは良いお年を！</p>]]>
        
    </content>
</entry>

<entry>
    <title>honoのJSXの特徴</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/hono/hono-jsx/" />
    <id>tag:blog.taaas.jp,2023://2.167</id>

    <published>2023-12-02T07:46:11Z</published>
    <updated>2023-12-12T21:18:21Z</updated>

    <summary>これはなんの記事か？honoはJSXを処理する実装をもっています。JSXはJav...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Hono" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これはなんの記事か？</h3><p><a href="https://github.com/honojs/hono/">hono</a>はJSXを処理する実装をもっています。JSXはJavaScriptの構文を拡張したもので...のような話は皆さんご存知でしょうしググってもらった方が正確な情報を得られると思うのでここでは書かずに、honoの実装での特徴的なところについて書いていこうと思います。</p><h3>特徴は？</h3><p>文字列の出力に特化していることです。Reactでいうところの`renderToString(&lt;App /&gt;)` のみに対応しています。`&lt;App /&gt;.toString()` が文字列になります。`document.body.innerHTML = &lt;App /&gt;`が動くのはそのためです。</p><blockquote class="twitter-tweet"><p lang="ja" dir="ltr">esm. sh/runのやつ、HTMLに内で書いたJSXコンポーネントをそのままHTMLとして渡すなんてことができる。意味不明でよい <a href="https://t.co/TD7AwSQ7HI">pic.twitter.com/TD7AwSQ7HI</a></p>&mdash; Yusuke Wada (@yusukebe) <a href="https://twitter.com/yusukebe/status/1729015602982072476?ref_src=twsrc%5Etfw">November 27, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <h3>Reactとの互換性は？</h3><p>一般的なHTMLの要素をはじめ、Function Component、Fragment、dangerouslySetInnerHTMLなど、JSXの基本的な構成要素は揃っているので、特に戸惑うこと無くJSXを書いてHTMLを出力することができると思います。</p><p>非互換の一番大きな点としては、今まで書いたことはなく質問されたこともなかったのですが、`<span>Component`のクラスに対応していないことかもしれません。とはいえ、文字列の出力に特化していて状態を持ちたいことはないと思うので</span><span>、クラスが必要になる場面は基本的にはないと思います。</span></p><p>地味な違いとしては"class"を"className"と書く必要がないので、HTMLをそのまま持ってきて必要なところだけコンポーネントに置き換えるときに楽です。そこはpreactと一緒ですね。（ただ逆にReactから持ってくるときにはclassNameをclassに置き換える必要がありますが。）</p><h3>ベンチマークは？</h3><p>honoといえば「Ultrafast &amp; Lightweight」なのでその点にもこだわっています。</p><p><a href="https://github.com/honojs/hono/tree/main/benchmarks/jsx" target="_blank" rel="noopener">honojs/hono/tree/main/benchmarks/jsx</a> にベンチマークがあり、React、Preact、Nano、という本家+メジャーなJSX処理系と比較しています。「honoに実装されている機能の範囲で比較した場合」というベンチマークなのでhonoに有利な条件ですが、この中で最速になっています。</p><p><img src="https://blog.taaas.jp/benchmark.jpg" alt="" width="900" height="375" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><p>またベンチマークの例でバンドルした場合のサイズ（honoの本体は含まずに、JSXの処理系だけをバンドルしたサイズ）は3.9kbと小さく、これも比較した中で最小です。</p><p><img src="https://blog.taaas.jp/bundle-size.jpg" alt="" width="900" height="287" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><h3>JSXの処理系の中で最速でしょうか？</h3><p>ルーターのベンチマークに関してはRegExpRouterが「必要十分な機能を持ったルーターとしてはJSの中で最速」となっていますが、JSXに関しては少し状況が違います。</p><p>honoのJSXでは（他の多くのJSXの処理系と同じように）一度データ構造の木を作成して、そこから文字列化を行っています。一度データ構造を作ることで親コンポーネントが子を管理しやすくなり、細かい要望に応えやすくなります。（後述するErrorBoundaryで同期的エラーを補足する場合とか）</p><p>ただJSXの文字列化のアプローチとしてはこの「データ構造の木を作成」というところを省略する方法もあり、その場合には細かい管理はできないもののより高速に処理できます。このアプローチを採用している処理系には<a href="https://github.com/kitajs/html" target="_blank" rel="noopener">@kitajs/html</a>があり、これは速度だけをみるとhonoのJSXよりも高速です。</p><h3>非同期なコンポーネント</h3><p>honoの3.10からは非同期なコンポーネントを使うことができるようになりました。</p><p>`<span>&lt;App /&gt;.toString()` がPromiseを返すようになってしまう気持ち悪さはありますが、受け取る側でラップすれば通常の文字列と同じ感覚で使うことができます。</span></p><script src="https://gist.github.com/usualoma/f8a27558216d8167e5bf258775058e05.js"></script><p>これは実はReactとも互換性があって、18.2まではエラーになるのですが、Reactの18.3（2023年12月現在は@nextのステータス）では`renderToReadableStream`を使うことで文字列にすることができます。Suspenseも不要です。</p><p>完全な互換性があるわけではないのであまり不用意なことは言えないのですが、honoのJSXは独自の実装ではあるものの意外と本家の挙動も意識しており、後述するSuspenseにおいても相互の乗り換えで混乱することがないようにしています。</p><p>もちろんですが、返されたPromiseは並列で処理されるので、同時にたくさんの非同期なコンポーネントを使っても大丈夫です。</p><script src="https://gist.github.com/usualoma/610458c1f74f3bdfd10ca87a8ecb30ed.js"></script><h3>Suspense</h3><p>honoの3.10で非同期なコンポーネントのサポートすると同時に、Reactで使えるSuspenseも用意しました。</p><p>前項の話とも重なりますが、Reactの<span>18.2まではSuspence[fallback]を使う場合にはPromiseをthrowするというのが作法だったと思いますが、18.3ではPromiseをreturnでもいけるようです。（Reactには詳しくないのですが。）honoでは、従来どおりのthrowする方法も、returnする方法も、どちらもサポートしています。（関連する機能としては`use`というhookもあり、honoでも一度実装したのですが、honoでは単に async/await で十分であり必要な場面がないだろうということで削除しました。）</span></p><p><span>以下のコードはhonoでもReact（18.3）でもどちらでも、最初に「Loading...」が表示され、fetchの完了後に内容が更新されるという動作になります。</span></p><script src="https://gist.github.com/usualoma/205f29ce9cac95be60704163aac1c4df.js"></script><h3>ErrorBoundary</h3><p>ErrorBoundaryはReactの本体では提供されていないのですが、<a href="https://github.com/bvaughn/react-error-boundary" target="_blank" rel="noopener">bvaughn/react-error-boundary</a>という公式のドキュメントからもリンクされていて広く使われているライブラリがあり便利そうだったので、仕様を真似て実装しました。</p><p>以下のコードで、<span>最初に「Loading...」が表示され、その後例外が投げられたタイミングで「Something went wrong」に更新されるという動作になります。</span></p><script src="https://gist.github.com/usualoma/e623c06486957040bb149542cd85d747.js"></script><p>ErrorBoundary[onError]やErrorBoundary[fallbackRender]を使って、ログを記録したり、エラーの内容に応じて出力を切り替えることもできます。</p><script src="https://gist.github.com/usualoma/2d36151eaaa1762fd2b2f03b92d85083.js"></script><script src="https://gist.github.com/usualoma/36e5be4cb4d3aa47ceea1636a9a90df0.js"></script><p>以上、honoのJSXの実装の紹介でした。</p><p>これは <a href="https://qiita.com/advent-calendar/2023/hono" target="_blank" rel="noopener">Hono Advent Calendar 2023</a> の13日目の記事です。引き続きよろしくお願いします！</p>]]>
        
    </content>
</entry>

<entry>
    <title>Passkey - Passkeyで認証できるようにするプラグイン </title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/passkey/" />
    <id>tag:blog.taaas.jp,2023://2.166</id>

    <published>2023-12-01T07:51:51Z</published>
    <updated>2023-12-01T23:06:54Z</updated>

    <summary>これは何かMovable Typeの管理画面へのサインインでPasskeyの認証...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これは何か</h3><p>Movable Typeの管理画面へのサインインでPasskeyの認証を利用できるようにするプラグインです。</p><p><a href="https://github.com/usualoma/mt-plugin-Passkey" target="_blank" rel="noopener">mt-plugin-Passkey</a></p><iframe width="640" height="360" src="https://www.youtube.com/embed/5Wta8HeNF2o?si=1BM02n67IR_cZp67" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe><h3>必要な環境</h3><p>サーバー環境に以下のPerl moduleが必要なので、ちょっと環境は選ぶかもしれません。</p><ul>
<li>Crypt::PK::ECC</li>
<li>Crypt::PK::RSA</li>
</ul><h3>感想</h3><p>1Passwordなどのパスワードマネージャを利用している場合には、普段からサインインの際の手間は殆どないのであまり変わらないようにも思いますが、「システムとして、パスワードよりも安全で手間のかからないサインインの方法を提供できる」というのが、Passkeyでサインイン可能にする際のシステム側のモチベーションであるように思いました。</p><p>（Passkey対応なので当然ですが）iCloudにPasskeyを登録しておけば、「デスクトップの端末からMTにサインインする際にiPhoneを経由して顔認証でサインインする」というのも思いの他さくっと成功するのでちょっとした感動があります。</p><h3>TODO</h3><ul>
<li>サインインをしたタイミングでPasskeyの登録を促す</li>
<li>セッションの有効期限切れからの再サインインでパラメータを引き継ぐ（今は簡易的に実装しているのでダッシュボードに戻ります）</li>
<li>HTMLを書くのが面倒でalert()やprompt()を多用しているのでちゃんとする（でも今のブラウザはalert()も野暮ったくないので、意外と気にならないような気がしますが）</li>
<li>MFAプラグインと連携して他要素認証としてちゃんと扱われるようにする</li>
</ul><p>というのができるともう少し「Passkey対応サービス」の雰囲気が出せそうな気がしました。</p><h3>この記事について</h3><p>この記事は<a href="https://adventar.org/calendars/8999" target="_blank" rel="noopener">Movable Type Advent Calendar 2023</a>の2日目の記事です！</p>]]>
        
    </content>
</entry>

<entry>
    <title>v3.8.0で入ったImprove path matching in the routerの変更でもRegExpRouterの速度を維持できた（むしろ速くなったかもしれない）理由</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/hono/rer-in-v380/" />
    <id>tag:blog.taaas.jp,2023://2.165</id>

    <published>2023-11-30T20:30:00Z</published>
    <updated>2023-12-01T00:16:15Z</updated>

    <summary>これは何かHonoのv3.8.0のリリースでは「Improve path mat...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Hono" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これは何か</h3><p>Honoの<a href="https://github.com/honojs/hono/releases/tag/v3.8.0">v3.8.0のリリース</a>では「Improve path matching in the router」が入り、内部で利用しているルーターの仕様が変更になったのですが、高速なルーターの実装であるRegExpRouterは変更に対応しつつも速度を維持することができました。これはその経緯を解説する記事です。</p><h3>「Improve path matching in the router」とはどのような変更であったか？</h3><p>RegExpRouterの話に入る前に「Improve path matching in the router」の説明をします。リリースノートにもありますが以下のような定義のとき、以前は1つのアプリケーション内で「異なる階層に、同じ名前のパラメータ」を指定すると例外が投げられてしまい実行できなかったのですが、これができるようになりました。</p><script src="https://gist.github.com/usualoma/715cb59779b970d3d9541369959a41f2.js"></script><p>この例だけ見ると「なぜ今までこれができなかったのか？」というように見えますが、例えば以下のような定義のときに、今までは内部のインターフェイスが「`c.req.param()` の戻り値をすべてのハンドラで共有」となっていて、両方に一致した時に妥当な結果を返せなかったため、ルーティングの登録の時点で例外を投げる仕様にしていました。</p><script src="https://gist.github.com/usualoma/6827f8f536d875449581599513b0ebfc.js"></script><p>この仕様を改善するために、「`c.req.param()` の戻り値をすべてのハンドラで共有」となっていた内部のインターフェイスを「`c.req.param()` の戻り値は対応するルーティングで指定されたもののみ」とするように変更して、パラメータ名がルーティング間で重複するような定義も受け入れるようにしたのが「Improve path matching in the router」の変更になります。</p><p>リクエストとレスポンスの対応で見ると、以下のように変わっています。</p><script src="https://gist.github.com/usualoma/aac9aa7c82f5e24b93c036f82175fa36.js"></script><script src="https://gist.github.com/usualoma/6d1c10c246b2028a0bf8fb287e97772c.js"></script><h3>この変更のルーターへの影響</h3><div>
<p>以前の仕様だとルーターが返すのは以下でしたが、</p>
<ul>
<li>一致したハンドラのリスト</li>
<li>一致したパスのパラメータ</li>
</ul>
<p>新しい仕様だと以下になります。</p>
<ul>
<li>一致したハンドラのリスト</li>
<li>ハンドラ毎のパラメータ</li>
</ul>
<p>インターフェイスはだいたい以下のように変わっています。（最終的にはもう少し複雑になります。）</p>
</div><script src="https://gist.github.com/usualoma/b745c6b5a58557e7d22deb200716b2d7.js"></script><script src="https://gist.github.com/usualoma/46ac48ba6d5b2d67cb2db5386a34e2e2.js"></script><p>以前の仕様だと、一致したハンドラの数に関わらずリクエスト時に生成するオブジェクトの数は一定でしたが、このインターフェイスだとハンドラの数に比例して増えることになります。</p><p>オブジェクトの生成はどのランタイムでも特別遅いわけではないので、一般的なJSのアプリケーションの中ではそこまで避けるべきものでもないと思いますが、RegExpRouterは「JSのルーター界隈」という（ニッチな😀）世界で戦っているのでこの辺りが問題になりました。</p><h3>RegExpRouterでの対応</h3><p>RegExpRouterは（ご存知でない方は<a href="https://www.youtube.com/watch?app=desktop&amp;v=dPpzQePKdzU" target="_blank" rel="noopener">過去の資料</a>を参照してください）正規表現の結果を可能な限りそのまま使うことで高速化しているので、それを活かせるようにルーター側のインターフェイスの方でも歩み寄ってもらって、以下のようにすることで対応しました。<br><br>急にまとまってしまって戸惑うかもしれませんが、minifyしたときのコードが小さくなるようにRecordからArrayにするというのも入れつつ最終的にこのようになりました。<a href="https://github.com/honojs/hono/blob/ce36f839789084b0eeb2fc72227e82d8a65c3b3f/src/router.ts#L11-L38" target="_blank" rel="noopener">実際のコードではコメント付きでこんな感じ</a>になっています。詳細については実際のコードを見てもらうほうがいいかもしれません。</p><script src="https://gist.github.com/usualoma/16aeae88b2a67dd467aa05af225b2822.js"></script><p>RegExpRouterに関してはこのインターフェイスにあわせて、上で出した例に対してはこのようなルーティングの結果を返すようになりました。</p><script src="https://gist.github.com/usualoma/aa1d5a2fc4438fe9e8e75b4b7c767be2.js"></script><script src="https://gist.github.com/usualoma/41a5b0d47e370e20e2bd49b978daa38c.js"></script><p>これは `[T, ParamIndexMap][]` と `ParamStash` のタプルですが、前者は `match()` の呼び出し前に準備しておくことができ、後者についてはコメントにある通り `String.prototype.match()` の戻り値そのものとなっています。`c.req.param(key)` の呼び出しではこのデータ構造から値を引いて返すので、その際には以前の仕様では発生しなかったオーバーヘッドが発生するのですが、実際の運用の環境でも多くは以下のような条件を満たすので、</p><ul>
<li>同じkeyで何度も `c.req.param(key)` が呼ばれるようなことはない</li>
<li>パスから取得するパラメータは多くても2〜3程度</li>
<li>middlewareは '*' や、静的なパス以下の '/js/*' のような使い方が多く、パラメータを取るケースは少ない</li>
</ul><p>実運用の環境でも、そしてベンチマークでも、このオーバーヘッドが見える形で影響してくることはないものと思われます。</p><p>以上が、RegExpRouterが「Improve path matching in the router」の変更でも速度を維持できた（パラメータが少ない場合にはむしろ速くなるケースもある）理由です。</p><h3>この記事について</h3><p>この記事は <a href="https://qiita.com/advent-calendar/2023/hono" target="_blank" rel="noopener">Hono Advent Calendar 2023</a> の1日目の記事です。明日から毎日楽しみです。よろしくお願いします！</p>]]>
        
    </content>
</entry>

<entry>
    <title>「MT Custom Block Editor」というVisual Studio Codeの拡張機能を公開しました</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/vscode-mt-custom-block-editor/" />
    <id>tag:blog.taaas.jp,2022://2.164</id>

    <published>2022-12-27T03:45:05Z</published>
    <updated>2022-12-27T04:18:54Z</updated>

    <summary>これはなにか？先日公開した「MTML」に続いて「MT Custom Block ...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これはなにか？</h3><p>先日公開した「<a href="https://marketplace.visualstudio.com/items?itemName=usualoma.language-mtml" target="_blank" rel="noopener">MTML</a>」に続いて「<a href="https://marketplace.visualstudio.com/items?itemName=usualoma.mt-custom-block-editor" target="_blank" rel="noopener">MT Custom Block Editor</a>」という拡張機能を公開してみました。この拡張機能をインストールすると、MTのブロックエディタのスクリプト部分をVSCodeで編集したり、プレビューしたりできるようになります。</p><iframe width="640" height="480" src="https://www.youtube.com/embed/Co1QpP0W8E0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen title="MT Custom Block Editor"></iframe><p>まだ細かいところは詰めていなくて検証の一環程度のものですが、CMSでのサイト構築段階におけるこういった形でのVSCodeとの連携について、可能性を感じさせるものにはなっているように思います。</p><h3>今後のやることリスト</h3><ul>
<li>エディタ内のwebviewで表示するのは簡単で見た目も悪くないけれども、実際には任意のウェブブラウザで開けた方が便利であると思う</li>
<li>実際の環境と同じように、画像ブロックも扱えるようにしたい</li>
<li>その他たくさん</li>
</ul><h3>この記事について</h3><p>この記事は<a href="https://adventar.org/calendars/7425" target="_blank" rel="noopener">Movable Type Advent Calendar 2022</a>の20日目の記事です！</p>]]>
        
    </content>
</entry>

<entry>
    <title>ImageTemplate - コンテンツのデータとMTMLから画像を生成するプラグイン</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/imagetemplate/" />
    <id>tag:blog.taaas.jp,2022://2.163</id>

    <published>2022-12-25T07:30:00Z</published>
    <updated>2022-12-25T20:24:57Z</updated>

    <summary>これは何か記事やウェブページ、またはコンテンツデータのデータとMTMLのテンプレ...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これは何か</h3><p>記事やウェブページ、またはコンテンツデータのデータとMTMLのテンプレートから画像を生成することができるようになるMovable Typeのプラグインです。主にog:imageやアイキャッチの画像を生成するユースケースを想定しています。</p><p><a href="https://github.com/usualoma/mt-plugin-ImageTemplate" target="_blank" rel="noopener">ImageTemplate</a></p><p>以下が簡単な出力例で、「記事内の画像を背景にして、ウェブサイトのテーマカラーで縁取りして、タイトルと執筆者情報を入れる」という画像です。</p><p><img src="https://blog.taaas.jp/images/image-template-ogimage-sample.jpg" alt="" width="900" height="600" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><h3>どのような問題を解決するか</h3><p>og:imageやアイキャッチ画像は、記事ごとにデザイナーさんに作成してもらうことができるのであれば、それがベストだと思っています。そのようにして作られた画像は目を引くうえに、内容も上手に凝縮して詰め込まれていて素晴らしいです。</p><p>ただ現実問題としてそこまで整えることのできないことも多く、そういう環境で記事の作成者が画像を用意するとなると、統一感のある画像を用意するのはなかなか難しいのではないかと思っています。このプラグインではそいう環境で作業者に時間やスキルがない場合にも、「あらかじめデザイナーさんにテンプレートを用意してもらう」ことにより、一定の品質で統一感のある画像を用意できるようになるというところを目指しています。</p><h3>デモ</h3><iframe width="560" height="315" src="https://www.youtube.com/embed/baifEAfnACU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><h3>使い方</h3><p>インストール後に、SVGのデータを出力するテンプレートを作成すると使えるようになります。記事やウェブページとの関連付けはテンプレート名で行います。それぞれ以下の名前で作成してください。</p><h4>記事</h4><p>image_template_entry_並び順（数字）_表示名</p><h4>ウェブページ</h4><p>image_template_page_並び順（数字）_表示名</p><h4>コンテンツデータ</h4><p>image_template_content_data_コンテンツタイプのID_並び順（数字）_表示名</p><h3>テンプレートの例</h3><p>デモのために作成したテンプレートです。いろいろと決めうちで品質はよくないですが、雰囲気は伝わるかと思います。ルート要素に指定したwidthとheightが、出力される画像のサイズになります。</p><script src="https://gist.github.com/usualoma/3eb91a4e5829088389ef2eaf11c43b5c.js"></script><h3>TODOリスト</h3><ul>
<li>SVGでなくて、HTMLで書くこともできるようにする</li>
<li>現在は「埋め込める画像はjpegのみ」「出力できる画像はpngのみ」なので、ちゃんと他のフォーマットも扱えるようにする</li>
<li>JavaScriptで、SVGの要素を調整して、その結果を出力できるようにする</li>
<li>管理画面で関連付けや並べ替えができるようにする</li>
<li>その他、たくさんあります。</li>
</ul><h3>この記事について</h3><p>この記事は <a href="https://adventar.org/calendars/7425" target="_blank" rel="noopener">Movable Type Advent Calendar 2022</a> の25日目の記事です。皆様お疲れさまでした。それでは良いお年を！</p>]]>
        
    </content>
</entry>

<entry>
    <title>「MTML」というVisual Studio Codeの拡張機能を公開しました</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/vscode-mtml/" />
    <id>tag:blog.taaas.jp,2022://2.156</id>

    <published>2022-12-07T09:00:00Z</published>
    <updated>2022-12-27T04:19:10Z</updated>

    <summary>これはなにか？Visual Studio Codeの拡張機能に興味が出たので、M...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これはなにか？</h3><p>Visual Studio Codeの拡張機能に興味が出たので、MTML（Movable Type Markup Language）向けのものを作ってみました。以下のように動作します。（音声での説明も入っています）</p><iframe width="640" height="360" src="https://www.youtube.com/embed/UbR2YoZLjjs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen title="Visual Studio Code の拡張機能である MTML のデモ"></iframe><h3>既存の拡張機能との関係</h3><p>MTML向けの拡張機能やスニペットのデータはすでに公開されたものがあって、以前のアドベントカレンダーで紹介されているものもあります。</p><ul>
<li><a href="https://hei-a.net/blog/movable_type/vscode-mtml-completions.html" target="_blank" rel="noopener">MTタグ入力補完スニペットの Visual Studio Code 版をつくってみました</a></li>
<li><a href="https://webrandum.net/vscode-plugin-mtml/" target="_blank" rel="noopener">Visual Studio CodeでMovable TypeのMTMLファイルを開く拡張機能「Movable Type Markup Language Syntax」</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=wyc.mtml" target="_blank" rel="noopener">mtml</a></li>
</ul><p>これらは実運用の中での知見が反映されたものでそれぞれすばらしいものなので、今回の拡張機能についてはこれらの置き換えを目指すものではなく、「もう一つの選択肢」というものとして考えています。ただ今回の拡張機能は「オプションで特定の機能のみを有効にする」ということもできるので、「リファレンスの表示機能のみを有効にする」というような形で、既存の機能と併用するという使い方もできるものになっています。</p><h3>機能の説明</h3><h4>シンタックスハイライト</h4><p>ファイルの編集時に言語を「MTML」にすると、MTタグのシンタックスハイライトが有効になります。「MTML」は「HTML」で書いても概ねいい感じに表示されるものですが、「,」区切りの属性値であったり、属性値の中にMTタグを書く場合にうまくハイライトされないという問題があります。この拡張機能を使うとそのようなケースでもいい感じに表示されるようになります。<br />また「HTML」のシンタックスも理解するのでHTMLの部分もそのままきれいに表示されます。</p><p>ただ、言語として「MTML」を選択してしまうと「HTML」向けのVisual Studio Codeのシンタックスハイライト以外の機能が使えなくなってしまうので、そこは若干、このシンタックスハイライトがほんとに便利なのかどうか、微妙だと思うところです。</p><p><img src="https://blog.taaas.jp/images/syntax-highlighting.jpg" alt="" width="" height="" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><h4>補完</h4><p>MTタグや、タグ毎のモディファイア、そしてグローバルモディファイアを補完することができます。「&lt;」の場合には全てのMTタグが対象になり「&lt;$」まで打てばファンクションタグのみが有効になります。</p><p>初期値では「mt:Var」のフォーマットで補完されますが、設定により「MTVar」のフォーマットに変更することもできます。</p><p>この機能はデフォルトで「HTML」や「CSS」でも有効になります。設定により「HTML」や「CSS」では無効にすることもできます。</p><p><img src="https://blog.taaas.jp/images/completion.jpg" alt="" width="" height="" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><h4>リファレンスマニュアルの表示</h4><p>MTタグにマウスカーソルを合わせると、リファレンスマニュアルを表示することができます。</p><p>この機能はデフォルトで「HTML」や「CSS」でも有効になります。設定により「HTML」や「CSS」では無効にすることもできます。</p><p><img src="https://blog.taaas.jp/images/reference-manual.jpg" alt="" width="" height="" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><h4>ブロックタグの折りたたみ</h4><p>ブロックタグを折りたたむことができます。</p><p>この機能はデフォルトで「CSS」でも有効になります。設定により無効にすることもできます。</p><p><img src="https://blog.taaas.jp/images/folding.jpg" alt="" width="" height="" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><h3>今後のやることリスト</h3><ul>
<li>リファレンスの表示の整形や、保管される値の候補の改善</li>
<li>同じフォルダ内の他のファイルも考慮した、変数名の補完</li>
<li>theme.yamlのデータを参照した、カスタムフィールドのMTタグの補完</li>
</ul><h3>この記事について</h3><p>この記事は<a href="https://adventar.org/calendars/7425" target="_blank" rel="noopener">Movable Type Advent Calendar 2022</a>の7日目の記事となっています。ここまでですでに、API、最近のパッケージリリース、Google Chromeの拡張機能、プラグイン、などいろいろな話題がでていて面白いです。まだまだ前半なので、今後の記事も楽しみです。引き続きよろしくお願いします。</p>]]>
        
    </content>
</entry>

<entry>
    <title>v8のlastIndexOfが（相対的に）遅い</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/tips/v8lastindexof/" />
    <id>tag:blog.taaas.jp,2022://2.150</id>

    <published>2022-02-21T06:42:39Z</published>
    <updated>2022-02-21T12:16:07Z</updated>

    <summary>最近honoにコントリビュートをしていて、正規表現の結果からの文字列を探索する際...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Tips" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<p>最近<a href="https://github.com/yusukebe/hono" target="_blank" rel="noopener">hono</a>にコントリビュートをしていて、正規表現の結果からの文字列を探索する際にindexOf()の代わりにlastIndexOf()を使ったら最適化できないだろうかと考えたりしていたのですが、だめでした。これはその際に調べたことのメモです。</p><p>まず最初に、1000個のcaptureを返す正規表現の結果から500番目を探すパターンでベンチマークをとってみます。</p><script src="https://gist.github.com/usualoma/70a4a75a8d09d2748853fa8915e3d024.js"></script><p><span>どのバージョンでもindexOf()が文字通り桁違いに速く、lastIndexOf()はforやwhileにすら負けて最下位になっています。（ただindexOf()を使った場合にも変数へのアサインを挟んだだけでここまでの差にはならなかったりするので、どれも基本的には速く、ちょっとした条件の変化で結果が変わったりする程度のものでもあるとは思います。）単純に1つの空文字列を探索する場合にはindexOf()を使うのがよさそうです。</span></p><p>v8のコードを見てみたところ、indexOfの方は<a href="https://github.com/v8/v8/blob/5dd39b1de19a2fd43e4140a81eb37a3430e594b8/src/compiler/js-call-reducer.cc#L2026" target="_blank" rel="noopener">c++のコード</a>で、lastIndexOfは<a href="https://github.com/v8/v8/blob/db50b4912875606e2d85cb8fe7f6c6281fc65b2d/src/builtins/array-lastindexof.tq" target="_blank" rel="noopener">マクロのコード</a>で書かれていたので、その辺りで違いが出ているのかもしれません。</p><p>次に、以下のように「最大で2つの連続した空文字列が返ってくる match() の結果から、一番最後の空文字列の位置を取得する（<span>captureは2000個）</span>」というケースでのベンチマークをとってみます。</p><script src="https://gist.github.com/usualoma/38e4e32bf4c5b7a6e3628dbb7e55f507.js"></script><p>これはバージョンごとの違いが大きく、v16だと「indexOf()とforループがほぼ同じ性能」で、v17だと「indexOf()が最速で2倍近い性能」、そしてv18(pre)だと「forループが最速」となりました。</p><p>結論のようなものはなかなか難しいですが。</p><ul>
<li>正規表現の結果から最初の1つの文字列を探す場合にはArray.prototype.indexOf()が桁違いに速い</li>
<li>いまのところArray.prototype.lastIndexOf()は遅い</li>
<li>少し条件が込み入ってくるとforループが最速になることもある</li>
</ul><p>というところでしょうか。v18でもネイティブで実装されたlastIndexOf()よりもforループのの方が早くなるケースがあるというのは若干複雑な気持ちにはなりました。</p>]]>
        
    </content>
</entry>

<entry>
    <title>TypeScriptのConditional Typesでinferを使って足し算を定義する</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/tips/typescript-infer/" />
    <id>tag:blog.taaas.jp,2022://2.148</id>

    <published>2022-02-20T23:00:00Z</published>
    <updated>2022-02-20T23:02:59Z</updated>

    <summary>String Literal TypesやTemplate Literal Ty...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Tips" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<p><a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types">String Literal Types</a>や<a href="https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html">Template Literal Types</a>を使うとGenericsや関数の引数の文字列から型を作れるという話を聞いたので、勉強も兼ねて足し算を定義してみました。</p><p>以下のような感じになります。 `<span class="pl-smi">Expr</span><span class="pl-kos">&lt;</span><span class="pl-s">"1 + 1"</span><span class="pl-kos">&gt;` が `"10"` というString Literal Typeになります。</span>2進数の足し算のみに対応していて、未対応の式では<span>UnrecognizedExpression型になります。3項以上でも計算できます。</span></p><script src="https://gist.github.com/usualoma/c92acd5061f970322b215dc9ce91a071.js"></script><p>型が補完されるエディタを使っていると、答を自分で打たなくても補完されたりして楽しいです。</p><p><img src="https://blog.taaas.jp/images/infer-expr.jpg" alt="" width="900" height="271" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><p>これをtscで変換すると以下のようになるのですが、これを見て、TypeScriptの型はほんとに実行時には影響のないものなのだなと実感することもできます。</p><script src="https://gist.github.com/usualoma/d9d08f43189ab7594ff0b738bf93c2d2.js"></script><p>足し算の定義は業務の役には立たないものの、このあたりを勉強しつつTypeScriptを使っているウェブのフレームワーク（<a href="https://github.com/yusukebe/hono">🔥</a>）に<a href="https://github.com/yusukebe/hono/pull/102">Added type to c.req.param key.</a>というPRを作ってみて、引数から型を生成するようなパターンには可能性があるなと感じたりもしています。</p><p><img src="https://blog.taaas.jp/imags/hono-jpg" alt="" width="900" height="366" class="asset asset-image" style="max-width:100%;height:auto;display:block"/></p><p>ちなみにTypeScriptではdocument.querySelector(`a`)と指定したときに引数からHTMLAnchorElementが推論されたりして面白いのですが、`div a`や`a[href^="#"]`だとHTMLElementになってしまうというのがあるのですが、以下のように指定すると要素名っぽいものから推論されるようにできます。（面白いけど、やっぱりこれも使う機会はないとは思いますが。）</p><script src="https://gist.github.com/usualoma/23b56d286e440e9511ae6c92094063da.js"></script>]]>
        
    </content>
</entry>

<entry>
    <title>MTBockEidtorのカスタムブロックでData APIを使う方法</title>
    <link rel="alternate" type="text/html" href="https://blog.taaas.jp/mt/customblock-with-dataapi/" />
    <id>tag:blog.taaas.jp,2021://2.139</id>

    <published>2021-12-25T08:20:00Z</published>
    <updated>2021-12-25T08:21:25Z</updated>

    <summary>これはどんな記事か？Movable Type 7でプラグインとして利用できるMT...</summary>
    <author>
        <name>Taku Amano</name>
        
    </author>
    
        <category term="Movable Type" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="https://blog.taaas.jp/">
        <![CDATA[<h3>これはどんな記事か？</h3><p>Movable Type 7でプラグインとして利用できるMTBlockEditorでは、管理画面で作成する「カスタムブロック」やプラグインから追加する独自のブロックでブロックの種類を追加することができますが、それらのブロックの中でData APIを使うことも可能です。</p><p>この記事ではいくつかのパターンを紹介していきます。</p><h3>管理画面で作成するカスタムブロック</h3><p>まず最初に「カスタムブロック」を使った例の紹介になりますが、最初に書いておくとこの方法は実際のところなかなか厳しいです。</p><ul>
<li>srcがdata:であるiframeの内で実行されれるため、JavaScriptでData APIにアクセスする際のOriginヘッダーがnullになります。そのため mt-config.cgi で DataAPICORSAllowOrigin の環境変数に対して null を指定する必要があります（これは、外部のサイトからでも JavaScript でアクセス可能にするという設定になります）</li>
<li>カスタムスクリプトで実行するためプレビューが更新されるたびにスクリプトが実行される形になり、実行毎の状態を保存することができません。つまりプレビューが更新されるたびにData APIへのアクセスが発生します。CGIで実行している時にはレスポンスが悪くなったり、また認証を必要とする場合にはプレビューが更新されるたびに認証が発生する形になったりしてしまう問題があります。</li>
</ul><p>というところが主な厳しいポイントです。</p><p>しかし、そういう部分もありつつではありますが、IPアドレス制限やBASIC認証を設定すれば利用できるケースもありますし、まずはPoCとして、実現が可能かどうかというところも大事だと思うので、以下で簡単な例を紹介します。</p><h4>カスタムスクリプトの効率的な開発と運用の1つの方法</h4><p>本題に入る前に、カスタムスクリプトの開発と運用の方法を1つ紹介します。</p><p>公式でもよく例として出されているカスタムスクリプトに直接style要素やscript要素を書くやり方は、一つの管理しやすい方法ではありますが、JavaScriptの処理が増えてくるとコーディングが大変であったり更新がしにくくなったりする面もあります。そういった時には、cssやjsのファイルを外部に置いて、linkやscript要素で読み込む方法を使うことができます。例えば以下のような感じです。</p><script src="https://gist.github.com/usualoma/e85c1f94de4e0674b6bba7b834757434.js"></script><p>CSSはlink要素を使い、JavaScriptはscript要素のsrc属性を使って指定します。JavaScriptにパラメータを渡す場合にはdata属性を使います。script要素にdefer属性（またはtype=moduleにしてもよいかもしれません）を指定することでDOMContentLoadedで囲む必要もなくなりシンプルにすることができます。</p><p>webpackを使っていれば「webpack serve」でバンドルしたファイルをローカルの開発サーバーから参照したりすることもできるので、「ファイルの更新 -&gt; ブロックエディタの編集画面のリロード」だけで（カスタムブロックの保存操作などをすることなく）開発をしていくことができるようになります。</p><p>今回の例でもこのやり方で開発を行っています。</p><h4>公開されている記事のリンクを挿入する</h4><p>ここからが本題です。Data APIを使って記事データを取得してリンクを挿入するブロックを作ります。</p><p>ブロックを追加するとキーワードの入力欄が表示されるので、そこにキーワードを入れて検索ボタンをクリックすると候補が出てきて、選択するとその記事のリンクが挿入されるというものです。</p><p>CSSとJavaScriptは以下のようにしました。</p><script src="https://gist.github.com/usualoma/c30e0265abde4813b2f997a14aeb5982.js"></script><script src="https://gist.github.com/usualoma/60be3b9c3c4c964bafc49d302ed6815f.js"></script><p>GitHubに保存しておくとjsdelivrなどを使ってCDN経由で参照できるので、カスタムブロックのカスタムスクリプト欄は以下のようになります。</p><script src="https://gist.github.com/usualoma/a5d1fbcd4e1a2fbaf4dfa28bfcb243a7.js"></script><p>以下のように動作します。</p><video controls style="max-width: 100%">
    <source src="https://blog.taaas.jp/movies/published_entries.mp4"
            type="video/mp4">
</video><p>前述の通りカスタムブロックでは<span>厳しいポイントも多いですが、状況によっては利用できそうな雰囲気も感じられるのではないかと思います。</span></p><h3><span>プラグインから追加する独自のブロック</span></h3><p>プラグインから独自のブロックを追加する場合にはカスタムブロックの時にあったような制限はなく、管理画面へJavaScriptを挿入するような自由度で作成することができます。（その反面、XSSなどのセキュリティ的な問題が発生しないように配慮する必要がありますが、<a href="https://www.npmjs.com/package/generator-mt-block-editor-block" target="_blank" rel="noopener">雛形作成ツール</a>から作成した場合にはセキュリティ的な問題が起きにくいようにもなっています。）</p><p>この記事ではData APIを使った独自のブロックの例として、<a href="https://github.com/usualoma/mt-plugin-mtbe-DataAPIBlockExample" target="_blank" rel="noopener">DataAPIBlockExample</a>とを作成しました。基本的な動作としては前述のカスタムブロックでの例と同じですが、<a href="https://github.com/m-logic/mt-plugin-dataapi-proxy" target="_blank" rel="noopener">DataAPIProxy</a> を使って現在のユーザーでサインインした状態で記事を取得するので、未公開の記事のリンクも挿入できるようになっています。その他にも以下のような違いがあります。</p><ul>
<li>カスタムブロックのように何度も読み込まれたりしないので、よりリッチな表現を利用しやすい
<ul>
<li>また表現については、CMSのスタイルをそのまま利用できるので、統一感のあるUIで作りやすい</li>
</ul>
</li>
<li>「挿入時の検索語」のような（出力に含まない）メタ情報も、簡単に保存しておくことができる</li>
</ul><p>以下のように動作します。</p><video controls style="max-width: 100%">
    <source src="https://blog.taaas.jp/movies/mt-plugin-mtbe-DataAPIBlockExample.mp4"
            type="video/mp4">
</video><p><a href="https://www.npmjs.com/package/generator-mt-block-editor-block" target="_blank" rel="noopener">雛形作成ツール</a>で作成されたものからは<a href="https://github.com/usualoma/mt-plugin-mtbe-DataAPIBlockExample/compare/0d4c3066e06a6ec3314418f5b60f5415f92e5719..d95bd80a3764266651731d9f254eb013c824d1b9" target="_blank" rel="noopener">それほど多くない差分</a>でここまで動くようになるので、構築するサイトにあわせた独自のブロックをこういった形で作成をするというのも、現実的な選択肢であると思います。</p><h3>この記事について</h3><p>この記事は <a href="https://adventar.org/calendars/6369">Movable Type Advent Calendar 2021</a> の25日目の記事です。皆様お疲れさまでした。それでは良いお年を！</p>]]>
        
    </content>
</entry>

</feed>
