@tutti-os/workspace-file-preview 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-MAJHX2MV.js → chunk-FYAXIZ3F.js} +35 -1
- package/dist/chunk-FYAXIZ3F.js.map +1 -0
- package/dist/core/index.d.ts +13 -2
- package/dist/core/index.js +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/react/index.d.ts +14 -1
- package/dist/react/index.js +46 -1
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-MAJHX2MV.js.map +0 -1
|
@@ -208,6 +208,16 @@ function resolveWorkspaceImageMimeType(pathOrName) {
|
|
|
208
208
|
return null;
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
|
+
function resolveWorkspaceVideoMimeType(pathOrName) {
|
|
212
|
+
switch (resolveWorkspaceFileExtension(pathOrName)) {
|
|
213
|
+
case "mp4":
|
|
214
|
+
return "video/mp4";
|
|
215
|
+
case "webm":
|
|
216
|
+
return "video/webm";
|
|
217
|
+
default:
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
211
221
|
function classifyWorkspaceFilePreviewKind(entry) {
|
|
212
222
|
if (entry.kind !== "file") {
|
|
213
223
|
return null;
|
|
@@ -216,6 +226,9 @@ function classifyWorkspaceFilePreviewKind(entry) {
|
|
|
216
226
|
if (resolveWorkspaceImageMimeType(name) !== null) {
|
|
217
227
|
return "image";
|
|
218
228
|
}
|
|
229
|
+
if (resolveWorkspaceVideoMimeType(name) !== null) {
|
|
230
|
+
return "video";
|
|
231
|
+
}
|
|
219
232
|
const normalizedName = name.trim().toLowerCase();
|
|
220
233
|
const extension = resolveWorkspaceFileExtension(name);
|
|
221
234
|
if (textExtensions.has(extension) || textFileNames.has(normalizedName)) {
|
|
@@ -286,6 +299,14 @@ function createWorkspaceFilePreviewLoadedState(input) {
|
|
|
286
299
|
status: "image"
|
|
287
300
|
};
|
|
288
301
|
}
|
|
302
|
+
if (input.target.fileKind === "video") {
|
|
303
|
+
return {
|
|
304
|
+
bytes: copyWorkspaceFilePreviewBytes(input.bytes),
|
|
305
|
+
contentType: input.contentType ?? resolveWorkspaceVideoMimeType(input.target.name) ?? "application/octet-stream",
|
|
306
|
+
entry: input.target,
|
|
307
|
+
status: "video"
|
|
308
|
+
};
|
|
309
|
+
}
|
|
289
310
|
try {
|
|
290
311
|
const content = decodeWorkspaceTextFile(input.bytes);
|
|
291
312
|
if (looksLikeBinaryText(content)) {
|
|
@@ -295,6 +316,13 @@ function createWorkspaceFilePreviewLoadedState(input) {
|
|
|
295
316
|
status: "readonly"
|
|
296
317
|
};
|
|
297
318
|
}
|
|
319
|
+
if (input.renderHtml && isWorkspaceHtmlFileName(input.target.name)) {
|
|
320
|
+
return {
|
|
321
|
+
content,
|
|
322
|
+
entry: input.target,
|
|
323
|
+
status: "html"
|
|
324
|
+
};
|
|
325
|
+
}
|
|
298
326
|
return {
|
|
299
327
|
content,
|
|
300
328
|
entry: input.target,
|
|
@@ -308,6 +336,11 @@ function createWorkspaceFilePreviewLoadedState(input) {
|
|
|
308
336
|
};
|
|
309
337
|
}
|
|
310
338
|
}
|
|
339
|
+
function isWorkspaceHtmlFileName(pathOrName) {
|
|
340
|
+
return browserOpenableHtmlExtensions.has(
|
|
341
|
+
resolveWorkspaceFileExtension(pathOrName)
|
|
342
|
+
);
|
|
343
|
+
}
|
|
311
344
|
function resolveWorkspaceFilePreviewName(entry) {
|
|
312
345
|
return entry.name?.trim() || entry.displayName?.trim() || entry.path.split("/").pop()?.trim() || entry.path;
|
|
313
346
|
}
|
|
@@ -374,6 +407,7 @@ export {
|
|
|
374
407
|
isWorkspaceFileBrowserOpenable,
|
|
375
408
|
shouldFilterVideoPlayersForOpenWith,
|
|
376
409
|
resolveWorkspaceImageMimeType,
|
|
410
|
+
resolveWorkspaceVideoMimeType,
|
|
377
411
|
classifyWorkspaceFilePreviewKind,
|
|
378
412
|
resolveWorkspaceFileActivationTarget,
|
|
379
413
|
resolveWorkspaceFilePreviewReadiness,
|
|
@@ -387,4 +421,4 @@ export {
|
|
|
387
421
|
looksLikeBinaryText,
|
|
388
422
|
formatWorkspacePreviewByteLimit
|
|
389
423
|
};
|
|
390
|
-
//# sourceMappingURL=chunk-
|
|
424
|
+
//# sourceMappingURL=chunk-FYAXIZ3F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/workspaceFilePreview.ts"],"sourcesContent":["export type WorkspaceFilePreviewEntryKind =\n | \"file\"\n | \"directory\"\n | \"folder\"\n | \"unknown\"\n | (string & {});\n\nexport type WorkspaceFilePreviewKind = \"image\" | \"text\" | \"video\";\n\nexport type WorkspaceFileVisualKind =\n | \"binary\"\n | \"code\"\n | \"directory\"\n | \"document\"\n | \"image\"\n | \"markdown\"\n | \"video\";\n\nexport interface WorkspaceFilePreviewEntry {\n displayName?: string;\n kind: WorkspaceFilePreviewEntryKind;\n mtimeMs?: number | null;\n name?: string;\n path: string;\n sizeBytes?: number | null;\n}\n\nexport interface WorkspaceFilePreviewActivationTarget {\n fileKind: WorkspaceFilePreviewKind;\n mtimeMs?: number | null;\n name: string;\n path: string;\n sizeBytes?: number | null;\n}\n\nexport type WorkspaceFilePreviewReadonlyReason =\n | \"binary\"\n | \"decode_failed\"\n | \"file_too_large\"\n | \"text_too_large\";\n\nexport type WorkspaceFilePreviewReadiness<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget =\n WorkspaceFilePreviewActivationTarget\n> =\n | { entry: TEntry; status: \"directory\" }\n | {\n entry: TEntry;\n maxSizeBytes: number;\n reason: Extract<\n WorkspaceFilePreviewReadonlyReason,\n \"file_too_large\" | \"text_too_large\"\n >;\n status: \"readonly\";\n }\n | { entry: TEntry; status: \"unsupported\" }\n | { entry: TEntry; status: \"ready\"; target: TTarget };\n\nexport type WorkspaceFilePreviewLoadedState<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget\n> =\n | { content: string; entry: TTarget; status: \"text\" }\n | { content: string; entry: TTarget; status: \"html\" }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string;\n entry: TTarget;\n status: \"image\";\n }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string;\n entry: TTarget;\n status: \"video\";\n }\n | {\n entry: TEntry;\n maxSizeBytes?: number;\n reason: WorkspaceFilePreviewReadonlyReason;\n status: \"readonly\";\n };\n\nconst imageExtensions = new Set([\n \"avif\",\n \"gif\",\n \"jpeg\",\n \"jpg\",\n \"png\",\n \"svg\",\n \"webp\"\n]);\nconst browserOpenableHtmlExtensions = new Set([\n \"htm\",\n \"html\",\n \"shtml\",\n \"xhtml\"\n]);\nconst browserOpenableVideoExtensions = new Set([\"mp4\", \"webm\"]);\n\nconst videoExtensions = new Set([\n \"avi\",\n \"m2ts\",\n \"mkv\",\n \"mov\",\n \"mp4\",\n \"mpeg\",\n \"mpg\",\n \"mts\",\n \"webm\",\n \"wmv\"\n]);\n/**\n * Extensions where macOS Launch Services may register video handlers even when\n * the workspace file is source code (UTI / uniform type collisions).\n */\nexport const workspaceFileVideoHandlerCollisionExtensions = new Set([\"ts\"]);\nconst markdownExtensions = new Set([\"md\", \"mdx\"]);\nconst codeExtensions = new Set([\n \"bash\",\n \"c\",\n \"cc\",\n \"conf\",\n \"cpp\",\n \"cs\",\n \"css\",\n \"go\",\n \"h\",\n \"hpp\",\n \"html\",\n \"java\",\n \"js\",\n \"jsx\",\n \"json\",\n \"lua\",\n \"m\",\n \"mm\",\n \"php\",\n \"plist\",\n \"proto\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"swift\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"xml\",\n \"yaml\",\n \"yml\",\n \"zsh\"\n]);\nconst documentExtensions = new Set([\n \"csv\",\n \"doc\",\n \"docx\",\n \"log\",\n \"pdf\",\n \"rtf\",\n \"txt\",\n \"xls\",\n \"xlsx\"\n]);\nconst textExtensions = new Set([\n \"bash\",\n \"c\",\n \"cc\",\n \"conf\",\n \"cpp\",\n \"cs\",\n \"css\",\n \"csv\",\n \"env\",\n \"go\",\n \"h\",\n \"hpp\",\n \"html\",\n \"ini\",\n \"java\",\n \"js\",\n \"json\",\n \"jsx\",\n \"log\",\n \"lua\",\n \"m\",\n \"md\",\n \"mdx\",\n \"mm\",\n \"php\",\n \"plist\",\n \"proto\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"swift\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"txt\",\n \"xml\",\n \"yaml\",\n \"yml\",\n \"zsh\"\n]);\nconst textFileNames = new Set([\n \".gitignore\",\n \".npmrc\",\n \".nvmrc\",\n \"dockerfile\",\n \"makefile\",\n \"readme\"\n]);\n\nexport const workspaceFileTextMaxBytes = 1024 * 1024;\nexport const workspaceFilePreviewMaxBytes = 20 * 1024 * 1024;\n\nexport function resolveWorkspaceFileVisualKind(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): WorkspaceFileVisualKind {\n if (entry.kind === \"directory\" || entry.kind === \"folder\") {\n return \"directory\";\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (imageExtensions.has(extension)) {\n return \"image\";\n }\n if (videoExtensions.has(extension)) {\n return \"video\";\n }\n if (markdownExtensions.has(extension)) {\n return \"markdown\";\n }\n if (codeExtensions.has(extension)) {\n return \"code\";\n }\n if (documentExtensions.has(extension)) {\n return \"document\";\n }\n return \"binary\";\n}\n\nexport function resolveWorkspaceFileExtension(pathOrName: string): string {\n const name = pathOrName.split(\"/\").pop()?.trim().toLowerCase() ?? \"\";\n const dotIndex = name.lastIndexOf(\".\");\n return dotIndex > 0 ? name.slice(dotIndex + 1) : \"\";\n}\n\nexport function isWorkspaceFileBrowserOpenable(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): boolean {\n if (entry.kind !== \"file\") {\n return false;\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (\n extension === \"pdf\" ||\n browserOpenableHtmlExtensions.has(extension) ||\n imageExtensions.has(extension) ||\n browserOpenableVideoExtensions.has(extension)\n ) {\n return true;\n }\n\n return classifyWorkspaceFilePreviewKind(entry) === \"text\";\n}\n\nexport function shouldFilterVideoPlayersForOpenWith(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): boolean {\n if (entry.kind !== \"file\") {\n return false;\n }\n\n const visualKind = resolveWorkspaceFileVisualKind(entry);\n if (visualKind === \"video\") {\n return false;\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (workspaceFileVideoHandlerCollisionExtensions.has(extension)) {\n return true;\n }\n\n if (visualKind === \"code\" || visualKind === \"markdown\") {\n return true;\n }\n\n return classifyWorkspaceFilePreviewKind(entry) === \"text\";\n}\n\nexport function resolveWorkspaceImageMimeType(\n pathOrName: string\n): string | null {\n switch (resolveWorkspaceFileExtension(pathOrName)) {\n case \"avif\":\n return \"image/avif\";\n case \"gif\":\n return \"image/gif\";\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"svg\":\n return \"image/svg+xml\";\n case \"webp\":\n return \"image/webp\";\n default:\n return null;\n }\n}\n\nexport function resolveWorkspaceVideoMimeType(\n pathOrName: string\n): string | null {\n switch (resolveWorkspaceFileExtension(pathOrName)) {\n case \"mp4\":\n return \"video/mp4\";\n case \"webm\":\n return \"video/webm\";\n default:\n return null;\n }\n}\n\nexport function classifyWorkspaceFilePreviewKind(\n entry: Pick<\n WorkspaceFilePreviewEntry,\n \"displayName\" | \"kind\" | \"name\" | \"path\"\n >\n): WorkspaceFilePreviewKind | null {\n if (entry.kind !== \"file\") {\n return null;\n }\n\n const name = resolveWorkspaceFilePreviewName(entry);\n if (resolveWorkspaceImageMimeType(name) !== null) {\n return \"image\";\n }\n if (resolveWorkspaceVideoMimeType(name) !== null) {\n return \"video\";\n }\n\n const normalizedName = name.trim().toLowerCase();\n const extension = resolveWorkspaceFileExtension(name);\n if (textExtensions.has(extension) || textFileNames.has(normalizedName)) {\n return \"text\";\n }\n\n return null;\n}\n\nexport function resolveWorkspaceFileActivationTarget(\n entry: WorkspaceFilePreviewEntry\n): WorkspaceFilePreviewActivationTarget | null {\n const fileKind = classifyWorkspaceFilePreviewKind(entry);\n if (!fileKind) {\n return null;\n }\n\n const target: WorkspaceFilePreviewActivationTarget = {\n fileKind,\n name: resolveWorkspaceFilePreviewName(entry),\n path: entry.path\n };\n if (entry.mtimeMs !== undefined) {\n target.mtimeMs = entry.mtimeMs;\n }\n if (entry.sizeBytes !== undefined) {\n target.sizeBytes = entry.sizeBytes;\n }\n return target;\n}\n\nexport function resolveWorkspaceFilePreviewReadiness<\n TEntry extends WorkspaceFilePreviewEntry\n>(entry: TEntry): WorkspaceFilePreviewReadiness<TEntry> {\n if (entry.kind === \"directory\" || entry.kind === \"folder\") {\n return {\n entry,\n status: \"directory\"\n };\n }\n\n const target = resolveWorkspaceFileActivationTarget(entry);\n if (!target) {\n return {\n entry,\n status: \"unsupported\"\n };\n }\n\n if (\n target.fileKind === \"text\" &&\n isWorkspaceTextFileTooLarge(entry.sizeBytes)\n ) {\n return {\n entry,\n maxSizeBytes: workspaceFileTextMaxBytes,\n reason: \"text_too_large\",\n status: \"readonly\"\n };\n }\n\n if (isWorkspacePreviewFileTooLarge(entry.sizeBytes)) {\n return {\n entry,\n maxSizeBytes: workspaceFilePreviewMaxBytes,\n reason: \"file_too_large\",\n status: \"readonly\"\n };\n }\n\n return {\n entry,\n status: \"ready\",\n target\n };\n}\n\nexport function createWorkspaceFilePreviewLoadedState<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget\n>(input: {\n bytes: Uint8Array | ArrayBuffer;\n contentType?: string | null;\n entry: TEntry;\n renderHtml?: boolean;\n target: TTarget;\n}): WorkspaceFilePreviewLoadedState<TEntry, TTarget> {\n if (input.target.fileKind === \"image\") {\n return {\n bytes: copyWorkspaceFilePreviewBytes(input.bytes),\n contentType:\n input.contentType ??\n resolveWorkspaceImageMimeType(input.target.name) ??\n \"application/octet-stream\",\n entry: input.target,\n status: \"image\"\n };\n }\n if (input.target.fileKind === \"video\") {\n return {\n bytes: copyWorkspaceFilePreviewBytes(input.bytes),\n contentType:\n input.contentType ??\n resolveWorkspaceVideoMimeType(input.target.name) ??\n \"application/octet-stream\",\n entry: input.target,\n status: \"video\"\n };\n }\n\n try {\n const content = decodeWorkspaceTextFile(input.bytes);\n if (looksLikeBinaryText(content)) {\n return {\n entry: input.entry,\n reason: \"binary\",\n status: \"readonly\"\n };\n }\n if (input.renderHtml && isWorkspaceHtmlFileName(input.target.name)) {\n return {\n content,\n entry: input.target,\n status: \"html\"\n };\n }\n return {\n content,\n entry: input.target,\n status: \"text\"\n };\n } catch {\n return {\n entry: input.entry,\n reason: \"decode_failed\",\n status: \"readonly\"\n };\n }\n}\n\nfunction isWorkspaceHtmlFileName(pathOrName: string): boolean {\n return browserOpenableHtmlExtensions.has(\n resolveWorkspaceFileExtension(pathOrName)\n );\n}\n\nexport function resolveWorkspaceFilePreviewName(\n entry: Pick<WorkspaceFilePreviewEntry, \"displayName\" | \"name\" | \"path\">\n): string {\n return (\n entry.name?.trim() ||\n entry.displayName?.trim() ||\n entry.path.split(\"/\").pop()?.trim() ||\n entry.path\n );\n}\n\nexport function isWorkspaceTextFileTooLarge(\n sizeBytes?: number | null\n): boolean {\n return (\n typeof sizeBytes === \"number\" &&\n Number.isFinite(sizeBytes) &&\n sizeBytes > workspaceFileTextMaxBytes\n );\n}\n\nexport function isWorkspacePreviewFileTooLarge(\n sizeBytes?: number | null\n): boolean {\n return (\n typeof sizeBytes === \"number\" &&\n Number.isFinite(sizeBytes) &&\n sizeBytes > workspaceFilePreviewMaxBytes\n );\n}\n\nexport function decodeWorkspaceTextFile(\n bytes: Uint8Array | ArrayBuffer\n): string {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n normalizeWorkspaceFilePreviewBytes(bytes)\n );\n}\n\nexport function normalizeWorkspaceFilePreviewBytes(\n value: Uint8Array | ArrayBuffer\n): Uint8Array {\n if (value instanceof Uint8Array) {\n return value;\n }\n return new Uint8Array(value);\n}\n\nexport function copyWorkspaceFilePreviewBytes(\n bytes: Uint8Array | ArrayBuffer\n): Uint8Array<ArrayBuffer> {\n const normalized = normalizeWorkspaceFilePreviewBytes(bytes);\n const buffer = new ArrayBuffer(normalized.byteLength);\n const copy = new Uint8Array(buffer);\n copy.set(normalized);\n return copy;\n}\n\nexport function looksLikeBinaryText(content: string): boolean {\n if (content.length === 0) {\n return false;\n }\n\n const sample = content.slice(0, 4096);\n if (sample.includes(\"\\u0000\")) {\n return true;\n }\n\n let suspiciousControlChars = 0;\n for (let index = 0; index < sample.length; index += 1) {\n const code = sample.charCodeAt(index);\n const isAllowedWhitespace = code === 9 || code === 10 || code === 13;\n const isControlChar = code < 32 || (code >= 127 && code <= 159);\n if (isControlChar && !isAllowedWhitespace) {\n suspiciousControlChars += 1;\n }\n }\n\n return suspiciousControlChars / sample.length > 0.12;\n}\n\nexport function formatWorkspacePreviewByteLimit(sizeBytes: number): string {\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n const mebibytes = sizeBytes / (1024 * 1024);\n if (Number.isInteger(mebibytes)) {\n return `${mebibytes} MiB`;\n }\n return `${mebibytes.toFixed(1)} MiB`;\n}\n"],"mappings":"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","names":[]}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
type WorkspaceFilePreviewEntryKind = "file" | "directory" | "folder" | "unknown" | (string & {});
|
|
2
|
-
type WorkspaceFilePreviewKind = "image" | "text";
|
|
2
|
+
type WorkspaceFilePreviewKind = "image" | "text" | "video";
|
|
3
3
|
type WorkspaceFileVisualKind = "binary" | "code" | "directory" | "document" | "image" | "markdown" | "video";
|
|
4
4
|
interface WorkspaceFilePreviewEntry {
|
|
5
5
|
displayName?: string;
|
|
@@ -37,11 +37,20 @@ type WorkspaceFilePreviewLoadedState<TEntry extends WorkspaceFilePreviewEntry, T
|
|
|
37
37
|
content: string;
|
|
38
38
|
entry: TTarget;
|
|
39
39
|
status: "text";
|
|
40
|
+
} | {
|
|
41
|
+
content: string;
|
|
42
|
+
entry: TTarget;
|
|
43
|
+
status: "html";
|
|
40
44
|
} | {
|
|
41
45
|
bytes: Uint8Array<ArrayBuffer>;
|
|
42
46
|
contentType: string;
|
|
43
47
|
entry: TTarget;
|
|
44
48
|
status: "image";
|
|
49
|
+
} | {
|
|
50
|
+
bytes: Uint8Array<ArrayBuffer>;
|
|
51
|
+
contentType: string;
|
|
52
|
+
entry: TTarget;
|
|
53
|
+
status: "video";
|
|
45
54
|
} | {
|
|
46
55
|
entry: TEntry;
|
|
47
56
|
maxSizeBytes?: number;
|
|
@@ -60,6 +69,7 @@ declare function resolveWorkspaceFileExtension(pathOrName: string): string;
|
|
|
60
69
|
declare function isWorkspaceFileBrowserOpenable(entry: Pick<WorkspaceFilePreviewEntry, "kind" | "name" | "path">): boolean;
|
|
61
70
|
declare function shouldFilterVideoPlayersForOpenWith(entry: Pick<WorkspaceFilePreviewEntry, "kind" | "name" | "path">): boolean;
|
|
62
71
|
declare function resolveWorkspaceImageMimeType(pathOrName: string): string | null;
|
|
72
|
+
declare function resolveWorkspaceVideoMimeType(pathOrName: string): string | null;
|
|
63
73
|
declare function classifyWorkspaceFilePreviewKind(entry: Pick<WorkspaceFilePreviewEntry, "displayName" | "kind" | "name" | "path">): WorkspaceFilePreviewKind | null;
|
|
64
74
|
declare function resolveWorkspaceFileActivationTarget(entry: WorkspaceFilePreviewEntry): WorkspaceFilePreviewActivationTarget | null;
|
|
65
75
|
declare function resolveWorkspaceFilePreviewReadiness<TEntry extends WorkspaceFilePreviewEntry>(entry: TEntry): WorkspaceFilePreviewReadiness<TEntry>;
|
|
@@ -67,6 +77,7 @@ declare function createWorkspaceFilePreviewLoadedState<TEntry extends WorkspaceF
|
|
|
67
77
|
bytes: Uint8Array | ArrayBuffer;
|
|
68
78
|
contentType?: string | null;
|
|
69
79
|
entry: TEntry;
|
|
80
|
+
renderHtml?: boolean;
|
|
70
81
|
target: TTarget;
|
|
71
82
|
}): WorkspaceFilePreviewLoadedState<TEntry, TTarget>;
|
|
72
83
|
declare function resolveWorkspaceFilePreviewName(entry: Pick<WorkspaceFilePreviewEntry, "displayName" | "name" | "path">): string;
|
|
@@ -78,4 +89,4 @@ declare function copyWorkspaceFilePreviewBytes(bytes: Uint8Array | ArrayBuffer):
|
|
|
78
89
|
declare function looksLikeBinaryText(content: string): boolean;
|
|
79
90
|
declare function formatWorkspacePreviewByteLimit(sizeBytes: number): string;
|
|
80
91
|
|
|
81
|
-
export { type WorkspaceFilePreviewActivationTarget, type WorkspaceFilePreviewEntry, type WorkspaceFilePreviewEntryKind, type WorkspaceFilePreviewKind, type WorkspaceFilePreviewLoadedState, type WorkspaceFilePreviewReadiness, type WorkspaceFilePreviewReadonlyReason, type WorkspaceFileVisualKind, classifyWorkspaceFilePreviewKind, copyWorkspaceFilePreviewBytes, createWorkspaceFilePreviewLoadedState, decodeWorkspaceTextFile, formatWorkspacePreviewByteLimit, isWorkspaceFileBrowserOpenable, isWorkspacePreviewFileTooLarge, isWorkspaceTextFileTooLarge, looksLikeBinaryText, normalizeWorkspaceFilePreviewBytes, resolveWorkspaceFileActivationTarget, resolveWorkspaceFileExtension, resolveWorkspaceFilePreviewName, resolveWorkspaceFilePreviewReadiness, resolveWorkspaceFileVisualKind, resolveWorkspaceImageMimeType, shouldFilterVideoPlayersForOpenWith, workspaceFilePreviewMaxBytes, workspaceFileTextMaxBytes, workspaceFileVideoHandlerCollisionExtensions };
|
|
92
|
+
export { type WorkspaceFilePreviewActivationTarget, type WorkspaceFilePreviewEntry, type WorkspaceFilePreviewEntryKind, type WorkspaceFilePreviewKind, type WorkspaceFilePreviewLoadedState, type WorkspaceFilePreviewReadiness, type WorkspaceFilePreviewReadonlyReason, type WorkspaceFileVisualKind, classifyWorkspaceFilePreviewKind, copyWorkspaceFilePreviewBytes, createWorkspaceFilePreviewLoadedState, decodeWorkspaceTextFile, formatWorkspacePreviewByteLimit, isWorkspaceFileBrowserOpenable, isWorkspacePreviewFileTooLarge, isWorkspaceTextFileTooLarge, looksLikeBinaryText, normalizeWorkspaceFilePreviewBytes, resolveWorkspaceFileActivationTarget, resolveWorkspaceFileExtension, resolveWorkspaceFilePreviewName, resolveWorkspaceFilePreviewReadiness, resolveWorkspaceFileVisualKind, resolveWorkspaceImageMimeType, resolveWorkspaceVideoMimeType, shouldFilterVideoPlayersForOpenWith, workspaceFilePreviewMaxBytes, workspaceFileTextMaxBytes, workspaceFileVideoHandlerCollisionExtensions };
|
package/dist/core/index.js
CHANGED
|
@@ -15,11 +15,12 @@ import {
|
|
|
15
15
|
resolveWorkspaceFilePreviewReadiness,
|
|
16
16
|
resolveWorkspaceFileVisualKind,
|
|
17
17
|
resolveWorkspaceImageMimeType,
|
|
18
|
+
resolveWorkspaceVideoMimeType,
|
|
18
19
|
shouldFilterVideoPlayersForOpenWith,
|
|
19
20
|
workspaceFilePreviewMaxBytes,
|
|
20
21
|
workspaceFileTextMaxBytes,
|
|
21
22
|
workspaceFileVideoHandlerCollisionExtensions
|
|
22
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-FYAXIZ3F.js";
|
|
23
24
|
export {
|
|
24
25
|
classifyWorkspaceFilePreviewKind,
|
|
25
26
|
copyWorkspaceFilePreviewBytes,
|
|
@@ -37,6 +38,7 @@ export {
|
|
|
37
38
|
resolveWorkspaceFilePreviewReadiness,
|
|
38
39
|
resolveWorkspaceFileVisualKind,
|
|
39
40
|
resolveWorkspaceImageMimeType,
|
|
41
|
+
resolveWorkspaceVideoMimeType,
|
|
40
42
|
shouldFilterVideoPlayersForOpenWith,
|
|
41
43
|
workspaceFilePreviewMaxBytes,
|
|
42
44
|
workspaceFileTextMaxBytes,
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { WorkspaceFilePreviewActivationTarget, WorkspaceFilePreviewEntry, WorkspaceFilePreviewEntryKind, WorkspaceFilePreviewKind, WorkspaceFilePreviewLoadedState, WorkspaceFilePreviewReadiness, WorkspaceFilePreviewReadonlyReason, WorkspaceFileVisualKind, classifyWorkspaceFilePreviewKind, copyWorkspaceFilePreviewBytes, createWorkspaceFilePreviewLoadedState, decodeWorkspaceTextFile, formatWorkspacePreviewByteLimit, isWorkspaceFileBrowserOpenable, isWorkspacePreviewFileTooLarge, isWorkspaceTextFileTooLarge, looksLikeBinaryText, normalizeWorkspaceFilePreviewBytes, resolveWorkspaceFileActivationTarget, resolveWorkspaceFileExtension, resolveWorkspaceFilePreviewName, resolveWorkspaceFilePreviewReadiness, resolveWorkspaceFileVisualKind, resolveWorkspaceImageMimeType, shouldFilterVideoPlayersForOpenWith, workspaceFilePreviewMaxBytes, workspaceFileTextMaxBytes, workspaceFileVideoHandlerCollisionExtensions } from './core/index.js';
|
|
1
|
+
export { WorkspaceFilePreviewActivationTarget, WorkspaceFilePreviewEntry, WorkspaceFilePreviewEntryKind, WorkspaceFilePreviewKind, WorkspaceFilePreviewLoadedState, WorkspaceFilePreviewReadiness, WorkspaceFilePreviewReadonlyReason, WorkspaceFileVisualKind, classifyWorkspaceFilePreviewKind, copyWorkspaceFilePreviewBytes, createWorkspaceFilePreviewLoadedState, decodeWorkspaceTextFile, formatWorkspacePreviewByteLimit, isWorkspaceFileBrowserOpenable, isWorkspacePreviewFileTooLarge, isWorkspaceTextFileTooLarge, looksLikeBinaryText, normalizeWorkspaceFilePreviewBytes, resolveWorkspaceFileActivationTarget, resolveWorkspaceFileExtension, resolveWorkspaceFilePreviewName, resolveWorkspaceFilePreviewReadiness, resolveWorkspaceFileVisualKind, resolveWorkspaceImageMimeType, resolveWorkspaceVideoMimeType, shouldFilterVideoPlayersForOpenWith, workspaceFilePreviewMaxBytes, workspaceFileTextMaxBytes, workspaceFileVideoHandlerCollisionExtensions } from './core/index.js';
|
package/dist/index.js
CHANGED
|
@@ -15,11 +15,12 @@ import {
|
|
|
15
15
|
resolveWorkspaceFilePreviewReadiness,
|
|
16
16
|
resolveWorkspaceFileVisualKind,
|
|
17
17
|
resolveWorkspaceImageMimeType,
|
|
18
|
+
resolveWorkspaceVideoMimeType,
|
|
18
19
|
shouldFilterVideoPlayersForOpenWith,
|
|
19
20
|
workspaceFilePreviewMaxBytes,
|
|
20
21
|
workspaceFileTextMaxBytes,
|
|
21
22
|
workspaceFileVideoHandlerCollisionExtensions
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-FYAXIZ3F.js";
|
|
23
24
|
export {
|
|
24
25
|
classifyWorkspaceFilePreviewKind,
|
|
25
26
|
copyWorkspaceFilePreviewBytes,
|
|
@@ -37,6 +38,7 @@ export {
|
|
|
37
38
|
resolveWorkspaceFilePreviewReadiness,
|
|
38
39
|
resolveWorkspaceFileVisualKind,
|
|
39
40
|
resolveWorkspaceImageMimeType,
|
|
41
|
+
resolveWorkspaceVideoMimeType,
|
|
40
42
|
shouldFilterVideoPlayersForOpenWith,
|
|
41
43
|
workspaceFilePreviewMaxBytes,
|
|
42
44
|
workspaceFileTextMaxBytes,
|
package/dist/react/index.d.ts
CHANGED
|
@@ -12,10 +12,18 @@ type WorkspaceFilePreviewSurfaceState<TEntry> = {
|
|
|
12
12
|
content: string;
|
|
13
13
|
entry: TEntry;
|
|
14
14
|
status: "text";
|
|
15
|
+
} | {
|
|
16
|
+
content: string;
|
|
17
|
+
entry: TEntry;
|
|
18
|
+
status: "html";
|
|
15
19
|
} | {
|
|
16
20
|
entry: TEntry;
|
|
17
21
|
objectUrl: string;
|
|
18
22
|
status: "image";
|
|
23
|
+
} | {
|
|
24
|
+
entry: TEntry;
|
|
25
|
+
objectUrl: string;
|
|
26
|
+
status: "video";
|
|
19
27
|
} | {
|
|
20
28
|
entry: TEntry;
|
|
21
29
|
message: string;
|
|
@@ -33,6 +41,9 @@ interface WorkspaceFilePreviewSurfaceProps<TEntry> {
|
|
|
33
41
|
directoryMessage: string;
|
|
34
42
|
emptyMessage: string;
|
|
35
43
|
frameClassName: string;
|
|
44
|
+
htmlClassName?: string;
|
|
45
|
+
htmlFrameClassName?: string;
|
|
46
|
+
htmlTitle?: (entry: TEntry) => string;
|
|
36
47
|
imageAlt: (entry: TEntry) => string;
|
|
37
48
|
imageFrameClassName?: string;
|
|
38
49
|
imageClassName?: string;
|
|
@@ -43,7 +54,9 @@ interface WorkspaceFilePreviewSurfaceProps<TEntry> {
|
|
|
43
54
|
state: WorkspaceFilePreviewSurfaceState<TEntry>;
|
|
44
55
|
textClassName?: string;
|
|
45
56
|
textFrameClassName?: string;
|
|
57
|
+
videoClassName?: string;
|
|
58
|
+
videoFrameClassName?: string;
|
|
46
59
|
}
|
|
47
|
-
declare function WorkspaceFilePreviewSurface<TEntry>({ directoryMessage, emptyMessage, frameClassName, imageAlt, imageClassName, imageFrameClassName, loadingIndicator, loadingMessage, messageClassName, renderIcon, state, textClassName, textFrameClassName }: WorkspaceFilePreviewSurfaceProps<TEntry>): ReactElement;
|
|
60
|
+
declare function WorkspaceFilePreviewSurface<TEntry>({ directoryMessage, emptyMessage, frameClassName, htmlClassName, htmlFrameClassName, htmlTitle, imageAlt, imageClassName, imageFrameClassName, loadingIndicator, loadingMessage, messageClassName, renderIcon, state, textClassName, textFrameClassName, videoClassName, videoFrameClassName }: WorkspaceFilePreviewSurfaceProps<TEntry>): ReactElement;
|
|
48
61
|
|
|
49
62
|
export { WorkspaceFilePreviewSurface, type WorkspaceFilePreviewSurfaceProps, type WorkspaceFilePreviewSurfaceState };
|
package/dist/react/index.js
CHANGED
|
@@ -4,6 +4,9 @@ function WorkspaceFilePreviewSurface({
|
|
|
4
4
|
directoryMessage,
|
|
5
5
|
emptyMessage,
|
|
6
6
|
frameClassName,
|
|
7
|
+
htmlClassName = "h-full w-full border-0 bg-white",
|
|
8
|
+
htmlFrameClassName,
|
|
9
|
+
htmlTitle,
|
|
7
10
|
imageAlt,
|
|
8
11
|
imageClassName = "max-h-full max-w-full rounded-[6px] object-contain",
|
|
9
12
|
imageFrameClassName,
|
|
@@ -13,7 +16,9 @@ function WorkspaceFilePreviewSurface({
|
|
|
13
16
|
renderIcon,
|
|
14
17
|
state,
|
|
15
18
|
textClassName = "h-full overflow-auto p-4 text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]",
|
|
16
|
-
textFrameClassName
|
|
19
|
+
textFrameClassName,
|
|
20
|
+
videoClassName = "block max-h-full max-w-full rounded-[6px] object-contain",
|
|
21
|
+
videoFrameClassName
|
|
17
22
|
}) {
|
|
18
23
|
switch (state.status) {
|
|
19
24
|
case "directory":
|
|
@@ -49,6 +54,46 @@ function WorkspaceFilePreviewSurface({
|
|
|
49
54
|
children: /* @__PURE__ */ jsx("pre", { className: textClassName, children: state.content })
|
|
50
55
|
}
|
|
51
56
|
);
|
|
57
|
+
case "html":
|
|
58
|
+
return /* @__PURE__ */ jsx(
|
|
59
|
+
WorkspaceFilePreviewFrame,
|
|
60
|
+
{
|
|
61
|
+
className: joinClassNames(frameClassName, htmlFrameClassName),
|
|
62
|
+
children: /* @__PURE__ */ jsx(
|
|
63
|
+
"iframe",
|
|
64
|
+
{
|
|
65
|
+
className: htmlClassName,
|
|
66
|
+
sandbox: "allow-forms allow-scripts",
|
|
67
|
+
srcDoc: state.content,
|
|
68
|
+
title: htmlTitle?.(state.entry) ?? "HTML preview"
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
case "video":
|
|
74
|
+
return /* @__PURE__ */ jsx(
|
|
75
|
+
WorkspaceFilePreviewFrame,
|
|
76
|
+
{
|
|
77
|
+
className: joinClassNames(frameClassName, videoFrameClassName),
|
|
78
|
+
children: /* @__PURE__ */ jsx(
|
|
79
|
+
"video",
|
|
80
|
+
{
|
|
81
|
+
"aria-label": imageAlt(state.entry),
|
|
82
|
+
className: videoClassName,
|
|
83
|
+
muted: true,
|
|
84
|
+
playsInline: true,
|
|
85
|
+
preload: "metadata",
|
|
86
|
+
src: state.objectUrl,
|
|
87
|
+
onLoadedMetadata: (event) => {
|
|
88
|
+
const video = event.currentTarget;
|
|
89
|
+
if (video.duration > 0 && video.currentTime === 0) {
|
|
90
|
+
video.currentTime = Math.min(0.1, video.duration / 2);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
);
|
|
52
97
|
case "readonly":
|
|
53
98
|
case "unsupported":
|
|
54
99
|
case "error":
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/workspaceFilePreviewSurface.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\n\nexport type WorkspaceFilePreviewSurfaceState<TEntry> =\n | { status: \"empty\" }\n | { entry: TEntry; status: \"directory\" }\n | { entry: TEntry; status: \"loading\" }\n | { content: string; entry: TEntry; status: \"text\" }\n | { entry: TEntry; objectUrl: string; status: \"image\" }\n | { entry: TEntry; message: string; status: \"readonly\" }\n | { entry: TEntry; message: string; status: \"unsupported\" }\n | { entry: TEntry; message: string; status: \"error\" };\n\nexport interface WorkspaceFilePreviewSurfaceProps<TEntry> {\n directoryMessage: string;\n emptyMessage: string;\n frameClassName: string;\n imageAlt: (entry: TEntry) => string;\n imageFrameClassName?: string;\n imageClassName?: string;\n loadingIndicator: ReactNode;\n loadingMessage: string;\n messageClassName?: string;\n renderIcon: (entry: TEntry) => ReactNode;\n state: WorkspaceFilePreviewSurfaceState<TEntry>;\n textClassName?: string;\n textFrameClassName?: string;\n}\n\nexport function WorkspaceFilePreviewSurface<TEntry>({\n directoryMessage,\n emptyMessage,\n frameClassName,\n imageAlt,\n imageClassName = \"max-h-full max-w-full rounded-[6px] object-contain\",\n imageFrameClassName,\n loadingIndicator,\n loadingMessage,\n messageClassName = \"max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]\",\n renderIcon,\n state,\n textClassName = \"h-full overflow-auto p-4 text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]\",\n textFrameClassName\n}: WorkspaceFilePreviewSurfaceProps<TEntry>): ReactElement {\n switch (state.status) {\n case \"directory\":\n return (\n <WorkspaceFilePreviewFrame className={frameClassName}>\n <div className=\"flex flex-col items-center justify-center gap-2.5 text-center text-[13px] leading-5 text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span>{directoryMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"loading\":\n return (\n <WorkspaceFilePreviewFrame className={frameClassName}>\n <div className=\"space-y-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {loadingIndicator}\n <span>{loadingMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"image\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(frameClassName, imageFrameClassName)}\n >\n <img\n alt={imageAlt(state.entry)}\n className={imageClassName}\n src={state.objectUrl}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"text\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(frameClassName, textFrameClassName)}\n >\n <pre className={textClassName}>{state.content}</pre>\n </WorkspaceFilePreviewFrame>\n );\n case \"readonly\":\n case \"unsupported\":\n case \"error\":\n return (\n <WorkspaceFilePreviewFrame className={frameClassName}>\n <div className=\"flex flex-col items-center justify-center gap-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span className={messageClassName}>{state.message}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"empty\":\n return (\n <WorkspaceFilePreviewFrame className={frameClassName}>\n <span className={messageClassName}>{emptyMessage}</span>\n </WorkspaceFilePreviewFrame>\n );\n }\n}\n\nfunction WorkspaceFilePreviewFrame({\n children,\n className\n}: {\n children: ReactNode;\n className: string;\n}): ReactElement {\n return <div className={className}>{children}</div>;\n}\n\nfunction joinClassNames(\n ...classNames: Array<string | false | null | undefined>\n): string {\n return classNames.filter(Boolean).join(\" \");\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../../src/react/workspaceFilePreviewSurface.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\n\nexport type WorkspaceFilePreviewSurfaceState<TEntry> =\n | { status: \"empty\" }\n | { entry: TEntry; status: \"directory\" }\n | { entry: TEntry; status: \"loading\" }\n | { content: string; entry: TEntry; status: \"text\" }\n | { content: string; entry: TEntry; status: \"html\" }\n | { entry: TEntry; objectUrl: string; status: \"image\" }\n | { entry: TEntry; objectUrl: string; status: \"video\" }\n | { entry: TEntry; message: string; status: \"readonly\" }\n | { entry: TEntry; message: string; status: \"unsupported\" }\n | { entry: TEntry; message: string; status: \"error\" };\n\nexport interface WorkspaceFilePreviewSurfaceProps<TEntry> {\n directoryMessage: string;\n emptyMessage: string;\n frameClassName: string;\n htmlClassName?: string;\n htmlFrameClassName?: string;\n htmlTitle?: (entry: TEntry) => string;\n imageAlt: (entry: TEntry) => string;\n imageFrameClassName?: string;\n imageClassName?: string;\n loadingIndicator: ReactNode;\n loadingMessage: string;\n messageClassName?: string;\n renderIcon: (entry: TEntry) => ReactNode;\n state: WorkspaceFilePreviewSurfaceState<TEntry>;\n textClassName?: string;\n textFrameClassName?: string;\n videoClassName?: string;\n videoFrameClassName?: string;\n}\n\nexport function WorkspaceFilePreviewSurface<TEntry>({\n directoryMessage,\n emptyMessage,\n frameClassName,\n htmlClassName = \"h-full w-full border-0 bg-white\",\n htmlFrameClassName,\n htmlTitle,\n imageAlt,\n imageClassName = \"max-h-full max-w-full rounded-[6px] object-contain\",\n imageFrameClassName,\n loadingIndicator,\n loadingMessage,\n messageClassName = \"max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]\",\n renderIcon,\n state,\n textClassName = \"h-full overflow-auto p-4 text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]\",\n textFrameClassName,\n videoClassName = \"block max-h-full max-w-full rounded-[6px] object-contain\",\n videoFrameClassName\n}: WorkspaceFilePreviewSurfaceProps<TEntry>): ReactElement {\n switch (state.status) {\n case \"directory\":\n return (\n <WorkspaceFilePreviewFrame className={frameClassName}>\n <div className=\"flex flex-col items-center justify-center gap-2.5 text-center text-[13px] leading-5 text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span>{directoryMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"loading\":\n return (\n <WorkspaceFilePreviewFrame className={frameClassName}>\n <div className=\"space-y-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {loadingIndicator}\n <span>{loadingMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"image\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(frameClassName, imageFrameClassName)}\n >\n <img\n alt={imageAlt(state.entry)}\n className={imageClassName}\n src={state.objectUrl}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"text\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(frameClassName, textFrameClassName)}\n >\n <pre className={textClassName}>{state.content}</pre>\n </WorkspaceFilePreviewFrame>\n );\n case \"html\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(frameClassName, htmlFrameClassName)}\n >\n <iframe\n className={htmlClassName}\n sandbox=\"allow-forms allow-scripts\"\n srcDoc={state.content}\n title={htmlTitle?.(state.entry) ?? \"HTML preview\"}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"video\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(frameClassName, videoFrameClassName)}\n >\n <video\n aria-label={imageAlt(state.entry)}\n className={videoClassName}\n muted\n playsInline\n preload=\"metadata\"\n src={state.objectUrl}\n onLoadedMetadata={(event) => {\n const video = event.currentTarget;\n if (video.duration > 0 && video.currentTime === 0) {\n video.currentTime = Math.min(0.1, video.duration / 2);\n }\n }}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"readonly\":\n case \"unsupported\":\n case \"error\":\n return (\n <WorkspaceFilePreviewFrame className={frameClassName}>\n <div className=\"flex flex-col items-center justify-center gap-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span className={messageClassName}>{state.message}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"empty\":\n return (\n <WorkspaceFilePreviewFrame className={frameClassName}>\n <span className={messageClassName}>{emptyMessage}</span>\n </WorkspaceFilePreviewFrame>\n );\n }\n}\n\nfunction WorkspaceFilePreviewFrame({\n children,\n className\n}: {\n children: ReactNode;\n className: string;\n}): ReactElement {\n return <div className={className}>{children}</div>;\n}\n\nfunction joinClassNames(\n ...classNames: Array<string | false | null | undefined>\n): string {\n return classNames.filter(Boolean).join(\" \");\n}\n"],"mappings":";AA2DU,SAEE,KAFF;AAxBH,SAAS,4BAAoC;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA,iBAAiB;AAAA,EACjB;AACF,GAA2D;AACzD,UAAQ,MAAM,QAAQ;AAAA,IACpB,KAAK;AACH,aACE,oBAAC,6BAA0B,WAAW,gBACpC,+BAAC,SAAI,WAAU,mHACZ;AAAA,mBAAW,MAAM,KAAK;AAAA,QACvB,oBAAC,UAAM,4BAAiB;AAAA,SAC1B,GACF;AAAA,IAEJ,KAAK;AACH,aACE,oBAAC,6BAA0B,WAAW,gBACpC,+BAAC,SAAI,WAAU,sEACZ;AAAA;AAAA,QACD,oBAAC,UAAM,0BAAe;AAAA,SACxB,GACF;AAAA,IAEJ,KAAK;AACH,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,eAAe,gBAAgB,mBAAmB;AAAA,UAE7D;AAAA,YAAC;AAAA;AAAA,cACC,KAAK,SAAS,MAAM,KAAK;AAAA,cACzB,WAAW;AAAA,cACX,KAAK,MAAM;AAAA;AAAA,UACb;AAAA;AAAA,MACF;AAAA,IAEJ,KAAK;AACH,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,eAAe,gBAAgB,kBAAkB;AAAA,UAE5D,8BAAC,SAAI,WAAW,eAAgB,gBAAM,SAAQ;AAAA;AAAA,MAChD;AAAA,IAEJ,KAAK;AACH,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,eAAe,gBAAgB,kBAAkB;AAAA,UAE5D;AAAA,YAAC;AAAA;AAAA,cACC,WAAW;AAAA,cACX,SAAQ;AAAA,cACR,QAAQ,MAAM;AAAA,cACd,OAAO,YAAY,MAAM,KAAK,KAAK;AAAA;AAAA,UACrC;AAAA;AAAA,MACF;AAAA,IAEJ,KAAK;AACH,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,eAAe,gBAAgB,mBAAmB;AAAA,UAE7D;AAAA,YAAC;AAAA;AAAA,cACC,cAAY,SAAS,MAAM,KAAK;AAAA,cAChC,WAAW;AAAA,cACX,OAAK;AAAA,cACL,aAAW;AAAA,cACX,SAAQ;AAAA,cACR,KAAK,MAAM;AAAA,cACX,kBAAkB,CAAC,UAAU;AAC3B,sBAAM,QAAQ,MAAM;AACpB,oBAAI,MAAM,WAAW,KAAK,MAAM,gBAAgB,GAAG;AACjD,wBAAM,cAAc,KAAK,IAAI,KAAK,MAAM,WAAW,CAAC;AAAA,gBACtD;AAAA,cACF;AAAA;AAAA,UACF;AAAA;AAAA,MACF;AAAA,IAEJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,oBAAC,6BAA0B,WAAW,gBACpC,+BAAC,SAAI,WAAU,4GACZ;AAAA,mBAAW,MAAM,KAAK;AAAA,QACvB,oBAAC,UAAK,WAAW,kBAAmB,gBAAM,SAAQ;AAAA,SACpD,GACF;AAAA,IAEJ,KAAK;AACH,aACE,oBAAC,6BAA0B,WAAW,gBACpC,8BAAC,UAAK,WAAW,kBAAmB,wBAAa,GACnD;AAAA,EAEN;AACF;AAEA,SAAS,0BAA0B;AAAA,EACjC;AAAA,EACA;AACF,GAGiB;AACf,SAAO,oBAAC,SAAI,WAAuB,UAAS;AAC9C;AAEA,SAAS,kBACJ,YACK;AACR,SAAO,WAAW,OAAO,OAAO,EAAE,KAAK,GAAG;AAC5C;","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/workspaceFilePreview.ts"],"sourcesContent":["export type WorkspaceFilePreviewEntryKind =\n | \"file\"\n | \"directory\"\n | \"folder\"\n | \"unknown\"\n | (string & {});\n\nexport type WorkspaceFilePreviewKind = \"image\" | \"text\";\n\nexport type WorkspaceFileVisualKind =\n | \"binary\"\n | \"code\"\n | \"directory\"\n | \"document\"\n | \"image\"\n | \"markdown\"\n | \"video\";\n\nexport interface WorkspaceFilePreviewEntry {\n displayName?: string;\n kind: WorkspaceFilePreviewEntryKind;\n mtimeMs?: number | null;\n name?: string;\n path: string;\n sizeBytes?: number | null;\n}\n\nexport interface WorkspaceFilePreviewActivationTarget {\n fileKind: WorkspaceFilePreviewKind;\n mtimeMs?: number | null;\n name: string;\n path: string;\n sizeBytes?: number | null;\n}\n\nexport type WorkspaceFilePreviewReadonlyReason =\n | \"binary\"\n | \"decode_failed\"\n | \"file_too_large\"\n | \"text_too_large\";\n\nexport type WorkspaceFilePreviewReadiness<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget =\n WorkspaceFilePreviewActivationTarget\n> =\n | { entry: TEntry; status: \"directory\" }\n | {\n entry: TEntry;\n maxSizeBytes: number;\n reason: Extract<\n WorkspaceFilePreviewReadonlyReason,\n \"file_too_large\" | \"text_too_large\"\n >;\n status: \"readonly\";\n }\n | { entry: TEntry; status: \"unsupported\" }\n | { entry: TEntry; status: \"ready\"; target: TTarget };\n\nexport type WorkspaceFilePreviewLoadedState<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget\n> =\n | { content: string; entry: TTarget; status: \"text\" }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string;\n entry: TTarget;\n status: \"image\";\n }\n | {\n entry: TEntry;\n maxSizeBytes?: number;\n reason: WorkspaceFilePreviewReadonlyReason;\n status: \"readonly\";\n };\n\nconst imageExtensions = new Set([\n \"avif\",\n \"gif\",\n \"jpeg\",\n \"jpg\",\n \"png\",\n \"svg\",\n \"webp\"\n]);\nconst browserOpenableHtmlExtensions = new Set([\n \"htm\",\n \"html\",\n \"shtml\",\n \"xhtml\"\n]);\nconst browserOpenableVideoExtensions = new Set([\"mp4\", \"webm\"]);\n\nconst videoExtensions = new Set([\n \"avi\",\n \"m2ts\",\n \"mkv\",\n \"mov\",\n \"mp4\",\n \"mpeg\",\n \"mpg\",\n \"mts\",\n \"webm\",\n \"wmv\"\n]);\n/**\n * Extensions where macOS Launch Services may register video handlers even when\n * the workspace file is source code (UTI / uniform type collisions).\n */\nexport const workspaceFileVideoHandlerCollisionExtensions = new Set([\"ts\"]);\nconst markdownExtensions = new Set([\"md\", \"mdx\"]);\nconst codeExtensions = new Set([\n \"bash\",\n \"c\",\n \"cc\",\n \"conf\",\n \"cpp\",\n \"cs\",\n \"css\",\n \"go\",\n \"h\",\n \"hpp\",\n \"html\",\n \"java\",\n \"js\",\n \"jsx\",\n \"json\",\n \"lua\",\n \"m\",\n \"mm\",\n \"php\",\n \"plist\",\n \"proto\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"swift\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"xml\",\n \"yaml\",\n \"yml\",\n \"zsh\"\n]);\nconst documentExtensions = new Set([\n \"csv\",\n \"doc\",\n \"docx\",\n \"log\",\n \"pdf\",\n \"rtf\",\n \"txt\",\n \"xls\",\n \"xlsx\"\n]);\nconst textExtensions = new Set([\n \"bash\",\n \"c\",\n \"cc\",\n \"conf\",\n \"cpp\",\n \"cs\",\n \"css\",\n \"csv\",\n \"env\",\n \"go\",\n \"h\",\n \"hpp\",\n \"html\",\n \"ini\",\n \"java\",\n \"js\",\n \"json\",\n \"jsx\",\n \"log\",\n \"lua\",\n \"m\",\n \"md\",\n \"mdx\",\n \"mm\",\n \"php\",\n \"plist\",\n \"proto\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"swift\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"txt\",\n \"xml\",\n \"yaml\",\n \"yml\",\n \"zsh\"\n]);\nconst textFileNames = new Set([\n \".gitignore\",\n \".npmrc\",\n \".nvmrc\",\n \"dockerfile\",\n \"makefile\",\n \"readme\"\n]);\n\nexport const workspaceFileTextMaxBytes = 1024 * 1024;\nexport const workspaceFilePreviewMaxBytes = 20 * 1024 * 1024;\n\nexport function resolveWorkspaceFileVisualKind(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): WorkspaceFileVisualKind {\n if (entry.kind === \"directory\" || entry.kind === \"folder\") {\n return \"directory\";\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (imageExtensions.has(extension)) {\n return \"image\";\n }\n if (videoExtensions.has(extension)) {\n return \"video\";\n }\n if (markdownExtensions.has(extension)) {\n return \"markdown\";\n }\n if (codeExtensions.has(extension)) {\n return \"code\";\n }\n if (documentExtensions.has(extension)) {\n return \"document\";\n }\n return \"binary\";\n}\n\nexport function resolveWorkspaceFileExtension(pathOrName: string): string {\n const name = pathOrName.split(\"/\").pop()?.trim().toLowerCase() ?? \"\";\n const dotIndex = name.lastIndexOf(\".\");\n return dotIndex > 0 ? name.slice(dotIndex + 1) : \"\";\n}\n\nexport function isWorkspaceFileBrowserOpenable(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): boolean {\n if (entry.kind !== \"file\") {\n return false;\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (\n extension === \"pdf\" ||\n browserOpenableHtmlExtensions.has(extension) ||\n imageExtensions.has(extension) ||\n browserOpenableVideoExtensions.has(extension)\n ) {\n return true;\n }\n\n return classifyWorkspaceFilePreviewKind(entry) === \"text\";\n}\n\nexport function shouldFilterVideoPlayersForOpenWith(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): boolean {\n if (entry.kind !== \"file\") {\n return false;\n }\n\n const visualKind = resolveWorkspaceFileVisualKind(entry);\n if (visualKind === \"video\") {\n return false;\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (workspaceFileVideoHandlerCollisionExtensions.has(extension)) {\n return true;\n }\n\n if (visualKind === \"code\" || visualKind === \"markdown\") {\n return true;\n }\n\n return classifyWorkspaceFilePreviewKind(entry) === \"text\";\n}\n\nexport function resolveWorkspaceImageMimeType(\n pathOrName: string\n): string | null {\n switch (resolveWorkspaceFileExtension(pathOrName)) {\n case \"avif\":\n return \"image/avif\";\n case \"gif\":\n return \"image/gif\";\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"svg\":\n return \"image/svg+xml\";\n case \"webp\":\n return \"image/webp\";\n default:\n return null;\n }\n}\n\nexport function classifyWorkspaceFilePreviewKind(\n entry: Pick<\n WorkspaceFilePreviewEntry,\n \"displayName\" | \"kind\" | \"name\" | \"path\"\n >\n): WorkspaceFilePreviewKind | null {\n if (entry.kind !== \"file\") {\n return null;\n }\n\n const name = resolveWorkspaceFilePreviewName(entry);\n if (resolveWorkspaceImageMimeType(name) !== null) {\n return \"image\";\n }\n\n const normalizedName = name.trim().toLowerCase();\n const extension = resolveWorkspaceFileExtension(name);\n if (textExtensions.has(extension) || textFileNames.has(normalizedName)) {\n return \"text\";\n }\n\n return null;\n}\n\nexport function resolveWorkspaceFileActivationTarget(\n entry: WorkspaceFilePreviewEntry\n): WorkspaceFilePreviewActivationTarget | null {\n const fileKind = classifyWorkspaceFilePreviewKind(entry);\n if (!fileKind) {\n return null;\n }\n\n const target: WorkspaceFilePreviewActivationTarget = {\n fileKind,\n name: resolveWorkspaceFilePreviewName(entry),\n path: entry.path\n };\n if (entry.mtimeMs !== undefined) {\n target.mtimeMs = entry.mtimeMs;\n }\n if (entry.sizeBytes !== undefined) {\n target.sizeBytes = entry.sizeBytes;\n }\n return target;\n}\n\nexport function resolveWorkspaceFilePreviewReadiness<\n TEntry extends WorkspaceFilePreviewEntry\n>(entry: TEntry): WorkspaceFilePreviewReadiness<TEntry> {\n if (entry.kind === \"directory\" || entry.kind === \"folder\") {\n return {\n entry,\n status: \"directory\"\n };\n }\n\n const target = resolveWorkspaceFileActivationTarget(entry);\n if (!target) {\n return {\n entry,\n status: \"unsupported\"\n };\n }\n\n if (\n target.fileKind === \"text\" &&\n isWorkspaceTextFileTooLarge(entry.sizeBytes)\n ) {\n return {\n entry,\n maxSizeBytes: workspaceFileTextMaxBytes,\n reason: \"text_too_large\",\n status: \"readonly\"\n };\n }\n\n if (isWorkspacePreviewFileTooLarge(entry.sizeBytes)) {\n return {\n entry,\n maxSizeBytes: workspaceFilePreviewMaxBytes,\n reason: \"file_too_large\",\n status: \"readonly\"\n };\n }\n\n return {\n entry,\n status: \"ready\",\n target\n };\n}\n\nexport function createWorkspaceFilePreviewLoadedState<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget\n>(input: {\n bytes: Uint8Array | ArrayBuffer;\n contentType?: string | null;\n entry: TEntry;\n target: TTarget;\n}): WorkspaceFilePreviewLoadedState<TEntry, TTarget> {\n if (input.target.fileKind === \"image\") {\n return {\n bytes: copyWorkspaceFilePreviewBytes(input.bytes),\n contentType:\n input.contentType ??\n resolveWorkspaceImageMimeType(input.target.name) ??\n \"application/octet-stream\",\n entry: input.target,\n status: \"image\"\n };\n }\n\n try {\n const content = decodeWorkspaceTextFile(input.bytes);\n if (looksLikeBinaryText(content)) {\n return {\n entry: input.entry,\n reason: \"binary\",\n status: \"readonly\"\n };\n }\n return {\n content,\n entry: input.target,\n status: \"text\"\n };\n } catch {\n return {\n entry: input.entry,\n reason: \"decode_failed\",\n status: \"readonly\"\n };\n }\n}\n\nexport function resolveWorkspaceFilePreviewName(\n entry: Pick<WorkspaceFilePreviewEntry, \"displayName\" | \"name\" | \"path\">\n): string {\n return (\n entry.name?.trim() ||\n entry.displayName?.trim() ||\n entry.path.split(\"/\").pop()?.trim() ||\n entry.path\n );\n}\n\nexport function isWorkspaceTextFileTooLarge(\n sizeBytes?: number | null\n): boolean {\n return (\n typeof sizeBytes === \"number\" &&\n Number.isFinite(sizeBytes) &&\n sizeBytes > workspaceFileTextMaxBytes\n );\n}\n\nexport function isWorkspacePreviewFileTooLarge(\n sizeBytes?: number | null\n): boolean {\n return (\n typeof sizeBytes === \"number\" &&\n Number.isFinite(sizeBytes) &&\n sizeBytes > workspaceFilePreviewMaxBytes\n );\n}\n\nexport function decodeWorkspaceTextFile(\n bytes: Uint8Array | ArrayBuffer\n): string {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n normalizeWorkspaceFilePreviewBytes(bytes)\n );\n}\n\nexport function normalizeWorkspaceFilePreviewBytes(\n value: Uint8Array | ArrayBuffer\n): Uint8Array {\n if (value instanceof Uint8Array) {\n return value;\n }\n return new Uint8Array(value);\n}\n\nexport function copyWorkspaceFilePreviewBytes(\n bytes: Uint8Array | ArrayBuffer\n): Uint8Array<ArrayBuffer> {\n const normalized = normalizeWorkspaceFilePreviewBytes(bytes);\n const buffer = new ArrayBuffer(normalized.byteLength);\n const copy = new Uint8Array(buffer);\n copy.set(normalized);\n return copy;\n}\n\nexport function looksLikeBinaryText(content: string): boolean {\n if (content.length === 0) {\n return false;\n }\n\n const sample = content.slice(0, 4096);\n if (sample.includes(\"\\u0000\")) {\n return true;\n }\n\n let suspiciousControlChars = 0;\n for (let index = 0; index < sample.length; index += 1) {\n const code = sample.charCodeAt(index);\n const isAllowedWhitespace = code === 9 || code === 10 || code === 13;\n const isControlChar = code < 32 || (code >= 127 && code <= 159);\n if (isControlChar && !isAllowedWhitespace) {\n suspiciousControlChars += 1;\n }\n }\n\n return suspiciousControlChars / sample.length > 0.12;\n}\n\nexport function formatWorkspacePreviewByteLimit(sizeBytes: number): string {\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n const mebibytes = sizeBytes / (1024 * 1024);\n if (Number.isInteger(mebibytes)) {\n return `${mebibytes} MiB`;\n }\n return `${mebibytes.toFixed(1)} MiB`;\n}\n"],"mappings":"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","names":[]}
|