kordoc 4.24.9 → 4.24.10
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 +5 -5
- package/dist/{-6LXREJIR.js → -H7GN7FIS.js} +11 -11
- package/dist/{chunk-NDC4AGLX.js → chunk-37JRATLZ.js} +100 -13
- package/dist/chunk-37JRATLZ.js.map +1 -0
- package/dist/{chunk-C6QK3PY2.js → chunk-3BRGHU2F.js} +2 -2
- package/dist/{chunk-C6QK3PY2.js.map → chunk-3BRGHU2F.js.map} +1 -1
- package/dist/{chunk-ESSLFMY3.js → chunk-4AKR7LBP.js} +6 -6
- package/dist/{chunk-BEPBXIKP.js → chunk-4TAOUMLJ.js} +2 -2
- package/dist/{chunk-W6R7HH2Q.js → chunk-ALCD3FB7.js} +2 -2
- package/dist/{chunk-SQCECEOH.js → chunk-CZGAGILH.js} +101 -14
- package/dist/chunk-CZGAGILH.js.map +1 -0
- package/dist/{chunk-SB4VN4TR.js → chunk-ENQWDN6M.js} +21 -7
- package/dist/chunk-ENQWDN6M.js.map +1 -0
- package/dist/{chunk-LVEY2XHM.js → chunk-HFNNRSAJ.js} +21 -7
- package/dist/chunk-HFNNRSAJ.js.map +1 -0
- package/dist/{chunk-ZFM7UP72.cjs → chunk-IV4ZRFHF.cjs} +82 -68
- package/dist/chunk-IV4ZRFHF.cjs.map +1 -0
- package/dist/{chunk-UVMVLE3M.cjs → chunk-JH3AA5TY.cjs} +3 -3
- package/dist/{chunk-UVMVLE3M.cjs.map → chunk-JH3AA5TY.cjs.map} +1 -1
- package/dist/{chunk-DF3YCAK6.js → chunk-LLKLJ2JF.js} +2 -2
- package/dist/{chunk-DF3YCAK6.js.map → chunk-LLKLJ2JF.js.map} +1 -1
- package/dist/{chunk-7NEBICPS.js → chunk-LMG7Y3TN.js} +2 -2
- package/dist/{chunk-WPA45TPL.js → chunk-NFJN75Y2.js} +2 -2
- package/dist/{chunk-YAKEEIR2.js → chunk-OZTG6NCW.js} +2 -2
- package/dist/{chunk-TO4T2M7R.js → chunk-PB6EOWE4.js} +3 -3
- package/dist/{chunk-O34AXZ4G.js → chunk-PDPHUGVP.js} +2 -2
- package/dist/{chunk-TY4PED6S.js → chunk-PSQJYUJC.js} +2 -2
- package/dist/{chunk-NSCYUL4P.cjs → chunk-QAHWMIBF.cjs} +2 -2
- package/dist/{chunk-NSCYUL4P.cjs.map → chunk-QAHWMIBF.cjs.map} +1 -1
- package/dist/{chunk-GINSLCL7.js → chunk-RNDG6RQU.js} +2 -2
- package/dist/{chunk-2A54AIAG.js → chunk-S4HE5OH5.js} +2 -2
- package/dist/{chunk-D5S5S6OP.js → chunk-TT6UHEDY.js} +2 -2
- package/dist/{chunk-VAR3NCSE.js → chunk-UK3CENY6.js} +11 -11
- package/dist/{chunk-A4TUSLGL.js → chunk-VAYHMKSC.js} +2 -2
- package/dist/{chunk-2WWQ6NU5.cjs → chunk-WKN5YUMP.cjs} +3 -3
- package/dist/{chunk-2WWQ6NU5.cjs.map → chunk-WKN5YUMP.cjs.map} +1 -1
- package/dist/{chunk-MSPBBDR5.js → chunk-WZWJCMM3.js} +2 -2
- package/dist/{chunk-TMHPNZ37.cjs → chunk-X5BFTWCB.cjs} +122 -35
- package/dist/chunk-X5BFTWCB.cjs.map +1 -0
- package/dist/{chunk-4BPHV36H.cjs → chunk-XFM4SX74.cjs} +6 -6
- package/dist/{chunk-4BPHV36H.cjs.map → chunk-XFM4SX74.cjs.map} +1 -1
- package/dist/{chunk-EF4MEYFE.js → chunk-XMAOBI35.js} +3 -3
- package/dist/{chunk-R3DNJRDD.js → chunk-YAKLWOT2.js} +2 -2
- package/dist/chunks-CMSL2XXG.js +10 -0
- package/dist/cli.js +30 -30
- package/dist/{formula-S7CTLTGZ.js → formula-P5VHY4YS.js} +3 -3
- package/dist/{formula-3SARACGW.cjs → formula-TBG6BYE2.cjs} +9 -9
- package/dist/{formula-3SARACGW.cjs.map → formula-TBG6BYE2.cjs.map} +1 -1
- package/dist/{formula-MDHYCNKI.js → formula-YCZOVUJU.js} +4 -4
- package/dist/{image-ocr-V6AQ4IAY.js → image-ocr-2UD6RWE6.js} +6 -6
- package/dist/{image-ocr-VDMEI7TD.js → image-ocr-3QCUKBTE.js} +9 -9
- package/dist/{image-ocr-2T4NBJ73.cjs → image-ocr-J6EWIQ73.cjs} +17 -17
- package/dist/{image-ocr-2T4NBJ73.cjs.map → image-ocr-J6EWIQ73.cjs.map} +1 -1
- package/dist/index.cjs +340 -340
- package/dist/index.js +6 -6
- package/dist/mcp.js +23 -23
- package/dist/{model-bundle-HCTCHMA2.js → model-bundle-EFAOVVYU.js} +5 -5
- package/dist/{models-NJROM7JD.js → models-SJXAHLSA.js} +5 -5
- package/dist/{parse-worker-v2-ALTGW2J3.js → parse-worker-v2-ZSSOTZVE.js} +12 -12
- package/dist/{parser-MY4WE64G.js → parser-3XHPJKL7.js} +11 -10
- package/dist/parser-3XHPJKL7.js.map +1 -0
- package/dist/{parser-6J5HFER5.js → parser-4I4MM5AJ.js} +14 -13
- package/dist/parser-4I4MM5AJ.js.map +1 -0
- package/dist/{parser-L3G6ON4U.cjs → parser-4MXHN43N.cjs} +161 -160
- package/dist/parser-4MXHN43N.cjs.map +1 -0
- package/dist/{pdf-ocr-HUSU2XMV.js → pdf-ocr-J6GXPLZJ.js} +6 -6
- package/dist/pdf-ocr-JPLZOU23.cjs +31 -0
- package/dist/{pdf-ocr-RF2SCGXD.cjs.map → pdf-ocr-JPLZOU23.cjs.map} +1 -1
- package/dist/{pdf-ocr-3VVSR4LN.js → pdf-ocr-QXZIMPQI.js} +9 -9
- package/dist/{profile-io-SQI3X7MD.js → profile-io-X7ZMPA7T.js} +3 -3
- package/dist/{rasterize-BHW5UZY2.js → rasterize-42GMMS3L.js} +3 -3
- package/dist/{redact-doc-KJ6M63BP.js → redact-doc-WCNALJSX.js} +11 -11
- package/dist/{render-Z6N2GGKL.js → render-2SSXV7MR.js} +7 -7
- package/dist/seal-ENUBZ7ZX.js +10 -0
- package/dist/{setup-MUBZ674O.js → setup-VY5MAK7O.js} +3 -3
- package/dist/visual-ON76FHWH.js +21 -0
- package/dist/{watch-D4AUDKVN.js → watch-JLCOQOAL.js} +12 -12
- package/package.json +1 -1
- package/dist/chunk-LVEY2XHM.js.map +0 -1
- package/dist/chunk-NDC4AGLX.js.map +0 -1
- package/dist/chunk-SB4VN4TR.js.map +0 -1
- package/dist/chunk-SQCECEOH.js.map +0 -1
- package/dist/chunk-TMHPNZ37.cjs.map +0 -1
- package/dist/chunk-ZFM7UP72.cjs.map +0 -1
- package/dist/chunks-L66VMJHU.js +0 -10
- package/dist/parser-6J5HFER5.js.map +0 -1
- package/dist/parser-L3G6ON4U.cjs.map +0 -1
- package/dist/parser-MY4WE64G.js.map +0 -1
- package/dist/pdf-ocr-RF2SCGXD.cjs +0 -31
- package/dist/seal-PM4624BB.js +0 -10
- package/dist/visual-AV46N5ZN.js +0 -21
- /package/dist/{-6LXREJIR.js.map → -H7GN7FIS.js.map} +0 -0
- /package/dist/{chunk-ESSLFMY3.js.map → chunk-4AKR7LBP.js.map} +0 -0
- /package/dist/{chunk-BEPBXIKP.js.map → chunk-4TAOUMLJ.js.map} +0 -0
- /package/dist/{chunk-W6R7HH2Q.js.map → chunk-ALCD3FB7.js.map} +0 -0
- /package/dist/{chunk-7NEBICPS.js.map → chunk-LMG7Y3TN.js.map} +0 -0
- /package/dist/{chunk-WPA45TPL.js.map → chunk-NFJN75Y2.js.map} +0 -0
- /package/dist/{chunk-YAKEEIR2.js.map → chunk-OZTG6NCW.js.map} +0 -0
- /package/dist/{chunk-TO4T2M7R.js.map → chunk-PB6EOWE4.js.map} +0 -0
- /package/dist/{chunk-O34AXZ4G.js.map → chunk-PDPHUGVP.js.map} +0 -0
- /package/dist/{chunk-TY4PED6S.js.map → chunk-PSQJYUJC.js.map} +0 -0
- /package/dist/{chunk-GINSLCL7.js.map → chunk-RNDG6RQU.js.map} +0 -0
- /package/dist/{chunk-2A54AIAG.js.map → chunk-S4HE5OH5.js.map} +0 -0
- /package/dist/{chunk-D5S5S6OP.js.map → chunk-TT6UHEDY.js.map} +0 -0
- /package/dist/{chunk-VAR3NCSE.js.map → chunk-UK3CENY6.js.map} +0 -0
- /package/dist/{chunk-A4TUSLGL.js.map → chunk-VAYHMKSC.js.map} +0 -0
- /package/dist/{chunk-MSPBBDR5.js.map → chunk-WZWJCMM3.js.map} +0 -0
- /package/dist/{chunk-EF4MEYFE.js.map → chunk-XMAOBI35.js.map} +0 -0
- /package/dist/{chunk-R3DNJRDD.js.map → chunk-YAKLWOT2.js.map} +0 -0
- /package/dist/{chunks-L66VMJHU.js.map → chunks-CMSL2XXG.js.map} +0 -0
- /package/dist/{formula-S7CTLTGZ.js.map → formula-P5VHY4YS.js.map} +0 -0
- /package/dist/{formula-MDHYCNKI.js.map → formula-YCZOVUJU.js.map} +0 -0
- /package/dist/{image-ocr-V6AQ4IAY.js.map → image-ocr-2UD6RWE6.js.map} +0 -0
- /package/dist/{image-ocr-VDMEI7TD.js.map → image-ocr-3QCUKBTE.js.map} +0 -0
- /package/dist/{model-bundle-HCTCHMA2.js.map → model-bundle-EFAOVVYU.js.map} +0 -0
- /package/dist/{models-NJROM7JD.js.map → models-SJXAHLSA.js.map} +0 -0
- /package/dist/{parse-worker-v2-ALTGW2J3.js.map → parse-worker-v2-ZSSOTZVE.js.map} +0 -0
- /package/dist/{pdf-ocr-3VVSR4LN.js.map → pdf-ocr-J6GXPLZJ.js.map} +0 -0
- /package/dist/{pdf-ocr-HUSU2XMV.js.map → pdf-ocr-QXZIMPQI.js.map} +0 -0
- /package/dist/{profile-io-SQI3X7MD.js.map → profile-io-X7ZMPA7T.js.map} +0 -0
- /package/dist/{rasterize-BHW5UZY2.js.map → rasterize-42GMMS3L.js.map} +0 -0
- /package/dist/{redact-doc-KJ6M63BP.js.map → redact-doc-WCNALJSX.js.map} +0 -0
- /package/dist/{render-Z6N2GGKL.js.map → render-2SSXV7MR.js.map} +0 -0
- /package/dist/{seal-PM4624BB.js.map → seal-ENUBZ7ZX.js.map} +0 -0
- /package/dist/{setup-MUBZ674O.js.map → setup-VY5MAK7O.js.map} +0 -0
- /package/dist/{visual-AV46N5ZN.js.map → visual-ON76FHWH.js.map} +0 -0
- /package/dist/{watch-D4AUDKVN.js.map → watch-JLCOQOAL.js.map} +0 -0
package/README.md
CHANGED
|
@@ -105,19 +105,19 @@ await writeFile("보고서.hwpx", Buffer.from(hwpx))
|
|
|
105
105
|
|
|
106
106
|
## 검증 결과
|
|
107
107
|
|
|
108
|
-
**4.22.14 · 2026-10-19 검증**(렌더 배치·PDF 글·표·OCR 은 4.24.
|
|
108
|
+
**4.22.14 · 2026-10-19 검증**(렌더 배치·PDF 글·표·OCR 은 4.24.10 · 2026-10-26). 고정 코퍼스와 참조 기준으로 측정한 결과입니다.
|
|
109
109
|
|
|
110
110
|
| 대상 | 규모 | 결과 |
|
|
111
111
|
| --- | --- | --- |
|
|
112
112
|
| HWPX | 2,424문서 · 10,342표 | 표 구조 일치 **10,342/10,342 · 100%** |
|
|
113
113
|
| HWP 5.x ↔ HWPX | 1,130쌍 · 4,315표 | 짝 문서의 표 구조 일치 **100%** |
|
|
114
|
-
| PDF 글 | 744쌍 | 글자 재현율 **99.881%** · 정확도 **99.
|
|
114
|
+
| PDF 글 | 744쌍 | 글자 재현율 **99.881%** · 정확도 **99.677%** · 읽기 순서 **99.309%** · 어절 F1 **99.066%** |
|
|
115
115
|
| PDF 표 | 708쌍 · 2,331표 | 표 탐지 **99.83%** · 구조 일치 **98.24%** · 칸 F1 **0.9919** |
|
|
116
116
|
| HWPX 재조판 | 다중줄 25,187문단 (12개 폴더) | 모든 줄 시작 일치 **24,941/25,187 · 99.02%** |
|
|
117
117
|
| PDF 중첩표 (텍스트층) | 29문서 · 101표 | 구조·칸 내용 **101/101 · 100%** |
|
|
118
118
|
| 법령 별표 | 272건 · 346표 | HWP **346/346**, PDF **342/346 · 98.84%** |
|
|
119
119
|
| PDF 전체 | 1,911문서 중 1,729건 채점 | 글 커버리지 **99.80%** |
|
|
120
|
-
| OCR | 53문서 · 102쪽 · 67표 | CER **0.
|
|
120
|
+
| OCR | 53문서 · 102쪽 · 67표 | CER **0.0310** · 글자 재현율 **99.10%** · 표 구조 일치 **25/67** |
|
|
121
121
|
| opendataloader-bench | PDF 200문서 | 종합 기본값 **0.964** · OCR 끔 **0.939** |
|
|
122
122
|
| HWPX 렌더 배치 (4.24.8) | 한컴 PDF 짝 · 글 조각 90,906 · 그림 4,107 | 글 위치(±1.5pt) **87,620 · 96.4%** · 그림 위치(±2pt) **4,019 · 97.9%** |
|
|
123
123
|
|
|
@@ -125,15 +125,15 @@ await writeFile("보고서.hwpx", Buffer.from(hwpx))
|
|
|
125
125
|
|
|
126
126
|
## 최근 업데이트
|
|
127
127
|
|
|
128
|
-
최신 배포: **[4.24.
|
|
128
|
+
최신 배포: **[4.24.10](https://github.com/chrisryugj/kordoc/releases/tag/v4.24.10)** · 2026-10-26
|
|
129
129
|
|
|
130
130
|
| 버전 | 주요 변경 | 수치 변화 |
|
|
131
131
|
| --- | --- | --- |
|
|
132
|
+
| 4.24.10 | 보안: 데모 lockfile 의 zod·fast-uri, 정부 GitLab 미러 복구(Java SDK `kordoc-pom.xml`) · OCR: 줄 머리 ▣·❐·‣, `\|` 로 읽은 로마 숫자, 날짜 끝 마침표 · PDF: 세로쓰기 、。, 그러데이션 배경 괘선, 중·일문 자동 간격 | OCR CER 0.0313 → **0.0310** · 글자 재현율 99.06% → **99.10%** · 열화 입력 9종 모두 개선(스캔 0.0734 → **0.0730**) · PDF 어절 F1 99.064% → **99.066%** |
|
|
132
133
|
| 4.24.9 | 견본 서식·patch 행 추가 표의 행마다 이중선 · OCR: 통째로 빠진 줄 머리 ○ · PDF: 쪽을 넘는 표가 다음 쪽 첫 행을 삼키던 것 | OCR CER 0.0314 → **0.0313** · 흐린 입력 OCR CER 0.0638 → **0.0635** · PDF 표 구조 98.20% → **98.24%** |
|
|
133
134
|
| 4.24.8 | 보안: 알려진 의존성 취약점 6건 → 0건(zod 4, MCP SDK 하위 의존성), 출시·CI 에 `npm audit` 게이트 · OCR: 숫자로 읽은 줄 머리 고리 글머리, 다음 글자와 맞닿은 「 · PDF: 머리 칸에만 클립을 건 통계표 | `npm audit` 6 → **0** · OCR CER 0.0327 → **0.0314** · 흐린 입력 OCR CER 0.0663 → **0.0638** · PDF 글 순서 99.307% → **99.309%** |
|
|
134
135
|
| 4.24.7 | 견본 생성: 목차 상자를 요약 상자로 쓰지 않음, 부호 문단 아래 들여 쓴 목록 단계 · HWPML: 묶음·고정폭 빈칸과 강제 줄바꿈 · OCR: 줄 끝 배경 무늬, 머리행에 붙은 숫자 열, 붙임표·줄표 길이 | OCR CER 0.0332 → **0.0327** · 글자 재현율 99.02% → **99.04%** |
|
|
135
136
|
| 4.24.6 | OCR: 예산 사업명세서의 목·내역 하위 행, 칸마다 갈린 색 머리 띠, 칸 안 위아래 두 줄 뒤집힘 · PDF: 쪽 바깥 넉 자 세로 탭 · 렌더: 쪽 번호 새로 시작 · HWPX: 들여 써 저장한 XML 의 공백 | OCR CER 0.0409 → **0.0332** · OCR 표 구조 24 → **25/67** · 렌더 글 위치 87,509 → **87,620** · PDF 글 순서 99.302% → **99.307%** |
|
|
136
|
-
| 4.24.5 | PDF: 분수 막대 수식 복원, 고정폭 글줄의 가짜 무괘선 표, 덧찍은 목차 쪽 번호 · OCR: 선 없이 쌓은 하위 행, 색 머리 띠 안 흰 구분선, 글의 밑줄 표지 · HWPX·HWP: 표 아래 캡션 차례 | PDF 글 순서 99.247% → **99.302%** · 별표 수식 7 → **11/11** · OCR 표 구조 21 → **24/67** |
|
|
137
137
|
|
|
138
138
|
이전 버전과 상세 내용은 [변경 이력](CHANGELOG.md)에 있습니다.
|
|
139
139
|
|
|
@@ -58,10 +58,10 @@ import {
|
|
|
58
58
|
usesGaejosikMunche,
|
|
59
59
|
usesLogicStructure,
|
|
60
60
|
validateHwpx
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-UK3CENY6.js";
|
|
62
62
|
import {
|
|
63
63
|
blocksToChunks
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-VAYHMKSC.js";
|
|
65
65
|
import {
|
|
66
66
|
SPACE_EM_FIXED,
|
|
67
67
|
SPACE_EM_FONT,
|
|
@@ -86,20 +86,20 @@ import {
|
|
|
86
86
|
renderSceneToHtml,
|
|
87
87
|
simulateWrap,
|
|
88
88
|
simulateWrapKeepWord
|
|
89
|
-
} from "./chunk-
|
|
90
|
-
import "./chunk-
|
|
89
|
+
} from "./chunk-4AKR7LBP.js";
|
|
90
|
+
import "./chunk-NFJN75Y2.js";
|
|
91
91
|
import {
|
|
92
92
|
blocksToPages
|
|
93
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-WZWJCMM3.js";
|
|
94
94
|
import "./chunk-VKVDMH7X.js";
|
|
95
95
|
import "./chunk-VQFA55IC.js";
|
|
96
96
|
import "./chunk-BYMPPVT3.js";
|
|
97
|
-
import "./chunk-
|
|
97
|
+
import "./chunk-RNDG6RQU.js";
|
|
98
98
|
import {
|
|
99
99
|
blocksToMarkdown,
|
|
100
100
|
flattenLayoutTables,
|
|
101
101
|
hasStructuredCellContent
|
|
102
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-TT6UHEDY.js";
|
|
103
103
|
import {
|
|
104
104
|
ValueCursor,
|
|
105
105
|
applySplices,
|
|
@@ -113,11 +113,11 @@ import {
|
|
|
113
113
|
isLabelCell,
|
|
114
114
|
placeSealHwpx,
|
|
115
115
|
scanSectionXml
|
|
116
|
-
} from "./chunk-
|
|
117
|
-
import "./chunk-
|
|
116
|
+
} from "./chunk-PB6EOWE4.js";
|
|
117
|
+
import "./chunk-S4HE5OH5.js";
|
|
118
118
|
import {
|
|
119
119
|
VERSION
|
|
120
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-3BRGHU2F.js";
|
|
121
121
|
import {
|
|
122
122
|
DEFAULT_REDACT_RULES,
|
|
123
123
|
redactMarkdown,
|
|
@@ -227,4 +227,4 @@ export {
|
|
|
227
227
|
usesLogicStructure,
|
|
228
228
|
validateHwpx
|
|
229
229
|
};
|
|
230
|
-
//# sourceMappingURL=-
|
|
230
|
+
//# sourceMappingURL=-H7GN7FIS.js.map
|
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
HEADING_RATIO_H3,
|
|
7
7
|
tidyScriptTags,
|
|
8
8
|
toTex
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-RNDG6RQU.js";
|
|
10
10
|
import {
|
|
11
11
|
safeMax,
|
|
12
12
|
safeMin
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-3BRGHU2F.js";
|
|
14
14
|
|
|
15
15
|
// src/ocr/line-split.ts
|
|
16
16
|
function grayCrop(rgba, pageW, box) {
|
|
@@ -507,7 +507,8 @@ function gapGlyphs(gray, w, h, ink) {
|
|
|
507
507
|
const speck = Math.max(3, bh * 0.08);
|
|
508
508
|
const dot = ch <= bh * 0.25 && cw <= bh * 0.25 && ch >= speck && cw >= speck && cw >= ch * 0.6 && cw <= ch * 1.6;
|
|
509
509
|
const small = ch <= bh * 0.25 && cw <= bh * 0.25 && ch >= 2 && cw >= 2 && cw >= ch * 0.6 && cw <= ch * 1.6 && fill >= 0.6 && cy >= 0.3 && cy <= 0.7;
|
|
510
|
-
|
|
510
|
+
const flushDot = !apart && dot && fill >= 0.6 && cy >= 0.75 && cw >= ch * 0.8 && !others.some((o) => o.x0 < c.x1 && o.x1 > c.x0);
|
|
511
|
+
if (!apart && !abut && !flushDot && !(nearlyApart && ch >= bh * 0.6)) {
|
|
511
512
|
if (small) out.push({ x0: c.x0, x1: c.x1, mark: "\xB7" });
|
|
512
513
|
continue;
|
|
513
514
|
}
|
|
@@ -524,7 +525,8 @@ function gapGlyphs(gray, w, h, ink) {
|
|
|
524
525
|
if (c.y1 >= bandB - bh * 0.15 && bottom >= 0.7 && top <= 0.5 && stem(c.y0, c.y1 - band) >= 0.65) return "\u300D";
|
|
525
526
|
return null;
|
|
526
527
|
};
|
|
527
|
-
if (
|
|
528
|
+
if (flushDot) mark = ".";
|
|
529
|
+
else if (!apart && !abut) {
|
|
528
530
|
} else if (abut) {
|
|
529
531
|
if (fill < 0.5) mark = bracket();
|
|
530
532
|
} else if (dot && fill >= 0.6 && cy >= 0.3 && cy <= 0.7) mark = "\xB7";
|
|
@@ -716,6 +718,29 @@ function leadingBullet(gray, w, h, ink, firstX) {
|
|
|
716
718
|
const cl = cand.filter((c) => c.x0 < first.x1 && c.x1 > first.x0);
|
|
717
719
|
const x0 = Math.min(...cl.map((c) => c.x0)), x1 = Math.max(...cl.map((c) => c.x1)), y0 = Math.min(...cl.map((c) => c.y0)), y1 = Math.max(...cl.map((c) => c.y1));
|
|
718
720
|
const cw = x1 - x0, ch = y1 - y0;
|
|
721
|
+
if (cl.length === 1 && cw >= ch * 0.55 && cw <= ch * 1.1 && ch >= charH * 0.3 && ch <= charH * 0.7) {
|
|
722
|
+
const runs = [];
|
|
723
|
+
let aligned = true;
|
|
724
|
+
for (let y = y0; y < y1 && aligned; y++) {
|
|
725
|
+
let first2 = -1, last = -1, segs = 0, prev = false;
|
|
726
|
+
for (let x = x0; x < x1; x++) {
|
|
727
|
+
const on = label[y * w + x] === cl[0].id;
|
|
728
|
+
if (on) {
|
|
729
|
+
if (!prev) segs++;
|
|
730
|
+
if (first2 < 0) first2 = x;
|
|
731
|
+
last = x;
|
|
732
|
+
}
|
|
733
|
+
prev = on;
|
|
734
|
+
}
|
|
735
|
+
aligned = segs === 1 && first2 - x0 <= Math.max(1, cw * 0.15);
|
|
736
|
+
runs.push(last - first2 + 1);
|
|
737
|
+
}
|
|
738
|
+
const peak = runs.indexOf(Math.max(...runs));
|
|
739
|
+
if (aligned && Math.abs(peak - ch / 2) <= ch * 0.2 && runs[0] <= cw * 0.45 && runs[runs.length - 1] <= cw * 0.45 && Math.max(...runs) >= cw * 0.85) {
|
|
740
|
+
const next2 = cand.find((c) => c.x0 >= x1);
|
|
741
|
+
if (!next2 || next2.x0 - x1 >= ch * 0.3) return { mark: "\u2023", covers: firstX <= x1 + ch * 0.3 };
|
|
742
|
+
}
|
|
743
|
+
}
|
|
719
744
|
if (cw < ch * 0.8 || cw > ch * 1.25) return null;
|
|
720
745
|
const next = cand.find((c) => c.x0 >= x1);
|
|
721
746
|
if (next && next.x0 - x1 < ch * 0.3) return null;
|
|
@@ -750,8 +775,32 @@ function leadingBullet(gray, w, h, ink, firstX) {
|
|
|
750
775
|
}
|
|
751
776
|
}
|
|
752
777
|
const hollowSquare = cl.length === 1 && fill < 0.5 && midRuns === 2 && edgeFull(y0, 1) && edgeFull(y1 - 1, -1);
|
|
778
|
+
const core = cl.length === 2 ? cl.find((b) => cl.some((a) => a !== b && b.x0 > a.x0 && b.x1 < a.x1 && b.y0 > a.y0 && b.y1 < a.y1)) : void 0;
|
|
779
|
+
const coreFill = (() => {
|
|
780
|
+
if (!core) return 0;
|
|
781
|
+
let k = 0;
|
|
782
|
+
for (let y = core.y0; y < core.y1; y++) for (let x = core.x0; x < core.x1; x++) if (label[y * w + x] === core.id) k++;
|
|
783
|
+
return k / ((core.x1 - core.x0) * (core.y1 - core.y0));
|
|
784
|
+
})();
|
|
785
|
+
const filledSquare = !!core && coreFill >= 0.85 && ring(core) && Math.abs(core.x0 + core.x1 - (x0 + x1)) <= cw * 0.2 && Math.abs(core.y0 + core.y1 - (y0 + y1)) <= ch * 0.2 && edgeFull(y0, 1) && edgeFull(y1 - 1, -1);
|
|
786
|
+
const run = (x, y, dx, dy) => {
|
|
787
|
+
let n = 0;
|
|
788
|
+
while (x >= x0 && x < x1 && y >= y0 && y < y1 && cl.some((c) => label[y * w + x] === c.id)) {
|
|
789
|
+
n++;
|
|
790
|
+
x += dx;
|
|
791
|
+
y += dy;
|
|
792
|
+
}
|
|
793
|
+
return n;
|
|
794
|
+
};
|
|
795
|
+
const my0 = y0 + (ch >> 1), mx0 = x0 + (cw >> 1);
|
|
796
|
+
const thin = (a, b) => a > 0 && b >= a * 1.8 && b - a >= Math.max(3, ch * 0.08);
|
|
797
|
+
const boxed = cl.length === 1 && midRuns === 2 && edgeFull(y0, 1) && edgeFull(y1 - 1, -1) && thin(run(x0, my0, 1, 0), run(x1 - 1, my0, -1, 0));
|
|
798
|
+
const top = run(mx0, y0, 0, 1), bottom = run(mx0, y1 - 1, 0, -1);
|
|
799
|
+
const shadow = !boxed ? null : thin(bottom, top) ? "\u2750" : thin(top, bottom) ? "\u274F" : null;
|
|
753
800
|
let mark = null;
|
|
754
|
-
if (
|
|
801
|
+
if (shadow && rel >= 0.6 && rel <= 0.92) mark = shadow;
|
|
802
|
+
else if (hollowSquare && rel >= 0.6 && rel <= 0.92) mark = "\u25A1";
|
|
803
|
+
else if (filledSquare && rel >= 0.6 && rel <= 0.92) mark = "\u25A3";
|
|
755
804
|
else if (nested && fill < 0.45 && rel >= 0.6) mark = "\u25CE";
|
|
756
805
|
else if (cl.length === 1 && fill >= 0.9 && rel >= 0.28 && rel <= 0.6) mark = "\u25AA";
|
|
757
806
|
else if (cl.length === 1 && fill >= 0.65 && fill <= 0.88 && rel >= 0.5 && rel <= 0.8) mark = "\u25CF";
|
|
@@ -1096,9 +1145,10 @@ function extractLines(fnArray, argsArray) {
|
|
|
1096
1145
|
break;
|
|
1097
1146
|
}
|
|
1098
1147
|
}
|
|
1148
|
+
const gradient = gradientBands(horizontals, verticals);
|
|
1099
1149
|
return {
|
|
1100
|
-
horizontals: chainShortSegments(horizontals, thinShortH, "h", (l) => thinFill.has(l)),
|
|
1101
|
-
verticals: chainShortSegments(verticals, thinShortV, "v", (l) => thinFill.has(l)),
|
|
1150
|
+
horizontals: chainShortSegments(horizontals.filter((l) => !gradient.has(l)), thinShortH, "h", (l) => thinFill.has(l)),
|
|
1151
|
+
verticals: chainShortSegments(verticals.filter((l) => !gradient.has(l)), thinShortV, "v", (l) => thinFill.has(l)),
|
|
1102
1152
|
clipRects,
|
|
1103
1153
|
fillRects,
|
|
1104
1154
|
hiddenBoxes,
|
|
@@ -1107,6 +1157,39 @@ function extractLines(fnArray, argsArray) {
|
|
|
1107
1157
|
nonRules
|
|
1108
1158
|
};
|
|
1109
1159
|
}
|
|
1160
|
+
var GRADIENT_MIN_EDGES = 8;
|
|
1161
|
+
var GRADIENT_PITCH = 1;
|
|
1162
|
+
function gradientBands(horizontals, verticals) {
|
|
1163
|
+
const out = /* @__PURE__ */ new Set();
|
|
1164
|
+
for (const [lines, dir] of [[horizontals, "h"], [verticals, "v"]]) {
|
|
1165
|
+
const pos = (l) => dir === "h" ? l.y1 : l.x1;
|
|
1166
|
+
const span2 = (l) => dir === "h" ? `${Math.round(l.x1)}|${Math.round(l.x2)}` : `${Math.round(l.y1)}|${Math.round(l.y2)}`;
|
|
1167
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1168
|
+
for (const l of lines) if (l.fromFill) {
|
|
1169
|
+
const k = span2(l);
|
|
1170
|
+
const g = groups.get(k);
|
|
1171
|
+
if (g) g.push(l);
|
|
1172
|
+
else groups.set(k, [l]);
|
|
1173
|
+
}
|
|
1174
|
+
for (const g of groups.values()) {
|
|
1175
|
+
if (g.length < GRADIENT_MIN_EDGES) continue;
|
|
1176
|
+
g.sort((a, b) => pos(a) - pos(b));
|
|
1177
|
+
let run = [g[0]];
|
|
1178
|
+
const flush = () => {
|
|
1179
|
+
if (run.length >= GRADIENT_MIN_EDGES) for (const l of run) out.add(l);
|
|
1180
|
+
};
|
|
1181
|
+
for (let i = 1; i < g.length; i++) {
|
|
1182
|
+
if (pos(g[i]) - pos(g[i - 1]) <= GRADIENT_PITCH) run.push(g[i]);
|
|
1183
|
+
else {
|
|
1184
|
+
flush();
|
|
1185
|
+
run = [g[i]];
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
flush();
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
return out;
|
|
1192
|
+
}
|
|
1110
1193
|
var SHORT_CHAIN_POS_TOL = 0.5;
|
|
1111
1194
|
var SHORT_CHAIN_GAP = 0.2;
|
|
1112
1195
|
function chainShortSegments(longs, shorts, dir, chainable = (l) => !l.fromFill) {
|
|
@@ -3473,6 +3556,7 @@ function cellTextToString(items, wrap) {
|
|
|
3473
3556
|
if (s.length === 1) return s[0].text;
|
|
3474
3557
|
if (s.length === 2 && /^[가-힣]$/.test(s[0].text) && /^[가-힣]$/.test(s[1].text) && !!wrap?.lex && (wrap.lex.isWord(s[0].text + s[1].text) || wrap.lex.evidence(s[0].text, s[1].text) === "" || REGION_LABELS.has(s[0].text + s[1].text)) && s[1].x - (s[0].x + s[0].w) >= Math.max(s[0].fontSize, s[1].fontSize) * 1.5 && s[1].x + s[1].w - s[0].x >= wrap.box.x2 - wrap.box.x1 - Math.max(s[0].fontSize, s[1].fontSize) * 2) return s[0].text + s[1].text;
|
|
3475
3558
|
const evenSpaced = detectEvenSpacedItems(s, true);
|
|
3559
|
+
const hangulLine = s.some((it) => /[가-힣]/.test(it.text));
|
|
3476
3560
|
let result = s[0].text;
|
|
3477
3561
|
for (let j = 1; j < s.length; j++) {
|
|
3478
3562
|
if (evenSpaced[j]) {
|
|
@@ -3481,7 +3565,7 @@ function cellTextToString(items, wrap) {
|
|
|
3481
3565
|
}
|
|
3482
3566
|
const gap = s[j].x - (s[j - 1].x + s[j - 1].w);
|
|
3483
3567
|
const avgFs = (s[j].fontSize + s[j - 1].fontSize) / 2;
|
|
3484
|
-
if (isCjkLatinAutospace(s[j - 1].text, s[j].text, gap, avgFs)) {
|
|
3568
|
+
if (isCjkLatinAutospace(s[j - 1].text, s[j].text, gap, avgFs, hangulLine)) {
|
|
3485
3569
|
result += s[j].text;
|
|
3486
3570
|
} else if (s[j].hasSpaceBefore && gap >= avgFs * 0.05) {
|
|
3487
3571
|
result += " " + s[j].text;
|
|
@@ -3820,8 +3904,9 @@ function sortLineByX(items) {
|
|
|
3820
3904
|
}
|
|
3821
3905
|
return items;
|
|
3822
3906
|
}
|
|
3823
|
-
function isCjkLatinAutospace(prevText, nextText, gap, fontSize) {
|
|
3824
|
-
if (!(gap < fontSize * 0.
|
|
3907
|
+
function isCjkLatinAutospace(prevText, nextText, gap, fontSize, hangulLine = false) {
|
|
3908
|
+
if (!(gap < fontSize * 0.35)) return false;
|
|
3909
|
+
if (hangulLine) return false;
|
|
3825
3910
|
const a = prevText.slice(-1), b = nextText[0] ?? "";
|
|
3826
3911
|
const cjk = /[\u3040-\u30ff\u3400-\u9fff\uf900-\ufaff]/, latin = /[A-Za-z0-9]/;
|
|
3827
3912
|
return cjk.test(a) && latin.test(b) || latin.test(a) && cjk.test(b);
|
|
@@ -4161,6 +4246,7 @@ function mergeLineSimple(items) {
|
|
|
4161
4246
|
if (items.length <= 1) return items[0]?.text || "";
|
|
4162
4247
|
const sorted = sortLineByX([...items]);
|
|
4163
4248
|
const isEvenSpaced = detectEvenSpacedItems(sorted);
|
|
4249
|
+
const hangulLine = sorted.some((it) => /[가-힣]/.test(it.text));
|
|
4164
4250
|
let result = sorted[0].text;
|
|
4165
4251
|
for (let i = 1; i < sorted.length; i++) {
|
|
4166
4252
|
const gap = sorted[i].x - (sorted[i - 1].x + sorted[i - 1].w);
|
|
@@ -4175,7 +4261,7 @@ function mergeLineSimple(items) {
|
|
|
4175
4261
|
result += sorted[i].text;
|
|
4176
4262
|
continue;
|
|
4177
4263
|
}
|
|
4178
|
-
if (isCjkLatinAutospace(sorted[i - 1].text, sorted[i].text, gap, avgFs)) {
|
|
4264
|
+
if (isCjkLatinAutospace(sorted[i - 1].text, sorted[i].text, gap, avgFs, hangulLine)) {
|
|
4179
4265
|
result += sorted[i].text;
|
|
4180
4266
|
continue;
|
|
4181
4267
|
}
|
|
@@ -4341,11 +4427,12 @@ function clusterCellLines(items) {
|
|
|
4341
4427
|
}
|
|
4342
4428
|
return lines.sort((a, b) => b.top - a.top).map(({ items: line }) => {
|
|
4343
4429
|
line.sort((a, b) => a.x - b.x);
|
|
4430
|
+
const hangulLine = line.some((it) => /[가-힣]/.test(it.text));
|
|
4344
4431
|
let s = line[0].text;
|
|
4345
4432
|
for (let i = 1; i < line.length; i++) {
|
|
4346
4433
|
const gap = line[i].x - (line[i - 1].x + line[i - 1].w);
|
|
4347
4434
|
const fs = (line[i].fontSize + line[i - 1].fontSize) / 2;
|
|
4348
|
-
s += (!isCjkLatinAutospace(line[i - 1].text, line[i].text, gap, fs) && (line[i].hasSpaceBefore && gap >= fs * 0.05 || gap > spaceGapThreshold(fs)) ? " " : "") + line[i].text;
|
|
4435
|
+
s += (!isCjkLatinAutospace(line[i - 1].text, line[i].text, gap, fs, hangulLine) && (line[i].hasSpaceBefore && gap >= fs * 0.05 || gap > spaceGapThreshold(fs)) ? " " : "") + line[i].text;
|
|
4349
4436
|
}
|
|
4350
4437
|
const last = line.reduce((a, b) => b.x + b.w > a.x + a.w ? b : a);
|
|
4351
4438
|
return {
|
|
@@ -10095,4 +10182,4 @@ export {
|
|
|
10095
10182
|
UNRULED_REGION_TABLES,
|
|
10096
10183
|
mergeOcrImageRegions
|
|
10097
10184
|
};
|
|
10098
|
-
//# sourceMappingURL=chunk-
|
|
10185
|
+
//# sourceMappingURL=chunk-37JRATLZ.js.map
|