Parse CSV text into row objects

JavaScript
// Parse CSV text (RFC 4180 style) into header-keyed objects.
function parseCsv(text) {
  const rows = [];
  let row = [];
  let field = '';
  let quoted = false;

  for (let i = 0; i < text.length; i += 1) {
    const char = text[i];
    if (quoted) {
      if (char === '"' && text[i + 1] === '"') { field += '"'; i += 1; }
      else if (char === '"') quoted = false;
      else field += char;
    } else if (char === '"') quoted = true;
    else if (char === ',') { row.push(field); field = ''; }
    else if (char === '\n') { row.push(field); rows.push(row); row = []; field = ''; }
    else if (char !== '\r') field += char;
  }
  if (field !== '' || row.length > 0) { row.push(field); rows.push(row); }

  const [header, ...body] = rows;
  return body
    .filter((cells) => cells.some((cell) => cell !== ''))
    .map((cells) => Object.fromEntries(header.map((key, index) => [key, cells[index] ?? ''])));
}

const csv = 'name,role\n"Ada, Lovelace",analyst\nGrace,engineer\n';
console.log(parseCsv(csv));
// [{ name: 'Ada, Lovelace', role: 'analyst' }, { name: 'Grace', role: 'engineer' }]