# -*- coding: utf-8 -*- """ASCII 박스표(┌┬┐│├┼┤└┴┘─)를 정식 마크다운 표로 변환. 법령 조문의 안에 있던 박스 드로잉 표가 이미지 로컬화 후 텍스트로 남는데, │로 열을 구분하므로 md 표로 복원한다. 각 표에는 대응 ![그림]도 이미 있다. """ import re, sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent BORDER = set("┌┬┐├┼┤└┴┘─━┏┳┓┣╋┫┗┻┛│┃ \t") VBAR = "│┃|" QP = re.compile(r"^\s*>+\s?") # 인용블록 접두 '> ' def unq(l): return QP.sub("", l) def is_border(l): s = unq(l).strip() return bool(s) and all(c in BORDER for c in s) and any(c in "─━┼┬┴┌┐└┘├┤" for c in s) def is_data(l): return any(c in "│┃" for c in unq(l)) def split_cells(l): s = unq(l).strip().strip("│┃") return [c.strip() for c in re.split(r"[│┃]", s)] def convert_block(lines): rows = [split_cells(l) for l in lines if is_data(l)] rows = [r for r in rows if any(c for c in r)] if len(rows) < 2: return None w = max(len(r) for r in rows) if w < 2: return None rows = [r + [""] * (w - len(r)) for r in rows] esc = lambda c: c.replace("|", "\\|") out = ["| " + " | ".join(esc(c) for c in rows[0]) + " |", "|" + "|".join(["---"] * w) + "|"] for r in rows[1:]: out.append("| " + " | ".join(esc(c) for c in r) + " |") return out def fix(md_path): lines = md_path.read_text(encoding="utf-8").split("\n") out = [] i, n = 0, len(lines) changed = 0 infence = False while i < n: if lines[i].lstrip().startswith("```"): infence = not infence out.append(lines[i]); i += 1 continue # 박스표 블록 시작: border 또는 data(│ 포함) 연속 (펜스 밖에서만) if not infence and (is_border(lines[i]) or (is_data(lines[i]) and not lines[i].lstrip().startswith("|"))): j = i block = [] while j < n and (is_border(lines[j]) or (is_data(lines[j]) and not lines[j].lstrip().startswith("|"))): block.append(lines[j]); j += 1 data_rows = [b for b in block if is_data(b)] md = convert_block(block) # 열이 일정한 진짜 표만 md 표로. 아니면(수식 등) 코드펜스로 정렬 보존. widths = {len(split_cells(b)) for b in data_rows} if md and len(data_rows) >= 2 and len(widths) == 1: out += ["", *md, ""] changed += 1 i = j continue if len(data_rows) >= 1 or any(is_border(b) for b in block): trimmed = [b.rstrip() for b in block if b.strip()] if trimmed: out += ["", "```text", *trimmed, "```", ""] changed += 1 i = j continue out.append(lines[i]); i += 1 if changed: md_path.write_text("\n".join(out), encoding="utf-8") return changed if __name__ == "__main__": total = 0 for md in ROOT.rglob("*.md"): if "임도기술교본" in str(md) or "_pipeline" in str(md): continue c = fix(md) if c: total += c print(f" {c}개 표 {md.parent.parent.name[:26]}/{md.name}") print(f"\n박스표 → md표 변환 {total}개")