news 2026/10/15 2:06:22

notion-x-to-md 实战:Notion 待办清单(to_do 块)到 GitHub 风格 Markdown 的转换原理与用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
notion-x-to-md 实战:Notion 待办清单(to_do 块)到 GitHub 风格 Markdown 的转换原理与用法
  • UI组件
  • 前端

【免费下载链接】react-notion-x

Fast and accurate React renderer for Notion. TS batteries included. ⚡️

项目地址:https://gitcode.com/gh_mirrors/re/react-notion-x
点击查看免费下载

导读

在 react-notion-x 生态中,notion-x-to-md 负责把 Notion 页面转换为 GitHub Flavored Markdown(GFM),是让 Notion 内容进入 LLM 上下文、构建知识库或静态博客的常用桥梁。本文以仓库中的 Checklists 转换示例 为线索,完整讲解 Notion 待办清单(to_do块)如何被渲染为- [x]/- [ ]任务列表,并深入源码剖析其判定逻辑、类型约束与快照测试,最后给出可直接运行的调用与 CLI 方案。读完你将掌握:待办清单块的转换规则、notionPageToMarkdown的完整调用链,以及如何用一条命令把任意公开 Notion 页面转成 Markdown。

一、示例文档还原:to_do块的转换输出

仓库中的 38fa73d49b8f40aab1f3f8c82332e518.md 是一个专门用于验证待办清单转换能力的示例页面,其转换结果如下:

# Checklists > This block type is called `to_do` - [x] Pretty URLs - [x] Custom domains - [x] Google Fonts - [x] Page title/description for SEO - [x] Custom scripts - [x] A setup wizard to customize the script (instead of having to change the raw code) - [ ] Stop random pages from showing up under custom domain - [ ] Hide the What's New banner

这个输出揭示了三条关键事实:

  1. 页面标题被渲染为 H1:# Checklists来自页面的 title 属性;
  2. 引用块被渲染为 GFM 引用:> This block type is called to_do对应 Notion 中的 quote 块;
  3. 每个待办项都被渲染为 GFM 任务列表项:已勾选输出- [x],未勾选输出- [ ]。

该页面在 readme.md 的示例索引表 中被标记为Checklists / Supported ✅,页面 ID 为38fa73d49b8f40aab1f3f8c82332e518,与当前文档文件名一致。

二、源码级剖析:to_do块如何变成- [x]

2.1 渲染入口:renderBlock的to_do分支

notion-x-to-md 的核心渲染函数是 src/block.ts 中的renderBlock,它接收(blockId, recordMap, level),先从recordMap.block中取出原始块数据,再根据块的type字段分发到对应分支。待办清单的分支位于 src/block.ts#L98-L102:

case 'to_do': { const checked = (block as any).properties?.checked?.[0]?.[0] === 'Yes' const checkbox = checked ? '- [x]' : '- [ ]' return `${checkbox} ${getTitle(block, recordMap)}` }

这段实现非常简洁,却包含了完整的状态判定逻辑:

  • 取勾选状态:block.properties?.checked是一个二维数组,[0][0]取到的是单元格中的第一个 token。当该值严格等于字符串'Yes'时判定为已勾选;
  • 映射为 GFM 语法:已勾选输出- [x],未勾选输出- [ ],这是 GitHub Flavored Markdown 任务列表(task list)的标准写法;
  • 拼接标题文本:getTitle在 src/block.ts#L398-L400 中实现,它调用decorationsToMarkdown(block.properties?.title ?? [], recordMap),将标题的富文本 decoration 还原为 Markdown 文本(粗体、斜体、链接、@提及等都会被正确还原)。

2.2 类型约束:TodoBlock的数据结构

to_do块的类型定义位于 packages/notion-types/src/block.ts#L244-L251:

// TODO export interface TodoBlock extends BaseTextBlock { type: 'to_do' properties: { title: Decoration[] checked: (['Yes'] | ['No'])[] } }

可以看到:

  • BlockType联合类型中注册了'to_do'(见 packages/notion-types/src/block.ts#L15);
  • checked属性被严格建模为(['Yes'] | ['No'])[],这与渲染端=== 'Yes'的判定完全吻合;
  • 每个待办项都拥有独立的title(Decoration 数组)与checked状态,因此同一个清单里已勾选与未勾选项可以混合出现,正如示例文档展示的 6 项[x]+ 2 项[ ]。

2.3 与 React 渲染端的对照验证

同一块类型在 react-notion-x 的 React 渲染端 src/block.tsx#L800-L821 中也有对应实现:

case 'to_do': { const isChecked = block.properties?.checked?.[0]?.[0] === 'Yes' return ( <div className={cs('notion-to-do', blockId)}> <div className='notion-to-do-item'> <components.Checkbox blockId={blockId} isChecked={isChecked} /> ...

两个渲染端采用了完全相同的判定表达式checked?.[0]?.[0] === 'Yes',可以确认这是 react-notion-x 生态中处理待办状态的事实标准。差别只在于输出形态:React 端渲染为带勾选框的 DOM(样式见 packages/react-notion-x/src/styles.css#L2199 的notion-to-do-checked规则),Markdown 端则映射为- [x]/- [ ]。

三、调用链与用法:如何复现这份输出

3.1 编程方式调用

示例输出的完整生成链路是:NotionAPI.getPage拉取页面 →notionPageToMarkdown递归渲染所有块。notionPageToMarkdown定义在 src/notion-page-to-markdown.ts#L17-L25:

export async function notionPageToMarkdown( recordMap: ExtendedRecordMap ): Promise<string> { const rootBlockId = Object.keys(recordMap.block)[0] if (!rootBlockId) return '' const markdown = await renderBlock(rootBlockId, recordMap) return markdown.trim() }

函数以recordMap.block的第一个 key 作为根页面块,调用renderBlock递归渲染整棵块树,最后trim()去除首尾空白。值得注意的是它必须为async——因为渲染过程中可能拉取远程资源(如 tweet 嵌入,见 tweet 分支)。子块通过renderBlockChildren以p-map并发(concurrency: 4)渲染,见 src/block.ts#L379-L396。

完整的可运行示例(摘自 packages/notion-x-to-md/readme.md#L27-L40):

import { NotionAPI } from 'notion-client' import { notionPageToMarkdown } from 'notion-x-to-md' const api = new NotionAPI() // fetch a notion page's content const page = await api.getPage('38fa73d49b8f40aab1f3f8c82332e518') // convert the page to a markdown string const markdown = await notionPageToMarkdown(page) console.log(markdown)

要点:

  • 无需 API Key:不要求创建 Notion 官方 API 集成,只要页面是公开可访问的即可(见 readme.md 的 Notes);
  • 输出为 GFM:notion-x-to-md明确输出 GitHub Flavored Markdown,这对 LLM 的解析尤为友好;
  • Node 版本要求:engines.node >= 18(见 package.json)。

3.2 CLI 一行命令

除编程调用外,包还内置了 CLI(bin字段指向 src/cli.ts,由 commander 实现)。直接用npx运行即可:

npx -y notion-x-to-md https://notion.so/38fa73d49b8f40aab1f3f8c82332e518

或直接传页面 ID:

npx -y notion-x-to-md 38fa73d49b8f40aab1f3f8c82332e518

CLI 的完整用法(摘自 readme.md):

Usage: notion-x-to-md [options] <page> Converts a Notion page to Markdown Arguments: page Notion page ID or URL (must be publicly accessible) Options: -h, --help display help for command

<page>参数既支持完整 URL,也支持不带连字符的 32 位页面 ID,由NotionAPI.getPage统一解析。

3.3 安装方式

npm install notion-x-to-md

该包以notion-client、notion-types、notion-utils为 workspace 依赖(见 package.json),构建工具为 tsdown,测试使用 vitest + typecheck。

四、测试与快照:示例文档是持续集成的产物

examples/38fa73d49b8f40aab1f3f8c82332e518.md并非手写文档,而是测试管线自动生成的产物。src/notion-page-to-markdown.test.ts 中的测试会:

  1. 用new NotionAPI().getPage(id)拉取真实公开页面;
  2. 调用notionPageToMarkdown转换;
  3. 断言输出非空、首尾无多余空白,并与快照比对。

测试文件中的writeExamples开关(test 文件 L32-L49)在开启时会把转换结果写入examples/<pageId>.md,因此该目录下的每个.md文件都可以视为一个"渲染正确性快照"。

对应的快照位于 src/snapshots/index.test.ts.snap#L469-L483:

exports[`notionPageToMarkdown success 38fa73d49b8f40aab1f3f8c82332e518 1`] = ` "# Checklists > This block type is called \`to_do\` - [x] Pretty URLs ...

快照内容与 examples 目录 完全一致,从测试角度再次证实:只要 Notion 页面结构不变,to_do块的 Markdown 输出就是稳定、可预期的。

五、相关设计细节与注意事项

5.1 状态语义:'Yes'字符串的来由

Notion 私有 API 中,勾选框类属性的原始值就是字符串'Yes'/'No'(这一点在集合(database)属性渲染中同样成立,见 src/property.ts#L35-L38 中 checkbox 属性渲染为✓/✗的逻辑)。因此转换器直接与原始数据比对,不经过任何布尔转换,判定唯一且无歧义。

5.2 待办项的富文本

to_do分支中的getTitle复用了通用标题渲染逻辑,因此待办项文本内可以包含粗体、斜体、删除线、行内代码、链接、页面引用、@ 提及、日期等所有 text.ts 支持的 decoration 类型,它们都会被还原为对应 Markdown 语法后再拼接到- [x]/- [ ]之后。

5.3 适用范围与限制

  • 仅支持公开可访问的 Notion 页面;
  • Notion 托管的临时图片 URL 在一段时间后会失效(与官方 Notion 应用行为一致),如需永久链接可对getPage返回的ExtendedRecordMap做后处理,将临时图片上传至永久 URL 并保存 block ID 到 URL 的映射(见 readme.md 的 Notes);
  • 集合(database)会被统一渲染为 Markdown 表格,所有视图类型一视同仁。

六、小结

围绕 Checklists 示例 这一最小但完整的样例,可以梳理出一条清晰的转换链路:

  • 数据来源:NotionAPI.getPage拉取ExtendedRecordMap,其中to_do块携带title与checked('Yes'/'No')属性;
  • 判定规则:checked?.[0]?.[0] === 'Yes'(block.ts#L99 与 notion-types block.ts#L249 双重印证);
  • 输出形态:- [x] 文本/- [ ] 文本,即标准 GFM 任务列表,天然被 GitHub 与主流 LLM 良好解析;
  • 可验证性:快照测试保证了输出的确定性,examples 目录即测试产物。

对于任何需要"把 Notion 待办清单接入 AI 工作流"的开发者,npx -y notion-x-to-md <页面ID>已经是一条足够可靠的最小路径;而当你需要把勾选状态、富文本样式或自定义映射融入业务逻辑时,renderBlock的to_do分支则是理想的改造锚点。

  • UI组件
  • 前端

【免费下载链接】react-notion-x

Fast and accurate React renderer for Notion. TS batteries included. ⚡️

项目地址:https://gitcode.com/gh_mirrors/re/react-notion-x
点击查看免费下载
上一篇:FreeRTOS OTA 回滚机制:3 步看懂升级失败如何恢复
下一篇:终极指南:解决ESP32 Arduino开发中NetworkClientSecure库SSL编译失败的完整方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 2:05:53

双11业务风控与反欺诈实战总结:构筑全链路抗黑产纵深防御长城

大促前夕的攻防对抗从来都不是偶发的试探&#xff0c;而是一场组织严密、分工明确的立体消耗战。黑灰产依托分布式代理池、群控设备农场、自研逆向破解框架以及高度自动化的脚本工具&#xff0c;在毫秒之间向核心结算、领券、加购与详情接口发起海量伪造请求。如果防御体系仅仅…

作者头像 李华
网站建设 2026/10/15 2:04:35

嵌套 ESXi 里的 VM 拿不到 DHCP?一篇讲透 vSwitch 混杂模式 + 实战配置

本文适用场景:vSphere 实验室 / NSX 试验环境 / vSphere with Kubernetes / VCF 演示 涉及版本:物理 ESXi 7.0/8.0/9.0,嵌套 ESXi 6.7/7.0/8.0 阅读时长:约 7 分钟一、排错日记:今天又踩了一遍这个坑今天下午在搭 vSphere with Kubernetes 实验环境,在物理 ESXi 8.0 上装了一台…

作者头像 李华
网站建设 2026/10/15 2:03:07

MFC多视频界面空壳程序设计与稳定性验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 2:02:38

SpringBoot+Vue旅游小程序开发与AI技术融合实践

1. 项目概述这个毕业设计项目是一个结合了前后端技术的旅游攻略小程序&#xff0c;采用SpringBoot作为后端框架&#xff0c;Vue.js作为前端框架&#xff0c;并融入了AI技术来增强用户体验。这类项目在当前旅游信息化浪潮中具有典型意义——随着移动互联网的普及&#xff0c;传统…

作者头像 李华
网站建设 2026/10/15 2:02:15

2026-10-15:重新排列字符串以避免字符对。用go语言,现有一个由小写字母组成的字符串 s,以及两个互不相同的小写字母 x、y。请把 s 中所有字符重新排序,得到另一个字符串 t。要求 t 中每

2026-10-15&#xff1a;重新排列字符串以避免字符对。用go语言&#xff0c;现有一个由小写字母组成的字符串 s&#xff0c;以及两个互不相同的小写字母 x、y。请把 s 中所有字符重新排序&#xff0c;得到另一个字符串 t。要求 t 中每种字符的数量和 s 完全一样&#xff1b;并且…

作者头像 李华
网站建设 2026/10/15 1:59:36

激光焊缝跟踪技术在波纹管制造中的应用

波纹管作为一种柔性压力元件&#xff0c;广泛应用于石油化工、航空航天、汽车制造等领域。其核心功能在于补偿管道热胀冷缩、吸收机械振动&#xff0c;这对焊接接头的密封性、耐疲劳性提出了极高要求。传统焊接方式&#xff08;如TIG焊&#xff09;存在热输入量大、变形控制难等…

作者头像 李华