From 0d8152e843040ce3e8faf8d6f65c0e3352d209fc Mon Sep 17 00:00:00 2001 From: devprakash93 Date: Tue, 31 Mar 2026 00:18:03 +0530 Subject: [PATCH 1/2] fix: preserve underscores in slug generation for anchor link compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove underscore (_) from the special-character replacement regex in DOC_API_SLUGS_REPLACEMENTS so that names like __dirname and __filename keep their underscores in generated IDs. Previously: __dirname → --dirname → dirname (broken anchor #__dirname) Now: __dirname → __dirname (matches anchor #__dirname correctly) - Update slugger tests to reflect new behavior - Add new 'underscore preservation' test suite covering: - __dirname - __filename - child_process (internal underscores) - mixed underscore + other special chars Fixes: broken anchor links for identifiers with leading/internal underscores --- src/generators/metadata/constants.mjs | 2 +- .../metadata/utils/__tests__/slugger.test.mjs | 34 ++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/generators/metadata/constants.mjs b/src/generators/metadata/constants.mjs index 614b30ef..9b0a8e26 100644 --- a/src/generators/metadata/constants.mjs +++ b/src/generators/metadata/constants.mjs @@ -6,7 +6,7 @@ export const IGNORE_STABILITY_STEMS = ['documentation']; export const DOC_API_SLUGS_REPLACEMENTS = [ { from: /node.js/i, to: 'nodejs' }, // Replace Node.js { from: /&/, to: '-and-' }, // Replace & - { from: /[/_,:;\\ ]/g, to: '-' }, // Replace /_,:;\. and whitespace + { from: /[/,:;\\ ]/g, to: '-' }, // Replace /,:;\ and whitespace (underscores are preserved) { from: /^-+(?!-*$)/g, to: '' }, // Remove any leading hyphens { from: /(? { }); describe('special character to hyphen replacement', () => { - it('replaces underscores with hyphens', () => { - assert.strictEqual(slug('foo_bar', identity), 'foo-bar'); + it('preserves underscores (does not replace with hyphens)', () => { + assert.strictEqual(slug('foo_bar', identity), 'foo_bar'); }); it('replaces forward slashes with hyphens', () => { @@ -46,6 +46,24 @@ describe('slug', () => { }); }); + describe('underscore preservation (anchor link compatibility)', () => { + it('preserves leading underscores so __dirname slug matches #__dirname anchor', () => { + assert.strictEqual(slug('__dirname', identity), '__dirname'); + }); + + it('preserves leading underscores so __filename slug matches #__filename anchor', () => { + assert.strictEqual(slug('__filename', identity), '__filename'); + }); + + it('preserves underscores within names', () => { + assert.strictEqual(slug('child_process', identity), 'child_process'); + }); + + it('preserves mixed underscores and other characters', () => { + assert.strictEqual(slug('foo_bar:baz', identity), 'foo_bar-baz'); + }); + }); + describe('leading hyphen removal', () => { it('removes a single leading hyphen', () => { assert.strictEqual(slug('-foo', identity), 'foo'); @@ -85,13 +103,21 @@ describe('slug', () => { assert.strictEqual(slug('Hello World'), 'hello-world'); }); - it('converts underscored names to hyphenated slugs', () => { - assert.strictEqual(slug('child_process'), 'child-process'); + it('preserves underscores in names (no hyphenation)', () => { + assert.strictEqual(slug('child_process'), 'child_process'); }); it('handles titles with no special characters', () => { assert.strictEqual(slug('stability index'), 'stability-index'); }); + + it('generates correct slug for __dirname', () => { + assert.strictEqual(slug('__dirname'), '__dirname'); + }); + + it('generates correct slug for __filename', () => { + assert.strictEqual(slug('__filename'), '__filename'); + }); }); }); From 2f8127ffa2b1693f0d127626d0bad767eb4a33dd Mon Sep 17 00:00:00 2001 From: devprakash93 Date: Tue, 31 Mar 2026 01:02:35 +0530 Subject: [PATCH 2/2] fix: use narrower regex to preserve only leading underscores --- src/generators/metadata/constants.mjs | 3 ++- .../metadata/utils/__tests__/slugger.test.mjs | 20 ++++++------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/generators/metadata/constants.mjs b/src/generators/metadata/constants.mjs index 9b0a8e26..f913c5b0 100644 --- a/src/generators/metadata/constants.mjs +++ b/src/generators/metadata/constants.mjs @@ -6,7 +6,8 @@ export const IGNORE_STABILITY_STEMS = ['documentation']; export const DOC_API_SLUGS_REPLACEMENTS = [ { from: /node.js/i, to: 'nodejs' }, // Replace Node.js { from: /&/, to: '-and-' }, // Replace & - { from: /[/,:;\\ ]/g, to: '-' }, // Replace /,:;\ and whitespace (underscores are preserved) + { from: /[/,:;\\ ]/g, to: '-' }, // Replace /,:;\ and whitespace + { from: /(?<=[^_])_+/g, to: '-' }, // Replace internal/trailing underscores with a hyphen { from: /^-+(?!-*$)/g, to: '' }, // Remove any leading hyphens { from: /(? { }); describe('special character to hyphen replacement', () => { - it('preserves underscores (does not replace with hyphens)', () => { - assert.strictEqual(slug('foo_bar', identity), 'foo_bar'); + it('replaces underscores with hyphens (except leading)', () => { + assert.strictEqual(slug('foo_bar', identity), 'foo-bar'); }); it('replaces forward slashes with hyphens', () => { @@ -54,14 +54,6 @@ describe('slug', () => { it('preserves leading underscores so __filename slug matches #__filename anchor', () => { assert.strictEqual(slug('__filename', identity), '__filename'); }); - - it('preserves underscores within names', () => { - assert.strictEqual(slug('child_process', identity), 'child_process'); - }); - - it('preserves mixed underscores and other characters', () => { - assert.strictEqual(slug('foo_bar:baz', identity), 'foo_bar-baz'); - }); }); describe('leading hyphen removal', () => { @@ -103,19 +95,19 @@ describe('slug', () => { assert.strictEqual(slug('Hello World'), 'hello-world'); }); - it('preserves underscores in names (no hyphenation)', () => { - assert.strictEqual(slug('child_process'), 'child_process'); + it('converts internal underscored names to hyphenated slugs', () => { + assert.strictEqual(slug('child_process'), 'child-process'); }); it('handles titles with no special characters', () => { assert.strictEqual(slug('stability index'), 'stability-index'); }); - it('generates correct slug for __dirname', () => { + it('generates correct slug for __dirname (preserves leading underscores)', () => { assert.strictEqual(slug('__dirname'), '__dirname'); }); - it('generates correct slug for __filename', () => { + it('generates correct slug for __filename (preserves leading underscores)', () => { assert.strictEqual(slug('__filename'), '__filename'); }); });