pd4d10/hashmd

如何编写插件修改frontmatter中的字段

ZiuChen opened this issue · 2 comments

非常感谢团队创造了这么好用的 Markdown 编辑器
我正在学习如何创建自己的 Plugin,然而我遇到了一些问题:

我希望能够通过工具栏的按钮,对 Markdown 文档中的 frontmatter 某些字段进行修改
但我查阅了remark的文档,也尝试了很多方法,但只能获取到frontmatter中的值,并没有找到能主动修改其中字段的方法

如果任何人能给出一些建议,我将十分感谢 ❤️
最后感谢开发团队的辛苦付出,这个库真的很好用!

Many thanks to the team for creating such an easy-to-use Markdown editor
I'm learning how to create my own Plugins, however I've run into some issues:

I want to be able to modify some fields of the frontmatter in the Markdown document through the buttons on the toolbar
But I checked the remark document and tried many methods, but I could only get the value in frontmatter, and I didn’t find a way to actively modify the fields

I would be very grateful if anyone could give some advice ❤️
Finally, thanks to the hard work of the development team, this library is really useful!

---
theme: github
---

# Some Title
import { dump } from 'js-yaml'
...
let currentTheme = 'xxx' // 当前主题
...
export function themePlugin(): BytemdPlugin {
  return {
    remark(processor) {
      // 读取 frontmatter 中的 theme 字段并设置主题样式
      return processor.use(() => (tree, file) => {
        // 由 frontmatter 插件解析 frontmatter
        const { theme } = file.frontmatter

        // 如果不一致 则修改 frontmatter 中的 theme 字段
        if (currentTheme !== theme) {
          // 将对象格式序列化为yaml 并重新赋值给yaml块的value
          // tree.children[0]: {"type":"yaml","value":"theme: github","position":{ ... }}
          tree.children[0].value = dump({
            ...file.frontmatter,
            theme: currentTheme
          })
         // 对 Markdown AST Tree 的修改并不会体现在编辑器中
        }
      })
    }
  }
}

Related Links:
remark-frontmatter
js-yaml

pd4d10 commented

对 Markdown 文档中的 frontmatter 某些字段进行修改

这个应该是可以的,可以参考 plugin-frontmatter 中的实现方式。

谢谢回复,frontmatter插件只是将文档中的frontmatter字段解析,并将相关信息保存在了vFile中
并没有暴露相关的接口用来对文档中已有的Frontmatter做修改

我通过了一个稍微hack一点的方法简单实现了一下这个功能,但是看上去也并不是那么优雅:

export function somePlugin(): BytemdPlugin {
  const frontmatterInfo = {
    highlight: '',
    position: {
      start: {
        line: 0,
        column: 0,
        offset: 0
      },
      end: {
        line: 0,
        column: 0,
        offset: 0
      }
    }
  }

  return {
    actions: [
      {
        title: '修改Frontmatter插件',
        icon: '',
        handler: {
          type: 'dropdown',
          actions: [
            {
              title: 'aaa',
              handler: {
                type: 'action',
                click: ({ editor }: BytemdEditorContext) => {
                  const v = editor.getValue()
                  const { start, end } = frontmatterInfo.position

                  // 用新的 frontmatter 替换旧的 frontmatter
                  const newFrontmatter = `---\nhighlight: ${frontmatterInfo.highlight}\n---\n`
                  editor.setValue(newFrontmatter + v)

                  editor.focus()
                }
              }
            }
          ]
        }
      }
    ],
    remark(processor) {
      // 由 frontmatter 插件解析 frontmatter
      // @ts-ignore
      return processor.use(() => (tree, file) => {
        // 获取 frontmatter 块的位置并保存到全局变量中
        const { start, end } = tree.children[0].position

        const { highlight } = file.frontmatter

        if (highlight) {
          frontmatterInfo.highlight = highlight
          frontmatterInfo.position = { start, end }
        }
      })
    }
  }
}