From 3d272c4bd00ee5fe8fd5893579043eaaad8009e2 Mon Sep 17 00:00:00 2001 From: btea <2356281422@qq.com> Date: Thu, 5 Feb 2026 15:29:47 +0800 Subject: [PATCH] fix: readme rendering result lacks anchor point jump --- server/utils/readme.ts | 48 +++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/server/utils/readme.ts b/server/utils/readme.ts index 2435b7ada..6f66d21e2 100644 --- a/server/utils/readme.ts +++ b/server/utils/readme.ts @@ -139,23 +139,24 @@ const ALLOWED_TAGS = [ ] const ALLOWED_ATTR: Record = { - a: ['href', 'title', 'target', 'rel'], - img: ['src', 'alt', 'title', 'width', 'height', 'align'], - source: ['src', 'srcset', 'type', 'media'], - button: ['class', 'title', 'type', 'aria-label', 'data-copy'], - th: ['colspan', 'rowspan', 'align'], - td: ['colspan', 'rowspan', 'align'], - h3: ['id', 'data-level', 'align'], - h4: ['id', 'data-level', 'align'], - h5: ['id', 'data-level', 'align'], - h6: ['id', 'data-level', 'align'], - blockquote: ['data-callout'], - details: ['open'], - code: ['class'], - pre: ['class', 'style'], - span: ['class', 'style'], - div: ['class', 'style', 'align'], - p: ['align'], + '*': ['id'], // Allow id on all tags + 'a': ['href', 'title', 'target', 'rel'], + 'img': ['src', 'alt', 'title', 'width', 'height', 'align'], + 'source': ['src', 'srcset', 'type', 'media'], + 'button': ['class', 'title', 'type', 'aria-label', 'data-copy'], + 'th': ['colspan', 'rowspan', 'align'], + 'td': ['colspan', 'rowspan', 'align'], + 'h3': ['data-level', 'align'], + 'h4': ['data-level', 'align'], + 'h5': ['data-level', 'align'], + 'h6': ['data-level', 'align'], + 'blockquote': ['data-callout'], + 'details': ['open'], + 'code': ['class'], + 'pre': ['class', 'style'], + 'span': ['class', 'style'], + 'div': ['class', 'style', 'align'], + 'p': ['align'], } // GitHub-style callout types @@ -397,6 +398,14 @@ ${html} const rawHtml = marked.parse(content) as string + // 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 } + } + const sanitized = sanitizeHtml(rawHtml, { allowedTags: ALLOWED_TAGS, allowedAttributes: ALLOWED_ATTR, @@ -436,6 +445,11 @@ ${html} } return { tagName, attribs } }, + div: prefixId, + p: prefixId, + span: prefixId, + section: prefixId, + article: prefixId, }, })