feat(showcase): 트웬티온스 사이트를 전면 개편한다
All checks were successful
ci / build (push) Successful in 33s

This commit is contained in:
Yun Chan 2026-08-25 03:50:28 +09:00
parent cb3c323c9f
commit 9529e3747c
29 changed files with 8906 additions and 1326 deletions

View file

@ -11,13 +11,17 @@ const root = path.resolve(here, "..");
const npx = process.platform === "win32" ? "npx.cmd" : "npx";
const steps = [
{
layer: "L0-자산/트웬티온스 3D",
cmd: () => spawnSync(process.execPath, ["tools/build-showcase-assets.mjs", "--check"], { cwd: root, encoding: "utf8" }),
},
{
layer: "L0-정적/stylelint",
cmd: () => spawnSync(npx, ["stylelint", "public/work/*/styles/*.css"], { cwd: root, encoding: "utf8", shell: true }),
},
{
layer: "L0-정식/html-validate",
cmd: () => spawnSync(npx, ["html-validate", "public/work/*/index.html", "public/work/*/*/index.html"], { cwd: root, encoding: "utf8", shell: true }),
cmd: () => spawnSync(npx, ["html-validate", "public/work/*/index.html", "public/work/*/*/index.html", "public/work/twentyoz-corp/products.html"], { cwd: root, encoding: "utf8", shell: true }),
},
{
// 미정의 CSS 변수·끊긴 상대경로·한글 조판 누락·슬롭 지문은 stylelint 도 html-validate 도
@ -28,10 +32,13 @@ const steps = [
{ layer: "L1-단위/계산로직", cmd: () => spawnSync(process.execPath, ["tools/unit/calc.test.mjs"], { cwd: root, encoding: "utf8" }) },
{ layer: "L2-기능/감사", cmd: () => spawnSync(process.execPath, ["tools/audit.mjs"], { cwd: root, encoding: "utf8" }) },
{ layer: "L2-불변식/렌더", cmd: () => spawnSync(process.execPath, ["tools/invariants.mjs"], { cwd: root, encoding: "utf8" }) },
{ layer: "L2-디자인 게이트/메인", cmd: () => spawnSync(process.execPath, ["tools/design-gate.mjs", "--config=gate.config.json"], { cwd: root, encoding: "utf8" }) },
{ layer: "L2-디자인 게이트/제품", cmd: () => spawnSync(process.execPath, ["tools/design-gate.mjs", "--config=gate.twentyoz-products.config.json"], { cwd: root, encoding: "utf8" }) },
{ layer: "L3-시각회귀/diff", cmd: () => spawnSync(process.execPath, ["tools/visual.mjs"], { cwd: root, encoding: "utf8" }) },
{ layer: "L4-WebKit", cmd: () => spawnSync(process.execPath, ["tools/webkit.mjs"], { cwd: root, encoding: "utf8" }) },
{ layer: "L5-탐색/키보드", cmd: () => spawnSync(process.execPath, ["tools/exploratory.mjs"], { cwd: root, encoding: "utf8" }) },
{ layer: "L6-시나리오/E2E", cmd: () => spawnSync(process.execPath, ["tools/e2e.mjs"], { cwd: root, encoding: "utf8" }) },
{ layer: "L6-시나리오/트웬티온스", cmd: () => spawnSync(process.execPath, ["tools/twentyoz-e2e.mjs"], { cwd: root, encoding: "utf8" }) },
];
const report = [];
@ -43,8 +50,10 @@ for (const step of steps) {
const ok = r.status === 0;
if (!ok) failed++;
const out = (r.stdout || "") + (r.stderr || "");
const passLine = (out.match(/PASS\s+[^\n]/g) || []).length;
const failLines = (out.match(/FAIL\s+[^\n]/g) || []).length;
const summaries = [...out.matchAll(/PASS\s+(\d+)\s*\/\s*FAIL\s+(\d+)/g)];
const summary = summaries.at(-1);
const passLine = summary ? Number(summary[1]) : (out.match(/^PASS\b/gm) || []).length;
const failLines = summary ? Number(summary[2]) : (out.match(/^FAIL\b/gm) || []).length;
const tail = out.trim().split("\n").slice(-3).join(" | ").slice(0, 180);
report.push({ layer: step.layer, ok, ms: Date.now() - s, passLine, failLines, tail });
console.log(`${ok ? "✓" : "✗"} ${step.layer} (${((Date.now() - s) / 1000).toFixed(1)}s)${passLine ? ` — PASS ${passLine}` : ""}${failLines ? ` FAIL ${failLines}` : ""}`);