Files
nocodb/packages/nc-gui/helpers/tiptap-markdown/serialize/state.ts
2025-03-20 10:14:20 +00:00

65 lines
1.7 KiB
TypeScript

import type { Mark, Node } from '@tiptap/pm/model'
import { MarkdownSerializerState as BaseMarkdownSerializerState } from '@tiptap/pm/markdown'
import { trimInline } from '../util/markdown'
interface InlineState {
delimiter?: string
start?: number
end?: number
}
/**
* Override default MarkdownSerializerState to:
* - handle commonmark delimiters (https://spec.commonmark.org/0.29/#left-flanking-delimiter-run)
*/
export class MarkdownSerializerState extends BaseMarkdownSerializerState {
inTable = false
public inlines: InlineState[] = []
public out = ''
constructor(nodes, marks, options) {
super(nodes, marks, options ?? {})
this.inlines = []
}
override render(node: Node, parent: Node, index: number): void {
super.render(node, parent, index)
const top = this.inlines[this.inlines.length - 1]
if (top?.start && top?.end) {
const { delimiter, start, end } = this.normalizeInline(top)
this.out = trimInline(this.out, delimiter, start, end)
this.inlines.pop()
}
}
override markString(mark: Mark, open: boolean, parent: Node, index: number): string {
const info = this.marks[mark.type.name]
if (info.expelEnclosingWhitespace) {
if (open) {
this.inlines.push({
start: this.out.length,
delimiter: info.open,
})
} else {
const top = this.inlines.pop() || {}
this.inlines.push({
...top,
end: this.out.length,
})
}
}
return super.markString(mark, open, parent, index)
}
normalizeInline(inline) {
let { start } = inline
while (this.out.charAt(start).match(/\s/)) {
start++
}
return {
...inline,
start,
}
}
}