Files
Aislo/resources/tester/spreadsheet/helper_spreadsheet_d.cjs
T
eomsangdonandClaude Opus 5.5 a2011c8035 feat(spreadsheet): D 입력 — 고름 · 칸 편집기 · 한글 조합 · 수식 입력줄 · 참조 가리키기 · 단축키 · 채우기 끌기 · 잇기
- spreadsheet.ts — createSpreadsheet 잇기(문맥 · 명령 → 되돌림 → 엔진 → 격자 · onChange · onSelect · 시트마다 고름 기억) · parts 한 곳(시험 틀이 빈 몸 부품을 바꿔 끼움)
- spreadsheet_selection.ts — 병합으로 늘림 · Shift/Ctrl 방향 · 숨김 건너뜀 · 행열 머리 · 고름 안 Enter/Tab 돌기
- spreadsheet_editor.ts — 숨은 textarea 늘 초점 · compositionstart/input 로 편집 시작 · enter/edit 방식 · 수식 입력줄 · 주소 상자 · 참조 넣기 · 색 테두리 · 입력 글 규칙(' · % · 천 단위)
- spreadsheet_keys.ts · spreadsheet_mouse.ts — 엑셀 단축키 · 끌기 고르기 · 채우기 핸들(늘림 · 줄여 지움 · 두 번 누르면 아래로) · 우클릭 자리
- 시험 resources/tester/spreadsheet — 규칙 7 묶음 · 가짜 부품 번들 시험 틀 html(ORCA)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L6KXAabDTenEU7hrDQmCKY
2026-09-27 20:22:02 +09:00

103 lines
3.6 KiB
JavaScript

/* 스프레드시트 D 순수 규칙 시험 도우미 — 고름 · 입력 글 규칙 · 가리키기 자리 · 채우기 끌기 목표.
* pytest(test_spreadsheet_d_input.py)가 부르고 결과 JSON 을 판정. */
const path = require("path");
const { load, SS } = require("./helper_spreadsheet_d_bundle.cjs");
const sel = load(path.join(SS, "spreadsheet_selection.ts"));
const ed = load(path.join(SS, "spreadsheet_editor.ts"));
const mouse = load(path.join(SS, "spreadsheet_mouse.ts"));
const addr = load(path.join(SS, "spreadsheet_address.ts"));
const sample = require(path.join(SS, "spreadsheet_sample.json"));
const s1 = sample.시트[0];
const a1 = (s) => `${addr.toA1(s.활성.r, s.활성.c)}|${addr.rangeToA1(s.범위[0])}`;
const cell = (r, c) => sel.selectCell(s1, r, c);
const keys = (start, list) => {
let s = start;
return list.map(([dr, dc, o]) => a1((s = sel.move(s1, s, dr, dc, o || {}))));
};
const out = {
// 병합 C4:F4 안을 누르면 병합 전체 · 활성은 왼위
mergeClick: a1(cell(3, 4)),
// 병합에서 오른쪽 → G4 · 왼쪽 → B4
mergeMove: keys(cell(3, 2), [
[0, 1],
[0, -1],
[0, -1],
]),
// Shift+→ 두 번(병합 걸침) · Shift+← 줄임 · Shift+↓
shiftExtend: keys(cell(3, 0), [
[0, 1, { extend: true }],
[0, 1, { extend: true }],
[0, -1, { extend: true }],
[1, 0, { extend: true }],
]),
// Ctrl+↓ 값 뭉치 끝 → 시트 끝 · Ctrl+↑ 되돌아 값
ctrlJump: keys(cell(2, 0), [
[1, 0, { jump: true }],
[1, 0, { jump: true }],
[-1, 0, { jump: true }],
]),
// 숨긴 열 J 건너뜀(I → K)
hiddenSkip: keys(cell(0, 8), [[0, 1]]).map((x) => x.split("|")[0]),
// 열 머리 C — 병합 C3:F3 걸쳐 C:F
colHead: addr.rangeToA1(sel.selectCols(s1, 2, 2).범위[0]),
// 고름 안 Enter 돌기(열 먼저) · Tab(행 먼저)
cycleEnter: (() => {
let s = {
시트: "s1",
범위: [{ r0: 10, c0: 10, r1: 11, c1: 11 }],
활성: { r: 10, c: 10 },
기준: { r: 10, c: 10 },
};
return [1, 1, 1, 1].map(() => addr.toA1((s = sel.cycle(s1, s, 1, 0)).활성.r, s.활성.c));
})(),
cycleTab: (() => {
let s = {
시트: "s1",
범위: [{ r0: 10, c0: 10, r1: 11, c1: 11 }],
활성: { r: 10, c: 10 },
기준: { r: 10, c: 10 },
};
return [1, 1, 1].map(() => addr.toA1((s = sel.cycle(s1, s, 0, 1)).활성.r, s.활성.c));
})(),
cycleSingle: sel.cycle(s1, cell(3, 2), 1, 0),
usedEnd: addr.toA1(sel.usedEnd(s1).r, sel.usedEnd(s1).c),
// 입력 글 → 칸
textToCell: ["12", "1,234.5", "50%", "-1e3", "true", "'=12", "=", "=A1+1", "", "1,23", "abc"].map(
(t) => ed.textToCell(t, { 서식: 4 }),
),
textToCellNoStyle: ed.textToCell("", {}),
cellToText: [
{ 값: "=12" },
{ 값: "12" },
{ 값: "abc" },
{ 값: 1.5 },
{ 값: false },
{ 식: "A1*2" },
undefined,
].map((c) => ed.cellToText(c)),
// 참조 넣을 자리
insertable: [
["=", 1],
["=A1+", 4],
["=A1", 3],
["=SUM(", 5],
["=SUM(A1,", 8],
["=1 + ", 5],
["abc", 3],
["=A1+B", 4],
].map(([t, p]) => ed.insertableAt(t, p)),
// 참조 색 — 같은 글은 같은 색 · 다른 시트
highlights: ed
.refHighlights("=A1+B2:C3*A1+치수!B1", "s1", (n) => (n === "치수" ? "s2" : null))
.map((h) => `${h.시트}:${addr.rangeToA1(h.범위)}:${h.색번호}`),
// 채우기 끌기 목표
fill: [[{ r: 9, c: 1 }], [{ r: 2, c: 6 }], [{ r: 3, c: 1 }], [{ r: 2, c: 1 }]].map(([p]) => {
const t = mouse.fillTarget({ r0: 1, c0: 1, r1: 3, c1: 2 }, p);
return [addr.rangeToA1(t.target), t.clear && addr.rangeToA1(t.clear)];
}),
};
console.log(JSON.stringify(out));