knowledge(품셈md): 도구 check — 되풀이 표 머리를 <!-- 되풀이 머리: … --> 로 셈 · 쪽 꼬리 줄 차례 맞춤 · 작성규칙 4-5 한 줄

- 쪽을 넘은 표의 되풀이 머리는 md 표에서 빼되 주석으로 적으면 ② 글자 대조에서 셈(짐작으로 빼면 새 표의 같은 밑수 줄까지 빠져 헛빠짐 — 4-1 쪽 60)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
This commit is contained in:
2026-09-19 01:45:51 +09:00
co-authored by Claude Opus 5
parent 6b3f2a7089
commit 67d305177a
3 changed files with 38 additions and 3 deletions
@@ -419,6 +419,7 @@ def plan(book_name: str) -> list[Path]:
# ── check ──────────────────────────────────────────────────────────────
#: md 문법 — 글자 대조·수 대조에서 뺌(원문 글자가 아님)
_COMMENT = re.compile(r"<!--.*?-->", re.S)
_REPEATED = re.compile(r"<!--\s*되풀이 머리:(.*?)-->")
_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
@@ -63,7 +63,7 @@ PDF쪽: 135~136
3. 머리가 두 단 이상이면 **윗머리를 md 머리 줄로, 아랫머리는 몸 첫 줄(들)로** 적고 주석을 담. 윗머리를 아랫머리마다 되풀이해 펼치지 않음.
`<!-- 머리: 몸 1행까지 머리 · 병합: 머리 2~4열 「소요인력(인/본당)」 -->`
4. 빈 칸은 빈 칸. `〃` · `-` · `·` 는 그대로 적음(위 값으로 채우지 않음).
5. 한 표가 쪽을 넘어가면 **한 표로 이음.** 넘어간 쪽에서 되풀이된 머리 줄은 뺌.
5. 한 표가 쪽을 넘어가면 **한 표로 이음.** 넘어간 쪽에서 되풀이된 머리 줄은 뺌. 뺀 자리(넘어간 첫 줄 앞)에 `<!-- 되풀이 머리: 명 칭 | 규 격 | 단위 -->` 로 그 글자를 적음 — 기계검사가 그 글자를 PDF 의 되풀이 머리와 맞대 셈.
6. 표가 너무 넓어 PDF 가 두 표로 나눠 찍었으면 PDF 대로 두 표.
## 5. 그림
+25
View File
@@ -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 |",
"<!-- 되풀이 머리: NAME | QTY -->",
"| Y | 2.0 |",
]
)
assert tool.verdict(tool.compare(pdf, tool.md_lines(md))).startswith("통과")