{"version":3,"sources":["../src/markdown.ts"],"sourcesContent":["import { Editor, Descendant, Element, Text } from '@editablejs/models'\n\nimport { Root, HTML, Content } from 'mdast'\nimport { fromMarkdown, Value } from 'mdast-util-from-markdown'\nimport { Extension } from 'micromark-util-types'\nimport { Config } from 'mdast-util-from-markdown/lib'\nimport { HTMLDeserializer } from './html'\n\nexport interface MarkdownDeserializerOptions {\n  element?: Omit<Element, 'children'>\n  text?: Omit<Text, 'text'>\n}\n\nexport type MarkdownDeserializerTransform = typeof MarkdownDeserializer.transform\n\nexport type MarkdownDeserializerWithTransform<T = MarkdownDeserializerOptions> = (\n  next: MarkdownDeserializerTransform,\n  deserializer: typeof MarkdownDeserializer,\n  options: T,\n) => MarkdownDeserializerTransform\n\nexport interface MarkdownDeserializerWithEditorTransform<T = MarkdownDeserializerOptions> {\n  transform: MarkdownDeserializerWithTransform<T>\n  options: T\n}\n\nconst defaultDisable = [\n  'attention',\n  'autolink',\n  'labelStartLink',\n  'labelStartImage',\n  'blockQuote',\n  'codeFenced',\n  'codeIndented',\n  'codeText',\n  'definition',\n  'headingAtx',\n  'list',\n  'thematicBreak',\n]\n\nexport type MarkdownCoreCommonmarkKeys =\n  | 'attention'\n  | 'autolink'\n  | 'labelStartLink'\n  | 'labelStartImage'\n  | 'blockQuote'\n  | 'codeFenced'\n  | 'codeIndented'\n  | 'codeText'\n  | 'definition'\n  | 'headingAtx'\n  | 'list'\n  | 'thematicBreak'\n\nexport type MarkdownDeserializerExtension =\n  | Extension\n  | MarkdownCoreCommonmarkKeys\n  | (Extension | MarkdownCoreCommonmarkKeys)[]\n\nexport type MarkdownDeserializerMdastExtension = Partial<Config> | Partial<Config>[]\nexport interface MarkdownDeserializerPlugin {\n  extensions?: MarkdownDeserializerExtension\n  mdastExtensions?: MarkdownDeserializerMdastExtension\n}\n\nconst MARKDOWN_DESERIALIZER_TRANSFORMS: WeakMap<Editor, MarkdownDeserializerWithEditorTransform[]> =\n  new WeakMap()\n\nconst MARKDOWN_DESERIALIZER_PLUGINS: WeakMap<Editor, MarkdownDeserializerPlugin[]> = new WeakMap()\n\nexport interface EditorMarkdownDeserializerOptions extends MarkdownDeserializerOptions {\n  editor: Editor\n}\n\nconst withEditorDeserializerTransform: MarkdownDeserializerWithTransform<\n  EditorMarkdownDeserializerOptions\n> = (next, self, { editor }) => {\n  return (node, options = {}) => {\n    if (node.type === 'html') {\n      if (self._consumedHTMLNodes.has(node)) {\n        if (self._consumedHTMLNodes.get(node) === true) self._consumedHTMLNodes.delete(node)\n        return []\n      }\n      const nodes = HTMLDeserializer.transformWithEditor(\n        editor,\n        new DOMParser().parseFromString(node.value, 'text/html').body,\n        options,\n      )\n      return nodes.length === 0 ? [{ text: node.value }] : nodes\n    }\n    return next(node, options)\n  }\n}\n\nexport const MarkdownDeserializer = {\n  transform(node: Content | Root, options: MarkdownDeserializerOptions = {}): Descendant[] {\n    const { element, text } = options\n    const children = []\n    switch (node.type) {\n      case 'root':\n        for (const child of node.children) {\n          children.push(...this.transform(child))\n        }\n        return children\n      case 'paragraph':\n        for (const child of node.children) {\n          children.push(...this.transform(child, { text }))\n        }\n        return [\n          {\n            ...element,\n            type: 'paragraph',\n            children: children.length === 0 ? [{ text: '' }] : children,\n          },\n        ]\n\n      case 'html':\n        if (this._consumedHTMLNodes.has(node)) {\n          if (this._consumedHTMLNodes.get(node) === true) this._consumedHTMLNodes.delete(node)\n          return []\n        }\n        const nodes = HTMLDeserializer.transform(\n          new DOMParser().parseFromString(node.value, 'text/html').body,\n          options,\n        )\n        return nodes.length === 0 ? [{ text: node.value }] : nodes\n\n      case 'text':\n        return [Object.assign({}, this._text, text, { text: node.value })]\n      default:\n        if ('children' in node) {\n          for (const child of node.children) {\n            children.push(...this.transform(child, { text }))\n          }\n        } else if ('value' in node) {\n          children.push(Object.assign(text ?? {}, { text: node.value }))\n        }\n        return children\n    }\n  },\n\n  with<T = MarkdownDeserializerOptions>(\n    transform: MarkdownDeserializerWithTransform<T>,\n    options: T,\n  ) {\n    const { transform: t } = this\n    this.transform = transform(t.bind(this), this, options)\n  },\n\n  withEditor<T = MarkdownDeserializerOptions>(\n    editor: Editor,\n    transform: MarkdownDeserializerWithTransform<T>,\n    options: T,\n  ) {\n    const fns = MARKDOWN_DESERIALIZER_TRANSFORMS.get(editor) ?? []\n    if (fns.find(fn => fn.transform === transform)) return\n    fns.push({\n      transform: transform as MarkdownDeserializerWithTransform,\n      options: options as MarkdownDeserializerOptions,\n    })\n    MARKDOWN_DESERIALIZER_TRANSFORMS.set(editor, fns)\n  },\n\n  transformWithEditor(editor: Editor, node: Content | Root) {\n    const MarkdownDeserializerEditor = Object.assign({}, MarkdownDeserializer)\n\n    const transforms = MARKDOWN_DESERIALIZER_TRANSFORMS.get(editor) ?? []\n\n    MarkdownDeserializerEditor.with(withEditorDeserializerTransform, { editor })\n\n    for (const { transform, options } of transforms) {\n      MarkdownDeserializerEditor.with(transform, options)\n    }\n\n    return MarkdownDeserializerEditor.transform(node)\n  },\n\n  _plugins: [] as MarkdownDeserializerPlugin[],\n\n  withPlugin(plugin: MarkdownDeserializerPlugin) {\n    this._plugins.push(plugin)\n  },\n\n  withEditorPlugin(editor: Editor, plugin: MarkdownDeserializerPlugin) {\n    const plugins = MARKDOWN_DESERIALIZER_PLUGINS.get(editor) ?? []\n    if (plugins.find(p => p === plugin)) return\n    plugins.push(plugin)\n    MARKDOWN_DESERIALIZER_PLUGINS.set(editor, plugins)\n  },\n\n  toMdast(value: Value, plugins: MarkdownDeserializerPlugin[] = []) {\n    const disable = defaultDisable.concat()\n    const extensions: Extension[] = [\n      {\n        disable: {\n          null: disable,\n        },\n      },\n    ]\n\n    const setExtensionsOrDisable = (ext: MarkdownDeserializerExtension) => {\n      if (Array.isArray(ext)) {\n        for (const e of ext) {\n          setExtensionsOrDisable(e)\n        }\n      } else if (typeof ext === 'string') {\n        const index = disable.indexOf(ext)\n        if (index > -1) disable.splice(index, 1)\n      } else {\n        extensions.push(ext)\n      }\n    }\n\n    const mdastExtensions: MarkdownDeserializerMdastExtension[] = []\n\n    const setMdastExtensions = (ext: MarkdownDeserializerMdastExtension) => {\n      if (Array.isArray(ext)) {\n        for (const e of ext) {\n          setMdastExtensions(e)\n        }\n      } else if (!mdastExtensions.some(e => e === ext)) {\n        mdastExtensions.push(ext)\n      }\n    }\n\n    for (const plugin of this._plugins.concat(plugins)) {\n      if (plugin.extensions) setExtensionsOrDisable(plugin.extensions)\n      if (plugin.mdastExtensions) setMdastExtensions(plugin.mdastExtensions)\n    }\n\n    return fromMarkdown(value, {\n      extensions,\n      mdastExtensions,\n    })\n  },\n\n  toMdastWithEditor(editor: Editor, value: Value) {\n    const plugins = MARKDOWN_DESERIALIZER_PLUGINS.get(editor) ?? []\n    return this.toMdast(value, plugins)\n  },\n\n  _text: {} as Omit<Text, 'text'>,\n\n  setNextText<T extends Text>(text: Omit<T, 'text'>) {\n    const keys = Object.keys(text) as (keyof Text)[]\n    for (const key of keys) {\n      if (key === 'text') continue\n      const value = text[key]\n      if (typeof value === 'undefined') {\n        delete this._text[key]\n      } else {\n        this._text[key] = value\n      }\n    }\n  },\n\n  _consumedHTMLNodes: new Map<HTML, boolean>(),\n  setConsumedHTMLNodes(node: HTML, consumed: boolean = false) {\n    this._consumedHTMLNodes.set(node, consumed)\n  },\n}\n"],"mappings":"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","names":[]}