@lamberl-lee/file-preview 0.2.0 → 0.3.0
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/README.md +6 -0
- package/dist/LargeFileGate.d.ts +23 -3
- package/dist/LargeFileGate.js +44 -40
- package/dist/LargeFileGate.js.map +1 -1
- package/dist/PluginPreviewRenderer.d.ts +20 -1
- package/dist/PluginPreviewRenderer.js +51 -10
- package/dist/PluginPreviewRenderer.js.map +1 -1
- package/dist/PreviewErrorBoundary.d.ts +2 -0
- package/dist/PreviewErrorBoundary.js +11 -2
- package/dist/PreviewErrorBoundary.js.map +1 -1
- package/dist/core/detect-meta.d.ts +73 -0
- package/dist/core/detect-meta.js +81 -0
- package/dist/core/detect-meta.js.map +1 -0
- package/dist/core/magic-bytes.d.ts +56 -0
- package/dist/core/magic-bytes.js +97 -0
- package/dist/core/magic-bytes.js.map +1 -0
- package/dist/core/plugin.d.ts +2 -2
- package/dist/core/plugin.js +5 -3
- package/dist/core/plugin.js.map +1 -1
- package/dist/core/preview-error.d.ts +35 -0
- package/dist/core/preview-error.js +39 -0
- package/dist/core/preview-error.js.map +1 -0
- package/dist/core/registry.d.ts +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +21 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/audio-plugin.d.ts +1 -0
- package/dist/plugins/builtin-plugins.d.ts +1 -0
- package/dist/plugins/csv-plugin.d.ts +1 -0
- package/dist/plugins/docx-plugin.d.ts +1 -0
- package/dist/plugins/epub-plugin.d.ts +1 -0
- package/dist/plugins/html-plugin.d.ts +1 -0
- package/dist/plugins/image-plugin.d.ts +1 -0
- package/dist/plugins/markdown-plugin.d.ts +1 -0
- package/dist/plugins/pdf-plugin.d.ts +1 -0
- package/dist/plugins/pptx-plugin.d.ts +1 -0
- package/dist/plugins/rtf-plugin.d.ts +1 -0
- package/dist/plugins/source-code-plugin.d.ts +1 -0
- package/dist/plugins/svg-plugin.d.ts +1 -0
- package/dist/plugins/text-plugin.d.ts +1 -0
- package/dist/plugins/video-plugin.d.ts +1 -0
- package/dist/plugins/xlsx-plugin.d.ts +1 -0
- package/dist/plugins/zip-plugin.d.ts +1 -0
- package/dist/remote-url.d.ts +20 -5
- package/dist/remote-url.js +52 -128
- package/dist/remote-url.js.map +1 -1
- package/docs/supported-formats.md +143 -0
- package/package.json +12 -11
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Magic-byte sniffers.
|
|
3
|
+
*
|
|
4
|
+
* Pulled out of `remote-url.ts` so both the remote-URL pipeline and the
|
|
5
|
+
* synchronous `detectFileMeta` can share one source of truth for byte-level
|
|
6
|
+
* format detection. Add a new format here, and every entry point that uses
|
|
7
|
+
* detection picks it up automatically.
|
|
8
|
+
*
|
|
9
|
+
* The two layers:
|
|
10
|
+
*
|
|
11
|
+
* 1. `sniffMagic(buffer)` — sync, reads the first ~32 bytes only.
|
|
12
|
+
* Cheap, deterministic, no peer deps.
|
|
13
|
+
* 2. `sniffZipContainer(buffer)` — async, loads the buffer through
|
|
14
|
+
* jszip and inspects the entry list to
|
|
15
|
+
* distinguish docx / pptx / xlsx / epub
|
|
16
|
+
* (all of which are zip files at the
|
|
17
|
+
* magic level). Requires the optional
|
|
18
|
+
* `jszip` peer; returns null if
|
|
19
|
+
* unavailable.
|
|
20
|
+
*/
|
|
21
|
+
interface MagicSniffResult {
|
|
22
|
+
/** Conventional extension (no leading dot), or null when no signature matched. */
|
|
23
|
+
ext: string | null;
|
|
24
|
+
/** MIME type for the matched signature, or null. */
|
|
25
|
+
mimeType: string | null;
|
|
26
|
+
}
|
|
27
|
+
interface ContainerSniffResult {
|
|
28
|
+
ext: string;
|
|
29
|
+
mimeType: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Inspect the first 32 bytes of `buffer` and identify the format by signature.
|
|
33
|
+
*
|
|
34
|
+
* Covered: PDF, ZIP (any of three local-file-header variants), PNG, JPEG, GIF
|
|
35
|
+
* (87a/89a), WebP, MP4 (ISO BMFF "ftyp"), OLE compound (legacy doc/xls/ppt).
|
|
36
|
+
*
|
|
37
|
+
* For ZIP-based office formats (docx/pptx/xlsx/epub) `sniffMagic` returns
|
|
38
|
+
* `ext: "zip"` — the caller must then run {@link sniffZipContainer} to
|
|
39
|
+
* disambiguate. Keeping it two-layered lets the cheap sync path handle 90%
|
|
40
|
+
* of files without paying jszip's load cost.
|
|
41
|
+
*/
|
|
42
|
+
declare function sniffMagic(buffer: ArrayBuffer): MagicSniffResult;
|
|
43
|
+
/**
|
|
44
|
+
* Look inside a ZIP buffer and tell which OOXML / EPUB format it actually is.
|
|
45
|
+
*
|
|
46
|
+
* - `word/document.xml` → docx
|
|
47
|
+
* - `ppt/presentation.xml` → pptx
|
|
48
|
+
* - `xl/workbook.xml` → xlsx
|
|
49
|
+
* - `mimetype` == `application/epub+zip` → epub
|
|
50
|
+
*
|
|
51
|
+
* Returns `null` when none of those marker entries are present (i.e. just a
|
|
52
|
+
* plain zip), or when jszip can't be loaded / the buffer isn't a valid zip.
|
|
53
|
+
*/
|
|
54
|
+
declare function sniffZipContainer(buffer: ArrayBuffer): Promise<ContainerSniffResult | null>;
|
|
55
|
+
|
|
56
|
+
export { type ContainerSniffResult, type MagicSniffResult, sniffMagic, sniffZipContainer };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
function startsWithBytes(bytes, signature) {
|
|
2
|
+
if (bytes.length < signature.length) return false;
|
|
3
|
+
return signature.every((value, index) => bytes[index] === value);
|
|
4
|
+
}
|
|
5
|
+
function readAscii(bytes, start, length) {
|
|
6
|
+
return String.fromCharCode(...bytes.subarray(start, start + length));
|
|
7
|
+
}
|
|
8
|
+
function sniffMagic(buffer) {
|
|
9
|
+
const bytes = new Uint8Array(buffer.slice(0, 32));
|
|
10
|
+
if (readAscii(bytes, 0, 5) === "%PDF-") {
|
|
11
|
+
return { ext: "pdf", mimeType: "application/pdf" };
|
|
12
|
+
}
|
|
13
|
+
if (startsWithBytes(bytes, [80, 75, 3, 4]) || startsWithBytes(bytes, [80, 75, 5, 6]) || startsWithBytes(bytes, [80, 75, 7, 8])) {
|
|
14
|
+
return { ext: "zip", mimeType: "application/zip" };
|
|
15
|
+
}
|
|
16
|
+
if (startsWithBytes(bytes, [
|
|
17
|
+
137,
|
|
18
|
+
80,
|
|
19
|
+
78,
|
|
20
|
+
71,
|
|
21
|
+
13,
|
|
22
|
+
10,
|
|
23
|
+
26,
|
|
24
|
+
10
|
|
25
|
+
])) {
|
|
26
|
+
return { ext: "png", mimeType: "image/png" };
|
|
27
|
+
}
|
|
28
|
+
if (startsWithBytes(bytes, [255, 216, 255])) {
|
|
29
|
+
return { ext: "jpg", mimeType: "image/jpeg" };
|
|
30
|
+
}
|
|
31
|
+
const gifHeader = readAscii(bytes, 0, 6);
|
|
32
|
+
if (gifHeader === "GIF87a" || gifHeader === "GIF89a") {
|
|
33
|
+
return { ext: "gif", mimeType: "image/gif" };
|
|
34
|
+
}
|
|
35
|
+
if (readAscii(bytes, 0, 4) === "RIFF" && readAscii(bytes, 8, 4) === "WEBP") {
|
|
36
|
+
return { ext: "webp", mimeType: "image/webp" };
|
|
37
|
+
}
|
|
38
|
+
if (bytes.length >= 12 && readAscii(bytes, 4, 4) === "ftyp") {
|
|
39
|
+
return { ext: "mp4", mimeType: "video/mp4" };
|
|
40
|
+
}
|
|
41
|
+
if (startsWithBytes(bytes, [
|
|
42
|
+
208,
|
|
43
|
+
207,
|
|
44
|
+
17,
|
|
45
|
+
224,
|
|
46
|
+
161,
|
|
47
|
+
177,
|
|
48
|
+
26,
|
|
49
|
+
225
|
|
50
|
+
])) {
|
|
51
|
+
return { ext: "ole", mimeType: "application/x-ole-storage" };
|
|
52
|
+
}
|
|
53
|
+
return { ext: null, mimeType: null };
|
|
54
|
+
}
|
|
55
|
+
async function sniffZipContainer(buffer) {
|
|
56
|
+
try {
|
|
57
|
+
const { default: JSZip } = await import("jszip");
|
|
58
|
+
const zip = await JSZip.loadAsync(buffer);
|
|
59
|
+
const fileNames = Object.keys(zip.files).map(
|
|
60
|
+
(name) => name.replace(/\\/g, "/").toLowerCase()
|
|
61
|
+
);
|
|
62
|
+
const hasFile = (target) => fileNames.includes(target);
|
|
63
|
+
if (hasFile("word/document.xml")) {
|
|
64
|
+
return {
|
|
65
|
+
ext: "docx",
|
|
66
|
+
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (hasFile("ppt/presentation.xml")) {
|
|
70
|
+
return {
|
|
71
|
+
ext: "pptx",
|
|
72
|
+
mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (hasFile("xl/workbook.xml")) {
|
|
76
|
+
return {
|
|
77
|
+
ext: "xlsx",
|
|
78
|
+
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const mimetypeFile = zip.file("mimetype");
|
|
82
|
+
if (mimetypeFile) {
|
|
83
|
+
const mimetype = (await mimetypeFile.async("string")).trim();
|
|
84
|
+
if (mimetype === "application/epub+zip") {
|
|
85
|
+
return { ext: "epub", mimeType: "application/epub+zip" };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
sniffMagic,
|
|
95
|
+
sniffZipContainer
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=magic-bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/magic-bytes.ts"],"sourcesContent":["/**\n * Magic-byte sniffers.\n *\n * Pulled out of `remote-url.ts` so both the remote-URL pipeline and the\n * synchronous `detectFileMeta` can share one source of truth for byte-level\n * format detection. Add a new format here, and every entry point that uses\n * detection picks it up automatically.\n *\n * The two layers:\n *\n * 1. `sniffMagic(buffer)` — sync, reads the first ~32 bytes only.\n * Cheap, deterministic, no peer deps.\n * 2. `sniffZipContainer(buffer)` — async, loads the buffer through\n * jszip and inspects the entry list to\n * distinguish docx / pptx / xlsx / epub\n * (all of which are zip files at the\n * magic level). Requires the optional\n * `jszip` peer; returns null if\n * unavailable.\n */\n\nexport interface MagicSniffResult {\n /** Conventional extension (no leading dot), or null when no signature matched. */\n ext: string | null;\n /** MIME type for the matched signature, or null. */\n mimeType: string | null;\n}\n\nexport interface ContainerSniffResult {\n ext: string;\n mimeType: string;\n}\n\nfunction startsWithBytes(bytes: Uint8Array, signature: number[]): boolean {\n if (bytes.length < signature.length) return false;\n return signature.every((value, index) => bytes[index] === value);\n}\n\nfunction readAscii(bytes: Uint8Array, start: number, length: number): string {\n return String.fromCharCode(...bytes.subarray(start, start + length));\n}\n\n/**\n * Inspect the first 32 bytes of `buffer` and identify the format by signature.\n *\n * Covered: PDF, ZIP (any of three local-file-header variants), PNG, JPEG, GIF\n * (87a/89a), WebP, MP4 (ISO BMFF \"ftyp\"), OLE compound (legacy doc/xls/ppt).\n *\n * For ZIP-based office formats (docx/pptx/xlsx/epub) `sniffMagic` returns\n * `ext: \"zip\"` — the caller must then run {@link sniffZipContainer} to\n * disambiguate. Keeping it two-layered lets the cheap sync path handle 90%\n * of files without paying jszip's load cost.\n */\nexport function sniffMagic(buffer: ArrayBuffer): MagicSniffResult {\n const bytes = new Uint8Array(buffer.slice(0, 32));\n\n if (readAscii(bytes, 0, 5) === \"%PDF-\") {\n return { ext: \"pdf\", mimeType: \"application/pdf\" };\n }\n\n // Three valid ZIP local-file-header variants. The first is by far the most\n // common; the latter two appear in spanned/empty zips but we still want to\n // recognize them.\n if (\n startsWithBytes(bytes, [0x50, 0x4b, 0x03, 0x04]) ||\n startsWithBytes(bytes, [0x50, 0x4b, 0x05, 0x06]) ||\n startsWithBytes(bytes, [0x50, 0x4b, 0x07, 0x08])\n ) {\n return { ext: \"zip\", mimeType: \"application/zip\" };\n }\n\n if (\n startsWithBytes(bytes, [\n 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,\n ])\n ) {\n return { ext: \"png\", mimeType: \"image/png\" };\n }\n\n if (startsWithBytes(bytes, [0xff, 0xd8, 0xff])) {\n return { ext: \"jpg\", mimeType: \"image/jpeg\" };\n }\n\n const gifHeader = readAscii(bytes, 0, 6);\n if (gifHeader === \"GIF87a\" || gifHeader === \"GIF89a\") {\n return { ext: \"gif\", mimeType: \"image/gif\" };\n }\n\n if (readAscii(bytes, 0, 4) === \"RIFF\" && readAscii(bytes, 8, 4) === \"WEBP\") {\n return { ext: \"webp\", mimeType: \"image/webp\" };\n }\n\n // ISO Base Media File Format (\"ftyp\" at offset 4). Could be MP4, MOV, M4A,\n // 3GP, etc. — we report mp4 as the umbrella; finer-grained classification\n // would require parsing the major-brand box, which we don't need for the\n // current preview pipeline.\n if (bytes.length >= 12 && readAscii(bytes, 4, 4) === \"ftyp\") {\n return { ext: \"mp4\", mimeType: \"video/mp4\" };\n }\n\n // OLE2 compound document signature — legacy doc / xls / ppt all use this.\n // We report \"ole\" generically; the file type is then resolved from the\n // filename extension upstream (binary OLE distinguishes by stream layout\n // which we don't parse).\n if (\n startsWithBytes(bytes, [\n 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1,\n ])\n ) {\n return { ext: \"ole\", mimeType: \"application/x-ole-storage\" };\n }\n\n return { ext: null, mimeType: null };\n}\n\n/**\n * Look inside a ZIP buffer and tell which OOXML / EPUB format it actually is.\n *\n * - `word/document.xml` → docx\n * - `ppt/presentation.xml` → pptx\n * - `xl/workbook.xml` → xlsx\n * - `mimetype` == `application/epub+zip` → epub\n *\n * Returns `null` when none of those marker entries are present (i.e. just a\n * plain zip), or when jszip can't be loaded / the buffer isn't a valid zip.\n */\nexport async function sniffZipContainer(\n buffer: ArrayBuffer\n): Promise<ContainerSniffResult | null> {\n try {\n const { default: JSZip } = await import(\"jszip\");\n const zip = await JSZip.loadAsync(buffer);\n\n // Path separators in zip entries are spec'd as forward slashes, but\n // Windows-built archives sometimes use backslashes. Normalize so\n // `hasFile` checks are reliable.\n const fileNames = Object.keys(zip.files).map((name) =>\n name.replace(/\\\\/g, \"/\").toLowerCase()\n );\n const hasFile = (target: string) => fileNames.includes(target);\n\n if (hasFile(\"word/document.xml\")) {\n return {\n ext: \"docx\",\n mimeType:\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n };\n }\n\n if (hasFile(\"ppt/presentation.xml\")) {\n return {\n ext: \"pptx\",\n mimeType:\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n };\n }\n\n if (hasFile(\"xl/workbook.xml\")) {\n return {\n ext: \"xlsx\",\n mimeType:\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n };\n }\n\n const mimetypeFile = zip.file(\"mimetype\");\n if (mimetypeFile) {\n const mimetype = (await mimetypeFile.async(\"string\")).trim();\n if (mimetype === \"application/epub+zip\") {\n return { ext: \"epub\", mimeType: \"application/epub+zip\" };\n }\n }\n\n return null;\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/core/plugin.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ComponentType } from 'react';
|
|
2
2
|
import { FileInfo } from './types.js';
|
|
3
|
+
import { PreviewError } from './preview-error.js';
|
|
3
4
|
|
|
4
5
|
interface PreviewPlugin {
|
|
5
6
|
id: string;
|
|
@@ -28,10 +29,9 @@ declare function loadWithOptionalDep<T>(loader: () => Promise<T>, meta: {
|
|
|
28
29
|
package: string;
|
|
29
30
|
featureLabel: string;
|
|
30
31
|
}): () => Promise<T>;
|
|
31
|
-
declare class MissingPeerDependencyError extends
|
|
32
|
+
declare class MissingPeerDependencyError extends PreviewError {
|
|
32
33
|
packageName: string;
|
|
33
34
|
featureLabel: string;
|
|
34
|
-
cause: unknown;
|
|
35
35
|
constructor(packageName: string, featureLabel: string, cause: unknown);
|
|
36
36
|
}
|
|
37
37
|
|
package/dist/core/plugin.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PreviewError } from "./preview-error";
|
|
1
2
|
function loadWithOptionalDep(loader, meta) {
|
|
2
3
|
return async () => {
|
|
3
4
|
try {
|
|
@@ -10,9 +11,10 @@ function loadWithOptionalDep(loader, meta) {
|
|
|
10
11
|
}
|
|
11
12
|
};
|
|
12
13
|
}
|
|
13
|
-
class MissingPeerDependencyError extends
|
|
14
|
+
class MissingPeerDependencyError extends PreviewError {
|
|
14
15
|
constructor(packageName, featureLabel, cause) {
|
|
15
16
|
super(
|
|
17
|
+
"MISSING_PEER_DEPENDENCY",
|
|
16
18
|
`${featureLabel} requires the optional peer dependency "${packageName}".
|
|
17
19
|
|
|
18
20
|
Install it in your app:
|
|
@@ -20,11 +22,11 @@ Install it in your app:
|
|
|
20
22
|
# or: npm install ${packageName}
|
|
21
23
|
# or: yarn add ${packageName}
|
|
22
24
|
|
|
23
|
-
See: https://github.com/CoderLambert/filevista/tree/main/packages/file-preview#optional-peer-dependencies
|
|
25
|
+
See: https://github.com/CoderLambert/filevista/tree/main/packages/file-preview#optional-peer-dependencies`,
|
|
26
|
+
{ cause, details: { packageName, featureLabel } }
|
|
24
27
|
);
|
|
25
28
|
this.packageName = packageName;
|
|
26
29
|
this.featureLabel = featureLabel;
|
|
27
|
-
this.cause = cause;
|
|
28
30
|
this.name = "MissingPeerDependencyError";
|
|
29
31
|
}
|
|
30
32
|
}
|
package/dist/core/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/plugin.ts"],"sourcesContent":["import type { ComponentType } from \"react\";\nimport type { FileInfo } from \"../utils\";\n\nexport interface PreviewPlugin {\n id: string;\n name: string;\n priority?: number;\n match(file: FileInfo): boolean;\n load(): Promise<{ default: ComponentType<{ file: FileInfo }> }>;\n}\n\n/**\n * Wrap a dynamic-import loader so that, if the import fails because an\n * optional peer dependency is missing (e.g. `pdfjs-dist`, `exceljs`), the\n * user sees a clear \"install this package\" message instead of the raw\n * bundler error.\n *\n * @example\n * load: loadWithOptionalDep(\n * () => import(\"../preview-adapters/PdfPreviewAdapter\"),\n * { package: \"pdfjs-dist\", featureLabel: \"PDF preview\" },\n * )\n */\nexport function loadWithOptionalDep<T>(\n loader: () => Promise<T>,\n meta: { package: string; featureLabel: string },\n): () => Promise<T> {\n return async () => {\n try {\n return await loader();\n } catch (cause) {\n if (isModuleNotFoundError(cause, meta.package)) {\n throw new MissingPeerDependencyError(meta.package, meta.featureLabel, cause);\n }\n throw cause;\n }\n };\n}\n\nexport class MissingPeerDependencyError extends
|
|
1
|
+
{"version":3,"sources":["../../src/core/plugin.ts"],"sourcesContent":["import type { ComponentType } from \"react\";\nimport type { FileInfo } from \"../utils\";\nimport { PreviewError } from \"./preview-error\";\n\nexport interface PreviewPlugin {\n id: string;\n name: string;\n priority?: number;\n match(file: FileInfo): boolean;\n load(): Promise<{ default: ComponentType<{ file: FileInfo }> }>;\n}\n\n/**\n * Wrap a dynamic-import loader so that, if the import fails because an\n * optional peer dependency is missing (e.g. `pdfjs-dist`, `exceljs`), the\n * user sees a clear \"install this package\" message instead of the raw\n * bundler error.\n *\n * @example\n * load: loadWithOptionalDep(\n * () => import(\"../preview-adapters/PdfPreviewAdapter\"),\n * { package: \"pdfjs-dist\", featureLabel: \"PDF preview\" },\n * )\n */\nexport function loadWithOptionalDep<T>(\n loader: () => Promise<T>,\n meta: { package: string; featureLabel: string },\n): () => Promise<T> {\n return async () => {\n try {\n return await loader();\n } catch (cause) {\n if (isModuleNotFoundError(cause, meta.package)) {\n throw new MissingPeerDependencyError(meta.package, meta.featureLabel, cause);\n }\n throw cause;\n }\n };\n}\n\nexport class MissingPeerDependencyError extends PreviewError {\n constructor(\n public packageName: string,\n public featureLabel: string,\n cause: unknown,\n ) {\n super(\n \"MISSING_PEER_DEPENDENCY\",\n `${featureLabel} requires the optional peer dependency \"${packageName}\".\\n\\n` +\n `Install it in your app:\\n` +\n ` pnpm add ${packageName}\\n` +\n ` # or: npm install ${packageName}\\n` +\n ` # or: yarn add ${packageName}\\n\\n` +\n `See: https://github.com/CoderLambert/filevista/tree/main/packages/file-preview#optional-peer-dependencies`,\n { cause, details: { packageName, featureLabel } },\n );\n this.name = \"MissingPeerDependencyError\";\n }\n}\n\n/**\n * Detect \"module not found\" failures across the bundlers/runtimes our users\n * are likely on — Webpack, Turbopack, Vite, native ESM, esbuild.\n *\n * We deliberately match loosely. False positives are cheap (the install hint\n * is always actionable) but false negatives swallow the affordance.\n */\nfunction isModuleNotFoundError(error: unknown, packageName: string): boolean {\n if (!(error instanceof Error)) return false;\n const message = error.message ?? \"\";\n if (!message) return false;\n\n // The package name must appear in the message — otherwise we're attributing\n // an unrelated error to the wrong dependency.\n if (!message.includes(packageName)) return false;\n\n return (\n message.includes(\"Cannot find module\") || // Node ESM, Webpack\n message.includes(\"Failed to fetch dynamically imported module\") || // Native browser ESM\n message.includes(\"Failed to resolve module specifier\") || // Vite dev\n message.includes(\"Module not found\") || // Webpack production\n message.includes(\"Unable to resolve\") // Metro / some bundlers\n );\n}\n"],"mappings":"AAEA,SAAS,oBAAoB;AAsBtB,SAAS,oBACd,QACA,MACkB;AAClB,SAAO,YAAY;AACjB,QAAI;AACF,aAAO,MAAM,OAAO;AAAA,IACtB,SAAS,OAAO;AACd,UAAI,sBAAsB,OAAO,KAAK,OAAO,GAAG;AAC9C,cAAM,IAAI,2BAA2B,KAAK,SAAS,KAAK,cAAc,KAAK;AAAA,MAC7E;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEO,MAAM,mCAAmC,aAAa;AAAA,EAC3D,YACS,aACA,cACP,OACA;AACA;AAAA,MACE;AAAA,MACA,GAAG,YAAY,2CAA2C,WAAW;AAAA;AAAA;AAAA,aAErD,WAAW;AAAA,sBACF,WAAW;AAAA,mBACd,WAAW;AAAA;AAAA;AAAA,MAEjC,EAAE,OAAO,SAAS,EAAE,aAAa,aAAa,EAAE;AAAA,IAClD;AAbO;AACA;AAaP,SAAK,OAAO;AAAA,EACd;AACF;AASA,SAAS,sBAAsB,OAAgB,aAA8B;AAC3E,MAAI,EAAE,iBAAiB,OAAQ,QAAO;AACtC,QAAM,UAAU,MAAM,WAAW;AACjC,MAAI,CAAC,QAAS,QAAO;AAIrB,MAAI,CAAC,QAAQ,SAAS,WAAW,EAAG,QAAO;AAE3C,SACE,QAAQ,SAAS,oBAAoB;AAAA,EACrC,QAAQ,SAAS,6CAA6C;AAAA,EAC9D,QAAQ,SAAS,oCAAoC;AAAA,EACrD,QAAQ,SAAS,kBAAkB;AAAA,EACnC,QAAQ,SAAS,mBAAmB;AAExC;","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
type PreviewErrorCode = "MISSING_PEER_DEPENDENCY" | "UNSUPPORTED_FILE_TYPE" | "FILE_TOO_LARGE" | "REMOTE_CORS_ERROR" | "REMOTE_HTTP_ERROR" | "INVALID_URL" | "UNSUPPORTED_PROTOCOL" | "ABORTED" | "PARSE_FAILED" | "RENDER_FAILED" | "SECURITY_BLOCKED";
|
|
2
|
+
interface PreviewErrorOptions {
|
|
3
|
+
cause?: unknown;
|
|
4
|
+
url?: string;
|
|
5
|
+
pluginId?: string;
|
|
6
|
+
pluginName?: string;
|
|
7
|
+
fileName?: string;
|
|
8
|
+
details?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Stable, SDK-facing error shape.
|
|
12
|
+
*
|
|
13
|
+
* Messages can change as UX improves; `code` is the contract consumers should
|
|
14
|
+
* switch on for telemetry, retry policy, and custom fallback UI.
|
|
15
|
+
*/
|
|
16
|
+
declare class PreviewError extends Error {
|
|
17
|
+
readonly code: PreviewErrorCode;
|
|
18
|
+
readonly cause?: unknown;
|
|
19
|
+
readonly url?: string;
|
|
20
|
+
readonly pluginId?: string;
|
|
21
|
+
readonly pluginName?: string;
|
|
22
|
+
readonly fileName?: string;
|
|
23
|
+
readonly details?: Record<string, unknown>;
|
|
24
|
+
constructor(code: PreviewErrorCode, message: string, options?: PreviewErrorOptions);
|
|
25
|
+
}
|
|
26
|
+
declare function isPreviewError(error: unknown): error is PreviewError;
|
|
27
|
+
declare function normalizePreviewError(error: unknown, fallback: {
|
|
28
|
+
code: PreviewErrorCode;
|
|
29
|
+
message: string;
|
|
30
|
+
pluginId?: string;
|
|
31
|
+
pluginName?: string;
|
|
32
|
+
fileName?: string;
|
|
33
|
+
}): PreviewError;
|
|
34
|
+
|
|
35
|
+
export { PreviewError, type PreviewErrorCode, type PreviewErrorOptions, isPreviewError, normalizePreviewError };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
class PreviewError extends Error {
|
|
2
|
+
constructor(code, message, options = {}) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "PreviewError";
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.cause = options.cause;
|
|
7
|
+
this.url = options.url;
|
|
8
|
+
this.pluginId = options.pluginId;
|
|
9
|
+
this.pluginName = options.pluginName;
|
|
10
|
+
this.fileName = options.fileName;
|
|
11
|
+
this.details = options.details;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function isPreviewError(error) {
|
|
15
|
+
return error instanceof PreviewError;
|
|
16
|
+
}
|
|
17
|
+
function normalizePreviewError(error, fallback) {
|
|
18
|
+
if (error instanceof PreviewError) return error;
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
return new PreviewError(fallback.code, error.message || fallback.message, {
|
|
21
|
+
cause: error,
|
|
22
|
+
pluginId: fallback.pluginId,
|
|
23
|
+
pluginName: fallback.pluginName,
|
|
24
|
+
fileName: fallback.fileName
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return new PreviewError(fallback.code, fallback.message, {
|
|
28
|
+
cause: error,
|
|
29
|
+
pluginId: fallback.pluginId,
|
|
30
|
+
pluginName: fallback.pluginName,
|
|
31
|
+
fileName: fallback.fileName
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
PreviewError,
|
|
36
|
+
isPreviewError,
|
|
37
|
+
normalizePreviewError
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=preview-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/preview-error.ts"],"sourcesContent":["export type PreviewErrorCode =\n | \"MISSING_PEER_DEPENDENCY\"\n | \"UNSUPPORTED_FILE_TYPE\"\n | \"FILE_TOO_LARGE\"\n | \"REMOTE_CORS_ERROR\"\n | \"REMOTE_HTTP_ERROR\"\n | \"INVALID_URL\"\n | \"UNSUPPORTED_PROTOCOL\"\n | \"ABORTED\"\n | \"PARSE_FAILED\"\n | \"RENDER_FAILED\"\n | \"SECURITY_BLOCKED\";\n\nexport interface PreviewErrorOptions {\n cause?: unknown;\n url?: string;\n pluginId?: string;\n pluginName?: string;\n fileName?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * Stable, SDK-facing error shape.\n *\n * Messages can change as UX improves; `code` is the contract consumers should\n * switch on for telemetry, retry policy, and custom fallback UI.\n */\nexport class PreviewError extends Error {\n readonly code: PreviewErrorCode;\n readonly cause?: unknown;\n readonly url?: string;\n readonly pluginId?: string;\n readonly pluginName?: string;\n readonly fileName?: string;\n readonly details?: Record<string, unknown>;\n\n constructor(code: PreviewErrorCode, message: string, options: PreviewErrorOptions = {}) {\n super(message);\n this.name = \"PreviewError\";\n this.code = code;\n this.cause = options.cause;\n this.url = options.url;\n this.pluginId = options.pluginId;\n this.pluginName = options.pluginName;\n this.fileName = options.fileName;\n this.details = options.details;\n }\n}\n\nexport function isPreviewError(error: unknown): error is PreviewError {\n return error instanceof PreviewError;\n}\n\nexport function normalizePreviewError(\n error: unknown,\n fallback: {\n code: PreviewErrorCode;\n message: string;\n pluginId?: string;\n pluginName?: string;\n fileName?: string;\n }\n): PreviewError {\n if (error instanceof PreviewError) return error;\n\n if (error instanceof Error) {\n return new PreviewError(fallback.code, error.message || fallback.message, {\n cause: error,\n pluginId: fallback.pluginId,\n pluginName: fallback.pluginName,\n fileName: fallback.fileName,\n });\n }\n\n return new PreviewError(fallback.code, fallback.message, {\n cause: error,\n pluginId: fallback.pluginId,\n pluginName: fallback.pluginName,\n fileName: fallback.fileName,\n });\n}\n"],"mappings":"AA4BO,MAAM,qBAAqB,MAAM;AAAA,EAStC,YAAY,MAAwB,SAAiB,UAA+B,CAAC,GAAG;AACtF,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,QAAQ,QAAQ;AACrB,SAAK,MAAM,QAAQ;AACnB,SAAK,WAAW,QAAQ;AACxB,SAAK,aAAa,QAAQ;AAC1B,SAAK,WAAW,QAAQ;AACxB,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;AAEO,SAAS,eAAe,OAAuC;AACpE,SAAO,iBAAiB;AAC1B;AAEO,SAAS,sBACd,OACA,UAOc;AACd,MAAI,iBAAiB,aAAc,QAAO;AAE1C,MAAI,iBAAiB,OAAO;AAC1B,WAAO,IAAI,aAAa,SAAS,MAAM,MAAM,WAAW,SAAS,SAAS;AAAA,MACxE,OAAO;AAAA,MACP,UAAU,SAAS;AAAA,MACnB,YAAY,SAAS;AAAA,MACrB,UAAU,SAAS;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,SAAO,IAAI,aAAa,SAAS,MAAM,SAAS,SAAS;AAAA,IACvD,OAAO;AAAA,IACP,UAAU,SAAS;AAAA,IACnB,YAAY,SAAS;AAAA,IACrB,UAAU,SAAS;AAAA,EACrB,CAAC;AACH;","names":[]}
|
package/dist/core/registry.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -2,12 +2,15 @@ export { PluginPreviewRenderer, PluginPreviewRendererProps } from './PluginPrevi
|
|
|
2
2
|
export { ALL_FILE_TYPES, FileInfo, FileType, NormalizedFile, PreviewSource } from './core/types.js';
|
|
3
3
|
export { PreviewPlugin } from './core/plugin.js';
|
|
4
4
|
export { PreviewPluginRegistry, createPreviewPluginRegistry } from './core/registry.js';
|
|
5
|
+
export { PreviewError, PreviewErrorCode, PreviewErrorOptions, isPreviewError, normalizePreviewError } from './core/preview-error.js';
|
|
5
6
|
export { ReadSourceOptions, createObjectUrlFromSource, getSourceMimeType, getSourceName, getSourceSize, readSourceAsArrayBuffer, readSourceAsBase64, readSourceAsText } from './core/source.js';
|
|
6
7
|
export { BinaryPreviewInput, readBinaryPreviewAsArrayBuffer, readBinaryPreviewAsUint8Array } from './core/binary.js';
|
|
7
8
|
export { downloadSource } from './core/download.js';
|
|
8
9
|
export { getAssetBasePath, resolveAssetPath, setAssetBasePath } from './core/config.js';
|
|
9
10
|
export { LocaleMessages, LocaleProvider, enUS, getDefaultLocale, useLocale, zhCN } from './core/i18n.js';
|
|
10
11
|
export { detectFileType } from './utils.js';
|
|
12
|
+
export { DetectFileMetaOptions, FileMeta, FileMetaConfidence, FileMetaDetectBy, detectFileMeta } from './core/detect-meta.js';
|
|
13
|
+
export { ContainerSniffResult, MagicSniffResult, sniffMagic, sniffZipContainer } from './core/magic-bytes.js';
|
|
11
14
|
export { PREVIEW_SUPPORT_MATRIX, PreviewSupportMeta, PreviewSupportStatus, RendererSupportState, getPreviewSupportMeta, isDegradedFileType, isPluginSupportedFileType, isUnsupportedFileType } from './support-status.js';
|
|
12
15
|
export { PREVIEW_SIZE_LIMITS, PreviewSizeLevel, PreviewSizePolicy, getPreviewSizeLevel, getPreviewSizePolicy } from './performance-limits.js';
|
|
13
16
|
export { FILE_PREVIEW_LIMITS, XLSX_PREVIEW_LIMITS, shouldHighlight, truncateContent } from './limits.js';
|
|
@@ -29,7 +32,7 @@ export { textPlugin } from './plugins/text-plugin.js';
|
|
|
29
32
|
export { videoPlugin } from './plugins/video-plugin.js';
|
|
30
33
|
export { xlsxPlugin } from './plugins/xlsx-plugin.js';
|
|
31
34
|
export { zipPlugin } from './plugins/zip-plugin.js';
|
|
32
|
-
export { ProcessRemoteUrlOptions, RemoteLoadProgress, RemoteUrlError, RemoteUrlErrorCode, processRemoteUrl } from './remote-url.js';
|
|
35
|
+
export { DEFAULT_REMOTE_MAX_BYTES, ProcessRemoteUrlOptions, RemoteLoadProgress, RemoteUrlError, RemoteUrlErrorCode, processRemoteUrl } from './remote-url.js';
|
|
33
36
|
export { SourceTextState, useSourceText } from './hooks/useSourceText.js';
|
|
34
37
|
export { SourceBase64State, useSourceBase64 } from './hooks/useSourceBase64.js';
|
|
35
38
|
export { useObjectUrlFromSource } from './hooks/useObjectUrlFromSource.js';
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,11 @@ import {
|
|
|
6
6
|
PreviewPluginRegistry,
|
|
7
7
|
createPreviewPluginRegistry
|
|
8
8
|
} from "./core/registry";
|
|
9
|
+
import {
|
|
10
|
+
PreviewError,
|
|
11
|
+
isPreviewError,
|
|
12
|
+
normalizePreviewError
|
|
13
|
+
} from "./core/preview-error";
|
|
9
14
|
import {
|
|
10
15
|
readSourceAsArrayBuffer,
|
|
11
16
|
readSourceAsText,
|
|
@@ -33,6 +38,13 @@ import {
|
|
|
33
38
|
getDefaultLocale
|
|
34
39
|
} from "./core/i18n";
|
|
35
40
|
import { detectFileType } from "./utils";
|
|
41
|
+
import {
|
|
42
|
+
detectFileMeta
|
|
43
|
+
} from "./core/detect-meta";
|
|
44
|
+
import {
|
|
45
|
+
sniffMagic,
|
|
46
|
+
sniffZipContainer
|
|
47
|
+
} from "./core/magic-bytes";
|
|
36
48
|
import {
|
|
37
49
|
PREVIEW_SUPPORT_MATRIX,
|
|
38
50
|
getPreviewSupportMeta,
|
|
@@ -74,7 +86,8 @@ import { xlsxPlugin } from "./plugins/xlsx-plugin";
|
|
|
74
86
|
import { zipPlugin } from "./plugins/zip-plugin";
|
|
75
87
|
import {
|
|
76
88
|
processRemoteUrl,
|
|
77
|
-
RemoteUrlError
|
|
89
|
+
RemoteUrlError,
|
|
90
|
+
DEFAULT_REMOTE_MAX_BYTES
|
|
78
91
|
} from "./remote-url";
|
|
79
92
|
import {
|
|
80
93
|
useSourceText
|
|
@@ -85,12 +98,14 @@ import {
|
|
|
85
98
|
import { useObjectUrlFromSource } from "./hooks/useObjectUrlFromSource";
|
|
86
99
|
export {
|
|
87
100
|
ALL_FILE_TYPES,
|
|
101
|
+
DEFAULT_REMOTE_MAX_BYTES,
|
|
88
102
|
FILE_PREVIEW_LIMITS,
|
|
89
103
|
LargeFileGate,
|
|
90
104
|
LocaleProvider,
|
|
91
105
|
PREVIEW_SIZE_LIMITS,
|
|
92
106
|
PREVIEW_SUPPORT_MATRIX,
|
|
93
107
|
PluginPreviewRenderer,
|
|
108
|
+
PreviewError,
|
|
94
109
|
PreviewPluginRegistry,
|
|
95
110
|
RemoteUrlError,
|
|
96
111
|
XLSX_PREVIEW_LIMITS,
|
|
@@ -100,6 +115,7 @@ export {
|
|
|
100
115
|
createObjectUrlFromSource,
|
|
101
116
|
createPreviewPluginRegistry,
|
|
102
117
|
csvPlugin,
|
|
118
|
+
detectFileMeta,
|
|
103
119
|
detectFileType,
|
|
104
120
|
docxPlugin,
|
|
105
121
|
downloadSource,
|
|
@@ -117,8 +133,10 @@ export {
|
|
|
117
133
|
imagePlugin,
|
|
118
134
|
isDegradedFileType,
|
|
119
135
|
isPluginSupportedFileType,
|
|
136
|
+
isPreviewError,
|
|
120
137
|
isUnsupportedFileType,
|
|
121
138
|
markdownPlugin,
|
|
139
|
+
normalizePreviewError,
|
|
122
140
|
pdfPlugin,
|
|
123
141
|
pptxPlugin,
|
|
124
142
|
processRemoteUrl,
|
|
@@ -131,6 +149,8 @@ export {
|
|
|
131
149
|
rtfPlugin,
|
|
132
150
|
setAssetBasePath,
|
|
133
151
|
shouldHighlight,
|
|
152
|
+
sniffMagic,
|
|
153
|
+
sniffZipContainer,
|
|
134
154
|
sourceCodePlugin,
|
|
135
155
|
svgPlugin,
|
|
136
156
|
textPlugin,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @lamberl-lee/file-preview — public API\n *\n * Quick start:\n *\n * import { PluginPreviewRenderer, setAssetBasePath } from \"@lamberl-lee/file-preview\";\n * import \"@lamberl-lee/file-preview/styles/index.css\";\n *\n * setAssetBasePath(\"/static\"); // where you serve PDF.js worker + RTF.js bundles\n * <PluginPreviewRenderer file={fileInfo} />\n */\n\n// ─── Top-level renderer ───────────────────────────────────────────────────\nexport {\n PluginPreviewRenderer,\n type PluginPreviewRendererProps,\n} from \"./PluginPreviewRenderer\";\n\n// ─── Core abstractions ────────────────────────────────────────────────────\nexport type {\n PreviewSource,\n NormalizedFile,\n FileType,\n FileInfo,\n} from \"./core/types\";\nexport { ALL_FILE_TYPES } from \"./core/types\";\nexport type { PreviewPlugin } from \"./core/plugin\";\nexport {\n PreviewPluginRegistry,\n createPreviewPluginRegistry,\n} from \"./core/registry\";\n\n// Source utilities — read PreviewSource as text / ArrayBuffer / base64 / object URL.\nexport {\n readSourceAsArrayBuffer,\n readSourceAsText,\n readSourceAsBase64,\n createObjectUrlFromSource,\n getSourceName,\n getSourceMimeType,\n getSourceSize,\n type ReadSourceOptions,\n} from \"./core/source\";\nexport {\n readBinaryPreviewAsArrayBuffer,\n readBinaryPreviewAsUint8Array,\n type BinaryPreviewInput,\n} from \"./core/binary\";\nexport { downloadSource } from \"./core/download\";\n\n// Runtime configuration — base path for static assets (PDF.js worker, RTF.js bundles).\nexport {\n setAssetBasePath,\n getAssetBasePath,\n resolveAssetPath,\n} from \"./core/config\";\n\n// Internationalization — locale messages + provider hook.\nexport {\n zhCN,\n enUS,\n LocaleProvider,\n useLocale,\n getDefaultLocale,\n type LocaleMessages,\n} from \"./core/i18n\";\n\n// ─── File detection ───────────────────────────────────────────────────────\nexport { detectFileType } from \"./utils\";\n\n// Support matrix — which renderers cover which file types.\nexport {\n PREVIEW_SUPPORT_MATRIX,\n getPreviewSupportMeta,\n isPluginSupportedFileType,\n isUnsupportedFileType,\n isDegradedFileType,\n type PreviewSupportStatus,\n type PreviewSupportMeta,\n type RendererSupportState,\n} from \"./support-status\";\n\n// ─── Performance / size limits ────────────────────────────────────────────\nexport {\n PREVIEW_SIZE_LIMITS,\n getPreviewSizeLevel,\n getPreviewSizePolicy,\n type PreviewSizeLevel,\n type PreviewSizePolicy,\n} from \"./performance-limits\";\nexport {\n XLSX_PREVIEW_LIMITS,\n FILE_PREVIEW_LIMITS,\n shouldHighlight,\n truncateContent,\n} from \"./limits\";\nexport { LargeFileGate } from \"./LargeFileGate\";\n\n// ─── Built-in plugins (full registry) ─────────────────────────────────────\nexport {\n builtinPreviewPlugins,\n createBuiltinPreviewRegistry,\n} from \"./plugins/builtin-plugins\";\n\n// Individual plugins — for custom registries that drop or replace formats.\nexport { audioPlugin } from \"./plugins/audio-plugin\";\nexport { csvPlugin } from \"./plugins/csv-plugin\";\nexport { docxPlugin } from \"./plugins/docx-plugin\";\nexport { epubPlugin } from \"./plugins/epub-plugin\";\nexport { htmlPlugin } from \"./plugins/html-plugin\";\nexport { imagePlugin } from \"./plugins/image-plugin\";\nexport { markdownPlugin } from \"./plugins/markdown-plugin\";\nexport { pdfPlugin } from \"./plugins/pdf-plugin\";\nexport { pptxPlugin } from \"./plugins/pptx-plugin\";\nexport { rtfPlugin } from \"./plugins/rtf-plugin\";\nexport { sourceCodePlugin } from \"./plugins/source-code-plugin\";\nexport { svgPlugin } from \"./plugins/svg-plugin\";\nexport { textPlugin } from \"./plugins/text-plugin\";\nexport { videoPlugin } from \"./plugins/video-plugin\";\nexport { xlsxPlugin } from \"./plugins/xlsx-plugin\";\nexport { zipPlugin } from \"./plugins/zip-plugin\";\n\n// ─── Remote URL loader ────────────────────────────────────────────────────\nexport {\n processRemoteUrl,\n RemoteUrlError,\n type RemoteUrlErrorCode,\n type RemoteLoadProgress,\n type ProcessRemoteUrlOptions,\n} from \"./remote-url\";\n\n// ─── React hooks ──────────────────────────────────────────────────────────\nexport {\n useSourceText,\n type SourceTextState,\n} from \"./hooks/useSourceText\";\nexport {\n useSourceBase64,\n type SourceBase64State,\n} from \"./hooks/useSourceBase64\";\nexport { useObjectUrlFromSource } from \"./hooks/useObjectUrlFromSource\";\n"],"mappings":"AAaA;AAAA,EACE;AAAA,OAEK;AASP,SAAS,sBAAsB;AAE/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,sBAAsB;AAG/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAGP,SAAS,sBAAsB;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @lamberl-lee/file-preview — public API\n *\n * Quick start:\n *\n * import { PluginPreviewRenderer, setAssetBasePath } from \"@lamberl-lee/file-preview\";\n * import \"@lamberl-lee/file-preview/styles/index.css\";\n *\n * setAssetBasePath(\"/static\"); // where you serve PDF.js worker + RTF.js bundles\n * <PluginPreviewRenderer file={fileInfo} />\n */\n\n// ─── Top-level renderer ───────────────────────────────────────────────────\nexport {\n PluginPreviewRenderer,\n type PluginPreviewRendererProps,\n} from \"./PluginPreviewRenderer\";\n\n// ─── Core abstractions ────────────────────────────────────────────────────\nexport type {\n PreviewSource,\n NormalizedFile,\n FileType,\n FileInfo,\n} from \"./core/types\";\nexport { ALL_FILE_TYPES } from \"./core/types\";\nexport type { PreviewPlugin } from \"./core/plugin\";\nexport {\n PreviewPluginRegistry,\n createPreviewPluginRegistry,\n} from \"./core/registry\";\nexport {\n PreviewError,\n isPreviewError,\n normalizePreviewError,\n type PreviewErrorCode,\n type PreviewErrorOptions,\n} from \"./core/preview-error\";\n\n// Source utilities — read PreviewSource as text / ArrayBuffer / base64 / object URL.\nexport {\n readSourceAsArrayBuffer,\n readSourceAsText,\n readSourceAsBase64,\n createObjectUrlFromSource,\n getSourceName,\n getSourceMimeType,\n getSourceSize,\n type ReadSourceOptions,\n} from \"./core/source\";\nexport {\n readBinaryPreviewAsArrayBuffer,\n readBinaryPreviewAsUint8Array,\n type BinaryPreviewInput,\n} from \"./core/binary\";\nexport { downloadSource } from \"./core/download\";\n\n// Runtime configuration — base path for static assets (PDF.js worker, RTF.js bundles).\nexport {\n setAssetBasePath,\n getAssetBasePath,\n resolveAssetPath,\n} from \"./core/config\";\n\n// Internationalization — locale messages + provider hook.\nexport {\n zhCN,\n enUS,\n LocaleProvider,\n useLocale,\n getDefaultLocale,\n type LocaleMessages,\n} from \"./core/i18n\";\n\n// ─── File detection ───────────────────────────────────────────────────────\nexport { detectFileType } from \"./utils\";\nexport {\n detectFileMeta,\n type FileMeta,\n type FileMetaConfidence,\n type FileMetaDetectBy,\n type DetectFileMetaOptions,\n} from \"./core/detect-meta\";\nexport {\n sniffMagic,\n sniffZipContainer,\n type MagicSniffResult,\n type ContainerSniffResult,\n} from \"./core/magic-bytes\";\n\n// Support matrix — which renderers cover which file types.\nexport {\n PREVIEW_SUPPORT_MATRIX,\n getPreviewSupportMeta,\n isPluginSupportedFileType,\n isUnsupportedFileType,\n isDegradedFileType,\n type PreviewSupportStatus,\n type PreviewSupportMeta,\n type RendererSupportState,\n} from \"./support-status\";\n\n// ─── Performance / size limits ────────────────────────────────────────────\nexport {\n PREVIEW_SIZE_LIMITS,\n getPreviewSizeLevel,\n getPreviewSizePolicy,\n type PreviewSizeLevel,\n type PreviewSizePolicy,\n} from \"./performance-limits\";\nexport {\n XLSX_PREVIEW_LIMITS,\n FILE_PREVIEW_LIMITS,\n shouldHighlight,\n truncateContent,\n} from \"./limits\";\nexport { LargeFileGate } from \"./LargeFileGate\";\n\n// ─── Built-in plugins (full registry) ─────────────────────────────────────\nexport {\n builtinPreviewPlugins,\n createBuiltinPreviewRegistry,\n} from \"./plugins/builtin-plugins\";\n\n// Individual plugins — for custom registries that drop or replace formats.\nexport { audioPlugin } from \"./plugins/audio-plugin\";\nexport { csvPlugin } from \"./plugins/csv-plugin\";\nexport { docxPlugin } from \"./plugins/docx-plugin\";\nexport { epubPlugin } from \"./plugins/epub-plugin\";\nexport { htmlPlugin } from \"./plugins/html-plugin\";\nexport { imagePlugin } from \"./plugins/image-plugin\";\nexport { markdownPlugin } from \"./plugins/markdown-plugin\";\nexport { pdfPlugin } from \"./plugins/pdf-plugin\";\nexport { pptxPlugin } from \"./plugins/pptx-plugin\";\nexport { rtfPlugin } from \"./plugins/rtf-plugin\";\nexport { sourceCodePlugin } from \"./plugins/source-code-plugin\";\nexport { svgPlugin } from \"./plugins/svg-plugin\";\nexport { textPlugin } from \"./plugins/text-plugin\";\nexport { videoPlugin } from \"./plugins/video-plugin\";\nexport { xlsxPlugin } from \"./plugins/xlsx-plugin\";\nexport { zipPlugin } from \"./plugins/zip-plugin\";\n\n// ─── Remote URL loader ────────────────────────────────────────────────────\nexport {\n processRemoteUrl,\n RemoteUrlError,\n DEFAULT_REMOTE_MAX_BYTES,\n type RemoteUrlErrorCode,\n type RemoteLoadProgress,\n type ProcessRemoteUrlOptions,\n} from \"./remote-url\";\n\n// ─── React hooks ──────────────────────────────────────────────────────────\nexport {\n useSourceText,\n type SourceTextState,\n} from \"./hooks/useSourceText\";\nexport {\n useSourceBase64,\n type SourceBase64State,\n} from \"./hooks/useSourceBase64\";\nexport { useObjectUrlFromSource } from \"./hooks/useObjectUrlFromSource\";\n"],"mappings":"AAaA;AAAA,EACE;AAAA,OAEK;AASP,SAAS,sBAAsB;AAE/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,sBAAsB;AAG/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAGP,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,OAKK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qBAAqB;AAG9B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAGP,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,wBAAwB;AACjC,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAG1B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,OAEK;AACP,SAAS,8BAA8B;","names":[]}
|
|
@@ -2,6 +2,7 @@ import { PreviewPluginRegistry } from '../core/registry.js';
|
|
|
2
2
|
import { PreviewPlugin } from '../core/plugin.js';
|
|
3
3
|
import '../core/types.js';
|
|
4
4
|
import 'react';
|
|
5
|
+
import '../core/preview-error.js';
|
|
5
6
|
|
|
6
7
|
declare const builtinPreviewPlugins: PreviewPlugin[];
|
|
7
8
|
declare function createBuiltinPreviewRegistry(): PreviewPluginRegistry;
|