kordoc 3.8.0 → 3.8.1
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 +6 -1
- package/dist/{-ATVQYFSW.js → -LD4BZDDJ.js} +3 -3
- package/dist/{chunk-3R3YK7EM.js → chunk-IFYJFWD2.js} +2 -2
- package/dist/{chunk-SLKF72QF.js → chunk-KT2BCHXI.js} +690 -671
- package/dist/chunk-KT2BCHXI.js.map +1 -0
- package/dist/{chunk-ITJIALN5.cjs → chunk-LFCS3UVG.cjs} +2 -2
- package/dist/{chunk-ITJIALN5.cjs.map → chunk-LFCS3UVG.cjs.map} +1 -1
- package/dist/{chunk-QV25HMU7.js → chunk-PELBIL4K.js} +2 -2
- package/dist/cli.js +4 -4
- package/dist/index.cjs +1052 -1033
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +689 -670
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +3 -3
- package/dist/{parser-7G5F7PT2.js → parser-FFEBMLSH.js} +1830 -1803
- package/dist/parser-FFEBMLSH.js.map +1 -0
- package/dist/{parser-GUSJH44K.cjs → parser-IXK5V7YG.cjs} +1830 -1803
- package/dist/parser-IXK5V7YG.cjs.map +1 -0
- package/dist/{parser-DCK42RMA.js → parser-XEDROIM7.js} +1830 -1803
- package/dist/parser-XEDROIM7.js.map +1 -0
- package/dist/{watch-GVZESOCE.js → watch-MAWCDNFI.js} +3 -3
- package/package.json +2 -2
- package/dist/chunk-SLKF72QF.js.map +0 -1
- package/dist/parser-7G5F7PT2.js.map +0 -1
- package/dist/parser-DCK42RMA.js.map +0 -1
- package/dist/parser-GUSJH44K.cjs.map +0 -1
- /package/dist/{-ATVQYFSW.js.map → -LD4BZDDJ.js.map} +0 -0
- /package/dist/{chunk-3R3YK7EM.js.map → chunk-IFYJFWD2.js.map} +0 -0
- /package/dist/{chunk-QV25HMU7.js.map → chunk-PELBIL4K.js.map} +0 -0
- /package/dist/{watch-GVZESOCE.js.map → watch-MAWCDNFI.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
var
|
|
22
|
+
var _chunkLFCS3UVGcjs = require('./chunk-LFCS3UVG.cjs');
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
var _chunkDCZVOIEOcjs = require('./chunk-DCZVOIEO.cjs');
|
|
@@ -283,8 +283,6 @@ async function detectZipFormat(buffer) {
|
|
|
283
283
|
|
|
284
284
|
// src/hwpx/parser.ts
|
|
285
285
|
|
|
286
|
-
var _zlib = require('zlib');
|
|
287
|
-
var _xmldom = require('@xmldom/xmldom');
|
|
288
286
|
|
|
289
287
|
// src/hwpx/com-fallback.ts
|
|
290
288
|
var _child_process = require('child_process');
|
|
@@ -393,6 +391,245 @@ function comResultToParseResult(pages, pageCount, warnings) {
|
|
|
393
391
|
};
|
|
394
392
|
}
|
|
395
393
|
|
|
394
|
+
// src/hwpx/parser-shared.ts
|
|
395
|
+
var _xmldom = require('@xmldom/xmldom');
|
|
396
|
+
var MAX_DECOMPRESS_SIZE = 100 * 1024 * 1024;
|
|
397
|
+
var MAX_ZIP_ENTRIES = 500;
|
|
398
|
+
function clampSpan(val, max) {
|
|
399
|
+
return Math.max(1, Math.min(val, max));
|
|
400
|
+
}
|
|
401
|
+
var MAX_XML_DEPTH = 200;
|
|
402
|
+
function createSectionShared() {
|
|
403
|
+
return { numState: /* @__PURE__ */ new Map(), pageText: { headers: [], footers: [] }, track: { deleteDepth: 0, warned: false } };
|
|
404
|
+
}
|
|
405
|
+
function createXmlParser(warnings) {
|
|
406
|
+
return new (0, _xmldom.DOMParser)({
|
|
407
|
+
onError(level, msg2) {
|
|
408
|
+
if (level === "fatalError") throw new (0, _chunkLFCS3UVGcjs.KordocError)(`XML \uD30C\uC2F1 \uC2E4\uD328: ${msg2}`);
|
|
409
|
+
_optionalChain([warnings, 'optionalAccess', _3 => _3.push, 'call', _4 => _4({ code: "MALFORMED_XML", message: `XML ${level === "warn" ? "\uACBD\uACE0" : "\uC624\uB958"}: ${msg2}` })]);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
function applyPageText(blocks, shared) {
|
|
414
|
+
const { headers, footers } = shared.pageText;
|
|
415
|
+
if (headers.length > 0) {
|
|
416
|
+
blocks.unshift(...headers.map((t) => ({ type: "paragraph", text: t, pageNumber: 1 })));
|
|
417
|
+
}
|
|
418
|
+
if (footers.length > 0) {
|
|
419
|
+
blocks.push(...footers.map((t) => ({ type: "paragraph", text: t })));
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function findChildByLocalName(parent, name) {
|
|
423
|
+
const children = parent.childNodes;
|
|
424
|
+
if (!children) return null;
|
|
425
|
+
for (let i = 0; i < children.length; i++) {
|
|
426
|
+
const ch = children[i];
|
|
427
|
+
if (ch.nodeType !== 1) continue;
|
|
428
|
+
const tag = (ch.tagName || ch.localName || "").replace(/^[^:]+:/, "");
|
|
429
|
+
if (tag === name) return ch;
|
|
430
|
+
}
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
function extractTextFromNode(node) {
|
|
434
|
+
let result = "";
|
|
435
|
+
const children = node.childNodes;
|
|
436
|
+
if (!children) return result;
|
|
437
|
+
for (let i = 0; i < children.length; i++) {
|
|
438
|
+
const child = children[i];
|
|
439
|
+
if (child.nodeType === 3) result += child.textContent || "";
|
|
440
|
+
else if (child.nodeType === 1) result += extractTextFromNode(child);
|
|
441
|
+
}
|
|
442
|
+
return result.trim();
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// src/hwpx/styles.ts
|
|
446
|
+
async function extractHwpxStyles(zip, decompressed) {
|
|
447
|
+
const result = {
|
|
448
|
+
charProperties: /* @__PURE__ */ new Map(),
|
|
449
|
+
styles: /* @__PURE__ */ new Map(),
|
|
450
|
+
numberings: /* @__PURE__ */ new Map(),
|
|
451
|
+
bullets: /* @__PURE__ */ new Map(),
|
|
452
|
+
paraHeadings: /* @__PURE__ */ new Map()
|
|
453
|
+
};
|
|
454
|
+
const headerPaths = ["Contents/header.xml", "header.xml", "Contents/head.xml", "head.xml"];
|
|
455
|
+
for (const hp of headerPaths) {
|
|
456
|
+
const hpLower = hp.toLowerCase();
|
|
457
|
+
const file = zip.file(hp) || Object.values(zip.files).find((f) => f.name.toLowerCase() === hpLower) || null;
|
|
458
|
+
if (!file) continue;
|
|
459
|
+
try {
|
|
460
|
+
const xml = await file.async("text");
|
|
461
|
+
if (decompressed) {
|
|
462
|
+
decompressed.total += xml.length * 2;
|
|
463
|
+
if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
|
|
464
|
+
}
|
|
465
|
+
const parser = createXmlParser();
|
|
466
|
+
const doc = parser.parseFromString(_chunkLFCS3UVGcjs.stripDtd.call(void 0, xml), "text/xml");
|
|
467
|
+
if (!doc.documentElement) continue;
|
|
468
|
+
parseCharProperties(doc, result.charProperties);
|
|
469
|
+
parseStyleElements(doc, result.styles);
|
|
470
|
+
const domDoc = doc;
|
|
471
|
+
parseNumberings(domDoc, result.numberings);
|
|
472
|
+
parseBullets(domDoc, result.bullets);
|
|
473
|
+
parseParaHeadings(domDoc, result.paraHeadings);
|
|
474
|
+
break;
|
|
475
|
+
} catch (e5) {
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return result;
|
|
480
|
+
}
|
|
481
|
+
function parseCharProperties(doc, map) {
|
|
482
|
+
const tagNames = ["hh:charPr", "charPr", "hp:charPr"];
|
|
483
|
+
for (const tagName of tagNames) {
|
|
484
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
485
|
+
for (let i = 0; i < elements.length; i++) {
|
|
486
|
+
const el = elements[i];
|
|
487
|
+
const id = el.getAttribute("id") || el.getAttribute("IDRef") || "";
|
|
488
|
+
if (!id) continue;
|
|
489
|
+
const prop = {};
|
|
490
|
+
const height = el.getAttribute("height");
|
|
491
|
+
if (height) {
|
|
492
|
+
const parsedHeight = parseInt(height, 10);
|
|
493
|
+
if (!isNaN(parsedHeight) && parsedHeight > 0) {
|
|
494
|
+
prop.fontSize = parsedHeight / 100;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
const bold = el.getAttribute("bold");
|
|
498
|
+
if (bold === "true" || bold === "1") prop.bold = true;
|
|
499
|
+
const italic = el.getAttribute("italic");
|
|
500
|
+
if (italic === "true" || italic === "1") prop.italic = true;
|
|
501
|
+
const fontFaces = el.getElementsByTagName("*");
|
|
502
|
+
for (let j = 0; j < fontFaces.length; j++) {
|
|
503
|
+
const ff = fontFaces[j];
|
|
504
|
+
const localTag = (ff.tagName || "").replace(/^[^:]+:/, "");
|
|
505
|
+
if (localTag === "fontface" || localTag === "fontRef") {
|
|
506
|
+
const face = ff.getAttribute("face") || ff.getAttribute("FontFace");
|
|
507
|
+
if (face) {
|
|
508
|
+
prop.fontName = face;
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
map.set(id, prop);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
function parseStyleElements(doc, map) {
|
|
518
|
+
const tagNames = ["hh:style", "style", "hp:style"];
|
|
519
|
+
for (const tagName of tagNames) {
|
|
520
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
521
|
+
for (let i = 0; i < elements.length; i++) {
|
|
522
|
+
const el = elements[i];
|
|
523
|
+
const id = el.getAttribute("id") || el.getAttribute("IDRef") || String(i);
|
|
524
|
+
const name = el.getAttribute("name") || el.getAttribute("engName") || "";
|
|
525
|
+
const charPrId = el.getAttribute("charPrIDRef") || void 0;
|
|
526
|
+
const paraPrId = el.getAttribute("paraPrIDRef") || void 0;
|
|
527
|
+
map.set(id, { name, charPrId, paraPrId });
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
function parseNumberings(doc, map) {
|
|
532
|
+
const tagNames = ["hh:numbering", "numbering"];
|
|
533
|
+
for (const tagName of tagNames) {
|
|
534
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
535
|
+
for (let i = 0; i < elements.length; i++) {
|
|
536
|
+
const el = elements[i];
|
|
537
|
+
const id = el.getAttribute("id") || "";
|
|
538
|
+
if (!id) continue;
|
|
539
|
+
const def = { heads: /* @__PURE__ */ new Map() };
|
|
540
|
+
const children = el.childNodes;
|
|
541
|
+
for (let j = 0; j < children.length; j++) {
|
|
542
|
+
const ch = children[j];
|
|
543
|
+
if (ch.nodeType !== 1) continue;
|
|
544
|
+
const tag = (ch.tagName || ch.localName || "").replace(/^[^:]+:/, "");
|
|
545
|
+
if (tag !== "paraHead") continue;
|
|
546
|
+
const level = parseInt(ch.getAttribute("level") || "", 10);
|
|
547
|
+
if (isNaN(level) || level < 1 || level > 10) continue;
|
|
548
|
+
const start = parseInt(ch.getAttribute("start") || "1", 10);
|
|
549
|
+
def.heads.set(level, {
|
|
550
|
+
numFormat: ch.getAttribute("numFormat") || "DIGIT",
|
|
551
|
+
text: ch.textContent || "",
|
|
552
|
+
start: isNaN(start) ? 1 : start
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
if (def.heads.size > 0) map.set(id, def);
|
|
556
|
+
}
|
|
557
|
+
if (map.size > 0) break;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
function parseBullets(doc, map) {
|
|
561
|
+
const tagNames = ["hh:bullet", "bullet"];
|
|
562
|
+
for (const tagName of tagNames) {
|
|
563
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
564
|
+
for (let i = 0; i < elements.length; i++) {
|
|
565
|
+
const el = elements[i];
|
|
566
|
+
const id = el.getAttribute("id") || "";
|
|
567
|
+
const char = el.getAttribute("char") || "";
|
|
568
|
+
if (id && char) map.set(id, char);
|
|
569
|
+
}
|
|
570
|
+
if (map.size > 0) break;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
function parseParaHeadings(doc, map) {
|
|
574
|
+
const tagNames = ["hh:paraPr", "paraPr"];
|
|
575
|
+
for (const tagName of tagNames) {
|
|
576
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
577
|
+
for (let i = 0; i < elements.length; i++) {
|
|
578
|
+
const el = elements[i];
|
|
579
|
+
const id = el.getAttribute("id") || "";
|
|
580
|
+
if (!id) continue;
|
|
581
|
+
const heading = findChildByLocalName(el, "heading");
|
|
582
|
+
if (!heading) continue;
|
|
583
|
+
const type = heading.getAttribute("type") || "NONE";
|
|
584
|
+
if (type !== "NUMBER" && type !== "BULLET" && type !== "OUTLINE") continue;
|
|
585
|
+
const level = parseInt(heading.getAttribute("level") || "0", 10);
|
|
586
|
+
map.set(id, {
|
|
587
|
+
type,
|
|
588
|
+
idRef: heading.getAttribute("idRef") || "0",
|
|
589
|
+
level: isNaN(level) ? 0 : Math.max(0, Math.min(level, 9))
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
if (map.size > 0) break;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function detectHwpxHeadings(blocks, styleMap) {
|
|
596
|
+
if (blocks.some((b) => b.type === "heading")) return;
|
|
597
|
+
let baseFontSize = 0;
|
|
598
|
+
const sizeFreq = /* @__PURE__ */ new Map();
|
|
599
|
+
for (const b of blocks) {
|
|
600
|
+
if (_optionalChain([b, 'access', _5 => _5.style, 'optionalAccess', _6 => _6.fontSize])) {
|
|
601
|
+
sizeFreq.set(b.style.fontSize, (sizeFreq.get(b.style.fontSize) || 0) + 1);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
let maxCount = 0;
|
|
605
|
+
for (const [size, count] of sizeFreq) {
|
|
606
|
+
if (count > maxCount) {
|
|
607
|
+
maxCount = count;
|
|
608
|
+
baseFontSize = size;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
for (const block of blocks) {
|
|
612
|
+
if (block.type !== "paragraph" || !block.text) continue;
|
|
613
|
+
const text = block.text.trim();
|
|
614
|
+
if (text.length === 0 || text.length > 200 || /^\d+$/.test(text)) continue;
|
|
615
|
+
let level = 0;
|
|
616
|
+
if (baseFontSize > 0 && _optionalChain([block, 'access', _7 => _7.style, 'optionalAccess', _8 => _8.fontSize])) {
|
|
617
|
+
const ratio = block.style.fontSize / baseFontSize;
|
|
618
|
+
if (ratio >= _chunkLFCS3UVGcjs.HEADING_RATIO_H1) level = 1;
|
|
619
|
+
else if (ratio >= _chunkLFCS3UVGcjs.HEADING_RATIO_H2) level = 2;
|
|
620
|
+
else if (ratio >= _chunkLFCS3UVGcjs.HEADING_RATIO_H3) level = 3;
|
|
621
|
+
}
|
|
622
|
+
const compactText = text.replace(/\s+/g, "");
|
|
623
|
+
if (/^제\d+[조장절편]/.test(compactText) && text.length <= 50) {
|
|
624
|
+
if (level === 0) level = 3;
|
|
625
|
+
}
|
|
626
|
+
if (level > 0) {
|
|
627
|
+
block.type = "heading";
|
|
628
|
+
block.level = level;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
396
633
|
// src/hwpx/equation.ts
|
|
397
634
|
var CONVERT_MAP = {
|
|
398
635
|
TIMES: "\\times",
|
|
@@ -676,7 +913,7 @@ function findEnclosingBrackets(eqString, startIdx) {
|
|
|
676
913
|
try {
|
|
677
914
|
const [start, end] = findBrackets(eqString, idx, 1);
|
|
678
915
|
if (start === idx && end > startIdx) return [start, end];
|
|
679
|
-
} catch (
|
|
916
|
+
} catch (e6) {
|
|
680
917
|
return null;
|
|
681
918
|
}
|
|
682
919
|
return null;
|
|
@@ -695,7 +932,7 @@ function replaceFrac(eqString) {
|
|
|
695
932
|
const beforeFrac = eqString.slice(0, numStart);
|
|
696
933
|
const afterFrac = eqString.slice(cursor + hmlFrac.length);
|
|
697
934
|
eqString = beforeFrac + "\\frac" + numerator + afterFrac;
|
|
698
|
-
} catch (
|
|
935
|
+
} catch (e7) {
|
|
699
936
|
return eqString;
|
|
700
937
|
}
|
|
701
938
|
}
|
|
@@ -713,7 +950,7 @@ function replaceRootOf(eqString) {
|
|
|
713
950
|
const e1 = eqString.slice(elem1[0] + 1, elem1[1] - 1);
|
|
714
951
|
const e2 = eqString.slice(elem2[0] + 1, elem2[1] - 1);
|
|
715
952
|
eqString = eqString.slice(0, rootCursor) + "\\sqrt[" + e1 + "]{" + e2 + "}" + eqString.slice(elem2[1] + 1);
|
|
716
|
-
} catch (
|
|
953
|
+
} catch (e8) {
|
|
717
954
|
return eqString;
|
|
718
955
|
}
|
|
719
956
|
}
|
|
@@ -745,7 +982,7 @@ function replaceAllMatrix(eqString) {
|
|
|
745
982
|
afterMat = input.slice(eEnd);
|
|
746
983
|
}
|
|
747
984
|
input = beforeMat + matElem.begin + elem + matElem.end + afterMat;
|
|
748
|
-
} catch (
|
|
985
|
+
} catch (e9) {
|
|
749
986
|
return input;
|
|
750
987
|
}
|
|
751
988
|
}
|
|
@@ -769,7 +1006,7 @@ function replaceAllBar(eqString) {
|
|
|
769
1006
|
const beforeBar = input.slice(0, replaceStart);
|
|
770
1007
|
const afterBar = input.slice(replaceEnd);
|
|
771
1008
|
input = beforeBar + barElem + elem + afterBar;
|
|
772
|
-
} catch (
|
|
1009
|
+
} catch (e10) {
|
|
773
1010
|
return input;
|
|
774
1011
|
}
|
|
775
1012
|
}
|
|
@@ -793,7 +1030,7 @@ function replaceAllBrace(eqString) {
|
|
|
793
1030
|
const beforeBrace = input.slice(0, cursor);
|
|
794
1031
|
const afterBrace = input.slice(eEnd2);
|
|
795
1032
|
input = beforeBrace + braceElem + elem1 + "^" + elem2 + afterBrace;
|
|
796
|
-
} catch (
|
|
1033
|
+
} catch (e11) {
|
|
797
1034
|
return input;
|
|
798
1035
|
}
|
|
799
1036
|
}
|
|
@@ -832,173 +1069,7 @@ function hmlToLatex(hmlEqStr) {
|
|
|
832
1069
|
return out;
|
|
833
1070
|
}
|
|
834
1071
|
|
|
835
|
-
// src/hwpx/
|
|
836
|
-
var MAX_DECOMPRESS_SIZE = 100 * 1024 * 1024;
|
|
837
|
-
var MAX_ZIP_ENTRIES = 500;
|
|
838
|
-
function clampSpan(val, max) {
|
|
839
|
-
return Math.max(1, Math.min(val, max));
|
|
840
|
-
}
|
|
841
|
-
var MAX_XML_DEPTH = 200;
|
|
842
|
-
function createSectionShared() {
|
|
843
|
-
return { numState: /* @__PURE__ */ new Map(), pageText: { headers: [], footers: [] }, track: { deleteDepth: 0, warned: false } };
|
|
844
|
-
}
|
|
845
|
-
function createXmlParser(warnings) {
|
|
846
|
-
return new (0, _xmldom.DOMParser)({
|
|
847
|
-
onError(level, msg2) {
|
|
848
|
-
if (level === "fatalError") throw new (0, _chunkITJIALN5cjs.KordocError)(`XML \uD30C\uC2F1 \uC2E4\uD328: ${msg2}`);
|
|
849
|
-
_optionalChain([warnings, 'optionalAccess', _3 => _3.push, 'call', _4 => _4({ code: "MALFORMED_XML", message: `XML ${level === "warn" ? "\uACBD\uACE0" : "\uC624\uB958"}: ${msg2}` })]);
|
|
850
|
-
}
|
|
851
|
-
});
|
|
852
|
-
}
|
|
853
|
-
async function extractHwpxStyles(zip, decompressed) {
|
|
854
|
-
const result = {
|
|
855
|
-
charProperties: /* @__PURE__ */ new Map(),
|
|
856
|
-
styles: /* @__PURE__ */ new Map(),
|
|
857
|
-
numberings: /* @__PURE__ */ new Map(),
|
|
858
|
-
bullets: /* @__PURE__ */ new Map(),
|
|
859
|
-
paraHeadings: /* @__PURE__ */ new Map()
|
|
860
|
-
};
|
|
861
|
-
const headerPaths = ["Contents/header.xml", "header.xml", "Contents/head.xml", "head.xml"];
|
|
862
|
-
for (const hp of headerPaths) {
|
|
863
|
-
const hpLower = hp.toLowerCase();
|
|
864
|
-
const file = zip.file(hp) || Object.values(zip.files).find((f) => f.name.toLowerCase() === hpLower) || null;
|
|
865
|
-
if (!file) continue;
|
|
866
|
-
try {
|
|
867
|
-
const xml = await file.async("text");
|
|
868
|
-
if (decompressed) {
|
|
869
|
-
decompressed.total += xml.length * 2;
|
|
870
|
-
if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
|
|
871
|
-
}
|
|
872
|
-
const parser = createXmlParser();
|
|
873
|
-
const doc = parser.parseFromString(_chunkITJIALN5cjs.stripDtd.call(void 0, xml), "text/xml");
|
|
874
|
-
if (!doc.documentElement) continue;
|
|
875
|
-
parseCharProperties(doc, result.charProperties);
|
|
876
|
-
parseStyleElements(doc, result.styles);
|
|
877
|
-
const domDoc = doc;
|
|
878
|
-
parseNumberings(domDoc, result.numberings);
|
|
879
|
-
parseBullets(domDoc, result.bullets);
|
|
880
|
-
parseParaHeadings(domDoc, result.paraHeadings);
|
|
881
|
-
break;
|
|
882
|
-
} catch (e11) {
|
|
883
|
-
continue;
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
return result;
|
|
887
|
-
}
|
|
888
|
-
function parseCharProperties(doc, map) {
|
|
889
|
-
const tagNames = ["hh:charPr", "charPr", "hp:charPr"];
|
|
890
|
-
for (const tagName of tagNames) {
|
|
891
|
-
const elements = doc.getElementsByTagName(tagName);
|
|
892
|
-
for (let i = 0; i < elements.length; i++) {
|
|
893
|
-
const el = elements[i];
|
|
894
|
-
const id = el.getAttribute("id") || el.getAttribute("IDRef") || "";
|
|
895
|
-
if (!id) continue;
|
|
896
|
-
const prop = {};
|
|
897
|
-
const height = el.getAttribute("height");
|
|
898
|
-
if (height) {
|
|
899
|
-
const parsedHeight = parseInt(height, 10);
|
|
900
|
-
if (!isNaN(parsedHeight) && parsedHeight > 0) {
|
|
901
|
-
prop.fontSize = parsedHeight / 100;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
const bold = el.getAttribute("bold");
|
|
905
|
-
if (bold === "true" || bold === "1") prop.bold = true;
|
|
906
|
-
const italic = el.getAttribute("italic");
|
|
907
|
-
if (italic === "true" || italic === "1") prop.italic = true;
|
|
908
|
-
const fontFaces = el.getElementsByTagName("*");
|
|
909
|
-
for (let j = 0; j < fontFaces.length; j++) {
|
|
910
|
-
const ff = fontFaces[j];
|
|
911
|
-
const localTag = (ff.tagName || "").replace(/^[^:]+:/, "");
|
|
912
|
-
if (localTag === "fontface" || localTag === "fontRef") {
|
|
913
|
-
const face = ff.getAttribute("face") || ff.getAttribute("FontFace");
|
|
914
|
-
if (face) {
|
|
915
|
-
prop.fontName = face;
|
|
916
|
-
break;
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
map.set(id, prop);
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
function parseStyleElements(doc, map) {
|
|
925
|
-
const tagNames = ["hh:style", "style", "hp:style"];
|
|
926
|
-
for (const tagName of tagNames) {
|
|
927
|
-
const elements = doc.getElementsByTagName(tagName);
|
|
928
|
-
for (let i = 0; i < elements.length; i++) {
|
|
929
|
-
const el = elements[i];
|
|
930
|
-
const id = el.getAttribute("id") || el.getAttribute("IDRef") || String(i);
|
|
931
|
-
const name = el.getAttribute("name") || el.getAttribute("engName") || "";
|
|
932
|
-
const charPrId = el.getAttribute("charPrIDRef") || void 0;
|
|
933
|
-
const paraPrId = el.getAttribute("paraPrIDRef") || void 0;
|
|
934
|
-
map.set(id, { name, charPrId, paraPrId });
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
function parseNumberings(doc, map) {
|
|
939
|
-
const tagNames = ["hh:numbering", "numbering"];
|
|
940
|
-
for (const tagName of tagNames) {
|
|
941
|
-
const elements = doc.getElementsByTagName(tagName);
|
|
942
|
-
for (let i = 0; i < elements.length; i++) {
|
|
943
|
-
const el = elements[i];
|
|
944
|
-
const id = el.getAttribute("id") || "";
|
|
945
|
-
if (!id) continue;
|
|
946
|
-
const def = { heads: /* @__PURE__ */ new Map() };
|
|
947
|
-
const children = el.childNodes;
|
|
948
|
-
for (let j = 0; j < children.length; j++) {
|
|
949
|
-
const ch = children[j];
|
|
950
|
-
if (ch.nodeType !== 1) continue;
|
|
951
|
-
const tag = (ch.tagName || ch.localName || "").replace(/^[^:]+:/, "");
|
|
952
|
-
if (tag !== "paraHead") continue;
|
|
953
|
-
const level = parseInt(ch.getAttribute("level") || "", 10);
|
|
954
|
-
if (isNaN(level) || level < 1 || level > 10) continue;
|
|
955
|
-
const start = parseInt(ch.getAttribute("start") || "1", 10);
|
|
956
|
-
def.heads.set(level, {
|
|
957
|
-
numFormat: ch.getAttribute("numFormat") || "DIGIT",
|
|
958
|
-
text: ch.textContent || "",
|
|
959
|
-
start: isNaN(start) ? 1 : start
|
|
960
|
-
});
|
|
961
|
-
}
|
|
962
|
-
if (def.heads.size > 0) map.set(id, def);
|
|
963
|
-
}
|
|
964
|
-
if (map.size > 0) break;
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
function parseBullets(doc, map) {
|
|
968
|
-
const tagNames = ["hh:bullet", "bullet"];
|
|
969
|
-
for (const tagName of tagNames) {
|
|
970
|
-
const elements = doc.getElementsByTagName(tagName);
|
|
971
|
-
for (let i = 0; i < elements.length; i++) {
|
|
972
|
-
const el = elements[i];
|
|
973
|
-
const id = el.getAttribute("id") || "";
|
|
974
|
-
const char = el.getAttribute("char") || "";
|
|
975
|
-
if (id && char) map.set(id, char);
|
|
976
|
-
}
|
|
977
|
-
if (map.size > 0) break;
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
function parseParaHeadings(doc, map) {
|
|
981
|
-
const tagNames = ["hh:paraPr", "paraPr"];
|
|
982
|
-
for (const tagName of tagNames) {
|
|
983
|
-
const elements = doc.getElementsByTagName(tagName);
|
|
984
|
-
for (let i = 0; i < elements.length; i++) {
|
|
985
|
-
const el = elements[i];
|
|
986
|
-
const id = el.getAttribute("id") || "";
|
|
987
|
-
if (!id) continue;
|
|
988
|
-
const heading = findChildByLocalName(el, "heading");
|
|
989
|
-
if (!heading) continue;
|
|
990
|
-
const type = heading.getAttribute("type") || "NONE";
|
|
991
|
-
if (type !== "NUMBER" && type !== "BULLET" && type !== "OUTLINE") continue;
|
|
992
|
-
const level = parseInt(heading.getAttribute("level") || "0", 10);
|
|
993
|
-
map.set(id, {
|
|
994
|
-
type,
|
|
995
|
-
idRef: heading.getAttribute("idRef") || "0",
|
|
996
|
-
level: isNaN(level) ? 0 : Math.max(0, Math.min(level, 9))
|
|
997
|
-
});
|
|
998
|
-
}
|
|
999
|
-
if (map.size > 0) break;
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1072
|
+
// src/hwpx/para-heading.ts
|
|
1002
1073
|
var HANGUL_SYLLABLE_SEQ = "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC\uC544\uC790\uCC28\uCE74\uD0C0\uD30C\uD558";
|
|
1003
1074
|
var HANGUL_JAMO_SEQ = "\u3131\u3134\u3137\u3139\u3141\u3142\u3145\u3147\u3148\u314A\u314B\u314C\u314D\u314E";
|
|
1004
1075
|
function toRoman(n) {
|
|
@@ -1080,783 +1151,423 @@ function resolveParaHeading(paraEl, ctx) {
|
|
|
1080
1151
|
ctx.shared.numState.set(numId, counters);
|
|
1081
1152
|
}
|
|
1082
1153
|
const head = numDef.heads.get(level);
|
|
1083
|
-
counters[level] = counters[level] === 0 ? _nullishCoalesce(_optionalChain([head, 'optionalAccess',
|
|
1154
|
+
counters[level] = counters[level] === 0 ? _nullishCoalesce(_optionalChain([head, 'optionalAccess', _9 => _9.start]), () => ( 1)) : counters[level] + 1;
|
|
1084
1155
|
for (let l = level + 1; l <= 10; l++) counters[l] = 0;
|
|
1085
|
-
const fmtText = _optionalChain([head, 'optionalAccess',
|
|
1156
|
+
const fmtText = _optionalChain([head, 'optionalAccess', _10 => _10.text, 'optionalAccess', _11 => _11.trim, 'call', _12 => _12()]) || `^${level}.`;
|
|
1086
1157
|
const prefix = fmtText.replace(/\^(10|[1-9])/g, (_, d) => {
|
|
1087
1158
|
const lv = parseInt(d, 10);
|
|
1088
1159
|
const refHead = numDef.heads.get(lv);
|
|
1089
|
-
const n = counters[lv] || _optionalChain([refHead, 'optionalAccess',
|
|
1090
|
-
return formatHeadNumber(n, _optionalChain([refHead, 'optionalAccess',
|
|
1160
|
+
const n = counters[lv] || _optionalChain([refHead, 'optionalAccess', _13 => _13.start]) || 1;
|
|
1161
|
+
return formatHeadNumber(n, _optionalChain([refHead, 'optionalAccess', _14 => _14.numFormat]) || "DIGIT");
|
|
1091
1162
|
});
|
|
1092
1163
|
return { prefix, headingLevel };
|
|
1093
1164
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
if (pages.some((p) => p && p.trim().length > 0)) {
|
|
1113
|
-
return comResultToParseResult(pages, pageCount, warnings2);
|
|
1165
|
+
|
|
1166
|
+
// src/hwpx/table-build.ts
|
|
1167
|
+
function buildTableWithCellMeta(state) {
|
|
1168
|
+
const table = _chunkLFCS3UVGcjs.buildTable.call(void 0, state.rows);
|
|
1169
|
+
if (state.caption) table.caption = state.caption;
|
|
1170
|
+
const anchors = [];
|
|
1171
|
+
{
|
|
1172
|
+
const covered = /* @__PURE__ */ new Set();
|
|
1173
|
+
for (let r = 0; r < table.rows; r++) {
|
|
1174
|
+
for (let c = 0; c < table.cols; c++) {
|
|
1175
|
+
if (covered.has(`${r},${c}`)) continue;
|
|
1176
|
+
const cell = _optionalChain([table, 'access', _15 => _15.cells, 'access', _16 => _16[r], 'optionalAccess', _17 => _17[c]]);
|
|
1177
|
+
if (!cell) continue;
|
|
1178
|
+
for (let dr = 0; dr < cell.rowSpan; dr++) {
|
|
1179
|
+
for (let dc = 0; dc < cell.colSpan; dc++) {
|
|
1180
|
+
if (dr === 0 && dc === 0) continue;
|
|
1181
|
+
if (r + dr < table.rows && c + dc < table.cols) covered.add(`${r + dr},${c + dc}`);
|
|
1182
|
+
}
|
|
1114
1183
|
}
|
|
1184
|
+
anchors.push(cell);
|
|
1185
|
+
c += cell.colSpan - 1;
|
|
1115
1186
|
}
|
|
1116
|
-
throw new (0, _chunkITJIALN5cjs.KordocError)("DRM \uC554\uD638\uD654\uB41C HWPX \uD30C\uC77C\uC785\uB2C8\uB2E4. Windows + \uD55C\uCEF4 \uC624\uD53C\uC2A4 \uC124\uCE58 \uC2DC \uC790\uB3D9 \uCD94\uCD9C\uB429\uB2C8\uB2E4.");
|
|
1117
1187
|
}
|
|
1118
1188
|
}
|
|
1119
|
-
const
|
|
1120
|
-
const
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
if (
|
|
1145
|
-
|
|
1189
|
+
const srcCount = state.rows.reduce((s, r) => s + r.length, 0);
|
|
1190
|
+
const ordinalReliable = anchors.length === srcCount;
|
|
1191
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
1192
|
+
let flatIdx = -1;
|
|
1193
|
+
for (const row of state.rows) {
|
|
1194
|
+
for (const src of row) {
|
|
1195
|
+
flatIdx++;
|
|
1196
|
+
const needsBlocks = src.hasStructure && src.blocks && src.blocks.length > 0;
|
|
1197
|
+
if (!needsBlocks && !src.isHeader) continue;
|
|
1198
|
+
let target;
|
|
1199
|
+
const trimmed = src.text.trim();
|
|
1200
|
+
if (src.rowAddr !== void 0 && src.colAddr !== void 0) {
|
|
1201
|
+
const cand = _optionalChain([table, 'access', _18 => _18.cells, 'access', _19 => _19[src.rowAddr], 'optionalAccess', _20 => _20[src.colAddr]]);
|
|
1202
|
+
if (cand && cand.text === trimmed && !claimed.has(cand)) target = cand;
|
|
1203
|
+
}
|
|
1204
|
+
if (!target) {
|
|
1205
|
+
outer: for (const irRow of table.cells) {
|
|
1206
|
+
for (const cand of irRow) {
|
|
1207
|
+
if (!claimed.has(cand) && cand.text === trimmed && cand.colSpan === src.colSpan && cand.rowSpan === src.rowSpan) {
|
|
1208
|
+
target = cand;
|
|
1209
|
+
break outer;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
if (!target && ordinalReliable) {
|
|
1215
|
+
const cand = anchors[flatIdx];
|
|
1216
|
+
if (cand && !claimed.has(cand)) target = cand;
|
|
1217
|
+
}
|
|
1218
|
+
if (!target) continue;
|
|
1219
|
+
claimed.add(target);
|
|
1220
|
+
if (needsBlocks) target.blocks = src.blocks;
|
|
1221
|
+
if (src.isHeader) target.isHeader = true;
|
|
1146
1222
|
}
|
|
1147
1223
|
}
|
|
1148
|
-
|
|
1149
|
-
const images = await extractImagesFromZip(zip, blocks, decompressed, warnings);
|
|
1150
|
-
detectHwpxHeadings(blocks, styleMap);
|
|
1151
|
-
const outline = blocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
|
|
1152
|
-
const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, blocks);
|
|
1153
|
-
return { markdown, blocks, metadata, outline: outline.length > 0 ? outline : void 0, warnings: warnings.length > 0 ? warnings : void 0, images: images.length > 0 ? images : void 0 };
|
|
1224
|
+
return table;
|
|
1154
1225
|
}
|
|
1155
|
-
function
|
|
1156
|
-
const
|
|
1157
|
-
if (
|
|
1158
|
-
|
|
1226
|
+
function completeTable(newTable, tableStack, blocks, ctx) {
|
|
1227
|
+
const parentTable = tableStack.length > 0 ? tableStack.pop() : null;
|
|
1228
|
+
if (newTable.rows.length === 0) {
|
|
1229
|
+
if (newTable.caption) blocks.push({ type: "paragraph", text: newTable.caption, pageNumber: ctx.sectionNum });
|
|
1230
|
+
return parentTable;
|
|
1159
1231
|
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1232
|
+
const ir = buildTableWithCellMeta(newTable);
|
|
1233
|
+
const block = { type: "table", table: ir, pageNumber: ctx.sectionNum };
|
|
1234
|
+
if (_optionalChain([parentTable, 'optionalAccess', _21 => _21.cell])) {
|
|
1235
|
+
const cell = parentTable.cell;
|
|
1236
|
+
(cell.blocks ??= []).push(block);
|
|
1237
|
+
cell.hasStructure = true;
|
|
1238
|
+
let flat = _chunkLFCS3UVGcjs.convertTableToText.call(void 0, newTable.rows);
|
|
1239
|
+
if (newTable.caption) flat = newTable.caption + (flat ? "\n" + flat : "");
|
|
1240
|
+
if (flat) cell.text += (cell.text ? "\n" : "") + flat;
|
|
1241
|
+
} else {
|
|
1242
|
+
blocks.push(block);
|
|
1162
1243
|
}
|
|
1244
|
+
return parentTable;
|
|
1163
1245
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
return "image/wmf";
|
|
1180
|
-
case "emf":
|
|
1181
|
-
return "image/emf";
|
|
1182
|
-
case "svg":
|
|
1183
|
-
return "image/svg+xml";
|
|
1184
|
-
default:
|
|
1185
|
-
return "application/octet-stream";
|
|
1246
|
+
|
|
1247
|
+
// src/hwpx/section-walker.ts
|
|
1248
|
+
function parseSectionXml(xml, styleMap, warnings, sectionNum, shared) {
|
|
1249
|
+
const parser = createXmlParser(warnings);
|
|
1250
|
+
const doc = parser.parseFromString(_chunkLFCS3UVGcjs.stripDtd.call(void 0, xml), "text/xml");
|
|
1251
|
+
if (!doc.documentElement) return [];
|
|
1252
|
+
const ctx = { styleMap, warnings, sectionNum, shared: _nullishCoalesce(shared, () => ( createSectionShared())) };
|
|
1253
|
+
ctx.shared.track.deleteDepth = 0;
|
|
1254
|
+
for (const tagName of ["hp:secPr", "secPr"]) {
|
|
1255
|
+
const els = doc.getElementsByTagName(tagName);
|
|
1256
|
+
if (els.length > 0) {
|
|
1257
|
+
const v = els[0].getAttribute("outlineShapeIDRef");
|
|
1258
|
+
if (v) ctx.outlineNumId = v;
|
|
1259
|
+
break;
|
|
1260
|
+
}
|
|
1186
1261
|
}
|
|
1262
|
+
const blocks = [];
|
|
1263
|
+
walkSection(doc.documentElement, blocks, null, [], ctx);
|
|
1264
|
+
return blocks;
|
|
1187
1265
|
}
|
|
1188
|
-
function
|
|
1189
|
-
|
|
1190
|
-
if (
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1199
|
-
function collectImageBlocks(blocks, out, ownerCell, depth = 0) {
|
|
1200
|
-
if (depth > MAX_XML_DEPTH) return;
|
|
1201
|
-
for (const block of blocks) {
|
|
1202
|
-
if (block.type === "image") {
|
|
1203
|
-
out.push({ block, ownerCell });
|
|
1204
|
-
} else if (block.type === "table" && block.table) {
|
|
1205
|
-
for (const row of block.table.cells) {
|
|
1206
|
-
for (const cell of row) {
|
|
1207
|
-
if (_optionalChain([cell, 'access', _15 => _15.blocks, 'optionalAccess', _16 => _16.length])) collectImageBlocks(cell.blocks, out, cell, depth + 1);
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1266
|
+
function extractImageRef(el) {
|
|
1267
|
+
const children = el.childNodes;
|
|
1268
|
+
if (!children) return null;
|
|
1269
|
+
for (let i = 0; i < children.length; i++) {
|
|
1270
|
+
const child = children[i];
|
|
1271
|
+
if (child.nodeType !== 1) continue;
|
|
1272
|
+
const tag = (child.tagName || child.localName || "").replace(/^[^:]+:/, "");
|
|
1273
|
+
if (tag === "imgRect" || tag === "img" || tag === "imgClip") {
|
|
1274
|
+
const ref = child.getAttribute("binaryItemIDRef") || child.getAttribute("href") || "";
|
|
1275
|
+
if (ref) return ref;
|
|
1210
1276
|
}
|
|
1277
|
+
const nested = extractImageRef(child);
|
|
1278
|
+
if (nested) return nested;
|
|
1211
1279
|
}
|
|
1280
|
+
const directRef = el.getAttribute("binaryItemIDRef") || "";
|
|
1281
|
+
if (directRef) return directRef;
|
|
1282
|
+
return null;
|
|
1212
1283
|
}
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
const
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1284
|
+
function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
|
|
1285
|
+
if (depth > MAX_XML_DEPTH) return;
|
|
1286
|
+
const children = node.childNodes;
|
|
1287
|
+
if (!children) return;
|
|
1288
|
+
for (let i = 0; i < children.length; i++) {
|
|
1289
|
+
const el = children[i];
|
|
1290
|
+
if (el.nodeType !== 1) continue;
|
|
1291
|
+
const tag = el.tagName || el.localName || "";
|
|
1292
|
+
const localTag = tag.replace(/^[^:]+:/, "");
|
|
1293
|
+
switch (localTag) {
|
|
1294
|
+
case "tbl": {
|
|
1295
|
+
if (tableCtx) tableStack.push(tableCtx);
|
|
1296
|
+
const newTable = { rows: [], currentRow: [], cell: null };
|
|
1297
|
+
walkSection(el, blocks, newTable, tableStack, ctx, depth + 1);
|
|
1298
|
+
tableCtx = completeTable(newTable, tableStack, blocks, ctx);
|
|
1299
|
+
break;
|
|
1300
|
+
}
|
|
1301
|
+
// 표/도표 캡션 — IRTable.caption으로 보존 (v3.0, 기존 무음 드롭 수정)
|
|
1302
|
+
case "caption":
|
|
1303
|
+
if (tableCtx) {
|
|
1304
|
+
const capText = collectSubListText(el, ctx);
|
|
1305
|
+
if (capText) tableCtx.caption = (tableCtx.caption ? tableCtx.caption + "\n" : "") + capText;
|
|
1306
|
+
}
|
|
1307
|
+
break;
|
|
1308
|
+
case "tr":
|
|
1309
|
+
if (tableCtx) {
|
|
1310
|
+
tableCtx.currentRow = [];
|
|
1311
|
+
walkSection(el, blocks, tableCtx, tableStack, ctx, depth + 1);
|
|
1312
|
+
if (tableCtx.currentRow.length > 0) tableCtx.rows.push(tableCtx.currentRow);
|
|
1313
|
+
tableCtx.currentRow = [];
|
|
1314
|
+
}
|
|
1315
|
+
break;
|
|
1316
|
+
case "tc":
|
|
1317
|
+
if (tableCtx) {
|
|
1318
|
+
tableCtx.cell = { text: "", colSpan: 1, rowSpan: 1 };
|
|
1319
|
+
if (el.getAttribute("header") === "1" || el.getAttribute("header") === "true") tableCtx.cell.isHeader = true;
|
|
1320
|
+
walkSection(el, blocks, tableCtx, tableStack, ctx, depth + 1);
|
|
1321
|
+
if (tableCtx.cell) {
|
|
1322
|
+
tableCtx.currentRow.push(tableCtx.cell);
|
|
1323
|
+
tableCtx.cell = null;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
break;
|
|
1327
|
+
case "cellAddr":
|
|
1328
|
+
if (_optionalChain([tableCtx, 'optionalAccess', _22 => _22.cell])) {
|
|
1329
|
+
const ca = parseInt(el.getAttribute("colAddr") || "", 10);
|
|
1330
|
+
const ra = parseInt(el.getAttribute("rowAddr") || "", 10);
|
|
1331
|
+
if (!isNaN(ca)) tableCtx.cell.colAddr = ca;
|
|
1332
|
+
if (!isNaN(ra)) tableCtx.cell.rowAddr = ra;
|
|
1333
|
+
}
|
|
1334
|
+
break;
|
|
1335
|
+
case "cellSpan":
|
|
1336
|
+
if (_optionalChain([tableCtx, 'optionalAccess', _23 => _23.cell])) {
|
|
1337
|
+
const rawCs = parseInt(el.getAttribute("colSpan") || "1", 10);
|
|
1338
|
+
const cs = isNaN(rawCs) ? 1 : rawCs;
|
|
1339
|
+
const rawRs = parseInt(el.getAttribute("rowSpan") || "1", 10);
|
|
1340
|
+
const rs = isNaN(rawRs) ? 1 : rawRs;
|
|
1341
|
+
tableCtx.cell.colSpan = clampSpan(cs, _chunkLFCS3UVGcjs.MAX_COLS);
|
|
1342
|
+
tableCtx.cell.rowSpan = clampSpan(rs, _chunkLFCS3UVGcjs.MAX_ROWS);
|
|
1343
|
+
}
|
|
1344
|
+
break;
|
|
1345
|
+
case "p": {
|
|
1346
|
+
const { text: rawText, href, footnote, style } = extractParagraphInfo(el, ctx.styleMap, ctx);
|
|
1347
|
+
let text = rawText;
|
|
1348
|
+
let headingLevel;
|
|
1349
|
+
if (text) {
|
|
1350
|
+
const ph = resolveParaHeading(el, ctx);
|
|
1351
|
+
if (_optionalChain([ph, 'optionalAccess', _24 => _24.prefix])) text = ph.prefix + " " + text;
|
|
1352
|
+
headingLevel = _optionalChain([ph, 'optionalAccess', _25 => _25.headingLevel]);
|
|
1353
|
+
}
|
|
1354
|
+
if (text) {
|
|
1355
|
+
if (_optionalChain([tableCtx, 'optionalAccess', _26 => _26.cell])) {
|
|
1356
|
+
const cell = tableCtx.cell;
|
|
1357
|
+
if (footnote) text += ` (\uC8FC: ${footnote})`;
|
|
1358
|
+
cell.text += (cell.text ? "\n" : "") + text;
|
|
1359
|
+
(cell.blocks ??= []).push({ type: "paragraph", text, pageNumber: ctx.sectionNum });
|
|
1360
|
+
} else if (!tableCtx) {
|
|
1361
|
+
const block = { type: headingLevel ? "heading" : "paragraph", text, pageNumber: ctx.sectionNum };
|
|
1362
|
+
if (headingLevel) block.level = headingLevel;
|
|
1363
|
+
if (style) block.style = style;
|
|
1364
|
+
if (href) block.href = href;
|
|
1365
|
+
if (footnote) block.footnoteText = footnote;
|
|
1366
|
+
blocks.push(block);
|
|
1367
|
+
} else {
|
|
1368
|
+
blocks.push({ type: "paragraph", text, pageNumber: ctx.sectionNum });
|
|
1239
1369
|
}
|
|
1240
1370
|
}
|
|
1371
|
+
tableCtx = walkParagraphChildren(el, blocks, tableCtx, tableStack, ctx, depth + 1);
|
|
1372
|
+
break;
|
|
1241
1373
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
if (
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
const mimeType = imageExtToMime(ext);
|
|
1253
|
-
imageIndex++;
|
|
1254
|
-
const filename = `image_${String(imageIndex).padStart(3, "0")}.${mimeToExt(mimeType)}`;
|
|
1255
|
-
img = { filename, data, mimeType };
|
|
1256
|
-
images.push(img);
|
|
1257
|
-
break;
|
|
1258
|
-
} catch (err) {
|
|
1259
|
-
if (err instanceof _chunkITJIALN5cjs.KordocError) throw err;
|
|
1374
|
+
// 이미지/그림/글상자 — 이미지·텍스트·캡션 병행 추출
|
|
1375
|
+
case "pic":
|
|
1376
|
+
case "shape":
|
|
1377
|
+
case "drawingObject": {
|
|
1378
|
+
if (_optionalChain([tableCtx, 'optionalAccess', _27 => _27.cell])) {
|
|
1379
|
+
const sink = [];
|
|
1380
|
+
handleShape(el, sink, ctx);
|
|
1381
|
+
mergeBlocksIntoCell(tableCtx.cell, sink);
|
|
1382
|
+
} else {
|
|
1383
|
+
handleShape(el, blocks, ctx);
|
|
1260
1384
|
}
|
|
1385
|
+
break;
|
|
1261
1386
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
continue;
|
|
1270
|
-
}
|
|
1271
|
-
block.text = img.filename;
|
|
1272
|
-
block.imageData = { data: img.data, mimeType: img.mimeType, filename: ref };
|
|
1273
|
-
if (ownerCell) ownerCell.text = ownerCell.text.replace(``, ``);
|
|
1274
|
-
}
|
|
1275
|
-
return images;
|
|
1276
|
-
}
|
|
1277
|
-
async function extractHwpxMetadata(zip, metadata, decompressed) {
|
|
1278
|
-
try {
|
|
1279
|
-
const metaPaths = ["meta.xml", "META-INF/meta.xml", "docProps/core.xml"];
|
|
1280
|
-
for (const mp of metaPaths) {
|
|
1281
|
-
const file = zip.file(mp) || Object.values(zip.files).find((f) => f.name.toLowerCase() === mp.toLowerCase()) || null;
|
|
1282
|
-
if (!file) continue;
|
|
1283
|
-
const xml = await file.async("text");
|
|
1284
|
-
if (decompressed) {
|
|
1285
|
-
decompressed.total += xml.length * 2;
|
|
1286
|
-
if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
|
|
1387
|
+
// 메모 — 본문 혼입 차단 (v3.0)
|
|
1388
|
+
case "memogroup":
|
|
1389
|
+
case "memo": {
|
|
1390
|
+
if (ctx.warnings && extractTextFromNode(el)) {
|
|
1391
|
+
ctx.warnings.push({ page: ctx.sectionNum, message: "\uBA54\uBAA8 \uD14D\uC2A4\uD2B8 \uBCF8\uBB38 \uC81C\uC678: memogroup", code: "HIDDEN_TEXT_FILTERED" });
|
|
1392
|
+
}
|
|
1393
|
+
break;
|
|
1287
1394
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1395
|
+
default:
|
|
1396
|
+
walkSection(el, blocks, tableCtx, tableStack, ctx, depth + 1);
|
|
1397
|
+
break;
|
|
1290
1398
|
}
|
|
1291
|
-
} catch (e13) {
|
|
1292
1399
|
}
|
|
1293
1400
|
}
|
|
1294
|
-
function
|
|
1295
|
-
const
|
|
1296
|
-
const
|
|
1297
|
-
if (
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
if (keywords && !metadata.keywords) {
|
|
1315
|
-
metadata.keywords = keywords.split(/[,;]/).map((k) => k.trim()).filter(Boolean);
|
|
1401
|
+
function handleShape(el, sink, ctx) {
|
|
1402
|
+
const imgRef = extractImageRef(el);
|
|
1403
|
+
const drawTextChild = findDescendant(el, "drawText");
|
|
1404
|
+
if (imgRef) {
|
|
1405
|
+
const block = { type: "image", text: imgRef, pageNumber: ctx.sectionNum };
|
|
1406
|
+
const alt = userShapeComment(el);
|
|
1407
|
+
if (alt) block.footnoteText = alt;
|
|
1408
|
+
sink.push(block);
|
|
1409
|
+
}
|
|
1410
|
+
if (drawTextChild) {
|
|
1411
|
+
extractDrawTextBlocks(drawTextChild, sink, ctx);
|
|
1412
|
+
}
|
|
1413
|
+
const capEl = findChildByLocalName(el, "caption");
|
|
1414
|
+
if (capEl) {
|
|
1415
|
+
const capText = collectSubListText(capEl, ctx);
|
|
1416
|
+
if (capText) sink.push({ type: "paragraph", text: capText, pageNumber: ctx.sectionNum });
|
|
1417
|
+
}
|
|
1418
|
+
if (!imgRef && !drawTextChild && ctx.warnings && ctx.sectionNum) {
|
|
1419
|
+
const localTag = (el.tagName || el.localName || "").replace(/^[^:]+:/, "");
|
|
1420
|
+
ctx.warnings.push({ page: ctx.sectionNum, message: `\uC2A4\uD0B5\uB41C \uC694\uC18C: ${localTag}`, code: "SKIPPED_IMAGE" });
|
|
1316
1421
|
}
|
|
1317
1422
|
}
|
|
1318
|
-
function
|
|
1319
|
-
const
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
pos++;
|
|
1423
|
+
function userShapeComment(el) {
|
|
1424
|
+
const commentEl = findChildByLocalName(el, "shapeComment");
|
|
1425
|
+
if (!commentEl) return void 0;
|
|
1426
|
+
const text = extractTextFromNode(commentEl);
|
|
1427
|
+
if (!text) return void 0;
|
|
1428
|
+
if (/^그림입니다/.test(text)) return void 0;
|
|
1429
|
+
if (/^(?:모서리가 둥근 |둥근 )?[^\n]{1,20}입니다\.?$/.test(text)) return void 0;
|
|
1430
|
+
return text;
|
|
1431
|
+
}
|
|
1432
|
+
function mergeBlocksIntoCell(cell, sink) {
|
|
1433
|
+
for (const b of sink) {
|
|
1434
|
+
if ((b.type === "paragraph" || b.type === "heading") && b.text) {
|
|
1435
|
+
cell.text += (cell.text ? "\n" : "") + b.text;
|
|
1436
|
+
(cell.blocks ??= []).push(b);
|
|
1437
|
+
} else if (b.type === "image" || b.type === "table") {
|
|
1438
|
+
if (b.type === "image" && b.text) {
|
|
1439
|
+
cell.text += (cell.text ? "\n" : "") + ``;
|
|
1336
1440
|
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
const method = view.getUint16(pos + 8, true);
|
|
1341
|
-
const compSize = view.getUint32(pos + 18, true);
|
|
1342
|
-
const nameLen = view.getUint16(pos + 26, true);
|
|
1343
|
-
const extraLen = view.getUint16(pos + 28, true);
|
|
1344
|
-
if (nameLen > 1024 || extraLen > 65535) {
|
|
1345
|
-
pos += 30 + nameLen + extraLen;
|
|
1346
|
-
continue;
|
|
1347
|
-
}
|
|
1348
|
-
const fileStart = pos + 30 + nameLen + extraLen;
|
|
1349
|
-
if (fileStart + compSize > data.length) break;
|
|
1350
|
-
if (compSize === 0 && method !== 0) {
|
|
1351
|
-
pos = fileStart;
|
|
1352
|
-
continue;
|
|
1441
|
+
;
|
|
1442
|
+
(cell.blocks ??= []).push(b);
|
|
1443
|
+
cell.hasStructure = true;
|
|
1353
1444
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
function collectSubListText(el, ctx, depth = 0) {
|
|
1448
|
+
if (depth > 10) return "";
|
|
1449
|
+
const parts = [];
|
|
1450
|
+
const children = el.childNodes;
|
|
1451
|
+
if (!children) return "";
|
|
1452
|
+
for (let i = 0; i < children.length; i++) {
|
|
1453
|
+
const ch = children[i];
|
|
1454
|
+
if (ch.nodeType !== 1) continue;
|
|
1455
|
+
const tag = (ch.tagName || ch.localName || "").replace(/^[^:]+:/, "");
|
|
1456
|
+
if (tag === "p" || tag === "para") {
|
|
1457
|
+
const t = extractParagraphInfo(ch, ctx.styleMap, ctx).text;
|
|
1458
|
+
if (t) parts.push(t);
|
|
1459
|
+
} else if (tag === "tbl") {
|
|
1358
1460
|
continue;
|
|
1461
|
+
} else {
|
|
1462
|
+
const t = collectSubListText(ch, ctx, depth + 1);
|
|
1463
|
+
if (t) parts.push(t);
|
|
1359
1464
|
}
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1465
|
+
}
|
|
1466
|
+
return parts.join("\n").trim();
|
|
1467
|
+
}
|
|
1468
|
+
function walkParagraphChildren(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
|
|
1469
|
+
if (depth > MAX_XML_DEPTH) return tableCtx;
|
|
1470
|
+
const children = node.childNodes;
|
|
1471
|
+
if (!children) return tableCtx;
|
|
1472
|
+
const walkChildren = (parent, d) => {
|
|
1473
|
+
if (d > MAX_XML_DEPTH) return;
|
|
1474
|
+
const kids2 = parent.childNodes;
|
|
1475
|
+
if (!kids2) return;
|
|
1476
|
+
for (let i = 0; i < kids2.length; i++) {
|
|
1477
|
+
const el = kids2[i];
|
|
1478
|
+
if (el.nodeType !== 1) continue;
|
|
1479
|
+
const tag = el.tagName || el.localName || "";
|
|
1480
|
+
const localTag = tag.replace(/^[^:]+:/, "");
|
|
1481
|
+
if (localTag === "tbl") {
|
|
1482
|
+
if (tableCtx) tableStack.push(tableCtx);
|
|
1483
|
+
const newTable = { rows: [], currentRow: [], cell: null };
|
|
1484
|
+
walkSection(el, blocks, newTable, tableStack, ctx, d + 1);
|
|
1485
|
+
tableCtx = completeTable(newTable, tableStack, blocks, ctx);
|
|
1486
|
+
} else if (localTag === "pic" || localTag === "shape" || localTag === "drawingObject") {
|
|
1487
|
+
if (_optionalChain([tableCtx, 'optionalAccess', _28 => _28.cell])) {
|
|
1488
|
+
const sink = [];
|
|
1489
|
+
handleShape(el, sink, ctx);
|
|
1490
|
+
mergeBlocksIntoCell(tableCtx.cell, sink);
|
|
1491
|
+
} else {
|
|
1492
|
+
handleShape(el, blocks, ctx);
|
|
1493
|
+
}
|
|
1494
|
+
} else if (localTag === "drawText") {
|
|
1495
|
+
if (_optionalChain([tableCtx, 'optionalAccess', _29 => _29.cell])) {
|
|
1496
|
+
const sink = [];
|
|
1497
|
+
extractDrawTextBlocks(el, sink, ctx);
|
|
1498
|
+
mergeBlocksIntoCell(tableCtx.cell, sink);
|
|
1499
|
+
} else {
|
|
1500
|
+
extractDrawTextBlocks(el, blocks, ctx);
|
|
1501
|
+
}
|
|
1502
|
+
} else if (localTag === "r" || localTag === "run" || localTag === "ctrl" || localTag === "rect" || localTag === "ellipse" || localTag === "polygon" || localTag === "line" || localTag === "arc" || localTag === "curve" || localTag === "connectLine" || localTag === "container") {
|
|
1503
|
+
walkChildren(el, d + 1);
|
|
1372
1504
|
}
|
|
1373
|
-
totalDecompressed += content.length * 2;
|
|
1374
|
-
if (totalDecompressed > MAX_DECOMPRESS_SIZE) throw new (0, _chunkITJIALN5cjs.KordocError)("\uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC");
|
|
1375
|
-
sectionNum++;
|
|
1376
|
-
blocks.push(...parseSectionXml(content, void 0, warnings, sectionNum, shared));
|
|
1377
|
-
} catch (e14) {
|
|
1378
|
-
continue;
|
|
1379
1505
|
}
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, blocks);
|
|
1384
|
-
return { markdown, blocks, warnings: warnings.length > 0 ? warnings : void 0 };
|
|
1506
|
+
};
|
|
1507
|
+
walkChildren(node, depth);
|
|
1508
|
+
return tableCtx;
|
|
1385
1509
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
const
|
|
1394
|
-
if (
|
|
1510
|
+
function findDescendant(node, targetTag, depth = 0) {
|
|
1511
|
+
if (depth > 5) return null;
|
|
1512
|
+
const children = node.childNodes;
|
|
1513
|
+
if (!children) return null;
|
|
1514
|
+
for (let i = 0; i < children.length; i++) {
|
|
1515
|
+
const child = children[i];
|
|
1516
|
+
if (child.nodeType !== 1) continue;
|
|
1517
|
+
const tag = (child.tagName || child.localName || "").replace(/^[^:]+:/, "");
|
|
1518
|
+
if (tag === targetTag) return child;
|
|
1519
|
+
const found = findDescendant(child, targetTag, depth + 1);
|
|
1520
|
+
if (found) return found;
|
|
1395
1521
|
}
|
|
1396
|
-
|
|
1397
|
-
return sectionFiles.map((f) => f.name).sort(_chunkITJIALN5cjs.compareSectionPaths);
|
|
1522
|
+
return null;
|
|
1398
1523
|
}
|
|
1399
|
-
function
|
|
1400
|
-
const
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1524
|
+
function extractDrawTextBlocks(drawTextNode, blocks, ctx) {
|
|
1525
|
+
const children = drawTextNode.childNodes;
|
|
1526
|
+
if (!children) return;
|
|
1527
|
+
for (let i = 0; i < children.length; i++) {
|
|
1528
|
+
const child = children[i];
|
|
1529
|
+
if (child.nodeType !== 1) continue;
|
|
1530
|
+
const tag = (child.tagName || child.localName || "").replace(/^[^:]+:/, "");
|
|
1531
|
+
if (tag === "subList" || tag === "p" || tag === "para") {
|
|
1532
|
+
if (tag === "subList") {
|
|
1533
|
+
extractDrawTextBlocks(child, blocks, ctx);
|
|
1534
|
+
} else {
|
|
1535
|
+
const info = extractParagraphInfo(child, ctx.styleMap, ctx);
|
|
1536
|
+
let text = info.text.trim();
|
|
1537
|
+
if (text) {
|
|
1538
|
+
const ph = resolveParaHeading(child, ctx);
|
|
1539
|
+
if (_optionalChain([ph, 'optionalAccess', _30 => _30.prefix])) text = ph.prefix + " " + text;
|
|
1540
|
+
const block = { type: "paragraph", text, style: _nullishCoalesce(info.style, () => ( void 0)), pageNumber: ctx.sectionNum };
|
|
1541
|
+
if (info.href) block.href = info.href;
|
|
1542
|
+
if (info.footnote) block.footnoteText = info.footnote;
|
|
1543
|
+
blocks.push(block);
|
|
1544
|
+
}
|
|
1545
|
+
walkParagraphChildren(child, blocks, null, [], ctx);
|
|
1546
|
+
}
|
|
1416
1547
|
}
|
|
1417
|
-
if (ordered.length > 0) return ordered;
|
|
1418
1548
|
}
|
|
1419
|
-
return Array.from(idToHref.values()).sort(_chunkITJIALN5cjs.compareSectionPaths);
|
|
1420
1549
|
}
|
|
1421
|
-
function
|
|
1422
|
-
if (
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
for (const block of blocks) {
|
|
1438
|
-
if (block.type !== "paragraph" || !block.text) continue;
|
|
1439
|
-
const text = block.text.trim();
|
|
1440
|
-
if (text.length === 0 || text.length > 200 || /^\d+$/.test(text)) continue;
|
|
1441
|
-
let level = 0;
|
|
1442
|
-
if (baseFontSize > 0 && _optionalChain([block, 'access', _25 => _25.style, 'optionalAccess', _26 => _26.fontSize])) {
|
|
1443
|
-
const ratio = block.style.fontSize / baseFontSize;
|
|
1444
|
-
if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H1) level = 1;
|
|
1445
|
-
else if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H2) level = 2;
|
|
1446
|
-
else if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H3) level = 3;
|
|
1447
|
-
}
|
|
1448
|
-
const compactText = text.replace(/\s+/g, "");
|
|
1449
|
-
if (/^제\d+[조장절편]/.test(compactText) && text.length <= 50) {
|
|
1450
|
-
if (level === 0) level = 3;
|
|
1451
|
-
}
|
|
1452
|
-
if (level > 0) {
|
|
1453
|
-
block.type = "heading";
|
|
1454
|
-
block.level = level;
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
function buildTableWithCellMeta(state) {
|
|
1459
|
-
const table = _chunkITJIALN5cjs.buildTable.call(void 0, state.rows);
|
|
1460
|
-
if (state.caption) table.caption = state.caption;
|
|
1461
|
-
const anchors = [];
|
|
1462
|
-
{
|
|
1463
|
-
const covered = /* @__PURE__ */ new Set();
|
|
1464
|
-
for (let r = 0; r < table.rows; r++) {
|
|
1465
|
-
for (let c = 0; c < table.cols; c++) {
|
|
1466
|
-
if (covered.has(`${r},${c}`)) continue;
|
|
1467
|
-
const cell = _optionalChain([table, 'access', _27 => _27.cells, 'access', _28 => _28[r], 'optionalAccess', _29 => _29[c]]);
|
|
1468
|
-
if (!cell) continue;
|
|
1469
|
-
for (let dr = 0; dr < cell.rowSpan; dr++) {
|
|
1470
|
-
for (let dc = 0; dc < cell.colSpan; dc++) {
|
|
1471
|
-
if (dr === 0 && dc === 0) continue;
|
|
1472
|
-
if (r + dr < table.rows && c + dc < table.cols) covered.add(`${r + dr},${c + dc}`);
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
anchors.push(cell);
|
|
1476
|
-
c += cell.colSpan - 1;
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
const srcCount = state.rows.reduce((s, r) => s + r.length, 0);
|
|
1481
|
-
const ordinalReliable = anchors.length === srcCount;
|
|
1482
|
-
const claimed = /* @__PURE__ */ new Set();
|
|
1483
|
-
let flatIdx = -1;
|
|
1484
|
-
for (const row of state.rows) {
|
|
1485
|
-
for (const src of row) {
|
|
1486
|
-
flatIdx++;
|
|
1487
|
-
const needsBlocks = src.hasStructure && src.blocks && src.blocks.length > 0;
|
|
1488
|
-
if (!needsBlocks && !src.isHeader) continue;
|
|
1489
|
-
let target;
|
|
1490
|
-
const trimmed = src.text.trim();
|
|
1491
|
-
if (src.rowAddr !== void 0 && src.colAddr !== void 0) {
|
|
1492
|
-
const cand = _optionalChain([table, 'access', _30 => _30.cells, 'access', _31 => _31[src.rowAddr], 'optionalAccess', _32 => _32[src.colAddr]]);
|
|
1493
|
-
if (cand && cand.text === trimmed && !claimed.has(cand)) target = cand;
|
|
1494
|
-
}
|
|
1495
|
-
if (!target) {
|
|
1496
|
-
outer: for (const irRow of table.cells) {
|
|
1497
|
-
for (const cand of irRow) {
|
|
1498
|
-
if (!claimed.has(cand) && cand.text === trimmed && cand.colSpan === src.colSpan && cand.rowSpan === src.rowSpan) {
|
|
1499
|
-
target = cand;
|
|
1500
|
-
break outer;
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
if (!target && ordinalReliable) {
|
|
1506
|
-
const cand = anchors[flatIdx];
|
|
1507
|
-
if (cand && !claimed.has(cand)) target = cand;
|
|
1508
|
-
}
|
|
1509
|
-
if (!target) continue;
|
|
1510
|
-
claimed.add(target);
|
|
1511
|
-
if (needsBlocks) target.blocks = src.blocks;
|
|
1512
|
-
if (src.isHeader) target.isHeader = true;
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
return table;
|
|
1516
|
-
}
|
|
1517
|
-
function completeTable(newTable, tableStack, blocks, ctx) {
|
|
1518
|
-
const parentTable = tableStack.length > 0 ? tableStack.pop() : null;
|
|
1519
|
-
if (newTable.rows.length === 0) {
|
|
1520
|
-
if (newTable.caption) blocks.push({ type: "paragraph", text: newTable.caption, pageNumber: ctx.sectionNum });
|
|
1521
|
-
return parentTable;
|
|
1522
|
-
}
|
|
1523
|
-
const ir = buildTableWithCellMeta(newTable);
|
|
1524
|
-
const block = { type: "table", table: ir, pageNumber: ctx.sectionNum };
|
|
1525
|
-
if (_optionalChain([parentTable, 'optionalAccess', _33 => _33.cell])) {
|
|
1526
|
-
const cell = parentTable.cell;
|
|
1527
|
-
(cell.blocks ??= []).push(block);
|
|
1528
|
-
cell.hasStructure = true;
|
|
1529
|
-
let flat = _chunkITJIALN5cjs.convertTableToText.call(void 0, newTable.rows);
|
|
1530
|
-
if (newTable.caption) flat = newTable.caption + (flat ? "\n" + flat : "");
|
|
1531
|
-
if (flat) cell.text += (cell.text ? "\n" : "") + flat;
|
|
1532
|
-
} else {
|
|
1533
|
-
blocks.push(block);
|
|
1534
|
-
}
|
|
1535
|
-
return parentTable;
|
|
1536
|
-
}
|
|
1537
|
-
function parseSectionXml(xml, styleMap, warnings, sectionNum, shared) {
|
|
1538
|
-
const parser = createXmlParser(warnings);
|
|
1539
|
-
const doc = parser.parseFromString(_chunkITJIALN5cjs.stripDtd.call(void 0, xml), "text/xml");
|
|
1540
|
-
if (!doc.documentElement) return [];
|
|
1541
|
-
const ctx = { styleMap, warnings, sectionNum, shared: _nullishCoalesce(shared, () => ( createSectionShared())) };
|
|
1542
|
-
ctx.shared.track.deleteDepth = 0;
|
|
1543
|
-
for (const tagName of ["hp:secPr", "secPr"]) {
|
|
1544
|
-
const els = doc.getElementsByTagName(tagName);
|
|
1545
|
-
if (els.length > 0) {
|
|
1546
|
-
const v = els[0].getAttribute("outlineShapeIDRef");
|
|
1547
|
-
if (v) ctx.outlineNumId = v;
|
|
1548
|
-
break;
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
const blocks = [];
|
|
1552
|
-
walkSection(doc.documentElement, blocks, null, [], ctx);
|
|
1553
|
-
return blocks;
|
|
1554
|
-
}
|
|
1555
|
-
function extractImageRef(el) {
|
|
1556
|
-
const children = el.childNodes;
|
|
1557
|
-
if (!children) return null;
|
|
1558
|
-
for (let i = 0; i < children.length; i++) {
|
|
1559
|
-
const child = children[i];
|
|
1560
|
-
if (child.nodeType !== 1) continue;
|
|
1561
|
-
const tag = (child.tagName || child.localName || "").replace(/^[^:]+:/, "");
|
|
1562
|
-
if (tag === "imgRect" || tag === "img" || tag === "imgClip") {
|
|
1563
|
-
const ref = child.getAttribute("binaryItemIDRef") || child.getAttribute("href") || "";
|
|
1564
|
-
if (ref) return ref;
|
|
1565
|
-
}
|
|
1566
|
-
const nested = extractImageRef(child);
|
|
1567
|
-
if (nested) return nested;
|
|
1568
|
-
}
|
|
1569
|
-
const directRef = el.getAttribute("binaryItemIDRef") || "";
|
|
1570
|
-
if (directRef) return directRef;
|
|
1571
|
-
return null;
|
|
1572
|
-
}
|
|
1573
|
-
function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
|
|
1574
|
-
if (depth > MAX_XML_DEPTH) return;
|
|
1575
|
-
const children = node.childNodes;
|
|
1576
|
-
if (!children) return;
|
|
1577
|
-
for (let i = 0; i < children.length; i++) {
|
|
1578
|
-
const el = children[i];
|
|
1579
|
-
if (el.nodeType !== 1) continue;
|
|
1580
|
-
const tag = el.tagName || el.localName || "";
|
|
1581
|
-
const localTag = tag.replace(/^[^:]+:/, "");
|
|
1582
|
-
switch (localTag) {
|
|
1583
|
-
case "tbl": {
|
|
1584
|
-
if (tableCtx) tableStack.push(tableCtx);
|
|
1585
|
-
const newTable = { rows: [], currentRow: [], cell: null };
|
|
1586
|
-
walkSection(el, blocks, newTable, tableStack, ctx, depth + 1);
|
|
1587
|
-
tableCtx = completeTable(newTable, tableStack, blocks, ctx);
|
|
1588
|
-
break;
|
|
1589
|
-
}
|
|
1590
|
-
// 표/도표 캡션 — IRTable.caption으로 보존 (v3.0, 기존 무음 드롭 수정)
|
|
1591
|
-
case "caption":
|
|
1592
|
-
if (tableCtx) {
|
|
1593
|
-
const capText = collectSubListText(el, ctx);
|
|
1594
|
-
if (capText) tableCtx.caption = (tableCtx.caption ? tableCtx.caption + "\n" : "") + capText;
|
|
1595
|
-
}
|
|
1596
|
-
break;
|
|
1597
|
-
case "tr":
|
|
1598
|
-
if (tableCtx) {
|
|
1599
|
-
tableCtx.currentRow = [];
|
|
1600
|
-
walkSection(el, blocks, tableCtx, tableStack, ctx, depth + 1);
|
|
1601
|
-
if (tableCtx.currentRow.length > 0) tableCtx.rows.push(tableCtx.currentRow);
|
|
1602
|
-
tableCtx.currentRow = [];
|
|
1603
|
-
}
|
|
1604
|
-
break;
|
|
1605
|
-
case "tc":
|
|
1606
|
-
if (tableCtx) {
|
|
1607
|
-
tableCtx.cell = { text: "", colSpan: 1, rowSpan: 1 };
|
|
1608
|
-
if (el.getAttribute("header") === "1" || el.getAttribute("header") === "true") tableCtx.cell.isHeader = true;
|
|
1609
|
-
walkSection(el, blocks, tableCtx, tableStack, ctx, depth + 1);
|
|
1610
|
-
if (tableCtx.cell) {
|
|
1611
|
-
tableCtx.currentRow.push(tableCtx.cell);
|
|
1612
|
-
tableCtx.cell = null;
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
break;
|
|
1616
|
-
case "cellAddr":
|
|
1617
|
-
if (_optionalChain([tableCtx, 'optionalAccess', _34 => _34.cell])) {
|
|
1618
|
-
const ca = parseInt(el.getAttribute("colAddr") || "", 10);
|
|
1619
|
-
const ra = parseInt(el.getAttribute("rowAddr") || "", 10);
|
|
1620
|
-
if (!isNaN(ca)) tableCtx.cell.colAddr = ca;
|
|
1621
|
-
if (!isNaN(ra)) tableCtx.cell.rowAddr = ra;
|
|
1622
|
-
}
|
|
1623
|
-
break;
|
|
1624
|
-
case "cellSpan":
|
|
1625
|
-
if (_optionalChain([tableCtx, 'optionalAccess', _35 => _35.cell])) {
|
|
1626
|
-
const rawCs = parseInt(el.getAttribute("colSpan") || "1", 10);
|
|
1627
|
-
const cs = isNaN(rawCs) ? 1 : rawCs;
|
|
1628
|
-
const rawRs = parseInt(el.getAttribute("rowSpan") || "1", 10);
|
|
1629
|
-
const rs = isNaN(rawRs) ? 1 : rawRs;
|
|
1630
|
-
tableCtx.cell.colSpan = clampSpan(cs, _chunkITJIALN5cjs.MAX_COLS);
|
|
1631
|
-
tableCtx.cell.rowSpan = clampSpan(rs, _chunkITJIALN5cjs.MAX_ROWS);
|
|
1632
|
-
}
|
|
1633
|
-
break;
|
|
1634
|
-
case "p": {
|
|
1635
|
-
const { text: rawText, href, footnote, style } = extractParagraphInfo(el, ctx.styleMap, ctx);
|
|
1636
|
-
let text = rawText;
|
|
1637
|
-
let headingLevel;
|
|
1638
|
-
if (text) {
|
|
1639
|
-
const ph = resolveParaHeading(el, ctx);
|
|
1640
|
-
if (_optionalChain([ph, 'optionalAccess', _36 => _36.prefix])) text = ph.prefix + " " + text;
|
|
1641
|
-
headingLevel = _optionalChain([ph, 'optionalAccess', _37 => _37.headingLevel]);
|
|
1642
|
-
}
|
|
1643
|
-
if (text) {
|
|
1644
|
-
if (_optionalChain([tableCtx, 'optionalAccess', _38 => _38.cell])) {
|
|
1645
|
-
const cell = tableCtx.cell;
|
|
1646
|
-
if (footnote) text += ` (\uC8FC: ${footnote})`;
|
|
1647
|
-
cell.text += (cell.text ? "\n" : "") + text;
|
|
1648
|
-
(cell.blocks ??= []).push({ type: "paragraph", text, pageNumber: ctx.sectionNum });
|
|
1649
|
-
} else if (!tableCtx) {
|
|
1650
|
-
const block = { type: headingLevel ? "heading" : "paragraph", text, pageNumber: ctx.sectionNum };
|
|
1651
|
-
if (headingLevel) block.level = headingLevel;
|
|
1652
|
-
if (style) block.style = style;
|
|
1653
|
-
if (href) block.href = href;
|
|
1654
|
-
if (footnote) block.footnoteText = footnote;
|
|
1655
|
-
blocks.push(block);
|
|
1656
|
-
} else {
|
|
1657
|
-
blocks.push({ type: "paragraph", text, pageNumber: ctx.sectionNum });
|
|
1658
|
-
}
|
|
1659
|
-
}
|
|
1660
|
-
tableCtx = walkParagraphChildren(el, blocks, tableCtx, tableStack, ctx, depth + 1);
|
|
1661
|
-
break;
|
|
1662
|
-
}
|
|
1663
|
-
// 이미지/그림/글상자 — 이미지·텍스트·캡션 병행 추출
|
|
1664
|
-
case "pic":
|
|
1665
|
-
case "shape":
|
|
1666
|
-
case "drawingObject": {
|
|
1667
|
-
if (_optionalChain([tableCtx, 'optionalAccess', _39 => _39.cell])) {
|
|
1668
|
-
const sink = [];
|
|
1669
|
-
handleShape(el, sink, ctx);
|
|
1670
|
-
mergeBlocksIntoCell(tableCtx.cell, sink);
|
|
1671
|
-
} else {
|
|
1672
|
-
handleShape(el, blocks, ctx);
|
|
1673
|
-
}
|
|
1674
|
-
break;
|
|
1675
|
-
}
|
|
1676
|
-
// 메모 — 본문 혼입 차단 (v3.0)
|
|
1677
|
-
case "memogroup":
|
|
1678
|
-
case "memo": {
|
|
1679
|
-
if (ctx.warnings && extractTextFromNode(el)) {
|
|
1680
|
-
ctx.warnings.push({ page: ctx.sectionNum, message: "\uBA54\uBAA8 \uD14D\uC2A4\uD2B8 \uBCF8\uBB38 \uC81C\uC678: memogroup", code: "HIDDEN_TEXT_FILTERED" });
|
|
1681
|
-
}
|
|
1682
|
-
break;
|
|
1683
|
-
}
|
|
1684
|
-
default:
|
|
1685
|
-
walkSection(el, blocks, tableCtx, tableStack, ctx, depth + 1);
|
|
1686
|
-
break;
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
function handleShape(el, sink, ctx) {
|
|
1691
|
-
const imgRef = extractImageRef(el);
|
|
1692
|
-
const drawTextChild = findDescendant(el, "drawText");
|
|
1693
|
-
if (imgRef) {
|
|
1694
|
-
const block = { type: "image", text: imgRef, pageNumber: ctx.sectionNum };
|
|
1695
|
-
const alt = userShapeComment(el);
|
|
1696
|
-
if (alt) block.footnoteText = alt;
|
|
1697
|
-
sink.push(block);
|
|
1698
|
-
}
|
|
1699
|
-
if (drawTextChild) {
|
|
1700
|
-
extractDrawTextBlocks(drawTextChild, sink, ctx);
|
|
1701
|
-
}
|
|
1702
|
-
const capEl = findChildByLocalName(el, "caption");
|
|
1703
|
-
if (capEl) {
|
|
1704
|
-
const capText = collectSubListText(capEl, ctx);
|
|
1705
|
-
if (capText) sink.push({ type: "paragraph", text: capText, pageNumber: ctx.sectionNum });
|
|
1706
|
-
}
|
|
1707
|
-
if (!imgRef && !drawTextChild && ctx.warnings && ctx.sectionNum) {
|
|
1708
|
-
const localTag = (el.tagName || el.localName || "").replace(/^[^:]+:/, "");
|
|
1709
|
-
ctx.warnings.push({ page: ctx.sectionNum, message: `\uC2A4\uD0B5\uB41C \uC694\uC18C: ${localTag}`, code: "SKIPPED_IMAGE" });
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
function userShapeComment(el) {
|
|
1713
|
-
const commentEl = findChildByLocalName(el, "shapeComment");
|
|
1714
|
-
if (!commentEl) return void 0;
|
|
1715
|
-
const text = extractTextFromNode(commentEl);
|
|
1716
|
-
if (!text) return void 0;
|
|
1717
|
-
if (/^그림입니다/.test(text)) return void 0;
|
|
1718
|
-
if (/^(?:모서리가 둥근 |둥근 )?[^\n]{1,20}입니다\.?$/.test(text)) return void 0;
|
|
1719
|
-
return text;
|
|
1720
|
-
}
|
|
1721
|
-
function mergeBlocksIntoCell(cell, sink) {
|
|
1722
|
-
for (const b of sink) {
|
|
1723
|
-
if ((b.type === "paragraph" || b.type === "heading") && b.text) {
|
|
1724
|
-
cell.text += (cell.text ? "\n" : "") + b.text;
|
|
1725
|
-
(cell.blocks ??= []).push(b);
|
|
1726
|
-
} else if (b.type === "image" || b.type === "table") {
|
|
1727
|
-
if (b.type === "image" && b.text) {
|
|
1728
|
-
cell.text += (cell.text ? "\n" : "") + ``;
|
|
1729
|
-
}
|
|
1730
|
-
;
|
|
1731
|
-
(cell.blocks ??= []).push(b);
|
|
1732
|
-
cell.hasStructure = true;
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
function collectSubListText(el, ctx, depth = 0) {
|
|
1737
|
-
if (depth > 10) return "";
|
|
1738
|
-
const parts = [];
|
|
1739
|
-
const children = el.childNodes;
|
|
1740
|
-
if (!children) return "";
|
|
1741
|
-
for (let i = 0; i < children.length; i++) {
|
|
1742
|
-
const ch = children[i];
|
|
1743
|
-
if (ch.nodeType !== 1) continue;
|
|
1744
|
-
const tag = (ch.tagName || ch.localName || "").replace(/^[^:]+:/, "");
|
|
1745
|
-
if (tag === "p" || tag === "para") {
|
|
1746
|
-
const t = extractParagraphInfo(ch, ctx.styleMap, ctx).text;
|
|
1747
|
-
if (t) parts.push(t);
|
|
1748
|
-
} else if (tag === "tbl") {
|
|
1749
|
-
continue;
|
|
1750
|
-
} else {
|
|
1751
|
-
const t = collectSubListText(ch, ctx, depth + 1);
|
|
1752
|
-
if (t) parts.push(t);
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
|
-
return parts.join("\n").trim();
|
|
1756
|
-
}
|
|
1757
|
-
function walkParagraphChildren(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
|
|
1758
|
-
if (depth > MAX_XML_DEPTH) return tableCtx;
|
|
1759
|
-
const children = node.childNodes;
|
|
1760
|
-
if (!children) return tableCtx;
|
|
1761
|
-
const walkChildren = (parent, d) => {
|
|
1762
|
-
if (d > MAX_XML_DEPTH) return;
|
|
1763
|
-
const kids2 = parent.childNodes;
|
|
1764
|
-
if (!kids2) return;
|
|
1765
|
-
for (let i = 0; i < kids2.length; i++) {
|
|
1766
|
-
const el = kids2[i];
|
|
1767
|
-
if (el.nodeType !== 1) continue;
|
|
1768
|
-
const tag = el.tagName || el.localName || "";
|
|
1769
|
-
const localTag = tag.replace(/^[^:]+:/, "");
|
|
1770
|
-
if (localTag === "tbl") {
|
|
1771
|
-
if (tableCtx) tableStack.push(tableCtx);
|
|
1772
|
-
const newTable = { rows: [], currentRow: [], cell: null };
|
|
1773
|
-
walkSection(el, blocks, newTable, tableStack, ctx, d + 1);
|
|
1774
|
-
tableCtx = completeTable(newTable, tableStack, blocks, ctx);
|
|
1775
|
-
} else if (localTag === "pic" || localTag === "shape" || localTag === "drawingObject") {
|
|
1776
|
-
if (_optionalChain([tableCtx, 'optionalAccess', _40 => _40.cell])) {
|
|
1777
|
-
const sink = [];
|
|
1778
|
-
handleShape(el, sink, ctx);
|
|
1779
|
-
mergeBlocksIntoCell(tableCtx.cell, sink);
|
|
1780
|
-
} else {
|
|
1781
|
-
handleShape(el, blocks, ctx);
|
|
1782
|
-
}
|
|
1783
|
-
} else if (localTag === "drawText") {
|
|
1784
|
-
if (_optionalChain([tableCtx, 'optionalAccess', _41 => _41.cell])) {
|
|
1785
|
-
const sink = [];
|
|
1786
|
-
extractDrawTextBlocks(el, sink, ctx);
|
|
1787
|
-
mergeBlocksIntoCell(tableCtx.cell, sink);
|
|
1788
|
-
} else {
|
|
1789
|
-
extractDrawTextBlocks(el, blocks, ctx);
|
|
1790
|
-
}
|
|
1791
|
-
} else if (localTag === "r" || localTag === "run" || localTag === "ctrl" || localTag === "rect" || localTag === "ellipse" || localTag === "polygon" || localTag === "line" || localTag === "arc" || localTag === "curve" || localTag === "connectLine" || localTag === "container") {
|
|
1792
|
-
walkChildren(el, d + 1);
|
|
1793
|
-
}
|
|
1794
|
-
}
|
|
1795
|
-
};
|
|
1796
|
-
walkChildren(node, depth);
|
|
1797
|
-
return tableCtx;
|
|
1798
|
-
}
|
|
1799
|
-
function findDescendant(node, targetTag, depth = 0) {
|
|
1800
|
-
if (depth > 5) return null;
|
|
1801
|
-
const children = node.childNodes;
|
|
1802
|
-
if (!children) return null;
|
|
1803
|
-
for (let i = 0; i < children.length; i++) {
|
|
1804
|
-
const child = children[i];
|
|
1805
|
-
if (child.nodeType !== 1) continue;
|
|
1806
|
-
const tag = (child.tagName || child.localName || "").replace(/^[^:]+:/, "");
|
|
1807
|
-
if (tag === targetTag) return child;
|
|
1808
|
-
const found = findDescendant(child, targetTag, depth + 1);
|
|
1809
|
-
if (found) return found;
|
|
1810
|
-
}
|
|
1811
|
-
return null;
|
|
1812
|
-
}
|
|
1813
|
-
function extractDrawTextBlocks(drawTextNode, blocks, ctx) {
|
|
1814
|
-
const children = drawTextNode.childNodes;
|
|
1815
|
-
if (!children) return;
|
|
1816
|
-
for (let i = 0; i < children.length; i++) {
|
|
1817
|
-
const child = children[i];
|
|
1818
|
-
if (child.nodeType !== 1) continue;
|
|
1819
|
-
const tag = (child.tagName || child.localName || "").replace(/^[^:]+:/, "");
|
|
1820
|
-
if (tag === "subList" || tag === "p" || tag === "para") {
|
|
1821
|
-
if (tag === "subList") {
|
|
1822
|
-
extractDrawTextBlocks(child, blocks, ctx);
|
|
1823
|
-
} else {
|
|
1824
|
-
const info = extractParagraphInfo(child, ctx.styleMap, ctx);
|
|
1825
|
-
let text = info.text.trim();
|
|
1826
|
-
if (text) {
|
|
1827
|
-
const ph = resolveParaHeading(child, ctx);
|
|
1828
|
-
if (_optionalChain([ph, 'optionalAccess', _42 => _42.prefix])) text = ph.prefix + " " + text;
|
|
1829
|
-
const block = { type: "paragraph", text, style: _nullishCoalesce(info.style, () => ( void 0)), pageNumber: ctx.sectionNum };
|
|
1830
|
-
if (info.href) block.href = info.href;
|
|
1831
|
-
if (info.footnote) block.footnoteText = info.footnote;
|
|
1832
|
-
blocks.push(block);
|
|
1833
|
-
}
|
|
1834
|
-
walkParagraphChildren(child, blocks, null, [], ctx);
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1838
|
-
}
|
|
1839
|
-
function extractHyperlinkHref(fieldBegin) {
|
|
1840
|
-
if ((fieldBegin.getAttribute("type") || "").toUpperCase() !== "HYPERLINK") return void 0;
|
|
1841
|
-
const params = findChildByLocalName(fieldBegin, "parameters");
|
|
1842
|
-
if (!params) return void 0;
|
|
1843
|
-
const children = params.childNodes;
|
|
1844
|
-
if (!children) return void 0;
|
|
1845
|
-
for (let i = 0; i < children.length; i++) {
|
|
1846
|
-
const ch = children[i];
|
|
1847
|
-
if (ch.nodeType !== 1) continue;
|
|
1848
|
-
const tag = (ch.tagName || ch.localName || "").replace(/^[^:]+:/, "");
|
|
1849
|
-
if (tag !== "stringParam" || ch.getAttribute("name") !== "Path") continue;
|
|
1850
|
-
let url = (ch.textContent || "").trim();
|
|
1851
|
-
if (!url) continue;
|
|
1852
|
-
url = url.replace(/^https?:\/\/(?=https?:\/\/)/i, "");
|
|
1853
|
-
const safe = _chunkITJIALN5cjs.sanitizeHref.call(void 0, url);
|
|
1854
|
-
if (safe) return safe;
|
|
1550
|
+
function extractHyperlinkHref(fieldBegin) {
|
|
1551
|
+
if ((fieldBegin.getAttribute("type") || "").toUpperCase() !== "HYPERLINK") return void 0;
|
|
1552
|
+
const params = findChildByLocalName(fieldBegin, "parameters");
|
|
1553
|
+
if (!params) return void 0;
|
|
1554
|
+
const children = params.childNodes;
|
|
1555
|
+
if (!children) return void 0;
|
|
1556
|
+
for (let i = 0; i < children.length; i++) {
|
|
1557
|
+
const ch = children[i];
|
|
1558
|
+
if (ch.nodeType !== 1) continue;
|
|
1559
|
+
const tag = (ch.tagName || ch.localName || "").replace(/^[^:]+:/, "");
|
|
1560
|
+
if (tag !== "stringParam" || ch.getAttribute("name") !== "Path") continue;
|
|
1561
|
+
let url = (ch.textContent || "").trim();
|
|
1562
|
+
if (!url) continue;
|
|
1563
|
+
url = url.replace(/^https?:\/\/(?=https?:\/\/)/i, "");
|
|
1564
|
+
const safe = _chunkLFCS3UVGcjs.sanitizeHref.call(void 0, url);
|
|
1565
|
+
if (safe) return safe;
|
|
1855
1566
|
}
|
|
1856
1567
|
return void 0;
|
|
1857
1568
|
}
|
|
1858
1569
|
function isInDeletedRange(ctx) {
|
|
1859
|
-
return (_nullishCoalesce(_optionalChain([ctx, 'optionalAccess',
|
|
1570
|
+
return (_nullishCoalesce(_optionalChain([ctx, 'optionalAccess', _31 => _31.shared, 'access', _32 => _32.track, 'access', _33 => _33.deleteDepth]), () => ( 0))) > 0;
|
|
1860
1571
|
}
|
|
1861
1572
|
function extractParagraphInfo(para, styleMap, ctx) {
|
|
1862
1573
|
let text = "";
|
|
@@ -1910,7 +1621,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
|
|
|
1910
1621
|
// 삽입분은 최종본에 포함
|
|
1911
1622
|
// 숨은 설명 — 본문 혼입 차단
|
|
1912
1623
|
case "hiddenComment": {
|
|
1913
|
-
if (_optionalChain([ctx, 'optionalAccess',
|
|
1624
|
+
if (_optionalChain([ctx, 'optionalAccess', _34 => _34.warnings]) && extractTextFromNode(k)) {
|
|
1914
1625
|
ctx.warnings.push({ page: ctx.sectionNum, message: "\uC228\uC740 \uC124\uBA85 \uD14D\uC2A4\uD2B8 \uC81C\uC678: hiddenComment", code: "HIDDEN_TEXT_FILTERED" });
|
|
1915
1626
|
}
|
|
1916
1627
|
break;
|
|
@@ -1927,7 +1638,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
|
|
|
1927
1638
|
break;
|
|
1928
1639
|
// 미지원 요소 — 텍스트를 가졌으면 무음 손실 대신 경고
|
|
1929
1640
|
default: {
|
|
1930
|
-
if (_optionalChain([ctx, 'optionalAccess',
|
|
1641
|
+
if (_optionalChain([ctx, 'optionalAccess', _35 => _35.warnings]) && extractTextFromNode(k)) {
|
|
1931
1642
|
ctx.warnings.push({ page: ctx.sectionNum, message: `\uBBF8\uC9C0\uC6D0 \uC81C\uC5B4 \uC694\uC18C\uC758 \uD14D\uC2A4\uD2B8 \uC190\uC2E4: ${ktag}`, code: "UNSUPPORTED_ELEMENT" });
|
|
1932
1643
|
}
|
|
1933
1644
|
}
|
|
@@ -1944,7 +1655,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
|
|
|
1944
1655
|
if (isInDeletedRange(ctx)) {
|
|
1945
1656
|
if (t && ctx && !ctx.shared.track.warned) {
|
|
1946
1657
|
ctx.shared.track.warned = true;
|
|
1947
|
-
_optionalChain([ctx, 'access',
|
|
1658
|
+
_optionalChain([ctx, 'access', _36 => _36.warnings, 'optionalAccess', _37 => _37.push, 'call', _38 => _38({ page: ctx.sectionNum, message: "\uBCC0\uACBD\uCD94\uC801 \uC0AD\uC81C \uD14D\uC2A4\uD2B8 \uCD9C\uB825 \uC81C\uC678", code: "HIDDEN_TEXT_FILTERED" })]);
|
|
1948
1659
|
}
|
|
1949
1660
|
} else {
|
|
1950
1661
|
text += t;
|
|
@@ -1985,7 +1696,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
|
|
|
1985
1696
|
case "hyperlink": {
|
|
1986
1697
|
const url = child.getAttribute("url") || child.getAttribute("href") || "";
|
|
1987
1698
|
if (url) {
|
|
1988
|
-
const safe =
|
|
1699
|
+
const safe = _chunkLFCS3UVGcjs.sanitizeHref.call(void 0, url);
|
|
1989
1700
|
if (safe) href = safe;
|
|
1990
1701
|
}
|
|
1991
1702
|
walk(child);
|
|
@@ -2050,66 +1761,374 @@ function extractParagraphInfo(para, styleMap, ctx) {
|
|
|
2050
1761
|
try {
|
|
2051
1762
|
const latex = hmlToLatex(raw).trim();
|
|
2052
1763
|
if (latex) text += " $" + latex + "$ ";
|
|
2053
|
-
} catch (
|
|
1764
|
+
} catch (e12) {
|
|
2054
1765
|
}
|
|
2055
1766
|
}
|
|
2056
|
-
break;
|
|
1767
|
+
break;
|
|
1768
|
+
}
|
|
1769
|
+
// run 요소에서 charPrIDRef 추출
|
|
1770
|
+
case "r": {
|
|
1771
|
+
const runCharPr = child.getAttribute("charPrIDRef");
|
|
1772
|
+
if (runCharPr && !charPrId) charPrId = runCharPr;
|
|
1773
|
+
walk(child);
|
|
1774
|
+
break;
|
|
1775
|
+
}
|
|
1776
|
+
default:
|
|
1777
|
+
walk(child);
|
|
1778
|
+
break;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
};
|
|
1782
|
+
walk(para);
|
|
1783
|
+
const leaderIdx = text.indexOf("");
|
|
1784
|
+
if (leaderIdx >= 0) text = text.substring(0, leaderIdx);
|
|
1785
|
+
let cleanText = text.replace(/[ \t]+/g, " ").trim();
|
|
1786
|
+
if (/^그림입니다\.?\s*원본\s*그림의\s*(이름|크기)/.test(cleanText)) cleanText = "";
|
|
1787
|
+
cleanText = cleanText.replace(/그림입니다\.?\s*원본\s*그림의\s*(이름|크기)[^\n]*(\n[^\n]*원본\s*그림의\s*(이름|크기)[^\n]*)*/g, "").trim();
|
|
1788
|
+
cleanText = cleanText.replace(/(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|선|직선|곡선|화살표|오각형|육각형|팔각형|별|십자|구름|마름모|도넛|평행사변형|사다리꼴|개체|그리기\s?개체|묶음\s?개체|글상자|표|그림|OLE\s?개체)\s?입니다\.?/g, "").trim();
|
|
1789
|
+
let style;
|
|
1790
|
+
if (styleMap && charPrId) {
|
|
1791
|
+
const charProp = styleMap.charProperties.get(charPrId);
|
|
1792
|
+
if (charProp) {
|
|
1793
|
+
style = {};
|
|
1794
|
+
if (charProp.fontSize) style.fontSize = charProp.fontSize;
|
|
1795
|
+
if (charProp.bold) style.bold = true;
|
|
1796
|
+
if (charProp.italic) style.italic = true;
|
|
1797
|
+
if (charProp.fontName) style.fontName = charProp.fontName;
|
|
1798
|
+
if (!style.fontSize && !style.bold && !style.italic) style = void 0;
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
return { text: cleanText, href, footnote, style };
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
// src/hwpx/images.ts
|
|
1805
|
+
function imageExtToMime(ext) {
|
|
1806
|
+
switch (ext.toLowerCase()) {
|
|
1807
|
+
case "jpg":
|
|
1808
|
+
case "jpeg":
|
|
1809
|
+
return "image/jpeg";
|
|
1810
|
+
case "png":
|
|
1811
|
+
return "image/png";
|
|
1812
|
+
case "gif":
|
|
1813
|
+
return "image/gif";
|
|
1814
|
+
case "bmp":
|
|
1815
|
+
return "image/bmp";
|
|
1816
|
+
case "tif":
|
|
1817
|
+
case "tiff":
|
|
1818
|
+
return "image/tiff";
|
|
1819
|
+
case "wmf":
|
|
1820
|
+
return "image/wmf";
|
|
1821
|
+
case "emf":
|
|
1822
|
+
return "image/emf";
|
|
1823
|
+
case "svg":
|
|
1824
|
+
return "image/svg+xml";
|
|
1825
|
+
default:
|
|
1826
|
+
return "application/octet-stream";
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
function mimeToExt(mime) {
|
|
1830
|
+
if (mime.includes("jpeg")) return "jpg";
|
|
1831
|
+
if (mime.includes("png")) return "png";
|
|
1832
|
+
if (mime.includes("gif")) return "gif";
|
|
1833
|
+
if (mime.includes("bmp")) return "bmp";
|
|
1834
|
+
if (mime.includes("tiff")) return "tif";
|
|
1835
|
+
if (mime.includes("wmf")) return "wmf";
|
|
1836
|
+
if (mime.includes("emf")) return "emf";
|
|
1837
|
+
if (mime.includes("svg")) return "svg";
|
|
1838
|
+
return "bin";
|
|
1839
|
+
}
|
|
1840
|
+
function collectImageBlocks(blocks, out, ownerCell, depth = 0) {
|
|
1841
|
+
if (depth > MAX_XML_DEPTH) return;
|
|
1842
|
+
for (const block of blocks) {
|
|
1843
|
+
if (block.type === "image") {
|
|
1844
|
+
out.push({ block, ownerCell });
|
|
1845
|
+
} else if (block.type === "table" && block.table) {
|
|
1846
|
+
for (const row of block.table.cells) {
|
|
1847
|
+
for (const cell of row) {
|
|
1848
|
+
if (_optionalChain([cell, 'access', _39 => _39.blocks, 'optionalAccess', _40 => _40.length])) collectImageBlocks(cell.blocks, out, cell, depth + 1);
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
async function extractImagesFromZip(zip, blocks, decompressed, warnings) {
|
|
1855
|
+
const images = [];
|
|
1856
|
+
let imageIndex = 0;
|
|
1857
|
+
const imageBlocks = [];
|
|
1858
|
+
collectImageBlocks(blocks, imageBlocks);
|
|
1859
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
1860
|
+
for (const { block, ownerCell } of imageBlocks) {
|
|
1861
|
+
if (block.type !== "image" || !block.text) continue;
|
|
1862
|
+
const ref = block.text;
|
|
1863
|
+
let img = resolved.get(ref);
|
|
1864
|
+
if (img === void 0) {
|
|
1865
|
+
img = null;
|
|
1866
|
+
const candidates = [
|
|
1867
|
+
`BinData/${ref}`,
|
|
1868
|
+
`Contents/BinData/${ref}`,
|
|
1869
|
+
ref
|
|
1870
|
+
// 절대 경로일 수도 있음
|
|
1871
|
+
];
|
|
1872
|
+
let resolvedPath = null;
|
|
1873
|
+
if (!ref.includes(".")) {
|
|
1874
|
+
const prefixes = [`BinData/${ref}`, `Contents/BinData/${ref}`];
|
|
1875
|
+
for (const prefix of prefixes) {
|
|
1876
|
+
const match = zip.file(new RegExp(`^${prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.[a-zA-Z0-9]+$`));
|
|
1877
|
+
if (match.length > 0) {
|
|
1878
|
+
resolvedPath = match[0].name;
|
|
1879
|
+
break;
|
|
1880
|
+
}
|
|
2057
1881
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
1882
|
+
}
|
|
1883
|
+
const allCandidates = resolvedPath ? [resolvedPath, ...candidates] : candidates;
|
|
1884
|
+
for (const path of allCandidates) {
|
|
1885
|
+
if (_chunkLFCS3UVGcjs.isPathTraversal.call(void 0, path)) continue;
|
|
1886
|
+
const file = zip.file(path);
|
|
1887
|
+
if (!file) continue;
|
|
1888
|
+
try {
|
|
1889
|
+
const data = await file.async("uint8array");
|
|
1890
|
+
decompressed.total += data.length;
|
|
1891
|
+
if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
|
|
1892
|
+
const ext = path.includes(".") ? path.split(".").pop() || "png" : "png";
|
|
1893
|
+
const mimeType = imageExtToMime(ext);
|
|
1894
|
+
imageIndex++;
|
|
1895
|
+
const filename = `image_${String(imageIndex).padStart(3, "0")}.${mimeToExt(mimeType)}`;
|
|
1896
|
+
img = { filename, data, mimeType };
|
|
1897
|
+
images.push(img);
|
|
2063
1898
|
break;
|
|
1899
|
+
} catch (err) {
|
|
1900
|
+
if (err instanceof _chunkLFCS3UVGcjs.KordocError) throw err;
|
|
2064
1901
|
}
|
|
2065
|
-
default:
|
|
2066
|
-
walk(child);
|
|
2067
|
-
break;
|
|
2068
1902
|
}
|
|
1903
|
+
if (!img) _optionalChain([warnings, 'optionalAccess', _41 => _41.push, 'call', _42 => _42({ page: block.pageNumber, message: `\uC774\uBBF8\uC9C0 \uD30C\uC77C \uC5C6\uC74C: ${ref}`, code: "SKIPPED_IMAGE" })]);
|
|
1904
|
+
resolved.set(ref, img);
|
|
2069
1905
|
}
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
if (/^그림입니다\.?\s*원본\s*그림의\s*(이름|크기)/.test(cleanText)) cleanText = "";
|
|
2076
|
-
cleanText = cleanText.replace(/그림입니다\.?\s*원본\s*그림의\s*(이름|크기)[^\n]*(\n[^\n]*원본\s*그림의\s*(이름|크기)[^\n]*)*/g, "").trim();
|
|
2077
|
-
cleanText = cleanText.replace(/(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|선|직선|곡선|화살표|오각형|육각형|팔각형|별|십자|구름|마름모|도넛|평행사변형|사다리꼴|개체|그리기\s?개체|묶음\s?개체|글상자|표|그림|OLE\s?개체)\s?입니다\.?/g, "").trim();
|
|
2078
|
-
let style;
|
|
2079
|
-
if (styleMap && charPrId) {
|
|
2080
|
-
const charProp = styleMap.charProperties.get(charPrId);
|
|
2081
|
-
if (charProp) {
|
|
2082
|
-
style = {};
|
|
2083
|
-
if (charProp.fontSize) style.fontSize = charProp.fontSize;
|
|
2084
|
-
if (charProp.bold) style.bold = true;
|
|
2085
|
-
if (charProp.italic) style.italic = true;
|
|
2086
|
-
if (charProp.fontName) style.fontName = charProp.fontName;
|
|
2087
|
-
if (!style.fontSize && !style.bold && !style.italic) style = void 0;
|
|
1906
|
+
if (!img) {
|
|
1907
|
+
block.type = "paragraph";
|
|
1908
|
+
block.text = `[\uC774\uBBF8\uC9C0: ${ref}]`;
|
|
1909
|
+
if (ownerCell) ownerCell.text = ownerCell.text.replace(``, `[\uC774\uBBF8\uC9C0: ${ref}]`);
|
|
1910
|
+
continue;
|
|
2088
1911
|
}
|
|
1912
|
+
block.text = img.filename;
|
|
1913
|
+
block.imageData = { data: img.data, mimeType: img.mimeType, filename: ref };
|
|
1914
|
+
if (ownerCell) ownerCell.text = ownerCell.text.replace(``, ``);
|
|
2089
1915
|
}
|
|
2090
|
-
return
|
|
1916
|
+
return images;
|
|
2091
1917
|
}
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
1918
|
+
|
|
1919
|
+
// src/hwpx/metadata.ts
|
|
1920
|
+
|
|
1921
|
+
|
|
1922
|
+
// src/hwpx/zip-sections.ts
|
|
1923
|
+
var _zlib = require('zlib');
|
|
1924
|
+
function extractFromBrokenZip(buffer) {
|
|
1925
|
+
const data = new Uint8Array(buffer);
|
|
1926
|
+
const view = new DataView(buffer);
|
|
1927
|
+
let pos = 0;
|
|
1928
|
+
const blocks = [];
|
|
1929
|
+
const warnings = [
|
|
1930
|
+
{ code: "BROKEN_ZIP_RECOVERY", message: "\uC190\uC0C1\uB41C ZIP \uAD6C\uC870 \u2014 Local File Header \uAE30\uBC18 \uBCF5\uAD6C \uBAA8\uB4DC" }
|
|
1931
|
+
];
|
|
1932
|
+
let totalDecompressed = 0;
|
|
1933
|
+
let entryCount = 0;
|
|
1934
|
+
let sectionNum = 0;
|
|
1935
|
+
const shared = createSectionShared();
|
|
1936
|
+
while (pos < data.length - 30) {
|
|
1937
|
+
if (data[pos] !== 80 || data[pos + 1] !== 75 || data[pos + 2] !== 3 || data[pos + 3] !== 4) {
|
|
1938
|
+
pos++;
|
|
1939
|
+
while (pos < data.length - 30) {
|
|
1940
|
+
if (data[pos] === 80 && data[pos + 1] === 75 && data[pos + 2] === 3 && data[pos + 3] === 4) break;
|
|
1941
|
+
pos++;
|
|
1942
|
+
}
|
|
1943
|
+
continue;
|
|
1944
|
+
}
|
|
1945
|
+
if (++entryCount > MAX_ZIP_ENTRIES) break;
|
|
1946
|
+
const method = view.getUint16(pos + 8, true);
|
|
1947
|
+
const compSize = view.getUint32(pos + 18, true);
|
|
1948
|
+
const nameLen = view.getUint16(pos + 26, true);
|
|
1949
|
+
const extraLen = view.getUint16(pos + 28, true);
|
|
1950
|
+
if (nameLen > 1024 || extraLen > 65535) {
|
|
1951
|
+
pos += 30 + nameLen + extraLen;
|
|
1952
|
+
continue;
|
|
1953
|
+
}
|
|
1954
|
+
const fileStart = pos + 30 + nameLen + extraLen;
|
|
1955
|
+
if (fileStart + compSize > data.length) break;
|
|
1956
|
+
if (compSize === 0 && method !== 0) {
|
|
1957
|
+
pos = fileStart;
|
|
1958
|
+
continue;
|
|
1959
|
+
}
|
|
1960
|
+
const nameBytes = data.slice(pos + 30, pos + 30 + nameLen);
|
|
1961
|
+
const name = new TextDecoder().decode(nameBytes);
|
|
1962
|
+
if (_chunkLFCS3UVGcjs.isPathTraversal.call(void 0, name)) {
|
|
1963
|
+
pos = fileStart + compSize;
|
|
1964
|
+
continue;
|
|
1965
|
+
}
|
|
1966
|
+
const fileData = data.slice(fileStart, fileStart + compSize);
|
|
1967
|
+
pos = fileStart + compSize;
|
|
1968
|
+
if (!name.toLowerCase().includes("section") || !name.endsWith(".xml")) continue;
|
|
1969
|
+
try {
|
|
1970
|
+
let content;
|
|
1971
|
+
if (method === 0) {
|
|
1972
|
+
content = new TextDecoder().decode(fileData);
|
|
1973
|
+
} else if (method === 8) {
|
|
1974
|
+
const decompressed = _zlib.inflateRawSync.call(void 0, Buffer.from(fileData), { maxOutputLength: MAX_DECOMPRESS_SIZE });
|
|
1975
|
+
content = new TextDecoder().decode(decompressed);
|
|
1976
|
+
} else {
|
|
1977
|
+
continue;
|
|
1978
|
+
}
|
|
1979
|
+
totalDecompressed += content.length * 2;
|
|
1980
|
+
if (totalDecompressed > MAX_DECOMPRESS_SIZE) throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC");
|
|
1981
|
+
sectionNum++;
|
|
1982
|
+
blocks.push(...parseSectionXml(content, void 0, warnings, sectionNum, shared));
|
|
1983
|
+
} catch (e13) {
|
|
1984
|
+
continue;
|
|
1985
|
+
}
|
|
2100
1986
|
}
|
|
2101
|
-
|
|
1987
|
+
if (blocks.length === 0) throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uC190\uC0C1\uB41C HWPX\uC5D0\uC11C \uC139\uC158 \uB370\uC774\uD130\uB97C \uBCF5\uAD6C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
1988
|
+
applyPageText(blocks, shared);
|
|
1989
|
+
const markdown = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, blocks);
|
|
1990
|
+
return { markdown, blocks, warnings: warnings.length > 0 ? warnings : void 0 };
|
|
2102
1991
|
}
|
|
2103
|
-
function
|
|
2104
|
-
|
|
2105
|
-
const
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
1992
|
+
async function resolveSectionPaths(zip) {
|
|
1993
|
+
const manifestPaths = ["Contents/content.hpf", "content.hpf"];
|
|
1994
|
+
for (const mp of manifestPaths) {
|
|
1995
|
+
const mpLower = mp.toLowerCase();
|
|
1996
|
+
const file = zip.file(mp) || Object.values(zip.files).find((f) => f.name.toLowerCase() === mpLower) || null;
|
|
1997
|
+
if (!file) continue;
|
|
1998
|
+
const xml = await file.async("text");
|
|
1999
|
+
const paths = parseSectionPathsFromManifest(xml);
|
|
2000
|
+
if (paths.length > 0) return paths;
|
|
2111
2001
|
}
|
|
2112
|
-
|
|
2002
|
+
const sectionFiles = zip.file(/[Ss]ection\d+\.xml$/);
|
|
2003
|
+
return sectionFiles.map((f) => f.name).sort(_chunkLFCS3UVGcjs.compareSectionPaths);
|
|
2004
|
+
}
|
|
2005
|
+
function parseSectionPathsFromManifest(xml) {
|
|
2006
|
+
const parser = createXmlParser();
|
|
2007
|
+
const doc = parser.parseFromString(_chunkLFCS3UVGcjs.stripDtd.call(void 0, xml), "text/xml");
|
|
2008
|
+
const items = doc.getElementsByTagName("opf:item");
|
|
2009
|
+
const spine = doc.getElementsByTagName("opf:itemref");
|
|
2010
|
+
const idToHref = /* @__PURE__ */ new Map();
|
|
2011
|
+
for (let i = 0; i < items.length; i++) {
|
|
2012
|
+
const item = items[i];
|
|
2013
|
+
const id = item.getAttribute("id") || "";
|
|
2014
|
+
const href = _chunkLFCS3UVGcjs.normalizeSectionHref.call(void 0, item.getAttribute("href") || "");
|
|
2015
|
+
if (id && href) idToHref.set(id, href);
|
|
2016
|
+
}
|
|
2017
|
+
if (spine.length > 0) {
|
|
2018
|
+
const ordered = [];
|
|
2019
|
+
for (let i = 0; i < spine.length; i++) {
|
|
2020
|
+
const href = idToHref.get(spine[i].getAttribute("idref") || "");
|
|
2021
|
+
if (href) ordered.push(href);
|
|
2022
|
+
}
|
|
2023
|
+
if (ordered.length > 0) return ordered;
|
|
2024
|
+
}
|
|
2025
|
+
return Array.from(idToHref.values()).sort(_chunkLFCS3UVGcjs.compareSectionPaths);
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
// src/hwpx/metadata.ts
|
|
2029
|
+
async function extractHwpxMetadata(zip, metadata, decompressed) {
|
|
2030
|
+
try {
|
|
2031
|
+
const metaPaths = ["meta.xml", "META-INF/meta.xml", "docProps/core.xml"];
|
|
2032
|
+
for (const mp of metaPaths) {
|
|
2033
|
+
const file = zip.file(mp) || Object.values(zip.files).find((f) => f.name.toLowerCase() === mp.toLowerCase()) || null;
|
|
2034
|
+
if (!file) continue;
|
|
2035
|
+
const xml = await file.async("text");
|
|
2036
|
+
if (decompressed) {
|
|
2037
|
+
decompressed.total += xml.length * 2;
|
|
2038
|
+
if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
|
|
2039
|
+
}
|
|
2040
|
+
parseDublinCoreMetadata(xml, metadata);
|
|
2041
|
+
if (metadata.title || metadata.author) return;
|
|
2042
|
+
}
|
|
2043
|
+
} catch (e14) {
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
function parseDublinCoreMetadata(xml, metadata) {
|
|
2047
|
+
const parser = createXmlParser();
|
|
2048
|
+
const doc = parser.parseFromString(_chunkLFCS3UVGcjs.stripDtd.call(void 0, xml), "text/xml");
|
|
2049
|
+
if (!doc.documentElement) return;
|
|
2050
|
+
const getText = (tagNames) => {
|
|
2051
|
+
for (const tag of tagNames) {
|
|
2052
|
+
const els = doc.getElementsByTagName(tag);
|
|
2053
|
+
if (els.length > 0) {
|
|
2054
|
+
const text = _optionalChain([els, 'access', _43 => _43[0], 'access', _44 => _44.textContent, 'optionalAccess', _45 => _45.trim, 'call', _46 => _46()]);
|
|
2055
|
+
if (text) return text;
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
return void 0;
|
|
2059
|
+
};
|
|
2060
|
+
metadata.title = metadata.title || getText(["dc:title", "title"]);
|
|
2061
|
+
metadata.author = metadata.author || getText(["dc:creator", "creator", "cp:lastModifiedBy"]);
|
|
2062
|
+
metadata.description = metadata.description || getText(["dc:description", "description", "dc:subject", "subject"]);
|
|
2063
|
+
metadata.createdAt = metadata.createdAt || getText(["dcterms:created", "meta:creation-date"]);
|
|
2064
|
+
metadata.modifiedAt = metadata.modifiedAt || getText(["dcterms:modified", "meta:date"]);
|
|
2065
|
+
const keywords = getText(["dc:keyword", "cp:keywords", "meta:keyword"]);
|
|
2066
|
+
if (keywords && !metadata.keywords) {
|
|
2067
|
+
metadata.keywords = keywords.split(/[,;]/).map((k) => k.trim()).filter(Boolean);
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
// src/hwpx/parser.ts
|
|
2072
|
+
async function parseHwpxDocument(buffer, options) {
|
|
2073
|
+
_chunkLFCS3UVGcjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE, MAX_ZIP_ENTRIES);
|
|
2074
|
+
let zip;
|
|
2075
|
+
try {
|
|
2076
|
+
zip = await _jszip2.default.loadAsync(buffer);
|
|
2077
|
+
} catch (e15) {
|
|
2078
|
+
return extractFromBrokenZip(buffer);
|
|
2079
|
+
}
|
|
2080
|
+
const actualEntryCount = Object.keys(zip.files).length;
|
|
2081
|
+
if (actualEntryCount > MAX_ZIP_ENTRIES) {
|
|
2082
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP \uC5D4\uD2B8\uB9AC \uC218 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
|
|
2083
|
+
}
|
|
2084
|
+
const manifestFile = zip.file("META-INF/manifest.xml");
|
|
2085
|
+
if (manifestFile) {
|
|
2086
|
+
const manifestXml = await manifestFile.async("text");
|
|
2087
|
+
if (isEncryptedHwpx(manifestXml)) {
|
|
2088
|
+
if (isComFallbackAvailable() && _optionalChain([options, 'optionalAccess', _47 => _47.filePath])) {
|
|
2089
|
+
const { pages, pageCount, warnings: warnings2 } = extractTextViaCom(options.filePath);
|
|
2090
|
+
if (pages.some((p) => p && p.trim().length > 0)) {
|
|
2091
|
+
return comResultToParseResult(pages, pageCount, warnings2);
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("DRM \uC554\uD638\uD654\uB41C HWPX \uD30C\uC77C\uC785\uB2C8\uB2E4. Windows + \uD55C\uCEF4 \uC624\uD53C\uC2A4 \uC124\uCE58 \uC2DC \uC790\uB3D9 \uCD94\uCD9C\uB429\uB2C8\uB2E4.");
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
const decompressed = { total: 0 };
|
|
2098
|
+
const metadata = {};
|
|
2099
|
+
await extractHwpxMetadata(zip, metadata, decompressed);
|
|
2100
|
+
const styleMap = await extractHwpxStyles(zip, decompressed);
|
|
2101
|
+
const warnings = [];
|
|
2102
|
+
const sectionPaths = await resolveSectionPaths(zip);
|
|
2103
|
+
if (sectionPaths.length === 0) throw new (0, _chunkLFCS3UVGcjs.KordocError)("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
2104
|
+
metadata.pageCount = sectionPaths.length;
|
|
2105
|
+
const pageFilter = _optionalChain([options, 'optionalAccess', _48 => _48.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, sectionPaths.length) : null;
|
|
2106
|
+
const totalTarget = pageFilter ? pageFilter.size : sectionPaths.length;
|
|
2107
|
+
const blocks = [];
|
|
2108
|
+
const shared = createSectionShared();
|
|
2109
|
+
let parsedSections = 0;
|
|
2110
|
+
for (let si = 0; si < sectionPaths.length; si++) {
|
|
2111
|
+
if (pageFilter && !pageFilter.has(si + 1)) continue;
|
|
2112
|
+
const file = zip.file(sectionPaths[si]);
|
|
2113
|
+
if (!file) continue;
|
|
2114
|
+
try {
|
|
2115
|
+
const xml = await file.async("text");
|
|
2116
|
+
decompressed.total += xml.length * 2;
|
|
2117
|
+
if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
|
|
2118
|
+
blocks.push(...parseSectionXml(xml, styleMap, warnings, si + 1, shared));
|
|
2119
|
+
parsedSections++;
|
|
2120
|
+
_optionalChain([options, 'optionalAccess', _49 => _49.onProgress, 'optionalCall', _50 => _50(parsedSections, totalTarget)]);
|
|
2121
|
+
} catch (secErr) {
|
|
2122
|
+
if (secErr instanceof _chunkLFCS3UVGcjs.KordocError) throw secErr;
|
|
2123
|
+
warnings.push({ page: si + 1, message: `\uC139\uC158 ${si + 1} \uD30C\uC2F1 \uC2E4\uD328: ${secErr instanceof Error ? secErr.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`, code: "PARTIAL_PARSE" });
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
applyPageText(blocks, shared);
|
|
2127
|
+
const images = await extractImagesFromZip(zip, blocks, decompressed, warnings);
|
|
2128
|
+
detectHwpxHeadings(blocks, styleMap);
|
|
2129
|
+
const outline = blocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
|
|
2130
|
+
const markdown = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, blocks);
|
|
2131
|
+
return { markdown, blocks, metadata, outline: outline.length > 0 ? outline : void 0, warnings: warnings.length > 0 ? warnings : void 0, images: images.length > 0 ? images : void 0 };
|
|
2113
2132
|
}
|
|
2114
2133
|
|
|
2115
2134
|
// src/hwp5/record.ts
|
|
@@ -2175,7 +2194,7 @@ function decompressStream(data) {
|
|
|
2175
2194
|
return _zlib.inflateRawSync.call(void 0, data, opts);
|
|
2176
2195
|
}
|
|
2177
2196
|
function parseFileHeader(data) {
|
|
2178
|
-
if (data.length < 40) throw new (0,
|
|
2197
|
+
if (data.length < 40) throw new (0, _chunkLFCS3UVGcjs.KordocError)("FileHeader\uAC00 \uB108\uBB34 \uC9E7\uC2B5\uB2C8\uB2E4 (\uCD5C\uC18C 40\uBC14\uC774\uD2B8)");
|
|
2179
2198
|
const sig = data.subarray(0, 32).toString("utf8").replace(/\0+$/, "");
|
|
2180
2199
|
return {
|
|
2181
2200
|
signature: sig,
|
|
@@ -3709,7 +3728,7 @@ function parseHwp5Document(buffer, options) {
|
|
|
3709
3728
|
lenientCfb = parseLenientCfb(buffer);
|
|
3710
3729
|
warnings.push({ message: "\uC190\uC0C1\uB41C CFB \uCEE8\uD14C\uC774\uB108 \u2014 lenient \uBAA8\uB4DC\uB85C \uBCF5\uAD6C", code: "LENIENT_CFB_RECOVERY" });
|
|
3711
3730
|
} catch (e21) {
|
|
3712
|
-
throw new (0,
|
|
3731
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("CFB \uCEE8\uD14C\uC774\uB108 \uD30C\uC2F1 \uC2E4\uD328 (strict \uBC0F lenient \uBAA8\uB450)");
|
|
3713
3732
|
}
|
|
3714
3733
|
}
|
|
3715
3734
|
const findStream = (path) => {
|
|
@@ -3720,11 +3739,11 @@ function parseHwp5Document(buffer, options) {
|
|
|
3720
3739
|
return lenientCfb.findStream(path);
|
|
3721
3740
|
};
|
|
3722
3741
|
const headerData = findStream("/FileHeader");
|
|
3723
|
-
if (!headerData) throw new (0,
|
|
3742
|
+
if (!headerData) throw new (0, _chunkLFCS3UVGcjs.KordocError)("FileHeader \uC2A4\uD2B8\uB9BC \uC5C6\uC74C");
|
|
3724
3743
|
const header = parseFileHeader(headerData);
|
|
3725
|
-
if (header.signature !== "HWP Document File") throw new (0,
|
|
3726
|
-
if (header.flags & FLAG_ENCRYPTED) throw new (0,
|
|
3727
|
-
if (header.flags & FLAG_DRM) throw new (0,
|
|
3744
|
+
if (header.signature !== "HWP Document File") throw new (0, _chunkLFCS3UVGcjs.KordocError)("HWP \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
|
|
3745
|
+
if (header.flags & FLAG_ENCRYPTED) throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uC554\uD638\uD654\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
3746
|
+
if (header.flags & FLAG_DRM) throw new (0, _chunkLFCS3UVGcjs.KordocError)("DRM \uBCF4\uD638\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
3728
3747
|
const compressed = (header.flags & FLAG_COMPRESSED) !== 0;
|
|
3729
3748
|
const distribution = (header.flags & FLAG_DISTRIBUTION) !== 0;
|
|
3730
3749
|
const metadata = {
|
|
@@ -3733,7 +3752,7 @@ function parseHwp5Document(buffer, options) {
|
|
|
3733
3752
|
if (cfb) extractHwp5Metadata(cfb, metadata);
|
|
3734
3753
|
const docInfo = cfb ? parseDocInfoStream(cfb, compressed) : parseDocInfoFromStream(findStream("/DocInfo"), compressed);
|
|
3735
3754
|
const sections = distribution ? cfb ? findViewTextSections(cfb, compressed) : findViewTextSectionsLenient(lenientCfb, compressed) : cfb ? findSections(cfb) : findSectionsLenient(lenientCfb, compressed);
|
|
3736
|
-
if (sections.length === 0) throw new (0,
|
|
3755
|
+
if (sections.length === 0) throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uC139\uC158 \uC2A4\uD2B8\uB9BC\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
3737
3756
|
metadata.pageCount = sections.length;
|
|
3738
3757
|
const pageFilter = _optionalChain([options, 'optionalAccess', _54 => _54.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, sections.length) : null;
|
|
3739
3758
|
const totalTarget = pageFilter ? pageFilter.size : sections.length;
|
|
@@ -3747,25 +3766,25 @@ function parseHwp5Document(buffer, options) {
|
|
|
3747
3766
|
const sectionData = sections[si];
|
|
3748
3767
|
const data = !distribution && compressed ? decompressStream(Buffer.from(sectionData)) : Buffer.from(sectionData);
|
|
3749
3768
|
totalDecompressed += data.length;
|
|
3750
|
-
if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0,
|
|
3769
|
+
if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
|
|
3751
3770
|
const records = readRecords(data);
|
|
3752
3771
|
const sectionBlocks = parseSection(records, docInfo, warnings, si + 1, doc);
|
|
3753
3772
|
bodyBlocks.push(...sectionBlocks);
|
|
3754
3773
|
parsedSections++;
|
|
3755
3774
|
_optionalChain([options, 'optionalAccess', _55 => _55.onProgress, 'optionalCall', _56 => _56(parsedSections, totalTarget)]);
|
|
3756
3775
|
} catch (secErr) {
|
|
3757
|
-
if (secErr instanceof
|
|
3776
|
+
if (secErr instanceof _chunkLFCS3UVGcjs.KordocError) throw secErr;
|
|
3758
3777
|
warnings.push({ page: si + 1, message: `\uC139\uC158 ${si + 1} \uD30C\uC2F1 \uC2E4\uD328: ${secErr instanceof Error ? secErr.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`, code: "PARTIAL_PARSE" });
|
|
3759
3778
|
}
|
|
3760
3779
|
}
|
|
3761
3780
|
const blocks = [...doc.headerBlocks, ...bodyBlocks, ...doc.footerBlocks];
|
|
3762
3781
|
const images = cfb ? extractHwp5Images(cfb.FileIndex, blocks, warnings) : extractHwp5ImagesLenient(lenientCfb, blocks, warnings);
|
|
3763
|
-
const flatBlocks =
|
|
3782
|
+
const flatBlocks = _chunkLFCS3UVGcjs.flattenLayoutTables.call(void 0, blocks);
|
|
3764
3783
|
if (docInfo) {
|
|
3765
3784
|
detectHwp5Headings(flatBlocks, docInfo);
|
|
3766
3785
|
}
|
|
3767
3786
|
const outline = flatBlocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
|
|
3768
|
-
const markdown =
|
|
3787
|
+
const markdown = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, flatBlocks);
|
|
3769
3788
|
return { markdown, blocks: flatBlocks, metadata, outline: outline.length > 0 ? outline : void 0, warnings: warnings.length > 0 ? warnings : void 0, images: images.length > 0 ? images : void 0 };
|
|
3770
3789
|
}
|
|
3771
3790
|
function parseDocInfoStream(cfb, compressed) {
|
|
@@ -3825,9 +3844,9 @@ function detectHwp5Headings(blocks, docInfo) {
|
|
|
3825
3844
|
let level = 0;
|
|
3826
3845
|
if (_optionalChain([block, 'access', _61 => _61.style, 'optionalAccess', _62 => _62.fontSize]) && baseFontSize > 0) {
|
|
3827
3846
|
const ratio = block.style.fontSize / baseFontSize;
|
|
3828
|
-
if (ratio >=
|
|
3829
|
-
else if (ratio >=
|
|
3830
|
-
else if (ratio >=
|
|
3847
|
+
if (ratio >= _chunkLFCS3UVGcjs.HEADING_RATIO_H1) level = 1;
|
|
3848
|
+
else if (ratio >= _chunkLFCS3UVGcjs.HEADING_RATIO_H2) level = 2;
|
|
3849
|
+
else if (ratio >= _chunkLFCS3UVGcjs.HEADING_RATIO_H3) level = 3;
|
|
3831
3850
|
}
|
|
3832
3851
|
if (/^제\d+[장절편]\s/.test(text) && text.length <= 50) {
|
|
3833
3852
|
if (level === 0) level = 2;
|
|
@@ -3912,7 +3931,7 @@ function findSectionsLenient(lcfb, compressed) {
|
|
|
3912
3931
|
if (!raw) break;
|
|
3913
3932
|
const content = compressed ? decompressStream(raw) : raw;
|
|
3914
3933
|
totalDecompressed += content.length;
|
|
3915
|
-
if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0,
|
|
3934
|
+
if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
|
|
3916
3935
|
sections.push({ idx: i, content });
|
|
3917
3936
|
}
|
|
3918
3937
|
if (sections.length === 0) {
|
|
@@ -3924,7 +3943,7 @@ function findSectionsLenient(lcfb, compressed) {
|
|
|
3924
3943
|
if (raw) {
|
|
3925
3944
|
const content = compressed ? decompressStream(raw) : raw;
|
|
3926
3945
|
totalDecompressed += content.length;
|
|
3927
|
-
if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0,
|
|
3946
|
+
if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
|
|
3928
3947
|
sections.push({ idx, content });
|
|
3929
3948
|
}
|
|
3930
3949
|
}
|
|
@@ -3941,7 +3960,7 @@ function findViewTextSectionsLenient(lcfb, compressed) {
|
|
|
3941
3960
|
try {
|
|
3942
3961
|
const content = decryptViewText(raw, compressed);
|
|
3943
3962
|
totalDecompressed += content.length;
|
|
3944
|
-
if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0,
|
|
3963
|
+
if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
|
|
3945
3964
|
sections.push({ idx: i, content });
|
|
3946
3965
|
} catch (e26) {
|
|
3947
3966
|
break;
|
|
@@ -4044,7 +4063,7 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
4044
4063
|
const ctrl = ctrls[r.ctrlIdx];
|
|
4045
4064
|
if (!_optionalChain([ctrl, 'optionalAccess', _69 => _69.href]) || r.end <= r.start) continue;
|
|
4046
4065
|
if (applied.some(([s, e]) => r.start < e && r.end > s)) continue;
|
|
4047
|
-
const href =
|
|
4066
|
+
const href = _chunkLFCS3UVGcjs.sanitizeHref.call(void 0, ctrl.href);
|
|
4048
4067
|
if (!href) continue;
|
|
4049
4068
|
const anchor = text.slice(r.start, r.end);
|
|
4050
4069
|
if (!anchor.trim()) continue;
|
|
@@ -4277,8 +4296,8 @@ function parseTableControl(ctrl, records, ctx) {
|
|
|
4277
4296
|
let tableIdx = -1;
|
|
4278
4297
|
for (let i2 = childStart; i2 < childEnd; i2++) {
|
|
4279
4298
|
if (records[i2].tagId === TAG_TABLE && records[i2].data.length >= 8) {
|
|
4280
|
-
rows = Math.min(records[i2].data.readUInt16LE(4),
|
|
4281
|
-
cols = Math.min(records[i2].data.readUInt16LE(6),
|
|
4299
|
+
rows = Math.min(records[i2].data.readUInt16LE(4), _chunkLFCS3UVGcjs.MAX_ROWS);
|
|
4300
|
+
cols = Math.min(records[i2].data.readUInt16LE(6), _chunkLFCS3UVGcjs.MAX_COLS);
|
|
4282
4301
|
tableIdx = i2;
|
|
4283
4302
|
break;
|
|
4284
4303
|
}
|
|
@@ -4327,7 +4346,7 @@ function parseTableControl(ctrl, records, ctx) {
|
|
|
4327
4346
|
return table2;
|
|
4328
4347
|
}
|
|
4329
4348
|
const cellRows = arrangeCells(rows, cols, cells);
|
|
4330
|
-
const table =
|
|
4349
|
+
const table = _chunkLFCS3UVGcjs.buildTable.call(void 0, cellRows);
|
|
4331
4350
|
if (caption && table.rows > 0) table.caption = caption;
|
|
4332
4351
|
return table.rows > 0 ? table : null;
|
|
4333
4352
|
}
|
|
@@ -4344,8 +4363,8 @@ function parseCell(records, lhIdx, end, ctx) {
|
|
|
4344
4363
|
rowAddr = rec.data.readUInt16LE(10);
|
|
4345
4364
|
const cs = rec.data.readUInt16LE(12);
|
|
4346
4365
|
const rs = rec.data.readUInt16LE(14);
|
|
4347
|
-
if (cs > 0) colSpan = Math.min(cs,
|
|
4348
|
-
if (rs > 0) rowSpan = Math.min(rs,
|
|
4366
|
+
if (cs > 0) colSpan = Math.min(cs, _chunkLFCS3UVGcjs.MAX_COLS);
|
|
4367
|
+
if (rs > 0) rowSpan = Math.min(rs, _chunkLFCS3UVGcjs.MAX_ROWS);
|
|
4349
4368
|
}
|
|
4350
4369
|
const blocks = ctx.depth < MAX_NEST_DEPTH ? parseParagraphList(records, lhIdx + 1, end, { ...ctx, depth: ctx.depth + 1 }) : [];
|
|
4351
4370
|
const parts = [];
|
|
@@ -4355,7 +4374,7 @@ function parseCell(records, lhIdx, end, ctx) {
|
|
|
4355
4374
|
parts.push(``);
|
|
4356
4375
|
hasStructure = true;
|
|
4357
4376
|
} else if (b.type === "table" && b.table) {
|
|
4358
|
-
const flat =
|
|
4377
|
+
const flat = _chunkLFCS3UVGcjs.convertTableToText.call(void 0, b.table.cells);
|
|
4359
4378
|
if (flat) parts.push(flat);
|
|
4360
4379
|
hasStructure = true;
|
|
4361
4380
|
} else if (b.text) {
|
|
@@ -16789,7 +16808,7 @@ function getTextContent(el) {
|
|
|
16789
16808
|
return _nullishCoalesce(_optionalChain([el, 'access', _82 => _82.textContent, 'optionalAccess', _83 => _83.trim, 'call', _84 => _84()]), () => ( ""));
|
|
16790
16809
|
}
|
|
16791
16810
|
function parseXml(text) {
|
|
16792
|
-
return new (0, _xmldom.DOMParser)().parseFromString(
|
|
16811
|
+
return new (0, _xmldom.DOMParser)().parseFromString(_chunkLFCS3UVGcjs.stripDtd.call(void 0, text), "text/xml");
|
|
16793
16812
|
}
|
|
16794
16813
|
function parseSharedStrings(xml) {
|
|
16795
16814
|
const doc = parseXml(xml);
|
|
@@ -16933,7 +16952,7 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
16933
16952
|
cellRows.push(row);
|
|
16934
16953
|
}
|
|
16935
16954
|
if (cellRows.length > 0) {
|
|
16936
|
-
const table =
|
|
16955
|
+
const table = _chunkLFCS3UVGcjs.buildTable.call(void 0, cellRows);
|
|
16937
16956
|
if (table.rows > 0) {
|
|
16938
16957
|
blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
|
|
16939
16958
|
}
|
|
@@ -16941,12 +16960,12 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
16941
16960
|
return blocks;
|
|
16942
16961
|
}
|
|
16943
16962
|
async function parseXlsxDocument(buffer, options) {
|
|
16944
|
-
|
|
16963
|
+
_chunkLFCS3UVGcjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE3);
|
|
16945
16964
|
const zip = await _jszip2.default.loadAsync(buffer);
|
|
16946
16965
|
const warnings = [];
|
|
16947
16966
|
const workbookFile = zip.file("xl/workbook.xml");
|
|
16948
16967
|
if (!workbookFile) {
|
|
16949
|
-
throw new (0,
|
|
16968
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 XLSX \uD30C\uC77C: xl/workbook.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
16950
16969
|
}
|
|
16951
16970
|
let sharedStrings = [];
|
|
16952
16971
|
const ssFile = zip.file("xl/sharedStrings.xml");
|
|
@@ -16955,7 +16974,7 @@ async function parseXlsxDocument(buffer, options) {
|
|
|
16955
16974
|
}
|
|
16956
16975
|
const sheets = parseWorkbook(await workbookFile.async("text"));
|
|
16957
16976
|
if (sheets.length === 0) {
|
|
16958
|
-
throw new (0,
|
|
16977
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("XLSX \uD30C\uC77C\uC5D0 \uC2DC\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
16959
16978
|
}
|
|
16960
16979
|
let relsMap = /* @__PURE__ */ new Map();
|
|
16961
16980
|
const relsFile = zip.file("xl/_rels/workbook.xml.rels");
|
|
@@ -17027,7 +17046,7 @@ async function parseXlsxDocument(buffer, options) {
|
|
|
17027
17046
|
} catch (e27) {
|
|
17028
17047
|
}
|
|
17029
17048
|
}
|
|
17030
|
-
const markdown =
|
|
17049
|
+
const markdown = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, blocks);
|
|
17031
17050
|
return { markdown, blocks, metadata, warnings: warnings.length > 0 ? warnings : void 0 };
|
|
17032
17051
|
}
|
|
17033
17052
|
|
|
@@ -17434,11 +17453,11 @@ function processGlobals(records) {
|
|
|
17434
17453
|
let encrypted = false;
|
|
17435
17454
|
const firstBof = records[0];
|
|
17436
17455
|
if (!firstBof || firstBof.opcode !== OP_BOF) {
|
|
17437
|
-
throw new (0,
|
|
17456
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("XLS: \uCCAB \uB808\uCF54\uB4DC\uAC00 BOF\uAC00 \uC544\uB2D8");
|
|
17438
17457
|
}
|
|
17439
17458
|
const bof = decodeBof(firstBof.data);
|
|
17440
17459
|
if (!bof || bof.dt !== DT_GLOBALS) {
|
|
17441
|
-
throw new (0,
|
|
17460
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("XLS: Globals \uC11C\uBE0C\uC2A4\uD2B8\uB9BC BOF \uB204\uB77D");
|
|
17442
17461
|
}
|
|
17443
17462
|
let i = 1;
|
|
17444
17463
|
while (i < records.length) {
|
|
@@ -17553,7 +17572,7 @@ function sheetToBlocks2(sheetName, sheet, sheetIndex) {
|
|
|
17553
17572
|
cellRows.push(row);
|
|
17554
17573
|
}
|
|
17555
17574
|
if (cellRows.length > 0) {
|
|
17556
|
-
const table =
|
|
17575
|
+
const table = _chunkLFCS3UVGcjs.buildTable.call(void 0, cellRows);
|
|
17557
17576
|
if (table.rows > 0) {
|
|
17558
17577
|
blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
|
|
17559
17578
|
}
|
|
@@ -17566,21 +17585,21 @@ async function parseXlsDocument(buffer, options) {
|
|
|
17566
17585
|
try {
|
|
17567
17586
|
cfb = parseLenientCfb(buf);
|
|
17568
17587
|
} catch (e) {
|
|
17569
|
-
throw new (0,
|
|
17588
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)(
|
|
17570
17589
|
`XLS: OLE2 \uC2DC\uADF8\uB2C8\uCC98 \uAC80\uC99D \uC2E4\uD328 \u2014 ${e instanceof Error ? e.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`
|
|
17571
17590
|
);
|
|
17572
17591
|
}
|
|
17573
17592
|
const wb = _nullishCoalesce(cfb.findStream("/Workbook"), () => ( cfb.findStream("/Book")));
|
|
17574
17593
|
if (!wb) {
|
|
17575
|
-
throw new (0,
|
|
17594
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("XLS: Workbook \uC2A4\uD2B8\uB9BC\uC774 \uC5C6\uC74C (BIFF5 \uB610\uB294 \uBE44\uD45C\uC900 \uD30C\uC77C)");
|
|
17576
17595
|
}
|
|
17577
17596
|
const records = readRecords2(wb);
|
|
17578
17597
|
if (records.length === 0) {
|
|
17579
|
-
throw new (0,
|
|
17598
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("XLS: \uC2DC\uADF8\uB2C8\uCC98 \uB808\uCF54\uB4DC\uAC00 \uC5C6\uC74C (Workbook \uC2A4\uD2B8\uB9BC \uC190\uC0C1)");
|
|
17580
17599
|
}
|
|
17581
17600
|
const firstBof = decodeBof(records[0].data);
|
|
17582
17601
|
if (firstBof && firstBof.vers !== 1536) {
|
|
17583
|
-
throw new (0,
|
|
17602
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)(
|
|
17584
17603
|
`XLS: BIFF8(0x0600)\uB9CC \uC9C0\uC6D0 \u2014 \uBCF8 \uD30C\uC77C\uC740 0x${firstBof.vers.toString(16)}`
|
|
17585
17604
|
);
|
|
17586
17605
|
}
|
|
@@ -17640,7 +17659,7 @@ async function parseXlsDocument(buffer, options) {
|
|
|
17640
17659
|
pageCount: totalSheets
|
|
17641
17660
|
};
|
|
17642
17661
|
return {
|
|
17643
|
-
markdown:
|
|
17662
|
+
markdown: _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, allBlocks),
|
|
17644
17663
|
blocks: allBlocks,
|
|
17645
17664
|
metadata,
|
|
17646
17665
|
warnings: warnings.length > 0 ? warnings : void 0
|
|
@@ -18078,7 +18097,7 @@ function getAttr(el, localName2) {
|
|
|
18078
18097
|
return null;
|
|
18079
18098
|
}
|
|
18080
18099
|
function parseXml2(text) {
|
|
18081
|
-
return new (0, _xmldom.DOMParser)().parseFromString(
|
|
18100
|
+
return new (0, _xmldom.DOMParser)().parseFromString(_chunkLFCS3UVGcjs.stripDtd.call(void 0, text), "text/xml");
|
|
18082
18101
|
}
|
|
18083
18102
|
function parseStyles(xml) {
|
|
18084
18103
|
const doc = parseXml2(xml);
|
|
@@ -18401,12 +18420,12 @@ async function extractImages(zip, rels, doc, warnings) {
|
|
|
18401
18420
|
return { blocks, images };
|
|
18402
18421
|
}
|
|
18403
18422
|
async function parseDocxDocument(buffer, options) {
|
|
18404
|
-
|
|
18423
|
+
_chunkLFCS3UVGcjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE4);
|
|
18405
18424
|
const zip = await _jszip2.default.loadAsync(buffer);
|
|
18406
18425
|
const warnings = [];
|
|
18407
18426
|
const docFile = zip.file("word/document.xml");
|
|
18408
18427
|
if (!docFile) {
|
|
18409
|
-
throw new (0,
|
|
18428
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 DOCX \uD30C\uC77C: word/document.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
18410
18429
|
}
|
|
18411
18430
|
let rels = /* @__PURE__ */ new Map();
|
|
18412
18431
|
const relsFile = zip.file("word/_rels/document.xml.rels");
|
|
@@ -18453,7 +18472,7 @@ async function parseDocxDocument(buffer, options) {
|
|
|
18453
18472
|
const doc = parseXml2(docXml);
|
|
18454
18473
|
const body = findElements(doc, "body");
|
|
18455
18474
|
if (body.length === 0) {
|
|
18456
|
-
throw new (0,
|
|
18475
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("DOCX \uBCF8\uBB38(w:body)\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
18457
18476
|
}
|
|
18458
18477
|
const blocks = [];
|
|
18459
18478
|
const bodyEl = body[0];
|
|
@@ -18494,7 +18513,7 @@ async function parseDocxDocument(buffer, options) {
|
|
|
18494
18513
|
}
|
|
18495
18514
|
}
|
|
18496
18515
|
const outline = blocks.filter((b) => b.type === "heading").map((b) => ({ level: _nullishCoalesce(b.level, () => ( 2)), text: _nullishCoalesce(b.text, () => ( "")) }));
|
|
18497
|
-
const markdown =
|
|
18516
|
+
const markdown = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, blocks);
|
|
18498
18517
|
return {
|
|
18499
18518
|
markdown,
|
|
18500
18519
|
blocks,
|
|
@@ -18517,7 +18536,7 @@ function parseHwpmlDocument(buffer, options) {
|
|
|
18517
18536
|
}
|
|
18518
18537
|
const text = new TextDecoder("utf-8").decode(buffer).replace(/^\uFEFF/, "");
|
|
18519
18538
|
const normalized = text.replace(/ /g, " ");
|
|
18520
|
-
const xml =
|
|
18539
|
+
const xml = _chunkLFCS3UVGcjs.stripDtd.call(void 0, normalized);
|
|
18521
18540
|
const warnings = [];
|
|
18522
18541
|
const parser = new (0, _xmldom.DOMParser)({
|
|
18523
18542
|
onError: (_level, msg2) => {
|
|
@@ -18557,7 +18576,7 @@ function parseHwpmlDocument(buffer, options) {
|
|
|
18557
18576
|
parseSection2(el, blocks, paraShapeMap, sectionIdx, warnings);
|
|
18558
18577
|
}
|
|
18559
18578
|
const outline = blocks.filter((b) => b.type === "heading" && b.text).map((b) => ({ level: _nullishCoalesce(b.level, () => ( 1)), text: b.text, pageNumber: b.pageNumber }));
|
|
18560
|
-
const markdown =
|
|
18579
|
+
const markdown = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, blocks);
|
|
18561
18580
|
return {
|
|
18562
18581
|
markdown,
|
|
18563
18582
|
blocks,
|
|
@@ -18699,7 +18718,7 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18699
18718
|
const cellRows = grid.map(
|
|
18700
18719
|
(row) => row.map((cell) => _nullishCoalesce(cell, () => ( { text: "", colSpan: 1, rowSpan: 1 })))
|
|
18701
18720
|
);
|
|
18702
|
-
const table =
|
|
18721
|
+
const table = _chunkLFCS3UVGcjs.buildTable.call(void 0, cellRows);
|
|
18703
18722
|
blocks.push({ type: "table", table, pageNumber: sectionNum });
|
|
18704
18723
|
}
|
|
18705
18724
|
function extractCellText(cellEl) {
|
|
@@ -19872,19 +19891,19 @@ function parseCentralDirectory(buf) {
|
|
|
19872
19891
|
}
|
|
19873
19892
|
}
|
|
19874
19893
|
}
|
|
19875
|
-
if (eocdOffset < 0) throw new (0,
|
|
19894
|
+
if (eocdOffset < 0) throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP EOCD\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
19876
19895
|
const totalEntries = view.getUint16(eocdOffset + 10, true);
|
|
19877
19896
|
const cdSize = view.getUint32(eocdOffset + 12, true);
|
|
19878
19897
|
const cdOffset = view.getUint32(eocdOffset + 16, true);
|
|
19879
|
-
if (cdOffset === 4294967295 || totalEntries === 65535) throw new (0,
|
|
19898
|
+
if (cdOffset === 4294967295 || totalEntries === 65535) throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
19880
19899
|
if (eocdOffset >= 20 && view.getUint32(eocdOffset - 20, true) === ZIP64_EOCD_LOC_SIG) {
|
|
19881
|
-
throw new (0,
|
|
19900
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
19882
19901
|
}
|
|
19883
19902
|
const decoder = new TextDecoder("utf-8");
|
|
19884
19903
|
const entries = [];
|
|
19885
19904
|
let pos = cdOffset;
|
|
19886
19905
|
for (let i = 0; i < totalEntries; i++) {
|
|
19887
|
-
if (view.getUint32(pos, true) !== CD_SIG) throw new (0,
|
|
19906
|
+
if (view.getUint32(pos, true) !== CD_SIG) throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP Central Directory \uC190\uC0C1");
|
|
19888
19907
|
const flags = view.getUint16(pos + 8, true);
|
|
19889
19908
|
const method = view.getUint16(pos + 10, true);
|
|
19890
19909
|
const crc = view.getUint32(pos + 16, true);
|
|
@@ -19895,7 +19914,7 @@ function parseCentralDirectory(buf) {
|
|
|
19895
19914
|
const commentLen = view.getUint16(pos + 32, true);
|
|
19896
19915
|
const localOffset = view.getUint32(pos + 42, true);
|
|
19897
19916
|
if (compSize === 4294967295 || uncompSize === 4294967295 || localOffset === 4294967295) {
|
|
19898
|
-
throw new (0,
|
|
19917
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
19899
19918
|
}
|
|
19900
19919
|
const name = decoder.decode(buf.subarray(pos + 46, pos + 46 + nameLen));
|
|
19901
19920
|
const cdEnd = pos + 46 + nameLen + extraLen + commentLen;
|
|
@@ -19924,7 +19943,7 @@ function patchZipEntries(original, replacements) {
|
|
|
19924
19943
|
const { entries, cdOffset, eocdOffset } = parseCentralDirectory(original);
|
|
19925
19944
|
const view = new DataView(original.buffer, original.byteOffset, original.byteLength);
|
|
19926
19945
|
for (const name of replacements.keys()) {
|
|
19927
|
-
if (!entries.some((e) => e.name === name)) throw new (0,
|
|
19946
|
+
if (!entries.some((e) => e.name === name)) throw new (0, _chunkLFCS3UVGcjs.KordocError)(`ZIP\uC5D0 \uC5C6\uB294 \uC5D4\uD2B8\uB9AC: ${name}`);
|
|
19928
19947
|
}
|
|
19929
19948
|
const byLocal = [...entries].sort((a, b) => a.localOffset - b.localOffset);
|
|
19930
19949
|
const segments = [];
|
|
@@ -19942,7 +19961,7 @@ function patchZipEntries(original, replacements) {
|
|
|
19942
19961
|
offset += seg.length;
|
|
19943
19962
|
continue;
|
|
19944
19963
|
}
|
|
19945
|
-
if (view.getUint32(e.localOffset, true) !== LOCAL_SIG) throw new (0,
|
|
19964
|
+
if (view.getUint32(e.localOffset, true) !== LOCAL_SIG) throw new (0, _chunkLFCS3UVGcjs.KordocError)("ZIP \uB85C\uCEEC \uD5E4\uB354 \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
|
|
19946
19965
|
const nameLen = view.getUint16(e.localOffset + 26, true);
|
|
19947
19966
|
const extraLen = view.getUint16(e.localOffset + 28, true);
|
|
19948
19967
|
const headerLen = 30 + nameLen + extraLen;
|
|
@@ -19997,7 +20016,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
19997
20016
|
const zip = await _jszip2.default.loadAsync(hwpxBuffer);
|
|
19998
20017
|
const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
|
|
19999
20018
|
if (sectionPaths.length === 0) {
|
|
20000
|
-
throw new (0,
|
|
20019
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
20001
20020
|
}
|
|
20002
20021
|
const normalizedValues = normalizeValues(values);
|
|
20003
20022
|
const cursor = new ValueCursor(normalizedValues);
|
|
@@ -20783,7 +20802,7 @@ function escapeGfm(text) {
|
|
|
20783
20802
|
}
|
|
20784
20803
|
var HWP_SHAPE_ALT_TEXT_RE = /(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|이등변 삼각형|직각 삼각형|선|직선|곡선|화살표|굵은 화살표|이중 화살표|오각형|육각형|팔각형|별|[4-8]점별|십자|십자형|구름|구름형|마름모|도넛|평행사변형|사다리꼴|부채꼴|호|반원|물결|번개|하트|빗금|블록 화살표|수식|표|그림|개체|그리기\s?개체|묶음\s?개체|글상자|수식\s?개체|OLE\s?개체)\s?입니다\.?/g;
|
|
20785
20804
|
function sanitizeText(text) {
|
|
20786
|
-
let result =
|
|
20805
|
+
let result = _chunkLFCS3UVGcjs.mapPuaText.call(void 0, text).replace(/[\u{F0000}-\u{FFFFD}]/gu, "").replace(HWP_SHAPE_ALT_TEXT_RE, "").replace(/ +/g, " ").trim();
|
|
20787
20806
|
if (result.length <= 30 && result.includes(" ")) {
|
|
20788
20807
|
const tokens = result.split(" ");
|
|
20789
20808
|
const koreanSingleCharCount = tokens.filter((t) => t.length === 1 && /[가-ㄱ-ㆎ]/.test(t)).length;
|
|
@@ -22501,7 +22520,7 @@ async function resolveSectionEntryNames(zip) {
|
|
|
22501
22520
|
const paths = sectionPathsFromManifest(xml).filter((p) => zip.file(p) !== null);
|
|
22502
22521
|
if (paths.length > 0) return paths;
|
|
22503
22522
|
}
|
|
22504
|
-
return Object.keys(zip.files).filter((n) => /[Ss]ection\d+\.xml$/.test(n)).sort(
|
|
22523
|
+
return Object.keys(zip.files).filter((n) => /[Ss]ection\d+\.xml$/.test(n)).sort(_chunkLFCS3UVGcjs.compareSectionPaths);
|
|
22505
22524
|
}
|
|
22506
22525
|
function sectionPathsFromManifest(xml) {
|
|
22507
22526
|
const attr = (tag, name) => {
|
|
@@ -22511,7 +22530,7 @@ function sectionPathsFromManifest(xml) {
|
|
|
22511
22530
|
const idToHref = /* @__PURE__ */ new Map();
|
|
22512
22531
|
for (const m of xml.matchAll(/<opf:item(\s(?:"[^"]*"|'[^']*'|[^>"'])*?)\/?>/g)) {
|
|
22513
22532
|
const id = attr(m[1], "id");
|
|
22514
|
-
const href =
|
|
22533
|
+
const href = _chunkLFCS3UVGcjs.normalizeSectionHref.call(void 0, attr(m[1], "href"));
|
|
22515
22534
|
if (id && href) idToHref.set(id, href);
|
|
22516
22535
|
}
|
|
22517
22536
|
const ordered = [];
|
|
@@ -22520,7 +22539,7 @@ function sectionPathsFromManifest(xml) {
|
|
|
22520
22539
|
if (href) ordered.push(href);
|
|
22521
22540
|
}
|
|
22522
22541
|
if (ordered.length > 0) return ordered;
|
|
22523
|
-
return Array.from(idToHref.values()).sort(
|
|
22542
|
+
return Array.from(idToHref.values()).sort(_chunkLFCS3UVGcjs.compareSectionPaths);
|
|
22524
22543
|
}
|
|
22525
22544
|
|
|
22526
22545
|
// src/roundtrip/patcher.ts
|
|
@@ -22631,9 +22650,9 @@ function buildOrigUnits(blocks) {
|
|
|
22631
22650
|
if (block.type === "paragraph" && block.text && /^\[별표\s*\d+/.test(sanitizeText(block.text))) {
|
|
22632
22651
|
const next = blocks[i + 1];
|
|
22633
22652
|
if (_optionalChain([next, 'optionalAccess', _220 => _220.type]) === "paragraph" && next.text && /관련\)?$/.test(next.text)) consume = 2;
|
|
22634
|
-
chunk =
|
|
22653
|
+
chunk = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, blocks.slice(i, i + consume));
|
|
22635
22654
|
} else {
|
|
22636
|
-
chunk =
|
|
22655
|
+
chunk = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, [block]);
|
|
22637
22656
|
}
|
|
22638
22657
|
if (chunk) {
|
|
22639
22658
|
const subUnits = splitMarkdownUnits(chunk);
|
|
@@ -24331,13 +24350,13 @@ async function htmlToPdf(html, options) {
|
|
|
24331
24350
|
try {
|
|
24332
24351
|
puppeteer = await Promise.resolve().then(() => _interopRequireWildcard(require("puppeteer-core")));
|
|
24333
24352
|
} catch (e30) {
|
|
24334
|
-
throw new (0,
|
|
24353
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)(
|
|
24335
24354
|
"PDF \uC0DD\uC131\uC5D0 puppeteer-core\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC124\uCE58: npm install puppeteer-core"
|
|
24336
24355
|
);
|
|
24337
24356
|
}
|
|
24338
24357
|
const executablePath = _nullishCoalesce(process.env.PUPPETEER_EXECUTABLE_PATH, () => ( findChromiumPath()));
|
|
24339
24358
|
if (!executablePath) {
|
|
24340
|
-
throw new (0,
|
|
24359
|
+
throw new (0, _chunkLFCS3UVGcjs.KordocError)(
|
|
24341
24360
|
"Chromium \uC2E4\uD589 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. PUPPETEER_EXECUTABLE_PATH \uD658\uACBD\uBCC0\uC218\uB97C \uC124\uC815\uD558\uC138\uC694."
|
|
24342
24361
|
);
|
|
24343
24362
|
}
|
|
@@ -24396,7 +24415,7 @@ async function markdownToPdf(markdown, options) {
|
|
|
24396
24415
|
return htmlToPdf(html, options);
|
|
24397
24416
|
}
|
|
24398
24417
|
async function blocksToPdf(blocks, options) {
|
|
24399
|
-
const markdown =
|
|
24418
|
+
const markdown = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, blocks);
|
|
24400
24419
|
return markdownToPdf(markdown, options);
|
|
24401
24420
|
}
|
|
24402
24421
|
|
|
@@ -24407,13 +24426,13 @@ async function parse(input, options) {
|
|
|
24407
24426
|
if (typeof input === "string") {
|
|
24408
24427
|
try {
|
|
24409
24428
|
const buf = await _promises.readFile.call(void 0, input);
|
|
24410
|
-
buffer =
|
|
24429
|
+
buffer = _chunkLFCS3UVGcjs.toArrayBuffer.call(void 0, buf);
|
|
24411
24430
|
} catch (err) {
|
|
24412
24431
|
const msg2 = err instanceof Error && "code" in err && err.code === "ENOENT" ? `\uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${input}` : `\uD30C\uC77C \uC77D\uAE30 \uC2E4\uD328: ${input}`;
|
|
24413
24432
|
return { success: false, fileType: "unknown", error: msg2, code: "PARSE_ERROR" };
|
|
24414
24433
|
}
|
|
24415
24434
|
} else if (Buffer.isBuffer(input)) {
|
|
24416
|
-
buffer =
|
|
24435
|
+
buffer = _chunkLFCS3UVGcjs.toArrayBuffer.call(void 0, input);
|
|
24417
24436
|
} else {
|
|
24418
24437
|
buffer = input;
|
|
24419
24438
|
}
|
|
@@ -24448,7 +24467,7 @@ async function parseHwp3(buffer, options) {
|
|
|
24448
24467
|
const { markdown, blocks, metadata, outline, warnings } = parseHwp3Document(buffer, options);
|
|
24449
24468
|
return { success: true, fileType: "hwp3", markdown, blocks, metadata, outline, warnings };
|
|
24450
24469
|
} catch (err) {
|
|
24451
|
-
return { success: false, fileType: "hwp3", error: err instanceof Error ? err.message : "HWP3 \uD30C\uC2F1 \uC2E4\uD328", code:
|
|
24470
|
+
return { success: false, fileType: "hwp3", error: err instanceof Error ? err.message : "HWP3 \uD30C\uC2F1 \uC2E4\uD328", code: _chunkLFCS3UVGcjs.classifyError.call(void 0, err) };
|
|
24452
24471
|
}
|
|
24453
24472
|
}
|
|
24454
24473
|
async function parseHwpx(buffer, options) {
|
|
@@ -24456,7 +24475,7 @@ async function parseHwpx(buffer, options) {
|
|
|
24456
24475
|
const { markdown, blocks, metadata, outline, warnings, images } = await parseHwpxDocument(buffer, options);
|
|
24457
24476
|
return { success: true, fileType: "hwpx", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _280 => _280.length]) ? images : void 0 };
|
|
24458
24477
|
} catch (err) {
|
|
24459
|
-
return { success: false, fileType: "hwpx", error: err instanceof Error ? err.message : "HWPX \uD30C\uC2F1 \uC2E4\uD328", code:
|
|
24478
|
+
return { success: false, fileType: "hwpx", error: err instanceof Error ? err.message : "HWPX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkLFCS3UVGcjs.classifyError.call(void 0, err) };
|
|
24460
24479
|
}
|
|
24461
24480
|
}
|
|
24462
24481
|
async function parseHwp(buffer, options) {
|
|
@@ -24481,13 +24500,13 @@ async function parseHwp(buffer, options) {
|
|
|
24481
24500
|
}
|
|
24482
24501
|
return { success: true, fileType: "hwp", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _282 => _282.length]) ? images : void 0 };
|
|
24483
24502
|
} catch (err) {
|
|
24484
|
-
return { success: false, fileType: "hwp", error: err instanceof Error ? err.message : "HWP \uD30C\uC2F1 \uC2E4\uD328", code:
|
|
24503
|
+
return { success: false, fileType: "hwp", error: err instanceof Error ? err.message : "HWP \uD30C\uC2F1 \uC2E4\uD328", code: _chunkLFCS3UVGcjs.classifyError.call(void 0, err) };
|
|
24485
24504
|
}
|
|
24486
24505
|
}
|
|
24487
24506
|
async function parsePdf(buffer, options) {
|
|
24488
24507
|
let parsePdfDocument;
|
|
24489
24508
|
try {
|
|
24490
|
-
const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./parser-
|
|
24509
|
+
const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./parser-IXK5V7YG.cjs")));
|
|
24491
24510
|
parsePdfDocument = mod.parsePdfDocument;
|
|
24492
24511
|
} catch (e32) {
|
|
24493
24512
|
return {
|
|
@@ -24502,7 +24521,7 @@ async function parsePdf(buffer, options) {
|
|
|
24502
24521
|
return { success: true, fileType: "pdf", markdown, blocks, metadata, outline, warnings, isImageBased, pageQuality, qualitySummary };
|
|
24503
24522
|
} catch (err) {
|
|
24504
24523
|
const isImageBased = err instanceof Error && "isImageBased" in err ? true : void 0;
|
|
24505
|
-
return { success: false, fileType: "pdf", error: err instanceof Error ? err.message : "PDF \uD30C\uC2F1 \uC2E4\uD328", code:
|
|
24524
|
+
return { success: false, fileType: "pdf", error: err instanceof Error ? err.message : "PDF \uD30C\uC2F1 \uC2E4\uD328", code: _chunkLFCS3UVGcjs.classifyError.call(void 0, err), isImageBased };
|
|
24506
24525
|
}
|
|
24507
24526
|
}
|
|
24508
24527
|
async function parseXlsx(buffer, options) {
|
|
@@ -24510,7 +24529,7 @@ async function parseXlsx(buffer, options) {
|
|
|
24510
24529
|
const { markdown, blocks, metadata, warnings } = await parseXlsxDocument(buffer, options);
|
|
24511
24530
|
return { success: true, fileType: "xlsx", markdown, blocks, metadata, warnings };
|
|
24512
24531
|
} catch (err) {
|
|
24513
|
-
return { success: false, fileType: "xlsx", error: err instanceof Error ? err.message : "XLSX \uD30C\uC2F1 \uC2E4\uD328", code:
|
|
24532
|
+
return { success: false, fileType: "xlsx", error: err instanceof Error ? err.message : "XLSX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkLFCS3UVGcjs.classifyError.call(void 0, err) };
|
|
24514
24533
|
}
|
|
24515
24534
|
}
|
|
24516
24535
|
async function parseXls(buffer, options) {
|
|
@@ -24518,7 +24537,7 @@ async function parseXls(buffer, options) {
|
|
|
24518
24537
|
const { markdown, blocks, metadata, warnings } = await parseXlsDocument(buffer, options);
|
|
24519
24538
|
return { success: true, fileType: "xls", markdown, blocks, metadata, warnings };
|
|
24520
24539
|
} catch (err) {
|
|
24521
|
-
return { success: false, fileType: "xls", error: err instanceof Error ? err.message : "XLS \uD30C\uC2F1 \uC2E4\uD328", code:
|
|
24540
|
+
return { success: false, fileType: "xls", error: err instanceof Error ? err.message : "XLS \uD30C\uC2F1 \uC2E4\uD328", code: _chunkLFCS3UVGcjs.classifyError.call(void 0, err) };
|
|
24522
24541
|
}
|
|
24523
24542
|
}
|
|
24524
24543
|
async function parseDocx(buffer, options) {
|
|
@@ -24526,7 +24545,7 @@ async function parseDocx(buffer, options) {
|
|
|
24526
24545
|
const { markdown, blocks, metadata, outline, warnings, images } = await parseDocxDocument(buffer, options);
|
|
24527
24546
|
return { success: true, fileType: "docx", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _283 => _283.length]) ? images : void 0 };
|
|
24528
24547
|
} catch (err) {
|
|
24529
|
-
return { success: false, fileType: "docx", error: err instanceof Error ? err.message : "DOCX \uD30C\uC2F1 \uC2E4\uD328", code:
|
|
24548
|
+
return { success: false, fileType: "docx", error: err instanceof Error ? err.message : "DOCX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkLFCS3UVGcjs.classifyError.call(void 0, err) };
|
|
24530
24549
|
}
|
|
24531
24550
|
}
|
|
24532
24551
|
async function parseHwpml(buffer, options) {
|
|
@@ -24534,16 +24553,16 @@ async function parseHwpml(buffer, options) {
|
|
|
24534
24553
|
const { markdown, blocks, metadata, outline, warnings } = parseHwpmlDocument(buffer, options);
|
|
24535
24554
|
return { success: true, fileType: "hwpml", markdown, blocks, metadata, outline, warnings };
|
|
24536
24555
|
} catch (err) {
|
|
24537
|
-
return { success: false, fileType: "hwpml", error: err instanceof Error ? err.message : "HWPML \uD30C\uC2F1 \uC2E4\uD328", code:
|
|
24556
|
+
return { success: false, fileType: "hwpml", error: err instanceof Error ? err.message : "HWPML \uD30C\uC2F1 \uC2E4\uD328", code: _chunkLFCS3UVGcjs.classifyError.call(void 0, err) };
|
|
24538
24557
|
}
|
|
24539
24558
|
}
|
|
24540
24559
|
async function fillForm(input, values, outputFormat = "markdown") {
|
|
24541
24560
|
let buffer;
|
|
24542
24561
|
if (typeof input === "string") {
|
|
24543
24562
|
const buf = await _promises.readFile.call(void 0, input);
|
|
24544
|
-
buffer =
|
|
24563
|
+
buffer = _chunkLFCS3UVGcjs.toArrayBuffer.call(void 0, buf);
|
|
24545
24564
|
} else if (Buffer.isBuffer(input)) {
|
|
24546
|
-
buffer =
|
|
24565
|
+
buffer = _chunkLFCS3UVGcjs.toArrayBuffer.call(void 0, input);
|
|
24547
24566
|
} else {
|
|
24548
24567
|
buffer = input;
|
|
24549
24568
|
}
|
|
@@ -24569,7 +24588,7 @@ async function fillForm(input, values, outputFormat = "markdown") {
|
|
|
24569
24588
|
throw new Error(`\uC11C\uC2DD \uD30C\uC2F1 \uC2E4\uD328: ${parsed.error}`);
|
|
24570
24589
|
}
|
|
24571
24590
|
const fill = fillFormFields(parsed.blocks, values);
|
|
24572
|
-
const markdown =
|
|
24591
|
+
const markdown = _chunkLFCS3UVGcjs.blocksToMarkdown.call(void 0, fill.blocks);
|
|
24573
24592
|
if (outputFormat === "hwpx") {
|
|
24574
24593
|
const hwpxBuffer = await markdownToHwpx(markdown);
|
|
24575
24594
|
return { output: hwpxBuffer, format: "hwpx", fill };
|
|
@@ -24627,5 +24646,5 @@ async function fillForm(input, values, outputFormat = "markdown") {
|
|
|
24627
24646
|
|
|
24628
24647
|
|
|
24629
24648
|
|
|
24630
|
-
exports.HwpxSession = HwpxSession; exports.PRESET_ALIAS = PRESET_ALIAS; exports.SPACE_EM_FIXED = SPACE_EM_FIXED; exports.SPACE_EM_FONT = SPACE_EM_FONT; exports.VERSION =
|
|
24649
|
+
exports.HwpxSession = HwpxSession; exports.PRESET_ALIAS = PRESET_ALIAS; exports.SPACE_EM_FIXED = SPACE_EM_FIXED; exports.SPACE_EM_FONT = SPACE_EM_FONT; exports.VERSION = _chunkLFCS3UVGcjs.VERSION; exports.ValueCursor = ValueCursor; exports.applySplices = applySplices; exports.blocksToMarkdown = _chunkLFCS3UVGcjs.blocksToMarkdown; exports.blocksToPdf = blocksToPdf; exports.buildParagraphSplices = buildParagraphSplices; exports.buildRangeSplices = buildRangeSplices; exports.charWidthEm1000 = charWidthEm1000; exports.compare = compare; exports.detectFormat = detectFormat; exports.detectOle2Format = detectOle2Format; exports.detectZipFormat = detectZipFormat; exports.diffBlocks = diffBlocks; exports.extractFormFields = extractFormFields; exports.extractFormSchema = extractFormSchema; exports.fillForm = fillForm; exports.fillFormFields = fillFormFields; exports.fillHwpx = fillHwpx; exports.fitRatioForFewerLines = fitRatioForFewerLines; exports.inferFieldType = inferFieldType; exports.isHwpxFile = isHwpxFile; exports.isLabelCell = isLabelCell; exports.isOldHwpFile = isOldHwpFile; exports.isPdfFile = isPdfFile; exports.isZipFile = isZipFile; exports.markdownToHwpx = markdownToHwpx; exports.markdownToPdf = markdownToPdf; exports.measureTextWidth = measureTextWidth; exports.normalizeGongmunPreset = normalizeGongmunPreset; exports.openHwpxDocument = openHwpxDocument; exports.parse = parse; exports.parseDocx = parseDocx; exports.parseHwp = parseHwp; exports.parseHwp3 = parseHwp3; exports.parseHwpml = parseHwpml; exports.parseHwpx = parseHwpx; exports.parsePdf = parsePdf; exports.parseXls = parseXls; exports.parseXlsx = parseXlsx; exports.patchHwp = patchHwp; exports.patchHwpx = patchHwpx; exports.patchHwpxBlocks = patchHwpxBlocks; exports.renderHtml = renderHtml; exports.scanSectionXml = scanSectionXml; exports.simulateWrap = simulateWrap; exports.simulateWrapKeepWord = simulateWrapKeepWord;
|
|
24631
24650
|
//# sourceMappingURL=index.cjs.map
|