Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 1x 16x 16x 16x 16x 16x 16x 1x 8x 8x 1x 8x 8x 8x 10x 10x 9x 9x 8x 8x 8x 8x 10x 7x 7x 7x 7x 7x 7x 7x 7x 8x 8x | import type { SubtitleCue } from "./types";
/** Parse "HH:MM:SS,mmm" or "HH:MM:SS.mmm" into seconds. */
const parseTimestamp = (ts: string): number => {
const clean = ts.trim().replace(",", ".");
const parts = clean.split(":");
if (parts.length !== 3) return 0;
const [h, m, s] = parts.map(Number);
return h * 3600 + m * 60 + s;
};
/** Strip SRT/HTML tags (<i>, <b>, <font ...>, etc.) from subtitle text. */
const stripTags = (text: string): string => {
return text.replace(/<[^>]+>/g, "").trim();
};
/** Parse SRT file content into an array of SubtitleCue objects. */
export const parseSrt = (content: string): SubtitleCue[] => {
const cues: SubtitleCue[] = [];
// Normalise line endings and split into blocks
const blocks = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim().split(/\n\n+/);
for (const block of blocks) {
const lines = block.trim().split("\n");
if (lines.length < 2) continue;
// Find the timestamp line (contains "-->")
const tsIdx = lines.findIndex((l) => l.includes("-->"));
if (tsIdx === -1) continue;
const tsParts = lines[tsIdx].split("-->");
if (tsParts.length !== 2) continue;
const start = parseTimestamp(tsParts[0]);
const end = parseTimestamp(tsParts[1]);
if (isNaN(start) || isNaN(end) || end <= start) continue;
// Everything after the timestamp line is the subtitle text
const text = lines
.slice(tsIdx + 1)
.map(stripTags)
.filter(Boolean)
.join("\n");
if (!text) continue;
cues.push({ start, end, text });
}
return cues;
};
|