UNPKG

mystjs

Version:
204 lines 8.05 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveReferences = exports.enumerateTargets = exports.State = exports.formatHeadingEnumerator = exports.incrementHeadingCounts = exports.ReferenceKind = exports.TargetKind = void 0; const unist_util_visit_1 = require("unist-util-visit"); const unist_util_select_1 = require("unist-util-select"); const mdast_util_find_and_replace_1 = require("mdast-util-find-and-replace"); const utils_1 = require("./utils"); var TargetKind; (function (TargetKind) { TargetKind["heading"] = "heading"; TargetKind["math"] = "math"; TargetKind["figure"] = "figure"; TargetKind["table"] = "table"; TargetKind["code"] = "code"; })(TargetKind = exports.TargetKind || (exports.TargetKind = {})); var ReferenceKind; (function (ReferenceKind) { ReferenceKind["ref"] = "ref"; ReferenceKind["numref"] = "numref"; ReferenceKind["eq"] = "eq"; })(ReferenceKind = exports.ReferenceKind || (exports.ReferenceKind = {})); /** * See https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-numref */ function fillReferenceEnumerators(node, enumerator) { const num = String(enumerator); (0, mdast_util_find_and_replace_1.findAndReplace)(node, { '%s': num, '{number}': num }); } function copyNode(node) { return JSON.parse(JSON.stringify(node)); } function kindFromNode(node) { return node.type === 'container' ? node.kind : node.type; } /** * Increment heading counts based on depth to increment * * depth is the depth to increment * counts is a list of 6 counts, corresponding to 6 heading depths * * When a certain depth is incremented, shallower depths are left the same * and deeper depths are reset to zero. Null counts anywhere are ignored. */ function incrementHeadingCounts(depth, counts) { const incrementIndex = depth - 1; return counts.map((count, index) => { if (count === null || index < incrementIndex) return count; if (index === incrementIndex) return count + 1; return 0; }); } exports.incrementHeadingCounts = incrementHeadingCounts; /** * Return dot-delimited header numbering based on heading counts * * counts is a list of 6 counts, corresponding to 6 heading depths * * Leading zeros are kept, trailing zeros are removed, nulls are ignored. */ function formatHeadingEnumerator(counts) { counts = counts.filter((d) => d !== null); while (counts && counts[counts.length - 1] === 0) { counts.pop(); } return counts.join('.'); } exports.formatHeadingEnumerator = formatHeadingEnumerator; class State { constructor(targetCounts, targets) { this.targetCounts = targetCounts || {}; this.targets = targets || {}; } addTarget(node) { const kind = kindFromNode(node); if (kind && kind in TargetKind) { let enumerator = null; if (node.enumerated !== false) { enumerator = this.incrementCount(node, kind); node.enumerator = enumerator; } if (node.identifier) { this.targets[node.identifier] = { node: copyNode(node), kind: kind, }; } } } initializeNumberedHeadingDepths(tree) { const headings = (0, unist_util_select_1.selectAll)('heading', tree).filter((node) => node.enumerated !== false); const headingDepths = new Set(headings.map((node) => node.depth)); this.targetCounts.heading = [1, 2, 3, 4, 5, 6].map((depth) => headingDepths.has(depth) ? 0 : null); } incrementCount(node, kind) { if (kind === TargetKind.heading) { // Ideally initializeNumberedHeadingDepths is called before incrementing // heading count to do a better job initializng headers based on tree if (!this.targetCounts.heading) this.targetCounts.heading = [0, 0, 0, 0, 0, 0]; this.targetCounts.heading = incrementHeadingCounts(node.depth, this.targetCounts.heading); return formatHeadingEnumerator(this.targetCounts.heading); } if (kind in this.targetCounts) { this.targetCounts[kind] += 1; } else { this.targetCounts[kind] = 1; } return String(this.targetCounts[kind]); } getTarget(identifier) { if (!identifier) return undefined; return this.targets[identifier]; } resolveReferenceContent(node) { var _a; const target = this.getTarget(node.identifier); if (!target) { return; } const kinds = { ref: { eq: node.kind === ReferenceKind.eq, ref: node.kind === ReferenceKind.ref, numref: node.kind === ReferenceKind.numref, }, target: { math: target.kind === TargetKind.math, figure: target.kind === TargetKind.figure, table: target.kind === TargetKind.table, heading: target.kind === TargetKind.heading, }, }; const noNodeChildren = !((_a = node.children) === null || _a === void 0 ? void 0 : _a.length); if (kinds.ref.eq && kinds.target.math && target.node.enumerator) { if (noNodeChildren) { (0, utils_1.setTextAsChild)(node, `(${target.node.enumerator})`); } node.resolved = true; } else if (kinds.ref.ref && kinds.target.heading) { if (noNodeChildren) { node.children = copyNode(target.node).children; } node.resolved = true; } else if (kinds.ref.ref && (kinds.target.figure || kinds.target.table)) { if (noNodeChildren) { const caption = (0, unist_util_select_1.select)('caption > paragraph', target.node); node.children = copyNode(caption).children; } node.resolved = true; } else if (kinds.ref.numref && kinds.target.figure && target.node.enumerator) { if (noNodeChildren) { (0, utils_1.setTextAsChild)(node, 'Figure %s'); } fillReferenceEnumerators(node, target.node.enumerator); node.resolved = true; } else if (kinds.ref.numref && kinds.target.table && target.node.enumerator) { if (noNodeChildren) { (0, utils_1.setTextAsChild)(node, 'Table %s'); } fillReferenceEnumerators(node, target.node.enumerator); node.resolved = true; } } } exports.State = State; const enumerateTargets = (state, tree, opts) => { state.initializeNumberedHeadingDepths(tree); if (!opts.disableContainerEnumeration) { (0, unist_util_visit_1.visit)(tree, 'container', (node) => state.addTarget(node)); } if (!opts.disableEquationEnumeration) { (0, unist_util_visit_1.visit)(tree, 'math', (node) => state.addTarget(node)); } if (!opts.disableHeadingEnumeration) { (0, unist_util_visit_1.visit)(tree, 'heading', (node) => state.addTarget(node)); } return tree; }; exports.enumerateTargets = enumerateTargets; const resolveReferences = (state, tree) => { (0, unist_util_select_1.selectAll)('link', tree).forEach((node) => { const reference = (0, utils_1.normalizeLabel)(node.url); if (reference && reference.identifier in state.targets) { node.type = 'crossReference'; node.kind = state.targets[reference.identifier].kind === TargetKind.math ? 'eq' : 'ref'; node.identifier = reference.identifier; node.label = reference.label; delete node.url; } }); (0, unist_util_visit_1.visit)(tree, 'crossReference', (node) => { state.resolveReferenceContent(node); }); }; exports.resolveReferences = resolveReferences; //# sourceMappingURL=state.js.map