Skip to content

Commit 72af330

Browse files
committed
fix: add /package/* path support for markdown rewrites + escape user-supplied maintainer fields
- Add vercel.json rewrites for /package/:path to strip prefix and serve markdown - Escape maintainer name with escapeMarkdown() since it's user-supplied - URL-encode maintainer username in link hrefs for safety
1 parent 07b045a commit 72af330

2 files changed

Lines changed: 40 additions & 5 deletions

File tree

server/utils/markdown.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,13 @@ export function generatePackageMarkdown(options: PackageMarkdownOptions): string
257257
lines.push('')
258258
for (const maintainer of pkg.maintainers.slice(0, 10)) {
259259
// npm API returns username but `@npm/types` `Contact` doesn't include it
260+
// maintainers is user-supplied so we escape both name and username
260261
const username = (maintainer as { username?: string }).username
261-
const name = maintainer.name || username || 'Unknown'
262+
const safeName = escapeMarkdown(maintainer.name || username || 'Unknown')
262263
if (username) {
263-
lines.push(`- [${name}](https://npmx.dev/~${username})`)
264+
lines.push(`- [${safeName}](https://npmx.dev/~${encodeURIComponent(username)})`)
264265
} else {
265-
lines.push(`- ${name}`)
266+
lines.push(`- ${safeName}`)
266267
}
267268
}
268269
lines.push('')

vercel.json

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,48 @@
22
"$schema": "https://openapi.vercel.sh/vercel.json",
33
"trailingSlash": false,
44
"rewrites": [
5+
{
6+
"source": "/package/:path(.*)",
7+
"has": [
8+
{
9+
"type": "header",
10+
"key": "accept",
11+
"value": "(.*?)text/markdown(.*)"
12+
}
13+
],
14+
"destination": "/raw/:path.md"
15+
},
16+
{
17+
"source": "/package/:path(.*)",
18+
"has": [
19+
{
20+
"type": "header",
21+
"key": "user-agent",
22+
"value": "curl/.*"
23+
}
24+
],
25+
"destination": "/raw/:path.md"
26+
},
527
{
628
"source": "/:path((?!api|_nuxt|_v|__nuxt|search|code|raw/).*)",
7-
"has": [{ "type": "header", "key": "accept", "value": "(.*?)text/markdown(.*)" }],
29+
"has": [
30+
{
31+
"type": "header",
32+
"key": "accept",
33+
"value": "(.*?)text/markdown(.*)"
34+
}
35+
],
836
"destination": "/raw/:path.md"
937
},
1038
{
1139
"source": "/:path((?!api|_nuxt|_v|__nuxt|search|code|raw/).*)",
12-
"has": [{ "type": "header", "key": "user-agent", "value": "curl/.*" }],
40+
"has": [
41+
{
42+
"type": "header",
43+
"key": "user-agent",
44+
"value": "curl/.*"
45+
}
46+
],
1347
"destination": "/raw/:path.md"
1448
}
1549
],

0 commit comments

Comments
 (0)