knowledge (구 Aislo-law 독립 저장소 → resources/knowledge 이관, 저장소 폐지): - 법령·행정규칙·표준시방서·교본 원문 + 기술문서 55건 + 실무 분석·종합비교 - 루트 지침 체계: README(지도)·00_운영지침·01_수집지침·02_분석지침· 03_미결_및_확인사항(교본 충돌 리스트 포함)·04_참조_법령기준_목록 - 기술문서 55건 원문 전수 검증 완료 (사방 설계홍수량 법정 기준 등 반영) - 정리: CAD·오피스 잔재 142건, 중복 zip 7건(413MB), 빈 폴더 30개 제거 resources 그룹 재편 (이름순 그룹핑): - app_branding(구 prog_icon.jpg)·app_policies(구 legal)· data_global_contours(구 grobal_contours)·data_rainfall_idf_cache(구 wamis_contours)· template_2dDrawing(구 dwg_analysis/templete — 오타 교정, 상수·경로 동기화) - dwg_analysis(분석 완료 1.8GB)·templates(빈 폴더)·templete_calc_cost.xlsx 삭제 - 참조 코드 5파일 경로 수정 + 프론트 재빌드 (구 경로 잔존 0) - .gitignore: resources 추적 전환, national_contours.gpkg(22GB) 영구 제외 - .env: knowledge 수집용 API 정보 주석 통합 (KCSC·법령센터·조달청 제비율) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
85 lines
2.9 KiB
Python
85 lines
2.9 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""기존 법령 md의 코드펜스(``` 부칙·개정문)를 인용블록으로 전환.
|
||
|
||
- 부칙: 같은 폴더 XML에서 절단 없이 다시 읽어 인용블록으로 교체(2500자 절단 복구)
|
||
- 개정문·제개정이유(CHANGELOG): 코드펜스 → 인용블록
|
||
본문·이미지 로컬화 결과는 건드리지 않는다(부칙/개정문 섹션만 치환).
|
||
"""
|
||
import re, sys
|
||
import xml.etree.ElementTree as ET
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
FENCE = "```"
|
||
|
||
def clean(t):
|
||
t = (t or "").replace(" ", " ")
|
||
return re.sub(r"[ \t]+", " ", t).strip()
|
||
|
||
def to_quote(text):
|
||
return "\n".join(f"> {ln}" if ln.strip() else ">" for ln in text.split("\n"))
|
||
|
||
def buchik_from_xml(xml_path):
|
||
"""XML에서 부칙 인용블록 md(절단 없음) 생성. '## 부칙' 섹션 문자열 반환."""
|
||
root = ET.parse(xml_path).getroot()
|
||
bc = root.find("부칙")
|
||
if bc is None:
|
||
return None
|
||
units = bc.findall("부칙단위")
|
||
if not units:
|
||
return None
|
||
out = ["## 부칙", ""]
|
||
for b in units[:20]:
|
||
body = clean(b.findtext("부칙내용") or "")
|
||
out.append(to_quote(body))
|
||
out.append("")
|
||
return "\n".join(out).rstrip() + "\n"
|
||
|
||
def fix_law_md(md_path, xml_path):
|
||
"""현행/교본시점 md: '## 부칙' ~ 다음 '## ' 사이를 XML 부칙으로 교체."""
|
||
text = md_path.read_text(encoding="utf-8")
|
||
if "## 부칙" not in text:
|
||
return 0
|
||
new_buchik = buchik_from_xml(xml_path)
|
||
if not new_buchik:
|
||
return 0
|
||
# '## 부칙' 부터 다음 '## ' 헤딩 전까지 잘라 교체
|
||
m = re.search(r"^## 부칙\s*$", text, re.M)
|
||
if not m:
|
||
return 0
|
||
start = m.start()
|
||
nxt = re.search(r"^## (?!부칙)", text[m.end():], re.M)
|
||
end = m.end() + nxt.start() if nxt else len(text)
|
||
new = text[:start] + new_buchik + ("\n" + text[end:].lstrip("\n") if text[end:].strip() else "")
|
||
if new != text:
|
||
md_path.write_text(new, encoding="utf-8")
|
||
return 1
|
||
return 0
|
||
|
||
def fix_changelog(md_path):
|
||
"""CHANGELOG: 개정문/제개정이유 코드펜스 → 인용블록."""
|
||
text = md_path.read_text(encoding="utf-8")
|
||
if FENCE not in text:
|
||
return 0
|
||
def repl(m):
|
||
inner = m.group(1).strip()
|
||
return to_quote(inner)
|
||
new = re.sub(FENCE + r"\w*\n(.*?)\n?" + FENCE, repl, text, flags=re.S)
|
||
if new != text:
|
||
md_path.write_text(new, encoding="utf-8")
|
||
return 1
|
||
return 0
|
||
|
||
if __name__ == "__main__":
|
||
n_law = n_cl = 0
|
||
for md in ROOT.rglob("*.md"):
|
||
if "임도기술교본" in str(md) or "_pipeline" in str(md):
|
||
continue
|
||
if md.name.startswith(("현행_", "교본시점_")):
|
||
xml = md.with_suffix(".xml")
|
||
if xml.exists():
|
||
n_law += fix_law_md(md, xml)
|
||
elif md.name == "CHANGELOG.md":
|
||
n_cl += fix_changelog(md)
|
||
print(f"부칙 인용블록 전환 {n_law}개 / CHANGELOG {n_cl}개")
|