UNPKG

@milkdown/preset-commonmark

Version:

The commonmark preset of [milkdown](https://milkdown.dev/).

68 lines (54 loc) 1.75 kB
import type { EditorView } from '@milkdown/prose/view' import { Plugin, PluginKey } from '@milkdown/prose/state' import { $prose } from '@milkdown/utils' import { withMeta } from '../__internal__' import { headingIdGenerator, headingSchema } from '../node/heading' /// This plugin is used to sync the heading id when the heading content changes. /// It will use the `headingIdGenerator` to generate the id. export const syncHeadingIdPlugin = $prose((ctx) => { const headingIdPluginKey = new PluginKey('MILKDOWN_HEADING_ID') const updateId = (view: EditorView) => { if (view.composing) return const getId = ctx.get(headingIdGenerator.key) const tr = view.state.tr.setMeta('addToHistory', false) let found = false const idMap: Record<string, number> = {} view.state.doc.descendants((node, pos) => { if (node.type === headingSchema.type(ctx)) { if (node.textContent.trim().length === 0) return const attrs = node.attrs let id = getId(node) if (idMap[id]) { idMap[id]! += 1 id += `-#${idMap[id]}` } else { idMap[id] = 1 } if (attrs.id !== id) { found = true tr.setMeta(headingIdPluginKey, true).setNodeMarkup(pos, undefined, { ...attrs, id, }) } } }) if (found) view.dispatch(tr) } return new Plugin({ key: headingIdPluginKey, view: (view) => { updateId(view) return { update: (view, prevState) => { if (view.state.doc.eq(prevState.doc)) return updateId(view) }, } }, }) }) withMeta(syncHeadingIdPlugin, { displayName: 'Prose<syncHeadingIdPlugin>', group: 'Prose', })