Files
Aislo/ui_template/ui_template_equation_text.ts
T
eomsangdonandClaude Opus 5.5 2376e70fbb revert(802-1): 801-1 wip 옛 나무 위 고침 걷음 — 요구 664 수식 문서로 다시 짬
- 걷음: 43784a4c0 의 옛 수식 나무 위 고침(서버 · 화면 · css) = 그 앞 판으로 되돌림
- 남김: master_equation_sign.py · ui_template_equation_text.ts · ui_template_equation_edit.ts(다시 쓸 조각 · 지금 안 부름) · text 는 `입력글` 을 제 타입에
- 지움: test_801_1_equation_inline.py — 걷은 옛 나무 고침을 재는 시험

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 17:55:58 +09:00

98 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =============================================================================
* ui_template_equation_text.ts
* 부품 「수식」 글 꼴(801-1 · 요구 662) — 수식 나무 ↔ 키보드 한 줄 식의 한 곳(화면 · DOM 없음 · 시험 `test_801_1_equation_inline`).
* textOf = 나무 → 키보드 식(변수 = 열쇠 · 표 찾기 · 요소 · 로직 부르기 = 서버 `입력글`(별칭 꼴) › 원문 식 · 만약 = 세 갈래 모두) · `swap` 마디는 그 글로
* leavesOf = 보이는 잎(수 · 글 · 변수 · 블록) 차례 — 값 식 그림의 숫자 차례와 같음(탄 갈래만 · 반올림 감싸개는 첫 인자만)
* 보이기 규칙 = `taken`(만약 = 탄 갈래만) · `HIDDEN`(반올림 = 자리 감싸개 숨김) — 셈 · 식은 그대로(그림만)
* ========================================================================== */
import type { EqNode as Base } from "./ui_template_equation";
/** 서버 마디 + 키보드 글(`입력글` · 별칭 꼴 · 없으면 식) */
type EqNode = Base & { 입력글?: string };
/** 그림에서 감싸개를 숨기는 함수(첫 인자만 보임) */
export const HIDDEN = new Set(["반올림"]);
/** 만약 — 탄 갈래 마디(모르면 null = 세 갈래 모두 보임) */
export const taken = (n: EqNode): EqNode | null =>
n.걸림 === 1 ? (n.참 ?? null) : n.걸림 === 2 ? (n.거짓 ?? null) : null;
const isOp = (n: EqNode | undefined): boolean => n?.꼴 === "연산";
const wrap = (text: string, yes: boolean): string => (yes ? `(${text})` : text);
/** 나무 → 키보드 한 줄 식 — 엔진 묶음 그대로(분수 · 퍼센트가 연산 오른쪽이면 괄호) */
export function textOf(n: EqNode | undefined, swap?: Map<EqNode, string>): string {
if (!n) return "";
const own = swap?.get(n);
if (own !== undefined) return own;
const t = (x: EqNode | string | undefined): string =>
typeof x === "string" ? x : textOf(x, swap);
switch (n.꼴) {
case "수": {
const raw = typeof n.값 === "number" || typeof n.값 === "string" ? String(n.값) : "";
return /^-?\d+(\.\d+)?(e-?\d+)?$/i.test(raw) ? raw : (n.글 ?? "").replace(/,/g, "");
}
case "글":
return n.따옴 ? `'${n.글 ?? ""}'` : (n.글 ?? "");
case "변수":
return n.갈래 === "입력" || n.갈래 === "중간"
? (n.열쇠 ?? "")
: n.입력글 || n.식 || n.열쇠 || "";
case "블록":
return n.입력글 || n.식 || n.열쇠 || "";
case "연산": {
const right = n.우?.꼴 === "분수" || n.우?.꼴 === "퍼센트";
return `${t(n.좌)} ${n.기호 ?? ""} ${wrap(t(n.우), right)}`;
}
case "분수": {
const top = n.위 as EqNode;
const low = n.아래 as EqNode;
const head = wrap(t(top), isOp(top) && !["×", "÷"].includes(top.기호 ?? ""));
if (n.사슬 && low?.꼴 === "연산")
return `${head} / ${wrap(t(low.좌), isOp(low.좌))} / ${wrap(t(low.우), isOp(low.우))}`;
return `${head} / ${wrap(t(low), isOp(low) || low?.꼴 === "분수")}`;
}
case "괄호":
return `(${t(n.안)})`;
case "퍼센트":
return `${t(n.안)} / 100`;
case "음":
return `-${t(n.안)}`;
case "조건":
return `만약(${t(n.조건)}, ${t(n.참)}, ${t(n.거짓)})`;
case "함수":
return `${n.이름 ?? ""}(${(n.인자 ?? []).map((a) => t(a)).join(", ")})`;
default:
return n.글 ?? "";
}
}
/** 보이는 잎 차례 — 값 식 그림(`renderEq`)의 수 · 글 차례와 같음 */
export function leavesOf(n: EqNode | undefined, out: EqNode[] = []): EqNode[] {
if (!n) return out;
const go = (x: EqNode | string | undefined): void => {
if (x && typeof x !== "string") leavesOf(x, out);
};
switch (n.꼴) {
case "수":
case "글":
case "변수":
case "블록":
out.push(n);
break;
case "조건": {
const pick = taken(n);
if (pick) go(pick);
else [n.조건, n.참, n.거짓].forEach(go);
break;
}
case "함수":
(HIDDEN.has(n.이름 ?? "") ? (n.인자 ?? []).slice(0, 1) : (n.인자 ?? [])).forEach(go);
break;
default:
[n.좌, n.우, n.위, n.아래, n.안].forEach(go);
}
return out;
}