All files / src/lib csv.ts

100% Statements 7/7
100% Branches 0/0
100% Functions 2/2
100% Lines 6/6

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                                          3x               4x 4x 4x       21x   4x    
/**
 * CSV helpers for the Room HTTP layer.
 *
 * - `csvToSocialCalc` converts a CSV string to a SocialCalc save string by
 *   delegating to the `csvToSave` wrapper in `@ethercalc/socialcalc-headless`,
 *   which calls `SocialCalc.ConvertOtherFormatToSave(csv, 'csv')`. This is
 *   the same entry point the legacy `src/main.ls` used via the `J` library
 *   (J.utils.to_socialcalc produces an object keyed by sheet name — we only
 *   consume the primary sheet here, matching the legacy `for k, save of …`
 *   first-iteration behavior).
 *
 * - `decodeDoubleEncoded` reproduces the `text/x-ethercalc-csv-double-encoded`
 *   round-trip (§7 item 4 in CLAUDE.md): UTF-8 decode → Latin-1 encode →
 *   UTF-8 decode. Legacy did this via `iconv-lite` (Node-only); we use the
 *   platform `TextDecoder('latin1')` / `TextEncoder` which is available in
 *   both workerd and Node 20+.
 */
import { csvToSave } from '@ethercalc/socialcalc-headless';
 
/** Convert a CSV string to a SocialCalc save string. */
export function csvToSocialCalc(csv: string): string {
  return csvToSave(csv);
}
 
/**
 * Re-encode a UTF-8 → Latin-1 → UTF-8 double-encoded body. Equivalent to
 * the legacy `iconv-lite` triple-step.
 */
export function decodeDoubleEncoded(bytes: Uint8Array): string {
  const first = new TextDecoder('utf-8').decode(bytes);
  const latin1Bytes = new Uint8Array(first.length);
  for (let i = 0; i < first.length; i++) {
    // Latin-1 is a strict subset of Unicode up to U+00FF; code points above
    // that never survived the original round-trip either (legacy would have
    // produced the same replacement character). Mask to 8 bits.
    latin1Bytes[i] = first.charCodeAt(i) & 0xff;
  }
  return new TextDecoder('utf-8').decode(latin1Bytes);
}