模块转换

为什么要自定义转换?

Notion Flow 转换 Notion 内容的格式是按照 Github 的 Markdown 格式,但是 Notion 中的模块有些无法转换成标准 Markdown 格式,这里有两个典型场景:

  • Notion Bookmark 在标准 Markdown 中无对应格式,Notion Flow 默认转成链接格式。
  • Notion 中的图片中的 Caption,想要在博客中将其设置为图片的图片描述,Notion Flow 默认忽略该属性。

支持的模块

也许你不想要我给你预设好的 Notion 模块转 Markdown 格式,因此,本插件支持你自己写如何转换 Notion 模块,除了下面所述的三种模块不支持转换外,其他的全部模块均支持,有些模块为了方便我还添加了额外的属性(见下面)。

不支持的模块处理

对于不支持的模块,如 embed、toggle、template 等,你需要自己按照下面描述的要求自行书写模块转换函数,如果一个模块不是标准 Markdown 模块,你又没有自己写对应的模块转换函数,那么该模块将会被忽略。

标准 Markdown 不能转换的模块

列表类型,由于其在 Notion 中可以嵌套,因此其内的子元素是通过接口递归获取的,相对其他模块而言比较麻烦,而且它的 Markdown 语法比较统一,因此不支持自定义转换,其中包括:

  • to_do
  • numbered_list_item
  • bulleted_list_item

额外添加的模块属性

各个模块的函数,除了 Notion 给的模块默认属性 外,我还添加了额外的属性,各个模块额外属性分别如下(部分字段可能覆盖 Notion 模块字段, 如无特殊说明均为 string):

  • paragraph
    • text: 文本内容,不带格式
  • bookmark
    • title: 标题
    • desc: 描述
    • img: bookmark 左侧的小图片(地址是 bookmark 引用链接的 favicon,可能由于同源策略无法正确显示)
  • image
    • url: 图片地址(上传到 OSS 及添加 CDN 地址后的最终地址)
    • caption: 图片描述
        // 内部处理为
        `![${block.caption}](${block.url})`
      
  • heading_1/2/3
    • text: 文本内容,不带格式
  • table
    • rows: 表格的 row 子元素列表,里面包含了 cells 字段,具体参看 Notion API 文档,内部对此的默认处理是:
      block.rows.reduce((prev: string, curr: string, index: number) => {
        const cells = curr[curr.type].cells;
        let divider = '';
        const cellsString = cells.map((cell: any, key: number) => {
            // Note: cell is rich_text, here transform to string
            const str = `| ${_inline(cell)} `;
            if (key === cells.length - 1) {
                divider += `| ---------- |\n`;
                return `${str}|`
            }
            divider += `| ---------- `;
            return str;
        }).join('');
        return prev += `${cellsString}\n${index === 0 ? divider : ''}`;
      }, '')
      
  • quote
    • text: 文本内容,不带格式
    • color: quote 左侧的边框颜色,从 Notion 官网窃得
  • callout
    • icon: callout 左侧的图标
    • text: 文本内容,不带格式
    • color: callout 字体颜色
    • bgColor: callout 背景颜色
  • divider
    • 无额外属性
  • video(包括文件类型和 Youtube、Bilibili 外部链接)
    • block.type === 'file'
      • url: 上传到 OSS 后同时加上 CDN 地址的最终地址
      • caption: 视频描述
      • suffix: 视频后缀
    • block.type === 'external'
      • yid: YouTube 的视频 id
      • bid: Bilibili 的视频 id
      • caption: 视频的描述
      • url: 外部视频地址
  • code
    • text: 代码文本内容,不带格式
  • equation
    • text: 公式文本内容,不带格式

如何使用自定义模块转换?

首先在插件设置中打开发布功能(废话),然后到「设置 → 高级 · 模块转换插件」的双栏编辑器中书写对应代码即可(自 0.4.5 起,模块转换从侧边栏移到了设置页):左栏写转换函数,右栏选择区块类型查看「输入 block → 输出字符串」,点「运行测试」可实时验证,覆盖 13 种可自定义区块类型。

Image

书写格式要求

提示

如果书写的函数不符合要求,将使用默认的模块转换逻辑。

配置书写非常简单,只要满足以下条件即可:

  1. 配置是一个对象,对象的键为模块名,值 必须为带有函数名 的函数,使用匿名函数将会报错,如

    {
      bookmark: function (block) {} // Error!
    }
    
  2. 配置对象首行不能为空。

  3. 配置对象的键对应的函数值,参数即为上面所述的模块(加上我给的额外属性),名字为 block

  4. 函数的返回值即为最终的模块转换成 Markdown 的值。

配置举例:

{ // <-- 首行不能为空!
  bookmark: function any_name_you_want(block) {
    return `[${block.title}](${block.url})`;
  },
  image: function any_name_you_want(block) {
    return `![${block.caption}](${block.url})`;
  }
}