Files
multica/scripts/generate-attachment-text-preview.mjs
802f0894e0 refactor(attachments): generate text preview whitelist (MUL-8248) (#9527)
* refactor(attachments): generate text preview whitelist

Co-authored-by: Cursor <[email protected]>

* fix(attachments): gate text previews on shared whitelist (MUL-8248)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 13:38:42 +08:00

77 lines
2.2 KiB
JavaScript

#!/usr/bin/env node
// Regenerates the TypeScript attachment text-preview whitelist from the JSON
// source embedded by the Go handler.
import { readFileSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const jsonPath = resolve(
repoRoot,
"server/internal/handler/attachment_text_preview.json",
);
const tsPath = resolve(
repoRoot,
"packages/views/editor/utils/text-preview-whitelist.generated.ts",
);
const data = JSON.parse(readFileSync(jsonPath, "utf8"));
const fields = [
["content_type_prefixes", "TEXT_PREVIEW_CONTENT_TYPE_PREFIXES"],
["content_types", "TEXT_PREVIEW_CONTENT_TYPES"],
["extensions", "TEXT_PREVIEW_EXTENSIONS"],
["basenames", "TEXT_PREVIEW_BASENAMES"],
];
for (const [jsonName] of fields) {
validateStringList(jsonName, data[jsonName]);
}
const lines = [
"// AUTO-GENERATED by scripts/generate-attachment-text-preview.mjs.",
"// Do not edit by hand — edit",
"// server/internal/handler/attachment_text_preview.json and run",
"// `pnpm generate:attachment-text-preview`.",
"",
];
for (const [jsonName, exportName] of fields) {
lines.push(`export const ${exportName}: ReadonlySet<string> = new Set([`);
for (const value of data[jsonName]) {
lines.push(` ${JSON.stringify(value)},`);
}
lines.push("]);");
lines.push("");
}
writeFileSync(tsPath, lines.join("\n"));
function validateStringList(name, value) {
if (!Array.isArray(value) || value.length === 0) {
throw new Error(
`attachment_text_preview.json: "${name}" must be a non-empty array`,
);
}
const seen = new Set();
for (const entry of value) {
if (
typeof entry !== "string" ||
entry.length === 0 ||
entry !== entry.trim() ||
entry !== entry.toLowerCase()
) {
throw new Error(
`attachment_text_preview.json: "${name}" entries must be non-empty, trimmed lowercase strings`,
);
}
if (seen.has(entry)) {
throw new Error(
`attachment_text_preview.json: duplicate ${name} entry ${JSON.stringify(entry)}`,
);
}
seen.add(entry);
}
}