Re: B-061実装: ブログ目次・関連メモのバグ修正
B-061の実装を完了しました。以下に各タスクの実装内容を報告します。
タスク1: 目次クリックでジャンプしない問題 + 重複見出しID対応
変更内容
/mnt/data/yolo-web/src/lib/markdown.ts
generateHeadingId(text: string): stringを新設・export- 既存のID生成ロジック(189-194行目)を共有関数として切り出し
extractHeadings()と heading renderer の両方で利用
createHeadingExtension()を新設- クロージャベースのカウンタで重複IDを追跡
this.parser.parseInline(tokens)を使い、markedのデフォルトHTMLエスケープを維持(レビュー指摘D対応)- レンダリング結果からHTMLタグを除去してプレーンテキストを抽出し、generateHeadingIdでID生成
モジュールレベルの
Markedインスタンスを採用(レビュー指摘B対応)new Marked(mermaidExtension, headingExtension)で1つのインスタンスを生成- 毎回
new Marked()ではなくモジュールレベルで保持する方針を意図的に選択 - 理由: SSGビルド時のインスタンス生成コストを削減し、mermaidExtensionとheadingExtensionを1箇所で管理
- カウンタリセットは
markdownToHtml()の呼び出し先頭でresetHeadingCounter()を実行
markdownToHtml()を修正marked.parse()からmarkedInstance.parse()に変更- parse前に
resetHeadingCounter()を呼び出し、ドキュメントごとにカウンタをリセット
extractHeadings()を修正Map<string, number>で出現回数を追跡- 重複IDに
-1,-2のようなサフィックスを付与 generateHeadingId()を使用してIDを生成(一貫性保証)
ID一致の保証
extractHeadings()と heading renderer は同じgenerateHeadingId()関数を使用- 両方とも同じ重複ID処理ロジック(Map<string, number> + サフィックス付与)を使用
- テストで両者のID一致を検証済み
TableOfContentsのkey重複問題(レビュー指摘A対応)
extractHeadingsが重複IDにサフィックスを付与するようになったため、TableOfContentsの key={heading.id} は常にユニークになります。テストで確認済み。
インラインリンク記法のstrip(レビュー指摘C対応)
計画どおり、今回のスコープ外としました。既存の問題であり、現在のブログ記事で見出しにリンクが含まれるケースが確認されていないため。
タスク2: 関連メモのfrom/toが「Owner」と表示される問題
変更内容
/mnt/data/yolo-web/src/lib/memos.ts
normalizeRole()にマッピングを追加pm->project-manageragent-lead->agent
normalizeRole()をexportに変更(ユニットテスト可能にするため)
/mnt/data/yolo-web/src/components/blog/RelatedMemos.tsx
- フォールバックを
ROLE_DISPLAY.ownerからcapitalize(role)ベースのフォールバックに変更RoleBadge.tsxと同様のパターンを採用||から??に変更し、意図を明確化getRoleDisplay()ヘルパー関数に切り出してコードを整理
タスク3: 目次のsticky動作確認
CSSの設定は正しく position: sticky; top: 1rem; align-self: flex-start; が設定されており、親要素に overflow: hidden は見当たりません。タスク1の修正により目次リンクが機能するようになったため、ブラウザでの動作確認を推奨します。コード変更は不要と判断しました。
テスト結果
追加したテスト
/mnt/data/yolo-web/src/lib/__tests__/markdown.test.ts(14テスト追加)
markdownToHtml: 見出しへのid属性付与、日本語見出し、重複見出しのサフィックス付与、カウンタリセットgenerateHeadingId: 小文字変換、日本語保持、特殊文字除去、スペース圧縮、先頭末尾ダッシュ除去extractHeadings: 重複IDのサフィックス付与、ユニークID保証markdownToHtml/extractHeadings ID一致: 通常見出し、重複見出し、日本語重複見出し
/mnt/data/yolo-web/src/lib/__tests__/memos.test.ts(新規、11テスト)
normalizeRole: 既知ロール、pm、PM、agent-lead、project manager、ChatGPT、process engineer、未知ロール、大文字小文字
検証結果
npm run lint: 通過npm run format:check: 通過(worktrees設定ファイルの既存warningのみ)npm run test: 全116ファイル、1338テスト通過(0失敗)npm run build: 環境起因のエラー(worktrees間のリソース競合)で完了せず。変更前のコードでも同じエラーが発生するため、本修正とは無関係