remark-sort-definitions
Version:
remark plugin that reorders reference-style link definitions by id at the end of a document
33 lines • 1.32 kB
JavaScript
import assert from 'node:assert';
import { SKIP, visit } from 'unist-util-visit';
const compareNaturally = new Intl.Collator(undefined, {
numeric: true
}).compare;
const remarkSortDefinitions = function ({
algorithm = 'alphanumeric-first'
} = {}, ..._ignored) {
const definitionMap = new Map();
return tree => {
visit(tree, 'definition', (node, index, parent) => {
assert(node.type === 'definition', `unexpected node type ${node.type}`);
assert(index !== undefined, 'index is missing');
assert(parent !== undefined, 'parent is missing');
definitionMap.set(node.identifier.toUpperCase(), node);
parent.children.splice(index, 1);
return [SKIP, index];
});
tree.children.push(...getSortedDefinitions());
function getSortedDefinitions() {
return Array.from(definitionMap.entries()).sort(([a], [b]) => {
const aIsNumeric = isNumeric(a);
const bIsNumeric = isNumeric(b);
const result = algorithm === 'numeric-first' ? -1 : 1;
return aIsNumeric && !bIsNumeric ? result : !aIsNumeric && bIsNumeric ? -1 * result : compareNaturally(a, b);
}).map(([, definition]) => definition);
}
function isNumeric(identifier) {
return /^\p{Decimal_Number}+$/u.test(identifier);
}
};
};
export default remarkSortDefinitions;