Merge remote-tracking branch 'origin/dev' into sub_laptop_8

This commit is contained in:
2026-10-05 00:33:56 +09:00
4 changed files with 109 additions and 2 deletions
@@ -238,3 +238,10 @@ def test_상세_화면_돌아가기는_집계표로_그_열_고른_채():
body = main.split('back.addEventListener("click"')[1]
assert "confirmLeave()" in body and "STRUCTURE_TABLE" in body
assert "sheet?.selectColumn(column)" in body
def test_상세_머리_돌아가기는_일반_단추():
"""43-5 — 도면 · 일위대가 · 면적산출 상세 머리 [돌아가기] = 공용 기본 단추(filled · 같은 높이 ·
알약 · ghost · sm 아님) · 대비는 ui_checks/43-5 시나리오(어두움 8.01)."""
main = _text(MAIN)
assert 'const back = createButton({ label: L("M02_Back") });' in main
@@ -0,0 +1,96 @@
/* 43-5 · E1 — 도면 · 일위대가 · 면적산출 상세 머리 [돌아가기] 꼴 · 머리 단추 글자 대비(밝음 · 어두움)
* 시작 화면: M02 마스터 템플릿 · 마스터 층(#/m02-master-template?open=구조물조합&root=master) · 시스템 관리자
* 부르는 법: orca eval --expression "$(cat 이 파일)" (async 식 · JSON 글을 돌려줌)
* 기대 수치:
* - 세 상세 모두 back.cls = "ui-btn ui-btn--filled"(ghost · sm 없음) · back.h = 머리 다른 단추 높이(±1px)
* - 밝음 · 어두움(앱 ☾ 단추) 모두 머리 보이는 단추 대비 ≥ 4.5
* - 끝나면 처음 테마로 되돌림(theme.end = theme.start)
* ⚠ 단추 color 전환(120ms)이 ORCA 탭에선 0ms 에 멈춰 옛 색이 읽힘(1.11 착오 · E1) — 재는 동안 전환을 끔
*/
(async () => {
const w = (ms) => new Promise((r) => setTimeout(r, ms));
const rgb = (s) => (s.match(/[\d.]+/g) || []).map(Number);
const lum = ([r, g, b]) => {
const f = (v) => ((v /= 255) <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);
};
/** 실제로 보이는 바탕 — 투명이면 조상으로 */
const bgOf = (el) => {
for (let e = el; e; e = e.parentElement) {
const c = rgb(getComputedStyle(e).backgroundColor);
if (c.length >= 3 && (c.length < 4 || c[3] > 0.5)) return c.slice(0, 3);
}
return [255, 255, 255];
};
const ratio = (el) => {
const a = lum(rgb(getComputedStyle(el).color).slice(0, 3));
const b = lum(bgOf(el));
return +((Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05)).toFixed(2);
};
const theme = () => document.documentElement.getAttribute("data-theme") || "auto";
const moon = () =>
[...document.querySelectorAll("button")].find((b) => /^[☾☀]$/.test(b.textContent.trim()));
const headButtons = () =>
[...document.querySelectorAll(".m02-main__head button")].filter(
(b) => !b.hidden && b.offsetParent,
);
const openRow = async (sectionTitle, prefix) => {
const sec = [...document.querySelectorAll(".m02-side__summary > section")].find(
(s) => s.querySelector("h3").textContent.trim() === sectionTitle,
);
sec.classList.remove("is-collapsed");
[...sec.querySelectorAll("button")].find((b) => b.textContent.startsWith(prefix)).click();
await w(5000);
};
const measure = () => {
const back = [...document.querySelectorAll(".m02-main__head button")].find(
(b) => b.textContent.trim() === "돌아가기",
);
const others = headButtons().filter((b) => b !== back);
return {
title: document.querySelector(".m02-main__title")?.textContent,
back: back && {
cls: back.className,
h: Math.round(back.getBoundingClientRect().height),
radius: getComputedStyle(back).borderRadius,
},
otherH: others.map((b) => Math.round(b.getBoundingClientRect().height)),
contrast: Object.fromEntries(
headButtons().map((b) => [b.textContent.trim() || b.title, ratio(b)]),
),
};
};
const still = document.createElement("style");
still.textContent = "*,*::before,*::after{transition:none!important}";
document.head.append(still);
const start = theme();
const out = { theme: { start }, pages: {} };
for (const [name, sec, prefix] of [
["도면", "구조물 도면", "SD-000001"],
["일위대가", "일위대가", "SU-000001"],
["면적산출", "면적산출", "SA-000001"],
]) {
await openRow(sec, prefix);
const light = measure();
moon()?.click();
await w(400);
const dark = { theme: theme(), ...measure() };
moon()?.click();
await w(400);
out.pages[name] = { light, dark };
}
if (theme() !== start) moon()?.click();
out.theme.end = theme();
still.remove();
const all = Object.values(out.pages).flatMap((p) => [
...Object.values(p.light.contrast),
...Object.values(p.dark.contrast),
]);
out.minContrast = Math.min(...all);
out.backOk = Object.values(out.pages).every(
(p) =>
p.light.back?.cls === "ui-btn ui-btn--filled" &&
p.light.otherH.every((h) => Math.abs(h - p.light.back.h) <= 1),
);
return JSON.stringify(out);
})();