chore: address code quality audit findings
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled

This commit is contained in:
Tom Boullay
2026-05-28 08:31:42 +02:00
parent 947025cbf5
commit d654565f87
73 changed files with 890 additions and 1457 deletions
+49 -12
View File
@@ -5,48 +5,85 @@ export interface SubtitleCue {
text: string;
}
interface SrtParseDiagnostic {
blockIndex: number;
reason: string;
}
export interface SrtParseResult {
cues: SubtitleCue[];
diagnostics: SrtParseDiagnostic[];
}
const SRT_TIME_SEPARATOR = " --> ";
const SRT_TIME_PATTERN = /^(\d{2}):(\d{2}):(\d{2}),(\d{3})$/;
export function parseSrt(srtContent: string): SubtitleCue[] {
return srtContent
return parseSrtWithDiagnostics(srtContent).cues;
}
export function parseSrtWithDiagnostics(srtContent: string): SrtParseResult {
const diagnostics: SrtParseDiagnostic[] = [];
const cues = srtContent
.replace(/^\uFEFF/, "")
.replace(/\r/g, "")
.trim()
.split(/\n{2,}/)
.map(parseSrtBlock)
.map((block, blockIndex) => {
const result = parseSrtBlock(block);
if (!result.cue) {
diagnostics.push({ blockIndex, reason: result.reason });
}
return result.cue;
})
.filter((cue): cue is SubtitleCue => cue !== null);
return { cues, diagnostics };
}
function parseSrtBlock(block: string): SubtitleCue | null {
function parseSrtBlock(block: string): {
cue: SubtitleCue | null;
reason: string;
} {
const lines = block
.split("\n")
.map((line) => line.trim())
.filter(Boolean);
if (lines.length < 3) return null;
if (lines.length < 3) {
return { cue: null, reason: "missing index, timecode, or text" };
}
const index = Number(lines[0]);
if (!Number.isInteger(index)) return null;
if (!Number.isInteger(index)) {
return { cue: null, reason: "invalid cue index" };
}
const [start, end] = lines[1]?.split(SRT_TIME_SEPARATOR) ?? [];
if (!start || !end) return null;
if (!start || !end) {
return { cue: null, reason: "invalid timecode separator" };
}
const startTime = parseSrtTime(start);
const endTime = parseSrtTime(end);
if (startTime === null || endTime === null || endTime <= startTime) {
return null;
return { cue: null, reason: "invalid cue duration" };
}
return {
index,
startTime,
endTime,
text: lines.slice(2).join("\n"),
cue: {
index,
startTime,
endTime,
text: lines.slice(2).join("\n"),
},
reason: "",
};
}
function parseSrtTime(value: string): number | null {
export function parseSrtTime(value: string): number | null {
const match = value.match(SRT_TIME_PATTERN);
if (!match) return null;