fix: readme rendering result lacks anchor point jump#994
fix: readme rendering result lacks anchor point jump#994danielroe merged 1 commit intonpmx-dev:mainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
📝 WalkthroughWalkthroughThe changes modify HTML sanitisation in the readme rendering utility. A wildcard key '*' is introduced in ALLOWED_ATTR to enable 'id' attributes across all HTML tags, removing redundant per-tag declarations. A helper function prefixes id attributes with 'user-content-' during sanitisation, applied via the transformTags pipeline to block elements including div, p, span, section, and article. Public function signatures remain unchanged; modifications are internal to the README HTML rendering and sanitisation logic. The adjustment involves 31 additions and 17 deletions. 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
| // Helper to prefix id attributes with 'user-content-' | ||
| const prefixId = (tagName: string, attribs: sanitizeHtml.Attributes) => { | ||
| if (attribs.id && !attribs.id.startsWith('user-content-')) { | ||
| attribs.id = `user-content-${attribs.id}` | ||
| } | ||
| return { tagName, attribs } | ||
| } |
There was a problem hiding this comment.
Make fragment normalisation idempotent to avoid double‑prefixing.
Links already using #user-content-… (common when copied from GitHub) will become #user-content-user-content-… because resolveUrl always prefixes hash fragments. Guard against that so those anchors still resolve.
🔧 Proposed fix
function resolveUrl(url: string, packageName: string, repoInfo?: RepositoryInfo): string {
if (!url) return url
if (url.startsWith('#')) {
// Prefix anchor links to match heading IDs (avoids collision with page IDs)
- return `#user-content-${url.slice(1)}`
+ if (url.startsWith('#user-content-')) return url
+ return `#user-content-${url.slice(1)}`
}| div: prefixId, | ||
| p: prefixId, | ||
| span: prefixId, | ||
| section: prefixId, | ||
| article: prefixId, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's locate the file and check its existence
find . -name "readme.ts" -path "*/server/utils/*" 2>/dev/null | head -20Repository: npmx-dev/npmx.dev
Length of output: 85
🏁 Script executed:
# Check the file size and read the specific lines mentioned
if [ -f "server/utils/readme.ts" ]; then
wc -l server/utils/readme.ts
echo "=== Lines 440-460 ==="
sed -n '440,460p' server/utils/readme.ts
fiRepository: npmx-dev/npmx.dev
Length of output: 648
🏁 Script executed:
# Search for the transformTags configuration to understand the full context
rg "transformTags" server/utils/readme.ts -A 30 -B 5Repository: npmx-dev/npmx.dev
Length of output: 1470
🏁 Script executed:
# Look for the prefixId function definition
rg "prefixId\s*[:=]|function prefixId" server/utils/readme.ts -B 2 -A 10Repository: npmx-dev/npmx.dev
Length of output: 511
🏁 Script executed:
# Check package.json for sanitize-html version
cat package.json | grep -A 2 -B 2 "sanitize-html"Repository: npmx-dev/npmx.dev
Length of output: 377
🌐 Web query:
sanitize-html 2.17.0 wildcard transform support transformTags
💡 Result:
In sanitize-html v2.17.0, transformTags supports a '*' wildcard key to apply a transform to all tags (not just a specific tag name). [1][2]
import sanitizeHtml from "sanitize-html";
const clean = sanitizeHtml(dirtyHtml, {
transformTags: {
"*": (tagName, attribs) => ({
tagName,
attribs: { ...attribs, "data-sanitized": "1" }
})
}
});You can also use the wildcard with sanitizeHtml.simpleTransform(...) for simpler “add/override attributes” cases. [1][2]
🏁 Script executed:
# Also search for any usage of wildcard transforms in the codebase
rg "transformTags" . -A 50 | grep -E "(\*|wildcard)" || echo "No wildcard patterns found in transformTags"Repository: npmx-dev/npmx.dev
Length of output: 104
🏁 Script executed:
# Let's check if there are any fragment link rewrites happening elsewhere
rg "user-content" server/utils/readme.ts -B 3 -A 3Repository: npmx-dev/npmx.dev
Length of output: 1054
🏁 Script executed:
# Check the ALLOWED_TAGS to see what tags are allowed through
rg "ALLOWED_TAGS\s*=" server/utils/readme.ts -A 30Repository: npmx-dev/npmx.dev
Length of output: 366
Prefix IDs for anchor elements to match rewritten fragment links.
Fragment links are rewritten to #user-content-foo, but anchor IDs are not prefixed, creating a mismatch. Apply prefixId to the a transform to keep anchor jumps consistent.
♻️ Proposed fix (apply to `a`)
a: (tagName, attribs) => {
// Add security attributes for external links
if (attribs.href && hasProtocol(attribs.href, { acceptRelative: true })) {
attribs.rel = 'nofollow noreferrer noopener'
attribs.target = '_blank'
}
- return { tagName, attribs }
+ return prefixId(tagName, attribs)
},Alternatively, sanitize-html 2.17.0 supports a wildcard '*' transform in transformTags if you prefer centralising ID prefixing.
fix #989