@milkdown/preset-commonmark
Version:
The commonmark preset of [milkdown](https://milkdown.dev/).
70 lines (54 loc) • 1.8 kB
text/typescript
import type { Node } from '@milkdown/transformer'
import { $remark } from '@milkdown/utils'
import { visit } from 'unist-util-visit'
import { withMeta } from '../__internal__'
/// This plugin is used to add inline line break for remark AST.
/// The inline line break should be treated as a `space`.
/// And the normal line break should be treated as a `LF`.
export const remarkLineBreak = $remark(
'remarkLineBreak',
() => () => (tree: Node) => {
const find = /[\t ]*(?:\r?\n|\r)/g
visit(
tree,
'text',
(
node: Node & { value: string },
index: number,
parent: Node & { children: Node[] }
) => {
if (!node.value || typeof node.value !== 'string') return
const result = []
let start = 0
find.lastIndex = 0
let match = find.exec(node.value)
while (match) {
const position = match.index
if (start !== position)
result.push({
type: 'text',
value: node.value.slice(start, position),
})
result.push({ type: 'break', data: { isInline: true } })
start = position + match[0].length
match = find.exec(node.value)
}
const hasResultAndIndex =
result.length > 0 && parent && typeof index === 'number'
if (!hasResultAndIndex) return
if (start < node.value.length)
result.push({ type: 'text', value: node.value.slice(start) })
parent.children.splice(index, 1, ...result)
return index + result.length
}
)
}
)
withMeta(remarkLineBreak.plugin, {
displayName: 'Remark<remarkLineBreak>',
group: 'Remark',
})
withMeta(remarkLineBreak.options, {
displayName: 'RemarkConfig<remarkLineBreak>',
group: 'Remark',
})