{"version":3,"file":"index.mjs","sources":["../src/module/plugin.ts","../src/module/index.ts"],"sourcesContent":["/**\n * @description plugin\n * @author wangfupeng\n */\n\nimport {\n  DomEditor,\n  IDomEditor,\n  SlateEditor,\n  SlateElement,\n  SlateRange,\n  SlateTransforms,\n} from '@wangeditor-next/editor'\n\n// 空格对应的 md 关键字\nconst KEY_TO_TYPE_FOR_SPACE: { [key: string]: string } = {\n  '*': 'list-item',\n  '-': 'list-item',\n  '+': 'list-item',\n  '>': 'blockquote',\n  '#': 'header1',\n  '##': 'header2',\n  '###': 'header3',\n  '####': 'header4',\n  '#####': 'header5',\n}\n\n// 回车对应的 md 关键字\nconst KEY_TO_TYPE_FOR_ENTER: { [key: string]: string } = {\n  '---': 'divider',\n  '----': 'divider',\n  '-----': 'divider',\n  '------': 'divider',\n\n  // PS： '```' 转换 pre/code 比较麻烦，单独写\n}\n\n/**\n * 获取 md 关键字和关键字的 range\n * @param editor editor\n */\nfunction getBeforeText(editor: IDomEditor): { beforeText: string; range: SlateRange | null } {\n  const { selection } = editor\n\n  if (selection == null) {\n    return { beforeText: '', range: null }\n  }\n  const { anchor } = selection\n  // 找到当前文本上面的 block 元素，如 header1 paragraph\n  const block = SlateEditor.above(editor, {\n    match: n => SlateElement.isElement(n) && SlateEditor.isBlock(editor, n),\n  })\n\n  if (block == null) {\n    return { beforeText: '', range: null }\n  }\n  const blockPath = block[1]\n  const blockStart = SlateEditor.start(editor, blockPath) // block 元素的起始位置，就第一个文字的位置\n  const range = { anchor, focus: blockStart }\n  const beforeText = SlateEditor.string(editor, range) || ''\n\n  return { beforeText, range }\n}\n\nfunction withMarkdown<T extends IDomEditor>(editor: T) {\n  const { insertBreak, insertText } = editor\n  const newEditor = editor\n\n  const isComposing = () => {\n    try {\n      return DomEditor.getTextarea(editor).isComposing\n    } catch {\n      return false\n    }\n  }\n\n  // 输入空格时，尝试转换 markdown\n  newEditor.insertText = text => {\n    const { selection } = editor\n\n    // Align with Slate/Plate autoformat behavior: never run markdown trigger\n    // while IME composition is active.\n    if (isComposing()) {\n      return insertText(text)\n    }\n    if (selection == null) {\n      return insertText(text)\n    }\n    if (SlateRange.isExpanded(selection)) {\n      return insertText(text)\n    }\n    if (DomEditor.getSelectedNodeByType(editor, 'paragraph') == null) {\n      return insertText(text)\n    } // 必须在 paragraph 内\n    if (text !== ' ') {\n      return insertText(text)\n    } // 必须是输入空格\n\n    // 获取空格前面的文字\n    const { beforeText, range } = getBeforeText(editor)\n\n    if (!beforeText || !range) {\n      return insertText(text)\n    }\n\n    // 根据 md 关键字，找到要转换 elem 的 type\n    const type = KEY_TO_TYPE_FOR_SPACE[beforeText]\n\n    if (!type) {\n      return insertText(text)\n    }\n\n    // 转换为 type elem\n    SlateTransforms.select(editor, range)\n    SlateTransforms.delete(editor)\n    const props: Partial<SlateElement> = {\n      type,\n    }\n\n    SlateTransforms.setNodes<SlateElement>(editor, props, {\n      match: n => SlateElement.isElement(n) && SlateEditor.isBlock(editor, n),\n    })\n\n    // 如果是 list-item ，则包裹一层 bulleted-list\n    if (type === 'list-item') {\n      const listElem = {\n        type: 'bulleted-list',\n        children: [],\n      }\n\n      SlateTransforms.wrapNodes(editor, listElem, {\n        match: n => DomEditor.getNodeType(n) === 'list-item',\n      })\n    }\n  }\n\n  // 换行时，尝试转换 markdown\n  newEditor.insertBreak = () => {\n    const { selection } = editor\n\n    if (isComposing()) {\n      return insertBreak()\n    }\n    if (selection == null) {\n      return insertBreak()\n    }\n    if (SlateRange.isExpanded(selection)) {\n      return insertBreak()\n    }\n    if (DomEditor.getSelectedNodeByType(editor, 'paragraph') == null) {\n      return insertBreak()\n    } // 必须在 paragraph 内\n\n    const { beforeText, range } = getBeforeText(editor) // 获取前面的文字\n\n    if (!beforeText || !range) {\n      return insertBreak()\n    }\n\n    // 单独处理 pre/code\n    if (beforeText.indexOf('```') === 0) {\n      let lang = beforeText.slice(3).toLowerCase().trim() // 获取 ```js 中的语言，如 js\n\n      if (lang === 'js') {\n        lang = 'javascript'\n      }\n      if (lang === 'ts') {\n        lang = 'typescript'\n      }\n      if (lang === 'md') {\n        lang = 'markdown'\n      }\n      if (lang === 'py') {\n        lang = 'python'\n      }\n      if (lang === 'vb') {\n        lang = 'visual-basic'\n      }\n      if (lang === 'c#') {\n        lang = 'csharp'\n      }\n\n      const codeLangs = editor.getConfig().MENU_CONF?.codeSelectLang?.codeLangs || []\n\n      if (lang) {\n        // lang 有可能不在支持范围之内\n        const isValid = codeLangs.some((item: any) => item.value === lang)\n\n        if (!isValid) {\n          return insertBreak()\n        }\n      }\n\n      // 删除 ```js 文字\n      SlateTransforms.select(editor, range)\n      SlateTransforms.delete(editor)\n\n      // 插入 pre/code elem\n      const preElem = {\n        type: 'pre',\n        children: [\n          {\n            type: 'code',\n            language: lang,\n            children: [{ text: '' }],\n          },\n        ],\n      }\n\n      SlateTransforms.insertNodes(editor, preElem)\n      return\n    }\n\n    // 根据 md 关键字，找到要转换 elem 的 type\n    const type = KEY_TO_TYPE_FOR_ENTER[beforeText]\n\n    if (!type) {\n      return insertBreak()\n    }\n\n    // 转换为 type elem\n    SlateTransforms.select(editor, range)\n    SlateTransforms.delete(editor)\n    const props: Partial<SlateElement> = {\n      type,\n    }\n\n    SlateTransforms.setNodes<SlateElement>(editor, props, {\n      match: n => SlateElement.isElement(n) && SlateEditor.isBlock(editor, n),\n    })\n  }\n\n  return newEditor\n}\n\nexport default withMarkdown\n","/**\n * @description module entry\n * @author wangfupeng\n */\n\nimport { IModuleConf } from '@wangeditor-next/editor'\n\nimport withMarkdown from './plugin'\n\nconst module: Partial<IModuleConf> = {\n  editorPlugin: withMarkdown,\n}\n\nexport default module\n"],"names":["KEY_TO_TYPE_FOR_SPACE","KEY_TO_TYPE_FOR_ENTER","getBeforeText","editor","selection","beforeText","range","anchor","block","SlateEditor","above","match","n","SlateElement","isElement","isBlock","blockPath","focus","start","string","module","editorPlugin","insertBreak","insertText","newEditor","isComposing","DomEditor","getTextarea","_a","text","SlateRange","isExpanded","getSelectedNodeByType","type","SlateTransforms","select","delete","props","setNodes","wrapNodes","children","getNodeType","_c","indexOf","lang_1","slice","toLowerCase","trim","codeLangs","_b","getConfig","MENU_CONF","codeSelectLang","some","item","value","preElem","language","insertNodes"],"mappings":"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"}