refactor: convert to bun-workspaces monorepo (desktop/ + www/)
- Move the Tauri app (React frontend + Rust backend) into desktop/ via git mv — configs unchanged (relative paths: tauri.conf.json, vite.config.ts) - Root package.json becomes a private bun workspace container with orchestration scripts; desktop package renamed gridline-desktop - Scaffold www/ with Astro 7 + Tailwind v4 (hand-wired vite plugin, static output, ready for Dokploy) - Update release.yml for the new layout: projectPath: desktop, desktop/src-tauri resource paths, rust-cache workspace path - Update README + AGENTS.md structure trees and dev commands - Verified: vitest (1074), cargo test (354), desktop build, tauri dev (window launches), tauri build (dmg + app bundles), Astro build
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
export interface ParsedCsv {
|
||||
headers: string[];
|
||||
rows: string[][];
|
||||
}
|
||||
|
||||
export function parseCsv(input: string): ParsedCsv {
|
||||
const text = input.replace(/^\uFEFF/, "");
|
||||
if (text.trim() === "") throw new Error("CSV input is empty");
|
||||
|
||||
const rows: string[][] = [];
|
||||
let field = "";
|
||||
let row: string[] = [];
|
||||
let inQuotes = false;
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const ch = text[i];
|
||||
if (inQuotes) {
|
||||
if (ch === '"') {
|
||||
if (text[i + 1] === '"') { field += '"'; i++; }
|
||||
else inQuotes = false;
|
||||
} else field += ch;
|
||||
} else if (ch === '"') {
|
||||
inQuotes = true;
|
||||
} else if (ch === ',') {
|
||||
row.push(field); field = "";
|
||||
} else if (ch === '\n' || ch === '\r') {
|
||||
if (ch === '\r' && text[i + 1] === '\n') i++;
|
||||
row.push(field); field = "";
|
||||
rows.push(row); row = [];
|
||||
} else field += ch;
|
||||
}
|
||||
if (field !== "" || row.length > 0) { row.push(field); rows.push(row); }
|
||||
if (rows.length === 0) throw new Error("CSV input is empty");
|
||||
|
||||
const [headers, ...data] = rows;
|
||||
const width = headers.length;
|
||||
const padded = data.map((r) => {
|
||||
const out = r.slice(0, width);
|
||||
while (out.length < width) out.push("");
|
||||
return out;
|
||||
});
|
||||
return { headers, rows: padded };
|
||||
}
|
||||
Reference in New Issue
Block a user