From 4ebabb28137a3c7c6f3e608ca1d73e0c3cb48b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?= Date: Wed, 11 Feb 2026 18:17:58 +0100 Subject: [PATCH 1/4] fix: remove unneeded code --- server/utils/readme.ts | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/server/utils/readme.ts b/server/utils/readme.ts index 9920eb2af..79624702c 100644 --- a/server/utils/readme.ts +++ b/server/utils/readme.ts @@ -221,16 +221,6 @@ const isNpmJsUrlThatCanBeRedirected = (url: URL) => { return true } -const replaceHtmlLink = (html: string) => { - return html.replace(/href="([^"]+)"/g, (match, href) => { - if (isNpmJsUrlThatCanBeRedirected(new URL(href, 'https://www.npmjs.com'))) { - const newHref = href.replace(/^https?:\/\/(www\.)?npmjs\.com/, '') - return `href="${newHref}"` - } - return match - }) -} - /** * Resolve a relative URL to an absolute URL. * If repository info is available, resolve to provider's raw file URLs. @@ -437,14 +427,7 @@ ${html} return `
${body}
\n` } - marked.setOptions({ - renderer, - walkTokens: token => { - if (token.type === 'html') { - token.text = replaceHtmlLink(token.text) - } - }, - }) + marked.setOptions({ renderer }) const rawHtml = marked.parse(content) as string From beca77716973d3ee069f9ff5249ed76fcbe71f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?= Date: Thu, 12 Feb 2026 11:19:49 +0100 Subject: [PATCH 2/4] feat: add clickable links to readme headings --- app/components/Readme.vue | 10 ++++++++++ server/utils/readme.ts | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/components/Readme.vue b/app/components/Readme.vue index e613e76e3..446c46079 100644 --- a/app/components/Readme.vue +++ b/app/components/Readme.vue @@ -150,6 +150,16 @@ function handleClick(event: MouseEvent) { @apply inline i-carbon:launch rtl-flip ms-1 opacity-50; } +.readme :deep(a[href^='#']::after) { + /* I don't know what kind of sorcery this is, but it ensures this icon can't wrap to a new line on its own. */ + content: '__'; + @apply inline i-carbon:link rtl-flip ms-1 opacity-0; +} + +.readme :deep(a[href^='#']:hover::after) { + @apply opacity-100; +} + .readme :deep(code) { @apply font-mono; font-size: 0.875em; diff --git a/server/utils/readme.ts b/server/utils/readme.ts index 79624702c..ca3ae0b35 100644 --- a/server/utils/readme.ts +++ b/server/utils/readme.ts @@ -377,7 +377,8 @@ export async function renderReadmeHtml( toc.push({ text: plainText, id, depth }) } - return `${text}\n` + /** The link href uses the unique slug WITHOUT the 'user-content-' prefix, because that will later be added for all links. */ + return `${text}\n` } // Syntax highlighting for code blocks (uses shared highlighter) From 15ef2797be415565601901eacc7706e7269be0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?= Date: Thu, 12 Feb 2026 11:31:59 +0100 Subject: [PATCH 3/4] test: update test --- test/unit/server/utils/readme.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unit/server/utils/readme.spec.ts b/test/unit/server/utils/readme.spec.ts index 08db45be2..9bd758a85 100644 --- a/test/unit/server/utils/readme.spec.ts +++ b/test/unit/server/utils/readme.spec.ts @@ -375,7 +375,8 @@ describe('HTML output', () => { const markdown = `# Title\n\nSome **bold** text and a [link](https://example.com).` const result = await renderReadmeHtml(markdown, 'test-pkg') - expect(result.html).toBe(`

Title

+ expect(result.html) + .toBe(`

Title

Some bold text and a link.

`) }) From efe69ba37551eeee5285282a52e7ef51130d7e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?= Date: Thu, 12 Feb 2026 13:18:56 +0100 Subject: [PATCH 4/4] fix: fix heading links for weird edge case --- server/utils/readme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/utils/readme.ts b/server/utils/readme.ts index ca3ae0b35..d4cabda86 100644 --- a/server/utils/readme.ts +++ b/server/utils/readme.ts @@ -378,7 +378,7 @@ export async function renderReadmeHtml( } /** The link href uses the unique slug WITHOUT the 'user-content-' prefix, because that will later be added for all links. */ - return `${text}\n` + return `${plainText}\n` } // Syntax highlighting for code blocks (uses shared highlighter)