fix: preserve underscores in slug generation for anchor link compatibility#733
fix: preserve underscores in slug generation for anchor link compatibility#733devprakash93 wants to merge 2 commits intonodejs:mainfrom
Conversation
…ility
- 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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| it('preserves underscores (does not replace with hyphens)', () => { | ||
| assert.strictEqual(slug('foo_bar', identity), 'foo_bar'); | ||
| }); |
There was a problem hiding this comment.
This breaks existing behavior, are we 100% sure no existing links break post this PR
There was a problem hiding this comment.
The fix was originally targeted at __dirname / __filename where the old behavior caused a two-step destruction: __dirname → --dirname → dirname (leading hyphens stripped), making the anchor completely unreachable.
However, you're correct that removing _ from the replacement entirely is too broad — names like child_process previously generated the slug child-process, and if existing documentation already links to #child-process, those links would silently break after this change.I'd like to propose a more targeted fix instead of removing _ from the replacement globally, we could handle the specific case where leading underscores get converted to leading hyphens and then stripped. For example, only preserve underscores that are at the start of the identifier.
I'll update the PR with a narrower approach and verify against existing cross-references in the docs before pushing. Thanks for the review!
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #733 +/- ##
==========================================
+ Coverage 76.37% 76.42% +0.04%
==========================================
Files 155 155
Lines 13766 13792 +26
Branches 1093 1100 +7
==========================================
+ Hits 10514 10540 +26
Misses 3247 3247
Partials 5 5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| 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'); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
You're right, those tests are redundant in their current form especially child_process and foo_bar:baz which just duplicate behavior already covered by the existing test suite.
As part of the narrower fix I mentioned in the previous comment (targeting only leading underscores rather than all underscores), I'll clean up these tests too. The updated test suite will:
Remove the redundant child_process and foo_bar:baz cases
Keep only the meaningful new cases: __dirname and __filename with clear assertions that their generated slugs match their markdown anchors
Restore the original child_process → child-process behavior and test
I'll push an updated commit shortly. Appreciate the thorough review!
| { 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) |
There was a problem hiding this comment.
| { from: /[/,:;\\ ]/g, to: '-' }, // Replace /,:;\ and whitespace (underscores are preserved) | |
| { from: /[/,:;\\ ]/g, to: '-' }, // Replace /,:;\ and whitespace. |
Fix broken anchor links for Node.js API identifiers containing underscores (e.g.
__dirname,__filename).Problem
The
_character was incorrectly included inDOC_API_SLUGS_REPLACEMENTS, causing underscores to be replaced during slug generation:__dirname → --dirname → dirname ❌
This resulted in mismatched anchor IDs (
dirname) and broken links (#__dirname).Solution
Remove
_from the replacement character class so underscores are preserved during slug generation.Result:
__dirname → __dirname ✅
__filename → __filename ✅
Changes
_from the slug replacement regex inDOC_API_SLUGS_REPLACEMENTS__dirname__filenamechild_processfoo_bar:bazValidation
All slug tests pass:
node --test src/generators/metadata/utils/tests/slugger.test.mjs
tests 32 | pass 32 | fail 0
Key checks:
slug('__dirname') → '__dirname'slug('__filename') → '__filename'slug('foo/bar') → 'foo-bar'slug('foo:bar') → 'foo-bar'Impact
Ensures anchor IDs remain consistent with source markdown and fixes broken links for all identifiers containing underscores.