59 lines
2.5 KiB
JavaScript
59 lines
2.5 KiB
JavaScript
// 배포 텍스트에는 한자를 두지 않는다. 이미지처럼 텍스트가 아닌 자산은 이 검사의 대상이 아니다.
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import url from "node:url";
|
|
|
|
const here = path.dirname(url.fileURLToPath(import.meta.url));
|
|
const root = path.resolve(here, "..");
|
|
const TEXT_EXTENSIONS = new Set([".astro", ".css", ".html", ".js", ".json", ".mjs", ".svg", ".ts", ".tsx", ".txt", ".webmanifest", ".xml"]);
|
|
const HANJA = /[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/u;
|
|
const HANJA_GLOBAL = /[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/gu;
|
|
|
|
function scanRoots(argv) {
|
|
const roots = [];
|
|
for (let index = 2; index < argv.length; index += 1) {
|
|
const argument = argv[index];
|
|
const value = argument === "--root" ? argv[++index] : argument.startsWith("--root=") ? argument.slice("--root=".length) : null;
|
|
if (!value) throw new Error(`Unknown or incomplete argument: ${argument}`);
|
|
const candidate = path.resolve(root, value);
|
|
if (candidate !== root && !candidate.startsWith(root + path.sep)) throw new Error(`Root must stay inside apps/site: ${value}`);
|
|
roots.push(candidate);
|
|
}
|
|
return roots.length ? roots : [path.join(root, "src"), path.join(root, "public")];
|
|
}
|
|
|
|
function textFiles(directory) {
|
|
const files = [];
|
|
const walk = (current) => {
|
|
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
const candidate = path.join(current, entry.name);
|
|
if (entry.isDirectory()) walk(candidate);
|
|
else if (entry.isFile() && TEXT_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) files.push(candidate);
|
|
}
|
|
};
|
|
walk(directory);
|
|
return files;
|
|
}
|
|
|
|
const failures = [];
|
|
let scanned = 0;
|
|
for (const scanRoot of scanRoots(process.argv)) {
|
|
if (!fs.existsSync(scanRoot)) throw new Error(`Scan root does not exist: ${path.relative(root, scanRoot) || "."}`);
|
|
for (const file of textFiles(scanRoot)) {
|
|
scanned += 1;
|
|
const lines = fs.readFileSync(file, "utf8").split(/\r?\n/);
|
|
lines.forEach((line, index) => {
|
|
if (!HANJA.test(line)) return;
|
|
const characters = [...new Set(line.match(HANJA_GLOBAL) || [])].join("");
|
|
failures.push(`${path.relative(root, file).replaceAll("\\", "/")}:${index + 1} contains ${characters}`);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (failures.length) {
|
|
console.error(`FAIL: ${failures.length} Hanja occurrence(s) across ${scanned} shipped text files.`);
|
|
for (const failure of failures) console.error(` ${failure}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`PASS: ${scanned} shipped text files contain no Hanja.`);
|