kordoc 4.18.1 → 4.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/dist/{-X4KTLQC6.js → -I3CP33G4.js} +13 -11
- package/dist/{chunk-NQR3VKWN.js → chunk-4B2EXELH.js} +2 -2
- package/dist/{chunk-SQQ4ITJ5.js → chunk-6OKBTY72.js} +2 -2
- package/dist/{chunk-HUGBJVAA.js → chunk-B2E6C2LH.js} +12 -7
- package/dist/chunk-B2E6C2LH.js.map +1 -0
- package/dist/{chunk-X625PCZM.js → chunk-BL7KRE6X.js} +3 -3
- package/dist/{chunk-5PNQIF3V.js → chunk-C2CVOC5K.js} +4 -4
- package/dist/{chunk-AQUNBGXH.js → chunk-CKUIFTXJ.js} +2 -2
- package/dist/{chunk-TMC4A3FM.js → chunk-F5HING4Y.js} +10 -5
- package/dist/chunk-F5HING4Y.js.map +1 -0
- package/dist/{chunk-PWRY4W6Q.js → chunk-GM7XIZF2.js} +2 -2
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-K35WIYBD.js → chunk-IA3UKDHA.js} +4 -4
- package/dist/chunk-IA3UKDHA.js.map +1 -0
- package/dist/chunk-J55UQC5H.cjs.map +1 -1
- package/dist/{chunk-7DC2KL3V.cjs → chunk-KDMAYOWH.cjs} +158 -43
- package/dist/chunk-KDMAYOWH.cjs.map +1 -0
- package/dist/{chunk-Z4KCEERM.js → chunk-L5RLJPI3.js} +3 -3
- package/dist/{chunk-WWOTHS2E.js → chunk-L64QRUMK.js} +202 -7
- package/dist/chunk-L64QRUMK.js.map +1 -0
- package/dist/{chunk-6N5BOPJI.js → chunk-LACO375L.js} +2 -2
- package/dist/{chunk-KXR4CTFT.js → chunk-LSOD2A6N.js} +2 -2
- package/dist/{chunk-UTVMLJZE.js → chunk-M4P7YS2N.js} +389 -57
- package/dist/chunk-M4P7YS2N.js.map +1 -0
- package/dist/{chunk-VDIXNEWV.js → chunk-N5DQFA7L.js} +2 -2
- package/dist/{chunk-R2IFWAHI.js → chunk-NZM2SSI4.js} +2 -2
- package/dist/{chunk-KBZ3MQJX.js → chunk-O2DI4GHD.js} +2 -2
- package/dist/{chunk-I7YWXECO.js → chunk-OBILAVWC.js} +2 -2
- package/dist/{chunk-6V7QRQY3.js → chunk-OGAYGUJF.js} +122 -87
- package/dist/chunk-OGAYGUJF.js.map +1 -0
- package/dist/{chunk-IUMV45TX.cjs → chunk-OI5ZSSIC.cjs} +12 -12
- package/dist/chunk-OI5ZSSIC.cjs.map +1 -0
- package/dist/{chunk-Q5N4YS3T.cjs → chunk-QGFZU3JE.cjs} +16 -11
- package/dist/chunk-QGFZU3JE.cjs.map +1 -0
- package/dist/{chunk-2VFZQ634.js → chunk-QP7IXF7R.js} +2 -2
- package/dist/{chunk-CWJ5KY2F.js → chunk-T4MXCSBP.js} +137 -27
- package/dist/chunk-T4MXCSBP.js.map +1 -0
- package/dist/{chunk-PCSOJ523.cjs → chunk-UZGZRGYM.cjs} +2 -2
- package/dist/chunk-UZGZRGYM.cjs.map +1 -0
- package/dist/{chunk-MTTYJEKA.js → chunk-VSY5PAJ5.js} +2 -2
- package/dist/{chunk-IXAXI2S3.cjs → chunk-W2YYBPW5.cjs} +3 -3
- package/dist/chunk-W2YYBPW5.cjs.map +1 -0
- package/dist/{chunk-SIZ63E5G.cjs → chunk-YNLW6EGU.cjs} +3 -3
- package/dist/chunk-YNLW6EGU.cjs.map +1 -0
- package/dist/chunks-IFFRC5IQ.js +10 -0
- package/dist/cli.js +26 -26
- package/dist/{formula-LICM6K27.js → formula-AQZODKZF.js} +3 -3
- package/dist/{formula-T4Q2UHWO.js → formula-E3N7KDDG.js} +4 -4
- package/dist/{formula-W3GQC6L6.cjs → formula-VY4ITOMN.cjs} +9 -9
- package/dist/formula-VY4ITOMN.cjs.map +1 -0
- package/dist/{image-ocr-7PNHBD2G.cjs → image-ocr-6LYEBMVR.cjs} +15 -15
- package/dist/image-ocr-6LYEBMVR.cjs.map +1 -0
- package/dist/{image-ocr-WZJURDX6.js → image-ocr-IMYXOHHV.js} +6 -6
- package/dist/{image-ocr-XB2NFKGZ.js → image-ocr-LN3GSQPW.js} +9 -9
- package/dist/index.cjs +1037 -603
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -5
- package/dist/index.d.ts +7 -5
- package/dist/index.js +523 -89
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +26 -27
- package/dist/mcp.js.map +1 -1
- package/dist/{model-bundle-O2XYR54X.js → model-bundle-IHKNDLOT.js} +5 -5
- package/dist/{models-SKK3NH3V.js → models-YXITRAMR.js} +5 -5
- package/dist/page-range-QHHFTL7X.cjs.map +1 -1
- package/dist/{parser-PJUZSMFR.cjs → parser-7KECZTTP.cjs} +176 -228
- package/dist/parser-7KECZTTP.cjs.map +1 -0
- package/dist/{parser-4D2M5BKY.js → parser-KB4BYQBZ.js} +14 -66
- package/dist/parser-KB4BYQBZ.js.map +1 -0
- package/dist/{parser-5G5G7HHG.js → parser-M3T2EWUN.js} +11 -63
- package/dist/parser-M3T2EWUN.js.map +1 -0
- package/dist/pdf-ocr-4S2OAHUX.js +15 -0
- package/dist/pdf-ocr-IGYCZ7G2.cjs +16 -0
- package/dist/pdf-ocr-IGYCZ7G2.cjs.map +1 -0
- package/dist/pdf-ocr-YEBFWU2K.js +19 -0
- package/dist/{profile-io-BAQTYPK7.js → profile-io-GQWQR7YQ.js} +3 -3
- package/dist/{rasterize-A2ZEACKV.js → rasterize-Y6TVFQ3M.js} +3 -3
- package/dist/{redact-doc-26KN2LSZ.js → redact-doc-TRPZ3HNW.js} +11 -11
- package/dist/{render-62ZUDMHB.js → render-GHT5HKBO.js} +7 -7
- package/dist/seal-3YTXSABW.js +10 -0
- package/dist/{setup-2A3E6WRE.js → setup-AGSCEHDB.js} +3 -3
- package/dist/visual-R3E35Q2K.js +20 -0
- package/dist/{watch-D2T5FEKT.js → watch-ALSEW4GB.js} +13 -13
- package/dist/watch-ALSEW4GB.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-6V7QRQY3.js.map +0 -1
- package/dist/chunk-7DC2KL3V.cjs.map +0 -1
- package/dist/chunk-CWJ5KY2F.js.map +0 -1
- package/dist/chunk-HUGBJVAA.js.map +0 -1
- package/dist/chunk-IUMV45TX.cjs.map +0 -1
- package/dist/chunk-IXAXI2S3.cjs.map +0 -1
- package/dist/chunk-K35WIYBD.js.map +0 -1
- package/dist/chunk-PCSOJ523.cjs.map +0 -1
- package/dist/chunk-Q5N4YS3T.cjs.map +0 -1
- package/dist/chunk-SIZ63E5G.cjs.map +0 -1
- package/dist/chunk-TMC4A3FM.js.map +0 -1
- package/dist/chunk-UTVMLJZE.js.map +0 -1
- package/dist/chunk-WWOTHS2E.js.map +0 -1
- package/dist/chunks-ACUC63N3.js +0 -10
- package/dist/formula-W3GQC6L6.cjs.map +0 -1
- package/dist/image-ocr-7PNHBD2G.cjs.map +0 -1
- package/dist/parser-4D2M5BKY.js.map +0 -1
- package/dist/parser-5G5G7HHG.js.map +0 -1
- package/dist/parser-PJUZSMFR.cjs.map +0 -1
- package/dist/pdf-ocr-EGWOIB6O.cjs +0 -16
- package/dist/pdf-ocr-EGWOIB6O.cjs.map +0 -1
- package/dist/pdf-ocr-NJTFXBRC.js +0 -19
- package/dist/pdf-ocr-ZXR6Q6BK.js +0 -15
- package/dist/seal-3GXC2API.js +0 -10
- package/dist/visual-4ZBZRMCM.js +0 -20
- package/dist/watch-D2T5FEKT.js.map +0 -1
- /package/dist/{-X4KTLQC6.js.map → -I3CP33G4.js.map} +0 -0
- /package/dist/{chunk-NQR3VKWN.js.map → chunk-4B2EXELH.js.map} +0 -0
- /package/dist/{chunk-SQQ4ITJ5.js.map → chunk-6OKBTY72.js.map} +0 -0
- /package/dist/{chunk-X625PCZM.js.map → chunk-BL7KRE6X.js.map} +0 -0
- /package/dist/{chunk-5PNQIF3V.js.map → chunk-C2CVOC5K.js.map} +0 -0
- /package/dist/{chunk-AQUNBGXH.js.map → chunk-CKUIFTXJ.js.map} +0 -0
- /package/dist/{chunk-PWRY4W6Q.js.map → chunk-GM7XIZF2.js.map} +0 -0
- /package/dist/{chunk-Z4KCEERM.js.map → chunk-L5RLJPI3.js.map} +0 -0
- /package/dist/{chunk-6N5BOPJI.js.map → chunk-LACO375L.js.map} +0 -0
- /package/dist/{chunk-KXR4CTFT.js.map → chunk-LSOD2A6N.js.map} +0 -0
- /package/dist/{chunk-VDIXNEWV.js.map → chunk-N5DQFA7L.js.map} +0 -0
- /package/dist/{chunk-R2IFWAHI.js.map → chunk-NZM2SSI4.js.map} +0 -0
- /package/dist/{chunk-KBZ3MQJX.js.map → chunk-O2DI4GHD.js.map} +0 -0
- /package/dist/{chunk-I7YWXECO.js.map → chunk-OBILAVWC.js.map} +0 -0
- /package/dist/{chunk-2VFZQ634.js.map → chunk-QP7IXF7R.js.map} +0 -0
- /package/dist/{chunk-MTTYJEKA.js.map → chunk-VSY5PAJ5.js.map} +0 -0
- /package/dist/{chunks-ACUC63N3.js.map → chunks-IFFRC5IQ.js.map} +0 -0
- /package/dist/{formula-LICM6K27.js.map → formula-AQZODKZF.js.map} +0 -0
- /package/dist/{formula-T4Q2UHWO.js.map → formula-E3N7KDDG.js.map} +0 -0
- /package/dist/{image-ocr-WZJURDX6.js.map → image-ocr-IMYXOHHV.js.map} +0 -0
- /package/dist/{image-ocr-XB2NFKGZ.js.map → image-ocr-LN3GSQPW.js.map} +0 -0
- /package/dist/{model-bundle-O2XYR54X.js.map → model-bundle-IHKNDLOT.js.map} +0 -0
- /package/dist/{models-SKK3NH3V.js.map → models-YXITRAMR.js.map} +0 -0
- /package/dist/{pdf-ocr-NJTFXBRC.js.map → pdf-ocr-4S2OAHUX.js.map} +0 -0
- /package/dist/{pdf-ocr-ZXR6Q6BK.js.map → pdf-ocr-YEBFWU2K.js.map} +0 -0
- /package/dist/{profile-io-BAQTYPK7.js.map → profile-io-GQWQR7YQ.js.map} +0 -0
- /package/dist/{rasterize-A2ZEACKV.js.map → rasterize-Y6TVFQ3M.js.map} +0 -0
- /package/dist/{redact-doc-26KN2LSZ.js.map → redact-doc-TRPZ3HNW.js.map} +0 -0
- /package/dist/{render-62ZUDMHB.js.map → render-GHT5HKBO.js.map} +0 -0
- /package/dist/{seal-3GXC2API.js.map → seal-3YTXSABW.js.map} +0 -0
- /package/dist/{setup-2A3E6WRE.js.map → setup-AGSCEHDB.js.map} +0 -0
- /package/dist/{visual-4ZBZRMCM.js.map → visual-R3E35Q2K.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
blocksToPages,
|
|
3
3
|
inlineImagesIntoMarkdown
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-O2DI4GHD.js";
|
|
5
5
|
import {
|
|
6
6
|
parsePageRange
|
|
7
7
|
} from "./chunk-V4BH5SRQ.js";
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
escapeGfm,
|
|
21
21
|
escapeHtmlCellText,
|
|
22
22
|
escapeLiteralDollar,
|
|
23
|
+
escapeLiteralTags,
|
|
23
24
|
flattenLayoutTables,
|
|
24
25
|
hasStructuredCellContent,
|
|
25
26
|
mapPuaText,
|
|
@@ -30,7 +31,7 @@ import {
|
|
|
30
31
|
tidyScriptTags,
|
|
31
32
|
unframeLayoutTables,
|
|
32
33
|
wrapScript
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-B2E6C2LH.js";
|
|
34
35
|
import {
|
|
35
36
|
KordocError,
|
|
36
37
|
OPTIONAL_DEP_INSTALL_HINT,
|
|
@@ -47,17 +48,17 @@ import {
|
|
|
47
48
|
toArrayBuffer,
|
|
48
49
|
unescapeHtml,
|
|
49
50
|
unzipLimitBytes
|
|
50
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-N5DQFA7L.js";
|
|
51
52
|
|
|
52
53
|
// src/plain-markdown.ts
|
|
53
54
|
function toPlainMarkdown(md2) {
|
|
54
|
-
return plainScripts(md2).replace(/!\[[^\]\n]*\]\([^)\n]*\)/g, "").replace(/<img\b[^>]*>/gi, "").replace(/(?<!!)\[([^\]\n]*)\]\((?:https?|mailto|ftp):[^)\s]*\)/g, "$1").replace(
|
|
55
|
+
return plainScripts(md2).replace(/!\[[^\]\n]*\]\([^)\n]*\)/g, "").replace(/<img\b[^>]*>/gi, "").replace(/(?<!!)\[([^\]\n]*)\]\((?:https?|mailto|ftp):[^)\s]*\)/g, "$1").replace(/(?<!\\)<\/?u>/g, "").replace(/(?<!\\)\*\*(?=\S)([^\n]*?\S)(?<!\\)\*\*/g, "$1").replace(/(<br>)+(?=<\/t[dh]>)/g, "").replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
// src/html-tables.ts
|
|
58
59
|
var TABLE_TAG = /(<\/?(?:table|tr|th|td)\b[^>]*>)/i;
|
|
59
60
|
function pipeCellToHtml(cell2) {
|
|
60
|
-
return cell2.split(/(<br
|
|
61
|
+
return cell2.split(/(<br>|(?<!\\)<\/?(?:u|sup|sub)>|<img\b[^>]*>)/).map((part, i) => i % 2 ? part : part.replace(/\\([\\`*_{}[\]()#+\-.!|~<>$])/g, "$1").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")).join("");
|
|
61
62
|
}
|
|
62
63
|
function splitPipeRow(line) {
|
|
63
64
|
const t = line.trim().replace(/^\|/, "").replace(/(?<!\\)\|$/, "");
|
|
@@ -688,6 +689,21 @@ async function decryptHwpxInPlace(zip, manifestXml, password) {
|
|
|
688
689
|
return decrypted.length;
|
|
689
690
|
}
|
|
690
691
|
|
|
692
|
+
// src/toc-entry.ts
|
|
693
|
+
var TOC_LEADER = "";
|
|
694
|
+
var LEADERS = /\x1F/g;
|
|
695
|
+
var PAGE_LABEL = /^(?:\d{1,4}|[ivxlc]{1,7}|\d{1,3}\s*[-–]\s*\d{1,4}|[-–]\s*\d{1,4}\s*[-–])$/i;
|
|
696
|
+
var TOC_ENTRY_BLOCKS = /* @__PURE__ */ new WeakSet();
|
|
697
|
+
function takeTocLeaders(text) {
|
|
698
|
+
if (!text.includes(TOC_LEADER)) return { text, tocEntry: false };
|
|
699
|
+
const lines = text.replace(/\x1E/g, "").split("\n").filter((l) => l.trim());
|
|
700
|
+
const tocEntry = lines.length > 0 && lines.every((l) => {
|
|
701
|
+
const at = l.lastIndexOf(TOC_LEADER);
|
|
702
|
+
return at > 0 && /\S/.test(l.slice(0, at).replace(LEADERS, "")) && PAGE_LABEL.test(l.slice(at + 1).trim());
|
|
703
|
+
});
|
|
704
|
+
return { text: text.replace(LEADERS, " "), tocEntry };
|
|
705
|
+
}
|
|
706
|
+
|
|
691
707
|
// src/hwpx/styles.ts
|
|
692
708
|
function isRealStrikeShape(shape) {
|
|
693
709
|
switch (shape) {
|
|
@@ -938,7 +954,7 @@ function detectHwpxHeadings(blocks, styleMap) {
|
|
|
938
954
|
}
|
|
939
955
|
}
|
|
940
956
|
for (const block of blocks) {
|
|
941
|
-
if (block.type !== "paragraph" || !block.text) continue;
|
|
957
|
+
if (block.type !== "paragraph" || !block.text || TOC_ENTRY_BLOCKS.has(block)) continue;
|
|
942
958
|
const text = block.text.trim();
|
|
943
959
|
if (text.length === 0 || text.length > 200 || /^\d+$/.test(text)) continue;
|
|
944
960
|
let level = 0;
|
|
@@ -1991,7 +2007,7 @@ function extractRunSpans(para2, ctx, mode, requireMixed) {
|
|
|
1991
2007
|
const tkids = rc.childNodes;
|
|
1992
2008
|
for (let k = 0; k < (tkids?.length ?? 0); k++) {
|
|
1993
2009
|
const tk = tkids[k];
|
|
1994
|
-
if (tk.nodeType === 3 || tk.nodeType === 4) text += escapeLiteralDollar(tk.textContent || "");
|
|
2010
|
+
if (tk.nodeType === 3 || tk.nodeType === 4) text += escapeLiteralTags(escapeLiteralDollar(tk.textContent || ""));
|
|
1995
2011
|
else if (tk.nodeType === 1) {
|
|
1996
2012
|
const ttag = (tk.tagName || tk.localName || "").replace(/^[^:]+:/, "");
|
|
1997
2013
|
if (ttag === "tab" || ttag === "fwSpace" || ttag === "hwSpace" || ttag === "nbSpace") text += " ";
|
|
@@ -2164,13 +2180,13 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
|
|
|
2164
2180
|
case "p": {
|
|
2165
2181
|
const paraPg = ctx.paraPage?.get(el);
|
|
2166
2182
|
if (paraPg !== void 0 && ctx.pageBase !== void 0) ctx.page = ctx.pageBase + paraPg + 1;
|
|
2167
|
-
const { text: rawText, href, footnote, style, segments, placeholderSpans } = extractParagraphInfo(el, ctx.styleMap, ctx);
|
|
2183
|
+
const { text: rawText, href, footnote, style, segments, placeholderSpans, tocEntry } = extractParagraphInfo(el, ctx.styleMap, ctx);
|
|
2168
2184
|
let text = rawText;
|
|
2169
2185
|
let headingLevel;
|
|
2170
2186
|
const ph = resolveParaHeading(el, ctx);
|
|
2171
2187
|
if (text) {
|
|
2172
2188
|
if (ph?.prefix) text = ph.prefix + " " + text;
|
|
2173
|
-
headingLevel = ph?.headingLevel;
|
|
2189
|
+
headingLevel = tocEntry ? void 0 : ph?.headingLevel;
|
|
2174
2190
|
}
|
|
2175
2191
|
if (segments) {
|
|
2176
2192
|
const cell2 = tableCtx?.cell ?? null;
|
|
@@ -2232,6 +2248,7 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
|
|
|
2232
2248
|
}
|
|
2233
2249
|
const block = { type: headingLevel ? "heading" : "paragraph", text, pageNumber: ctx.page };
|
|
2234
2250
|
if (headingLevel) block.level = headingLevel;
|
|
2251
|
+
if (tocEntry) TOC_ENTRY_BLOCKS.add(block);
|
|
2235
2252
|
if (style) block.style = style;
|
|
2236
2253
|
if (href) block.href = href;
|
|
2237
2254
|
if (footnote) block.footnoteText = footnote;
|
|
@@ -2664,7 +2681,7 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2664
2681
|
const open = openFields.pop();
|
|
2665
2682
|
if (open?.rangeIdx !== void 0) linkRanges[open.rangeIdx].end = text.length;
|
|
2666
2683
|
if (open?.guide !== void 0 && open.start !== void 0) {
|
|
2667
|
-
const value = text.slice(open.start).replace(
|
|
2684
|
+
const value = text.slice(open.start).replace(/\\([$<])/g, "$1");
|
|
2668
2685
|
if (value && (value === open.guide || value.trimEnd() === open.guide)) {
|
|
2669
2686
|
text = text.slice(0, open.start) + PH_OPEN + text.slice(open.start) + PH_CLOSE;
|
|
2670
2687
|
}
|
|
@@ -2773,7 +2790,7 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2773
2790
|
ctx.warnings?.push({ page: ctx.page, message: "\uBCC0\uACBD\uCD94\uC801 \uC0AD\uC81C \uD14D\uC2A4\uD2B8 \uCD9C\uB825 \uC81C\uC678", code: "HIDDEN_TEXT_FILTERED" });
|
|
2774
2791
|
}
|
|
2775
2792
|
} else {
|
|
2776
|
-
text += escapeLiteralDollar(t.replace(/\x1E/g, ""));
|
|
2793
|
+
text += escapeLiteralTags(escapeLiteralDollar(t.replace(/\x1E/g, "")));
|
|
2777
2794
|
}
|
|
2778
2795
|
continue;
|
|
2779
2796
|
}
|
|
@@ -2793,8 +2810,9 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2793
2810
|
// 점 채움을 탭 하나로 바꾸고 쪽 번호를 남기는 것과 같다). 종전엔 채움 탭 뒤를 쪽 번호로 보고 잘라, 목차 쪽 번호만이 아니라
|
|
2794
2811
|
// 일정표 "사용자 의견조사 ····· '26년 8~9월"(gate-fill 36646162)의 일정, 줄바꿈 뒤 다음 목차 항목
|
|
2795
2812
|
// "<참고2> 직종별사업체노동력조사 개요"(rhwp issue6044)까지 사라졌다
|
|
2813
|
+
// (채움 탭은 목차 항목 판정까지 TOC_LEADER 표지로 들고 가다 보통 탭으로 바꾼다 — toc-entry.ts)
|
|
2796
2814
|
case "tab":
|
|
2797
|
-
text += " ";
|
|
2815
|
+
text += /^(?:|0|NONE)$/i.test(child.getAttribute("leader") ?? "") ? " " : TOC_LEADER;
|
|
2798
2816
|
break;
|
|
2799
2817
|
case "br":
|
|
2800
2818
|
if ((child.getAttribute("type") || "line") === "line") text += "\n";
|
|
@@ -2941,6 +2959,9 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2941
2959
|
if (applied.length) href = void 0;
|
|
2942
2960
|
}
|
|
2943
2961
|
text = tidyScriptTags(text);
|
|
2962
|
+
const toc = takeTocLeaders(text);
|
|
2963
|
+
text = toc.text;
|
|
2964
|
+
const tocEntry = toc.tocEntry;
|
|
2944
2965
|
const cleanParaText = (raw) => {
|
|
2945
2966
|
let t = raw.replace(/[ \t]+/g, " ").trim();
|
|
2946
2967
|
if (/^그림입니다\.?\s*원본\s*그림의\s*(이름|크기)/.test(t)) t = "";
|
|
@@ -2976,7 +2997,7 @@ function extractParagraphInfo(para2, styleMap, ctx) {
|
|
|
2976
2997
|
if (!style.fontSize && !style.bold && !style.italic) style = void 0;
|
|
2977
2998
|
}
|
|
2978
2999
|
}
|
|
2979
|
-
return { text: cleanText, href, footnote, style, segments, placeholderSpans };
|
|
3000
|
+
return { text: cleanText, href, footnote, style, segments, placeholderSpans, ...tocEntry ? { tocEntry } : {} };
|
|
2980
3001
|
}
|
|
2981
3002
|
function withPrefixSpan(spans, prefix) {
|
|
2982
3003
|
return prefix ? [{ text: prefix + " " }, ...spans] : spans;
|
|
@@ -3180,6 +3201,11 @@ function parseDocInfo(records) {
|
|
|
3180
3201
|
return { charShapes, paraShapes, styles, binData, numberings, bullets, borderEdges };
|
|
3181
3202
|
}
|
|
3182
3203
|
var LITERAL_DOLLAR_MARK = "\uFDD0";
|
|
3204
|
+
var LITERAL_LT_MARK = "\uFDD1";
|
|
3205
|
+
var LITERAL_LT_TAG = /\uFDD1(?=\/?(?:u|sup|sub)>)/g;
|
|
3206
|
+
function resolveLiteralLt(text) {
|
|
3207
|
+
return text.includes(LITERAL_LT_MARK) ? text.replace(LITERAL_LT_TAG, "\\<").replaceAll(LITERAL_LT_MARK, "<") : text;
|
|
3208
|
+
}
|
|
3183
3209
|
function createParaTextState() {
|
|
3184
3210
|
return { text: "", ctrlIdx: 0, fieldStack: [], fieldRanges: [] };
|
|
3185
3211
|
}
|
|
@@ -3244,8 +3270,9 @@ function appendParaText(state, data, resolveControl) {
|
|
|
3244
3270
|
// ── inline 타입 (2바이트 + 14바이트 확장) ──
|
|
3245
3271
|
// 확장 u16[7] 중 [2] 의 하위 바이트 = 채움 모양(0 없음·3 점선 …), 상위 = 탭 종류+1 (rhwp tab_extended 실측).
|
|
3246
3272
|
// 채움 탭도 보통 탭 — 채움선은 글이 아니고 뒤 글(목차 쪽 번호 등)은 남긴다 (HWPX section-walker "tab" 과 같은 정책)
|
|
3273
|
+
// 본문 파서(tocLeaders)는 목차 항목 판정까지 채움 탭을 TOC_LEADER 표지로 받는다 (#121)
|
|
3247
3274
|
case CHAR_TAB:
|
|
3248
|
-
result += " ";
|
|
3275
|
+
result += state.tocLeaders && i + 6 <= data.length && (data.readUInt16LE(i + 4) & 255) !== 0 ? TOC_LEADER : " ";
|
|
3249
3276
|
if (i + 14 <= data.length) i += 14;
|
|
3250
3277
|
break;
|
|
3251
3278
|
default:
|
|
@@ -3278,7 +3305,7 @@ function appendParaText(state, data, resolveControl) {
|
|
|
3278
3305
|
break;
|
|
3279
3306
|
}
|
|
3280
3307
|
}
|
|
3281
|
-
result += ch === 36
|
|
3308
|
+
result += !state.dollarMark ? String.fromCharCode(ch) : ch === 36 ? LITERAL_DOLLAR_MARK : ch === 60 ? LITERAL_LT_MARK : String.fromCharCode(ch);
|
|
3282
3309
|
}
|
|
3283
3310
|
break;
|
|
3284
3311
|
}
|
|
@@ -5135,6 +5162,7 @@ function emitParagraphBlocks(p) {
|
|
|
5135
5162
|
pageNumber
|
|
5136
5163
|
};
|
|
5137
5164
|
if (p.headingLevel > 0) block.level = p.headingLevel;
|
|
5165
|
+
if (p.tocEntry) TOC_ENTRY_BLOCKS.add(block);
|
|
5138
5166
|
if (style) {
|
|
5139
5167
|
block.style = style;
|
|
5140
5168
|
if (style.strike || style.underline) block.text = headMarker ? `${headMarker} ${decorate(trimmed)}` : decorate(trimmed);
|
|
@@ -5410,6 +5438,7 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
5410
5438
|
}
|
|
5411
5439
|
const state = createParaTextState();
|
|
5412
5440
|
state.dollarMark = true;
|
|
5441
|
+
state.tocLeaders = true;
|
|
5413
5442
|
state.scriptAt = scriptLookup(charShapeRuns, ctx.docInfo);
|
|
5414
5443
|
const resolver = (idx, id) => {
|
|
5415
5444
|
let ctrl = idx >= 0 && idx < ctrls.length ? ctrls[idx] : void 0;
|
|
@@ -5434,7 +5463,7 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
5434
5463
|
const anchor = text.slice(r.start, r.end);
|
|
5435
5464
|
if (ctrl.guide !== void 0) {
|
|
5436
5465
|
if (ctx.doc.includeFieldPlaceholders) continue;
|
|
5437
|
-
const plain4 = anchor.replaceAll(LITERAL_DOLLAR_MARK, "$");
|
|
5466
|
+
const plain4 = anchor.replaceAll(LITERAL_DOLLAR_MARK, "$").replaceAll(LITERAL_LT_MARK, "<");
|
|
5438
5467
|
if (plain4 === ctrl.guide || plain4.trimEnd() === ctrl.guide) {
|
|
5439
5468
|
text = text.slice(0, r.start) + text.slice(r.end);
|
|
5440
5469
|
applied.push([r.start, r.end]);
|
|
@@ -5450,13 +5479,16 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
5450
5479
|
}
|
|
5451
5480
|
}
|
|
5452
5481
|
if (text.includes(LITERAL_DOLLAR_MARK)) text = text.replaceAll(LITERAL_DOLLAR_MARK, "\\$");
|
|
5482
|
+
text = resolveLiteralLt(text);
|
|
5453
5483
|
text = tidyScriptTags(text);
|
|
5484
|
+
const toc = takeTocLeaders(text);
|
|
5485
|
+
text = toc.text;
|
|
5454
5486
|
let headingLevel = 0;
|
|
5455
5487
|
let headMarker = null;
|
|
5456
5488
|
const ps = ctx.docInfo && paraShapeId >= 0 && paraShapeId < ctx.docInfo.paraShapes.length ? ctx.docInfo.paraShapes[paraShapeId] : null;
|
|
5457
5489
|
if (ps && ps.headType > 0) {
|
|
5458
5490
|
if (ps.headType === 1) {
|
|
5459
|
-
headingLevel = Math.min(ps.paraLevel + 1, 6);
|
|
5491
|
+
if (!toc.tocEntry) headingLevel = Math.min(ps.paraLevel + 1, 6);
|
|
5460
5492
|
}
|
|
5461
5493
|
if (ps.headType === 1 || ps.headType === 2) {
|
|
5462
5494
|
const nid = ps.numberingId || (ps.headType === 1 ? ctx.doc.outlineNumberingId : 0);
|
|
@@ -5478,6 +5510,7 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
5478
5510
|
text,
|
|
5479
5511
|
headMarker,
|
|
5480
5512
|
headingLevel,
|
|
5513
|
+
tocEntry: toc.tocEntry,
|
|
5481
5514
|
style: ctx.docInfo && charShapeIds.length > 0 ? resolveCharStyle(charShapeIds, ctx.docInfo) : void 0,
|
|
5482
5515
|
footnotes: ctrls.filter((c) => c.footnote).map((c) => c.footnote),
|
|
5483
5516
|
// 컨트롤 파생 블록 (표/이미지/글상자) — 컨트롤 순서대로
|
|
@@ -6095,7 +6128,7 @@ function detectHwp5Headings(blocks, docInfo) {
|
|
|
6095
6128
|
if (baseFontSize <= 0) return;
|
|
6096
6129
|
for (const block of blocks) {
|
|
6097
6130
|
if (block.type === "heading") continue;
|
|
6098
|
-
if (block.type !== "paragraph" || !block.text) continue;
|
|
6131
|
+
if (block.type !== "paragraph" || !block.text || TOC_ENTRY_BLOCKS.has(block)) continue;
|
|
6099
6132
|
const text = block.text.trim();
|
|
6100
6133
|
if (text.length === 0 || text.length > 200) continue;
|
|
6101
6134
|
if (/^\d+$/.test(text)) continue;
|
|
@@ -19006,7 +19039,7 @@ function parseCharStream(reader, charCount, ctx, para2) {
|
|
|
19006
19039
|
continue;
|
|
19007
19040
|
}
|
|
19008
19041
|
if (ch >= 32) {
|
|
19009
|
-
para2.text += escapeLiteralDollar(decodeJohabText(ch) ?? "");
|
|
19042
|
+
para2.text += escapeLiteralTags(escapeLiteralDollar(decodeJohabText(ch) ?? ""));
|
|
19010
19043
|
continue;
|
|
19011
19044
|
}
|
|
19012
19045
|
if (ch === 9) {
|
|
@@ -19354,7 +19387,7 @@ function collectRichText(root) {
|
|
|
19354
19387
|
const el = children[i];
|
|
19355
19388
|
const local = el.localName || el.tagName?.replace(/^[^:]+:/, "") || "";
|
|
19356
19389
|
if (local === "rPh") continue;
|
|
19357
|
-
if (local === "t") out += el.textContent ?? "";
|
|
19390
|
+
if (local === "t") out += escapeLiteralTags(el.textContent ?? "");
|
|
19358
19391
|
else walk(el);
|
|
19359
19392
|
}
|
|
19360
19393
|
};
|
|
@@ -19978,14 +20011,14 @@ function extractSheetCells(records, bofIndex, sst, convertNum) {
|
|
|
19978
20011
|
const h = readCellHeader(rec.data);
|
|
19979
20012
|
if (h && rec.data.length >= 10) {
|
|
19980
20013
|
const isst = rec.data.readUInt32LE(6);
|
|
19981
|
-
cells.push({ row: h.row, col: h.col, value: sst[isst] ?? "" });
|
|
20014
|
+
cells.push({ row: h.row, col: h.col, value: escapeLiteralTags(sst[isst] ?? "") });
|
|
19982
20015
|
}
|
|
19983
20016
|
break;
|
|
19984
20017
|
}
|
|
19985
20018
|
case OP_LABEL: {
|
|
19986
20019
|
const h = readCellHeader(rec.data);
|
|
19987
20020
|
if (h) {
|
|
19988
|
-
cells.push({ row: h.row, col: h.col, value: decodeLabelString(rec.data) });
|
|
20021
|
+
cells.push({ row: h.row, col: h.col, value: escapeLiteralTags(decodeLabelString(rec.data)) });
|
|
19989
20022
|
}
|
|
19990
20023
|
break;
|
|
19991
20024
|
}
|
|
@@ -20001,7 +20034,7 @@ function extractSheetCells(records, bofIndex, sst, convertNum) {
|
|
|
20001
20034
|
cells.push({
|
|
20002
20035
|
row: h.row,
|
|
20003
20036
|
col: h.col,
|
|
20004
|
-
value: decodeFormulaStringRecord(next.data)
|
|
20037
|
+
value: escapeLiteralTags(decodeFormulaStringRecord(next.data))
|
|
20005
20038
|
});
|
|
20006
20039
|
i = j;
|
|
20007
20040
|
} else {
|
|
@@ -20904,7 +20937,7 @@ function parseFootnotes(xml) {
|
|
|
20904
20937
|
const runs = findElements(p, "r");
|
|
20905
20938
|
for (const r of runs) {
|
|
20906
20939
|
const tElements = getChildElements(r, "t");
|
|
20907
|
-
for (const t of tElements) texts.push(t.textContent ?? "");
|
|
20940
|
+
for (const t of tElements) texts.push(escapeLiteralTags(t.textContent ?? ""));
|
|
20908
20941
|
}
|
|
20909
20942
|
}
|
|
20910
20943
|
notes.set(id, texts.join("").trim());
|
|
@@ -20935,7 +20968,7 @@ function collectOmmlRoots(p) {
|
|
|
20935
20968
|
function extractRun(r) {
|
|
20936
20969
|
let text = "";
|
|
20937
20970
|
for (const el of effectiveChildElements(r)) {
|
|
20938
|
-
if (matchesLocal(el, "t")) text += el.textContent ?? "";
|
|
20971
|
+
if (matchesLocal(el, "t")) text += escapeLiteralTags(el.textContent ?? "");
|
|
20939
20972
|
else if (matchesLocal(el, "br") || matchesLocal(el, "cr")) text += "\n";
|
|
20940
20973
|
else if (matchesLocal(el, "tab")) text += " ";
|
|
20941
20974
|
else if (matchesLocal(el, "sym")) text += symbolChar(getAttr(el, "font"), getAttr(el, "char"));
|
|
@@ -21446,8 +21479,323 @@ async function parseDocxDocument(buffer, options) {
|
|
|
21446
21479
|
};
|
|
21447
21480
|
}
|
|
21448
21481
|
|
|
21449
|
-
// src/
|
|
21482
|
+
// src/pptx/parser.ts
|
|
21483
|
+
import JSZip6 from "jszip";
|
|
21450
21484
|
import { DOMParser as DOMParser4 } from "@xmldom/xmldom";
|
|
21485
|
+
var MAX_DECOMPRESS_SIZE6 = unzipLimitBytes(100 * 1024 * 1024);
|
|
21486
|
+
var MEDIA_PART_RE2 = /^ppt\/(?:media|embeddings)\//;
|
|
21487
|
+
var MAX_ZIP_ENTRIES2 = 1e4;
|
|
21488
|
+
var MAX_SLIDES = 2e3;
|
|
21489
|
+
var SKIP_PLACEHOLDERS = /* @__PURE__ */ new Set(["sldNum", "dt", "ftr", "hdr", "sldImg"]);
|
|
21490
|
+
var BULLET_PLACEHOLDERS = /* @__PURE__ */ new Set(["body", "obj"]);
|
|
21491
|
+
var REL_NOTES = "/notesSlide";
|
|
21492
|
+
var REL_IMAGE = "/image";
|
|
21493
|
+
var SLIDE_PART_RE = /^ppt\/slides\/slide(\d+)\.xml$/;
|
|
21494
|
+
var IMAGE_MIME = {
|
|
21495
|
+
png: "image/png",
|
|
21496
|
+
jpg: "image/jpeg",
|
|
21497
|
+
jpeg: "image/jpeg",
|
|
21498
|
+
gif: "image/gif",
|
|
21499
|
+
bmp: "image/bmp",
|
|
21500
|
+
wmf: "image/wmf",
|
|
21501
|
+
emf: "image/emf",
|
|
21502
|
+
tif: "image/tiff",
|
|
21503
|
+
tiff: "image/tiff",
|
|
21504
|
+
svg: "image/svg+xml"
|
|
21505
|
+
};
|
|
21506
|
+
function parseXml3(text) {
|
|
21507
|
+
return new DOMParser4().parseFromString(stripDtd(text), "text/xml");
|
|
21508
|
+
}
|
|
21509
|
+
function getAttr2(el, name) {
|
|
21510
|
+
const attrs = el.attributes;
|
|
21511
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
21512
|
+
const attr = attrs[i];
|
|
21513
|
+
if (attr.localName === name || attr.name === name) return attr.value;
|
|
21514
|
+
}
|
|
21515
|
+
return null;
|
|
21516
|
+
}
|
|
21517
|
+
var NS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
21518
|
+
function getRelId(el) {
|
|
21519
|
+
const attrs = el.attributes;
|
|
21520
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
21521
|
+
const attr = attrs[i];
|
|
21522
|
+
if (attr.localName === "id" && (attr.namespaceURI === NS_REL || attr.name === "r:id")) return attr.value;
|
|
21523
|
+
}
|
|
21524
|
+
return null;
|
|
21525
|
+
}
|
|
21526
|
+
function findPath(el, ...names) {
|
|
21527
|
+
for (const name of names) {
|
|
21528
|
+
if (!el) return null;
|
|
21529
|
+
el = findChildByLocalName(el, name);
|
|
21530
|
+
}
|
|
21531
|
+
return el;
|
|
21532
|
+
}
|
|
21533
|
+
function resolvePart(baseDir, target) {
|
|
21534
|
+
if (target.startsWith("/")) return target.slice(1);
|
|
21535
|
+
const parts = baseDir ? baseDir.split("/") : [];
|
|
21536
|
+
for (const seg of target.split("/")) {
|
|
21537
|
+
if (seg === "..") parts.pop();
|
|
21538
|
+
else if (seg && seg !== ".") parts.push(seg);
|
|
21539
|
+
}
|
|
21540
|
+
return parts.join("/");
|
|
21541
|
+
}
|
|
21542
|
+
async function readRels(zip, part) {
|
|
21543
|
+
const map = /* @__PURE__ */ new Map();
|
|
21544
|
+
const slash = part.lastIndexOf("/");
|
|
21545
|
+
const dir = slash >= 0 ? part.slice(0, slash) : "";
|
|
21546
|
+
const file = zip.file(`${dir ? dir + "/" : ""}_rels/${part.slice(slash + 1)}.rels`);
|
|
21547
|
+
if (!file) return map;
|
|
21548
|
+
const doc = parseXml3(await file.async("text"));
|
|
21549
|
+
for (const rel of childrenByLocalName(doc.documentElement, "Relationship")) {
|
|
21550
|
+
const id = getAttr2(rel, "Id");
|
|
21551
|
+
const target = getAttr2(rel, "Target");
|
|
21552
|
+
if (!id || !target || getAttr2(rel, "TargetMode") === "External") continue;
|
|
21553
|
+
map.set(id, { type: getAttr2(rel, "Type") ?? "", target: resolvePart(dir, target) });
|
|
21554
|
+
}
|
|
21555
|
+
return map;
|
|
21556
|
+
}
|
|
21557
|
+
async function slideParts(zip) {
|
|
21558
|
+
const ordered = [];
|
|
21559
|
+
const presFile = zip.file("ppt/presentation.xml");
|
|
21560
|
+
if (presFile) {
|
|
21561
|
+
const pres = parseXml3(await presFile.async("text"));
|
|
21562
|
+
const rels = await readRels(zip, "ppt/presentation.xml");
|
|
21563
|
+
const list = findChildByLocalName(pres.documentElement, "sldIdLst");
|
|
21564
|
+
for (const sld of list ? childrenByLocalName(list, "sldId") : []) {
|
|
21565
|
+
const target = rels.get(getRelId(sld) ?? "")?.target;
|
|
21566
|
+
if (target && zip.file(target)) ordered.push(target);
|
|
21567
|
+
}
|
|
21568
|
+
}
|
|
21569
|
+
if (ordered.length === 0) {
|
|
21570
|
+
const names = Object.keys(zip.files).filter((n) => SLIDE_PART_RE.test(n));
|
|
21571
|
+
names.sort((a, b) => Number(SLIDE_PART_RE.exec(a)[1]) - Number(SLIDE_PART_RE.exec(b)[1]));
|
|
21572
|
+
ordered.push(...names);
|
|
21573
|
+
}
|
|
21574
|
+
if (ordered.length > MAX_SLIDES) throw new KordocError(`PPTX \uC2AC\uB77C\uC774\uB4DC \uC218 \uCD08\uACFC: ${ordered.length} (\uCD5C\uB300 ${MAX_SLIDES})`);
|
|
21575
|
+
return ordered;
|
|
21576
|
+
}
|
|
21577
|
+
function paragraphText(p) {
|
|
21578
|
+
let text = "";
|
|
21579
|
+
for (const child of elementChildren(p)) {
|
|
21580
|
+
const name = localName(child);
|
|
21581
|
+
if (name === "r" || name === "fld") {
|
|
21582
|
+
const t = findChildByLocalName(child, "t");
|
|
21583
|
+
if (t) text += escapeLiteralTags(escapeLiteralDollar(rawTextContent(t)));
|
|
21584
|
+
} else if (name === "br") {
|
|
21585
|
+
text += " ";
|
|
21586
|
+
}
|
|
21587
|
+
}
|
|
21588
|
+
return text.replace(/\s+/g, " ").trim();
|
|
21589
|
+
}
|
|
21590
|
+
function bodyParagraphs(txBody) {
|
|
21591
|
+
const out = [];
|
|
21592
|
+
for (const p of childrenByLocalName(txBody, "p")) {
|
|
21593
|
+
const text = paragraphText(p);
|
|
21594
|
+
if (!text) continue;
|
|
21595
|
+
const pPr = findChildByLocalName(p, "pPr");
|
|
21596
|
+
let bullet;
|
|
21597
|
+
if (pPr) {
|
|
21598
|
+
if (findChildByLocalName(pPr, "buNone")) bullet = "none";
|
|
21599
|
+
else if (findChildByLocalName(pPr, "buAutoNum")) bullet = "ordered";
|
|
21600
|
+
else if (findChildByLocalName(pPr, "buChar") || findChildByLocalName(pPr, "buBlip")) bullet = "unordered";
|
|
21601
|
+
}
|
|
21602
|
+
const lvl = Math.max(0, parseInt(pPr ? getAttr2(pPr, "lvl") ?? "0" : "0", 10) || 0);
|
|
21603
|
+
out.push({ text, lvl, bullet });
|
|
21604
|
+
}
|
|
21605
|
+
return out;
|
|
21606
|
+
}
|
|
21607
|
+
function placeholderType(sp) {
|
|
21608
|
+
const ph = findPath(sp, "nvSpPr", "nvPr", "ph");
|
|
21609
|
+
return ph ? getAttr2(ph, "type") ?? "obj" : null;
|
|
21610
|
+
}
|
|
21611
|
+
function pushParagraphs(paras, bulletDefault, page, out) {
|
|
21612
|
+
let lastList = null;
|
|
21613
|
+
for (const para2 of paras) {
|
|
21614
|
+
const bullet = para2.bullet ?? (bulletDefault ? "unordered" : "none");
|
|
21615
|
+
if (bullet === "none") {
|
|
21616
|
+
out.push({ type: "paragraph", text: para2.text, pageNumber: page });
|
|
21617
|
+
lastList = null;
|
|
21618
|
+
continue;
|
|
21619
|
+
}
|
|
21620
|
+
const item = { type: "list", text: para2.text, listType: bullet, pageNumber: page };
|
|
21621
|
+
if (para2.lvl > 0 && lastList) {
|
|
21622
|
+
;
|
|
21623
|
+
(lastList.children ??= []).push(item);
|
|
21624
|
+
} else {
|
|
21625
|
+
out.push(item);
|
|
21626
|
+
lastList = item;
|
|
21627
|
+
}
|
|
21628
|
+
}
|
|
21629
|
+
}
|
|
21630
|
+
function parseTable2(tbl2, page, keepEmptyCols) {
|
|
21631
|
+
const rows = childrenByLocalName(tbl2, "tr");
|
|
21632
|
+
if (rows.length === 0) return null;
|
|
21633
|
+
const cellRows = rows.map((tr, r) => {
|
|
21634
|
+
const cells = [];
|
|
21635
|
+
childrenByLocalName(tr, "tc").forEach((tc2, c) => {
|
|
21636
|
+
if (getAttr2(tc2, "hMerge") === "1" || getAttr2(tc2, "vMerge") === "1") return;
|
|
21637
|
+
const txBody = findChildByLocalName(tc2, "txBody");
|
|
21638
|
+
const text = txBody ? bodyParagraphs(txBody).map((p) => p.text).join("\n") : "";
|
|
21639
|
+
cells.push({
|
|
21640
|
+
text,
|
|
21641
|
+
colSpan: Math.max(1, parseInt(getAttr2(tc2, "gridSpan") ?? "1", 10) || 1),
|
|
21642
|
+
rowSpan: Math.max(1, parseInt(getAttr2(tc2, "rowSpan") ?? "1", 10) || 1),
|
|
21643
|
+
colAddr: c,
|
|
21644
|
+
rowAddr: r
|
|
21645
|
+
});
|
|
21646
|
+
});
|
|
21647
|
+
return cells;
|
|
21648
|
+
});
|
|
21649
|
+
const table2 = buildTable(cellRows, { keepAnchoredEmptyCols: keepEmptyCols });
|
|
21650
|
+
if (table2.rows === 0 || table2.cols === 0) return null;
|
|
21651
|
+
return { type: "table", table: table2, pageNumber: page };
|
|
21652
|
+
}
|
|
21653
|
+
async function pictureBlock(pic, ctx) {
|
|
21654
|
+
const blip = findPath(pic, "blipFill", "blip");
|
|
21655
|
+
const embed = blip ? getAttr2(blip, "embed") : null;
|
|
21656
|
+
const rel = embed ? ctx.rels.get(embed) : void 0;
|
|
21657
|
+
if (!rel || !rel.type.endsWith(REL_IMAGE)) return null;
|
|
21658
|
+
let filename = ctx.imageNames.get(rel.target);
|
|
21659
|
+
if (!filename) {
|
|
21660
|
+
const file = ctx.zip.file(rel.target);
|
|
21661
|
+
if (!file) return null;
|
|
21662
|
+
const ext = rel.target.split(".").pop()?.toLowerCase() ?? "png";
|
|
21663
|
+
filename = `image_${String(ctx.imageNames.size + 1).padStart(3, "0")}.${ext}`;
|
|
21664
|
+
try {
|
|
21665
|
+
if (ctx.options?.images !== false) {
|
|
21666
|
+
const data = await file.async("uint8array");
|
|
21667
|
+
ctx.images.push({ filename, data, mimeType: IMAGE_MIME[ext] ?? detectImageMime(data) ?? "application/octet-stream", source: rel.target });
|
|
21668
|
+
}
|
|
21669
|
+
} catch (err) {
|
|
21670
|
+
ctx.warnings.push({
|
|
21671
|
+
page: ctx.page,
|
|
21672
|
+
code: "SKIPPED_IMAGE",
|
|
21673
|
+
message: `PPTX \uC774\uBBF8\uC9C0 \uCD94\uCD9C \uC2E4\uD328 (${rel.target}): ${err instanceof Error ? err.message : String(err)}`
|
|
21674
|
+
});
|
|
21675
|
+
return null;
|
|
21676
|
+
}
|
|
21677
|
+
ctx.imageNames.set(rel.target, filename);
|
|
21678
|
+
}
|
|
21679
|
+
return { type: "image", text: filename, pageNumber: ctx.page };
|
|
21680
|
+
}
|
|
21681
|
+
async function walkShapes(tree, ctx, out, depth = 0) {
|
|
21682
|
+
if (depth > MAX_XML_DEPTH) return;
|
|
21683
|
+
for (const el of elementChildren(tree)) {
|
|
21684
|
+
switch (localName(el)) {
|
|
21685
|
+
case "grpSp":
|
|
21686
|
+
await walkShapes(el, ctx, out, depth + 1);
|
|
21687
|
+
break;
|
|
21688
|
+
case "AlternateContent": {
|
|
21689
|
+
const choice = findChildByLocalName(el, "Choice");
|
|
21690
|
+
if (choice) await walkShapes(choice, ctx, out, depth + 1);
|
|
21691
|
+
break;
|
|
21692
|
+
}
|
|
21693
|
+
case "sp": {
|
|
21694
|
+
const ph = placeholderType(el);
|
|
21695
|
+
const txBody = findChildByLocalName(el, "txBody");
|
|
21696
|
+
if (ph && SKIP_PLACEHOLDERS.has(ph) || !txBody) break;
|
|
21697
|
+
const paras = bodyParagraphs(txBody);
|
|
21698
|
+
if (paras.length === 0) break;
|
|
21699
|
+
if (ph === "title" || ph === "ctrTitle") {
|
|
21700
|
+
out.push({ type: "heading", level: ph === "ctrTitle" ? 1 : 2, text: paras.map((p) => p.text).join(" "), pageNumber: ctx.page });
|
|
21701
|
+
} else {
|
|
21702
|
+
pushParagraphs(paras, ph !== null && BULLET_PLACEHOLDERS.has(ph), ctx.page, out);
|
|
21703
|
+
}
|
|
21704
|
+
break;
|
|
21705
|
+
}
|
|
21706
|
+
case "graphicFrame": {
|
|
21707
|
+
const data = findPath(el, "graphic", "graphicData");
|
|
21708
|
+
const tbl2 = data ? findChildByLocalName(data, "tbl") : null;
|
|
21709
|
+
if (tbl2) {
|
|
21710
|
+
const block = parseTable2(tbl2, ctx.page, ctx.options?.keepTrailingEmptyCols);
|
|
21711
|
+
if (block) out.push(block);
|
|
21712
|
+
} else if (data) {
|
|
21713
|
+
const uri = getAttr2(data, "uri") ?? "";
|
|
21714
|
+
const kind = /chart/i.test(uri) ? "\uCC28\uD2B8" : /diagram/i.test(uri) ? "SmartArt" : "\uAC1C\uCCB4";
|
|
21715
|
+
ctx.warnings.push({ page: ctx.page, code: "UNSUPPORTED_ELEMENT", message: `PPTX ${kind}\uC758 \uAE00\uC740 \uC77D\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (${ctx.page}\uCABD)` });
|
|
21716
|
+
}
|
|
21717
|
+
break;
|
|
21718
|
+
}
|
|
21719
|
+
case "pic": {
|
|
21720
|
+
const block = await pictureBlock(el, ctx);
|
|
21721
|
+
if (block) out.push(block);
|
|
21722
|
+
break;
|
|
21723
|
+
}
|
|
21724
|
+
}
|
|
21725
|
+
}
|
|
21726
|
+
}
|
|
21727
|
+
async function notesText(zip, rels) {
|
|
21728
|
+
const rel = [...rels.values()].find((r) => r.type.endsWith(REL_NOTES));
|
|
21729
|
+
const file = rel ? zip.file(rel.target) : null;
|
|
21730
|
+
if (!file) return "";
|
|
21731
|
+
const tree = findPath(parseXml3(await file.async("text")).documentElement, "cSld", "spTree");
|
|
21732
|
+
const texts = [];
|
|
21733
|
+
for (const sp of tree ? childrenByLocalName(tree, "sp") : []) {
|
|
21734
|
+
const txBody = findChildByLocalName(sp, "txBody");
|
|
21735
|
+
if (placeholderType(sp) === "body" && txBody) texts.push(...bodyParagraphs(txBody).map((p) => p.text));
|
|
21736
|
+
}
|
|
21737
|
+
return texts.join(" ");
|
|
21738
|
+
}
|
|
21739
|
+
async function parsePptxDocument(buffer, options) {
|
|
21740
|
+
precheckZipSize(buffer, MAX_DECOMPRESS_SIZE6, MAX_ZIP_ENTRIES2, { re: MEDIA_PART_RE2, skip: options?.images === false });
|
|
21741
|
+
const zip = await JSZip6.loadAsync(buffer);
|
|
21742
|
+
if (!zip.file("ppt/presentation.xml")) {
|
|
21743
|
+
throw new KordocError("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 PPTX \uD30C\uC77C: ppt/presentation.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
21744
|
+
}
|
|
21745
|
+
const warnings = [];
|
|
21746
|
+
const blocks = [];
|
|
21747
|
+
const imageNames = /* @__PURE__ */ new Map();
|
|
21748
|
+
const images = [];
|
|
21749
|
+
const slides = await slideParts(zip);
|
|
21750
|
+
for (let i = 0; i < slides.length; i++) {
|
|
21751
|
+
const page = i + 1;
|
|
21752
|
+
const root = parseXml3(await zip.file(slides[i]).async("text")).documentElement;
|
|
21753
|
+
if (getAttr2(root, "show") === "0") {
|
|
21754
|
+
warnings.push({ page, code: "HIDDEN_TEXT_FILTERED", message: `PPTX \uC228\uAE34 \uC2AC\uB77C\uC774\uB4DC ${page}\uCABD\uC744 \uAC74\uB108\uB701\uB2C8\uB2E4` });
|
|
21755
|
+
continue;
|
|
21756
|
+
}
|
|
21757
|
+
const rels = await readRels(zip, slides[i]);
|
|
21758
|
+
const tree = findPath(root, "cSld", "spTree");
|
|
21759
|
+
if (tree) await walkShapes(tree, { zip, rels, page, warnings, options, imageNames, images }, blocks);
|
|
21760
|
+
const notes = await notesText(zip, rels);
|
|
21761
|
+
if (notes) blocks.push({ type: "paragraph", text: `\uBC1C\uD45C\uC790 \uB178\uD2B8: ${notes}`, quote: true, pageNumber: page });
|
|
21762
|
+
}
|
|
21763
|
+
const metadata = { pageCount: slides.length, pageMode: "layout" };
|
|
21764
|
+
const coreFile = zip.file("docProps/core.xml");
|
|
21765
|
+
if (coreFile) {
|
|
21766
|
+
try {
|
|
21767
|
+
const coreDoc = parseXml3(await coreFile.async("text"));
|
|
21768
|
+
const getFirst = (tag) => {
|
|
21769
|
+
const els = coreDoc.getElementsByTagName(tag);
|
|
21770
|
+
return els.length > 0 ? (els[0].textContent ?? "").trim() || void 0 : void 0;
|
|
21771
|
+
};
|
|
21772
|
+
metadata.title = getFirst("dc:title") || getFirst("dcterms:title");
|
|
21773
|
+
metadata.author = getFirst("dc:creator");
|
|
21774
|
+
metadata.description = getFirst("dc:description");
|
|
21775
|
+
const created = getFirst("dcterms:created");
|
|
21776
|
+
if (created) metadata.createdAt = created;
|
|
21777
|
+
const modified = getFirst("dcterms:modified");
|
|
21778
|
+
if (modified) metadata.modifiedAt = modified;
|
|
21779
|
+
} catch (err) {
|
|
21780
|
+
warnings.push({
|
|
21781
|
+
code: "PARTIAL_PARSE",
|
|
21782
|
+
message: `PPTX \uBA54\uD0C0\uB370\uC774\uD130(core.xml) \uD30C\uC2F1 \uC2E4\uD328: ${err instanceof Error ? err.message : String(err)}`
|
|
21783
|
+
});
|
|
21784
|
+
}
|
|
21785
|
+
}
|
|
21786
|
+
const outline = blocks.filter((b) => b.type === "heading").map((b) => ({ level: b.level ?? 2, text: b.text ?? "", pageNumber: b.pageNumber }));
|
|
21787
|
+
return {
|
|
21788
|
+
markdown: blocksToMarkdown(blocks),
|
|
21789
|
+
blocks,
|
|
21790
|
+
metadata,
|
|
21791
|
+
outline: outline.length > 0 ? outline : void 0,
|
|
21792
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
21793
|
+
images: images.length > 0 ? images : void 0
|
|
21794
|
+
};
|
|
21795
|
+
}
|
|
21796
|
+
|
|
21797
|
+
// src/hwpml/parser.ts
|
|
21798
|
+
import { DOMParser as DOMParser5 } from "@xmldom/xmldom";
|
|
21451
21799
|
var MAX_TABLE_ROWS = 5e3;
|
|
21452
21800
|
var MAX_TABLE_COLS = 500;
|
|
21453
21801
|
var MAX_HWPML_BYTES = 50 * 1024 * 1024;
|
|
@@ -21459,7 +21807,7 @@ function parseHwpmlDocument(buffer, options) {
|
|
|
21459
21807
|
const normalized = text.replace(/ /g, " ");
|
|
21460
21808
|
const xml = stripDtd(normalized);
|
|
21461
21809
|
const warnings = [];
|
|
21462
|
-
const parser = new
|
|
21810
|
+
const parser = new DOMParser5({
|
|
21463
21811
|
onError: (_level, msg2) => {
|
|
21464
21812
|
warnings.push({ message: `HWPML XML \uD30C\uC2F1 \uACBD\uACE0: ${msg2}`, code: "MALFORMED_XML" });
|
|
21465
21813
|
}
|
|
@@ -21552,7 +21900,7 @@ function walkContent(node, blocks, paraShapeMap, sectionNum, warnings, inHeaderF
|
|
|
21552
21900
|
}
|
|
21553
21901
|
if (tag === "TABLE") {
|
|
21554
21902
|
if (!inHeaderFooter) {
|
|
21555
|
-
|
|
21903
|
+
parseTable3(el, blocks, paraShapeMap, sectionNum, warnings, keep);
|
|
21556
21904
|
}
|
|
21557
21905
|
continue;
|
|
21558
21906
|
}
|
|
@@ -21571,7 +21919,7 @@ function walkTablesInP(node, blocks, paraShapeMap, sectionNum, warnings, keep, d
|
|
|
21571
21919
|
if (el.nodeType !== 1) continue;
|
|
21572
21920
|
const tag = localName(el);
|
|
21573
21921
|
if (tag === "TABLE") {
|
|
21574
|
-
|
|
21922
|
+
parseTable3(el, blocks, paraShapeMap, sectionNum, warnings, keep);
|
|
21575
21923
|
continue;
|
|
21576
21924
|
}
|
|
21577
21925
|
if (tag === "FOOTNOTE" || tag === "ENDNOTE" || tag === "HEADER" || tag === "FOOTER") continue;
|
|
@@ -21604,7 +21952,7 @@ function collectCharText(node, parts, depth = 0) {
|
|
|
21604
21952
|
if (tag === "CHAR") {
|
|
21605
21953
|
for (const c of Array.from(el.childNodes)) {
|
|
21606
21954
|
const t = c.nodeType === 1 ? localName(c) === "TAB" ? " " : rawTextContent(c) : c.nodeType === 3 || c.nodeType === 4 ? c.nodeValue ?? "" : "";
|
|
21607
|
-
if (t) parts.push(t);
|
|
21955
|
+
if (t) parts.push(escapeLiteralTags(t));
|
|
21608
21956
|
}
|
|
21609
21957
|
} else if (tag === "TABLE" || tag === "PICTURE" || tag === "SHAPEOBJECT") {
|
|
21610
21958
|
} else if (tag === "AUTONUM") {
|
|
@@ -21613,7 +21961,7 @@ function collectCharText(node, parts, depth = 0) {
|
|
|
21613
21961
|
}
|
|
21614
21962
|
}
|
|
21615
21963
|
}
|
|
21616
|
-
function
|
|
21964
|
+
function parseTable3(el, blocks, _paraShapeMap, sectionNum, warnings, keep) {
|
|
21617
21965
|
const table2 = buildHmlTable(el, warnings, keep, 0);
|
|
21618
21966
|
if (!table2) return;
|
|
21619
21967
|
const caption = extractShapeCaption(el);
|
|
@@ -22555,10 +22903,10 @@ function fillInlineFields(text, values, filled, matchedLabels, blockedLabels) {
|
|
|
22555
22903
|
}
|
|
22556
22904
|
|
|
22557
22905
|
// src/form/filler-hwpx.ts
|
|
22558
|
-
import
|
|
22906
|
+
import JSZip8 from "jszip";
|
|
22559
22907
|
|
|
22560
22908
|
// src/form/click-here.ts
|
|
22561
|
-
import
|
|
22909
|
+
import JSZip7 from "jszip";
|
|
22562
22910
|
|
|
22563
22911
|
// src/roundtrip/source-map.ts
|
|
22564
22912
|
function escapeXmlText(text) {
|
|
@@ -22644,7 +22992,7 @@ function prefixOf(qname) {
|
|
|
22644
22992
|
}
|
|
22645
22993
|
function scanSectionXml(xml, sectionIndex) {
|
|
22646
22994
|
const stack = [];
|
|
22647
|
-
const
|
|
22995
|
+
const bodyParagraphs2 = [];
|
|
22648
22996
|
const tables = [];
|
|
22649
22997
|
const headerTexts = [];
|
|
22650
22998
|
const footerTexts = [];
|
|
@@ -22767,8 +23115,8 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
22767
23115
|
} else if (local === "cellAddr") {
|
|
22768
23116
|
const cell2 = cellStack[cellStack.length - 1];
|
|
22769
23117
|
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
22770
|
-
const ca = parseInt(
|
|
22771
|
-
const ra = parseInt(
|
|
23118
|
+
const ca = parseInt(getAttr3(attrsRaw, "colAddr") || "", 10);
|
|
23119
|
+
const ra = parseInt(getAttr3(attrsRaw, "rowAddr") || "", 10);
|
|
22772
23120
|
if (!isNaN(ca)) cell2.colAddr = ca;
|
|
22773
23121
|
if (!isNaN(ra)) cell2.rowAddr = ra;
|
|
22774
23122
|
cell2.addrTagRange = { start: m.index, end: m.index + full.length };
|
|
@@ -22776,8 +23124,8 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
22776
23124
|
} else if (local === "cellSpan") {
|
|
22777
23125
|
const cell2 = cellStack[cellStack.length - 1];
|
|
22778
23126
|
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
22779
|
-
const cs = parseInt(
|
|
22780
|
-
const rs = parseInt(
|
|
23127
|
+
const cs = parseInt(getAttr3(attrsRaw, "colSpan") || "1", 10);
|
|
23128
|
+
const rs = parseInt(getAttr3(attrsRaw, "rowSpan") || "1", 10);
|
|
22781
23129
|
cell2.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
|
|
22782
23130
|
cell2.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
|
|
22783
23131
|
}
|
|
@@ -22806,7 +23154,7 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
22806
23154
|
if (cls.inTextbox) para2.inTextbox = true;
|
|
22807
23155
|
stack.push({ local, qname, contentStart });
|
|
22808
23156
|
paraStack.push(para2);
|
|
22809
|
-
if (para2.kind === "body" || para2.kind === "draw")
|
|
23157
|
+
if (para2.kind === "body" || para2.kind === "draw") bodyParagraphs2.push(para2);
|
|
22810
23158
|
else if (para2.kind === "cell") {
|
|
22811
23159
|
const cell2 = cellStack[cellStack.length - 1];
|
|
22812
23160
|
if (cell2) cell2.paragraphs.push(para2);
|
|
@@ -22841,14 +23189,14 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
22841
23189
|
const cell2 = cellStack[cellStack.length - 1];
|
|
22842
23190
|
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
22843
23191
|
if (local === "cellAddr") {
|
|
22844
|
-
const ca = parseInt(
|
|
22845
|
-
const ra = parseInt(
|
|
23192
|
+
const ca = parseInt(getAttr3(attrsRaw, "colAddr") || "", 10);
|
|
23193
|
+
const ra = parseInt(getAttr3(attrsRaw, "rowAddr") || "", 10);
|
|
22846
23194
|
if (!isNaN(ca)) cell2.colAddr = ca;
|
|
22847
23195
|
if (!isNaN(ra)) cell2.rowAddr = ra;
|
|
22848
23196
|
cell2.addrTagRange = { start: m.index, end: contentStart };
|
|
22849
23197
|
} else {
|
|
22850
|
-
const cs = parseInt(
|
|
22851
|
-
const rs = parseInt(
|
|
23198
|
+
const cs = parseInt(getAttr3(attrsRaw, "colSpan") || "1", 10);
|
|
23199
|
+
const rs = parseInt(getAttr3(attrsRaw, "rowSpan") || "1", 10);
|
|
22852
23200
|
cell2.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
|
|
22853
23201
|
cell2.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
|
|
22854
23202
|
}
|
|
@@ -22862,7 +23210,7 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
22862
23210
|
if (para2) para2.text += " ";
|
|
22863
23211
|
}
|
|
22864
23212
|
}
|
|
22865
|
-
for (const para2 of
|
|
23213
|
+
for (const para2 of bodyParagraphs2) fillRunInsertPos(para2, xml);
|
|
22866
23214
|
for (const para2 of excludedParagraphs) fillRunInsertPos(para2, xml);
|
|
22867
23215
|
const fillTableInsertPos = (table2, depth = 0) => {
|
|
22868
23216
|
if (depth > 16) return;
|
|
@@ -22875,9 +23223,9 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
22875
23223
|
};
|
|
22876
23224
|
for (const table2 of tables) fillTableInsertPos(table2);
|
|
22877
23225
|
for (const table2 of orphanTables) fillTableInsertPos(table2);
|
|
22878
|
-
return { sectionIndex, xml, bodyParagraphs, tables, headerTexts, footerTexts, excludedParagraphs, orphanTables };
|
|
23226
|
+
return { sectionIndex, xml, bodyParagraphs: bodyParagraphs2, tables, headerTexts, footerTexts, excludedParagraphs, orphanTables };
|
|
22879
23227
|
}
|
|
22880
|
-
function
|
|
23228
|
+
function getAttr3(attrsRaw, name) {
|
|
22881
23229
|
const re = new RegExp(`(?:^|\\s)${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)')`);
|
|
22882
23230
|
const m = attrsRaw.match(re);
|
|
22883
23231
|
return m ? m[1] ?? m[2] : void 0;
|
|
@@ -23201,7 +23549,7 @@ function fillClickHereInXml(xml, cursor, blockedLabels) {
|
|
|
23201
23549
|
}
|
|
23202
23550
|
async function extractClickHereFields(hwpxBuffer) {
|
|
23203
23551
|
precheckZipSize(hwpxBuffer);
|
|
23204
|
-
const zip = await
|
|
23552
|
+
const zip = await JSZip7.loadAsync(hwpxBuffer);
|
|
23205
23553
|
const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
|
|
23206
23554
|
const fields = [];
|
|
23207
23555
|
for (let si = 0; si < sectionPaths.length; si++) {
|
|
@@ -23430,7 +23778,7 @@ function patchZipEntries(original, replacements, additions) {
|
|
|
23430
23778
|
async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
23431
23779
|
const u8 = new Uint8Array(hwpxBuffer);
|
|
23432
23780
|
precheckZipSize(hwpxBuffer);
|
|
23433
|
-
const zip = await
|
|
23781
|
+
const zip = await JSZip8.loadAsync(hwpxBuffer);
|
|
23434
23782
|
const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
|
|
23435
23783
|
if (sectionPaths.length === 0) {
|
|
23436
23784
|
throw new KordocError("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
@@ -23889,7 +24237,7 @@ function chooseTableRepresentation(table2, opts = {}) {
|
|
|
23889
24237
|
}
|
|
23890
24238
|
|
|
23891
24239
|
// src/hwpx/generator.ts
|
|
23892
|
-
import
|
|
24240
|
+
import JSZip9 from "jszip";
|
|
23893
24241
|
|
|
23894
24242
|
// src/hwpx/font-metrics.ts
|
|
23895
24243
|
var FONTS = {
|
|
@@ -30140,7 +30488,8 @@ function renderListItem(block, blockIdx, ctx) {
|
|
|
30140
30488
|
ctx.prevWasOrdered = false;
|
|
30141
30489
|
}
|
|
30142
30490
|
const indentPrefix = " ".repeat(indent);
|
|
30143
|
-
|
|
30491
|
+
const markerRun = `<hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t>${escapeTextXml(indentPrefix + marker)}</hp:t></hp:run>`;
|
|
30492
|
+
return `<hp:p paraPrIDRef="${PARA_LIST}" styleIDRef="0">${markerRun}${generateRuns(block.text || "")}</hp:p>`;
|
|
30144
30493
|
}
|
|
30145
30494
|
function renderHr(ctx) {
|
|
30146
30495
|
return ctx.gongmun ? `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t></hp:t></hp:run></hp:p>` : `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0"><hp:t>\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500</hp:t></hp:run></hp:p>`;
|
|
@@ -31648,7 +31997,7 @@ async function markdownToHwpx(markdown, options) {
|
|
|
31648
31997
|
if (remap2 && remap2.tables.length > 0 && remap2.tables.every((t) => !t.used)) {
|
|
31649
31998
|
console.warn(`[kordoc] format profile: \uD504\uB85C\uD544 \uD45C ${remap2.tables.length}\uAC1C\uAC00 \uBB38\uC11C \uD45C\uC640 \uB9E4\uCE6D\uB418\uC9C0 \uC54A\uC544 \uBBF8\uC801\uC6A9 (\uD589\xB7\uC5F4/\uCCAB \uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58)`);
|
|
31650
31999
|
}
|
|
31651
|
-
const zip2 = new
|
|
32000
|
+
const zip2 = new JSZip9();
|
|
31652
32001
|
zip2.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
31653
32002
|
zip2.file("META-INF/container.xml", generateContainerXml());
|
|
31654
32003
|
zip2.file("Contents/content.hpf", generateManifest(chartParts2, images2.manifestItems(), "gongmun"));
|
|
@@ -31695,7 +32044,7 @@ async function markdownToHwpx(markdown, options) {
|
|
|
31695
32044
|
}
|
|
31696
32045
|
}
|
|
31697
32046
|
const extraBorderFills = [...remap?.borderFillXmls ?? [], ...bfReg?.emit() ?? []];
|
|
31698
|
-
const zip = new
|
|
32047
|
+
const zip = new JSZip9();
|
|
31699
32048
|
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
31700
32049
|
zip.file("META-INF/container.xml", generateContainerXml());
|
|
31701
32050
|
zip.file("Contents/content.hpf", generateManifest(chartParts, images.manifestItems(), gongmun ? "gongmun" : "default"));
|
|
@@ -31915,7 +32264,7 @@ function readBuiltinTemplateSample(t) {
|
|
|
31915
32264
|
}
|
|
31916
32265
|
|
|
31917
32266
|
// src/form/seal.ts
|
|
31918
|
-
import
|
|
32267
|
+
import JSZip10 from "jszip";
|
|
31919
32268
|
|
|
31920
32269
|
// src/render/head-styles.ts
|
|
31921
32270
|
var DEFAULT_PARA_GEOM = {
|
|
@@ -32261,7 +32610,7 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
32261
32610
|
if (ops.length === 0) throw new KordocError("place_seal: \uBC30\uCE58\uD560 \uB3C4\uC7A5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
32262
32611
|
const u8 = new Uint8Array(hwpxBuffer);
|
|
32263
32612
|
precheckZipSize(hwpxBuffer);
|
|
32264
|
-
const zip = await
|
|
32613
|
+
const zip = await JSZip10.loadAsync(hwpxBuffer);
|
|
32265
32614
|
const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort((a, b) => Number(a.match(/(\d+)\.xml$/i)?.[1] ?? 0) - Number(b.match(/(\d+)\.xml$/i)?.[1] ?? 0));
|
|
32266
32615
|
if (sectionPaths.length === 0) throw new KordocError("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
32267
32616
|
const manifestPath = Object.keys(zip.files).find((name) => /\.hpf$/i.test(name));
|
|
@@ -32425,7 +32774,7 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
32425
32774
|
}
|
|
32426
32775
|
|
|
32427
32776
|
// src/hwpx/extract-profile.ts
|
|
32428
|
-
import
|
|
32777
|
+
import JSZip11 from "jszip";
|
|
32429
32778
|
function elemsByLocal(root, name) {
|
|
32430
32779
|
const all = root.getElementsByTagName("*");
|
|
32431
32780
|
const out = [];
|
|
@@ -32512,7 +32861,7 @@ function num(s) {
|
|
|
32512
32861
|
const n = parseInt(s, 10);
|
|
32513
32862
|
return Number.isFinite(n) ? n : void 0;
|
|
32514
32863
|
}
|
|
32515
|
-
function
|
|
32864
|
+
function parseTable4(tbl2, tableIndex, borderFills, charPrs) {
|
|
32516
32865
|
const rows = num(tbl2.getAttribute("rowCnt")) ?? 0;
|
|
32517
32866
|
const cols = num(tbl2.getAttribute("colCnt")) ?? 0;
|
|
32518
32867
|
const sz = findChildByLocalName(tbl2, "sz");
|
|
@@ -32628,7 +32977,7 @@ function pick(map, keys) {
|
|
|
32628
32977
|
}
|
|
32629
32978
|
async function hwpxToProfile(input) {
|
|
32630
32979
|
const buf = input instanceof ArrayBuffer ? input : toArrayBuffer(input);
|
|
32631
|
-
const zip = await
|
|
32980
|
+
const zip = await JSZip11.loadAsync(buf);
|
|
32632
32981
|
const parser = createXmlParser();
|
|
32633
32982
|
const headerFile = zip.file("Contents/header.xml") ?? zip.file(/[Hh]eader\.xml$/)?.[0];
|
|
32634
32983
|
let headerXml = "<root/>";
|
|
@@ -32643,7 +32992,7 @@ async function hwpxToProfile(input) {
|
|
|
32643
32992
|
const doc = parser.parseFromString(await f.async("text"), "text/xml");
|
|
32644
32993
|
for (const tbl2 of elemsByLocal(doc, "tbl")) {
|
|
32645
32994
|
if (!isTopLevelTable(tbl2)) continue;
|
|
32646
|
-
tables.push(
|
|
32995
|
+
tables.push(parseTable4(tbl2, tableIndex++, borderFills, charPrs));
|
|
32647
32996
|
}
|
|
32648
32997
|
}
|
|
32649
32998
|
return { schema_version: "0.3.0", tables };
|
|
@@ -33345,7 +33694,7 @@ function muncheLintWarnings(text, limit = 10) {
|
|
|
33345
33694
|
}
|
|
33346
33695
|
|
|
33347
33696
|
// src/roundtrip/patcher.ts
|
|
33348
|
-
import
|
|
33697
|
+
import JSZip12 from "jszip";
|
|
33349
33698
|
|
|
33350
33699
|
// src/roundtrip/table-rows.ts
|
|
33351
33700
|
var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
|
|
@@ -35212,7 +35561,7 @@ async function patchHwpx(original, editedMarkdown, options) {
|
|
|
35212
35561
|
}
|
|
35213
35562
|
let zip;
|
|
35214
35563
|
try {
|
|
35215
|
-
zip = await
|
|
35564
|
+
zip = await JSZip12.loadAsync(original);
|
|
35216
35565
|
} catch {
|
|
35217
35566
|
return { success: false, applied: 0, skipped, error: "ZIP \uB85C\uB4DC \uC2E4\uD328" };
|
|
35218
35567
|
}
|
|
@@ -35657,8 +36006,8 @@ async function resolveHeaderEntryName(zip) {
|
|
|
35657
36006
|
}
|
|
35658
36007
|
|
|
35659
36008
|
// src/validate.ts
|
|
35660
|
-
import
|
|
35661
|
-
import { DOMParser as
|
|
36009
|
+
import JSZip13 from "jszip";
|
|
36010
|
+
import { DOMParser as DOMParser6 } from "@xmldom/xmldom";
|
|
35662
36011
|
var REQUIRED_FILES = [
|
|
35663
36012
|
"mimetype",
|
|
35664
36013
|
"META-INF/container.xml",
|
|
@@ -35675,7 +36024,7 @@ async function validateHwpx(buffer) {
|
|
|
35675
36024
|
const issues = [];
|
|
35676
36025
|
let zip;
|
|
35677
36026
|
try {
|
|
35678
|
-
zip = await
|
|
36027
|
+
zip = await JSZip13.loadAsync(buffer);
|
|
35679
36028
|
} catch (err) {
|
|
35680
36029
|
return {
|
|
35681
36030
|
ok: false,
|
|
@@ -35704,7 +36053,7 @@ async function validateHwpx(buffer) {
|
|
|
35704
36053
|
const text = await zip.files[name].async("string");
|
|
35705
36054
|
let firstError = null;
|
|
35706
36055
|
try {
|
|
35707
|
-
new
|
|
36056
|
+
new DOMParser6({
|
|
35708
36057
|
onError(level, msg2) {
|
|
35709
36058
|
if (level !== "warning" && firstError === null) firstError = String(msg2);
|
|
35710
36059
|
}
|
|
@@ -38211,12 +38560,12 @@ function blocksToChunks(blocks, options) {
|
|
|
38211
38560
|
}
|
|
38212
38561
|
|
|
38213
38562
|
// src/roundtrip/session.ts
|
|
38214
|
-
import
|
|
38563
|
+
import JSZip14 from "jszip";
|
|
38215
38564
|
async function buildState(bytes) {
|
|
38216
38565
|
const format2 = detectFormat(new Uint8Array(bytes.subarray(0, 512)).buffer);
|
|
38217
38566
|
if (format2 !== "hwpx") throw new Error(`HWPX \uC138\uC158\uC740 HWPX \uBB38\uC11C\uB9CC \uC5FD\uB2C8\uB2E4 (\uAC10\uC9C0\uB41C \uD3EC\uB9F7: ${format2}) \u2014 HWP 5.x \uB294 patchHwp \uB85C \uD328\uCE58\uD558\uC138\uC694`);
|
|
38218
38567
|
const parsed = await parseHwpxDocument(u8ToArrayBuffer2(bytes), { layoutTables: "keep" });
|
|
38219
|
-
const zip = await
|
|
38568
|
+
const zip = await JSZip14.loadAsync(bytes);
|
|
38220
38569
|
const sectionPaths = await resolveSectionEntryNames(zip);
|
|
38221
38570
|
if (sectionPaths.length === 0) {
|
|
38222
38571
|
throw new Error("HWPX \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
@@ -38737,7 +39086,7 @@ async function blocksToPdf(blocks, options) {
|
|
|
38737
39086
|
}
|
|
38738
39087
|
|
|
38739
39088
|
// src/render/svg-render.ts
|
|
38740
|
-
import
|
|
39089
|
+
import JSZip15 from "jszip";
|
|
38741
39090
|
|
|
38742
39091
|
// src/render/layout.ts
|
|
38743
39092
|
function toInt32(v, fallback = 0) {
|
|
@@ -39343,22 +39692,48 @@ function rotatedBounds(box, rotations) {
|
|
|
39343
39692
|
if (!rotations.length) return box;
|
|
39344
39693
|
let points = [[box.x, box.y], [box.x + box.w, box.y], [box.x + box.w, box.y + box.h], [box.x, box.y + box.h]];
|
|
39345
39694
|
for (let i = rotations.length - 1; i >= 0; i--) {
|
|
39346
|
-
const
|
|
39695
|
+
const r = rotations[i];
|
|
39696
|
+
if (Array.isArray(r)) {
|
|
39697
|
+
points = points.map(([x2, y2]) => [r[0] * x2 + r[2] * y2 + r[4], r[1] * x2 + r[3] * y2 + r[5]]);
|
|
39698
|
+
continue;
|
|
39699
|
+
}
|
|
39700
|
+
const { angle, cx, cy } = r;
|
|
39347
39701
|
const a = angle * Math.PI / 180, c = Math.cos(a), s = Math.sin(a);
|
|
39348
39702
|
points = points.map(([x2, y2]) => [cx + c * (x2 - cx) - s * (y2 - cy), cy + s * (x2 - cx) + c * (y2 - cy)]);
|
|
39349
39703
|
}
|
|
39350
39704
|
const x = Math.min(...points.map((p) => p[0])), y = Math.min(...points.map((p) => p[1]));
|
|
39351
39705
|
return { x, y, w: Math.max(...points.map((p) => p[0])) - x, h: Math.max(...points.map((p) => p[1])) - y };
|
|
39352
39706
|
}
|
|
39353
|
-
function
|
|
39707
|
+
function mulAffine(m, n) {
|
|
39708
|
+
return [
|
|
39709
|
+
m[0] * n[0] + m[2] * n[1],
|
|
39710
|
+
m[1] * n[0] + m[3] * n[1],
|
|
39711
|
+
m[0] * n[2] + m[2] * n[3],
|
|
39712
|
+
m[1] * n[2] + m[3] * n[3],
|
|
39713
|
+
m[0] * n[4] + m[2] * n[5] + m[4],
|
|
39714
|
+
m[1] * n[4] + m[3] * n[5] + m[5]
|
|
39715
|
+
];
|
|
39716
|
+
}
|
|
39717
|
+
function renderingMatrix(el) {
|
|
39718
|
+
const info = findChildByLocalName(el, "renderingInfo");
|
|
39719
|
+
if (!info) return null;
|
|
39720
|
+
let m = null;
|
|
39721
|
+
for (const c of elements(info)) {
|
|
39722
|
+
const tag = ln(c);
|
|
39723
|
+
if (tag !== "transMatrix" && tag !== "scaMatrix" && tag !== "rotMatrix") continue;
|
|
39724
|
+
const n = [num2(c, "e1", 1), num2(c, "e4"), num2(c, "e2"), num2(c, "e5", 1), num2(c, "e3"), num2(c, "e6")];
|
|
39725
|
+
m = m ? mulAffine(m, n) : n;
|
|
39726
|
+
}
|
|
39727
|
+
return m;
|
|
39728
|
+
}
|
|
39729
|
+
function objectGeometry(el, x, y, w, h, boxW = w, boxH = h) {
|
|
39354
39730
|
const rot = findChildByLocalName(el, "rotationInfo");
|
|
39355
39731
|
const angle = num2(rot, "angle") % 360;
|
|
39356
39732
|
if (!angle) return { x, y, w, h, bbox: { x, y, w, h }, transform: "" };
|
|
39357
|
-
const
|
|
39358
|
-
const
|
|
39359
|
-
const cy = y + num2(rot, "centerY", num2(org, "height", h) / 2) * (h / (num2(org, "height") || h || 1));
|
|
39733
|
+
const cx = x + boxW / 2, cy = y + boxH / 2;
|
|
39734
|
+
const fx = cx - w / 2, fy = cy - h / 2;
|
|
39360
39735
|
const rotation = { angle, cx: Math.round(cx), cy: Math.round(cy) };
|
|
39361
|
-
return { x, y, w, h, bbox: rotatedBounds({ x, y, w, h }, [rotation]), rotation, transform: `rotate(${angle} ${pt(cx)} ${pt(cy)})` };
|
|
39736
|
+
return { x: fx, y: fy, w, h, bbox: rotatedBounds({ x: fx, y: fy, w, h }, [rotation]), rotation, transform: `rotate(${angle} ${pt(cx)} ${pt(cy)})` };
|
|
39362
39737
|
}
|
|
39363
39738
|
function shapeFill(el, defs, images, warn) {
|
|
39364
39739
|
const brush = findChildByLocalName(el, "fillBrush");
|
|
@@ -39406,10 +39781,13 @@ function shapeFill(el, defs, images, warn) {
|
|
|
39406
39781
|
}
|
|
39407
39782
|
return "none";
|
|
39408
39783
|
}
|
|
39409
|
-
function shapeGeometry(o,
|
|
39784
|
+
function shapeGeometry(o, boxX, boxY, defs, images, warn, local = false) {
|
|
39410
39785
|
const el = o.el, org = findChildByLocalName(el, "orgSz"), cur = findChildByLocalName(el, "curSz");
|
|
39411
39786
|
const ow = num2(org, "width"), oh = num2(org, "height");
|
|
39412
|
-
const w = num2(cur, "width") || ow ||
|
|
39787
|
+
const w = (local ? ow : num2(cur, "width")) || ow || num2(cur, "width") || o.width;
|
|
39788
|
+
const h = (local ? oh : num2(cur, "height")) || oh || num2(cur, "height") || o.height;
|
|
39789
|
+
const geometry = local ? { x: boxX, y: boxY, w, h, bbox: { x: boxX, y: boxY, w, h }, transform: "" } : objectGeometry(el, boxX, boxY, w, h, o.width || w, o.height || h);
|
|
39790
|
+
const { x, y } = geometry;
|
|
39413
39791
|
const sx = ow > 0 ? w / ow : 1, sy = oh > 0 ? h / oh : 1;
|
|
39414
39792
|
const line = findChildByLocalName(el, "lineShape"), style = line?.getAttribute("style") ?? "SOLID";
|
|
39415
39793
|
const color = esc(line?.getAttribute("color") || "#000000");
|
|
@@ -39428,8 +39806,7 @@ function shapeGeometry(o, x, y, defs, images, warn) {
|
|
|
39428
39806
|
if (pts.length >= 2) svg = `<polygon points="${pts.join(" ")}"${fill}${stroke}/>`;
|
|
39429
39807
|
} else if (o.tag === "curve") {
|
|
39430
39808
|
const segs = elements(el).filter((c) => ln(c) === "seg");
|
|
39431
|
-
if (segs.
|
|
39432
|
-
else if (segs.length) {
|
|
39809
|
+
if (segs.length) {
|
|
39433
39810
|
let path = "", lastX, lastY;
|
|
39434
39811
|
for (const s of segs) {
|
|
39435
39812
|
const x1 = num2(s, "x1"), y1 = num2(s, "y1"), x2 = num2(s, "x2"), y2 = num2(s, "y2");
|
|
@@ -39441,7 +39818,7 @@ function shapeGeometry(o, x, y, defs, images, warn) {
|
|
|
39441
39818
|
svg = `<path d="${path}"${fill}${stroke}/>`;
|
|
39442
39819
|
}
|
|
39443
39820
|
} else if (o.tag === "arc") svg = `<ellipse cx="${pt(x + w / 2)}" cy="${pt(y + h / 2)}" rx="${pt(w / 2)}" ry="${pt(h / 2)}" fill="none"${stroke || ` stroke="${color}" stroke-width="0.3"`}/>`;
|
|
39444
|
-
return { ...
|
|
39821
|
+
return { ...geometry, svg };
|
|
39445
39822
|
}
|
|
39446
39823
|
|
|
39447
39824
|
// src/render/svg-render.ts
|
|
@@ -39735,6 +40112,7 @@ function drawObject(o, x, y, baseV, areaW, ctx, depth) {
|
|
|
39735
40112
|
if (o.tag === "tbl") drawTable(o.el, x, y, ctx, depth + 1);
|
|
39736
40113
|
else if (o.tag === "pic") drawPic(o.el, x, y, ctx);
|
|
39737
40114
|
else if (o.tag === "container") {
|
|
40115
|
+
if (drawGroupByMatrix(o, x, y, baseV, areaW, ctx, depth)) return;
|
|
39738
40116
|
for (const ch of elements(o.el)) {
|
|
39739
40117
|
const tag = ln(ch);
|
|
39740
40118
|
if (!OBJ_TAGS.has(tag)) continue;
|
|
@@ -39751,8 +40129,42 @@ function drawObject(o, x, y, baseV, areaW, ctx, depth) {
|
|
|
39751
40129
|
warnOnce(ctx, `shape:${o.tag}`, `\uAC1C\uCCB4(${o.tag}) \uB80C\uB354 \uBBF8\uC9C0\uC6D0 \u2014 \uC0DD\uB7B5`);
|
|
39752
40130
|
}
|
|
39753
40131
|
}
|
|
39754
|
-
function
|
|
39755
|
-
const
|
|
40132
|
+
function drawGroupByMatrix(o, x, y, baseV, areaW, ctx, depth) {
|
|
40133
|
+
const top = renderingMatrix(o.el);
|
|
40134
|
+
const leaves = [];
|
|
40135
|
+
const collect = (el) => {
|
|
40136
|
+
for (const ch of elements(el)) {
|
|
40137
|
+
const tag = ln(ch);
|
|
40138
|
+
if (!OBJ_TAGS.has(tag)) continue;
|
|
40139
|
+
if (tag === "container") {
|
|
40140
|
+
if (!collect(ch)) return false;
|
|
40141
|
+
} else if (renderingMatrix(ch)) leaves.push(ch);
|
|
40142
|
+
else return false;
|
|
40143
|
+
}
|
|
40144
|
+
return true;
|
|
40145
|
+
};
|
|
40146
|
+
if (!top || !collect(o.el)) return false;
|
|
40147
|
+
const org = findChildByLocalName(o.el, "orgSz");
|
|
40148
|
+
const box = rotatedBounds({ x: 0, y: 0, w: num2(org, "width"), h: num2(org, "height") }, [top]);
|
|
40149
|
+
const base = [1, 0, 0, 1, x - box.x, y - box.y];
|
|
40150
|
+
for (const leaf of leaves) {
|
|
40151
|
+
const m = mulAffine(base, renderingMatrix(leaf));
|
|
40152
|
+
const tag = ln(leaf), lorg = findChildByLocalName(leaf, "orgSz");
|
|
40153
|
+
const w = num2(lorg, "width") || num2(findChildByLocalName(leaf, "curSz"), "width");
|
|
40154
|
+
const h = num2(lorg, "height") || num2(findChildByLocalName(leaf, "curSz"), "height");
|
|
40155
|
+
ctx.regionRotations.push(m);
|
|
40156
|
+
emit(ctx, `<g transform="matrix(${m.slice(0, 4).map((v) => Math.round(v * 1e6) / 1e6).join(" ")} ${pt2(m[4])} ${pt2(m[5])})">`);
|
|
40157
|
+
const sub = { el: leaf, tag, index: 0, inline: true, width: w, height: h, omL: 0, omR: 0 };
|
|
40158
|
+
if (tag === "pic") drawPicFrame(leaf, 0, 0, w, h, "", ctx);
|
|
40159
|
+
else if (SHAPE_TAGS.has(tag)) drawShape(sub, 0, 0, ctx, depth + 1, true);
|
|
40160
|
+
else drawObject(sub, 0, 0, baseV, areaW, ctx, depth + 1);
|
|
40161
|
+
emit(ctx, "</g>");
|
|
40162
|
+
ctx.regionRotations.pop();
|
|
40163
|
+
}
|
|
40164
|
+
return true;
|
|
40165
|
+
}
|
|
40166
|
+
function drawShape(o, x, y, ctx, depth, local = false) {
|
|
40167
|
+
const geometry = shapeGeometry(o, x, y, ctx.defs, ctx.images, (key, msg2) => warnOnce(ctx, key, msg2), local);
|
|
39756
40168
|
const b = geometry;
|
|
39757
40169
|
if (geometry.rotation) ctx.regionRotations.push(geometry.rotation);
|
|
39758
40170
|
ctx.stats.shapes++;
|
|
@@ -39846,16 +40258,31 @@ function imageSymbol(loaded, ctx) {
|
|
|
39846
40258
|
}
|
|
39847
40259
|
function drawPic(pic, x, y, ctx) {
|
|
39848
40260
|
const sz = findChildByLocalName(pic, "sz");
|
|
39849
|
-
|
|
40261
|
+
let w = num2(sz, "width", 5669), h = num2(sz, "height", 5669);
|
|
40262
|
+
const cur = findChildByLocalName(pic, "curSz");
|
|
40263
|
+
const rotated = objectGeometry(pic, x, y, num2(cur, "width") || w, num2(cur, "height") || h, w, h);
|
|
40264
|
+
if (rotated.rotation) {
|
|
40265
|
+
x = rotated.x;
|
|
40266
|
+
y = rotated.y;
|
|
40267
|
+
w = rotated.w;
|
|
40268
|
+
h = rotated.h;
|
|
40269
|
+
ctx.regionRotations.push(rotated.rotation);
|
|
40270
|
+
}
|
|
40271
|
+
drawPicFrame(pic, x, y, w, h, rotated.transform, ctx);
|
|
40272
|
+
if (rotated.rotation) ctx.regionRotations.pop();
|
|
40273
|
+
}
|
|
40274
|
+
function drawPicFrame(pic, x, y, w, h, transform, ctx) {
|
|
39850
40275
|
const img = findFirst(pic, "img");
|
|
39851
40276
|
const ref = img?.getAttribute("binaryItemIDRef");
|
|
39852
40277
|
const loaded = ref != null ? ctx.images.get(ref) : void 0;
|
|
39853
40278
|
const imgId = ctx.regions.add("image", bboxOf(ctx, x, y, w, h), { sourceId: ref ?? void 0, parentId: parentId(ctx) });
|
|
39854
40279
|
emit(ctx, regionOpenTag(imgId, "image", pageNo(ctx)));
|
|
40280
|
+
const close = transform ? "</g></g>" : "</g>";
|
|
40281
|
+
if (transform) emit(ctx, `<g transform="${transform}">`);
|
|
39855
40282
|
if (!loaded) {
|
|
39856
40283
|
emit(ctx, `<rect x="${pt2(x)}" y="${pt2(y)}" width="${pt2(w)}" height="${pt2(h)}" fill="#eee" stroke="#c00" stroke-width="0.5"/>`);
|
|
39857
40284
|
warnOnce(ctx, `img:${ref}`, `\uC774\uBBF8\uC9C0 \uBC14\uC774\uB108\uB9AC \uB204\uB77D: ${ref ?? "(ref \uC5C6\uC74C)"}`);
|
|
39858
|
-
emit(ctx,
|
|
40285
|
+
emit(ctx, close);
|
|
39859
40286
|
return;
|
|
39860
40287
|
}
|
|
39861
40288
|
ctx.stats.images++;
|
|
@@ -39877,7 +40304,7 @@ function drawPic(pic, x, y, ctx) {
|
|
|
39877
40304
|
} else {
|
|
39878
40305
|
emit(ctx, `<use href="#${symId}" x="${pt2(x)}" y="${pt2(y)}" width="${pt2(w)}" height="${pt2(h)}"/>`);
|
|
39879
40306
|
}
|
|
39880
|
-
emit(ctx,
|
|
40307
|
+
emit(ctx, close);
|
|
39881
40308
|
}
|
|
39882
40309
|
function sniffMime(name, bytes) {
|
|
39883
40310
|
const lower = name.toLowerCase();
|
|
@@ -40005,7 +40432,7 @@ async function renderHwpxInternal(input, options) {
|
|
|
40005
40432
|
precheckZipSize(ab, MAX_DECOMPRESS_SIZE, MAX_ZIP_ENTRIES);
|
|
40006
40433
|
let zip;
|
|
40007
40434
|
try {
|
|
40008
|
-
zip = await
|
|
40435
|
+
zip = await JSZip15.loadAsync(input);
|
|
40009
40436
|
} catch {
|
|
40010
40437
|
throw new KordocError("HWPX(ZIP) \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4 \u2014 \uB80C\uB354\uB294 HWPX\uB9CC \uC9C0\uC6D0");
|
|
40011
40438
|
}
|
|
@@ -41060,9 +41487,7 @@ async function dispatch(format2, buffer, opts) {
|
|
|
41060
41487
|
const zipFormat = await detectZipFormat(buffer);
|
|
41061
41488
|
if (zipFormat === "xlsx") return parseXlsx(buffer, opts);
|
|
41062
41489
|
if (zipFormat === "docx") return parseDocx(buffer, opts);
|
|
41063
|
-
if (zipFormat === "pptx")
|
|
41064
|
-
return { success: false, fileType: "pptx", error: "PPTX \uD30C\uC77C\uC740 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD\uC785\uB2C8\uB2E4.", code: "UNSUPPORTED_FORMAT" };
|
|
41065
|
-
}
|
|
41490
|
+
if (zipFormat === "pptx") return parsePptx(buffer, opts);
|
|
41066
41491
|
return parseHwpx(buffer, opts);
|
|
41067
41492
|
}
|
|
41068
41493
|
case "hwp": {
|
|
@@ -41087,7 +41512,7 @@ function scriptsOff(r, off) {
|
|
|
41087
41512
|
}
|
|
41088
41513
|
async function parseImage(buffer, options) {
|
|
41089
41514
|
try {
|
|
41090
|
-
const { parseImageDocument } = await import("./image-ocr-
|
|
41515
|
+
const { parseImageDocument } = await import("./image-ocr-IMYXOHHV.js");
|
|
41091
41516
|
const { blocks, warnings } = await parseImageDocument(buffer, options);
|
|
41092
41517
|
stripScriptTags({ blocks });
|
|
41093
41518
|
return {
|
|
@@ -41147,7 +41572,7 @@ async function parseHwp(buffer, options) {
|
|
|
41147
41572
|
async function parsePdf(buffer, options) {
|
|
41148
41573
|
let parsePdfDocument;
|
|
41149
41574
|
try {
|
|
41150
|
-
const mod = await import("./parser-
|
|
41575
|
+
const mod = await import("./parser-M3T2EWUN.js");
|
|
41151
41576
|
parsePdfDocument = mod.parsePdfDocument;
|
|
41152
41577
|
} catch {
|
|
41153
41578
|
return {
|
|
@@ -41189,6 +41614,14 @@ async function parseDocx(buffer, options) {
|
|
|
41189
41614
|
return { success: false, fileType: "docx", error: sanitizeError(err), code: classifyError(err) };
|
|
41190
41615
|
}
|
|
41191
41616
|
}
|
|
41617
|
+
async function parsePptx(buffer, options) {
|
|
41618
|
+
try {
|
|
41619
|
+
const { markdown, blocks, metadata, outline, warnings, images } = await parsePptxDocument(buffer, options);
|
|
41620
|
+
return { success: true, fileType: "pptx", markdown, blocks, metadata, outline, warnings, images: images?.length ? images : void 0, pageCount: metadata?.pageCount };
|
|
41621
|
+
} catch (err) {
|
|
41622
|
+
return { success: false, fileType: "pptx", error: sanitizeError(err), code: classifyError(err) };
|
|
41623
|
+
}
|
|
41624
|
+
}
|
|
41192
41625
|
async function parseHwpml(buffer, options) {
|
|
41193
41626
|
try {
|
|
41194
41627
|
const { markdown, blocks, metadata, outline, warnings } = parseHwpmlDocument(buffer, options);
|
|
@@ -41301,6 +41734,7 @@ export {
|
|
|
41301
41734
|
parseHwpx,
|
|
41302
41735
|
parseImage,
|
|
41303
41736
|
parsePdf,
|
|
41737
|
+
parsePptx,
|
|
41304
41738
|
parseXls,
|
|
41305
41739
|
parseXlsx,
|
|
41306
41740
|
patchHwp,
|