Skip to content

Commit c7914eb

Browse files
committed
feat: replace binary file estimation logic using content-type
1 parent e0629de commit c7914eb

3 files changed

Lines changed: 43 additions & 79 deletions

File tree

app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type {
44
PackageFileTreeResponse,
55
PackageFileContentResponse,
66
} from '#shared/types'
7-
import { isBinaryFilePath } from '~/utils/file-types'
87
98
definePageMeta({
109
name: 'code',
@@ -107,7 +106,12 @@ const isViewingFile = computed(() => currentNode.value?.type === 'file')
107106
// Maximum file size we'll try to load (500KB) - must match server
108107
const MAX_FILE_SIZE = 500 * 1024
109108
110-
const isBinaryFile = computed(() => !!filePath.value && isBinaryFilePath(filePath.value))
109+
// Estimate binary file based on mime type
110+
const isBinaryFile = computed(() => {
111+
const contentType = fileContent.value?.contentType
112+
if (!contentType) return false
113+
return isBinaryContentType(contentType)
114+
})
111115
112116
const isFileTooLarge = computed(() => {
113117
const size = currentNode.value?.size
@@ -117,13 +121,7 @@ const isFileTooLarge = computed(() => {
117121
// Fetch file content when a file is selected (and not too large)
118122
const fileContentUrl = computed(() => {
119123
// Don't fetch if no file path, file tree not loaded, file is too large, or it's a directory
120-
if (
121-
!filePath.value ||
122-
!fileTree.value ||
123-
isFileTooLarge.value ||
124-
!isViewingFile.value ||
125-
isBinaryFile.value
126-
) {
124+
if (!filePath.value || !fileTree.value || isFileTooLarge.value || !isViewingFile.value) {
127125
return null
128126
}
129127
return `/api/registry/file/${packageName.value}/v/${version.value}/${filePath.value}`
@@ -533,7 +531,13 @@ defineOgImageComponent('Default', {
533531
<div v-else-if="isViewingFile && isBinaryFile" class="py-20 text-center">
534532
<div class="i-lucide:binary w-12 h-12 mx-auto text-fg-subtle mb-4" />
535533
<p class="text-fg-muted mb-2">{{ $t('code.binary_file') }}</p>
536-
<p class="text-fg-subtle text-sm mb-4">{{ $t('code.binary_rendering_warning') }}</p>
534+
<p class="text-fg-subtle text-sm mb-4">
535+
{{
536+
$t('code.binary_rendering_warning', {
537+
contentType: fileContent?.contentType ?? 'unknown',
538+
})
539+
}}
540+
</p>
537541
<LinkBase
538542
variant="button-secondary"
539543
:to="`https://cdn.jsdelivr.net/npm/${packageName}@${version}/${filePath}`"

app/utils/file-types.ts

Lines changed: 28 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,31 @@
1-
// Extensions that are binary and cannot be meaningfully displayed as text
2-
const BINARY_EXTENSIONS = new Set([
3-
// Images
4-
'png',
5-
'jpg',
6-
'jpeg',
7-
'gif',
8-
'webp',
9-
'ico',
10-
'bmp',
11-
'tiff',
12-
'tif',
13-
'avif',
14-
'heic',
15-
'heif',
16-
// Fonts
17-
'woff',
18-
'woff2',
19-
'ttf',
20-
'otf',
21-
'eot',
22-
// Archives
23-
'zip',
24-
'tar',
25-
'gz',
26-
'tgz',
27-
'bz2',
28-
'xz',
29-
'7z',
30-
'rar',
31-
// Executables / compiled
32-
'exe',
33-
'dll',
34-
'so',
35-
'dylib',
36-
'node',
37-
'wasm',
38-
'pyc',
39-
'class',
40-
// Media
41-
'mp3',
42-
'mp4',
43-
'ogg',
44-
'wav',
45-
'avi',
46-
'mov',
47-
'webm',
48-
'flac',
49-
'aac',
50-
'mkv',
51-
// Documents
52-
'pdf',
53-
'doc',
54-
'docx',
55-
'xls',
56-
'xlsx',
57-
'ppt',
58-
'pptx',
59-
// Data
60-
'bin',
61-
'dat',
62-
'db',
63-
'sqlite',
64-
'sqlite3',
1+
// MIME types that are binary and cannot be meaningfully displayed as text
2+
const BINARY_MIME_PREFIXES = new Set([
3+
'image/',
4+
'audio/',
5+
'video/',
6+
'font/',
7+
'application/wasm',
8+
'application/pdf',
9+
'application/zip',
10+
'application/x-rar-compressed',
11+
'application/x-7z-compressed',
12+
'application/x-gzip',
13+
'application/x-tar',
14+
'application/x-bz2',
15+
'application/x-xz',
16+
'application/x-executable',
17+
'application/x-msdownload', // exe / dll
18+
'application/x-sharedlib', // so / dylib
19+
'application/msword', // .doc
20+
'application/vnd.',
21+
'application/octet-stream',
6522
])
6623

67-
export function isBinaryFilePath(filePath: string): boolean {
68-
const dotIndex = filePath.lastIndexOf('.')
69-
const ext = dotIndex > -1 ? filePath.slice(dotIndex + 1).toLowerCase() : ''
70-
return BINARY_EXTENSIONS.has(ext)
24+
export function isBinaryContentType(contentType: string): boolean {
25+
for (const prefix of BINARY_MIME_PREFIXES) {
26+
if (contentType.startsWith(prefix)) {
27+
return true
28+
}
29+
}
30+
return false
7131
}

i18n/locales/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@
794794
"file_path": "File path",
795795
"scroll_to_top": "Scroll to top",
796796
"binary_file": "Binary file",
797-
"binary_rendering_warning": "File type not supported for preview."
797+
"binary_rendering_warning": "File type \"{contentType}\" is not supported for preview."
798798
},
799799
"badges": {
800800
"provenance": {

0 commit comments

Comments
 (0)