Skip to content

Instantly share code, notes, and snippets.

@chand1012
Created February 22, 2025 02:40
Show Gist options
  • Save chand1012/708eed96ae2a08bcb22011b85b5043f2 to your computer and use it in GitHub Desktop.
Save chand1012/708eed96ae2a08bcb22011b85b5043f2 to your computer and use it in GitHub Desktop.
Notion Workflow to Convert a page content to Markdown.
{
"name": "Get Notion Page as Markdown",
"nodes": [
{
"parameters": {
"workflowInputs": {
"values": [
{
"name": "id"
}
]
}
},
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1.1,
"position": [
0,
0
],
"id": "923b21e3-4cc6-4c1d-891a-741294a15a22",
"name": "When Executed by Another Workflow"
},
{
"parameters": {
"resource": "block",
"operation": "getAll",
"blockId": {
"__rl": true,
"value": "={{ $json.id }}",
"mode": "id"
},
"returnAll": true
},
"type": "n8n-nodes-base.notion",
"typeVersion": 2.2,
"position": [
220,
0
],
"id": "f3492a23-7afb-4e8b-a236-cb580ac36af5",
"name": "Notion",
"credentials": {
"notionApi": {
"id": "AU2OswMIKpgpSkxd",
"name": "TSL Notion"
}
}
},
{
"parameters": {
"jsCode": "/* Helper function to extract plain text from a rich_text array */\nfunction parseRichText(richTextArray) {\n if (!richTextArray || !Array.isArray(richTextArray)) return \"\";\n return richTextArray.map(rt => rt.plain_text).join(\"\");\n}\n\n/* Recursively convert a list of notion blocks into a Markdown string */\nfunction convertNotionBlocksToMarkdown(blocks, indentLevel = 0) {\n const indent = \" \".repeat(indentLevel); // two spaces per indent level\n let md = \"\";\n blocks.forEach(block => {\n let text = \"\";\n switch (block.type) {\n case \"paragraph\":\n text = block.paragraph?.rich_text ? parseRichText(block.paragraph.rich_text) : block.content;\n break;\n case \"heading_1\":\n text = \"# \" + (block.heading_1?.rich_text ? parseRichText(block.heading_1.rich_text) : block.content);\n break;\n case \"heading_2\":\n text = \"## \" + (block.heading_2?.rich_text ? parseRichText(block.heading_2.rich_text) : block.content);\n break;\n case \"heading_3\":\n text = \"### \" + (block.heading_3?.rich_text ? parseRichText(block.heading_3.rich_text) : block.content);\n break;\n case \"bulleted_list_item\":\n text = \"- \" + (block.bulleted_list_item?.rich_text ? parseRichText(block.bulleted_list_item.rich_text) : block.content);\n break;\n case \"numbered_list_item\":\n text = \"1. \" + (block.numbered_list_item?.rich_text ? parseRichText(block.numbered_list_item.rich_text) : block.content);\n break;\n case \"to_do\":\n text = \"- [\" + (block.to_do?.checked ? \"x\" : \" \") + \"] \" + (block.to_do?.rich_text ? parseRichText(block.to_do.rich_text) : block.content);\n break;\n case \"quote\":\n text = \"> \" + (block.quote?.rich_text ? parseRichText(block.quote.rich_text) : block.content);\n break;\n case \"code\": {\n const codeLang = block.code?.language || \"\";\n const codeText = block.code?.rich_text ? parseRichText(block.code.rich_text) : block.content;\n text = \"```\" + codeLang + \"\\n\" + codeText + \"\\n```\";\n break;\n }\n case \"divider\":\n text = \"---\";\n break;\n case \"callout\": {\n const icon = block.callout?.icon?.emoji ? `${block.callout.icon.emoji} ` : \"\";\n text = \"> \" + icon + (block.callout?.rich_text ? parseRichText(block.callout.rich_text) : block.content);\n break;\n }\n case \"image\": {\n const image = block.image;\n const url = image?.type === \"external\" ? image.external?.url : image.file?.url;\n const caption = image?.caption ? parseRichText(image.caption) : \"\";\n text = url ? `![${caption}](${url})` : \"\";\n break;\n }\n default:\n text = block[block.type]?.rich_text ? parseRichText(block[block.type].rich_text) : block.content;\n }\n if (text !== \"\") {\n md += indent + text + \"\\n\\n\";\n }\n if (block.has_children && Array.isArray(block.children) && block.children.length > 0) {\n md += convertNotionBlocksToMarkdown(block.children, indentLevel + 1);\n }\n });\n return md.trim();\n}\n\nfor (const item of $input.all()) {\n item.json.markdown = convertNotionBlocksToMarkdown([item.json]);\n}\n\nreturn $input.all();"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
0
],
"id": "e1677627-356c-4051-bf56-802fd45c62bd",
"name": "Code"
},
{
"parameters": {
"fieldsToAggregate": {
"fieldToAggregate": [
{
"fieldToAggregate": "markdown"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.aggregate",
"typeVersion": 1,
"position": [
660,
0
],
"id": "4231c3ca-381f-4429-b602-6e7fd42f2efd",
"name": "Aggregate"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "335dc705-e651-43c1-b34d-2e47f899c387",
"name": "content",
"value": "={{ $json.markdown.join('\\n\\n') }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
880,
0
],
"id": "1cd8b8ad-d6d3-4d38-97c4-8f6757c02b0c",
"name": "Edit Fields"
}
],
"pinData": {
"When Executed by Another Workflow": [
{
"json": {
"id": "1a2272d8-2348-8021-87fa-f6b0536b138d"
}
}
]
},
"connections": {
"When Executed by Another Workflow": {
"main": [
[
{
"node": "Notion",
"type": "main",
"index": 0
}
]
]
},
"Notion": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "Aggregate",
"type": "main",
"index": 0
}
]
]
},
"Aggregate": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "4abfee5f-c08a-4c15-a9e9-b8a0fe84b2cf",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "264d698b5e64261284d507dd7b12172313952935a60b637601e363e5fd657924"
},
"id": "bLipx1fs4ZCzjBKg",
"tags": [
{
"createdAt": "2024-09-23T20:07:28.009Z",
"updatedAt": "2024-09-23T20:07:28.009Z",
"id": "7uLdfBNMEKOs8GIy",
"name": "Chandler"
},
{
"name": "Notion",
"id": "trTFWJS3aCaKvWyG",
"createdAt": "2025-02-22T01:33:50.022Z",
"updatedAt": "2025-02-22T01:33:50.022Z"
},
{
"name": "Utilities",
"id": "vrfgmsvbsUWYgNx9",
"createdAt": "2025-02-22T01:33:54.259Z",
"updatedAt": "2025-02-22T01:33:54.259Z"
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment