kordoc 2.0.2 → 2.0.3

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 chrisryugj
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 chrisryugj
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,291 +1,291 @@
1
- # kordoc
2
-
3
- **모두 파싱해버리겠다.**
4
-
5
- [![npm version](https://img.shields.io/badge/npm-v2.0.1-cb3837.svg)](https://www.npmjs.com/package/kordoc)
6
- [![license](https://img.shields.io/npm/l/kordoc.svg)](https://github.com/chrisryugj/kordoc/blob/main/LICENSE)
7
-
8
- > *대한민국에서 둘째가라면 서러울 문서지옥. 거기서 7년 버틴 공무원이 만들었습니다.*
9
-
10
- HWP, HWPX, PDF, XLSX, DOCX — 관공서에서 쏟아지는 모든 문서를 파싱하고, 비교하고, 분석하고, 생성합니다.
11
-
12
- [English](./README-EN.md)
13
-
14
- ![kordoc 데모](./demo.gif)
15
-
16
- ---
17
-
18
- ## 💡 kordoc으로 무엇을 할 수 있나요?
19
-
20
- 단순한 텍스트 추출을 넘어, **공문서 처리를 위한 모든 과정**을 자동화합니다.
21
-
22
- * **📄 어떤 문서든 마크다운으로**: `HWP`, `HWPX`, `PDF`, `XLSX`, `DOCX` 파일을 즉시 `Markdown`으로 변환합니다. AI(LLM)가 문서를 읽고 분석하기 가장 좋은 상태로 만들어줍니다.
23
- * **📊 복잡한 표(Table) 완벽 재현**: 선이 없는 PDF나 복잡하게 병합된 HWP 표도 구조를 분석하여 정확한 마크다운 테이블로 복원합니다.
24
- * **🔍 신구대조표 자동 생성**: 두 문서의 차이점을 분석하여 무엇이 바뀌었는지 한눈에 보여줍니다. (HWP와 HWPX 간의 비교도 가능!)
25
- * **📝 마크다운을 다시 HWPX로**: AI가 작성한 내용을 다시 보고서 양식(`HWPX`)으로 되돌려줍니다. 이제 복사-붙여넣기 노가다에서 해방되세요.
26
- * **🤖 AI 에이전트 연동 (MCP)**: `Claude`, `Cursor`와 같은 도구에서 직접 `kordoc`을 호출해 문서를 읽고 코딩할 수 있습니다.
27
-
28
- ---
29
-
30
- ## v2.0 변경사항
31
-
32
- - **🔓 배포용(열람 제한) HWP 파싱 지원** — 관공서에서 배포용으로 잠근 HWP 파일도 이제 파싱됩니다. AES-128 ECB 복호화, 순수 JS 구현. [rhwp](https://github.com/edwardkim/rhwp)(MIT) 알고리즘 포팅.
33
- - **손상된 HWP 파일 복구** — 표준 CFB 모듈이 거부하는 파일을 직접 FAT/디렉토리 파싱으로 복구. rhwp LenientCfbReader 포팅.
34
- - **HWP5 각주/미주/하이퍼링크 추출** — 각주 본문 텍스트 연결, 하이퍼링크 URL 추출 및 XSS 살균.
35
- - **HWPX 표 병합 밀림 수정** — colspan/rowspan 그리드 계산 버그 수정.
36
- - **보안 강화** — CFB 섹터 크기 검증, sanitizeHref 3중 경로 일관 적용.
37
-
38
- <details>
39
- <summary>v1.8.0 변경사항</summary>
40
-
41
- - **XLSX 파서 추가** — Excel 스프레드시트 파싱. 공유 문자열, 병합 셀, 다중 시트 지원. 시트별 heading + table 블록 생성.
42
- - **DOCX 파서 추가** — Word 문서 파싱. 스타일 기반 heading, 번호 매기기(리스트), 각주, 하이퍼링크, 이미지 추출, vMerge/gridSpan 테이블 병합.
43
- - **파싱 품질 대폭 개선** — PDF/HWPX/HWP5/XLSX 전 포맷 품질 점수 73→93점.
44
- - **프로덕션 리뷰 17건 수정** — CLI `--no-header-footer` 플래그 반전 버그, MCP XLSX/DOCX 확장자 허용, ZIP bomb 보호 공유 유틸화, href XSS 살균 강화, PDF timeout 타이머 정리, HWP5 BinData O(n) 최적화, cluster indexOf O(n²)→O(n), SSRF IPv6 차단 등.
45
-
46
- </details>
47
-
48
- <details>
49
- <summary>v1.7.x 변경사항</summary>
50
-
51
- - **이미지 추출 (HWP/HWPX)** — ZIP 엔트리와 HWP5 BinData 스트림에서 바이너리 이미지 추출.
52
- - **부분 파싱 (Graceful Degradation)** — 개별 페이지 실패가 전체 파싱을 중단하지 않음.
53
- - **진행률 콜백** — `onProgress` 콜백. CLI에서 `[3/15 pages]` 형태 표시.
54
- - **파일 경로 직접 입력** — `parse("path/to/file.hwp")` 문자열 오버로드.
55
- - **PDF 머리글/바닥글 필터링** — `removeHeaderFooter` 옵션.
56
- - **보안 강화** — ZIP bomb 추적, SSRF 방지, XSS 방어, 널바이트 감지, PDF 타임아웃.
57
- - **pdfjs-dist v5 호환** — constructPath 연산자 형식 변경 대응.
58
-
59
- </details>
60
-
61
- <details>
62
- <summary>v1.6.1 수정사항</summary>
63
-
64
- - **HWP5 테이블 셀 오프셋 수정** — LIST_HEADER 파싱 시 2바이트 오프셋 밀림으로 rowAddr를 colSpan으로 잘못 읽던 치명적 버그 수정. 3열 테이블이 6열로 뻥튀기되던 문제 해결. colAddr/rowAddr 기반 직접 배치로 병합 테이블 정확도 향상.
65
- - **HWP5 TAB 제어문자 수정** — TAB(0x0009) 인라인 컨트롤의 14바이트 확장 데이터 스킵 누락으로 `࣐Ā` 쓰레기 문자가 출력되던 버그 수정.
66
-
67
- </details>
68
-
69
- <details>
70
- <summary>v1.6.0 기능</summary>
71
-
72
- - **클러스터 기반 테이블 감지 (PDF)** — 선 없는 PDF에서 텍스트 정렬 패턴으로 테이블 구조 추론. baseline 그룹핑 + X좌표 클러스터링으로 2열 이상 테이블 감지. 선 기반 감지가 실패한 경우의 중간 계층 fallback.
73
- - **한국어 특수 테이블 감지** — `구분/항목/종류/기준` 등 한국 공문서 key-value 패턴을 자동으로 2열 테이블로 변환.
74
- - **한국어 어절 끊김 복원** — PDF 셀 내 한글 문자별 렌더링으로 인한 미세 갭 처리 개선. 셀 줄바꿈 병합 임계값 8자로 확장, 1글자 조사 자동 연결.
75
- - **빈 테이블 필터링** — 장식용 선에서 생긴 빈 테이블 자동 제거.
76
-
77
- </details>
78
-
79
- <details>
80
- <summary>v1.5.0 기능</summary>
81
-
82
- - **선 기반 테이블 감지 (PDF)** — OpenDataLoader 핵심 알고리즘 포팅. PDF 그래픽 명령에서 수평/수직 선을 추출하고, 교차점으로 그리드 구성, bbox overlap으로 텍스트→셀 매핑. colspan/rowspan 자동 감지. 선 없는 PDF는 기존 휴리스틱 fallback.
83
- - **IRBlock v2** — 6가지 블록 타입: `heading`, `paragraph`, `table`, `list`, `image`, `separator`. 새 필드: `bbox`, `style`, `pageNumber`, `level`, `href`, `footnoteText`.
84
- - **ParseResult v2** — `outline` (문서 구조), `warnings` (스킵된 요소, 숨김 텍스트) 필드 추가.
85
- - **PDF 개선** — XY-Cut 읽기 순서, 폰트 크기 기반 헤딩 감지, hidden text 필터링 (프롬프트 인젝션 방어), 모든 블록에 바운딩 박스.
86
- - **HWP5 개선** — CHAR_SHAPE 파싱, 스타일 기반 헤딩 감지, OLE/이미지 스킵 경고.
87
- - **HWPX 개선** — header.xml 스타일 파싱, 하이퍼링크/각주 추출.
88
- - **리스트 감지** — 테이블 뒤 번호 문단을 ordered list 블록으로 자동 변환.
89
- - **MCP 서버** — parse_document 응답에 `outline`, `warnings` 포함.
90
-
91
- </details>
92
-
93
- <details>
94
- <summary>v1.4.x 기능</summary>
95
-
96
- - **문서 비교 (Diff)** — IR 레벨 블록 비교로 신구대조표 생성. HWP↔HWPX 크로스 포맷 지원.
97
- - **양식 인식** — 공문서 테이블에서 label-value 쌍 자동 추출. 성명, 소속, 전화번호 등.
98
- - **구조화 파싱** — `IRBlock[]`과 `DocumentMetadata`에 직접 접근. 마크다운 넘어선 데이터 활용.
99
- - **페이지 범위** — `parse(buffer, { pages: "1-3" })` — 필요한 페이지만 빠르게.
100
- - **Markdown → HWPX** — 역변환. AI가 생성한 내용을 바로 공문서로.
101
- - **OCR 연동** — 이미지 기반 PDF도 텍스트 추출 (Tesseract, Claude Vision 등 프로바이더 직접 제공).
102
- - **Watch 모드** — `kordoc watch ./수신함 -d ./변환결과 --webhook https://...`
103
- - **MCP 7개 도구** — parse_document, detect_format, parse_metadata, parse_pages, parse_table, compare_documents, parse_form
104
- - **에러 코드** — `"ENCRYPTED"`, `"ZIP_BOMB"`, `"IMAGE_BASED_PDF"` 등 구조화된 에러 핸들링
105
-
106
- </details>
107
-
108
- ---
109
-
110
- ## 설치
111
-
112
- ```bash
113
- npm install kordoc
114
-
115
- # PDF 파싱이 필요하면 (선택)
116
- npm install pdfjs-dist
117
- ```
118
-
119
- ## 빠른 시작
120
-
121
- ### 문서 파싱
122
-
123
- ```typescript
124
- import { parse } from "kordoc"
125
- import { readFileSync } from "fs"
126
-
127
- const buffer = readFileSync("사업계획서.hwpx")
128
- const result = await parse(buffer.buffer)
129
-
130
- if (result.success) {
131
- console.log(result.markdown) // 마크다운 텍스트
132
- console.log(result.blocks) // IRBlock[] 구조화 데이터
133
- console.log(result.metadata) // { title, author, createdAt, ... }
134
- }
135
- ```
136
-
137
- ### 문서 비교 (신구대조표)
138
-
139
- ```typescript
140
- import { compare } from "kordoc"
141
-
142
- const diff = await compare(구버전Buffer, 신버전Buffer)
143
- // diff.stats → { added: 3, removed: 1, modified: 5, unchanged: 42 }
144
- // diff.diffs → BlockDiff[] (테이블은 셀 단위 diff 포함)
145
- ```
146
-
147
- HWP vs HWPX 크로스 포맷 비교도 가능합니다.
148
-
149
- ### 양식 필드 추출
150
-
151
- ```typescript
152
- import { parse, extractFormFields } from "kordoc"
153
-
154
- const result = await parse(buffer)
155
- if (result.success) {
156
- const form = extractFormFields(result.blocks)
157
- // form.fields → [{ label: "성명", value: "홍길동", row: 0, col: 0 }, ...]
158
- // form.confidence → 0.85
159
- }
160
- ```
161
-
162
- ### HWPX 생성 (역변환)
163
-
164
- ```typescript
165
- import { markdownToHwpx } from "kordoc"
166
-
167
- const hwpxBuffer = await markdownToHwpx("# 제목\n\n본문 텍스트\n\n| 이름 | 직급 |\n| --- | --- |\n| 홍길동 | 과장 |")
168
- writeFileSync("출력.hwpx", Buffer.from(hwpxBuffer))
169
- ```
170
-
171
- ### 페이지 범위 지정
172
-
173
- ```typescript
174
- const result = await parse(buffer, { pages: "1-3" }) // 1~3 페이지만
175
- const result = await parse(buffer, { pages: [1, 5, 10] }) // 특정 페이지
176
- ```
177
-
178
- ### OCR (이미지 PDF)
179
-
180
- ```typescript
181
- const result = await parse(buffer, {
182
- ocr: async (pageImage, pageNumber, mimeType) => {
183
- return await myOcrService.recognize(pageImage)
184
- }
185
- })
186
- ```
187
-
188
- ## CLI
189
-
190
- ```bash
191
- npx kordoc 사업계획서.hwpx # 터미널 출력
192
- npx kordoc 보고서.hwp -o 보고서.md # 파일 저장
193
- npx kordoc *.pdf -d ./변환결과/ # 일괄 변환
194
- npx kordoc 검토서.hwpx --format json # JSON (blocks + metadata 포함)
195
- npx kordoc 보고서.hwpx --pages 1-3 # 페이지 범위
196
- npx kordoc watch ./수신함 -d ./변환결과 # 폴더 감시 모드
197
- npx kordoc watch ./문서 --webhook https://api/hook # 웹훅 알림
198
- ```
199
-
200
- ## MCP 서버 (Claude / Cursor / Windsurf)
201
-
202
- ```json
203
- {
204
- "mcpServers": {
205
- "kordoc": {
206
- "command": "npx",
207
- "args": ["-y", "kordoc-mcp"]
208
- }
209
- }
210
- }
211
- ```
212
-
213
- **7개 도구:**
214
-
215
- | 도구 | 설명 |
216
- |------|------|
217
- | `parse_document` | HWP/HWPX/PDF/XLSX/DOCX → 마크다운 (메타데이터 포함) |
218
- | `detect_format` | 매직 바이트로 포맷 감지 |
219
- | `parse_metadata` | 메타데이터만 빠르게 추출 |
220
- | `parse_pages` | 특정 페이지 범위만 파싱 |
221
- | `parse_table` | N번째 테이블만 추출 |
222
- | `compare_documents` | 두 문서 비교 (크로스 포맷) |
223
- | `parse_form` | 양식 필드를 JSON으로 추출 |
224
-
225
- ## API
226
-
227
- ### 핵심 함수
228
-
229
- | 함수 | 설명 |
230
- |------|------|
231
- | `parse(buffer, options?)` | 포맷 자동 감지 → Markdown + IRBlock[] |
232
- | `parseHwpx(buffer, options?)` | HWPX 전용 |
233
- | `parseHwp(buffer, options?)` | HWP 5.x 전용 |
234
- | `parsePdf(buffer, options?)` | PDF 전용 |
235
- | `parseXlsx(buffer, options?)` | XLSX 전용 |
236
- | `parseDocx(buffer, options?)` | DOCX 전용 |
237
- | `detectFormat(buffer)` | `"hwpx" \| "hwp" \| "pdf" \| "xlsx" \| "docx" \| "unknown"` |
238
-
239
- ### 고급 함수
240
-
241
- | 함수 | 설명 |
242
- |------|------|
243
- | `compare(bufferA, bufferB, options?)` | IR 레벨 문서 비교 |
244
- | `extractFormFields(blocks)` | IRBlock[]에서 양식 필드 인식 |
245
- | `markdownToHwpx(markdown)` | Markdown → HWPX 역변환 |
246
- | `blocksToMarkdown(blocks)` | IRBlock[] → Markdown 문자열 |
247
-
248
- ### 타입
249
-
250
- ```typescript
251
- import type {
252
- ParseResult, ParseSuccess, ParseFailure, FileType,
253
- IRBlock, IRTable, IRCell, CellContext,
254
- DocumentMetadata, ParseOptions, ErrorCode,
255
- DiffResult, BlockDiff, CellDiff, DiffChangeType,
256
- FormField, FormResult,
257
- OcrProvider, WatchOptions,
258
- } from "kordoc"
259
- ```
260
-
261
- ## 지원 포맷
262
-
263
- | 포맷 | 엔진 | 특징 |
264
- |------|------|------|
265
- | **HWPX** (한컴 2020+) | ZIP + XML DOM | 매니페스트, 중첩 테이블, 병합 셀, 손상 ZIP 복구 |
266
- | **HWP 5.x** (한컴 레거시) | OLE2 + CFB | 배포용 복호화, 손상 CFB 복구, 각주/하이퍼링크, 21종 제어문자, 이미지 추출 |
267
- | **PDF** | pdfjs-dist | 선 기반 테이블, XY-Cut 읽기 순서, 헤딩 감지, OCR |
268
- | **XLSX** (Excel) | ZIP + XML DOM | 공유 문자열, 병합 셀, 다중 시트, 수식 표시 |
269
- | **DOCX** (Word) | ZIP + XML DOM | 스타일 heading, 번호 매기기, 각주, 이미지 추출 |
270
-
271
- ## 보안
272
-
273
- 프로덕션급 보안 강화: ZIP bomb 방지, XXE/Billion Laughs 방지, 압축 폭탄 방지, 경로 순회 차단, MCP 에러 정제, 파일 크기 제한(500MB). 자세한 내용은 [SECURITY.md](./SECURITY.md) 참조.
274
-
275
- ## 만든 사람
276
-
277
- 대한민국 지방공무원. 광진구청에서 7년간 HWP 파일과 싸우다가 이걸 만들었습니다.
278
- 5개 공공 프로젝트에서 수천 건의 실제 관공서 문서를 파싱하며 검증했습니다.
279
-
280
- ## 라이선스
281
-
282
- [MIT](./LICENSE)
283
-
284
- 이 프로젝트는 아래 오픈소스를 포함합니다:
285
- - **rhwp** (MIT, edwardkim) — HWP5 배포용 복호화 및 lenient CFB 파싱 알고리즘
286
- - **OpenDataLoader PDF** (Apache 2.0, Hancom Inc.) — PDF 테이블 감지 알고리즘
287
- - **cfb** (Apache 2.0, SheetJS) — HWP5 OLE2 컨테이너 파싱
288
- - **pdfjs-dist** (Apache 2.0, Mozilla) — PDF 텍스트 추출
289
- - **JSZip** (MIT, Stuart Knightley 외) — ZIP 기반 포맷 파싱
290
-
291
- 자세한 내용은 [NOTICE](./NOTICE) 파일을 참조하세요.
1
+ # kordoc
2
+
3
+ **모두 파싱해버리겠다.**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/kordoc.svg)](https://www.npmjs.com/package/kordoc)
6
+ [![license](https://img.shields.io/npm/l/kordoc.svg)](https://github.com/chrisryugj/kordoc/blob/main/LICENSE)
7
+
8
+ > *대한민국에서 둘째가라면 서러울 문서지옥. 거기서 7년 버틴 공무원이 만들었습니다.*
9
+
10
+ HWP, HWPX, PDF, XLSX, DOCX — 관공서에서 쏟아지는 모든 문서를 파싱하고, 비교하고, 분석하고, 생성합니다.
11
+
12
+ [English](./README-EN.md)
13
+
14
+ ![kordoc 데모](./demo.gif)
15
+
16
+ ---
17
+
18
+ ## 💡 kordoc으로 무엇을 할 수 있나요?
19
+
20
+ 단순한 텍스트 추출을 넘어, **공문서 처리를 위한 모든 과정**을 자동화합니다.
21
+
22
+ * **📄 어떤 문서든 마크다운으로**: `HWP`, `HWPX`, `PDF`, `XLSX`, `DOCX` 파일을 즉시 `Markdown`으로 변환합니다. AI(LLM)가 문서를 읽고 분석하기 가장 좋은 상태로 만들어줍니다.
23
+ * **📊 복잡한 표(Table) 완벽 재현**: 선이 없는 PDF나 복잡하게 병합된 HWP 표도 구조를 분석하여 정확한 마크다운 테이블로 복원합니다.
24
+ * **🔍 신구대조표 자동 생성**: 두 문서의 차이점을 분석하여 무엇이 바뀌었는지 한눈에 보여줍니다. (HWP와 HWPX 간의 비교도 가능!)
25
+ * **📝 마크다운을 다시 HWPX로**: AI가 작성한 내용을 다시 보고서 양식(`HWPX`)으로 되돌려줍니다. 이제 복사-붙여넣기 노가다에서 해방되세요.
26
+ * **🤖 AI 에이전트 연동 (MCP)**: `Claude`, `Cursor`와 같은 도구에서 직접 `kordoc`을 호출해 문서를 읽고 코딩할 수 있습니다.
27
+
28
+ ---
29
+
30
+ ## v2.0 변경사항
31
+
32
+ - **🔓 배포용(열람 제한) HWP 파싱 지원** — 관공서에서 배포용으로 잠근 HWP 파일도 이제 파싱됩니다. AES-128 ECB 복호화, 순수 JS 구현. [rhwp](https://github.com/edwardkim/rhwp)(MIT) 알고리즘 포팅.
33
+ - **손상된 HWP 파일 복구** — 표준 CFB 모듈이 거부하는 파일을 직접 FAT/디렉토리 파싱으로 복구. rhwp LenientCfbReader 포팅.
34
+ - **HWP5 각주/미주/하이퍼링크 추출** — 각주 본문 텍스트 연결, 하이퍼링크 URL 추출 및 XSS 살균.
35
+ - **HWPX 표 병합 밀림 수정** — colspan/rowspan 그리드 계산 버그 수정.
36
+ - **보안 강화** — CFB 섹터 크기 검증, sanitizeHref 3중 경로 일관 적용.
37
+
38
+ <details>
39
+ <summary>v1.8.0 변경사항</summary>
40
+
41
+ - **XLSX 파서 추가** — Excel 스프레드시트 파싱. 공유 문자열, 병합 셀, 다중 시트 지원. 시트별 heading + table 블록 생성.
42
+ - **DOCX 파서 추가** — Word 문서 파싱. 스타일 기반 heading, 번호 매기기(리스트), 각주, 하이퍼링크, 이미지 추출, vMerge/gridSpan 테이블 병합.
43
+ - **파싱 품질 대폭 개선** — PDF/HWPX/HWP5/XLSX 전 포맷 품질 점수 73→93점.
44
+ - **프로덕션 리뷰 17건 수정** — CLI `--no-header-footer` 플래그 반전 버그, MCP XLSX/DOCX 확장자 허용, ZIP bomb 보호 공유 유틸화, href XSS 살균 강화, PDF timeout 타이머 정리, HWP5 BinData O(n) 최적화, cluster indexOf O(n²)→O(n), SSRF IPv6 차단 등.
45
+
46
+ </details>
47
+
48
+ <details>
49
+ <summary>v1.7.x 변경사항</summary>
50
+
51
+ - **이미지 추출 (HWP/HWPX)** — ZIP 엔트리와 HWP5 BinData 스트림에서 바이너리 이미지 추출.
52
+ - **부분 파싱 (Graceful Degradation)** — 개별 페이지 실패가 전체 파싱을 중단하지 않음.
53
+ - **진행률 콜백** — `onProgress` 콜백. CLI에서 `[3/15 pages]` 형태 표시.
54
+ - **파일 경로 직접 입력** — `parse("path/to/file.hwp")` 문자열 오버로드.
55
+ - **PDF 머리글/바닥글 필터링** — `removeHeaderFooter` 옵션.
56
+ - **보안 강화** — ZIP bomb 추적, SSRF 방지, XSS 방어, 널바이트 감지, PDF 타임아웃.
57
+ - **pdfjs-dist v5 호환** — constructPath 연산자 형식 변경 대응.
58
+
59
+ </details>
60
+
61
+ <details>
62
+ <summary>v1.6.1 수정사항</summary>
63
+
64
+ - **HWP5 테이블 셀 오프셋 수정** — LIST_HEADER 파싱 시 2바이트 오프셋 밀림으로 rowAddr를 colSpan으로 잘못 읽던 치명적 버그 수정. 3열 테이블이 6열로 뻥튀기되던 문제 해결. colAddr/rowAddr 기반 직접 배치로 병합 테이블 정확도 향상.
65
+ - **HWP5 TAB 제어문자 수정** — TAB(0x0009) 인라인 컨트롤의 14바이트 확장 데이터 스킵 누락으로 `࣐Ā` 쓰레기 문자가 출력되던 버그 수정.
66
+
67
+ </details>
68
+
69
+ <details>
70
+ <summary>v1.6.0 기능</summary>
71
+
72
+ - **클러스터 기반 테이블 감지 (PDF)** — 선 없는 PDF에서 텍스트 정렬 패턴으로 테이블 구조 추론. baseline 그룹핑 + X좌표 클러스터링으로 2열 이상 테이블 감지. 선 기반 감지가 실패한 경우의 중간 계층 fallback.
73
+ - **한국어 특수 테이블 감지** — `구분/항목/종류/기준` 등 한국 공문서 key-value 패턴을 자동으로 2열 테이블로 변환.
74
+ - **한국어 어절 끊김 복원** — PDF 셀 내 한글 문자별 렌더링으로 인한 미세 갭 처리 개선. 셀 줄바꿈 병합 임계값 8자로 확장, 1글자 조사 자동 연결.
75
+ - **빈 테이블 필터링** — 장식용 선에서 생긴 빈 테이블 자동 제거.
76
+
77
+ </details>
78
+
79
+ <details>
80
+ <summary>v1.5.0 기능</summary>
81
+
82
+ - **선 기반 테이블 감지 (PDF)** — OpenDataLoader 핵심 알고리즘 포팅. PDF 그래픽 명령에서 수평/수직 선을 추출하고, 교차점으로 그리드 구성, bbox overlap으로 텍스트→셀 매핑. colspan/rowspan 자동 감지. 선 없는 PDF는 기존 휴리스틱 fallback.
83
+ - **IRBlock v2** — 6가지 블록 타입: `heading`, `paragraph`, `table`, `list`, `image`, `separator`. 새 필드: `bbox`, `style`, `pageNumber`, `level`, `href`, `footnoteText`.
84
+ - **ParseResult v2** — `outline` (문서 구조), `warnings` (스킵된 요소, 숨김 텍스트) 필드 추가.
85
+ - **PDF 개선** — XY-Cut 읽기 순서, 폰트 크기 기반 헤딩 감지, hidden text 필터링 (프롬프트 인젝션 방어), 모든 블록에 바운딩 박스.
86
+ - **HWP5 개선** — CHAR_SHAPE 파싱, 스타일 기반 헤딩 감지, OLE/이미지 스킵 경고.
87
+ - **HWPX 개선** — header.xml 스타일 파싱, 하이퍼링크/각주 추출.
88
+ - **리스트 감지** — 테이블 뒤 번호 문단을 ordered list 블록으로 자동 변환.
89
+ - **MCP 서버** — parse_document 응답에 `outline`, `warnings` 포함.
90
+
91
+ </details>
92
+
93
+ <details>
94
+ <summary>v1.4.x 기능</summary>
95
+
96
+ - **문서 비교 (Diff)** — IR 레벨 블록 비교로 신구대조표 생성. HWP↔HWPX 크로스 포맷 지원.
97
+ - **양식 인식** — 공문서 테이블에서 label-value 쌍 자동 추출. 성명, 소속, 전화번호 등.
98
+ - **구조화 파싱** — `IRBlock[]`과 `DocumentMetadata`에 직접 접근. 마크다운 넘어선 데이터 활용.
99
+ - **페이지 범위** — `parse(buffer, { pages: "1-3" })` — 필요한 페이지만 빠르게.
100
+ - **Markdown → HWPX** — 역변환. AI가 생성한 내용을 바로 공문서로.
101
+ - **OCR 연동** — 이미지 기반 PDF도 텍스트 추출 (Tesseract, Claude Vision 등 프로바이더 직접 제공).
102
+ - **Watch 모드** — `kordoc watch ./수신함 -d ./변환결과 --webhook https://...`
103
+ - **MCP 7개 도구** — parse_document, detect_format, parse_metadata, parse_pages, parse_table, compare_documents, parse_form
104
+ - **에러 코드** — `"ENCRYPTED"`, `"ZIP_BOMB"`, `"IMAGE_BASED_PDF"` 등 구조화된 에러 핸들링
105
+
106
+ </details>
107
+
108
+ ---
109
+
110
+ ## 설치
111
+
112
+ ```bash
113
+ npm install kordoc
114
+
115
+ # PDF 파싱이 필요하면 (선택)
116
+ npm install pdfjs-dist
117
+ ```
118
+
119
+ ## 빠른 시작
120
+
121
+ ### 문서 파싱
122
+
123
+ ```typescript
124
+ import { parse } from "kordoc"
125
+ import { readFileSync } from "fs"
126
+
127
+ const buffer = readFileSync("사업계획서.hwpx")
128
+ const result = await parse(buffer.buffer)
129
+
130
+ if (result.success) {
131
+ console.log(result.markdown) // 마크다운 텍스트
132
+ console.log(result.blocks) // IRBlock[] 구조화 데이터
133
+ console.log(result.metadata) // { title, author, createdAt, ... }
134
+ }
135
+ ```
136
+
137
+ ### 문서 비교 (신구대조표)
138
+
139
+ ```typescript
140
+ import { compare } from "kordoc"
141
+
142
+ const diff = await compare(구버전Buffer, 신버전Buffer)
143
+ // diff.stats → { added: 3, removed: 1, modified: 5, unchanged: 42 }
144
+ // diff.diffs → BlockDiff[] (테이블은 셀 단위 diff 포함)
145
+ ```
146
+
147
+ HWP vs HWPX 크로스 포맷 비교도 가능합니다.
148
+
149
+ ### 양식 필드 추출
150
+
151
+ ```typescript
152
+ import { parse, extractFormFields } from "kordoc"
153
+
154
+ const result = await parse(buffer)
155
+ if (result.success) {
156
+ const form = extractFormFields(result.blocks)
157
+ // form.fields → [{ label: "성명", value: "홍길동", row: 0, col: 0 }, ...]
158
+ // form.confidence → 0.85
159
+ }
160
+ ```
161
+
162
+ ### HWPX 생성 (역변환)
163
+
164
+ ```typescript
165
+ import { markdownToHwpx } from "kordoc"
166
+
167
+ const hwpxBuffer = await markdownToHwpx("# 제목\n\n본문 텍스트\n\n| 이름 | 직급 |\n| --- | --- |\n| 홍길동 | 과장 |")
168
+ writeFileSync("출력.hwpx", Buffer.from(hwpxBuffer))
169
+ ```
170
+
171
+ ### 페이지 범위 지정
172
+
173
+ ```typescript
174
+ const result = await parse(buffer, { pages: "1-3" }) // 1~3 페이지만
175
+ const result = await parse(buffer, { pages: [1, 5, 10] }) // 특정 페이지
176
+ ```
177
+
178
+ ### OCR (이미지 PDF)
179
+
180
+ ```typescript
181
+ const result = await parse(buffer, {
182
+ ocr: async (pageImage, pageNumber, mimeType) => {
183
+ return await myOcrService.recognize(pageImage)
184
+ }
185
+ })
186
+ ```
187
+
188
+ ## CLI
189
+
190
+ ```bash
191
+ npx kordoc 사업계획서.hwpx # 터미널 출력
192
+ npx kordoc 보고서.hwp -o 보고서.md # 파일 저장
193
+ npx kordoc *.pdf -d ./변환결과/ # 일괄 변환
194
+ npx kordoc 검토서.hwpx --format json # JSON (blocks + metadata 포함)
195
+ npx kordoc 보고서.hwpx --pages 1-3 # 페이지 범위
196
+ npx kordoc watch ./수신함 -d ./변환결과 # 폴더 감시 모드
197
+ npx kordoc watch ./문서 --webhook https://api/hook # 웹훅 알림
198
+ ```
199
+
200
+ ## MCP 서버 (Claude / Cursor / Windsurf)
201
+
202
+ ```json
203
+ {
204
+ "mcpServers": {
205
+ "kordoc": {
206
+ "command": "npx",
207
+ "args": ["-y", "kordoc-mcp"]
208
+ }
209
+ }
210
+ }
211
+ ```
212
+
213
+ **7개 도구:**
214
+
215
+ | 도구 | 설명 |
216
+ |------|------|
217
+ | `parse_document` | HWP/HWPX/PDF/XLSX/DOCX → 마크다운 (메타데이터 포함) |
218
+ | `detect_format` | 매직 바이트로 포맷 감지 |
219
+ | `parse_metadata` | 메타데이터만 빠르게 추출 |
220
+ | `parse_pages` | 특정 페이지 범위만 파싱 |
221
+ | `parse_table` | N번째 테이블만 추출 |
222
+ | `compare_documents` | 두 문서 비교 (크로스 포맷) |
223
+ | `parse_form` | 양식 필드를 JSON으로 추출 |
224
+
225
+ ## API
226
+
227
+ ### 핵심 함수
228
+
229
+ | 함수 | 설명 |
230
+ |------|------|
231
+ | `parse(buffer, options?)` | 포맷 자동 감지 → Markdown + IRBlock[] |
232
+ | `parseHwpx(buffer, options?)` | HWPX 전용 |
233
+ | `parseHwp(buffer, options?)` | HWP 5.x 전용 |
234
+ | `parsePdf(buffer, options?)` | PDF 전용 |
235
+ | `parseXlsx(buffer, options?)` | XLSX 전용 |
236
+ | `parseDocx(buffer, options?)` | DOCX 전용 |
237
+ | `detectFormat(buffer)` | `"hwpx" \| "hwp" \| "pdf" \| "xlsx" \| "docx" \| "unknown"` |
238
+
239
+ ### 고급 함수
240
+
241
+ | 함수 | 설명 |
242
+ |------|------|
243
+ | `compare(bufferA, bufferB, options?)` | IR 레벨 문서 비교 |
244
+ | `extractFormFields(blocks)` | IRBlock[]에서 양식 필드 인식 |
245
+ | `markdownToHwpx(markdown)` | Markdown → HWPX 역변환 |
246
+ | `blocksToMarkdown(blocks)` | IRBlock[] → Markdown 문자열 |
247
+
248
+ ### 타입
249
+
250
+ ```typescript
251
+ import type {
252
+ ParseResult, ParseSuccess, ParseFailure, FileType,
253
+ IRBlock, IRTable, IRCell, CellContext,
254
+ DocumentMetadata, ParseOptions, ErrorCode,
255
+ DiffResult, BlockDiff, CellDiff, DiffChangeType,
256
+ FormField, FormResult,
257
+ OcrProvider, WatchOptions,
258
+ } from "kordoc"
259
+ ```
260
+
261
+ ## 지원 포맷
262
+
263
+ | 포맷 | 엔진 | 특징 |
264
+ |------|------|------|
265
+ | **HWPX** (한컴 2020+) | ZIP + XML DOM | 매니페스트, 중첩 테이블, 병합 셀, 손상 ZIP 복구 |
266
+ | **HWP 5.x** (한컴 레거시) | OLE2 + CFB | 배포용 복호화, 손상 CFB 복구, 각주/하이퍼링크, 21종 제어문자, 이미지 추출 |
267
+ | **PDF** | pdfjs-dist | 선 기반 테이블, XY-Cut 읽기 순서, 헤딩 감지, OCR |
268
+ | **XLSX** (Excel) | ZIP + XML DOM | 공유 문자열, 병합 셀, 다중 시트, 수식 표시 |
269
+ | **DOCX** (Word) | ZIP + XML DOM | 스타일 heading, 번호 매기기, 각주, 이미지 추출 |
270
+
271
+ ## 보안
272
+
273
+ 프로덕션급 보안 강화: ZIP bomb 방지, XXE/Billion Laughs 방지, 압축 폭탄 방지, 경로 순회 차단, MCP 에러 정제, 파일 크기 제한(500MB). 자세한 내용은 [SECURITY.md](./SECURITY.md) 참조.
274
+
275
+ ## 만든 사람
276
+
277
+ 대한민국 지방공무원. 광진구청에서 7년간 HWP 파일과 싸우다가 이걸 만들었습니다.
278
+ 5개 공공 프로젝트에서 수천 건의 실제 관공서 문서를 파싱하며 검증했습니다.
279
+
280
+ ## 라이선스
281
+
282
+ [MIT](./LICENSE)
283
+
284
+ 이 프로젝트는 아래 오픈소스를 포함합니다:
285
+ - **rhwp** (MIT, edwardkim) — HWP5 배포용 복호화 및 lenient CFB 파싱 알고리즘
286
+ - **OpenDataLoader PDF** (Apache 2.0, Hancom Inc.) — PDF 테이블 감지 알고리즘
287
+ - **cfb** (Apache 2.0, SheetJS) — HWP5 OLE2 컨테이너 파싱
288
+ - **pdfjs-dist** (Apache 2.0, Mozilla) — PDF 텍스트 추출
289
+ - **JSZip** (MIT, Stuart Knightley 외) — ZIP 기반 포맷 파싱
290
+
291
+ 자세한 내용은 [NOTICE](./NOTICE) 파일을 참조하세요.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/utils.ts
4
- var VERSION = true ? "2.0.2" : "0.0.0-dev";
4
+ var VERSION = true ? "2.0.3" : "0.0.0-dev";
5
5
  function toArrayBuffer(buf) {
6
6
  if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
7
7
  return buf.buffer;
@@ -90,4 +90,4 @@ export {
90
90
  sanitizeHref,
91
91
  classifyError
92
92
  };
93
- //# sourceMappingURL=chunk-EVWOJ4T5.js.map
93
+ //# sourceMappingURL=chunk-25TXW6EP.js.map