kordoc 4.14.2 → 4.14.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -6
- package/dist/{-AQKXLFIM.js → -Z4TJ3QGK.js} +13 -11
- package/dist/{chunk-QOMNEWCQ.cjs → chunk-5LAZQCUJ.cjs} +305 -31
- package/dist/chunk-5LAZQCUJ.cjs.map +1 -0
- package/dist/{chunk-7IAQ4HOK.js → chunk-6BWU6SQX.js} +1 -1
- package/dist/chunk-6BWU6SQX.js.map +1 -0
- package/dist/{chunk-FOJZNMMK.js → chunk-6CUIXJOC.js} +1 -1
- package/dist/chunk-6CUIXJOC.js.map +1 -0
- package/dist/{chunk-ZWD734EY.js → chunk-7SE4EZ45.js} +2 -2
- package/dist/{chunk-TSFS5VKD.js → chunk-D4U2TXDC.js} +332 -141
- package/dist/chunk-D4U2TXDC.js.map +1 -0
- package/dist/chunk-DPWWXUOG.js +2222 -0
- package/dist/chunk-DPWWXUOG.js.map +1 -0
- package/dist/{chunk-GDW4YP7K.js → chunk-GLSBEEZJ.js} +2 -2
- package/dist/{chunk-JQEFP45L.js → chunk-GUJ4Q73I.js} +2 -2
- package/dist/{chunk-ZWOFQRIB.js → chunk-HIJUKZHM.js} +3 -3
- package/dist/chunk-IMAAFSAX.cjs +1352 -0
- package/dist/chunk-IMAAFSAX.cjs.map +1 -0
- package/dist/{chunk-TNCKOL2O.js → chunk-LCW7SEPG.js} +2 -2
- package/dist/chunk-LFSQAMSM.js +1352 -0
- package/dist/chunk-LFSQAMSM.js.map +1 -0
- package/dist/chunk-MG6DJEX4.js +1299 -0
- package/dist/chunk-MG6DJEX4.js.map +1 -0
- package/dist/{chunk-QC5T6D4J.js → chunk-NLU6LBLY.js} +299 -25
- package/dist/chunk-NLU6LBLY.js.map +1 -0
- package/dist/{chunk-EQZI77PP.cjs → chunk-QEJUY6SK.cjs} +3 -3
- package/dist/{chunk-EQZI77PP.cjs.map → chunk-QEJUY6SK.cjs.map} +1 -1
- package/dist/{chunk-VQ5W4MYO.js → chunk-QIF2VXBQ.js} +298 -24
- package/dist/chunk-QIF2VXBQ.js.map +1 -0
- package/dist/{chunk-UET462HB.js → chunk-TITDJWVZ.js} +2 -2
- package/dist/{chunk-247ANM72.cjs → chunk-USHQCF5T.cjs} +870 -147
- package/dist/chunk-USHQCF5T.cjs.map +1 -0
- package/dist/{chunk-C7FQBSON.js → chunk-V3DX4DUF.js} +2 -2
- package/dist/{chunk-DOGPOY4B.js → chunk-VDN7LMPL.js} +2 -2
- package/dist/{chunk-EDNJLUSE.js → chunk-VJIL6PIL.js} +2 -2
- package/dist/{chunk-L7DMSMAG.cjs → chunk-VWUYVEFN.cjs} +1 -1
- package/dist/chunk-VWUYVEFN.cjs.map +1 -0
- package/dist/{chunk-HR2XNERB.cjs → chunk-WJHAU73B.cjs} +2 -2
- package/dist/{chunk-HR2XNERB.cjs.map → chunk-WJHAU73B.cjs.map} +1 -1
- package/dist/{chunk-NS55SM7A.js → chunk-WJJGW5PL.js} +2 -2
- package/dist/{chunk-EISO3POT.js → chunk-XVXHXQIO.js} +788 -194
- package/dist/chunk-XVXHXQIO.js.map +1 -0
- package/dist/{chunk-ILU76UF3.js → chunk-YAKC46HZ.js} +2 -2
- package/dist/chunk-YAKC46HZ.js.map +1 -0
- package/dist/{chunk-3DUADAY2.js → chunk-YAVHVFRY.js} +851 -128
- package/dist/chunk-YAVHVFRY.js.map +1 -0
- package/dist/{chunk-A7QC2ZVP.js → chunk-YT3GC62E.js} +851 -128
- package/dist/chunk-YT3GC62E.js.map +1 -0
- package/dist/chunks-CCMRL4MJ.js +10 -0
- package/dist/cli.js +228 -97
- package/dist/cli.js.map +1 -1
- package/dist/{formula-PJJ6S3Z2.cjs → formula-5LOVHAKE.cjs} +9 -9
- package/dist/{formula-PJJ6S3Z2.cjs.map → formula-5LOVHAKE.cjs.map} +1 -1
- package/dist/{formula-JGFTXWYT.js → formula-7RANCW5L.js} +3 -3
- package/dist/{formula-5S7WWXGH.js → formula-7UYJOVTB.js} +4 -4
- package/dist/{image-ocr-WCAYXLOA.js → image-ocr-I6JOCATS.js} +34 -16
- package/dist/image-ocr-I6JOCATS.js.map +1 -0
- package/dist/{image-ocr-ZTYAGV3W.cjs → image-ocr-NYBJEOH2.cjs} +36 -18
- package/dist/image-ocr-NYBJEOH2.cjs.map +1 -0
- package/dist/{image-ocr-FLIL7MGN.js → image-ocr-ZV6PDBUQ.js} +32 -14
- package/dist/image-ocr-ZV6PDBUQ.js.map +1 -0
- package/dist/index.cjs +4048 -1216
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -28
- package/dist/index.d.ts +66 -28
- package/dist/index.js +3487 -655
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +74 -53
- package/dist/mcp.js.map +1 -1
- package/dist/{model-bundle-FSPZZ2EM.js → model-bundle-2C5IYDLE.js} +5 -5
- package/dist/{models-CJPAQK5R.js → models-SEQZHZFT.js} +5 -5
- package/dist/{parser-SCUTZAIJ.js → parser-3FNXEP6T.js} +708 -250
- package/dist/parser-3FNXEP6T.js.map +1 -0
- package/dist/{parser-A4TMPJAM.js → parser-FJBJXRJK.js} +708 -250
- package/dist/parser-FJBJXRJK.js.map +1 -0
- package/dist/{parser-VCXE4I5A.cjs → parser-HVEKF73B.cjs} +733 -275
- package/dist/parser-HVEKF73B.cjs.map +1 -0
- package/dist/pdf-ocr-JRDBJ6TA.cjs +14 -0
- package/dist/{pdf-ocr-MBZZ57LD.cjs.map → pdf-ocr-JRDBJ6TA.cjs.map} +1 -1
- package/dist/pdf-ocr-UUBWBEHL.js +16 -0
- package/dist/pdf-ocr-VJSF2SQC.js +13 -0
- package/dist/{profile-io-LBM263K7.js → profile-io-RUFZOZO6.js} +3 -3
- package/dist/{rasterize-46RG4ZF6.js → rasterize-IOYXR5SI.js} +3 -3
- package/dist/redact-NMIKVHMP.js +18 -0
- package/dist/redact-doc-QBHNJ2BU.js +1284 -0
- package/dist/redact-doc-QBHNJ2BU.js.map +1 -0
- package/dist/{render-NGP5T24S.js → render-YZ2TEC3N.js} +7 -7
- package/dist/seal-ECV44TUH.js +10 -0
- package/dist/{setup-AU4OCHNH.js → setup-MPIEP6XT.js} +3 -3
- package/dist/visual-ICMOWUCR.js +19 -0
- package/dist/{watch-MKPUCPXM.js → watch-RYO7MN5B.js} +12 -12
- package/package.json +2 -2
- package/dist/chunk-247ANM72.cjs.map +0 -1
- package/dist/chunk-3DUADAY2.js.map +0 -1
- package/dist/chunk-422427XJ.cjs +0 -571
- package/dist/chunk-422427XJ.cjs.map +0 -1
- package/dist/chunk-7IAQ4HOK.js.map +0 -1
- package/dist/chunk-A7QC2ZVP.js.map +0 -1
- package/dist/chunk-DZIXKL7E.js +0 -145
- package/dist/chunk-DZIXKL7E.js.map +0 -1
- package/dist/chunk-EISO3POT.js.map +0 -1
- package/dist/chunk-EP7KOI2V.js +0 -571
- package/dist/chunk-EP7KOI2V.js.map +0 -1
- package/dist/chunk-FOJZNMMK.js.map +0 -1
- package/dist/chunk-ILU76UF3.js.map +0 -1
- package/dist/chunk-KVWV4ULP.js +0 -516
- package/dist/chunk-KVWV4ULP.js.map +0 -1
- package/dist/chunk-L7DMSMAG.cjs.map +0 -1
- package/dist/chunk-QC5T6D4J.js.map +0 -1
- package/dist/chunk-QOMNEWCQ.cjs.map +0 -1
- package/dist/chunk-TSFS5VKD.js.map +0 -1
- package/dist/chunk-VQ5W4MYO.js.map +0 -1
- package/dist/chunks-SX77P5CV.js +0 -10
- package/dist/image-ocr-FLIL7MGN.js.map +0 -1
- package/dist/image-ocr-WCAYXLOA.js.map +0 -1
- package/dist/image-ocr-ZTYAGV3W.cjs.map +0 -1
- package/dist/parser-A4TMPJAM.js.map +0 -1
- package/dist/parser-SCUTZAIJ.js.map +0 -1
- package/dist/parser-VCXE4I5A.cjs.map +0 -1
- package/dist/pdf-ocr-76SAUXMZ.js +0 -13
- package/dist/pdf-ocr-CPU55CVF.js +0 -16
- package/dist/pdf-ocr-MBZZ57LD.cjs +0 -14
- package/dist/redact-7ILEAUTS.js +0 -12
- package/dist/seal-RGUPOLXD.js +0 -10
- package/dist/visual-NZLYIYEM.js +0 -19
- /package/dist/{-AQKXLFIM.js.map → -Z4TJ3QGK.js.map} +0 -0
- /package/dist/{chunk-ZWD734EY.js.map → chunk-7SE4EZ45.js.map} +0 -0
- /package/dist/{chunk-GDW4YP7K.js.map → chunk-GLSBEEZJ.js.map} +0 -0
- /package/dist/{chunk-JQEFP45L.js.map → chunk-GUJ4Q73I.js.map} +0 -0
- /package/dist/{chunk-ZWOFQRIB.js.map → chunk-HIJUKZHM.js.map} +0 -0
- /package/dist/{chunk-TNCKOL2O.js.map → chunk-LCW7SEPG.js.map} +0 -0
- /package/dist/{chunk-UET462HB.js.map → chunk-TITDJWVZ.js.map} +0 -0
- /package/dist/{chunk-C7FQBSON.js.map → chunk-V3DX4DUF.js.map} +0 -0
- /package/dist/{chunk-DOGPOY4B.js.map → chunk-VDN7LMPL.js.map} +0 -0
- /package/dist/{chunk-EDNJLUSE.js.map → chunk-VJIL6PIL.js.map} +0 -0
- /package/dist/{chunk-NS55SM7A.js.map → chunk-WJJGW5PL.js.map} +0 -0
- /package/dist/{chunks-SX77P5CV.js.map → chunks-CCMRL4MJ.js.map} +0 -0
- /package/dist/{formula-JGFTXWYT.js.map → formula-7RANCW5L.js.map} +0 -0
- /package/dist/{formula-5S7WWXGH.js.map → formula-7UYJOVTB.js.map} +0 -0
- /package/dist/{model-bundle-FSPZZ2EM.js.map → model-bundle-2C5IYDLE.js.map} +0 -0
- /package/dist/{models-CJPAQK5R.js.map → models-SEQZHZFT.js.map} +0 -0
- /package/dist/{pdf-ocr-76SAUXMZ.js.map → pdf-ocr-UUBWBEHL.js.map} +0 -0
- /package/dist/{pdf-ocr-CPU55CVF.js.map → pdf-ocr-VJSF2SQC.js.map} +0 -0
- /package/dist/{profile-io-LBM263K7.js.map → profile-io-RUFZOZO6.js.map} +0 -0
- /package/dist/{rasterize-46RG4ZF6.js.map → rasterize-IOYXR5SI.js.map} +0 -0
- /package/dist/{redact-7ILEAUTS.js.map → redact-NMIKVHMP.js.map} +0 -0
- /package/dist/{render-NGP5T24S.js.map → render-YZ2TEC3N.js.map} +0 -0
- /package/dist/{seal-RGUPOLXD.js.map → seal-ECV44TUH.js.map} +0 -0
- /package/dist/{setup-AU4OCHNH.js.map → setup-MPIEP6XT.js.map} +0 -0
- /package/dist/{visual-NZLYIYEM.js.map → visual-ICMOWUCR.js.map} +0 -0
- /package/dist/{watch-MKPUCPXM.js.map → watch-RYO7MN5B.js.map} +0 -0
package/README.md
CHANGED
|
@@ -84,18 +84,42 @@ MCP 등록 대신 스킬(SKILL.md) 형태로 쓰려면:
|
|
|
84
84
|
* **✏️ 양식 자동 채우기**: 공문서 양식 템플릿(신청서, 보고서)에 값을 넣으면 자동으로 빈칸을 채웁니다. 원본 서식(글꼴, 크기, 정렬)을 100% 보존합니다.
|
|
85
85
|
* **👓 내장 OCR — API 키 없이 (v4.2)**: 스캔본·이미지 PDF와 PNG/JPG/WebP 이미지를 **로컬 CPU 추론**(PP-OCRv5 korean)으로 읽습니다. 외부 서비스도 API 키도 없이, 텍스트층이 깨진 페이지만 골라 OCR 하고, 래스터 괘선까지 찾아 스캔본에서도 표를 복원합니다.
|
|
86
86
|
* **📑 RAG·인용 대응 (v4.1~4.8)**: 헤딩·개조식 위계를 breadcrumb으로 보존한 구조 청크(`--format chunks`)와, 조판 캐시로 복원한 **실제 쪽 번호** 기준 페이지별 마크다운(`pages`)을 냅니다 — 답변에 "몇 쪽" 각주를 붙일 수 있습니다.
|
|
87
|
-
* **🕶️ 개인정보 마스킹 (v4.1)**:
|
|
87
|
+
* **🕶️ 개인정보 마스킹 (v4.1)**: 주민·외국인등록번호·전화·이메일·카드·계좌·사업자등록번호·여권·운전면허(v4.14.4 부터 opt-in 으로 이름·주소)를 탐지해 **원본 서식 그대로** 가린 HWPX/HWP를 냅니다 (`kordoc redact`). 본문·표·머리말/꼬리말·각주·글상자·필드·미리보기(텍스트·이미지)·문서 정보(제목·작성자)까지 가리고, 결과 파일을 다시 훑어 남은 개인정보가 있으면 실패(exit 2)로 알립니다. **PDF·DOCX·XLSX 등은 원본 파일을 고치지 않고 마스킹된 마크다운만** 냅니다 — PDF 자체의 가림(redaction)은 지원하지 않습니다. 이미지 속 글자와 문맥 없는 맨이름은 탐지하지 못하는 자동 검출 보조 도구이므로 공개 전 사람 확인은 필수입니다.
|
|
88
88
|
* **🤖 AI 에이전트 연동 (MCP)**: `Claude Desktop`, `Cursor`, `Codex`와 같은 도구에서 직접 `kordoc`을 호출해 문서를 읽고 코딩할 수 있습니다.
|
|
89
89
|
|
|
90
90
|
---
|
|
91
91
|
|
|
92
|
+
## v4.14.4 변경사항
|
|
93
|
+
|
|
94
|
+
읽기 품질을 한 번 더 점검했습니다. 원본 HWPX 를 정답으로 PDF 글을 재는 벤치를 새로 세워 띄어쓰기·읽기 순서까지 보고, PDF 표·OCR·개인정보 마스킹을 고쳤습니다.
|
|
95
|
+
|
|
96
|
+
- **📊 PDF 표**: 쪽을 넘는 표의 쪼개진 행과 반복 머리 행, 쪽을 넘는 한 칸, 표 위에 걸친 그림·글상자, 셀 간격 표를 바로잡았습니다. hwpx↔pdf 430쌍 1,784표 정확 일치 90.1% → 92.9%, 표 안의 표 63.7% → 72.0%. 텍스트층이 있는 417쌍만 보면 94.5%, 칸 글이 제자리에 있는 비율 0.768 → 0.903.
|
|
97
|
+
- **✍️ PDF 띄어쓰기·줄 이음**: 본문을 시각 줄이 아니라 문단으로 복원합니다. 한글이 글자 단위로 줄바꿈된 문서에서 "재 일학도의용군인"·"또 는" 처럼 낱말 중간에 공백이 들어가던 것을 조사·어미·문서 안 어휘로 판정해 붙입니다. 어절 F1 0.925 → 0.971.
|
|
98
|
+
- **🧮 한컴 밖에서 만든 PDF**: 예산서처럼 글자마다 떨어져 찍힌 숫자("2 0 , 7 7 5" → "20,775"), 행마다 끊어 그은 괘선, 빈칸 위에 따로 얹은 숫자를 바로잡았습니다. PDF 글자 커버리지 0.99569 → 0.99760.
|
|
99
|
+
- **🔎 글자를 곡선으로 그린 PDF**: 한글을 글꼴 대신 곡선으로 그린 쪽은 텍스트층에 한글이 없어 종전엔 경고 없이 한글이 빠졌습니다. 이런 쪽을 찾아(`ocrReason: "vector_text"`) OCR 을 켜면 읽고, 끄면 경고합니다. 표는 그 쪽의 실제 괘선으로 복원합니다.
|
|
100
|
+
- **👓 OCR**: 점선 괘선·색 칸 경계·목차 리더 점·숫자 앞 △ 를 바로잡았습니다. 글자 오류율 0.171 → 0.096(정답지인 텍스트층 수정분 포함), OCR 표 셀 F1 0.440 → 0.618.
|
|
101
|
+
- **🕶️ 개인정보 마스킹 인명·주소** (opt-in, `--rules …,name,address`): 역할어·호칭·라벨·표 머리글 문맥으로 이름을, 도로명·지번 문법으로 주소를 찾아 가립니다(주소는 시·군·구까지 남김). 외부 정답(473문장) 인명 354/411·주소 141/141, 실문서 표본 오탐 0. 공무원 결재란 이름은 정보공개 관행상 공개 대상이라 기본값에는 넣지 않았습니다.
|
|
102
|
+
|
|
103
|
+
## v4.14.3 변경사항
|
|
104
|
+
|
|
105
|
+
읽기 품질을 전면 점검했습니다. 코퍼스를 넓히고(rhwp 표본 1,351파일·정책브리핑 hwpx+pdf 짝 200쌍) 포맷마다 정답지 벤치를 다시 세운 뒤 표·PDF·OCR·개인정보 마스킹을 고쳤고, 검색 색인처럼 글자만 필요한 호출자를 위한 두 가지를 더했습니다.
|
|
106
|
+
|
|
107
|
+
- **📊 PDF 표 복원**: 쪽을 넘는 표를 잇고, 표 안의 표를 틀 칸 안에 넣습니다. hwpx↔pdf 430쌍 1,784표 정확 일치 64.1% → 90.1%, 셀 F1 0.790 → 0.945.
|
|
108
|
+
- **🧾 HWP·HWP3·HWPX 표와 주석**: HWP 표를 HWPX 와 같은 규칙으로 배치해 hwp↔hwpx 쌍 3,593표가 모두 정확히 일치합니다(0.824 → 1). HWP3 표 격자를 복원하고, HWPX 각주·미주 번호와 문서 정보(제목·지은이 등)를 읽습니다.
|
|
109
|
+
- **👓 OCR**: 기울기를 보정하고 세로로 이어진 글 상자를 나눠 읽으며 공문서 기호(○·△·따옴표)를 되살립니다. 글자 오류율 0.201 → 0.171, 3° 기울어진 스캔 57.6% → 22.0%.
|
|
110
|
+
- **🕶️ 개인정보 마스킹**: 파일 안 모든 글자 저장소(머리말·각주·글상자·필드·미리보기·문서 정보 등)를 같은 길이로 가리고 결과를 다시 훑습니다. 5,081문서 오탐 387 → 0.
|
|
111
|
+
- **💲 본문의 `$` 가 수식이 되지 않습니다**: 한글 문서(HWPX·HWP·HWP3)의 리터럴 `$` 는 `\$` 로 내고 `$…$` 는 수식에만 씁니다. "echo $HOME $PATH" 같은 글이 마크다운 렌더러에서 수식으로 바뀌던 것. 역슬래시 뒤 구두점("C:\.Pls")에서 역슬래시가 사라지던 것도 고쳤습니다.
|
|
112
|
+
- **📝 미기입 누름틀 안내문을 빼고 읽습니다**: 한컴이 화면에만 흐리게 보이고 인쇄하지 않는 HWPX 안내문을 마크다운에서 뺍니다(블록 글에는 남김). 누름틀을 채우면 수정 표시를 켭니다.
|
|
113
|
+
- **🖼️ 이미지 끄기** (`images: false` / `--no-images`): 결과에 이미지 바이트를 싣지 않습니다. 그림 자리 표시(``)와 본문 글자는 그대로라 그림 위치는 알 수 있습니다. PDF 는 PNG 인코딩을 건너뜁니다. 그림 많은 PDF 실측: JSON 출력 200MB → 9.5MB, CPU 시간 30% 감소.
|
|
114
|
+
- **🚀 상주 파싱 워커** (`kordoc parse-worker`): 프로세스를 띄워 둔 채 stdin 요청 한 줄마다 한 줄 JSON 을 돌려줍니다. 파일마다 node 를 새로 띄우지 않아 대량 색인에 알맞습니다. 응답에 메모리 사용량(`rss`)을 실어 호스트가 워커 교체 시점을 정할 수 있습니다.
|
|
115
|
+
|
|
92
116
|
## v4.14.2 변경사항
|
|
93
117
|
|
|
94
118
|
공문서 출력을 한글 2024 실렌더 PDF로 다시 대조해 "진짜 공문처럼" 다듬었습니다.
|
|
95
119
|
|
|
96
120
|
- **📐 항목 둘째 줄이 첫 줄 내용과 정확히 맞습니다**: 부호(□ ○ - ※ 1. 가.) 뒤를 공백이 아니라 탭으로 두고, 한글의 "내어쓰기용 자동 탭"을 씁니다. 양쪽 정렬이 부호 뒤 공백을 늘려 첫 줄 내용이 밀리던 것, 자간을 줄인 줄에서 내용이 당겨지던 것이 구조적으로 없어졌습니다. 기안문·보고서·계획서·통지·회의록·업무보고·개조식·보도자료 전부.
|
|
97
121
|
- **✂️ 낱말이 줄 끝에서 쪼개지지 않습니다**: 본문을 어절 단위 줄바꿈으로 바꾸고("동대/문" → "동대문") 외톨이줄 보호를 켰습니다. 날짜·금액은 묶음 빈칸으로 묶어 "2026. 1. / 22." 처럼 갈라지지 않습니다. 곧은따옴표는 ‘ ’ “ ”로 바꿉니다.
|
|
98
|
-
- **📏 한글 글꼴 실폭으로 조판을 재현합니다**: 한컴돋움·HY견고딕·휴먼명조 등 8종의 실제 글자 폭으로 줄바꿈을
|
|
122
|
+
- **📏 한글 글꼴 실폭으로 조판을 재현합니다**: 한컴돋움·HY견고딕·휴먼명조 등 8종의 실제 글자 폭으로 줄바꿈을 계산합니다(한글 2024 PDF 154줄 전부 일치). 마지막 줄이 짧으면(줄 폭 절반 이하) 자간·장평을 최대 15%까지 줄여 한 줄 올리고, 한 줄에 맞춘다는 판단엔 2% 여유를 둬 한글에서 넘치지 않게 했습니다. 공백 없는 긴 목록("구(강남·강서·…·종로)가")처럼 한 줄보다 긴 어절이 있는 문단은 그 문단만 글자 단위로 조판하되 가운뎃점·쉼표 뒤에서만 끊어, 앞 줄이 크게 벌어지지 않습니다.
|
|
99
123
|
- **🧩 PPTX 감지** (#80, PR #81 @LimePencil): PPTX 를 넣으면 "HWPX 섹션 없음" 대신 지원하지 않는 형식이라고 알려 줍니다.
|
|
100
124
|
- **🧹 기술부채**: 1,200줄 넘던 `mcp.ts`·`cli.ts`·`hwp5/parser.ts`·`svg-render.ts` 를 기능별 모듈로 나눴고, 파서가 묶음 빈칸을 버리던 것과 `kordoc render` 미리보기의 탭 폭·줄 끝 공백 정렬을 고쳤습니다.
|
|
101
125
|
|
|
@@ -898,6 +922,24 @@ CLI로도: `kordoc render 결재문서.hwpx -o 결재문서.svg` — 조판 캐
|
|
|
898
922
|
reflow 조판되며 `--no-reflow`로 끌 수 있습니다 (`--highlight 예산,집행` 지원),
|
|
899
923
|
연속 렌더는 `kordoc render-worker`(stdin NDJSON, 미리보기 앱 연동용)
|
|
900
924
|
|
|
925
|
+
### 글자만 필요할 때 (이미지 끄기·상주 파싱 워커)
|
|
926
|
+
|
|
927
|
+
```typescript
|
|
928
|
+
const result = await parse(buffer, { images: false }) // 이미지 바이트 없이 (그림 자리 표시는 남김)
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
CLI 는 `kordoc 문서.pdf --format json --no-images`. 대량 변환은 `kordoc parse-worker` 를 띄워 두고
|
|
932
|
+
stdin 으로 한 줄씩 요청합니다 (한 줄 = 한 JSON).
|
|
933
|
+
|
|
934
|
+
```text
|
|
935
|
+
시작 {"ready":true,"version":"4.14.4","protocol":1}
|
|
936
|
+
요청 {"id":1,"file":"문서.hwpx","images":false,"ocr":"off"}
|
|
937
|
+
응답 {"id":1,"rss":183500800,"result":{ …--format json 과 같은 결과, 실패도 success:false 로… }}
|
|
938
|
+
종료 {"cmd":"quit"} (또는 stdin 닫기)
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
`ocr` 은 `"off"`·`"auto"`(OCR 필요 페이지만)·`"force"`, 그 밖에 `formulaOcr`·`password` 를 받습니다.
|
|
942
|
+
|
|
901
943
|
### 페이지 범위 지정
|
|
902
944
|
|
|
903
945
|
```typescript
|
|
@@ -946,7 +988,7 @@ for (const p of r.pageQuality ?? []) {
|
|
|
946
988
|
}
|
|
947
989
|
```
|
|
948
990
|
|
|
949
|
-
신호 키: `textChars`, `hangulRatio`, `controlCharRatio`, `replacementCharRatio`, `puaRatio` / `needsOcr` (페이지·문서 단위) / `ocrReason` (`low_text` | `high_pua` | `high_control` | `high_replacement`).
|
|
991
|
+
신호 키: `textChars`, `hangulRatio`, `controlCharRatio`, `replacementCharRatio`, `puaRatio` / `needsOcr` (페이지·문서 단위) / `ocrReason` (`low_text` | `high_pua` | `high_control` | `high_replacement` | `garbled_hangul` | `vector_text`). `vector_text` 는 글자를 곡선으로 그려 텍스트층에 글이 없는 쪽입니다(v4.14.4).
|
|
950
992
|
|
|
951
993
|
## CLI
|
|
952
994
|
|
|
@@ -973,8 +1015,11 @@ npx kordoc patch 원본.hwpx 편집.md -o 반영.hwpx # 서식 보존 라
|
|
|
973
1015
|
npx kordoc seal 신청서.hwpx --image 도장.png --anchor "(인)" -o 날인.hwpx # 도장/서명 날인
|
|
974
1016
|
npx kordoc validate 산출물.hwpx # HWPX 구조 검증 (ZIP·필수 파트·XML)
|
|
975
1017
|
npx kordoc lint 보고서.md # 공문서 표기법 검수 19룰 — 입력은 md/txt('-'=stdin), error 있으면 exit 1
|
|
976
|
-
npx kordoc redact 민원서류.hwpx -o 마스킹.hwpx # 개인정보 탐지 + 서식 보존 마스킹 (
|
|
1018
|
+
npx kordoc redact 민원서류.hwpx -o 마스킹.hwpx # 개인정보 탐지 + 서식 보존 마스킹 (머리말·각주·미리보기·문서 정보 포함, 잔존 재검사 — 남으면 exit 2)
|
|
977
1019
|
npx kordoc redact 민원서류.hwpx --mask-char '*' -o 마스킹.hwpx # 마스크 문자 지정 (기본 ●)
|
|
1020
|
+
npx kordoc redact 계약서.hwp --rules rrn,phone,crn --json --dry-run # 룰 선택(법인등록번호 crn·IP 는 opt-in) + 위치별 리포트만
|
|
1021
|
+
npx kordoc redact 민원서류.hwpx --rules rrn,phone,email,name,address -o 마스킹.hwpx # 이름·주소까지 (opt-in)
|
|
1022
|
+
npx kordoc redact 공문.pdf # PDF·DOCX 등은 원본을 고치지 않고 마스킹된 마크다운(.redacted.md)만 — PDF 가림 미지원
|
|
978
1023
|
npx kordoc profile 기관서식.hwpx # 표 서식 프로필(JSON) 추출 → generate --profile 로 재현
|
|
979
1024
|
npx kordoc render 결재문서.hwpx -o 미리보기.svg # 레이아웃 보존 SVG 렌더 (캐시 없는 문서는 자동 reflow 조판, --no-reflow로 끔)
|
|
980
1025
|
npx kordoc render 결재문서.hwpx --reflow-mode charAll -o 미리보기.svg # reflow 줄바꿈: keep(어절, 기본) | charAll(글자)
|
|
@@ -1091,7 +1136,7 @@ codex mcp add kordoc -- npx -y kordoc mcp
|
|
|
1091
1136
|
| `generate_document` | 마크다운(표·수식·차트 포함) → HWPX 생성, 공문서 프리셋 (v3.5) |
|
|
1092
1137
|
| `place_seal` | 도장/서명 이미지를 앵커 문구 위에 부유 배치 (v3.16) |
|
|
1093
1138
|
| `render_document` | HWPX·HWP를 조판 그대로 PNG/JPEG 이미지(응답)·SVG/HTML/PDF 파일로 렌더 — 생성·수정 결과를 AI가 눈으로 검증 (v4.1, HWP·포맷 확장 v4.13.1) |
|
|
1094
|
-
| `redact_document` | 개인정보(
|
|
1139
|
+
| `redact_document` | 개인정보(주민·외국인등록번호·전화·이메일·카드·계좌·사업자등록번호·여권·운전면허, opt-in 법인등록번호·IP·이름·주소) 탐지 + 서식 보존 마스킹 — HWPX/HWP는 머리말·각주·미리보기·문서 정보까지 가리고 잔존 재검사, 그 외 포맷은 마스킹된 마크다운만 (v4.1) |
|
|
1095
1140
|
| `parse_chunks` | RAG용 구조 청크 JSON — 헤딩·개조식 위계 breadcrumb + 표 독립 청크 (v4.1) |
|
|
1096
1141
|
| `crop_regions` | 렌더 영역(표·이미지·문단·도형)을 페이지 이미지에서 실배율로 잘라 저장 + regions.json (v4.13) |
|
|
1097
1142
|
| `extract_tables` | 표 분류(데이터표/조직도류/불확실) + 페이지·bbox + 정책별 crop — 조직도는 이미지로, 데이터표는 구조로 (v4.13.1) |
|
|
@@ -1148,7 +1193,7 @@ PPTX는 감지만 지원합니다. `parse()`는 PPTX 입력에 `success: false`,
|
|
|
1148
1193
|
| `placeSealHwpx(buffer, seals)` | 도장/서명 이미지를 앵커 문구 위에 부유 배치 (v3.16) |
|
|
1149
1194
|
| `validateHwpx(buffer)` | HWPX 구조 검증 — ZIP·mimetype·필수 파트·XML 웰폼드 (v3.16) |
|
|
1150
1195
|
| `lintGongmunText(text, { document? })` | 공문서 표기법 검수 19룰 + AI 슬롭 2룰 — 텍스트/마크다운 입력 (v4.0.1, v4.12.1 보강). `document: true` 면 붙임/"끝." 문서 단위 검사 포함 |
|
|
1151
|
-
| `redactMarkdown(text, options?)` / `redactText(...)` | 개인정보 탐지 + 마스킹 (기본 룰:
|
|
1196
|
+
| `redactMarkdown(text, options?)` / `redactText(...)` | 개인정보 탐지 + 마스킹 (기본 룰: 주민·외국인등록번호·전화·이메일·카드·계좌·사업자등록번호·여권·운전면허, opt-in: 법인등록번호·IP — 텍스트 단위, 파일 단위 마스킹은 CLI `redact`/MCP `redact_document`, v4.1) |
|
|
1152
1197
|
| `blocksToChunks(blocks, options?)` | RAG용 구조 청크 — 헤딩·개조식 위계 breadcrumb + 표 독립 청크 (v4.1) |
|
|
1153
1198
|
| `blocksToMarkdown(blocks)` | IRBlock[] → Markdown 문자열 |
|
|
1154
1199
|
| `blocksToPages(blocks)` | IRBlock[] → `[{ pageNumber, markdown }]` 페이지별 마크다운 (v4.8) |
|
|
@@ -51,22 +51,22 @@ import {
|
|
|
51
51
|
unknownFontWarnings,
|
|
52
52
|
usesGaejosikMunche,
|
|
53
53
|
validateHwpx
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-XVXHXQIO.js";
|
|
55
55
|
import {
|
|
56
56
|
applySplices,
|
|
57
57
|
buildParagraphSplices,
|
|
58
58
|
buildRangeSplices,
|
|
59
59
|
placeSealHwpx,
|
|
60
60
|
scanSectionXml
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-HIJUKZHM.js";
|
|
62
62
|
import {
|
|
63
63
|
DEFAULT_REDACT_RULES,
|
|
64
64
|
redactMarkdown,
|
|
65
65
|
redactText
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-DPWWXUOG.js";
|
|
67
67
|
import {
|
|
68
68
|
blocksToChunks
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-VJIL6PIL.js";
|
|
70
70
|
import {
|
|
71
71
|
SPACE_EM_FIXED,
|
|
72
72
|
SPACE_EM_FONT,
|
|
@@ -91,19 +91,20 @@ import {
|
|
|
91
91
|
renderSceneToHtml,
|
|
92
92
|
simulateWrap,
|
|
93
93
|
simulateWrapKeepWord
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-D4U2TXDC.js";
|
|
95
95
|
import "./chunk-7FCNOKOR.js";
|
|
96
|
-
import "./chunk-
|
|
96
|
+
import "./chunk-6BWU6SQX.js";
|
|
97
97
|
import "./chunk-MOL7MDBG.js";
|
|
98
|
-
import "./chunk-
|
|
98
|
+
import "./chunk-YAKC46HZ.js";
|
|
99
99
|
import {
|
|
100
100
|
blocksToMarkdown,
|
|
101
|
+
flattenLayoutTables,
|
|
101
102
|
hasStructuredCellContent
|
|
102
|
-
} from "./chunk-
|
|
103
|
-
import "./chunk-
|
|
103
|
+
} from "./chunk-NLU6LBLY.js";
|
|
104
|
+
import "./chunk-V3DX4DUF.js";
|
|
104
105
|
import {
|
|
105
106
|
VERSION
|
|
106
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-TITDJWVZ.js";
|
|
107
108
|
export {
|
|
108
109
|
BUILTIN_TEMPLATES,
|
|
109
110
|
DEFAULT_REDACT_RULES,
|
|
@@ -140,6 +141,7 @@ export {
|
|
|
140
141
|
fillHwpx,
|
|
141
142
|
fillWithUniqueGuard,
|
|
142
143
|
fitRatioForFewerLines,
|
|
144
|
+
flattenLayoutTables,
|
|
143
145
|
formatFillValue,
|
|
144
146
|
gongmunLintWarnings,
|
|
145
147
|
hasStructuredCellContent,
|
|
@@ -192,4 +194,4 @@ export {
|
|
|
192
194
|
usesGaejosikMunche,
|
|
193
195
|
validateHwpx
|
|
194
196
|
};
|
|
195
|
-
//# sourceMappingURL=-
|
|
197
|
+
//# sourceMappingURL=-Z4TJ3QGK.js.map
|
|
@@ -1,6 +1,237 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkWJHAU73Bcjs = require('./chunk-WJHAU73B.cjs');
|
|
4
|
+
|
|
5
|
+
// src/shared/symbol-fonts.ts
|
|
6
|
+
var WINGDINGS = [
|
|
7
|
+
"\u{1F589}",
|
|
8
|
+
"\u2702",
|
|
9
|
+
"\u2701",
|
|
10
|
+
"\u{1F453}",
|
|
11
|
+
"\u{1F56D}",
|
|
12
|
+
"\u{1F56E}",
|
|
13
|
+
"\u{1F56F}",
|
|
14
|
+
"\u{1F57F}",
|
|
15
|
+
"\u2706",
|
|
16
|
+
"\u{1F582}",
|
|
17
|
+
"\u{1F583}",
|
|
18
|
+
"\u{1F4EA}",
|
|
19
|
+
"\u{1F4EB}",
|
|
20
|
+
"\u{1F4EC}",
|
|
21
|
+
"\u{1F4ED}",
|
|
22
|
+
"\u{1F4C1}",
|
|
23
|
+
"\u{1F4C2}",
|
|
24
|
+
"\u{1F4C4}",
|
|
25
|
+
"\u{1F5CF}",
|
|
26
|
+
"\u{1F5D0}",
|
|
27
|
+
"\u{1F5C4}",
|
|
28
|
+
"\u231B",
|
|
29
|
+
"\u{1F5AE}",
|
|
30
|
+
"\u{1F5B0}",
|
|
31
|
+
"\u{1F5B2}",
|
|
32
|
+
"\u{1F5B3}",
|
|
33
|
+
"\u{1F5B4}",
|
|
34
|
+
"\u{1F5AB}",
|
|
35
|
+
"\u{1F5AC}",
|
|
36
|
+
"\u2707",
|
|
37
|
+
"\u270D",
|
|
38
|
+
"\u{1F58E}",
|
|
39
|
+
"\u270C",
|
|
40
|
+
"\u{1F44C}",
|
|
41
|
+
"\u{1F44D}",
|
|
42
|
+
"\u{1F44E}",
|
|
43
|
+
"\u261C",
|
|
44
|
+
"\u261E",
|
|
45
|
+
"\u261D",
|
|
46
|
+
"\u261F",
|
|
47
|
+
"\u{1F590}",
|
|
48
|
+
"\u263A",
|
|
49
|
+
"\u{1F610}",
|
|
50
|
+
"\u2639",
|
|
51
|
+
"\u{1F4A3}",
|
|
52
|
+
"\u2620",
|
|
53
|
+
"\u{1F3F3}",
|
|
54
|
+
"\u{1F3F1}",
|
|
55
|
+
"\u2708",
|
|
56
|
+
"\u263C",
|
|
57
|
+
"\u{1F4A7}",
|
|
58
|
+
"\u2744",
|
|
59
|
+
"\u{1F546}",
|
|
60
|
+
"\u271E",
|
|
61
|
+
"\u{1F548}",
|
|
62
|
+
"\u2720",
|
|
63
|
+
"\u2721",
|
|
64
|
+
"\u262A",
|
|
65
|
+
"\u262F",
|
|
66
|
+
"\u0950",
|
|
67
|
+
"\u2638",
|
|
68
|
+
"\u2648",
|
|
69
|
+
"\u2649",
|
|
70
|
+
"\u264A",
|
|
71
|
+
"\u264B",
|
|
72
|
+
"\u264C",
|
|
73
|
+
"\u264D",
|
|
74
|
+
"\u264E",
|
|
75
|
+
"\u264F",
|
|
76
|
+
"\u2650",
|
|
77
|
+
"\u2651",
|
|
78
|
+
"\u2652",
|
|
79
|
+
"\u2653",
|
|
80
|
+
"\u{1F670}",
|
|
81
|
+
"\u{1F675}",
|
|
82
|
+
"\u25CF",
|
|
83
|
+
"\u25CB",
|
|
84
|
+
"\u25A0",
|
|
85
|
+
"\u25A1",
|
|
86
|
+
"\u25A1",
|
|
87
|
+
"\u2751",
|
|
88
|
+
"\u2752",
|
|
89
|
+
"\u2B27",
|
|
90
|
+
"\u29EB",
|
|
91
|
+
"\u25C6",
|
|
92
|
+
"\u2756",
|
|
93
|
+
"\u2B25",
|
|
94
|
+
"\u2327",
|
|
95
|
+
"\u2BB9",
|
|
96
|
+
"\u2318",
|
|
97
|
+
"\u{1F3F5}",
|
|
98
|
+
"\u{1F3F6}",
|
|
99
|
+
"\u{1F676}",
|
|
100
|
+
"\u{1F677}",
|
|
101
|
+
"",
|
|
102
|
+
"\u24EA",
|
|
103
|
+
"\u2460",
|
|
104
|
+
"\u2461",
|
|
105
|
+
"\u2462",
|
|
106
|
+
"\u2463",
|
|
107
|
+
"\u2464",
|
|
108
|
+
"\u2465",
|
|
109
|
+
"\u2466",
|
|
110
|
+
"\u2467",
|
|
111
|
+
"\u2468",
|
|
112
|
+
"\u2469",
|
|
113
|
+
"\u24FF",
|
|
114
|
+
"\u2776",
|
|
115
|
+
"\u2777",
|
|
116
|
+
"\u2778",
|
|
117
|
+
"\u2779",
|
|
118
|
+
"\u277A",
|
|
119
|
+
"\u277B",
|
|
120
|
+
"\u277C",
|
|
121
|
+
"\u277D",
|
|
122
|
+
"\u277E",
|
|
123
|
+
"\u277F",
|
|
124
|
+
"\u{1F662}",
|
|
125
|
+
"\u{1F660}",
|
|
126
|
+
"\u{1F661}",
|
|
127
|
+
"\u{1F663}",
|
|
128
|
+
"\u{1F65E}",
|
|
129
|
+
"\u{1F65C}",
|
|
130
|
+
"\u{1F65D}",
|
|
131
|
+
"\u{1F65F}",
|
|
132
|
+
"\xB7",
|
|
133
|
+
"\u2022",
|
|
134
|
+
"\u25AA",
|
|
135
|
+
"\u26AA",
|
|
136
|
+
"\u25CB",
|
|
137
|
+
"\u25EF",
|
|
138
|
+
"\u25C9",
|
|
139
|
+
"\u25CE",
|
|
140
|
+
"\u{1F53F}",
|
|
141
|
+
"\u25AA",
|
|
142
|
+
"\u25FB",
|
|
143
|
+
"\u{1F7C2}",
|
|
144
|
+
"\u2726",
|
|
145
|
+
"\u2605",
|
|
146
|
+
"\u2736",
|
|
147
|
+
"\u2734",
|
|
148
|
+
"\u2739",
|
|
149
|
+
"\u2735",
|
|
150
|
+
"\u2BD0",
|
|
151
|
+
"\u2316",
|
|
152
|
+
"\u27E1",
|
|
153
|
+
"\u2311",
|
|
154
|
+
"\u2BD1",
|
|
155
|
+
"\u272A",
|
|
156
|
+
"\u2730",
|
|
157
|
+
"\u{1F550}",
|
|
158
|
+
"\u{1F551}",
|
|
159
|
+
"\u{1F552}",
|
|
160
|
+
"\u{1F553}",
|
|
161
|
+
"\u{1F554}",
|
|
162
|
+
"\u{1F555}",
|
|
163
|
+
"\u{1F556}",
|
|
164
|
+
"\u{1F557}",
|
|
165
|
+
"\u{1F558}",
|
|
166
|
+
"\u{1F559}",
|
|
167
|
+
"\u{1F55A}",
|
|
168
|
+
"\u{1F55B}",
|
|
169
|
+
"\u2BB0",
|
|
170
|
+
"\u2BB1",
|
|
171
|
+
"\u2BB2",
|
|
172
|
+
"\u2BB3",
|
|
173
|
+
"\u2BB4",
|
|
174
|
+
"\u2BB5",
|
|
175
|
+
"\u2BB6",
|
|
176
|
+
"\u2BB7",
|
|
177
|
+
"\u{1F66A}",
|
|
178
|
+
"\u{1F66B}",
|
|
179
|
+
"\u{1F655}",
|
|
180
|
+
"\u{1F654}",
|
|
181
|
+
"\u{1F657}",
|
|
182
|
+
"\u{1F656}",
|
|
183
|
+
"\u{1F650}",
|
|
184
|
+
"\u{1F651}",
|
|
185
|
+
"\u{1F652}",
|
|
186
|
+
"\u{1F653}",
|
|
187
|
+
"\u232B",
|
|
188
|
+
"\u2326",
|
|
189
|
+
"\u2B98",
|
|
190
|
+
"\u2B9A",
|
|
191
|
+
"\u2B99",
|
|
192
|
+
"\u2B9B",
|
|
193
|
+
"\u2B88",
|
|
194
|
+
"\u2B8A",
|
|
195
|
+
"\u2B89",
|
|
196
|
+
"\u2B8B",
|
|
197
|
+
"\u2190",
|
|
198
|
+
"\u2192",
|
|
199
|
+
"\u2191",
|
|
200
|
+
"\u2193",
|
|
201
|
+
"\u2196",
|
|
202
|
+
"\u2197",
|
|
203
|
+
"\u2199",
|
|
204
|
+
"\u2198",
|
|
205
|
+
"\u2B05",
|
|
206
|
+
"\u2794",
|
|
207
|
+
"\u2B06",
|
|
208
|
+
"\u2B07",
|
|
209
|
+
"\u2B09",
|
|
210
|
+
"\u2B08",
|
|
211
|
+
"\u2B0B",
|
|
212
|
+
"\u2B0A",
|
|
213
|
+
"\u21E6",
|
|
214
|
+
"\u21E8",
|
|
215
|
+
"\u21E7",
|
|
216
|
+
"\u21E9",
|
|
217
|
+
"\u2B04",
|
|
218
|
+
"\u21F3",
|
|
219
|
+
"\u2B00",
|
|
220
|
+
"\u2B01",
|
|
221
|
+
"\u2B03",
|
|
222
|
+
"\u2B02",
|
|
223
|
+
"\u{1F8AC}",
|
|
224
|
+
"\u{1F8AD}",
|
|
225
|
+
"\u2717",
|
|
226
|
+
"\u2714",
|
|
227
|
+
"\u2612",
|
|
228
|
+
"\u2611",
|
|
229
|
+
""
|
|
230
|
+
];
|
|
231
|
+
function wingdingsChar(code) {
|
|
232
|
+
if (code < 33 || code > 255) return void 0;
|
|
233
|
+
return WINGDINGS[code - 33] || void 0;
|
|
234
|
+
}
|
|
4
235
|
|
|
5
236
|
// src/shared/pua.ts
|
|
6
237
|
var BMP_SYMBOL_MAP = {
|
|
@@ -188,7 +419,7 @@ var BOXED_NUMBER_START = 983729;
|
|
|
188
419
|
var BOXED_NUMBER_END = 983748;
|
|
189
420
|
function mapPuaChar(code) {
|
|
190
421
|
if (code >= 61472 && code <= 61695) {
|
|
191
|
-
return BMP_SYMBOL_MAP[code - 61440];
|
|
422
|
+
return _nullishCoalesce(BMP_SYMBOL_MAP[code - 61440], () => ( wingdingsChar(code - 61440)));
|
|
192
423
|
}
|
|
193
424
|
if (code >= BOXED_NUMBER_START && code <= BOXED_NUMBER_END) {
|
|
194
425
|
return String.fromCodePoint(9312 + (code - BOXED_NUMBER_START));
|
|
@@ -264,32 +495,54 @@ function buildTable(rows, options) {
|
|
|
264
495
|
}
|
|
265
496
|
function buildTableDirect(rows, numRows, options) {
|
|
266
497
|
let maxCols = 0;
|
|
498
|
+
const rowCap = Math.min(MAX_ROWS, numRows + rows.reduce((n, r) => n + r.length, 0) + 1);
|
|
267
499
|
for (const row of rows) {
|
|
268
500
|
for (const cell of row) {
|
|
269
501
|
const end = (_nullishCoalesce(cell.colAddr, () => ( 0))) + cell.colSpan;
|
|
270
502
|
if (end > maxCols) maxCols = end;
|
|
503
|
+
if (cell.rowAddr !== void 0 && cell.rowAddr >= numRows) numRows = Math.min(cell.rowAddr + 1, rowCap);
|
|
271
504
|
}
|
|
272
505
|
}
|
|
273
506
|
if (maxCols > MAX_COLS) maxCols = MAX_COLS;
|
|
274
|
-
if (maxCols === 0) return { rows: 0, cols: 0, cells: [], hasHeader: false };
|
|
507
|
+
if (maxCols === 0 || numRows === 0) return { rows: 0, cols: 0, cells: [], hasHeader: false };
|
|
275
508
|
const grid = Array.from(
|
|
276
509
|
{ length: numRows },
|
|
277
510
|
() => Array.from({ length: maxCols }, () => ({ text: "", colSpan: 1, rowSpan: 1 }))
|
|
278
511
|
);
|
|
512
|
+
const owner = Array.from({ length: numRows }, () => new Array(maxCols));
|
|
279
513
|
const anchorCols = /* @__PURE__ */ new Set();
|
|
280
|
-
for (
|
|
281
|
-
for (const cell of
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
|
|
514
|
+
for (let ri = 0; ri < rows.length; ri++) {
|
|
515
|
+
for (const cell of rows[ri]) {
|
|
516
|
+
const text = _optionalChain([options, 'optionalAccess', _3 => _3.keepEmptyParagraphs]) ? cell.text : cell.text.trim();
|
|
517
|
+
const r = Math.min(_nullishCoalesce(cell.rowAddr, () => ( ri)), numRows - 1);
|
|
518
|
+
let c = _nullishCoalesce(cell.colAddr, () => ( 0));
|
|
519
|
+
if (r < 0 || c < 0) continue;
|
|
520
|
+
if (cell.colAddr === void 0) while (c < maxCols - 1 && owner[r][c]) c++;
|
|
521
|
+
if (c >= maxCols) c = maxCols - 1;
|
|
522
|
+
const own = owner[r][c];
|
|
523
|
+
if (own) {
|
|
524
|
+
if (text.trim()) own.text = own.text ? `${own.text}
|
|
525
|
+
${text}` : text;
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
let colSpan = Math.max(1, Math.min(cell.colSpan, maxCols - c));
|
|
529
|
+
for (let dc = 1; dc < colSpan; dc++) if (owner[r][c + dc]) {
|
|
530
|
+
colSpan = dc;
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
let rowSpan = Math.max(1, Math.min(cell.rowSpan, numRows - r));
|
|
534
|
+
for (let dr = 1; dr < rowSpan; dr++) {
|
|
535
|
+
if (owner[r + dr].slice(c, c + colSpan).some(Boolean)) {
|
|
536
|
+
rowSpan = dr;
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const ir = { text, colSpan, rowSpan };
|
|
285
541
|
anchorCols.add(c);
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (r + dr < numRows && c + dc < maxCols) {
|
|
291
|
-
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
292
|
-
}
|
|
542
|
+
for (let dr = 0; dr < rowSpan; dr++) {
|
|
543
|
+
for (let dc = 0; dc < colSpan; dc++) {
|
|
544
|
+
owner[r + dr][c + dc] = ir;
|
|
545
|
+
grid[r + dr][c + dc] = dr === 0 && dc === 0 ? ir : { text: "", colSpan: 1, rowSpan: 1 };
|
|
293
546
|
}
|
|
294
547
|
}
|
|
295
548
|
}
|
|
@@ -306,6 +559,11 @@ function trimAndReturn(grid, numRows, maxCols, anchorCols, options) {
|
|
|
306
559
|
}
|
|
307
560
|
if (effectiveCols < maxCols && effectiveCols > 0) {
|
|
308
561
|
const trimmed = grid.map((row) => row.slice(0, effectiveCols));
|
|
562
|
+
for (const row of trimmed) {
|
|
563
|
+
for (let c = 0; c < row.length; c++) {
|
|
564
|
+
if (c + row[c].colSpan > effectiveCols) row[c].colSpan = effectiveCols - c;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
309
567
|
return { rows: numRows, cols: effectiveCols, cells: trimmed, hasHeader: numRows > 1 };
|
|
310
568
|
}
|
|
311
569
|
return { rows: numRows, cols: maxCols, cells: grid, hasHeader: numRows > 1 };
|
|
@@ -318,13 +576,16 @@ function convertTableToText(rows) {
|
|
|
318
576
|
function escapeGfm(text) {
|
|
319
577
|
const NUL = String.fromCharCode(0);
|
|
320
578
|
const spans = [];
|
|
321
|
-
const masked = text.replace(/!\[[^\]]*\]\([^)\n]*\)|\]\((?:https?:|mailto:|tel:|#)[^)\n]*\)
|
|
579
|
+
const masked = text.replace(/!\[[^\]]*\]\([^)\n]*\)|\]\((?:https?:|mailto:|tel:|#)[^)\n]*\)|(?<!\\)\$\$(?:\\[\s\S]|[^\\$])*\$\$|(?<!\\)\$(?:\\[^\n]|[^\\$\n])*\$/gi, (m) => {
|
|
322
580
|
spans.push(m);
|
|
323
581
|
return NUL + (spans.length - 1) + NUL;
|
|
324
582
|
});
|
|
325
|
-
const escaped = masked.replace(/([~*_`])/g, "\\$1");
|
|
583
|
+
const escaped = masked.replace(/\\(?=[!-#%-\/:-@\[-\x60{}~])/g, "\\\\").replace(/([~*_`])/g, "\\$1").replace(/(?<!\\)\|/g, "\\|").replace(/^([ \t]*)(?=#{1,6}(?:[ \t]|$))/gm, "$1\\").replace(/<(?!\/?u>)(?=[A-Za-z/!?])/g, "\\<");
|
|
326
584
|
return escaped.replace(new RegExp(NUL + "(\\d+)" + NUL, "g"), (_, n) => spans[Number(n)]);
|
|
327
585
|
}
|
|
586
|
+
function escapeLiteralDollar(text) {
|
|
587
|
+
return text.includes("$") ? text.replace(/\$/g, "\\$") : text;
|
|
588
|
+
}
|
|
328
589
|
var HWP_SHAPE_ALT_TEXT_RE = /^(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|이등변 삼각형|직각 삼각형|선|직선|곡선|화살표|굵은 화살표|이중 화살표|오각형|육각형|팔각형|별|[4-8]점별|십자|십자형|구름|구름형|마름모|도넛|평행사변형|사다리꼴|부채꼴|호|반원|물결|번개|하트|빗금|블록 화살표|수식|표|그림|개체|그리기\s?개체|묶음\s?개체|글상자|수식\s?개체|OLE\s?개체)\s?입니다\.?$/gm;
|
|
329
590
|
function sanitizePua(text) {
|
|
330
591
|
return mapPuaText(text).replace(/[\u{F0000}-\u{FFFFD}]/gu, "");
|
|
@@ -423,6 +684,7 @@ function dedupeRunningHeaders(blocks) {
|
|
|
423
684
|
function spansToMarkdown(spans) {
|
|
424
685
|
let out = "";
|
|
425
686
|
for (const s of spans) {
|
|
687
|
+
if (s.placeholder) continue;
|
|
426
688
|
const text = sanitizePua(_nullishCoalesce(s.text, () => ( "")));
|
|
427
689
|
if (!text) continue;
|
|
428
690
|
let marker = s.code ? "`" : s.bold && s.italic ? "***" : s.bold ? "**" : s.italic ? "*" : "";
|
|
@@ -455,7 +717,8 @@ function blocksToMarkdown(blocks) {
|
|
|
455
717
|
if (block.type === "heading" && block.text) {
|
|
456
718
|
const prefix = "#".repeat(Math.min(block.level || 2, 6));
|
|
457
719
|
const headingText = sanitizeText(block.text);
|
|
458
|
-
|
|
720
|
+
const note = block.footnoteText ? ` (\uC8FC: ${block.footnoteText})` : "";
|
|
721
|
+
if (headingText) lines.push("", `${prefix} ${escapeGfm(headingText + note)}`, "");
|
|
459
722
|
continue;
|
|
460
723
|
}
|
|
461
724
|
if (block.type === "image" && block.text) {
|
|
@@ -501,7 +764,7 @@ function blocksToMarkdown(blocks) {
|
|
|
501
764
|
if (_optionalChain([block, 'access', _26 => _26.spans, 'optionalAccess', _27 => _27.length])) {
|
|
502
765
|
let rendered = spansToMarkdown(block.spans);
|
|
503
766
|
if (block.href) {
|
|
504
|
-
const href =
|
|
767
|
+
const href = _chunkWJHAU73Bcjs.sanitizeHref.call(void 0, block.href);
|
|
505
768
|
if (href) rendered = `[${rendered}](${href})`;
|
|
506
769
|
}
|
|
507
770
|
if (block.footnoteText) rendered += ` (\uC8FC: ${block.footnoteText})`;
|
|
@@ -509,7 +772,7 @@ function blocksToMarkdown(blocks) {
|
|
|
509
772
|
continue;
|
|
510
773
|
}
|
|
511
774
|
if (block.href) {
|
|
512
|
-
const href =
|
|
775
|
+
const href = _chunkWJHAU73Bcjs.sanitizeHref.call(void 0, block.href);
|
|
513
776
|
if (href) text = `[${text}](${href})`;
|
|
514
777
|
}
|
|
515
778
|
if (block.footnoteText) {
|
|
@@ -549,16 +812,22 @@ function hasStructuredCellContent(table) {
|
|
|
549
812
|
}
|
|
550
813
|
return false;
|
|
551
814
|
}
|
|
815
|
+
function noteSuffix(b) {
|
|
816
|
+
return b.footnoteText && b.text ? ` (\uC8FC: ${b.footnoteText})` : "";
|
|
817
|
+
}
|
|
818
|
+
function visibleText(b) {
|
|
819
|
+
return _optionalChain([b, 'access', _31 => _31.spans, 'optionalAccess', _32 => _32.some, 'call', _33 => _33((s) => s.placeholder)]) ? b.spans.filter((s) => !s.placeholder).map((s) => s.text).join("") : _nullishCoalesce(b.text, () => ( ""));
|
|
820
|
+
}
|
|
552
821
|
function cellInnerHtml(cell) {
|
|
553
|
-
if (_optionalChain([cell, 'access',
|
|
822
|
+
if (_optionalChain([cell, 'access', _34 => _34.blocks, 'optionalAccess', _35 => _35.length])) {
|
|
554
823
|
return cell.blocks.map((b) => {
|
|
555
824
|
if (b.type === "table" && b.table) {
|
|
556
825
|
const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
|
|
557
826
|
return (cap ? cap + "<br>" : "") + tableToHtml(b.table);
|
|
558
827
|
}
|
|
559
828
|
if (b.type === "image" && b.text) return `<img src="${b.text}" alt="image">`;
|
|
560
|
-
const t = sanitizeText(
|
|
561
|
-
return t ? t.replace(/\n/g, "<br>") : "";
|
|
829
|
+
const t = sanitizeText(visibleText(b));
|
|
830
|
+
return t ? (t + noteSuffix(b)).replace(/\n/g, "<br>") : "";
|
|
562
831
|
}).filter(Boolean).join("<br>");
|
|
563
832
|
}
|
|
564
833
|
return sanitizeText(cell.text).replace(/\n/g, "<br>");
|
|
@@ -583,7 +852,7 @@ function tableToHtml(table) {
|
|
|
583
852
|
const rowHtml = [];
|
|
584
853
|
for (let c = 0; c < numCols; c++) {
|
|
585
854
|
if (skip.has(`${r},${c}`)) continue;
|
|
586
|
-
const cell = _optionalChain([cells, 'access',
|
|
855
|
+
const cell = _optionalChain([cells, 'access', _36 => _36[r], 'optionalAccess', _37 => _37[c]]);
|
|
587
856
|
if (!cell) continue;
|
|
588
857
|
for (let dr = 0; dr < cell.rowSpan; dr++) {
|
|
589
858
|
for (let dc = 0; dc < cell.colSpan; dc++) {
|
|
@@ -598,7 +867,7 @@ function tableToHtml(table) {
|
|
|
598
867
|
const attrStr = attrs.length ? " " + attrs.join(" ") : "";
|
|
599
868
|
rowHtml.push(`<${tag}${attrStr}>${text}</${tag}>`);
|
|
600
869
|
}
|
|
601
|
-
|
|
870
|
+
lines.push(`<tr>${rowHtml.join("")}</tr>`);
|
|
602
871
|
}
|
|
603
872
|
lines.push("</table>");
|
|
604
873
|
return lines.join("\n");
|
|
@@ -606,7 +875,8 @@ function tableToHtml(table) {
|
|
|
606
875
|
function tableToMarkdown(table) {
|
|
607
876
|
if (table.rows === 0 || table.cols === 0) return "";
|
|
608
877
|
const { cells, rows: numRows, cols: numCols } = table;
|
|
609
|
-
if (
|
|
878
|
+
if (hasStructuredCellContent(table)) return tableToHtml(table);
|
|
879
|
+
if (hasMergedCells(table) && !tableContainsInlineMath(table)) {
|
|
610
880
|
return tableToHtml(table);
|
|
611
881
|
}
|
|
612
882
|
if (numRows === 1 && numCols === 1) {
|
|
@@ -628,9 +898,9 @@ function tableToMarkdown(table) {
|
|
|
628
898
|
for (let r = 0; r < numRows; r++) {
|
|
629
899
|
for (let c = 0; c < numCols; c++) {
|
|
630
900
|
if (skip.has(`${r},${c}`)) continue;
|
|
631
|
-
const cell = _optionalChain([cells, 'access',
|
|
901
|
+
const cell = _optionalChain([cells, 'access', _38 => _38[r], 'optionalAccess', _39 => _39[c]]);
|
|
632
902
|
if (!cell) continue;
|
|
633
|
-
display[r][c] = (_optionalChain([cell, 'access',
|
|
903
|
+
display[r][c] = (_optionalChain([cell, 'access', _40 => _40.blocks, 'optionalAccess', _41 => _41.some, 'call', _42 => _42((b) => b.spans || b.type === "image" && b.text)]) ? cell.blocks.map((b) => b.type === "image" && b.text ? `` : b.spans ? spansToMarkdown(b.spans) + escapeGfm(noteSuffix(b)) : escapeGfm(sanitizeText(_nullishCoalesce(b.text, () => ( ""))) + noteSuffix(b))).filter(Boolean).join("<br>") : escapeGfm(sanitizeText(cell.text)).replace(/\n/g, "<br>")).replace(/(?<!\\)\|/g, "\\|");
|
|
634
904
|
for (let dr = 0; dr < cell.rowSpan; dr++) {
|
|
635
905
|
for (let dc = 0; dc < cell.colSpan; dc++) {
|
|
636
906
|
if (dr === 0 && dc === 0) continue;
|
|
@@ -791,7 +1061,7 @@ function encodePng(width, height, rgba) {
|
|
|
791
1061
|
return out;
|
|
792
1062
|
}
|
|
793
1063
|
function inlineImagesIntoMarkdown(markdown, images, opts) {
|
|
794
|
-
const compress = _optionalChain([opts, 'optionalAccess',
|
|
1064
|
+
const compress = _optionalChain([opts, 'optionalAccess', _43 => _43.compress]) !== false;
|
|
795
1065
|
const uris = /* @__PURE__ */ new Map();
|
|
796
1066
|
for (const img of images) {
|
|
797
1067
|
let bytes = img.data;
|
|
@@ -829,5 +1099,9 @@ function inlineImagesIntoMarkdown(markdown, images, opts) {
|
|
|
829
1099
|
|
|
830
1100
|
|
|
831
1101
|
|
|
832
|
-
|
|
833
|
-
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
exports.WINGDINGS = WINGDINGS; exports.mapPuaText = mapPuaText; exports.MAX_COLS = MAX_COLS; exports.MAX_ROWS = MAX_ROWS; exports.buildTable = buildTable; exports.convertTableToText = convertTableToText; exports.escapeGfm = escapeGfm; exports.escapeLiteralDollar = escapeLiteralDollar; exports.flattenLayoutTables = flattenLayoutTables; exports.dedupeRunningHeaders = dedupeRunningHeaders; exports.blocksToMarkdown = blocksToMarkdown; exports.hasStructuredCellContent = hasStructuredCellContent; exports.noteSuffix = noteSuffix; exports.encodePng = encodePng; exports.inlineImagesIntoMarkdown = inlineImagesIntoMarkdown;
|
|
1107
|
+
//# sourceMappingURL=chunk-5LAZQCUJ.cjs.map
|