ProseMirror Markdown 模块

prosemirror

ProseMirror Markdown 模块

prosemirror-markdown 模块用于实现 markdown 与 prosemirror 之间的转换

  • 该模块提供了一个 schema 数据结构的约束对象,基于 CommonMark 所支持的 Markdown 语法创建对应的 ProseMirror 节点 nodes 和样式标记 marks 类型
  • 该模块导出了两个类
    • class MarkdownParser 用于构建 parser 解析器,(使用 markdown-it)解析 markdown 文档,转换为 prosemirror 文档(根节点)
      该模块已提供了该类的一个实例 defaultMarkdownParser 它基于 CommonMark 语法对 markdown 文档进行解析,转换为 ProseMirror 文档(采用该模块所提供的 schema 作为数据结构约束对象)
      ParseSpec

      该模块导出了一种 TypeScript interface ParseSpec 表示 markdown-it 所生成的各种 tokens 应该如何解析(转换为 ProseMirror 对应的节点或样式标记)

      它是实例化 new MarkdownParser(schema: Schema, tokenizer: any, tokens: Object<ParseSpec>) 时,第三个参数 tokens 所需需要满足的类型

    • class MarkdownSerializer 用于构建 serializer 序列化器,将 ProseMirror 文档序列化为 markdown 文档(字符串)
      该模块已提供了该类的一个实例 defaultMarkdownSerializer 它将(采用该模块所提供的 schema 作为数据结构约束对象)ProseMirror 文档序列化为 markdown 文档进行解析

官方有一个样例 Friendly Markdown 介绍了如何使用该模块,完整的源码可以查看相关的 Github 仓库

简化版本

根据官方示例编写了一个简化版本

其中关键是使用 defaultMarkdownParserdefaultMarkdownSerializer 方法实现 markdown 与 prosemirror 之间的转换,相关代码如下

ts
// setup markdown editor
const markdownEditor = document.querySelector("#markdownEditor") as HTMLTextAreaElement;
const initContent = markdownEditor.value;

markdownEditor.addEventListener('input', () => {
  // sync the change from markdown editor to prosemirror rich text editor
  const activeEditor = document.activeElement; // get the active/focus editor
  if(activeEditor && activeEditor.id === 'markdownEditor') {
    // 💡 parse the markdown text to prosemirror doc
    const content = defaultMarkdownParser.parse(markdownEditor.value);
    const newState = EditorState.create({
      doc: content,
      plugins: view.state.plugins
    })
    view.updateState(newState);
  }
})

// setup prosemirror editor
const state = EditorState.create({
  // parse preset content from (hidden) DOM in page
  doc: defaultMarkdownParser.parse(initContent),
  // add other augment features for editor
  plugins: exampleSetup({schema})
});

const editorContainer = document.querySelector("#prosemirrorEditorContainer");

const view = new EditorView(editorContainer, {
  state: state,
  dispatchTransaction(tr) {
    const newState = view.state.apply(tr);
    // sync the change from prosemirror rich text editor to markdown editor
    const activeEditor = document.activeElement; // get the active/focus editor
    if(activeEditor && activeEditor.id !== 'markdownEditor') {
      console.log('update markdown');
      // 💡 serializer the prosemirror doc to markdown text
      const content = defaultMarkdownSerializer.serialize(newState.doc);
      console.log(content);

      markdownEditor.value = content;
    }
    view.updateState(newState);
  }
});

Copyright © 2025 Ben

Theme BlogiNote

Icons from Icônes