diff --git a/tools/doc/html.mjs b/tools/doc/html.mjs index 14461df589e23a..74bc82e66bcfd5 100644 --- a/tools/doc/html.mjs +++ b/tools/doc/html.mjs @@ -381,6 +381,7 @@ const DEPRECATION_HEADING_PATTERN = /^DEP\d+:/; export function buildToc({ filename, apilinks }) { return (tree, file) => { const idCounters = Object.create(null); + const legacyIdCounters = Object.create(null); let toc = ''; let depth = 0; @@ -399,6 +400,8 @@ export function buildToc({ filename, apilinks }) { node.children[0].position.start.offset, node.position.end.offset).trim(); const id = getId(headingText, idCounters); + // Use previous ID generator to create alias + const legacyId = getLegacyId(`${realFilename}_${headingText}`, legacyIdCounters); const isDeprecationHeading = DEPRECATION_HEADING_PATTERN.test(headingText); @@ -417,6 +420,9 @@ export function buildToc({ filename, apilinks }) { let anchor = `#`; + // Add alias anchor to preserve old links + anchor += ``; + if (realFilename === 'errors' && headingText.startsWith('ERR_')) { anchor += `#`; @@ -446,6 +452,7 @@ export function buildToc({ filename, apilinks }) { }; } +// ID generator that mirrors Github's heading anchor parser const punctuation = /[^\w\- ]/g; function getId(text, idCounters) { text = text.toLowerCase() @@ -458,6 +465,23 @@ function getId(text, idCounters) { return text; } +// This ID generator is purely to generate aliases +// so we can preserve old doc links +const notAlphaNumerics = /[^a-z0-9]+/g; +const edgeUnderscores = /^_+|_+$/g; +const notAlphaStart = /^[^a-z]/; +function getLegacyId(text, idCounters) { + text = text.toLowerCase() + .replace(notAlphaNumerics, '_') + .replace(edgeUnderscores, '') + .replace(notAlphaStart, '_$&'); + if (idCounters[text] !== undefined) { + return `${text}_${++idCounters[text]}`; + } + idCounters[text] = 0; + return text; +} + function altDocs(filename, docCreated, versions) { const [, docCreatedMajor, docCreatedMinor] = docCreated.map(Number); const host = 'https://nodejs.org';