Files
Aislo/resources/tester/ui_checks/54-2_도움말.js
T
eomsangdonandClaude Opus 5.5 0f32c241ca feat(가이드): 538-1 글 자리 A05_EduDetail/guide 로 옮김 + GET /api/help 한 가이드 읽기
- resources/help → A05_EduDetail/guide (git mv · 이력 남김) · 참조 고침(서버 · 시험 · B03 주석 · ui_checks)
- GET /api/help = 모든 페이지 [{page, title, items:[{key, title, text, version}]}] + admin
  · 페이지 = ^[BDE]\d{2}$ 폴더 · `_` 파일 · 그림 뺌 · version = sha256 앞 16자 · 페이지 제목 = 00_설명서 제목
- GET /api/help/{page} 는 538-2 까지 살림 · B01 폴더 허용
- 시험: 글 내용 검사(명사형 · 400 자) 걷음 — 시스템 관리자가 화면에서 바로 고친 글이
  지킴 시험을 빨갛게 하지 않게(요구서 359 4장 6) · 차례 · 판 · `_` 파일 · 나쁜 폴더 · 경로 탈출 시험 더함

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 08:37:33 +09:00

115 lines
5.0 KiB
JavaScript

/* 54-2 — [?] 설명서: B02~B09 좌측 패널 아래 단추 묶음 맨 왼쪽 · 모달 = 왼쪽 차례 · 오른쪽 파일 글 ·
* 구조물 종류를 고르면 그 항목 먼저 · 패널 안 설명 글 0
* 시작 화면: 아무 B 화면(로그인 · 환경 배정 storage 프로젝트가 현재 프로젝트)
* 부르는 법: orca eval --expression "$(cat 이 파일)" (async 식 · JSON 글을 돌려줌) · 1분 넘으면 끊기므로
* `window.__help542 = ["b02-proj-register", …];` 를 앞에 붙여 네 화면씩 두 번
* 쓰는 것: 없음(주소 이동 · 누르기 · 모달 닫기 · 끝나면 처음 주소로)
* 파일 고침 반영: 셸이 `A05_EduDetail/guide/B04/99_임시.md` 를 만들고(글 A) 부름 → 글 B 로 고치고 다시 부름 →
* `temp` 가 A → B 로 바뀌면 통과 · 뒤에 파일 지움(없으면 temp = null)
* 기대 수치:
* - pages 8 · 줄마다 btn = 1 · first = true(묶음 맨 왼쪽) · inLeft = true(B02 는 아래 단추 줄) ·
* modal = true · toc[0] = 「… 설명서」 · text = 그 설명서 제목 글
* - B03 toc = 설명서 + 필요한 파일 · 고르는 방법 · 알아 둘 것 · B06 toc 에 「표준 횡단면 설정」
* - pipeTopic = 「구조물 · 배관」(B05 에서 배관을 고른 채 [?]) · leftovers = 0(옮긴 글이 패널에 없음)
*/
(async () => {
const w = (ms) => new Promise((r) => setTimeout(r, ms));
const until = async (fn, ms = 15000) => {
for (let t = 0; t < ms; t += 200) {
const v = fn();
if (v) return v;
await w(200);
}
return null;
};
const MOVED = [
"[저장]은 이 폼에 있는 칸만",
"에서 관리 — 여기서 넣어도",
"사방기술교본",
"표준 편절편성 단면 모식도",
"L형 측구는 각 횡단면도에서",
"끌어 놓으면 확장자로",
"shapefile 한 벌",
"작업 좌표계는 라이다 PRJ",
"칸이 생기기 전의 동작",
"소광리 도면 H=2.0",
];
const start = location.hash;
const vis = (n) => n && n.offsetParent !== null;
const leftText = () =>
document.querySelector(".ui-workflow-overlay__panel--title")?.innerText ?? "";
const openModal = async (btn) => {
btn.click();
const box = await until(() => document.querySelector(".ui-help .ui-help__text h2"));
const res = {
modal: !!box,
toc: [...document.querySelectorAll(".ui-help__link")].map((b) => b.innerText.trim()),
text: box?.innerText ?? null,
active: document.querySelector(".ui-help__text")?.dataset.helpKey ?? null,
};
const temp = [...document.querySelectorAll(".ui-help__link")].find((b) =>
b.dataset.helpKey?.startsWith("99_"),
);
if (temp) {
temp.click();
res.temp = document.querySelector(".ui-help__text p")?.innerText ?? null;
}
document.querySelector(".ui-help .ui-modal__top button")?.click();
await w(200);
res.closed = !document.querySelector(".ui-help");
return res;
};
const out = { pages: [] };
// orca eval 은 한 번에 1분쯤에서 끊김 — 앞에 `window.__help542 = ["b05-profile", …];` 를 붙이면 그 화면만
const routes = window.__help542 ?? [
"b02-proj-register",
"b03-file-input",
"b04-preprocess",
"b05-profile",
"b06-section",
"b07-design-detail",
"b08-quantity",
"b09-estimation",
];
let prev = null;
for (const route of routes) {
location.hash = `#/${route}`;
await w(3000); // 불러오는 동안의 임시 틀(B05 등)이 실제 화면으로 바뀔 때까지
// 앞 화면 단추가 빠지고 이 화면 단추가 설 때까지
const btn = await until(() =>
[...document.querySelectorAll(".ui-help-btn")].find((b) => vis(b) && b !== prev),
);
prev = btn;
await w(1500);
const row = btn?.parentElement;
const res = {
page: route.slice(0, 3).toUpperCase(),
btn: document.querySelectorAll(".ui-help-btn").length,
first: !!row && row.firstElementChild === btn,
inLeft: !!btn?.closest(".ui-sidebar-actions") || !!btn?.closest(".b02-proj__actions"),
leftovers: MOVED.filter((s) => leftText().includes(s)),
};
if (btn) Object.assign(res, await openModal(btn));
if (route === "b05-profile") {
// 배관 하나를 골라 [?] — 구조물 종류 항목이 먼저 열림(이미 골라져 있으면 그대로 · 끝나면 처음 상태로)
const picked = () => document.querySelector('[data-help-topic="구조물_배관"]');
const was = !!picked();
const item = await until(() =>
[...document.querySelectorAll(".b05-route__irregular-item")].find((li) =>
li.innerText.includes("배관"),
),
);
if (!was) item?.click();
await until(picked, 8000);
await w(800);
res.leftoversPipe = MOVED.filter((s) => leftText().includes(s));
const again = await openModal([...document.querySelectorAll(".ui-help-btn")].find(vis));
res.pipeTopic = again.text;
if (!was) item?.click(); // 고름 풂
}
out.pages.push(res);
}
location.hash = start;
return JSON.stringify(out);
})();