Skip to content

scaffold への resolveIdTemplate 組み込み + 依存膨張回避策の検討 #907

Description

@YusukeHirao

背景

PR #906@d-zero/site-migratorresolveIdTemplate 純関数を追加した。rewritePageRefs が残す {{<id>}} token を後段ビルド時に実 URL に解決するためのもの。site-migrator 自身は URL を知らないため、組み込みはビルドツール側の責務として残してある。

このイシューでやること

@d-zero/scaffoldkamado.config.ts に id 解決ロジックを組み込み、site-migrator 出力ページが scaffold ビルドでそのまま使えるようにする。

検討時に下記のうちどれを採るか決める必要がある:

案 A: scaffold に inline

kamado.config.ts 内に 10 行程度の regex replace を直接書く。

  • ✅ 依存ツリーを変えない(puppeteer 等が伝播しない)
  • ✅ 一番手数が少ない
  • ❌ site-migrator 側の resolveIdTemplate と仕様コピーが二重化(仕様変更時に同期が必要)

案 B: 新規軽量 workspace パッケージ

@d-zero/page-id-token のような純関数だけの新パッケージを packages/@d-zero/ に作り、scaffold と site-migrator の両方から使う。

  • ✅ 仕様の単一ソース化
  • ✅ scaffold 経由で puppeteer が伝播しない(純関数だけのパッケージなので依存ゼロ)
  • ❌ パッケージ数が増えるオーバーヘッド(release タグ、CI、ドキュメント等)

案 C: 別リポの @d-zero/shared に移す

@d-zero/shared (別リポ) に純関数を移し、scaffold と site-migrator の両方から使う。

  • ✅ 仕様の単一ソース化
  • ✅ 既存の共有パッケージなのでパッケージ数は増えない
  • ❌ 別リポへの PR が必要(本リポ単独で完結しない)

案 D: site-migrator を publish 解禁してそのまま import

  • ✅ 既に書いた API がそのまま使える
  • ❌ scaffold 経由で @nitpicker/crawlerpuppeteer(Chromium 100MB+ postinstall)が伝播し、site-migrator を使わない scaffold ユーザーに不要な代償

実装メモ(採用案が決まったら参照)

// kamado.config.ts (概要)
const idToUrl = new Map<number, string>();

pageList: async (pageAssetFiles) => {
  idToUrl.clear();
  for (const file of pageAssetFiles) {
    const { metaData } = await file.get();
    if (typeof metaData.id === 'number') idToUrl.set(metaData.id, file.url);
  }
  // kamado は mutable な配列を期待するので spread でコピー
  return [...pageAssetFiles];
},
compilers: [
  pageCompiler({
    replace: (content) => resolveIdTemplate({ html: content, idMap: idToUrl, onUnresolved: ... }),
    // ...
  }),
],

注意点

  • pageList は kamado の getGlobalData 経由でサーバ起動時に 1 度だけ走る。dev サーバ中にページを増減した場合は再起動が必要(kamado 自体がそうなっている)。
  • pageCompiler.options.globalData.dir が設定されているときだけ kamado は pageList を呼ぶので、globalData を外す方向の改修と組み合わせる場合は注意。
  • as const satisfies UserConfig 構文下では pageList の戻り値型 ((CompilableFile & { title?: string })[]) と引数の readonly CompilableFile[] がミスマッチするので spread コピーが必須。
  • 同一 id を持つページが複数あると last-write-wins で silent に上書きされる。警告を出す仕掛けが要検討。
  • id: "10000"(YAML が文字列で受け取った場合)は typeof === 'number' ガードで silent drop される。数値強制 or 警告のどちらかにする必要あり。

QA レビューで上がった追加観点

  • Number.isSafeInteger チェックで極大 id の精度欠落を検出
  • assignPageIds → buildPageIdLookup → rewritePageRefs → resolveIdTemplate のラウンドトリップ統合テスト
  • 連続トークン {{1}}{{2}} / 隣接 {{1}}{{1}} の置換境界
  • ?q=foo#h を含む URL が idMap の値側にある場合のクエリ二重化挙動(README の "callers が前処理する" 仕様の回帰テスト)

関連 issue (別リポ)

関連 PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions