透過 HTTP 呼叫 API的方式來加入頁面比較複雜,但也更靈活,可以自定義一些操作,在 Notion 中,如果要完整保留 Markdown 的層級結構(標題、清單、程式碼區塊等),單純文字轉換不夠,需要先把 Markdown 解析成 Notion 語法。以下展示如何利用 n8n + Python 轉換程式,並呼叫 Notion API 將內容寫入指定頁面。
以下程式碼可在 n8n 的 Code Node (Python) 執行,將輸入的 Markdown 轉換為 Notion Blocks 格式。
# n8n Code (Python) — Convert Markdown to Notion Blocks
# Input: items[*].json.content.parts[0].text
# Output: items[*].json.blocks → 可直接餵給 Notion API 的 children
import re
def _rt_text(s: str, *, bold=False, italic=False, code=False, link_url=None):
o = {"type": "text", "text": {"content": s}}
if link_url:
o["text"]["link"] = {"url": link_url}
ann = {}
if bold: ann["bold"] = True
if italic: ann["italic"] = True
if code: ann["code"] = True
if ann: o["annotations"] = ann
return o
_inline_pattern = re.compile(
r'(\*\*|__)(.*?)\1|(?<!\*)\*(?!\*)(.*?)\*|(?<!_)_(?!_)(.*?)_|`([^`]+)`|\[([^\]]+)\]\(([^)]+)\)'
)
def parse_rich_text(text: str):
rich, last = [], 0
for m in _inline_pattern.finditer(text):
start, end = m.span()
if start > last: rich.append(_rt_text(text[last:start]))
if m.group(2): rich.append(_rt_text(m.group(2), bold=True))
elif m.group(3): rich.append(_rt_text(m.group(3), italic=True))
elif m.group(4): rich.append(_rt_text(m.group(4), italic=True))
elif m.group(5): rich.append(_rt_text(m.group(5), code=True))
elif m.group(6): rich.append(_rt_text(m.group(6), link_url=m.group(7)))
last = end
if last < len(text): rich.append(_rt_text(text[last:]))
return rich or [_rt_text(text)]
def markdown_to_notion_blocks(markdown: str):
lines, blocks, i = markdown.splitlines(), [], 0
while i < len(lines):
line = lines[i]
if not line.strip(): i += 1; continue
if line.startswith("```"):
lang, i, code_lines = line[3:].strip() or "plain text", i+1, []
while i < len(lines) and not lines[i].startswith("```"):
code_lines.append(lines[i]); i += 1
if i < len(lines) and lines[i].startswith("```"): i += 1
blocks.append({"object":"block","type":"code","code":{"language":lang,"rich_text":[_rt_text("\n".join(code_lines))]}})
continue
if line.startswith("# "): blocks.append({"object":"block","type":"heading_1","heading_1":{"rich_text":parse_rich_text(line[2:])}}); i+=1; continue
if line.startswith("## "): blocks.append({"object":"block","type":"heading_2","heading_2":{"rich_text":parse_rich_text(line[3:])}}); i+=1; continue
if line.startswith("### "): blocks.append({"object":"block","type":"heading_3","heading_3":{"rich_text":parse_rich_text(line[4:])}}); i+=1; continue
if line.startswith("> "):
quote_lines=[line[2:]]; i+=1
while i < len(lines) and lines[i].startswith("> "): quote_lines.append(lines[i][2:]); i+=1
blocks.append({"object":"block","type":"quote","quote":{"rich_text":parse_rich_text("\n".join(quote_lines))}})
continue
if line.startswith("- "):
while i < len(lines) and lines[i].startswith("- "):
blocks.append({"object":"block","type":"bulleted_list_item","bulleted_list_item":{"rich_text":parse_rich_text(lines[i][2:])}})
i+=1
continue
para=[line]; i+=1
while i < len(lines) and lines[i].strip() and not any(lines[i].startswith(p) for p in ("```","# ","## ","### ","- ","> ")):
para.append(lines[i]); i+=1
blocks.append({"object":"block","type":"paragraph","paragraph":{"rich_text":parse_rich_text("\n".join(para))}})
return blocks
output=[]
for item in items:
text=item.get("json",{}).get("content",{}).get("parts",[{}])[0].get("text","") or ""
blocks=markdown_to_notion_blocks(text)
output.append({"json":{"blocks":blocks}})
return output
這段程式會將輸入的 Markdown 文字,轉換為 Notion API 可接受的 children
區塊格式。
接著在 n8n 中新增 HTTP Request Node,用來把轉換後的 blocks 寫入上一篇介紹 Notion 節點所創建的頁面。
設定範例:
{
"method": "PATCH",
"url": "https://api.notion.com/v1/blocks/{{ $json.id.replaceAll('-','') }}/children",
"nodeCredentialType": "notionApi",
"sendBody": true,
"specifyBody": "json",
"jsonBody": {
"children": {{ $('Md to Notion').item.json.blocks.toJsonString() }}
}
}
執行流程後,即可在指定的 Notion 頁面中,看到完整保留 Markdown 結構的內容。