Skip to content

fix(ui): normalize README heading fragments to lowercase slugs#2385

Merged
ghostdevv merged 2 commits intonpmx-dev:mainfrom
trivikr:fix/lowercase-readme-links
Apr 5, 2026
Merged

fix(ui): normalize README heading fragments to lowercase slugs#2385
ghostdevv merged 2 commits intonpmx-dev:mainfrom
trivikr:fix/lowercase-readme-links

Conversation

@trivikr
Copy link
Copy Markdown
Contributor

@trivikr trivikr commented Apr 5, 2026

🔗 Linked issue

resolves #2381

🧭 Context

README heading links on package pages were preserving the original fragment casing, while generated heading ids are lowercased GitHub-style slugs. That meant links like #Associations produced #user-content-Associations, which did not match the rendered heading id #user-content-associations.

This change makes README hash links use the same normalization path as generated heading ids.

📚 Description

This updates the README URL resolver to normalize unprefixed hash fragments with the same slugification logic used for heading ids before adding the user-content- prefix. Already-prefixed fragments are left unchanged so existing custom user-content-* targets still work as-is.

A regression test was added to cover mixed-case heading fragments and verify that #Associations is rendered as #user-content-associations.

- Decode and slugify in-page README anchors before prefixing
- Keep already prefixed `user-content` fragments unchanged
- Add coverage for mixed-case heading links
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Apr 5, 2026 6:37am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Apr 5, 2026 6:37am
npmx-lunaria Ignored Ignored Apr 5, 2026 6:37am

Request Review

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7acc85e9-65b4-46d4-ade5-55f578cdd211

📥 Commits

Reviewing files that changed from the base of the PR and between 3fe683a and 2ec90fa.

📒 Files selected for processing (1)
  • server/utils/readme.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/utils/readme.ts

📝 Walkthrough

Walkthrough

Updated README URL fragment handling: added decodeHashFragment() to safely URL-decode fragments with a fallback; changed resolveUrl() for fragment-only URLs to return # for empty fragments, preserve fragments already starting with USER_CONTENT_PREFIX, or else decode, slugify to the README heading-id format and wrap with toUserContentHash() (falling back to the original fragment if slugification yields empty). Removed the prior behaviour that always converted #<fragment> into toUserContentHash(<fragment>) without decoding or slug normalization. A unit test verifying slug normalisation for mixed-case headings was added.

Possibly related PRs

Suggested labels

needs review

Suggested reviewers

  • danielroe
  • serhalp
  • gameroman
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description clearly explains the issue, context, and solution related to normalizing README heading fragments to lowercase slugs.
Linked Issues check ✅ Passed The PR directly addresses issue #2381 by normalizing unprefixed hash fragments to lowercase slugs matching generated heading ids, resolving the broken anchoring issue.
Out of Scope Changes check ✅ Passed All changes are within scope: the helper function modification and URL resolver logic directly address fragment normalization, with a regression test for mixed-case headings.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6cd493a5-d6ac-4b24-ae7d-6b1ada38dbac

📥 Commits

Reviewing files that changed from the base of the PR and between a2254fd and 3fe683a.

📒 Files selected for processing (2)
  • server/utils/readme.ts
  • test/unit/server/utils/readme.spec.ts

@trivikr
Copy link
Copy Markdown
Contributor Author

trivikr commented Apr 5, 2026

Testing:

  1. Go to https://npmx-dlw1pzg6q-npmx.vercel.app/package/fishery/v/2.4.0#user-content-build-api
  2. Click on "Associations section"
  3. Check window URL is https://npmx-dlw1pzg6q-npmx.vercel.app/package/fishery/v/2.4.0#user-content-associations

@ghostdevv ghostdevv added this pull request to the merge queue Apr 5, 2026
Merged via the queue into npmx-dev:main with commit 5324b96 Apr 5, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Broken anchoring to headers on package reademe page

2 participants