開発excel-viewer完了
Excel風行番号表示機能の実装状況
そもそもの課題
マークダウンコンテンツの表示に、Excel風の行番号を追加したい。
要件
- 全てのコンテンツ要素(見出し、段落、リスト、コードブロック、テーブル)に行番号を表示
- 行番号は小さいグレーの数字で表示
- 全ての行番号を左端の同じX座標に揃える(最重要)
- 選択できないようにする
- スクロールしても見やすいように
クリアできている点
✅ 基本的な行番号表示
- CSSの
counter-resetとcounter-incrementで自動採番 ::before擬似要素を使って行番号を表示- グレー色(
#9ca3af)の小さい文字(0.7rem)で表示 user-select: noneで選択不可
✅ 見出しの行番号配置
.doc__body :deep(h1)::before,
.doc__body :deep(h2)::before,
.doc__body :deep(h3)::before {
position: absolute;
left: -3rem;
top: 50%;
transform: translateY(-50%);
}
- 見出しは垂直方向中央に配置
- 左端に固定(
left: -3rem)
✅ 段落とコードブロックの行番号配置
.doc__body :deep(p)::before,
.doc__body :deep(pre)::before {
position: absolute;
left: -3rem;
top: 0;
}
- 段落とコードブロックは上端に配置
- 左端に固定(
left: -3rem)
✅ コードブロックの言語ラベル競合回避
- 元々
::beforeに言語ラベル(BASH, JSなど)を表示していた ::afterに移動することで、::beforeを行番号に使用可能に
実装の変遷
初期の問題:リスト項目の行番号がずれる
当初、リスト項目にも行番号を表示しようとしたが、以下の問題に直面:
問題:
- リスト項目(
li)の行番号が右にずれる - ネストされたリストはさらに右にずれる
position: absoluteのleftは最も近いposition指定された祖先要素からの相対位置のため、親ul/olのインデントの影響を受ける
試した解決策:
calc()で親のmarginを打ち消す → ネストで失敗right: calc(100% + 0.5rem)を使用 → リストの幅に依存position: fixedを使用 → スクロール時に問題
最終的な判断:
- マークダウンには元々行番号が表示されていない
- 箇条書きに行番号を付ける必要性は低い
- 複雑な実装よりも、リスト項目から行番号を削除してシンプル化
最終的な解決策
✅ CSS変数ベースのアプローチ(実装済み)
CSS変数を使ってネストレベルのインデント量を累積計算し、常に絶対位置に行番号を配置する方法を実装。
.doc__body {
--doc-line-gutter: 3rem;
--doc-line-indent: 0rem;
}
.doc__body :deep(ul),
.doc__body :deep(ol) {
--doc-line-indent: calc(var(--doc-line-indent, 0rem) + 1.25rem);
}
.doc__body :deep(li)::before {
left: calc(var(--doc-line-gutter) * -1 - var(--doc-line-indent, 0rem));
}
この方法により、ネストされたリストでもインデント量を累積計算し、全ての行番号を統一位置(-48px)に配置可能。
✅ さらなるシンプル化:リスト項目から行番号を削除
決定事項:
- マークダウンには元々行番号が表示されていない
- 箇条書き(リスト項目)に行番号を付ける必要性は低い
- リスト項目(
li)から行番号を削除してシンプル化
最終仕様:
- 見出し(h1-h6):行番号表示 ✅
- 段落(p):行番号表示 ✅
- コードブロック(pre):行番号表示 ✅
- テーブル(table):行番号表示 ✅
- リスト項目(li):行番号なし ✅
実装結果
全ての行番号が-48pxで完璧に揃い、リスト項目は行番号なしでシンプルに表示される。
実装ファイル
apps/web/app/components/DocPage.vue の<style scoped>セクション