Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| /** | |
| * Parse clipboard text into a 2-D matrix of cells. | |
| * Recognizes three formats, in order: | |
| * 1. Markdown / GFM pipe tables (`| col | col |` with optional `|---|---|` separator) | |
| * 2. TSV (Excel / Google Sheets default copy format) | |
| * 3. CSV with quoted-comma support | |
| */ | |
| export function parseClipboardTable(text: string): string[][] { | |
| const stripped = text.replace(/\r\n?/g, "\n").replace(/\n+$/, ""); | |
| if (!stripped) return []; | |
| const lines = stripped.split("\n"); | |
| // ββ 1) Markdown pipe table βββββββββββββββββββββββββββββββββββββββββββββ | |
| const nonEmpty = lines.filter((l) => l.trim().length > 0); | |
| const pipedLines = nonEmpty.filter((l) => l.includes("|")); | |
| const pipeCount = (stripped.match(/\|/g) ?? []).length; | |
| const tabCount = (stripped.match(/\t/g) ?? []).length; | |
| const isMarkdownTable = | |
| pipedLines.length >= 2 && | |
| pipedLines.length === nonEmpty.length && | |
| pipeCount > tabCount; | |
| if (isMarkdownTable) { | |
| const splitMdRow = (line: string): string[] => { | |
| let s = line.trim(); | |
| if (s.startsWith("|")) s = s.slice(1); | |
| if (s.endsWith("|")) s = s.slice(0, -1); | |
| return s.split("|").map((c) => c.trim()); | |
| }; | |
| const isSeparatorRow = (cells: string[]) => | |
| cells.length > 0 && cells.every((c) => /^:?-{2,}:?$/.test(c.trim())); | |
| return nonEmpty.map(splitMdRow).filter((cells) => !isSeparatorRow(cells)); | |
| } | |
| // ββ 2) TSV / 3) CSV βββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const hasTabs = stripped.includes("\t"); | |
| return lines.map((line) => | |
| hasTabs | |
| ? line.split("\t") | |
| : (line.match(/("([^"]|"")*"|[^,]*)(,|$)/g) ?? []) | |
| .filter((_, i, a) => i < a.length - 1 || a[i] !== "") | |
| .map((tok) => tok.replace(/,$/, "").trim().replace(/^"(.*)"$/, "$1").replace(/""/g, '"')), | |
| ); | |
| } | |