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';