From 67d305177afcfa13743cc28838da2d32f7662497 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 19 Sep 2026 01:45:51 +0900 Subject: [PATCH] =?UTF-8?q?knowledge(=ED=92=88=EC=85=88md):=20=EB=8F=84?= =?UTF-8?q?=EA=B5=AC=20check=20=E2=80=94=20=EB=90=98=ED=92=80=EC=9D=B4=20?= =?UTF-8?q?=ED=91=9C=20=EB=A8=B8=EB=A6=AC=EB=A5=BC=20=20?= =?UTF-8?q?=EB=A1=9C=20=EC=85=88=20=C2=B7=20=EC=AA=BD=20=EA=BC=AC=EB=A6=AC?= =?UTF-8?q?=20=EC=A4=84=20=EC=B0=A8=EB=A1=80=20=EB=A7=9E=EC=B6=A4=20=C2=B7?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=EA=B7=9C=EC=B9=99=204-5=20=ED=95=9C=20?= =?UTF-8?q?=EC=A4=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 쪽을 넘은 표의 되풀이 머리는 md 표에서 빼되 주석으로 적으면 ② 글자 대조에서 셈(짐작으로 빼면 새 표의 같은 밑수 줄까지 빠져 헛빠짐 — 4-1 쪽 60) Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj --- .../original/_pipeline/pum_md_tool.py | 14 +++++++++-- .../original/원가계산/_품셈md_작성규칙.md | 2 +- resources/tester/test_pum_md_tool.py | 25 +++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/resources/knowledge/original/_pipeline/pum_md_tool.py b/resources/knowledge/original/_pipeline/pum_md_tool.py index 17573dd4..ed755f49 100644 --- a/resources/knowledge/original/_pipeline/pum_md_tool.py +++ b/resources/knowledge/original/_pipeline/pum_md_tool.py @@ -419,6 +419,7 @@ def plan(book_name: str) -> list[Path]: # ── check ────────────────────────────────────────────────────────────── #: md 문법 — 글자 대조·수 대조에서 뺌(원문 글자가 아님) _COMMENT = re.compile(r"", re.S) +_REPEATED = re.compile(r"") _IMAGE = re.compile(r"!\[[^\]]*\]\([^)]*\)") _TABLE_RULE = re.compile(r"^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?\s*$") #: 막음표 — 원문 글자가 md 문법으로 읽히지 않게 앞에 `\` 를 붙인 것(`\*` `\-` `\#` `\>` `\|` …) @@ -442,7 +443,11 @@ def split_head(text: str) -> tuple[str, str]: def md_lines(body: str) -> list[tuple[int, str]]: - """몸의 (줄 번호, 원문 글자) — 주석 · 그림 · 표 구분 줄 · md 문법 글자를 뺌. 줄 번호는 몸 기준 1부터.""" + """몸의 (줄 번호, 원문 글자) — 주석 · 그림 · 표 구분 줄 · md 문법 글자를 뺌. 줄 번호는 몸 기준 1부터. + + `` 는 셈 — 쪽을 넘은 표가 PDF 에서 되풀이한 머리 줄(md 표에서는 뺌 · 규칙 4-5). + """ + body = _REPEATED.sub(r"\1", body) body = _COMMENT.sub(lambda m: "\n" * m.group(0).count("\n"), body) out = [] for number, line in enumerate(body.split("\n"), start=1): @@ -473,9 +478,14 @@ def pdf_lines(doc, head: dict[str, str], footer: re.Pattern) -> list[tuple[int, pass out = [] for number in range(start_page, min(end_page, last) + 1): - for index, row in enumerate(_body_rows(doc[number - 1], footer)): + rows = [row.strip() for row in _page_rows(doc[number - 1])] + if rows and footer.match(rows[-1]): + rows[-1] = "" # 쪽 꼬리 + for index, row in enumerate(rows): if (number, index) < (start_page, start_row) or (number, index) >= (end_page, end_row): continue + if not row or row == "→": # 이어짐 표지 + continue out.append((number, row)) return out diff --git a/resources/knowledge/original/원가계산/_품셈md_작성규칙.md b/resources/knowledge/original/원가계산/_품셈md_작성규칙.md index 63ed7a6a..38320209 100644 --- a/resources/knowledge/original/원가계산/_품셈md_작성규칙.md +++ b/resources/knowledge/original/원가계산/_품셈md_작성규칙.md @@ -63,7 +63,7 @@ PDF쪽: 135~136 3. 머리가 두 단 이상이면 **윗머리를 md 머리 줄로, 아랫머리는 몸 첫 줄(들)로** 적고 주석을 담. 윗머리를 아랫머리마다 되풀이해 펼치지 않음. `` 4. 빈 칸은 빈 칸. `〃` · `-` · `·` 는 그대로 적음(위 값으로 채우지 않음). -5. 한 표가 쪽을 넘어가면 **한 표로 이음.** 넘어간 쪽에서 되풀이된 머리 줄은 뺌. +5. 한 표가 쪽을 넘어가면 **한 표로 이음.** 넘어간 쪽에서 되풀이된 머리 줄은 뺌. 뺀 자리(넘어간 첫 줄 앞)에 `` 로 그 글자를 적음 — 기계검사가 그 글자를 PDF 의 되풀이 머리와 맞대 셈. 6. 표가 너무 넓어 PDF 가 두 표로 나눠 찍었으면 PDF 대로 두 표. ## 5. 그림 diff --git a/resources/tester/test_pum_md_tool.py b/resources/tester/test_pum_md_tool.py index aed13087..c3e39efc 100644 --- a/resources/tester/test_pum_md_tool.py +++ b/resources/tester/test_pum_md_tool.py @@ -145,3 +145,28 @@ def test_const_toc_counts(): "유지관리부문", ] assert sum(e.ident.startswith("제") for e in entries) == 45 + + +def test_repeated_head_comment_counts_and_footer_dropped(): + """쪽을 넘은 표의 되풀이 머리 — md 표에선 빼고 `` 로 적으면 셈(규칙 4-5) · 쪽 꼬리는 뺌.""" + pymupdf = pytest.importorskip("pymupdf") + doc = pymupdf.open() + for lines in (["9-5. A", "NAME QTY", "X 1.0", "- 1 -"], ["NAME QTY", "Y 2.0", "- 2 -"]): + page = doc.new_page() + for n, text in enumerate(lines): + page.insert_text((72, 72 + 30 * n), text) + head = {"PDF쪽": "1~2", "시작표지": "9-5. A", "끝표지": "끝"} + pdf = tool.pdf_lines(doc, head, tool.BOOKS["산림"]["footer"]) + assert [row for _, row in pdf] == ["9-5. A", "NAME QTY", "X 1.0", "NAME QTY", "Y 2.0"] + md = "\n".join( + [ + "## 9-5. A", + "", + "| NAME | QTY |", + "|---|---|", + "| X | 1.0 |", + "", + "| Y | 2.0 |", + ] + ) + assert tool.verdict(tool.compare(pdf, tool.md_lines(md))).startswith("통과")