Skip to content

Commit c69847e

Browse files
committed
fix(readme): fetch README from jsDelivr to avoid npm registry truncation
The npm registry truncates the packument readme field at exactly 65,536 characters, causing large READMEs to render incomplete. Fetch the actual README file from jsDelivr CDN (npm tarball) as the primary source, falling back to the packument field when jsDelivr doesn't have it. Closes #1458
1 parent c3090e0 commit c69847e

1 file changed

Lines changed: 16 additions & 40 deletions

File tree

server/api/registry/readme/[...pkg].get.ts

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@ const standardReadmeFilenames = [
1717
'readme.markdown',
1818
]
1919

20-
/** Matches standard README filenames (case-insensitive, for checking registry metadata) */
21-
const standardReadmePattern = /^readme(?:\.md|\.markdown)?$/i
22-
2320
/**
2421
* Fetch README from jsdelivr CDN for a specific package version.
2522
* Falls back through common README filenames.
@@ -71,42 +68,25 @@ export default defineCachedEventHandler(
7168
})
7269

7370
const packageData = await fetchNpmPackage(packageName)
74-
75-
let readmeContent: string | undefined
76-
let readmeFilename: string | undefined
77-
78-
// If a specific version is requested, get README from that version
79-
if (version) {
80-
const versionData = packageData.versions[version]
81-
if (versionData) {
82-
readmeContent = versionData.readme
83-
readmeFilename = versionData.readmeFilename
71+
const resolvedVersion = version ?? packageData['dist-tags']?.latest
72+
73+
// Prefer jsDelivr (actual file from npm tarball) over the packument readme field,
74+
// because the npm registry truncates readme content at 65,536 characters.
75+
let readmeContent = await fetchReadmeFromJsdelivr(
76+
packageName,
77+
standardReadmeFilenames,
78+
resolvedVersion,
79+
)
80+
81+
// Fall back to packument readme if jsDelivr didn't have it
82+
if (!readmeContent) {
83+
const packumentReadme = version ? packageData.versions[version]?.readme : packageData.readme
84+
if (packumentReadme && packumentReadme !== NPM_MISSING_README_SENTINEL) {
85+
readmeContent = packumentReadme
8486
}
85-
} else {
86-
// Use the packument-level readme (from latest version)
87-
readmeContent = packageData.readme
88-
readmeFilename = packageData.readmeFilename
8987
}
9088

91-
const hasValidNpmReadme = readmeContent && readmeContent !== NPM_MISSING_README_SENTINEL
92-
93-
// If no README in packument, or if readmeFilename is non-standard (e.g., README.zh-TW.md),
94-
// try fetching a standard README from jsdelivr (package tarball).
95-
// Note: When readmeFilename is missing, we defensively fetch from jsdelivr to ensure
96-
// we get a standard English README if one exists.
97-
if (!hasValidNpmReadme || !isStandardReadme(readmeFilename)) {
98-
const jsdelivrReadme = await fetchReadmeFromJsdelivr(
99-
packageName,
100-
standardReadmeFilenames,
101-
version,
102-
)
103-
// Only replace npm content if jsdelivr returned something
104-
if (jsdelivrReadme) {
105-
readmeContent = jsdelivrReadme
106-
}
107-
}
108-
109-
if (!readmeContent || readmeContent === NPM_MISSING_README_SENTINEL) {
89+
if (!readmeContent) {
11090
return { html: '', playgroundLinks: [], toc: [] }
11191
}
11292

@@ -130,7 +110,3 @@ export default defineCachedEventHandler(
130110
},
131111
},
132112
)
133-
134-
function isStandardReadme(filename: string | undefined): boolean {
135-
return !!filename && standardReadmePattern.test(filename)
136-
}

0 commit comments

Comments
 (0)