TODO #
**このファイルの更新について:** 運用ルールは
.claude/skills/todo-md/SKILL.mdにある。 タスクを追加・完了するときは必ずそれに従う。要点: このファイルには着手できる 作業だけを書く([ ]/[-])。終わった作業は[x]にし、定期的な GC でTODO-archive.mdに移す。
このファイルは着手できるタスクだけを管理する。完了した作業は、定期的な GC で
TODO-archive.md に移す。
To Be Implemented #
- [ ] **MoonBit の http ライブラリから非同期の I/O を使えるようにする**:
serveは 同期なので、ハンドラーから KV、R2、D1、Static Assets、外へのfetchを呼べない。 JSPI(WebAssembly.Suspending/promising)で Wasm から JS のfetchを待つ形が、 spike(moonbit/experiments/wasm-fetch)では Node とwrangler devで動いた。これをライブラリに取り込み、 本番の Workers で確かめる。上の Static Assets の TODO の「文章を Wasm にどう渡すか」とつながる。 探索メモの「ライブラリとして出すときに考えること」を参照。 - [ ] **MoonBit 版のブログで、記事と文書の解析を isolate の起動時に移す**: 今は
最初のリクエストで解析している(
worker.mbtのRef(None))。ts 版では、起動時に 解析すると Startup Time は 3 ms から約 13 ms に増えたが、新しい isolate に当たった リクエストの CPU 時間は 18〜43 ms から 0〜3 ms に減った(探索メモの「デプロイ」)。 MoonBit 版でも同じことが起きるかを確かめる。- 完了の条件:
make compareで Go 版と一致したまま、Startup Time とwrangler tailのcpuTimeを、今の形と比べて調査メモに記録する。
- 完了の条件:
- [-] **Go と MoonBit の
pkg/elとpkg/tinymarkdownに profiler をかけて速くする**: profiler で 2 つのパッケージの重いところを見て、確保と走査を直す。まず Go 版から (調査メモ、issue #39)。 - [-] **
moon run --profileが空になる原因を切り分けて直す**: この環境(WSL2)ではmoon run --profileが常にSamples: 0になる。原因は、環境側では perf が libdw / libelf を持たずにビルドされていること、moon 側ではperf recordに--sample-cpuを 付けずパーサがヘッダの[cpu]を必須にしていることの 2 つだった (issue #52)。 - [ ] **ts 版のブログが front matter の
prevとnextで起動できない**: 記事がprev:/next:を持つようになったが( docs/sketch/ja/blog.md)、ts 版のfrontMatterKeys(ts/examples/blog/src/content.ts)はtitleとdescriptionしか認めないので、loadPostsが例外で止まりapp.test.tsが落ちる。Go 版と MoonBit 版の relNav(記事末の 前後リンク)に相当するものもまだない。 - [ ] **ts 版にも
/previewを足す**: Go 版と MoonBit 版に足した プレビューページを ts 版にも揃える( issue #71)。 先に上の「ts 版のブログが front matter のprevとnextで起動 できない」を直す必要がある。 - [x] **
TestEmbeddedHumanBundleが posts の記事追加で落ちる**: go/examples/blog/internal/site/collections_test.go が posts を wsl-opencode の1件だけと決め打ちしているので、 posts/2026-10-27-why-ai-novel-is-bored.md を足した 2bcf887 からmake test-goが落ちる。件数ではなく wsl-opencode の束を探して 確かめる形にする。 - [ ] **ts 版のテストが wsl-opencode の記事の旧本文を期待している**:
ts/examples/blog/src/app.test.ts の「all three Gist files form one
article with separate downloads」は
# 【記事で始まる本文を、 「the human Gist article renders asterisk bullets as lists」は**選定理由**を含む箇条書きを期待しているが、記事を直した dd249e8 から本文が変わり、make test-tsの2件が落ちる。今の 本文に合わせて期待値を直す。
Future work #
- [ ] **見出しの
{#id}記法で明示的な id を付けられるようにする**: 自動 スラッグ化(issue #69)はタイトルから id を作るので、タイトルの変更や 翻訳で id が揺れる。Pandoc 式の## 見出し {#my-id}を tinymarkdown の 構文拡張として入れると、表示と独立した安定した id が書ける (issue #69 の コメントで先送りに決めた)。
- [ ] **
svg ブロックの中身をサニタイズする**:svg フェンスのブロックは 中身をそのまま HTML に書くので、<script>やon*属性、foreignObject経由でブログと同じオリジンのスクリプトが動く。今は記事の作者=自分なので 意図どおりだが、要素/属性の allowlist 方式のサニタイザーを Go と MoonBit に同じ形で入れると安心(Devin Review SEC finding 由来)。なお/previewは textarea の任意入力をそのまま描くので、他人が用意した Markdown を貼ると被害者のブラウザーでスクリプトが動きうる( PR #77 の Devin Review でも指摘)。
- [ ] **記事に図を載せられるようにする**: 同じ wasm をブラウザーと Worker で
動かしたいのように、ブラウザー、Worker、
workerd、wasm の関係を図で示したくなる。図をテキストのまま Markdown に書き、
ページでは図として見せたい。tinymarkdown のコードブロックは言語名を持つ
ようになり(
CodeBlock(String, info~))、\\\svg フェンスのブロックは inline の<svg>` として描画される。記法は mermaid/graphviz などもあるので svg 直書きで足りるか、どこで描くか(ビルド時、Worker、ブラウザー)を決める。 画像で済ませる道もあるので、下の画像の TODO より先に考える。
- [-] **記事に画像を載せられるようにする**: バンドルの
.svgメンバーがimage/svg+xmlで配信され、ページでは<img>として表示されるようになった (バンドルの例)。![]()の画像記法とdata:URI は未対応、メンバーはテキストしか持てないので PNG/JPEG など バイナリー画像は載せられない。置き場所(リポジトリに入れて埋め込む、R2 など 外に置く)と、tinymarkdown の画像の記法から決める。
- [ ] **バンドルメンバーのファイル名を URL エスケープする**:
#や?、空白を 含むメンバー名は、セクションのリンクや<img src>(base + "/" + m.Name)が そのまま置くのでブラウザーで別のパスとして解釈されて 404 になる。<a href>の時点で同じ問題なので svg 固有ではない。パーセントエンコードで 作る URL と、Go/MoonBit 両方のルーティングでのデコード側の一致も要確認。