+31
-4
@@ -12,6 +12,35 @@ export interface EdlImportRow {
|
|||||||
existingShotId?: string;
|
existingShotId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parse a single CSV line, handling quoted fields and escaped double-quotes. */
|
||||||
|
function parseCsvLine(line: string): string[] {
|
||||||
|
const result: string[] = [];
|
||||||
|
let current = "";
|
||||||
|
let inQuotes = false;
|
||||||
|
for (let i = 0; i < line.length; i++) {
|
||||||
|
const ch = line[i];
|
||||||
|
if (inQuotes) {
|
||||||
|
if (ch === '"') {
|
||||||
|
if (line[i + 1] === '"') { current += '"'; i++; } // escaped ""
|
||||||
|
else { inQuotes = false; }
|
||||||
|
} else {
|
||||||
|
current += ch;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ch === '"') {
|
||||||
|
inQuotes = true;
|
||||||
|
} else if (ch === ',') {
|
||||||
|
result.push(current.trim());
|
||||||
|
current = "";
|
||||||
|
} else {
|
||||||
|
current += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push(current.trim());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a VFX pull CSV into import rows.
|
* Parse a VFX pull CSV into import rows.
|
||||||
* Output Name format: {showId}_{episode}_{scene}_{shot}_BG01_TT_v001
|
* Output Name format: {showId}_{episode}_{scene}_{shot}_BG01_TT_v001
|
||||||
@@ -22,9 +51,7 @@ export function parseEdlCsv(csvText: string): { rows: EdlImportRow[]; errors: st
|
|||||||
const lines = csvText.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
const lines = csvText.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
||||||
if (lines.length < 2) return { rows: [], errors: ["CSV must have a header row and at least one data row"] };
|
if (lines.length < 2) return { rows: [], errors: ["CSV must have a header row and at least one data row"] };
|
||||||
|
|
||||||
const unquote = (s: string) => s.replace(/^"|"$/g, "").trim();
|
const rawHeaders = parseCsvLine(lines[0]).map((h) => h.toLowerCase());
|
||||||
|
|
||||||
const rawHeaders = lines[0].split(",").map(unquote).map((h) => h.toLowerCase());
|
|
||||||
const col = (name: string) => rawHeaders.indexOf(name);
|
const col = (name: string) => rawHeaders.indexOf(name);
|
||||||
|
|
||||||
const outNameIdx = col("output name");
|
const outNameIdx = col("output name");
|
||||||
@@ -41,7 +68,7 @@ export function parseEdlCsv(csvText: string): { rows: EdlImportRow[]; errors: st
|
|||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
|
|
||||||
for (let i = 1; i < lines.length; i++) {
|
for (let i = 1; i < lines.length; i++) {
|
||||||
const cells = lines[i].match(/("(?:[^"]|"")*"|[^,]*)/g)?.map(unquote) ?? [];
|
const cells = parseCsvLine(lines[i]);
|
||||||
const get = (idx: number) => (idx !== -1 ? cells[idx] ?? "" : "");
|
const get = (idx: number) => (idx !== -1 ? cells[idx] ?? "" : "");
|
||||||
|
|
||||||
const outputName = get(outNameIdx);
|
const outputName = get(outNameIdx);
|
||||||
|
|||||||
Reference in New Issue
Block a user