UNPKG

myst-to-jats

Version:
104 lines (103 loc) 3.99 kB
import { selectAll } from 'unist-util-select'; const CONTAINER_KINDS = ['figure', 'table', 'code', 'quote']; function updateInventory(node, key, idPrefix, inventory) { const keyInv = inventory[key] ?? { count: 0, lookup: {} }; keyInv.count += 1; const newId = typeof idPrefix === 'function' ? idPrefix(keyInv.count) : `${idPrefix}-${keyInv.count}`; if (node.identifier) { keyInv.lookup[node.identifier] = newId; } node.identifier = newId; inventory[key] = keyInv; } /** * Traverse mdast tree, find reference targets, and replace them with simple identifiers * * This builds a map of old identifiers to new identifiers, subsequently used * for updating references. Modified nodes include sections, containers, * footnotes, inlineExpressions, math, and citations. */ export function referenceTargetTransform(mdast, inventory, citations) { const sections = selectAll('section', mdast); sections.forEach((sec) => { updateInventory(sec, 'section', 'sec', inventory); }); const expressions = selectAll('inlineExpression', mdast); expressions.forEach((expr) => { updateInventory(expr, 'expression', 'expr', inventory); }); const equations = selectAll('math', mdast); equations.forEach((eq) => { updateInventory(eq, 'equation', 'eq', inventory); }); const footnotes = selectAll('footnoteDefinition', mdast); footnotes.forEach((fn) => { updateInventory(fn, 'footnote', 'fn', inventory); }); const proofs = selectAll('proof', mdast); proofs.forEach((fn) => { updateInventory(fn, 'proof', 'stm', inventory); }); const containers = selectAll('container', mdast); containers.forEach((container) => { if (!container.kind || !CONTAINER_KINDS.includes(container.kind)) { return; } updateInventory(container, container.kind, container.kind, inventory); }); if (!citations) return; const citationIds = Object.keys(citations); citationIds.forEach((citationId) => { inventory.cite ??= { count: 0, lookup: {} }; if (!inventory.cite.lookup[citationId]) { inventory.cite.count += 1; const newId = `ref-${inventory.cite.count}`; inventory.cite.lookup[citationId] = newId; citations[newId] = citations[citationId]; } delete citations[citationId]; }); } /** * Use reference lookup from referenceTargetTransform to update cross references */ export function referenceResolutionTransform(mdast, inventory) { const xrefs = selectAll('crossReference', mdast); const lookup = { ...inventory.section?.lookup, ...inventory.expression?.lookup, ...inventory.equation?.lookup, ...inventory.figure?.lookup, ...inventory.table?.lookup, ...inventory.code?.lookup, ...inventory.quote?.lookup, ...inventory.proof?.lookup, }; xrefs.forEach((xref) => { if (xref.identifier && lookup[xref.identifier]) { xref.identifier = lookup[xref.identifier]; } }); const supplements = selectAll('supplementaryMaterial', mdast); supplements.forEach((supp) => { if (supp.figIdentifier && lookup[supp.figIdentifier]) { supp.figIdentifier = lookup[supp.figIdentifier]; } if (supp.embedIdentifier && lookup[supp.embedIdentifier]) { supp.embedIdentifier = lookup[supp.embedIdentifier]; } }); const footnotes = selectAll('footnoteReference', mdast); footnotes.forEach((fn) => { if (fn.identifier && inventory.footnote?.lookup[fn.identifier]) { fn.identifier = inventory.footnote.lookup[fn.identifier]; } }); const citations = selectAll('cite', mdast); citations.forEach((cite) => { if (cite.label && inventory.cite?.lookup[cite.label]) { cite.label = inventory.cite.lookup[cite.label]; } }); }