Spaces:
Sleeping
Sleeping
| import { readFileSync } from "fs"; | |
| import { resolve } from "path"; | |
| const envContent = readFileSync(resolve(import.meta.dirname, "../.env"), "utf-8"); | |
| for (const line of envContent.split("\n")) { | |
| const t = line.trim(); if (!t || t.startsWith("#")) continue; | |
| const e = t.indexOf("="); if (e < 0) continue; | |
| if (!process.env[t.slice(0, e)]) process.env[t.slice(0, e)] = t.slice(e + 1); | |
| } | |
| import { detectFormat } from "../src/lib/gts/formats"; | |
| import { richTextToPlain } from "../src/lib/gts/models/text"; | |
| import { runNetflixChecks } from "../src/lib/qc/netflix-checks"; | |
| import { runRuleChecks } from "../src/lib/qc/rule-checks"; | |
| import type { QCLine } from "../src/lib/qc/types"; | |
| const TEST_DIR = resolve(import.meta.dirname, "../test-pmws"); | |
| const manifest = JSON.parse(readFileSync(resolve(TEST_DIR, "manifest.json"), "utf-8")) as Array<{ | |
| lang: string; | |
| file: string; | |
| sensitiveTermCount: number; | |
| glyphViolationCount: number; | |
| expectedIssues: number; | |
| [key: string]: any; | |
| }>; | |
| console.log(`=== QC VALIDATION: ${manifest.length} PMW files ===`); | |
| console.log(""); | |
| let totalFiles = 0; | |
| let passedFiles = 0; | |
| let failedFiles = 0; | |
| const failures: string[] = []; | |
| for (const entry of manifest) { | |
| totalFiles++; | |
| const filePath = resolve(TEST_DIR, entry.file); | |
| try { | |
| // Parse PMW | |
| const buf = readFileSync(filePath); | |
| const handler = detectFormat(buf, entry.file); | |
| if (!handler) { | |
| console.log(`β ${entry.lang.padEnd(8)} | PARSE FAILED: format not detected`); | |
| failedFiles++; | |
| failures.push(`${entry.lang}: format not detected`); | |
| continue; | |
| } | |
| const doc = handler.read(buf, entry.file); | |
| const track = doc.tracks[0]; | |
| const lines: QCLine[] = track.subtitles.map((sub, i) => ({ | |
| id: i + 1, | |
| text: typeof sub.text === "string" ? sub.text : richTextToPlain(sub.text), | |
| })); | |
| // Run Netflix checks (glyph + sensitive terms) | |
| const netflixIssues = runNetflixChecks(lines, entry.lang); | |
| const glyphIssues = netflixIssues.filter((i) => i.category === "glyph"); | |
| const sensitiveIssues = netflixIssues.filter((i) => i.category === "sensitive"); | |
| // Also run rule checks | |
| const ruleIssues = runRuleChecks(lines, entry.lang); | |
| // Validate: did we detect at least as many as expected? | |
| // Note: some terms may match multiple times in different contexts, so actual >= expected | |
| const sensitiveOk = sensitiveIssues.length >= entry.sensitiveTermCount; | |
| const glyphOk = glyphIssues.length >= entry.glyphViolationCount; | |
| const status = sensitiveOk && glyphOk ? "β" : "β"; | |
| if (sensitiveOk && glyphOk) { | |
| passedFiles++; | |
| } else { | |
| failedFiles++; | |
| if (!sensitiveOk) failures.push(`${entry.lang}: sensitive ${sensitiveIssues.length}/${entry.sensitiveTermCount}`); | |
| if (!glyphOk) failures.push(`${entry.lang}: glyph ${glyphIssues.length}/${entry.glyphViolationCount}`); | |
| } | |
| console.log( | |
| `${status} ${entry.lang.padEnd(8)} | ` + | |
| `sensitive: ${String(sensitiveIssues.length).padStart(4)}/${String(entry.sensitiveTermCount).padStart(4)} ` + | |
| `${sensitiveOk ? "β" : "β"} | ` + | |
| `glyph: ${String(glyphIssues.length).padStart(2)}/${String(entry.glyphViolationCount).padStart(2)} ` + | |
| `${glyphOk ? "β" : "β"} | ` + | |
| `rule: ${String(ruleIssues.length).padStart(3)} | ` + | |
| `total: ${netflixIssues.length + ruleIssues.length}` | |
| ); | |
| } catch (err) { | |
| failedFiles++; | |
| const msg = (err as Error).message.substring(0, 60); | |
| console.log(`β ${entry.lang.padEnd(8)} | ERROR: ${msg}`); | |
| failures.push(`${entry.lang}: ${msg}`); | |
| } | |
| } | |
| console.log(""); | |
| console.log("=== SUMMARY ==="); | |
| console.log(`Files: ${totalFiles}`); | |
| console.log(`Passed: ${passedFiles}`); | |
| console.log(`Failed: ${failedFiles}`); | |
| console.log(""); | |
| if (failures.length > 0) { | |
| console.log("FAILURES:"); | |
| for (const f of failures) console.log(` ${f}`); | |
| } else { | |
| console.log("ALL 32 LANGUAGES PASSED β"); | |
| } | |
| // Aggregate stats | |
| const totalSensitive = manifest.reduce((s, e) => s + e.sensitiveTermCount, 0); | |
| const totalGlyphs = manifest.reduce((s, e) => s + e.glyphViolationCount, 0); | |
| console.log(""); | |
| console.log(`Injected: ${totalSensitive} sensitive terms + ${totalGlyphs} illegal glyphs across ${totalFiles} files`); | |