- Add LargeFilePolicy union type ("default" | "off" | PreviewSizePolicyConfig)
with validatePreviewSizePolicy / resolvePreviewSizePolicy helpers; validator
rejects Infinity/NaN and inverted thresholds
- LargeFileGate accepts policy / onError / renderBlockedFallback props; all
UI strings externalized via useLocale (5 new locale fields); block report
dedup keyed on id+size+name so contract-violating id reuse still re-reports
- PluginPreviewRenderer passes through largeFilePolicy and
renderLargeFileFallback; unsupported branch now also goes through gate
- downloadSource refactored by source kind (file/blob/arrayBuffer/url);
caller mimeType overrides response Content-Type; network/HTTP errors
normalized to PreviewError (REMOTE_CORS_ERROR / REMOTE_HTTP_ERROR)
- Tests cover custom maxBytes, tiered policy, FILE_TOO_LARGE onError,
custom renderLargeFileFallback; tests pin LocaleProvider value={zhCN}
- Demo app shows 4 policy variants with onError telemetry pattern and
policy-derived UI label (no hardcoded strings to drift)
- README documents the largeFilePolicy API and user-input safety pattern
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
46 lines
1.3 KiB
TypeScript
46 lines
1.3 KiB
TypeScript
import { defineConfig } from "tsup";
|
|
import { promises as fs } from "node:fs";
|
|
import path from "node:path";
|
|
|
|
/**
|
|
* Recursively copy non-source side-effect files (CSS) from src/ to dist/
|
|
* so consumer bundlers can resolve `import "./styles/Foo.css"` exactly the
|
|
* way it appears in the source.
|
|
*/
|
|
async function copyNonSourceAssets(srcDir: string, destDir: string) {
|
|
const entries = await fs.readdir(srcDir, { withFileTypes: true });
|
|
for (const entry of entries) {
|
|
if (entry.name === "__tests__") continue;
|
|
const srcPath = path.join(srcDir, entry.name);
|
|
const destPath = path.join(destDir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
await fs.mkdir(destPath, { recursive: true });
|
|
await copyNonSourceAssets(srcPath, destPath);
|
|
} else if (entry.name.endsWith(".css")) {
|
|
await fs.copyFile(srcPath, destPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
export default defineConfig({
|
|
entry: [
|
|
"src/**/*.ts",
|
|
"src/**/*.tsx",
|
|
"!src/**/*.test.ts",
|
|
"!src/**/*.test.tsx",
|
|
"!src/**/__tests__/**",
|
|
"!src/**/*.d.ts",
|
|
],
|
|
format: ["esm"],
|
|
dts: true,
|
|
bundle: false, // preserve module structure — better for code-splitting and CSS side-imports
|
|
splitting: false,
|
|
sourcemap: true,
|
|
clean: true,
|
|
target: "es2020",
|
|
external: ["react", "react-dom"],
|
|
async onSuccess() {
|
|
await copyNonSourceAssets("src", "dist");
|
|
},
|
|
});
|