Skip to content

v1.3.0 - #194

Merged
riiimparm merged 36 commits into
mainfrom
develop
Sep 8, 2026
Merged

v1.3.0#194
riiimparm merged 36 commits into
mainfrom
develop

Conversation

@riiimparm

Copy link
Copy Markdown
Collaborator

rehype-tocが生成する.tocを2カラムグリッドで本文脇に固定し、
IntersectionObserverで現在読んでいるセクションのリンクをハイライトする。
新規ライブラリは追加せずネイティブAPIのみで実装。
@terrastruct/d2 (ブラウザ向けWASM実装) をCDN経由で動的importし、
mermaidと同じパターンでd2コードブロックをSVGに変換するremarkプラグインを追加。

Shikiが"d2"言語を認識できずplaintextにフォールバックしてしまうため、
markdown.syntaxHighlight.excludeLangsでd2のみシンタックスハイライトを無効化。
コンテナにmax-width:80vw、SVGにwidth/height:auto + max-width:100%/max-height:90vhを
指定し、アスペクト比を保ったまま画面内に収まるようCSSのみで制約(img的なreplaced
element縮小に任せる)。1024px未満(モバイル)は従来通り制約なし。
前回のtoc sidebar化(gridレイアウト+toc sticky+scrollspyハイライト)は
方針転換のため差し戻し、.tocは無変更に戻した。

代わりにVSCodeのSticky Scrollのような挙動を実装:
記事中のh2/h3/h4をクライアントサイドJSでネストしたラッパー
(.stack-section > .stack-heading + .stack-content)に組み替え、
各見出しをposition:stickyで階層順にヘッダー下へ積み重ねる。
ネストしたsticky要素は所属セクションを抜けると自然に外れる
(CSSのposition:stickyの挙動のみで実現、追加のJS制御は不要)。

見出しがスタック位置に固定される直前の約4rem分のスクロール量に
連動して、CSSカスタムプロパティ(--stack-progress)経由でfont-sizeを
本来のサイズからスタック時サイズへ連続的に縮小させる。
横長/縦長のD2図を含む再現用記事。デスクトップ幅での80vw/90vh制約の
証跡として残す。
@terrastruct/d2のJS APIはthemeOverrides的なAPIを持たず、themeIDでは
mermaid側の配色(背景#0f172a/ボーダー#38bdf8/ライン#22d3ee/文字#e2e8f0)に
近いものが無かったため、D2のテーマシステムが付与する意味的クラス
(N1-N7, B1-B6, AA/AB1-5)をCSSで直接上書きしてmermaidと同じ配色にした。

また、高さ制約(max-height:90vh基準のスケールダウン)をデスクトップ限定の
メディアクエリの外に出し、モバイルでも常時適用されるようにした
(幅80vwの制約は引き続きデスクトップのみ)。

コンテナはmermaidと同様にflex+justify-content:centerで中央揃えにし、
Tailwindクラス文字列(purge対象外で効かない可能性がある)からinline
style指定に変更した。
VSCode風の見出しネストスティッキースタック(DOM再構成+stack-progressに
よるフォントシュリンク)は撤回し、目次通過後にヘッダー直下へ現在の
h2 > h3 > h4パスを表示する薄いパンくずバーに置き換えた。DOMは元の
フラットな見出し構造のまま、スクロール位置から現在アクティブな見出しを
算出して表示するだけのシンプルな実装。
- 長い見出しで現在地(白文字)側が消えないよう、親階層側を別要素に分離しflex-shrink:0の現在地を優先して残す形に変更
- バー内側をヘッダーと同じcontainerクラスでラップし左端をロゴと揃える
- document.fonts.readyとResizeObserverでフォント読み込み後・レイアウト変動後も見出し位置キャッシュを更新
- デモ記事の説明文を旧ネストスタック方式からパンくずバー方式の説明に更新し、省略確認用の長い見出しを追加
connectionのfill-B1(矢印先端マーカーのpolygon)とstroke-B1(線本体の
path、fill="none")を同一セレクタでまとめてfill/strokeを両方
!important上書きしていたため、線本体のfill="none"が上書きされ、
閉じていないbezierパスがブラウザにより暗黙的に閉じられて塗りつぶされ、
扇状に複数エッジが出る図で特に目立つ太いリボン状の見た目になっていた。
fill-B1とstroke-B1を別々のセレクタに分離し、それぞれの役割(マーカー
の塗り/線の色)にのみ対応するプロパティを当てるよう修正。
BlogLayout.astroにインライン実装されていたdiv/script/styleを
src/components/HeadingBreadcrumbBar.astroへ移動。機能・見た目の変更なし。
ファイル名(HeadingBreadcrumbBar.astro)とDOM上のid/classが
heading-crumbのままずれていたため、子要素のクラス名
(__inner, __ancestors, __item, __item--current, __sep)も含めて
heading-crumb-barに揃えた。機能・見た目の変更なし。
sepのテキストを' > 'としていたため、currentItemフレックスアイテムの
先頭子要素になるケース(祖先→現在地の境目)で、CSSの空白つぶしにより
先頭のスペースだけ描画上消え「実装> Claude Codeをインストール」の
ように左側の余白が無くなっていた。祖先同士をつなぐsep(同一span内の
途中に位置する)ではこの問題は起きないため、階層や文言によって
余白の有無が不揃いに見えていた。

space文字をやめて'>'のみとし、margin: 0 0.3emで余白を作ることで、
flexアイテム境界の位置によらず常に安定した余白になるようにした。
見出しが長い場合に横スクロールを可能にした前回の実装は、
ヘッダーと同じcontainerクラスのpaddingをスクロール対象の要素に
直接持たせていたため、スクロール終端でそのpaddingが失われ、
長い見出しが左右マージンを無視して画面端まではみ出してしまう
問題があった。

.heading-crumb-bar__inner(containerのpadding、常に固定・非スクロール)
の内側に新設した.heading-crumb-bar__track(overflow-x:auto)を置き、
実際にスクロールする要素をtrackだけに限定。マージン領域は常に
バー背景色のみで、どれだけ長い見出しが来てもテキストがマージンに
はみ出さないようにした。

あわせて、自動スクロールの挙動を「現在地見出しの末尾」ではなく
「先頭」が見える位置に変更(currentItemの左端をtrackの左端に揃える)。
.heading-crumb-bar__innerのpadding-top(0.4rem)を削除し、
ヘッダー直下に隙間なく積み重なるようにした。padding-bottomは
テキストとしての読みやすさのため維持。
配色・矢印修正の経緯を詳しく説明する長いコメントが多く、初見の
可読性を下げていたため、要点(何のためか)だけ残して簡潔にした。
機能・見た目の変更なし。
クライアント側でCDNからD2 WASMを読み込んでレンダリングしていたのを廃止し、
Node上の@terrastruct/d2でビルド時にSVGへ変換してpublic/images/blog/<slug>/に
保存する方式に変更。d2のD2クラスは同時に1リクエストしか処理できないため
逐次処理に統一し、worker_threadsも明示的にterminateする。

またprefetchAllとの組み合わせでdev起動時に画像404が発生する競合があったため、
出力先ディレクトリを事前削除せず上書き+処理完了後の孤児ファイル削除に変更した。
# Conflicts:
#	astro.config.mjs
#	pnpm-lock.yaml
強制的なダーク配色CSS上書きをやめ、D2ネイティブのthemeID:0(Neutral default)+
sketch:trueをrenderOptionsで指定する方式に変更。コンテナの背景色・paddingも
撤去し、画像サイズぴったりにフィットするようにした。デスクトップの最大幅は
80vw→60vw、最大高さは90vh→80vhに変更。
クライアント側でCDNからmermaid.jsを読み込んでレンダリングしていたのを廃止し、
puppeteer経由の@mermaid-js/mermaid-cli(renderMermaid)でビルド時にSVGへ変換して
public/images/blog/<slug>/に保存する方式に変更。d2と同じくthemeはmermaidの
デフォルトテーマを使用する。

d2/mermaid共通で使うコンテナ用CSS(サイジング・中央寄せ)は各remarkプラグインの
per-article style注入から、src/layouts/BlogLayout.astroのグローバルCSSに寄せ、
クラス名も.d2-container/.d2-diagramから.diagram-container/.diagram-frameへ
統一した。
mermaid本体のlook:'handDrawn'は図種によって効かないものがあった(gantt/pie等)
ため、レンダリング後のSVGをsvg2roughjs(rough.js)で後処理する方式に変更。
図種によらず一様に手描き風の揺らぎ・ハッチングが適用されるようになった。

mermaidはデフォルトでラベルをforeignObject(HTML)で描画しており、
svg2roughjsがそれを正しく手描き変換できず日本語ラベルが文字化けしていた。
htmlLabels:falseでネイティブSVGの<text>を強制することで解決した。
あわせてsvg2roughjsの出力(viewBoxを持たずwidth/height属性のみ)に
対応するようextractSize()にフォールバックを追加。
theme:'base'+themeVariablesで、mermaidの配色をD2の実際のパレット値
(fill-B4:#E3E9FD、stroke-B1:#0D32B2、fill-N1:#0A0F25等)に合わせた。
mermaid公式のtheming docsに載っている変数を参照し、フローチャート/
シーケンス図/ノート/円グラフ/状態遷移図など今回使用する図種に関連する
項目を網羅的に設定している。
コードを読めば分かる説明的コメント(JSDocヘッダー等)を削除し、
非自明な理由(競合回避・ライブラリ制約・フォント回避策など)の
説明だけ一行に簡潔化した。
CIはpnpm install(non-frozen)でPrettier 3.9.6に解決される一方、
ローカルのlockfileは3.5.3に固定されており、バージョン差でformat:checkが
CIのみ失敗していた。prettierを3.9.6に上げて再フォーマットし一致させた。
@netlify

netlify Bot commented Sep 8, 2026

Copy link
Copy Markdown

Deploy Preview for rowicy ready!

Name Link
🔨 Latest commit 869d860
🔍 Latest deploy log https://app.netlify.com/projects/rowicy/deploys/6aa01219b8c8f30008ab8003
😎 Deploy Preview https://deploy-preview-194--rowicy.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@riiimparm
riiimparm merged commit e0d34e5 into main Sep 8, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant