Merge remote-tracking branch 'origin/sub_laptop_2' into main_laptop_1

This commit is contained in:
2026-10-28 21:37:21 +09:00
2 changed files with 71 additions and 4 deletions
@@ -19,10 +19,9 @@ import { appendFordOverlay } from "../B06_Section/B06_Section_UI_Cross_Ford";
import { appendFordPavementOverlay } from "../B06_Section/B06_Section_UI_Cross_Ford_Pavement";
import { appendUnderdrainOverlay } from "../B06_Section/B06_Section_UI_Cross_Underdrain";
import { groundLine } from "../B06_Section/logic/B06_Section_Cross_Wall_Hatch_Geom";
import {
appendCrossDesignOverlay,
appendPavementOverlay,
} from "../B06_Section/B06_Section_UI_Cross_Design";
// 허브(`_UI_Cross_Design`)가 아닌 그리기 파일에서 직접 — 허브는 상세 창 · CAD · API 를 끈다(574-1)
import { appendCrossDesignOverlay } from "../B06_Section/B06_Section_UI_Cross_Design_Line";
import { appendPavementOverlay } from "../B06_Section/B06_Section_UI_Cross_Design_Surface";
import { appendRevetmentOverlay } from "../B06_Section/B06_Section_UI_Cross_Revetment";
import { clipPointsToPolygon, clipSegment, pointInPolygon } from "../A00_Common/b_polygon_clip";
@@ -0,0 +1,68 @@
"""B07 횡단 덧그림 서버 묶음(`b07-extent`)이 화면 코드를 끌지 않음 (574-1).
묶음 입구에서 값 import 를 따라가 닿는 TS 파일에 확인 창 · CAD · 상세 창 · API ·
부품 상자 · B06 허브(`_UI_Cross_Design`)가 없어야 함. `import type` 은 지워지므로 뺌.
"""
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
ENTRY = ROOT / "B07_DesignDetail" / "B07_DesignDetail_Cross_Extent_Node.ts"
ALIAS = {"@util/": ROOT / "common_util", "@ui/": ROOT / "ui_template"}
_IMPORT = re.compile(
r"^\s*(?:import|export)\s+(type\s+)?(?:([^;]*?)\s+from\s+)?[\"']([^\"']+)[\"']",
re.M | re.S,
)
FORBIDDEN = re.compile(
r"ui_template|_Cad|Cross_Detail|_Api_|B06_Section_UI_Cross_Design\.ts$|three"
)
def _type_only(names: str | None) -> bool:
inner = (names or "").strip()
if not inner.startswith("{"):
return False
parts = [p.strip() for p in inner.strip("{} \n").split(",") if p.strip()]
return bool(parts) and all(p.startswith("type ") for p in parts)
def _resolve(origin: Path, spec: str) -> Path | None:
for prefix, base in ALIAS.items():
if spec.startswith(prefix):
target = base / spec[len(prefix) :]
break
else:
if not spec.startswith("."):
return None # node:fs · 라이브러리
target = origin.parent / spec
for suffix in (".ts", ""):
path = Path(str(target) + suffix).resolve()
if path.is_file():
return path
return None
def _reachable() -> set[Path]:
seen, queue = {ENTRY.resolve()}, [ENTRY.resolve()]
while queue:
current = queue.pop()
if current.suffix != ".ts":
continue
for match in _IMPORT.finditer(current.read_text(encoding="utf-8")):
type_kw, names, spec = match.groups()
if type_kw or _type_only(names):
continue
found = _resolve(current, spec)
if found and found not in seen:
seen.add(found)
queue.append(found)
return seen
def test_extent_bundle_pulls_no_screen_code():
reached = _reachable()
names = {p.relative_to(ROOT).as_posix() for p in reached}
assert "B07_DesignDetail/B07_DesignDetail_Cross_Overlay.ts" in names # 걷기가 실제로 돎
bad = sorted(n for n in names if FORBIDDEN.search(n))
assert not bad, bad