myst-to-jats
Version:
Export from MyST Markdown to JATS
48 lines (47 loc) • 2 kB
JavaScript
import { selectAll } from 'unist-util-select';
/**
* This transforms a flat list of alternating dt/dd into a definitionItem for each term.
* - `defList -> [defTerm, defDescription, defDescription, defTerm, defDescription]`
* - `defList -> [defItem -> [defTerm, defDescription, defDescription], defItem -> [defTerm, defDescription]]`
*
* It will also ensure that any nested defDescriptions that are not paragraphs are wrapped in paragraphs.
*/
export function definitionTransform(mdast) {
const defList = selectAll('definitionList', mdast);
defList.forEach((node) => {
const children = [];
let current = undefined;
function pushItem() {
if (current && current.children.length > 0) {
children.push(current);
}
current = { type: 'definitionItem', children: [] };
}
node.children.forEach((child) => {
if (child.type === 'definitionTerm' || !current) {
pushItem();
}
current?.children.push(child);
});
pushItem();
node.children = children;
});
// Ensure that the only children of the def node are paragraphs
// This is necessary for the JATS spec
const defDescriptions = selectAll('definitionDescription', mdast);
defDescriptions.forEach((node) => {
const allParagraphs = node.children.reduce((b, n) => b && n.type === 'paragraph', true);
const oneParagraph = !!node.children.find((n) => n.type === 'paragraph');
// If there isn't any paragraph, it is likely text/inline content and we can handle this in the renderer
if (allParagraphs || !oneParagraph)
return;
node.children = node.children.map((child) => {
if (child.type === 'paragraph')
return child;
return { type: 'paragraph', children: [child] };
});
});
}
export const definitionPlugin = () => (tree) => {
definitionTransform(tree);
};