kordoc 4.24.8 → 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 +7 -7
- package/dist/{-TLCDUU22.js → -H7GN7FIS.js} +11 -11
- package/dist/{chunk-IT5XO3UG.js → chunk-37JRATLZ.js} +129 -13
- package/dist/chunk-37JRATLZ.js.map +1 -0
- package/dist/{chunk-5MQG3GJI.js → chunk-3BRGHU2F.js} +2 -2
- package/dist/{chunk-5MQG3GJI.js.map → chunk-3BRGHU2F.js.map} +1 -1
- package/dist/{chunk-RCT5MO53.js → chunk-4AKR7LBP.js} +6 -6
- package/dist/{chunk-CB57N2MG.js → chunk-4TAOUMLJ.js} +2 -2
- package/dist/{chunk-OUJIV2AM.js → chunk-ALCD3FB7.js} +2 -2
- package/dist/{chunk-DPB6ZVQ5.js → chunk-CZGAGILH.js} +130 -14
- package/dist/chunk-CZGAGILH.js.map +1 -0
- package/dist/{chunk-KA6JZZIW.js → chunk-ENQWDN6M.js} +23 -7
- package/dist/chunk-ENQWDN6M.js.map +1 -0
- package/dist/{chunk-TTUAJYTC.js → chunk-HFNNRSAJ.js} +23 -7
- package/dist/chunk-HFNNRSAJ.js.map +1 -0
- package/dist/{chunk-ZJYNTA5R.cjs → chunk-IV4ZRFHF.cjs} +83 -67
- package/dist/chunk-IV4ZRFHF.cjs.map +1 -0
- package/dist/{chunk-7F35EPMM.cjs → chunk-JH3AA5TY.cjs} +3 -3
- package/dist/{chunk-7F35EPMM.cjs.map → chunk-JH3AA5TY.cjs.map} +1 -1
- package/dist/{chunk-F7UWIMUA.js → chunk-LLKLJ2JF.js} +2 -2
- package/dist/{chunk-F7UWIMUA.js.map → chunk-LLKLJ2JF.js.map} +1 -1
- package/dist/{chunk-WTSID6AI.js → chunk-LMG7Y3TN.js} +2 -2
- package/dist/{chunk-J7MFKS73.js → chunk-NFJN75Y2.js} +2 -2
- package/dist/{chunk-D3EHIHYN.js → chunk-OZTG6NCW.js} +2 -2
- package/dist/{chunk-FSWJC5RR.js → chunk-PB6EOWE4.js} +3 -3
- package/dist/{chunk-N2XN6GAQ.js → chunk-PDPHUGVP.js} +2 -2
- package/dist/{chunk-XOUZC7MX.js → chunk-PSQJYUJC.js} +2 -2
- package/dist/{chunk-C3BOYTY5.cjs → chunk-QAHWMIBF.cjs} +2 -2
- package/dist/{chunk-C3BOYTY5.cjs.map → chunk-QAHWMIBF.cjs.map} +1 -1
- package/dist/{chunk-TDB27K2Z.js → chunk-RNDG6RQU.js} +2 -2
- package/dist/{chunk-7XPTKW76.js → chunk-S4HE5OH5.js} +2 -2
- package/dist/{chunk-BJABLQMB.js → chunk-TT6UHEDY.js} +2 -2
- package/dist/{chunk-K2FGQ5D5.js → chunk-UK3CENY6.js} +151 -20
- package/dist/chunk-UK3CENY6.js.map +1 -0
- package/dist/{chunk-RCDRTQ37.js → chunk-VAYHMKSC.js} +2 -2
- package/dist/{chunk-JM7PZM6E.cjs → chunk-WKN5YUMP.cjs} +3 -3
- package/dist/{chunk-JM7PZM6E.cjs.map → chunk-WKN5YUMP.cjs.map} +1 -1
- package/dist/{chunk-7JUF6G6Z.js → chunk-WZWJCMM3.js} +2 -2
- package/dist/{chunk-73MRAQXA.cjs → chunk-X5BFTWCB.cjs} +152 -36
- package/dist/chunk-X5BFTWCB.cjs.map +1 -0
- package/dist/{chunk-NW2CKOFL.cjs → chunk-XFM4SX74.cjs} +6 -6
- package/dist/{chunk-NW2CKOFL.cjs.map → chunk-XFM4SX74.cjs.map} +1 -1
- package/dist/{chunk-Z5DT55TW.js → chunk-XMAOBI35.js} +3 -3
- package/dist/{chunk-NE6G6LCP.js → chunk-YAKLWOT2.js} +2 -2
- package/dist/chunks-CMSL2XXG.js +10 -0
- package/dist/cli.js +30 -30
- package/dist/{formula-PNMQ5JFJ.js → formula-P5VHY4YS.js} +3 -3
- package/dist/{formula-ZLNSVWS6.cjs → formula-TBG6BYE2.cjs} +9 -9
- package/dist/{formula-ZLNSVWS6.cjs.map → formula-TBG6BYE2.cjs.map} +1 -1
- package/dist/{formula-DZMBNPWT.js → formula-YCZOVUJU.js} +4 -4
- package/dist/{image-ocr-P5Q6YXTO.js → image-ocr-2UD6RWE6.js} +6 -6
- package/dist/{image-ocr-BPH25SFW.js → image-ocr-3QCUKBTE.js} +9 -9
- package/dist/{image-ocr-YUXCVOOP.cjs → image-ocr-J6EWIQ73.cjs} +17 -17
- package/dist/{image-ocr-YUXCVOOP.cjs.map → image-ocr-J6EWIQ73.cjs.map} +1 -1
- package/dist/index.cjs +826 -695
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +146 -15
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +23 -23
- package/dist/{model-bundle-XAM6JFZV.js → model-bundle-EFAOVVYU.js} +5 -5
- package/dist/{models-6Q5ULSTP.js → models-SJXAHLSA.js} +5 -5
- package/dist/{parse-worker-v2-ONX5QLJZ.js → parse-worker-v2-ZSSOTZVE.js} +12 -12
- package/dist/{parser-54R7ENH6.js → parser-3XHPJKL7.js} +12 -10
- package/dist/parser-3XHPJKL7.js.map +1 -0
- package/dist/{parser-JHXN4S6L.js → parser-4I4MM5AJ.js} +15 -13
- package/dist/parser-4I4MM5AJ.js.map +1 -0
- package/dist/{parser-Z352BN56.cjs → parser-4MXHN43N.cjs} +162 -160
- package/dist/parser-4MXHN43N.cjs.map +1 -0
- package/dist/{pdf-ocr-LFVER7IE.js → pdf-ocr-J6GXPLZJ.js} +6 -6
- package/dist/pdf-ocr-JPLZOU23.cjs +31 -0
- package/dist/{pdf-ocr-SMFFJYTD.cjs.map → pdf-ocr-JPLZOU23.cjs.map} +1 -1
- package/dist/{pdf-ocr-FQ4LAXM6.js → pdf-ocr-QXZIMPQI.js} +9 -9
- package/dist/{profile-io-YW5QWKBB.js → profile-io-X7ZMPA7T.js} +3 -3
- package/dist/{rasterize-T4S3NMQ7.js → rasterize-42GMMS3L.js} +3 -3
- package/dist/{redact-doc-CAVBR5XO.js → redact-doc-WCNALJSX.js} +11 -11
- package/dist/{render-ZW52ZX6R.js → render-2SSXV7MR.js} +7 -7
- package/dist/seal-ENUBZ7ZX.js +10 -0
- package/dist/{setup-7UGSJPJP.js → setup-VY5MAK7O.js} +3 -3
- package/dist/visual-ON76FHWH.js +21 -0
- package/dist/{watch-M4A7B5WS.js → watch-JLCOQOAL.js} +12 -12
- package/package.json +1 -1
- package/dist/chunk-73MRAQXA.cjs.map +0 -1
- package/dist/chunk-DPB6ZVQ5.js.map +0 -1
- package/dist/chunk-IT5XO3UG.js.map +0 -1
- package/dist/chunk-K2FGQ5D5.js.map +0 -1
- package/dist/chunk-KA6JZZIW.js.map +0 -1
- package/dist/chunk-TTUAJYTC.js.map +0 -1
- package/dist/chunk-ZJYNTA5R.cjs.map +0 -1
- package/dist/chunks-S2GGFN6W.js +0 -10
- package/dist/parser-54R7ENH6.js.map +0 -1
- package/dist/parser-JHXN4S6L.js.map +0 -1
- package/dist/parser-Z352BN56.cjs.map +0 -1
- package/dist/pdf-ocr-SMFFJYTD.cjs +0 -31
- package/dist/seal-TQ3RLVVT.js +0 -10
- package/dist/visual-6GXHKPCJ.js +0 -21
- /package/dist/{-TLCDUU22.js.map → -H7GN7FIS.js.map} +0 -0
- /package/dist/{chunk-RCT5MO53.js.map → chunk-4AKR7LBP.js.map} +0 -0
- /package/dist/{chunk-CB57N2MG.js.map → chunk-4TAOUMLJ.js.map} +0 -0
- /package/dist/{chunk-OUJIV2AM.js.map → chunk-ALCD3FB7.js.map} +0 -0
- /package/dist/{chunk-WTSID6AI.js.map → chunk-LMG7Y3TN.js.map} +0 -0
- /package/dist/{chunk-J7MFKS73.js.map → chunk-NFJN75Y2.js.map} +0 -0
- /package/dist/{chunk-D3EHIHYN.js.map → chunk-OZTG6NCW.js.map} +0 -0
- /package/dist/{chunk-FSWJC5RR.js.map → chunk-PB6EOWE4.js.map} +0 -0
- /package/dist/{chunk-N2XN6GAQ.js.map → chunk-PDPHUGVP.js.map} +0 -0
- /package/dist/{chunk-XOUZC7MX.js.map → chunk-PSQJYUJC.js.map} +0 -0
- /package/dist/{chunk-TDB27K2Z.js.map → chunk-RNDG6RQU.js.map} +0 -0
- /package/dist/{chunk-7XPTKW76.js.map → chunk-S4HE5OH5.js.map} +0 -0
- /package/dist/{chunk-BJABLQMB.js.map → chunk-TT6UHEDY.js.map} +0 -0
- /package/dist/{chunk-RCDRTQ37.js.map → chunk-VAYHMKSC.js.map} +0 -0
- /package/dist/{chunk-7JUF6G6Z.js.map → chunk-WZWJCMM3.js.map} +0 -0
- /package/dist/{chunk-Z5DT55TW.js.map → chunk-XMAOBI35.js.map} +0 -0
- /package/dist/{chunk-NE6G6LCP.js.map → chunk-YAKLWOT2.js.map} +0 -0
- /package/dist/{chunks-S2GGFN6W.js.map → chunks-CMSL2XXG.js.map} +0 -0
- /package/dist/{formula-PNMQ5JFJ.js.map → formula-P5VHY4YS.js.map} +0 -0
- /package/dist/{formula-DZMBNPWT.js.map → formula-YCZOVUJU.js.map} +0 -0
- /package/dist/{image-ocr-P5Q6YXTO.js.map → image-ocr-2UD6RWE6.js.map} +0 -0
- /package/dist/{image-ocr-BPH25SFW.js.map → image-ocr-3QCUKBTE.js.map} +0 -0
- /package/dist/{model-bundle-XAM6JFZV.js.map → model-bundle-EFAOVVYU.js.map} +0 -0
- /package/dist/{models-6Q5ULSTP.js.map → models-SJXAHLSA.js.map} +0 -0
- /package/dist/{parse-worker-v2-ONX5QLJZ.js.map → parse-worker-v2-ZSSOTZVE.js.map} +0 -0
- /package/dist/{pdf-ocr-FQ4LAXM6.js.map → pdf-ocr-J6GXPLZJ.js.map} +0 -0
- /package/dist/{pdf-ocr-LFVER7IE.js.map → pdf-ocr-QXZIMPQI.js.map} +0 -0
- /package/dist/{profile-io-YW5QWKBB.js.map → profile-io-X7ZMPA7T.js.map} +0 -0
- /package/dist/{rasterize-T4S3NMQ7.js.map → rasterize-42GMMS3L.js.map} +0 -0
- /package/dist/{redact-doc-CAVBR5XO.js.map → redact-doc-WCNALJSX.js.map} +0 -0
- /package/dist/{render-ZW52ZX6R.js.map → render-2SSXV7MR.js.map} +0 -0
- /package/dist/{seal-TQ3RLVVT.js.map → seal-ENUBZ7ZX.js.map} +0 -0
- /package/dist/{setup-7UGSJPJP.js.map → setup-VY5MAK7O.js.map} +0 -0
- /package/dist/{visual-6GXHKPCJ.js.map → visual-ON76FHWH.js.map} +0 -0
- /package/dist/{watch-M4A7B5WS.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.
|
|
115
|
-
| PDF 표 | 708쌍 · 2,331표 | 표 탐지 **99.83%** · 구조 일치 **98.
|
|
114
|
+
| PDF 글 | 744쌍 | 글자 재현율 **99.881%** · 정확도 **99.677%** · 읽기 순서 **99.309%** · 어절 F1 **99.066%** |
|
|
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%** |
|
|
133
|
+
| 4.24.9 | 견본 서식·patch 행 추가 표의 행마다 이중선 · OCR: 통째로 빠진 줄 머리 ○ · PDF: 쪽을 넘는 표가 다음 쪽 첫 행을 삼키던 것 | OCR CER 0.0314 → **0.0313** · 흐린 입력 OCR CER 0.0638 → **0.0635** · PDF 표 구조 98.20% → **98.24%** |
|
|
132
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%** |
|
|
133
135
|
| 4.24.7 | 견본 생성: 목차 상자를 요약 상자로 쓰지 않음, 부호 문단 아래 들여 쓴 목록 단계 · HWPML: 묶음·고정폭 빈칸과 강제 줄바꿈 · OCR: 줄 끝 배경 무늬, 머리행에 붙은 숫자 열, 붙임표·줄표 길이 | OCR CER 0.0332 → **0.0327** · 글자 재현율 99.02% → **99.04%** |
|
|
134
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%** |
|
|
135
|
-
| 4.24.5 | PDF: 분수 막대 수식 복원, 고정폭 글줄의 가짜 무괘선 표, 덧찍은 목차 쪽 번호 · OCR: 선 없이 쌓은 하위 행, 색 머리 띠 안 흰 구분선, 글의 밑줄 표지 · HWPX·HWP: 표 아래 캡션 차례 | PDF 글 순서 99.247% → **99.302%** · 별표 수식 7 → **11/11** · OCR 표 구조 21 → **24/67** |
|
|
136
|
-
| 4.24.4 | 렌더: 넘친 줄 줄이기(빈칸 20%·나머지 글자마다), 칸 안 개체가 키운 칸 높이, KoPub 대체 글꼴로 작성된 문서, 쪽 바닥 행 판정 · PDF: 옆 칸 선이 걸친 칸 변 | 렌더 글 위치 87,289 → **87,509**(새 측정 기준) · 그림 4,017 → **4,019** · PDF 표 구조 98.16% → **98.20%** |
|
|
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";
|
|
@@ -604,6 +606,34 @@ function dashRatio(gray, w, h, ink, cx) {
|
|
|
604
606
|
const dash = comps.filter((c) => c.y1 - c.y0 <= bh * 0.25 && c.x1 - c.x0 >= (c.y1 - c.y0) * 2 && Math.abs((c.x0 + c.x1) / 2 - cx) <= bh * 0.6).sort((a, b) => Math.abs((a.x0 + a.x1) / 2 - cx) - Math.abs((b.x0 + b.x1) / 2 - cx))[0];
|
|
605
607
|
return dash ? (dash.x1 - dash.x0) / bh : null;
|
|
606
608
|
}
|
|
609
|
+
function leadingRing(gray, w, h, ink, firstX) {
|
|
610
|
+
if (firstX < h * 0.8) return false;
|
|
611
|
+
const isInk = (v) => ink.darkInk ? v <= ink.threshold : v > ink.threshold;
|
|
612
|
+
let left = -1;
|
|
613
|
+
for (let x = 0; x < w && left < 0; x++) for (let y = 0; y < h; y++) if (isInk(gray[y * w + x])) {
|
|
614
|
+
left = x;
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
if (left < 0 || ringBullet(gray, w, h, ink, left + h * 0.25) !== "\u25CB") return false;
|
|
618
|
+
const colInk = (x) => {
|
|
619
|
+
for (let y = 0; y < h; y++) if (isInk(gray[y * w + x])) return true;
|
|
620
|
+
return false;
|
|
621
|
+
};
|
|
622
|
+
let right = left;
|
|
623
|
+
while (right + 1 < w && colInk(right + 1)) right++;
|
|
624
|
+
let top = h, bottom = -1;
|
|
625
|
+
for (let y = 0; y < h; y++) for (let x = left; x <= right; x++) if (isInk(gray[y * w + x])) {
|
|
626
|
+
top = Math.min(top, y);
|
|
627
|
+
bottom = Math.max(bottom, y);
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
const cw = right - left + 1, ch = bottom - top + 1, kx = Math.max(1, Math.round(cw * 0.1)), ky = Math.max(1, Math.round(ch * 0.1));
|
|
631
|
+
const corner = (x0, y0) => {
|
|
632
|
+
for (let y = y0; y < y0 + ky; y++) for (let x = x0; x < x0 + kx; x++) if (isInk(gray[y * w + x])) return true;
|
|
633
|
+
return false;
|
|
634
|
+
};
|
|
635
|
+
return !corner(left, top) && !corner(right + 1 - kx, top) && !corner(left, bottom + 1 - ky) && !corner(right + 1 - kx, bottom + 1 - ky);
|
|
636
|
+
}
|
|
607
637
|
function discAt(gray, w, h, ink, cx) {
|
|
608
638
|
const { comps, label } = components(gray, w, h, ink);
|
|
609
639
|
let charH = 0;
|
|
@@ -688,6 +718,29 @@ function leadingBullet(gray, w, h, ink, firstX) {
|
|
|
688
718
|
const cl = cand.filter((c) => c.x0 < first.x1 && c.x1 > first.x0);
|
|
689
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));
|
|
690
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
|
+
}
|
|
691
744
|
if (cw < ch * 0.8 || cw > ch * 1.25) return null;
|
|
692
745
|
const next = cand.find((c) => c.x0 >= x1);
|
|
693
746
|
if (next && next.x0 - x1 < ch * 0.3) return null;
|
|
@@ -722,8 +775,32 @@ function leadingBullet(gray, w, h, ink, firstX) {
|
|
|
722
775
|
}
|
|
723
776
|
}
|
|
724
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;
|
|
725
800
|
let mark = null;
|
|
726
|
-
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";
|
|
727
804
|
else if (nested && fill < 0.45 && rel >= 0.6) mark = "\u25CE";
|
|
728
805
|
else if (cl.length === 1 && fill >= 0.9 && rel >= 0.28 && rel <= 0.6) mark = "\u25AA";
|
|
729
806
|
else if (cl.length === 1 && fill >= 0.65 && fill <= 0.88 && rel >= 0.5 && rel <= 0.8) mark = "\u25CF";
|
|
@@ -1068,9 +1145,10 @@ function extractLines(fnArray, argsArray) {
|
|
|
1068
1145
|
break;
|
|
1069
1146
|
}
|
|
1070
1147
|
}
|
|
1148
|
+
const gradient = gradientBands(horizontals, verticals);
|
|
1071
1149
|
return {
|
|
1072
|
-
horizontals: chainShortSegments(horizontals, thinShortH, "h", (l) => thinFill.has(l)),
|
|
1073
|
-
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)),
|
|
1074
1152
|
clipRects,
|
|
1075
1153
|
fillRects,
|
|
1076
1154
|
hiddenBoxes,
|
|
@@ -1079,6 +1157,39 @@ function extractLines(fnArray, argsArray) {
|
|
|
1079
1157
|
nonRules
|
|
1080
1158
|
};
|
|
1081
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
|
+
}
|
|
1082
1193
|
var SHORT_CHAIN_POS_TOL = 0.5;
|
|
1083
1194
|
var SHORT_CHAIN_GAP = 0.2;
|
|
1084
1195
|
function chainShortSegments(longs, shorts, dir, chainable = (l) => !l.fromFill) {
|
|
@@ -3445,6 +3556,7 @@ function cellTextToString(items, wrap) {
|
|
|
3445
3556
|
if (s.length === 1) return s[0].text;
|
|
3446
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;
|
|
3447
3558
|
const evenSpaced = detectEvenSpacedItems(s, true);
|
|
3559
|
+
const hangulLine = s.some((it) => /[가-힣]/.test(it.text));
|
|
3448
3560
|
let result = s[0].text;
|
|
3449
3561
|
for (let j = 1; j < s.length; j++) {
|
|
3450
3562
|
if (evenSpaced[j]) {
|
|
@@ -3453,7 +3565,7 @@ function cellTextToString(items, wrap) {
|
|
|
3453
3565
|
}
|
|
3454
3566
|
const gap = s[j].x - (s[j - 1].x + s[j - 1].w);
|
|
3455
3567
|
const avgFs = (s[j].fontSize + s[j - 1].fontSize) / 2;
|
|
3456
|
-
if (isCjkLatinAutospace(s[j - 1].text, s[j].text, gap, avgFs)) {
|
|
3568
|
+
if (isCjkLatinAutospace(s[j - 1].text, s[j].text, gap, avgFs, hangulLine)) {
|
|
3457
3569
|
result += s[j].text;
|
|
3458
3570
|
} else if (s[j].hasSpaceBefore && gap >= avgFs * 0.05) {
|
|
3459
3571
|
result += " " + s[j].text;
|
|
@@ -3792,8 +3904,9 @@ function sortLineByX(items) {
|
|
|
3792
3904
|
}
|
|
3793
3905
|
return items;
|
|
3794
3906
|
}
|
|
3795
|
-
function isCjkLatinAutospace(prevText, nextText, gap, fontSize) {
|
|
3796
|
-
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;
|
|
3797
3910
|
const a = prevText.slice(-1), b = nextText[0] ?? "";
|
|
3798
3911
|
const cjk = /[\u3040-\u30ff\u3400-\u9fff\uf900-\ufaff]/, latin = /[A-Za-z0-9]/;
|
|
3799
3912
|
return cjk.test(a) && latin.test(b) || latin.test(a) && cjk.test(b);
|
|
@@ -4133,6 +4246,7 @@ function mergeLineSimple(items) {
|
|
|
4133
4246
|
if (items.length <= 1) return items[0]?.text || "";
|
|
4134
4247
|
const sorted = sortLineByX([...items]);
|
|
4135
4248
|
const isEvenSpaced = detectEvenSpacedItems(sorted);
|
|
4249
|
+
const hangulLine = sorted.some((it) => /[가-힣]/.test(it.text));
|
|
4136
4250
|
let result = sorted[0].text;
|
|
4137
4251
|
for (let i = 1; i < sorted.length; i++) {
|
|
4138
4252
|
const gap = sorted[i].x - (sorted[i - 1].x + sorted[i - 1].w);
|
|
@@ -4147,7 +4261,7 @@ function mergeLineSimple(items) {
|
|
|
4147
4261
|
result += sorted[i].text;
|
|
4148
4262
|
continue;
|
|
4149
4263
|
}
|
|
4150
|
-
if (isCjkLatinAutospace(sorted[i - 1].text, sorted[i].text, gap, avgFs)) {
|
|
4264
|
+
if (isCjkLatinAutospace(sorted[i - 1].text, sorted[i].text, gap, avgFs, hangulLine)) {
|
|
4151
4265
|
result += sorted[i].text;
|
|
4152
4266
|
continue;
|
|
4153
4267
|
}
|
|
@@ -4313,11 +4427,12 @@ function clusterCellLines(items) {
|
|
|
4313
4427
|
}
|
|
4314
4428
|
return lines.sort((a, b) => b.top - a.top).map(({ items: line }) => {
|
|
4315
4429
|
line.sort((a, b) => a.x - b.x);
|
|
4430
|
+
const hangulLine = line.some((it) => /[가-힣]/.test(it.text));
|
|
4316
4431
|
let s = line[0].text;
|
|
4317
4432
|
for (let i = 1; i < line.length; i++) {
|
|
4318
4433
|
const gap = line[i].x - (line[i - 1].x + line[i - 1].w);
|
|
4319
4434
|
const fs = (line[i].fontSize + line[i - 1].fontSize) / 2;
|
|
4320
|
-
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;
|
|
4321
4436
|
}
|
|
4322
4437
|
const last = line.reduce((a, b) => b.x + b.w > a.x + a.w ? b : a);
|
|
4323
4438
|
return {
|
|
@@ -10004,6 +10119,7 @@ export {
|
|
|
10004
10119
|
gapGlyphs,
|
|
10005
10120
|
ringBullet,
|
|
10006
10121
|
dashRatio,
|
|
10122
|
+
leadingRing,
|
|
10007
10123
|
discAt,
|
|
10008
10124
|
serifOne,
|
|
10009
10125
|
starRun,
|
|
@@ -10066,4 +10182,4 @@ export {
|
|
|
10066
10182
|
UNRULED_REGION_TABLES,
|
|
10067
10183
|
mergeOcrImageRegions
|
|
10068
10184
|
};
|
|
10069
|
-
//# sourceMappingURL=chunk-
|
|
10185
|
+
//# sourceMappingURL=chunk-37JRATLZ.js.map
|