Martian: Markdown 到 Notion 解析器
将 Markdown 和 GitHub 风格的 Markdown 转换为 Notion API 块和富文本。
Martian 是一个 Markdown 解析器,可以将任何 Markdown 内容转换为 Notion API 块或富文本对象。它使用 unified 创建 Markdown 抽象语法树(AST),然后将 AST 转换为 Notion 对象。
旨在使 Notion SDK 和 API 的使用更加简便。适用于 Notion API 1.0 版本。
支持的 Markdown 元素
- 所有内联元素(斜体、粗体、删除线、内联代码、超链接、方程式)
- 列表(有序、无序、复选框)- 支持任意深度
- 所有标题(3级及以上的标题都被视为3级标题)
- 代码块,支持语言高亮
- 引用块
- 表格
- 方程式
- 图片
- 内联图片会从段落中提取并在后面添加(因为 Notion 不支持内联图片)
- 图片 URL 会进行验证,如果不符合 Notion 外部规范,将以文本形式插入,供您手动修复
使用方法
基本用法:
该包导出两个函数,您可以按以下方式导入:
// JS
const {markdownToBlocks, markdownToRichText} = require('@tryfabric/martian');
// TS
import {markdownToBlocks, markdownToRichText} from '@tryfabric/martian';
以下是两个函数的使用示例:
markdownToRichText(`**Hello _world_**`);
结果
[ { "type": "text", "annotations": { "bold": true, "strikethrough": false, "underline": false, "italic": false, "code": false, "color": "default" }, "text": { "content": "Hello " } }, { "type": "text", "annotations": { "bold": true, "strikethrough": false, "underline": false, "italic": true, "code": false, "color": "default" }, "text": { "content": "world" } } ]
markdownToBlocks(`
hello _world_
***
## heading2
* [x] todo
`);
结果
[ { "object": "block", "type": "paragraph", "paragraph": { "rich_text": [ { "type": "text", "annotations": { "bold": false, "strikethrough": false, "underline": false, "italic": false, "code": false, "color": "default" }, "text": { "content": "你好 " } }, { "type": "text", "annotations": { "bold": false, "strikethrough": false, "underline": false, "italic": true, "code": false, "color": "default" }, "text": { "content": "世界" } } ] } }, { "object": "block", "type": "heading_2", "heading_2": { "rich_text": [ { "type": "text", "annotations": { "bold": false, "strikethrough": false, "underline": false, "italic": false, "code": false, "color": "default" }, "text": { "content": "二级标题" } } ] } }, { "object": "block", "type": "to_do", "to_do": { "rich_text": [ { "type": "text", "annotations": { "bold": false, "strikethrough": false, "underline": false, "italic": false, "code": false, "color": "default" }, "text": { "content": "待办事项" } } ], "checked": true } } ]
处理Notion的限制
有时,Markdown输入可能会导致输出被Notion API拒绝:以下是一些处理这种情况的选项。
项目超出子项或字符限制
默认情况下,该包会尝试通过将内容重新分配到多个块来解决此类问题:当无法做到这一点时,martian
会截断输出以避免您的请求导致错误。
如果您想禁用这种行为,可以使用以下选项:
const options = {
notionLimits: {
truncate: false,
},
};
markdownToBlocks('输入', options);
markdownToRichText('输入', options);
手动处理与Notion限制相关的错误
您可以为结果项超出Notion限制时设置回调函数。请注意,无论最终输出是否会被截断,此函数都会被调用。
const options = {
notionLimits: {
// truncate: true, // 默认值
onError: (err: Error) => {
// 发生了某些情况!
console.error(err);
},
},
};
markdownToBlocks('输入', options);
markdownToRichText('输入', options);
处理图片
如果图片的URL无效,Notion API将拒绝整个请求:martian
通过将无效链接的图片转换为文本来防止这个问题,这样请求就能成功,您以后可以修复链接。
如果您想禁用这种行为,可以使用以下选项:
const options = {
strictImageUrls: false,
};
默认行为:
markdownToBlocks('![](https://raw.githubusercontent.com/tryfabric/martian/master/InvalidURL)');
结果
[ { "object": "block", "type": "paragraph", "paragraph": { "rich_text": [ { "type": "text", "annotations": { "bold": false, "strikethrough": false, "underline": false, "italic": false, "code": false, "color": "default" }, "text": { "content": "InvalidURL" } } ] } } ]
禁用strictImageUrls
:
markdownToBlocks('![](https://raw.githubusercontent.com/tryfabric/martian/master/InvalidURL)', {
strictImageUrls: false,
});
结果
[ { "object": "block", "type": "image", "image": { "type": "external", "external": { "url": "无效URL" } } } ]
解析富文本时的非内联元素
默认情况下,如果提供给markdownToRichText
的文本会产生一个或多个非内联元素,该包会忽略这些元素,只解析段落。
你可以通过将nonInline
选项设置为'throw'
来使包在检测到非内联元素时抛出错误。
默认行为:
markdownToRichText('# 标题\nAbc', {
// nonInline: 'ignore', // 默认
});
结果
[ { type: 'text', annotations: { bold: false, strikethrough: false, underline: false, italic: false, code: false, color: 'default' }, text: { content: 'Abc', link: undefined } } ]
抛出错误:
markdownToRichText('# 标题\nAbc', {
nonInline: 'throw',
});
结果
错误:不支持的markdown元素:{"type":"heading","depth":1,"children":[{"type":"text","value":"标题","position":{"start":{"line":1,"column":3, "offset":2},"end":{"line":1,"column":9,"offset":8}}}],"position":{"start":{"line":1,"column":1,"offset":0},"end":{"line":1,"column":9,"offset":8}}}
由Fabric背后的团队用💙构建。