diff --git a/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue b/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue
index cb1d3955d1..6a3cc71763 100644
--- a/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue
+++ b/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue
@@ -4,7 +4,6 @@ import type {
PackageFileTreeResponse,
PackageFileContentResponse,
} from '#shared/types'
-import { isBinaryFilePath } from '~/utils/file-types'
definePageMeta({
name: 'code',
@@ -107,7 +106,12 @@ const isViewingFile = computed(() => currentNode.value?.type === 'file')
// Maximum file size we'll try to load (500KB) - must match server
const MAX_FILE_SIZE = 500 * 1024
-const isBinaryFile = computed(() => !!filePath.value && isBinaryFilePath(filePath.value))
+// Estimate binary file based on mime type
+const isBinaryFile = computed(() => {
+ const contentType = fileContent.value?.contentType
+ if (!contentType) return false
+ return isBinaryContentType(contentType)
+})
const isFileTooLarge = computed(() => {
const size = currentNode.value?.size
@@ -117,13 +121,7 @@ const isFileTooLarge = computed(() => {
// Fetch file content when a file is selected (and not too large)
const fileContentUrl = computed(() => {
// Don't fetch if no file path, file tree not loaded, file is too large, or it's a directory
- if (
- !filePath.value ||
- !fileTree.value ||
- isFileTooLarge.value ||
- !isViewingFile.value ||
- isBinaryFile.value
- ) {
+ if (!filePath.value || !fileTree.value || isFileTooLarge.value || !isViewingFile.value) {
return null
}
return `/api/registry/file/${packageName.value}/v/${version.value}/${filePath.value}`
@@ -533,7 +531,13 @@ defineOgImageComponent('Default', {
{{ $t('code.binary_file') }}
-
{{ $t('code.binary_rendering_warning') }}
+
+ {{
+ $t('code.binary_rendering_warning', {
+ contentType: fileContent?.contentType ?? 'unknown',
+ })
+ }}
+
-1 ? filePath.slice(dotIndex + 1).toLowerCase() : ''
- return BINARY_EXTENSIONS.has(ext)
+export function isBinaryContentType(contentType: string): boolean {
+ for (const prefix of BINARY_MIME_PREFIXES) {
+ if (contentType.startsWith(prefix)) {
+ return true
+ }
+ }
+ return false
}
diff --git a/i18n/locales/en.json b/i18n/locales/en.json
index c187265c73..93957b3a22 100644
--- a/i18n/locales/en.json
+++ b/i18n/locales/en.json
@@ -794,7 +794,7 @@
"file_path": "File path",
"scroll_to_top": "Scroll to top",
"binary_file": "Binary file",
- "binary_rendering_warning": "File type not supported for preview."
+ "binary_rendering_warning": "File type \"{contentType}\" is not supported for preview."
},
"badges": {
"provenance": {
diff --git a/server/api/registry/file/[...pkg].get.ts b/server/api/registry/file/[...pkg].get.ts
index c1dd76c1b3..e3d0c37d2d 100644
--- a/server/api/registry/file/[...pkg].get.ts
+++ b/server/api/registry/file/[...pkg].get.ts
@@ -50,7 +50,7 @@ async function fetchFileContent(
packageName: string,
version: string,
filePath: string,
-): Promise {
+): Promise<{ content: string; contentType: string | null }> {
const url = `https://cdn.jsdelivr.net/npm/${packageName}@${version}/${filePath}`
const response = await fetch(url)
@@ -64,6 +64,8 @@ async function fetchFileContent(
})
}
+ const contentType = response.headers.get('content-type')
+
// Check content-length header if available
const contentLength = response.headers.get('content-length')
if (contentLength && parseInt(contentLength, 10) > MAX_FILE_SIZE) {
@@ -83,7 +85,7 @@ async function fetchFileContent(
})
}
- return content
+ return { content, contentType }
}
/**
@@ -123,7 +125,7 @@ export default defineCachedEventHandler(
filePath: rawFilePath,
})
- const content = await fetchFileContent(packageName, version, filePath)
+ const { content, contentType } = await fetchFileContent(packageName, version, filePath)
const language = getLanguageFromPath(filePath)
// For JS/TS files, resolve dependency versions and relative imports for linking
@@ -185,6 +187,7 @@ export default defineCachedEventHandler(
version,
path: filePath,
language,
+ contentType,
content,
html,
lines: content.split('\n').length,
diff --git a/shared/types/npm-registry.ts b/shared/types/npm-registry.ts
index 250a9218e6..629c9fbc20 100644
--- a/shared/types/npm-registry.ts
+++ b/shared/types/npm-registry.ts
@@ -381,6 +381,7 @@ export interface PackageFileContentResponse {
version: string
path: string
language: string
+ contentType: string | null
content: string
html: string
lines: number