

Notion上ではきれいに見える記事が、ブログ上ではレイアウトが崩れる。Notion APIのブロック構造の特性を理解しないと解決できない問題が4つあった。
Notionのcallout/quoteブロックの子ブロック問題
連続コードブロックがくっつく原因とCSS修正
テキストが残る原因と除去
callout絵文字重複の原因と対策
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つのコードブロックがくっついて表示される。
pre要素にmarginがなかった。
CSSで.znc pre { margin: 1.5rem 0; }を追加。またNotion記事側でも連続コードブロックの間に説明テキストを入れる運用ルールを追加。
記事内にや""がそのまま表示される。
HTML生成後に正規表現で除去:
processedHtml = processedHtml
.replace(/<p>\s*\[toc\]\s*<\/p>/gi, '')
.replace(/"\[toc\]"/gi, '')
.replace(/\[toc\]/gi, '');
calloutのアイコンとテキスト内の絵文字が両方表示される。
テキスト先頭の絵文字を正規表現で除去:
let cleanText = text.replace(
/^[\u{1F300}-\u{1F9FF}\u{2600}-\u{27BF}]+\s*/u,
''
).trim();
Notionのcallout/quoteの子ブロックはhas_childrenで検出できる
記事化スキルにフォーマットルールを追加して再発防止
全記事を一括チェックするスクリプトを用意すると便利
Notion APIのブロック構造を理解することが重要
callout/quoteの子ブロックは再帰取得が必要
コード側の除去だけでなく、記事の書き方ルールも整備する
この記事が役に立ったら共有しよう

Koki
フルスタックエンジニア / React, Next.js, TypeScript