/* spreadsheet_clipboard.ts 의 TSV(밖 → 안, DOM 없이 되는 부분)만 — 값 · 참거짓 · 「엑셀 수식 표시」 식 잡기(끝수 · 「=」 한 글자는 글). HTML(DOMParser) 쪽은 ORCA 화면 시험으로. 진짜 앱 별칭(`@ui` 등)까지 그대로 vite 로 번들해 Node 로 돌린다(`build:formula` 방식) — A(주소) · B(형식) 는 부르지 않는 길만 시험하므로 0 계약 몸(던짐)이어도 됨. */ import assert from "node:assert/strict"; import { execFileSync } from "node:child_process"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { pathToFileURL } from "node:url"; const out = mkdtempSync(join(tmpdir(), "aislo-ss-clip-")); execFileSync( process.execPath, [ "./config/node_modules/vite/bin/vite.js", "build", "--configLoader", "runner", "--ssr", "spreadsheet/spreadsheet_clipboard.ts", "--outDir", out, ], { stdio: "inherit" }, ); const { parseClipboard } = await import(pathToFileURL(join(out, "spreadsheet_clipboard.js")).href); const at = { r: 0, c: 0 }; // 값 · 참거짓 잡기 { const block = parseClipboard("", "10\t20\nTRUE\t3.5", at); assert.equal(block.rows, 2); assert.equal(block.cols, 2); assert.deepEqual(block.칸["0,0"], { 값: 10 }); assert.deepEqual(block.칸["1,0"], { 값: true }); assert.deepEqual(block.칸["1,1"], { 값: 3.5 }); assert.equal(block.출처, "text"); assert.equal(block.원점, null); } // 「=」 뒤에 글이 있으면 식 · 한 글자 「=」 는 글(엑셀 「수식 표시」 대응) { const block = parseClipboard("", "=SUM(A1:A2)\t=", at); assert.deepEqual(block.칸["0,0"], { 식: "SUM(A1:A2)" }); assert.deepEqual(block.칸["0,1"], { 값: "=" }); } // 빈 칸은 안 적음(성긴 모양) · 끝 빈 줄 버림 { const block = parseClipboard("", "a\t\tb\n\n", at); assert.equal(Object.keys(block.칸).length, 2); assert.equal(block.rows, 1); assert.equal(block.cols, 3); } // 읽을 것 없으면 null { assert.equal(parseClipboard("", "", at), null); } console.log("OK — 클립보드 TSV 값 · 참거짓 · 「수식 표시」 식 잡기");