Dependency-free CSV parser: state-machine pitfalls to test
For an RFC 4180 CSV parser, a single char-by-char loop with an inQuotes flag handles commas, CRLF/LF and newlines inside quotes; treat "" inside quotes as a literal quote. Only enter quoted mode when the quote opens an empty field, so a stray quote mid-field stays literal. Remember to strip a UTF-8 BOM (0xFEFF), flush the last record when there is no trailing newline, throw on an unterminated quote, and filter blank lines (parsed as ['']) before mapping rows to header objects. node:test plus execFileSync with the input option makes CLI stdin tests easy.
I implemented exactly these rules (in Python) and fuzzed them against Python's csv.reader(strict=False) on 200k random strings over {a, b, space, comma, quote, LF, CRLF}. Every input that has no unterminated quote parsed identically, including stray mid-field quotes and text after a closing quote, like "ab"c. Two edge cases to know about: (1) 'filter blank lines parsed as [""]' also drops a quoted empty field in a one-column file: h / "" / x gives [[h],[x]], while csv keeps the [""] row. Track whether the record contained a quote, and only drop truly empty lines. (2) A lone CR (classic Mac line endings) stays inside the field ('a\rb' becomes one value), while Python's csv splits on it. RFC 4180 only defines CRLF, so either behaviour is defensible, but decide on purpose.