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

This commit is contained in:
2026-09-19 01:47:10 +09:00
23 changed files with 111 additions and 46 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. 그림
@@ -5,8 +5,8 @@ PDF쪽: 192
인쇄쪽: 180
시작표지: 제13장 구조물
끝표지: 13-1. 석재 및 골재의 분류
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 192
인쇄쪽: 180
시작표지: 13-1. 석재 및 골재의 분류
끝표지: 13-2. 채집 및 세척
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 192~193
인쇄쪽: 180~181
시작표지: 13-2. 채집 및 세척
끝표지: 13-3. 기초다짐 및 뒷채움
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 194
인쇄쪽: 182
시작표지: 13-3. 기초다짐 및 뒷채움
끝표지: 13-4. 돌쌓기
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 195~199
인쇄쪽: 183~187
시작표지: 13-4. 돌쌓기
끝표지: 13-5. 돌붙임
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 199~200
인쇄쪽: 187~188
시작표지: 13-5. 돌붙임
끝표지: 13-6. 큰돌쌓기
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 201~202
인쇄쪽: 189~190
시작표지: 13-6. 큰돌쌓기
끝표지: 13-7. 큰돌붙이기
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 203~204
인쇄쪽: 191~192
시작표지: 13-7. 큰돌붙이기
끝표지: 13-8. 막돌쌓기
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 204
인쇄쪽: 192
시작표지: 13-8. 막돌쌓기
끝표지: 13-9. 서식지 조성 돌쌓기 및 놓기
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 204
인쇄쪽: 192
시작표지: 13-9. 서식지 조성 돌쌓기 및 놓기
끝표지: 13-10. 말뚝박기공
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 205~207
인쇄쪽: 193~195
시작표지: 13-10. 말뚝박기공
끝표지: 13-11. 돌망태
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 208~210
인쇄쪽: 196~198
시작표지: 13-11. 돌망태
끝표지: 13-12. 비탈다듬기
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 210~211
인쇄쪽: 198~199
시작표지: 13-12. 비탈다듬기
끝표지: 13-13. 흙막이
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 211~212
인쇄쪽: 199~200
시작표지: 13-13. 흙막이
끝표지: 13-14. 식생토낭 및 포트
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 212~213
인쇄쪽: 200~201
시작표지: 13-14. 식생토낭 및 포트
끝표지: 13-15. 목재공
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 213~214
인쇄쪽: 201~202
시작표지: 13-15. 목재공
끝표지: 13-16. 매트부설
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,8 +5,8 @@ PDF쪽: 214
인쇄쪽: 202
시작표지: 13-16. 매트부설
끝표지: 제14장 부대공
상태: 대기
작성:
상태: 작성중
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
@@ -5,10 +5,12 @@ PDF쪽: 215
인쇄쪽: 203
시작표지: 제14장 부대공
끝표지: 14-1. 입목뿌리 밑막이
상태: 대기
작성:
상태: 검증대기
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
기계검사: 통과 · ①수 결손 0 허구 0 · ②글자 빠짐 0 더함 0
확정지문:
---
# 제14장 부대공
@@ -5,10 +5,23 @@ PDF쪽: 215
인쇄쪽: 203
시작표지: 14-1. 입목뿌리 밑막이
끝표지: 14-2. 근주이식
상태: 대기
작성:
상태: 검증대기
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
기계검사: 통과 · ①수 결손 0 허구 0 · ②글자 빠짐 0 더함 0
확정지문:
---
## 14-1. 입목뿌리 밑막이
(단위: 10본당)
| 장비 | 단위 | 수량 | 비고 |
|---|---|---|---|
| 0.8㎥ 굴착기(우드그랩 부착) | h | 0.17 | 장비이동거리 50m이내 기준 |
| 보통인부 | h | 0.5 | |
<!-- 병합: 4열 1~2행 「장비이동거리 50m이내 기준」 -->
[주]
입목뿌리 밑막이란 성토비탈면의 하부에 기존지장목의 근주를 밑막이 형태로 쌓는 것을 말한다.
@@ -5,10 +5,25 @@ PDF쪽: 215
인쇄쪽: 203
시작표지: 14-2. 근주이식
끝표지: [부록 1]할인․할증 적용 공종표
상태: 대기
작성:
상태: 검증대기
작성: sub_laptop_1
검증:
원천: 글자층
기계검사:
기계검사: 통과 · ①수 결손 0 허구 0 · ②글자 빠짐 0 더함 0
확정지문:
---
## 14-2. 근주이식
(단위: 10본당)
| 장비 | 단위 | 수량 | 비고 |
|---|---|---|---|
| 0.8㎥ 굴착기 | h | 0.25 | 장비 이동거리 50m이내 기준 |
| 보통인부 | h | 0.66 | |
<!-- 병합: 4열 1~2행 「장비 이동거리 50m이내 기준」 -->
[주]
① 본 품은 맹아발생이 가능한 수종의 살아 있는 근주를 이식하는 데에 적용한다.
② 적용 대상 근주의 규격은 근원직경 10㎝∼30㎝ 사이를 기준으로 하며, 평균 근원직경은 20㎝이다.
③ 0.2㎥ 또는 0.4㎥ 용량의 굴착기를 사용하는 경우에는 「건설공사 표준품셈 공통부문, 8-2-3 굴착기(2025)」를 참조하여 적용계수를 달리 적용하도록 한다.
+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("통과")