72 lines
2 KiB
TypeScript
72 lines
2 KiB
TypeScript
import type { Root, Element, ElementContent, Text } from 'hast'
|
|
import type { Plugin } from 'unified'
|
|
import { visit } from 'unist-util-visit'
|
|
|
|
/**
|
|
* A rehype plugin that transforms paragraphs containing a leading "Term:" into
|
|
* definition lists. For example, a paragraph like "Term: Definition" will be
|
|
* transformed into a <dl> element with a <dt> for the term and a <dd> for the
|
|
* definition.
|
|
*/
|
|
export const rehypeDefinition: Plugin<[], Root> = () => (tree: Root) => {
|
|
visit(tree, 'element', (node: Element, index, parent) => {
|
|
if (!parent || typeof index !== 'number') return
|
|
if (node.tagName !== 'p') return
|
|
|
|
const children = node.children
|
|
|
|
let splitIndex = -1
|
|
let colonIndex = -1
|
|
for (let i = 0; i < children.length; i++) {
|
|
const child = children[i]
|
|
if (child.type === 'text') {
|
|
const idx = child.value.indexOf(':')
|
|
if (idx !== -1) {
|
|
splitIndex = i
|
|
colonIndex = idx
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if (splitIndex === -1) return
|
|
|
|
const splitText = children[splitIndex] as Text
|
|
const beforeColon = splitText.value.slice(0, colonIndex)
|
|
const afterColon = splitText.value.slice(colonIndex + 1).replace(/^\s+/, '')
|
|
|
|
const termChildren: ElementContent[] = [
|
|
...children.slice(0, splitIndex),
|
|
...(beforeColon ? [{ type: 'text', value: beforeColon } as Text] : []),
|
|
]
|
|
|
|
const definitionChildren: ElementContent[] = [
|
|
...(afterColon ? [{ type: 'text', value: afterColon } as Text] : []),
|
|
...children.slice(splitIndex + 1),
|
|
]
|
|
|
|
if (termChildren.length === 0 || definitionChildren.length === 0) return
|
|
|
|
const dlNode: Element = {
|
|
type: 'element',
|
|
tagName: 'dl',
|
|
properties: {},
|
|
children: [
|
|
{
|
|
type: 'element',
|
|
tagName: 'dt',
|
|
properties: {},
|
|
children: termChildren,
|
|
},
|
|
{
|
|
type: 'element',
|
|
tagName: 'dd',
|
|
properties: {},
|
|
children: definitionChildren,
|
|
},
|
|
],
|
|
}
|
|
|
|
parent.children[index] = dlNode
|
|
})
|
|
}
|