kordoc 4.1.0 → 4.2.0
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 +25 -5
- package/dist/{-AS4IABL2.js → -SXQIZHYA.js} +10 -9
- package/dist/{parser-PEOYBXBO.js → chunk-26AJJCFF.js} +1339 -2023
- package/dist/chunk-26AJJCFF.js.map +1 -0
- package/dist/{parser-XX4QTDFQ.js → chunk-4JPPLIIV.js} +1337 -2019
- package/dist/chunk-4JPPLIIV.js.map +1 -0
- package/dist/chunk-4VNLZ2GZ.js +13 -0
- package/dist/chunk-4VNLZ2GZ.js.map +1 -0
- package/dist/{chunk-37HJHCPA.js → chunk-6SHO3BNV.js} +3 -3
- package/dist/{chunk-UOO7LSDG.js → chunk-7FCNOKOR.js} +1 -9
- package/dist/chunk-7FCNOKOR.js.map +1 -0
- package/dist/{chunk-SSTK6IKK.js → chunk-CMN3SYZ3.js} +14 -5
- package/dist/chunk-CMN3SYZ3.js.map +1 -0
- package/dist/{chunk-F2ZU3IZG.js → chunk-ELOV2GIJ.js} +2 -2
- package/dist/chunk-F2HYH62H.cjs +130 -0
- package/dist/chunk-F2HYH62H.cjs.map +1 -0
- package/dist/{chunk-O5VS7RIR.js → chunk-FSXLSHCW.js} +3 -3
- package/dist/{chunk-O5VS7RIR.js.map → chunk-FSXLSHCW.js.map} +1 -1
- package/dist/chunk-GEPINOL6.js +83 -0
- package/dist/chunk-GEPINOL6.js.map +1 -0
- package/dist/chunk-H7OWEYH2.cjs +243 -0
- package/dist/chunk-H7OWEYH2.cjs.map +1 -0
- package/dist/{chunk-L2XQQTOY.js → chunk-IGGRLWT5.js} +126 -46
- package/dist/chunk-IGGRLWT5.js.map +1 -0
- package/dist/chunk-J2RZ444H.js +243 -0
- package/dist/chunk-J2RZ444H.js.map +1 -0
- package/dist/chunk-JP5YH3Z4.js +130 -0
- package/dist/chunk-JP5YH3Z4.js.map +1 -0
- package/dist/{parser-N4A7UGDK.cjs → chunk-LHROM2BO.cjs} +1300 -1985
- package/dist/chunk-LHROM2BO.cjs.map +1 -0
- package/dist/chunk-NNDVFNMJ.js +246 -0
- package/dist/chunk-NNDVFNMJ.js.map +1 -0
- package/dist/{chunk-WO52HVQJ.js → chunk-PLIY23LY.js} +2 -2
- package/dist/{chunk-GQVSHGG4.js → chunk-V6U6YS5B.js} +2 -2
- package/dist/{chunk-4KI23VHA.js → chunk-WF2E5P2G.js} +16 -130
- package/dist/chunk-WF2E5P2G.js.map +1 -0
- package/dist/{chunk-AX2R5Q2N.js → chunk-WQLHPOMJ.js} +3 -3
- package/dist/{chunk-37VKMUST.cjs → chunk-XTCT6KQ5.cjs} +34 -148
- package/dist/chunk-XTCT6KQ5.cjs.map +1 -0
- package/dist/chunks-ZQEFAZNC.js +10 -0
- package/dist/cli.js +76 -19
- package/dist/cli.js.map +1 -1
- package/dist/{formula-RXVSQPXI.js → formula-KSNAEBZ2.js} +23 -232
- package/dist/formula-KSNAEBZ2.js.map +1 -0
- package/dist/{formula-5NKVS2LR.cjs → formula-SB3NHDUM.cjs} +30 -240
- package/dist/formula-SB3NHDUM.cjs.map +1 -0
- package/dist/{formula-JCNF43NE.js → formula-SXC6LRRC.js} +23 -233
- package/dist/formula-SXC6LRRC.js.map +1 -0
- package/dist/index.cjs +527 -447
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +129 -49
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +21 -19
- package/dist/mcp.js.map +1 -1
- package/dist/models-KA4GLQK5.js +25 -0
- package/dist/parser-ND2YGQZR.js +800 -0
- package/dist/parser-ND2YGQZR.js.map +1 -0
- package/dist/parser-RBZHA6SY.js +804 -0
- package/dist/parser-RBZHA6SY.js.map +1 -0
- package/dist/parser-WDZOMDG4.cjs +803 -0
- package/dist/parser-WDZOMDG4.cjs.map +1 -0
- package/dist/pdf-ocr-2Z7VZIFI.cjs +439 -0
- package/dist/pdf-ocr-2Z7VZIFI.cjs.map +1 -0
- package/dist/pdf-ocr-FJFXFADQ.js +438 -0
- package/dist/pdf-ocr-FJFXFADQ.js.map +1 -0
- package/dist/pdf-ocr-VYE4DHD4.js +386 -0
- package/dist/pdf-ocr-VYE4DHD4.js.map +1 -0
- package/dist/{profile-io-PLDQFPJA.js → profile-io-TWHDIVPL.js} +3 -3
- package/dist/{rasterize-WWNQLKYW.js → rasterize-W2NEZUSW.js} +2 -2
- package/dist/render-4MG5QUDG.js +10 -0
- package/dist/seal-D2QNXJVO.js +10 -0
- package/dist/seal-D2QNXJVO.js.map +1 -0
- package/dist/{watch-SFHXZALC.js → watch-VWXJZT2R.js} +11 -10
- package/dist/watch-VWXJZT2R.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-37VKMUST.cjs.map +0 -1
- package/dist/chunk-4KI23VHA.js.map +0 -1
- package/dist/chunk-L2XQQTOY.js.map +0 -1
- package/dist/chunk-SSTK6IKK.js.map +0 -1
- package/dist/chunk-UOO7LSDG.js.map +0 -1
- package/dist/chunks-WVMGF7JL.js +0 -10
- package/dist/formula-5NKVS2LR.cjs.map +0 -1
- package/dist/formula-JCNF43NE.js.map +0 -1
- package/dist/formula-RXVSQPXI.js.map +0 -1
- package/dist/parser-N4A7UGDK.cjs.map +0 -1
- package/dist/parser-PEOYBXBO.js.map +0 -1
- package/dist/parser-XX4QTDFQ.js.map +0 -1
- package/dist/provider-4FAYHJ6N.cjs +0 -39
- package/dist/provider-4FAYHJ6N.cjs.map +0 -1
- package/dist/provider-C6IOGIS5.js +0 -37
- package/dist/provider-C6IOGIS5.js.map +0 -1
- package/dist/provider-UIBW2MIH.js +0 -39
- package/dist/provider-UIBW2MIH.js.map +0 -1
- package/dist/render-T7S6H6AN.js +0 -10
- package/dist/seal-7PTL6MXH.js +0 -10
- package/dist/watch-SFHXZALC.js.map +0 -1
- /package/dist/{-AS4IABL2.js.map → -SXQIZHYA.js.map} +0 -0
- /package/dist/{chunk-37HJHCPA.js.map → chunk-6SHO3BNV.js.map} +0 -0
- /package/dist/{chunk-F2ZU3IZG.js.map → chunk-ELOV2GIJ.js.map} +0 -0
- /package/dist/{chunk-WO52HVQJ.js.map → chunk-PLIY23LY.js.map} +0 -0
- /package/dist/{chunk-GQVSHGG4.js.map → chunk-V6U6YS5B.js.map} +0 -0
- /package/dist/{chunk-AX2R5Q2N.js.map → chunk-WQLHPOMJ.js.map} +0 -0
- /package/dist/{chunks-WVMGF7JL.js.map → chunks-ZQEFAZNC.js.map} +0 -0
- /package/dist/{profile-io-PLDQFPJA.js.map → models-KA4GLQK5.js.map} +0 -0
- /package/dist/{render-T7S6H6AN.js.map → profile-io-TWHDIVPL.js.map} +0 -0
- /package/dist/{rasterize-WWNQLKYW.js.map → rasterize-W2NEZUSW.js.map} +0 -0
- /package/dist/{seal-7PTL6MXH.js.map → render-4MG5QUDG.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -134,8 +134,12 @@ interface ParseOptions {
|
|
|
134
134
|
* PDF: 정확한 페이지 단위. HWP/HWPX: 섹션 단위 근사치.
|
|
135
135
|
*/
|
|
136
136
|
pages?: number[] | string;
|
|
137
|
-
/** 이미지 기반 PDF
|
|
138
|
-
|
|
137
|
+
/** 이미지 기반 PDF OCR (선택).
|
|
138
|
+
* - `true`: 내장 엔진(PP-OCRv5 korean, ~18MB 자동 다운로드)으로 OCR 필요 판정
|
|
139
|
+
* 페이지만 인식 (스캔 페이지·글꼴 매핑 깨진 페이지). 정상 페이지는 파싱 결과 유지.
|
|
140
|
+
* - `"force"`: 전 페이지를 내장 엔진으로 강제 OCR.
|
|
141
|
+
* - 함수: 사용자 제공 OcrProvider (Claude Vision·Tesseract 등) — 판정은 `true`와 동일. */
|
|
142
|
+
ocr?: boolean | "force" | OcrProvider;
|
|
139
143
|
/** 진행률 콜백 — current: 현재 페이지/섹션, total: 전체 수 */
|
|
140
144
|
onProgress?: (current: number, total: number) => void;
|
|
141
145
|
/** PDF 머리글/바닥글 자동 제거 */
|
|
@@ -190,7 +194,7 @@ interface ParseWarning {
|
|
|
190
194
|
/** 구조화된 경고 코드 */
|
|
191
195
|
code: WarningCode;
|
|
192
196
|
}
|
|
193
|
-
type WarningCode = "SKIPPED_IMAGE" | "SKIPPED_OLE" | "TRUNCATED_TABLE" | "OCR_FALLBACK" | "UNSUPPORTED_ELEMENT" | "BROKEN_ZIP_RECOVERY" | "HIDDEN_TEXT_FILTERED" | "MALFORMED_XML" | "PARTIAL_PARSE" | "LENIENT_CFB_RECOVERY" | "NEEDS_OCR" | "COM_EMPTY" | "DRM_COM_FALLBACK";
|
|
197
|
+
type WarningCode = "SKIPPED_IMAGE" | "SKIPPED_OLE" | "TRUNCATED_TABLE" | "OCR_FALLBACK" | "UNSUPPORTED_ELEMENT" | "BROKEN_ZIP_RECOVERY" | "HIDDEN_TEXT_FILTERED" | "MALFORMED_XML" | "PARTIAL_PARSE" | "LENIENT_CFB_RECOVERY" | "NEEDS_OCR" | "OCR_FAILED" | "OCR_APPLIED" | "COM_EMPTY" | "DRM_COM_FALLBACK";
|
|
194
198
|
/** 문서 구조 (헤딩 트리) */
|
|
195
199
|
interface OutlineItem {
|
|
196
200
|
level: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -134,8 +134,12 @@ interface ParseOptions {
|
|
|
134
134
|
* PDF: 정확한 페이지 단위. HWP/HWPX: 섹션 단위 근사치.
|
|
135
135
|
*/
|
|
136
136
|
pages?: number[] | string;
|
|
137
|
-
/** 이미지 기반 PDF
|
|
138
|
-
|
|
137
|
+
/** 이미지 기반 PDF OCR (선택).
|
|
138
|
+
* - `true`: 내장 엔진(PP-OCRv5 korean, ~18MB 자동 다운로드)으로 OCR 필요 판정
|
|
139
|
+
* 페이지만 인식 (스캔 페이지·글꼴 매핑 깨진 페이지). 정상 페이지는 파싱 결과 유지.
|
|
140
|
+
* - `"force"`: 전 페이지를 내장 엔진으로 강제 OCR.
|
|
141
|
+
* - 함수: 사용자 제공 OcrProvider (Claude Vision·Tesseract 등) — 판정은 `true`와 동일. */
|
|
142
|
+
ocr?: boolean | "force" | OcrProvider;
|
|
139
143
|
/** 진행률 콜백 — current: 현재 페이지/섹션, total: 전체 수 */
|
|
140
144
|
onProgress?: (current: number, total: number) => void;
|
|
141
145
|
/** PDF 머리글/바닥글 자동 제거 */
|
|
@@ -190,7 +194,7 @@ interface ParseWarning {
|
|
|
190
194
|
/** 구조화된 경고 코드 */
|
|
191
195
|
code: WarningCode;
|
|
192
196
|
}
|
|
193
|
-
type WarningCode = "SKIPPED_IMAGE" | "SKIPPED_OLE" | "TRUNCATED_TABLE" | "OCR_FALLBACK" | "UNSUPPORTED_ELEMENT" | "BROKEN_ZIP_RECOVERY" | "HIDDEN_TEXT_FILTERED" | "MALFORMED_XML" | "PARTIAL_PARSE" | "LENIENT_CFB_RECOVERY" | "NEEDS_OCR" | "COM_EMPTY" | "DRM_COM_FALLBACK";
|
|
197
|
+
type WarningCode = "SKIPPED_IMAGE" | "SKIPPED_OLE" | "TRUNCATED_TABLE" | "OCR_FALLBACK" | "UNSUPPORTED_ELEMENT" | "BROKEN_ZIP_RECOVERY" | "HIDDEN_TEXT_FILTERED" | "MALFORMED_XML" | "PARTIAL_PARSE" | "LENIENT_CFB_RECOVERY" | "NEEDS_OCR" | "OCR_FAILED" | "OCR_APPLIED" | "COM_EMPTY" | "DRM_COM_FALLBACK";
|
|
194
198
|
/** 문서 구조 (헤딩 트리) */
|
|
195
199
|
interface OutlineItem {
|
|
196
200
|
level: number;
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
|
-
HEADING_RATIO_H1,
|
|
3
|
-
HEADING_RATIO_H2,
|
|
4
|
-
HEADING_RATIO_H3,
|
|
5
|
-
KordocError,
|
|
6
2
|
MAX_COLS,
|
|
7
3
|
MAX_ROWS,
|
|
8
|
-
VERSION,
|
|
9
4
|
blocksToMarkdown,
|
|
10
5
|
buildTable,
|
|
11
|
-
classifyError,
|
|
12
|
-
compareSectionPaths,
|
|
13
6
|
convertTableToText,
|
|
14
7
|
dedupeRunningHeaders,
|
|
15
8
|
flattenLayoutTables,
|
|
16
9
|
inlineImagesIntoMarkdown,
|
|
10
|
+
mapPuaText
|
|
11
|
+
} from "./chunk-WF2E5P2G.js";
|
|
12
|
+
import {
|
|
13
|
+
parsePageRange
|
|
14
|
+
} from "./chunk-GE43BE46.js";
|
|
15
|
+
import {
|
|
16
|
+
HEADING_RATIO_H1,
|
|
17
|
+
HEADING_RATIO_H2,
|
|
18
|
+
HEADING_RATIO_H3,
|
|
19
|
+
KordocError,
|
|
20
|
+
VERSION,
|
|
21
|
+
classifyError,
|
|
22
|
+
compareSectionPaths,
|
|
17
23
|
isPathTraversal,
|
|
18
|
-
mapPuaText,
|
|
19
24
|
normalizeSectionHref,
|
|
20
25
|
precheckZipSize,
|
|
21
26
|
sanitizeError,
|
|
22
27
|
sanitizeHref,
|
|
23
28
|
stripDtd,
|
|
24
29
|
toArrayBuffer
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import {
|
|
27
|
-
parsePageRange
|
|
28
|
-
} from "./chunk-GE43BE46.js";
|
|
30
|
+
} from "./chunk-JP5YH3Z4.js";
|
|
29
31
|
|
|
30
32
|
// src/index.ts
|
|
31
33
|
import { readFile } from "fs/promises";
|
|
@@ -2232,6 +2234,19 @@ function findKordocMarkedCell(el, depth) {
|
|
|
2232
2234
|
}
|
|
2233
2235
|
return null;
|
|
2234
2236
|
}
|
|
2237
|
+
function hasPageAutoNum(el, depth = 0) {
|
|
2238
|
+
if (depth > 10) return false;
|
|
2239
|
+
const children = el.childNodes;
|
|
2240
|
+
if (!children) return false;
|
|
2241
|
+
for (let i = 0; i < children.length; i++) {
|
|
2242
|
+
const ch = children[i];
|
|
2243
|
+
if (ch.nodeType !== 1) continue;
|
|
2244
|
+
const tag = (ch.tagName || ch.localName || "").replace(/^[^:]+:/, "");
|
|
2245
|
+
if (tag === "autoNum" && ch.getAttribute?.("numType") === "PAGE") return true;
|
|
2246
|
+
if (hasPageAutoNum(ch, depth + 1)) return true;
|
|
2247
|
+
}
|
|
2248
|
+
return false;
|
|
2249
|
+
}
|
|
2235
2250
|
function collectSubListText(el, ctx, depth = 0) {
|
|
2236
2251
|
if (depth > 10) return "";
|
|
2237
2252
|
const parts = [];
|
|
@@ -2410,6 +2425,22 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2410
2425
|
let href;
|
|
2411
2426
|
let footnote;
|
|
2412
2427
|
let charPrId;
|
|
2428
|
+
const linkRanges = [];
|
|
2429
|
+
const openFields = [];
|
|
2430
|
+
const onFieldBegin = (el) => {
|
|
2431
|
+
const url = extractHyperlinkHref(el);
|
|
2432
|
+
if (url) {
|
|
2433
|
+
linkRanges.push({ url, start: text.length });
|
|
2434
|
+
openFields.push({ rangeIdx: linkRanges.length - 1 });
|
|
2435
|
+
if (!href) href = url;
|
|
2436
|
+
} else {
|
|
2437
|
+
openFields.push({});
|
|
2438
|
+
}
|
|
2439
|
+
};
|
|
2440
|
+
const onFieldEnd = () => {
|
|
2441
|
+
const open = openFields.pop();
|
|
2442
|
+
if (open?.rangeIdx !== void 0) linkRanges[open.rangeIdx].end = text.length;
|
|
2443
|
+
};
|
|
2413
2444
|
const handleCtrl = (ctrlEl) => {
|
|
2414
2445
|
const kids2 = ctrlEl.childNodes;
|
|
2415
2446
|
if (!kids2) return;
|
|
@@ -2419,10 +2450,13 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2419
2450
|
const ktag = (k.tagName || k.localName || "").replace(/^[^:]+:/, "");
|
|
2420
2451
|
switch (ktag) {
|
|
2421
2452
|
// 머리말/꼬리말 — 문서당 1회 수집, 본문 앞/뒤 배치
|
|
2453
|
+
// 페이지 번호 크롬(autoNum PAGE + 문자 없는 잔여 텍스트, 예: "- 1 -")은 본문 정보가
|
|
2454
|
+
// 아니므로 방출하지 않는다
|
|
2422
2455
|
case "header":
|
|
2423
2456
|
case "footer": {
|
|
2424
2457
|
if (!ctx) break;
|
|
2425
2458
|
const t = collectSubListText(k, ctx);
|
|
2459
|
+
if (t && hasPageAutoNum(k) && !/\p{L}/u.test(t)) break;
|
|
2426
2460
|
if (t) {
|
|
2427
2461
|
const bucket = ktag === "header" ? ctx.shared.pageText.headers : ctx.shared.pageText.footers;
|
|
2428
2462
|
if (!bucket.includes(t)) bucket.push(t);
|
|
@@ -2436,13 +2470,12 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2436
2470
|
if (noteText) footnote = (footnote ? footnote + "; " : "") + noteText;
|
|
2437
2471
|
break;
|
|
2438
2472
|
}
|
|
2439
|
-
// 하이퍼링크 — fieldBegin type=HYPERLINK의 Path 파라미터
|
|
2440
|
-
case "fieldBegin":
|
|
2441
|
-
|
|
2442
|
-
if (url && !href) href = url;
|
|
2473
|
+
// 하이퍼링크 — fieldBegin type=HYPERLINK의 Path 파라미터 (extent 오프셋 추적)
|
|
2474
|
+
case "fieldBegin":
|
|
2475
|
+
onFieldBegin(k);
|
|
2443
2476
|
break;
|
|
2444
|
-
}
|
|
2445
2477
|
case "fieldEnd":
|
|
2478
|
+
onFieldEnd();
|
|
2446
2479
|
break;
|
|
2447
2480
|
// 변경추적 — 삭제 구간(deleteBegin~End)의 텍스트는 출력 제외 (최종본 상태 재현)
|
|
2448
2481
|
case "deleteBegin":
|
|
@@ -2555,12 +2588,10 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2555
2588
|
case "ctrl":
|
|
2556
2589
|
handleCtrl(child);
|
|
2557
2590
|
break;
|
|
2558
|
-
// run 직계 fieldBegin (비표준 경로) — 하이퍼링크 URL
|
|
2559
|
-
case "fieldBegin":
|
|
2560
|
-
|
|
2561
|
-
if (url && !href) href = url;
|
|
2591
|
+
// run 직계 fieldBegin (비표준 경로) — 하이퍼링크 URL·extent 추적
|
|
2592
|
+
case "fieldBegin":
|
|
2593
|
+
onFieldBegin(child);
|
|
2562
2594
|
break;
|
|
2563
|
-
}
|
|
2564
2595
|
// run 직계 변경추적 마커 (비표준 경로)
|
|
2565
2596
|
case "deleteBegin":
|
|
2566
2597
|
if (ctx) ctx.shared.track.deleteDepth++;
|
|
@@ -2572,6 +2603,8 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2572
2603
|
case "insertEnd":
|
|
2573
2604
|
break;
|
|
2574
2605
|
case "fieldEnd":
|
|
2606
|
+
onFieldEnd();
|
|
2607
|
+
break;
|
|
2575
2608
|
case "parameters":
|
|
2576
2609
|
case "stringParam":
|
|
2577
2610
|
case "integerParam":
|
|
@@ -2620,6 +2653,18 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2620
2653
|
}
|
|
2621
2654
|
};
|
|
2622
2655
|
walk(para2);
|
|
2656
|
+
{
|
|
2657
|
+
const applied = [];
|
|
2658
|
+
const closed = linkRanges.filter((r) => r.end !== void 0 && r.end > r.start).sort((a, b) => b.start - a.start);
|
|
2659
|
+
for (const r of closed) {
|
|
2660
|
+
if (applied.some(([s, e]) => r.start < e && r.end > s)) continue;
|
|
2661
|
+
const anchor = text.slice(r.start, r.end);
|
|
2662
|
+
if (!anchor.trim() || /[\n\x1F\[\]]/.test(anchor)) continue;
|
|
2663
|
+
text = text.slice(0, r.start) + `[${anchor}](${r.url})` + text.slice(r.end);
|
|
2664
|
+
applied.push([r.start, r.end]);
|
|
2665
|
+
}
|
|
2666
|
+
if (applied.length) href = void 0;
|
|
2667
|
+
}
|
|
2623
2668
|
const leaderIdx = text.indexOf("");
|
|
2624
2669
|
if (leaderIdx >= 0) text = text.substring(0, leaderIdx);
|
|
2625
2670
|
let cleanText = text.replace(/[ \t]+/g, " ").trim();
|
|
@@ -17413,8 +17458,50 @@ function decodeJohab(ch) {
|
|
|
17413
17458
|
}
|
|
17414
17459
|
const hit = lookupSymbol(ch);
|
|
17415
17460
|
if (hit !== null) return hit;
|
|
17461
|
+
return JOHAB_UNMAPPED;
|
|
17462
|
+
}
|
|
17463
|
+
return decodeHwp3Extra(ch);
|
|
17464
|
+
}
|
|
17465
|
+
function decodeHwp3Extra(ch) {
|
|
17466
|
+
if (ch >= 13712 && ch <= 13721) return 8544 + (ch - 13712);
|
|
17467
|
+
if (ch >= 14055 && ch <= 14064) return 9312 + (ch - 14055);
|
|
17468
|
+
switch (ch) {
|
|
17469
|
+
case 129:
|
|
17470
|
+
return 8220;
|
|
17471
|
+
// 왼쪽 큰따옴표
|
|
17472
|
+
case 130:
|
|
17473
|
+
return 8221;
|
|
17474
|
+
// 오른쪽 큰따옴표
|
|
17475
|
+
case 12316:
|
|
17476
|
+
return 9473;
|
|
17477
|
+
// ━ 굵은 가로선 (rhwp: U+F080F, 표시값 직행)
|
|
17478
|
+
case 12349:
|
|
17479
|
+
return 9632;
|
|
17480
|
+
// ■ (rhwp: U+F0827, 표시값 직행)
|
|
17481
|
+
case 13158:
|
|
17482
|
+
return 9633;
|
|
17483
|
+
// □ 글머리 (rhwp: U+F03C5, 한컴 표시값 직행)
|
|
17484
|
+
case 13316:
|
|
17485
|
+
return 8228;
|
|
17486
|
+
// 한 점 리더
|
|
17487
|
+
case 13377:
|
|
17488
|
+
return 9632;
|
|
17489
|
+
// ■
|
|
17490
|
+
case 13382:
|
|
17491
|
+
return 8594;
|
|
17492
|
+
// → 오른쪽 화살표
|
|
17493
|
+
case 13793:
|
|
17494
|
+
return 9472;
|
|
17495
|
+
// ─ 상자 그리기 가로선
|
|
17496
|
+
case 13433:
|
|
17497
|
+
return 9655;
|
|
17498
|
+
// ▷
|
|
17499
|
+
case 13434:
|
|
17500
|
+
return 9654;
|
|
17501
|
+
// ▶
|
|
17502
|
+
default:
|
|
17503
|
+
return JOHAB_UNMAPPED;
|
|
17416
17504
|
}
|
|
17417
|
-
return JOHAB_UNMAPPED;
|
|
17418
17505
|
}
|
|
17419
17506
|
function decodeHcharString(bytes) {
|
|
17420
17507
|
let out = "";
|
|
@@ -17534,7 +17621,7 @@ var PARA_SHAPE_SIZE = 187;
|
|
|
17534
17621
|
var LINE_INFO_SIZE = 14;
|
|
17535
17622
|
var INLINE_CHAR_SHAPE_SIZE = 31;
|
|
17536
17623
|
var SIMPLE_CTRL = /* @__PURE__ */ new Map([
|
|
17537
|
-
[9, { extraBytes:
|
|
17624
|
+
[9, { extraBytes: 6, extraHchar: 3, emit: " " }],
|
|
17538
17625
|
[7, { extraBytes: 6, extraHchar: 3, emit: "\uFFFC" }],
|
|
17539
17626
|
[8, { extraBytes: 6, extraHchar: 3, emit: "\uFFFC" }],
|
|
17540
17627
|
[18, { extraBytes: 6, extraHchar: 3, emit: " " }],
|
|
@@ -17710,6 +17797,12 @@ function parseCharStream(reader, charCount, ctx) {
|
|
|
17710
17797
|
parseParagraphList2(reader, ctx);
|
|
17711
17798
|
break;
|
|
17712
17799
|
}
|
|
17800
|
+
case 5:
|
|
17801
|
+
if (headerVal1 > 0 && headerVal1 < 1e6) reader.skip(headerVal1);
|
|
17802
|
+
break;
|
|
17803
|
+
case 6:
|
|
17804
|
+
reader.skip(34);
|
|
17805
|
+
break;
|
|
17713
17806
|
case 29:
|
|
17714
17807
|
if (headerVal1 < 1e6) reader.skip(headerVal1);
|
|
17715
17808
|
break;
|
|
@@ -17987,7 +18080,7 @@ function parseWorksheet(xml, sharedStrings, dateXfs, date1904) {
|
|
|
17987
18080
|
}
|
|
17988
18081
|
return { grid, merges, maxRow, maxCol };
|
|
17989
18082
|
}
|
|
17990
|
-
function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
18083
|
+
function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex, keepAnchoredEmptyCols) {
|
|
17991
18084
|
const blocks = [];
|
|
17992
18085
|
if (sheetName) {
|
|
17993
18086
|
blocks.push({
|
|
@@ -18039,7 +18132,7 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
18039
18132
|
cellRows.push(row);
|
|
18040
18133
|
}
|
|
18041
18134
|
if (cellRows.length > 0) {
|
|
18042
|
-
const table2 = buildTable(cellRows);
|
|
18135
|
+
const table2 = buildTable(cellRows, { keepAnchoredEmptyCols });
|
|
18043
18136
|
if (table2.rows > 0) {
|
|
18044
18137
|
blocks.push({ type: "table", table: table2, pageNumber: sheetIndex + 1 });
|
|
18045
18138
|
}
|
|
@@ -18109,7 +18202,7 @@ async function parseXlsxDocument(buffer, options) {
|
|
|
18109
18202
|
try {
|
|
18110
18203
|
const sheetXml = await sheetFile.async("text");
|
|
18111
18204
|
const { grid, merges, maxRow, maxCol } = parseWorksheet(sheetXml, sharedStrings, dateXfs, date1904);
|
|
18112
|
-
const sheetBlocks = sheetToBlocks(sheet.name, grid, merges, maxRow, maxCol, i);
|
|
18205
|
+
const sheetBlocks = sheetToBlocks(sheet.name, grid, merges, maxRow, maxCol, i, options?.keepTrailingEmptyCols);
|
|
18113
18206
|
blocks.push(...sheetBlocks);
|
|
18114
18207
|
} catch (err) {
|
|
18115
18208
|
warnings.push({
|
|
@@ -18658,7 +18751,7 @@ function cellValueToText(v) {
|
|
|
18658
18751
|
if (typeof v === "boolean") return v ? "TRUE" : "FALSE";
|
|
18659
18752
|
return v;
|
|
18660
18753
|
}
|
|
18661
|
-
function sheetToBlocks2(sheetName, sheet, sheetIndex) {
|
|
18754
|
+
function sheetToBlocks2(sheetName, sheet, sheetIndex, keepAnchoredEmptyCols) {
|
|
18662
18755
|
const blocks = [];
|
|
18663
18756
|
if (sheetName) {
|
|
18664
18757
|
blocks.push({
|
|
@@ -18731,7 +18824,7 @@ function sheetToBlocks2(sheetName, sheet, sheetIndex) {
|
|
|
18731
18824
|
cellRows.push(row);
|
|
18732
18825
|
}
|
|
18733
18826
|
if (cellRows.length > 0) {
|
|
18734
|
-
const table2 = buildTable(cellRows);
|
|
18827
|
+
const table2 = buildTable(cellRows, { keepAnchoredEmptyCols });
|
|
18735
18828
|
if (table2.rows > 0) {
|
|
18736
18829
|
blocks.push({ type: "table", table: table2, pageNumber: sheetIndex + 1 });
|
|
18737
18830
|
}
|
|
@@ -18812,7 +18905,7 @@ async function parseXlsDocument(buffer, options) {
|
|
|
18812
18905
|
}
|
|
18813
18906
|
try {
|
|
18814
18907
|
const { sheet } = extractSheetCells(records, bofIdx, globals.sst, convertNum);
|
|
18815
|
-
const blocks = sheetToBlocks2(meta.name, sheet, i);
|
|
18908
|
+
const blocks = sheetToBlocks2(meta.name, sheet, i, options?.keepTrailingEmptyCols);
|
|
18816
18909
|
allBlocks.push(...blocks);
|
|
18817
18910
|
} catch (e) {
|
|
18818
18911
|
warnings.push({
|
|
@@ -20033,8 +20126,8 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings, keep) {
|
|
|
20033
20126
|
for (let j = 0; j < rowCells.length; j++) {
|
|
20034
20127
|
const cellEl = rowCells[j];
|
|
20035
20128
|
if (cellEl.nodeType !== 1 || localName(cellEl) !== "CELL") continue;
|
|
20036
|
-
const colAddr = parseInt(cellEl.getAttribute("ColAddr") ?? "0", 10);
|
|
20037
|
-
const rowAddr = parseInt(cellEl.getAttribute("RowAddr") ?? "0", 10);
|
|
20129
|
+
const colAddr = parseInt(cellEl.getAttribute("ColAddr") ?? "0", 10) || 0;
|
|
20130
|
+
const rowAddr = parseInt(cellEl.getAttribute("RowAddr") ?? "0", 10) || 0;
|
|
20038
20131
|
const colSpan = Math.min(Math.max(1, parseInt(cellEl.getAttribute("ColSpan") ?? "1", 10) || 1), MAX_TABLE_COLS);
|
|
20039
20132
|
const rowSpan = Math.min(Math.max(1, parseInt(cellEl.getAttribute("RowSpan") ?? "1", 10) || 1), MAX_TABLE_ROWS);
|
|
20040
20133
|
const cellText = extractCellText(cellEl);
|
|
@@ -20042,24 +20135,11 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings, keep) {
|
|
|
20042
20135
|
}
|
|
20043
20136
|
}
|
|
20044
20137
|
if (cells.length === 0) return;
|
|
20045
|
-
const
|
|
20138
|
+
const cellRows = Array.from({ length: rowCount }, () => []);
|
|
20046
20139
|
for (const cell2 of cells) {
|
|
20047
|
-
const r = cell2.rowAddr ?? 0;
|
|
20048
|
-
|
|
20049
|
-
if (isNaN(r) || isNaN(c) || r >= rowCount || c >= colCount) continue;
|
|
20050
|
-
grid[r][c] = cell2;
|
|
20051
|
-
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
20052
|
-
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
20053
|
-
if (dr === 0 && dc === 0) continue;
|
|
20054
|
-
if (r + dr < rowCount && c + dc < colCount) {
|
|
20055
|
-
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
20056
|
-
}
|
|
20057
|
-
}
|
|
20058
|
-
}
|
|
20140
|
+
const r = Math.min(Math.max(cell2.rowAddr ?? 0, 0), rowCount - 1);
|
|
20141
|
+
cellRows[r].push(cell2);
|
|
20059
20142
|
}
|
|
20060
|
-
const cellRows = grid.map(
|
|
20061
|
-
(row) => row.map((cell2) => cell2 ?? { text: "", colSpan: 1, rowSpan: 1 })
|
|
20062
|
-
);
|
|
20063
20143
|
const table2 = buildTable(cellRows, { keepAnchoredEmptyCols: keep });
|
|
20064
20144
|
const caption = extractShapeCaption(el);
|
|
20065
20145
|
if (caption.text && caption.before) {
|
|
@@ -30414,7 +30494,7 @@ async function parseHwp(buffer, options) {
|
|
|
30414
30494
|
async function parsePdf(buffer, options) {
|
|
30415
30495
|
let parsePdfDocument;
|
|
30416
30496
|
try {
|
|
30417
|
-
const mod = await import("./parser-
|
|
30497
|
+
const mod = await import("./parser-ND2YGQZR.js");
|
|
30418
30498
|
parsePdfDocument = mod.parsePdfDocument;
|
|
30419
30499
|
} catch {
|
|
30420
30500
|
return {
|