【トラブルシューティング】Notionブログのレイアウト崩れ対策 — callout・コードブロック・目次の罠

この記事でわかること
- callout の中のリストがバラバラになる原因(子ブロックとして別に入っている)
- 連続したコードブロックがくっつく問題
- [toc] が本文に残る問題と、整形後の HTML に正規表現を当ててはいけない理由
- callout のアイコンと本文の絵文字が二重になる件
Notion API を CMS にしてブログを運用していること。
概要: Notion APIをCMSとしてブログを運用する際に遇遇したレイアウト崩れの原因と対策。calloutの子ブロック問題、連続コードブロック、[toc]残り、絵文字重複の4つの罠と解決策。
はじめに
Notion 上ではきれいに見える記事が、ブログ上ではレイアウトが崩れる。Notion API のブロック構造の特性を理解しないと解決できない問題が 4 つありました。
1. callout/quoteの子ブロック問題
症状
Notionで1つのcallout内にリストを書いても、ブログでは各項目が個別のcalloutとして表示される。
原因
Notion APIではcallout/quote内のリスト項目は子ブロックとして格納される。rich_textだけ取得してもリストは含まれない。
対策
has_childrenをチェックし、子ブロックを再帰取得:
if (block.has_children) {
const children = await notionFetch(
`/blocks/${block.id}/children`
);
for (const child of children.results) {
if (child.type === 'bulleted_list_item') {
childContent += `\n- ${richTextToMarkdown(
child.bulleted_list_item.rich_text
)}`;
}
}
}2. 連続コードブロックの間隔
症状
2つのコードブロックがくっついて表示される。
原因
pre要素にmarginがなかった。
対策
CSSで.znc pre { margin: 1.5rem 0; }を追加。またNotion記事側でも連続コードブロックの間に説明テキストを入れる運用ルールを追加。
3. [toc] テキスト残り
症状
記事内に [toc] や "[toc]" がそのまま表示される。
当時の対策
HTML 生成後に正規表現で除去していました。
processedHtml = processedHtml
.replace(/<p>\s*\[toc\]\s*<\/p>/gi, '')
.replace(/"\[toc\]"/gi, '')
.replace(/\[toc\]/gi, '');このやり方は後で事故になりました。完成した HTML 全体に正規表現を当てるので、コードブロックの中に書いた [toc] まで消えます。つまり「この記法の説明記事」が書けなくなるということです。
現在は HTML にする前の段階で、ブロック単位に判定しています。「段落ブロックで、中身が [toc] だけなら落とす」とすれば、コードブロックには一切触れません。
教訓: 整形後の文字列に正規表現を当てると、「その文字列を意図して書いた箇所」と区別がつきません。構造が残っている段階で処理するのが安全です。
4. callout絵文字重複
症状
calloutのアイコンとテキスト内の絵文字が両方表示される。
対策
テキスト先頭の絵文字を正規表現で除去:
let cleanText = text.replace(
/^[\u{1F300}-\u{1F9FF}\u{2600}-\u{27BF}]+\s*/u,
''
).trim();Tips
has_children で検出できる参考リンク
まとめ
- Notion API のブロック構造を理解することが重要
- callout/quote の子ブロックは再帰取得が必要
- 整形後の HTML に正規表現を当てない。ブロック構造が残っている段階で処理する
- コード側の除去だけでなく、記事の書き方ルールも整備する
更新履歴
- [toc] 除去の方法について、整形後の HTML に正規表現を当てるとコードブロック内の記述まで消える事故を起こしたことと、現在はブロック単位で判定していることを警告として追加。誤字を修正(遇遇→遭遇)。エスケープされていた [toc] の表記をインラインコードに修正。箸条書きの Tips を callout に統一。自動目次と関連記事へのリンクを追加。「この記事でわかること」「対象読者」を概要プロパティへ移動。


