kordoc 3.15.0 → 3.16.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 +20 -0
- package/dist/{-EYPKRLMN.js → -YVONYEEN.js} +17 -12
- package/dist/chunk-7WUTJXKP.js +1048 -0
- package/dist/chunk-7WUTJXKP.js.map +1 -0
- package/dist/{chunk-734GJLXH.js → chunk-CDFCA37S.js} +15 -177
- package/dist/chunk-CDFCA37S.js.map +1 -0
- package/dist/{chunk-Q5ZPWQID.js → chunk-F62GOZFB.js} +13 -6
- package/dist/chunk-F62GOZFB.js.map +1 -0
- package/dist/{chunk-Q3IHI3E6.js → chunk-I6T3DKYK.js} +371 -756
- package/dist/chunk-I6T3DKYK.js.map +1 -0
- package/dist/chunk-IY3NX4FT.js +185 -0
- package/dist/chunk-IY3NX4FT.js.map +1 -0
- package/dist/{chunk-SCFFABCT.js → chunk-K4L563FA.js} +2 -2
- package/dist/{chunk-ZRNYYEE6.js → chunk-QOPY6URE.js} +13 -6
- package/dist/chunk-QOPY6URE.js.map +1 -0
- package/dist/{chunk-DMBTOJK4.cjs → chunk-VNIQK4AL.cjs} +13 -6
- package/dist/chunk-VNIQK4AL.cjs.map +1 -0
- package/dist/cli.js +105 -14
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1020 -384
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -4
- package/dist/index.d.ts +76 -4
- package/dist/index.js +817 -181
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +80 -13
- package/dist/mcp.js.map +1 -1
- package/dist/{parser-O2SD4DFR.cjs → parser-3O2UF6VO.cjs} +35 -22
- package/dist/parser-3O2UF6VO.cjs.map +1 -0
- package/dist/{parser-76JSTEP3.js → parser-B4O7CW5Q.js} +24 -11
- package/dist/parser-B4O7CW5Q.js.map +1 -0
- package/dist/{parser-SNBQZO5E.js → parser-BNEAMKUF.js} +23 -10
- package/dist/parser-BNEAMKUF.js.map +1 -0
- package/dist/render-QCNMRR7L.js +10 -0
- package/dist/seal-REDSMUI5.js +10 -0
- package/dist/seal-REDSMUI5.js.map +1 -0
- package/dist/{watch-LEK5U5P6.js → watch-RLF5F3TN.js} +7 -5
- package/dist/{watch-LEK5U5P6.js.map → watch-RLF5F3TN.js.map} +1 -1
- package/package.json +2 -5
- package/dist/chunk-734GJLXH.js.map +0 -1
- package/dist/chunk-DMBTOJK4.cjs.map +0 -1
- package/dist/chunk-Q3IHI3E6.js.map +0 -1
- package/dist/chunk-Q5ZPWQID.js.map +0 -1
- package/dist/chunk-ZRNYYEE6.js.map +0 -1
- package/dist/parser-76JSTEP3.js.map +0 -1
- package/dist/parser-O2SD4DFR.cjs.map +0 -1
- package/dist/parser-SNBQZO5E.js.map +0 -1
- package/dist/render-LDI3LO2P.js +0 -9
- /package/dist/{-EYPKRLMN.js.map → -YVONYEEN.js.map} +0 -0
- /package/dist/{chunk-SCFFABCT.js.map → chunk-K4L563FA.js.map} +0 -0
- /package/dist/{render-LDI3LO2P.js.map → render-QCNMRR7L.js.map} +0 -0
|
@@ -1,39 +1,53 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
HEADING_RATIO_H1,
|
|
4
|
+
HEADING_RATIO_H2,
|
|
5
|
+
HEADING_RATIO_H3,
|
|
6
|
+
MAX_COLS,
|
|
7
|
+
MAX_ROWS,
|
|
8
|
+
blocksToMarkdown,
|
|
9
|
+
buildTable,
|
|
10
|
+
convertTableToText,
|
|
11
|
+
flattenLayoutTables,
|
|
12
|
+
mapPuaText
|
|
13
|
+
} from "./chunk-F62GOZFB.js";
|
|
2
14
|
import {
|
|
3
15
|
detectFormat,
|
|
4
16
|
detectOle2Format,
|
|
5
17
|
detectZipFormat,
|
|
6
18
|
parseLenientCfb
|
|
7
19
|
} from "./chunk-MEPHGCPQ.js";
|
|
20
|
+
import {
|
|
21
|
+
parsePageRange
|
|
22
|
+
} from "./chunk-MOL7MDBG.js";
|
|
23
|
+
import {
|
|
24
|
+
allLinesegRemovalSplices,
|
|
25
|
+
applySplices,
|
|
26
|
+
buildParagraphSplices,
|
|
27
|
+
buildRangeSplices,
|
|
28
|
+
escapeXmlText,
|
|
29
|
+
findElementEnd,
|
|
30
|
+
paraTText,
|
|
31
|
+
paraTextPureT,
|
|
32
|
+
patchZipEntries,
|
|
33
|
+
scanSectionXml
|
|
34
|
+
} from "./chunk-7WUTJXKP.js";
|
|
35
|
+
import {
|
|
36
|
+
SPACE_EM_FIXED,
|
|
37
|
+
charWidthEm1000,
|
|
38
|
+
fitRatioForFewerLines
|
|
39
|
+
} from "./chunk-CDFCA37S.js";
|
|
8
40
|
import {
|
|
9
41
|
MAX_DECOMPRESS_SIZE,
|
|
10
42
|
MAX_XML_DEPTH,
|
|
11
43
|
MAX_ZIP_ENTRIES,
|
|
12
|
-
SPACE_EM_FIXED,
|
|
13
44
|
applyPageText,
|
|
14
|
-
charWidthEm1000,
|
|
15
45
|
clampSpan,
|
|
16
46
|
createSectionShared,
|
|
17
47
|
createXmlParser,
|
|
18
48
|
extractTextFromNode,
|
|
19
|
-
findChildByLocalName
|
|
20
|
-
|
|
21
|
-
} from "./chunk-734GJLXH.js";
|
|
22
|
-
import {
|
|
23
|
-
HEADING_RATIO_H1,
|
|
24
|
-
HEADING_RATIO_H2,
|
|
25
|
-
HEADING_RATIO_H3,
|
|
26
|
-
MAX_COLS,
|
|
27
|
-
MAX_ROWS,
|
|
28
|
-
blocksToMarkdown,
|
|
29
|
-
buildTable,
|
|
30
|
-
convertTableToText,
|
|
31
|
-
flattenLayoutTables,
|
|
32
|
-
mapPuaText
|
|
33
|
-
} from "./chunk-Q5ZPWQID.js";
|
|
34
|
-
import {
|
|
35
|
-
parsePageRange
|
|
36
|
-
} from "./chunk-MOL7MDBG.js";
|
|
49
|
+
findChildByLocalName
|
|
50
|
+
} from "./chunk-IY3NX4FT.js";
|
|
37
51
|
import {
|
|
38
52
|
KordocError,
|
|
39
53
|
classifyError,
|
|
@@ -44,7 +58,7 @@ import {
|
|
|
44
58
|
sanitizeHref,
|
|
45
59
|
stripDtd,
|
|
46
60
|
toArrayBuffer
|
|
47
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-K4L563FA.js";
|
|
48
62
|
|
|
49
63
|
// src/index.ts
|
|
50
64
|
import { readFile } from "fs/promises";
|
|
@@ -646,8 +660,8 @@ function maskLiteralSpans(eqString) {
|
|
|
646
660
|
function findKeywordToken(eqString, word, from = 0) {
|
|
647
661
|
const masked = maskLiteralSpans(eqString);
|
|
648
662
|
for (let i = masked.indexOf(word, from); i !== -1; i = masked.indexOf(word, i + 1)) {
|
|
649
|
-
const okL = i === 0 || masked[i - 1]
|
|
650
|
-
const okR = i + word.length === masked.length || masked[i + word.length]
|
|
663
|
+
const okL = i === 0 || /\s/.test(masked[i - 1]);
|
|
664
|
+
const okR = i + word.length === masked.length || /\s/.test(masked[i + word.length]);
|
|
651
665
|
if (okL && okR) return i;
|
|
652
666
|
}
|
|
653
667
|
return -1;
|
|
@@ -658,11 +672,22 @@ function replaceFrac(eqString) {
|
|
|
658
672
|
const cursor = findKeywordToken(eqString, hmlFrac);
|
|
659
673
|
if (cursor === -1) break;
|
|
660
674
|
try {
|
|
661
|
-
|
|
662
|
-
|
|
675
|
+
let end = cursor;
|
|
676
|
+
while (end > 0 && /\s/.test(eqString[end - 1])) end--;
|
|
677
|
+
let numStart, numEnd, wrapped;
|
|
678
|
+
if (end > 0 && eqString[end - 1] === "}") {
|
|
679
|
+
[numStart, numEnd] = findBrackets(eqString, end - 1, 0);
|
|
680
|
+
wrapped = eqString.slice(numStart, numEnd);
|
|
681
|
+
} else {
|
|
682
|
+
numEnd = end;
|
|
683
|
+
numStart = end;
|
|
684
|
+
while (numStart > 0 && !/\s/.test(eqString[numStart - 1])) numStart--;
|
|
685
|
+
if (numStart === numEnd) throw new Error("empty numerator");
|
|
686
|
+
wrapped = "{" + eqString.slice(numStart, numEnd) + "}";
|
|
687
|
+
}
|
|
663
688
|
const beforeFrac = eqString.slice(0, numStart);
|
|
664
689
|
const afterFrac = eqString.slice(cursor + hmlFrac.length);
|
|
665
|
-
eqString = beforeFrac + "\\frac" +
|
|
690
|
+
eqString = beforeFrac + "\\frac" + wrapped + afterFrac;
|
|
666
691
|
} catch {
|
|
667
692
|
return eqString;
|
|
668
693
|
}
|
|
@@ -18095,7 +18120,7 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18095
18120
|
if (trPrEls.length > 0) {
|
|
18096
18121
|
const gridBeforeEls = getChildElements(trPrEls[0], "gridBefore");
|
|
18097
18122
|
if (gridBeforeEls.length > 0) {
|
|
18098
|
-
col = parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0;
|
|
18123
|
+
col = Math.max(0, parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0);
|
|
18099
18124
|
}
|
|
18100
18125
|
}
|
|
18101
18126
|
for (const tc of getChildElements(tr, "tc")) {
|
|
@@ -18624,34 +18649,47 @@ function countSections(body) {
|
|
|
18624
18649
|
|
|
18625
18650
|
// src/form/match.ts
|
|
18626
18651
|
function parseYMD(v) {
|
|
18627
|
-
const d = v.replace(/\D/g, "");
|
|
18628
18652
|
let y, m, day;
|
|
18629
|
-
|
|
18630
|
-
|
|
18631
|
-
|
|
18632
|
-
|
|
18633
|
-
|
|
18634
|
-
|
|
18635
|
-
|
|
18636
|
-
|
|
18637
|
-
|
|
18638
|
-
|
|
18653
|
+
const parts = v.split(/[^0-9]+/).filter(Boolean);
|
|
18654
|
+
if (parts.length === 3) {
|
|
18655
|
+
const [yp, mp, dp] = parts;
|
|
18656
|
+
const yn = +yp;
|
|
18657
|
+
y = yp.length >= 3 ? yp : String(yn <= 29 ? 2e3 + yn : 1900 + yn);
|
|
18658
|
+
m = mp.padStart(2, "0");
|
|
18659
|
+
day = dp.padStart(2, "0");
|
|
18660
|
+
} else {
|
|
18661
|
+
const d = v.replace(/\D/g, "");
|
|
18662
|
+
if (d.length >= 8) {
|
|
18663
|
+
y = d.slice(0, 4);
|
|
18664
|
+
m = d.slice(4, 6);
|
|
18665
|
+
day = d.slice(6, 8);
|
|
18666
|
+
} else if (d.length === 6) {
|
|
18667
|
+
const yy = +d.slice(0, 2);
|
|
18668
|
+
y = String(yy <= 29 ? 2e3 + yy : 1900 + yy);
|
|
18669
|
+
m = d.slice(2, 4);
|
|
18670
|
+
day = d.slice(4, 6);
|
|
18671
|
+
} else return null;
|
|
18672
|
+
}
|
|
18673
|
+
if (+m < 1 || +m > 12 || +day < 1 || +day > 31) return null;
|
|
18639
18674
|
return { y, yy: y.slice(2), m, d: day };
|
|
18640
18675
|
}
|
|
18641
18676
|
function fmtDate(v, style) {
|
|
18642
18677
|
const p = parseYMD(v);
|
|
18643
18678
|
if (!p) return v;
|
|
18644
|
-
return (style || "yyyy-mm-dd").replace(/yyyy/
|
|
18679
|
+
return (style || "yyyy-mm-dd").replace(/yyyy/gi, p.y).replace(/yy/gi, p.yy).replace(/mm/gi, p.m).replace(/dd/gi, p.d).replace(/(?<![a-z])m(?![a-z])/gi, String(+p.m)).replace(/(?<![a-z])d(?![a-z])/gi, String(+p.d));
|
|
18645
18680
|
}
|
|
18646
18681
|
function maskDigits(v, pattern) {
|
|
18647
18682
|
const ds = v.replace(/\D/g, "");
|
|
18683
|
+
const need = (pattern.match(/#/g) ?? []).length;
|
|
18684
|
+
if (need === 0 || ds.length !== need) return v;
|
|
18648
18685
|
let i = 0;
|
|
18649
|
-
return pattern.replace(/#/g, () => ds[i++]
|
|
18686
|
+
return pattern.replace(/#/g, () => ds[i++]);
|
|
18650
18687
|
}
|
|
18651
18688
|
function fmtPhone(v, style) {
|
|
18652
18689
|
const d = v.replace(/\D/g, "");
|
|
18653
18690
|
if (d.length < 9) return v;
|
|
18654
|
-
const
|
|
18691
|
+
const areaLen = d.startsWith("02") ? 2 : 3;
|
|
18692
|
+
const a = d.slice(0, areaLen), b = d.slice(areaLen, -4), c = d.slice(-4);
|
|
18655
18693
|
switch (style) {
|
|
18656
18694
|
case "digits":
|
|
18657
18695
|
return d;
|
|
@@ -18660,9 +18698,9 @@ function fmtPhone(v, style) {
|
|
|
18660
18698
|
case "space":
|
|
18661
18699
|
return `${a} ${b} ${c}`;
|
|
18662
18700
|
case "intl":
|
|
18663
|
-
return `+82-${d.slice(1,
|
|
18701
|
+
return `+82-${d.slice(1, areaLen)}-${b}-${c}`;
|
|
18664
18702
|
case "intl-paren":
|
|
18665
|
-
return `82)${d.slice(1,
|
|
18703
|
+
return `82)${d.slice(1, areaLen)}-${b}-${c}`;
|
|
18666
18704
|
default:
|
|
18667
18705
|
return `${a}-${b}-${c}`;
|
|
18668
18706
|
}
|
|
@@ -18690,7 +18728,10 @@ function formatFillValue(value, format) {
|
|
|
18690
18728
|
if (kind === "phone") return fmtPhone(value, style);
|
|
18691
18729
|
if (kind === "rrn") return fmtRRN(value, style);
|
|
18692
18730
|
if (kind === "mask") return maskDigits(value, style);
|
|
18693
|
-
if (kind === "digits")
|
|
18731
|
+
if (kind === "digits") {
|
|
18732
|
+
const only = value.replace(/\D/g, "");
|
|
18733
|
+
return only || value;
|
|
18734
|
+
}
|
|
18694
18735
|
if (kind === "upper") return value.toUpperCase();
|
|
18695
18736
|
if (kind === "lower") return value.toLowerCase();
|
|
18696
18737
|
if (kind === "nospace") return value.replace(/\s+/g, "");
|
|
@@ -18767,7 +18808,7 @@ function isKeywordLabel(text) {
|
|
|
18767
18808
|
}
|
|
18768
18809
|
return false;
|
|
18769
18810
|
}
|
|
18770
|
-
function fillInCellPatterns(cellText, values, matchedLabels) {
|
|
18811
|
+
function fillInCellPatterns(cellText, values, matchedLabels, blockedLabels) {
|
|
18771
18812
|
let text = cellText;
|
|
18772
18813
|
const matches = [];
|
|
18773
18814
|
text = text.replace(
|
|
@@ -18775,6 +18816,7 @@ function fillInCellPatterns(cellText, values, matchedLabels) {
|
|
|
18775
18816
|
(match, prefix, suffix) => {
|
|
18776
18817
|
const label = prefix + suffix;
|
|
18777
18818
|
const normalizedLabel = normalizeLabel(label);
|
|
18819
|
+
if (blockedLabels?.has(normalizedLabel)) return match;
|
|
18778
18820
|
const matchKey = values.available(normalizedLabel) ? normalizedLabel : values.available(normalizeLabel(prefix)) ? normalizeLabel(prefix) : void 0;
|
|
18779
18821
|
if (matchKey === void 0) return match;
|
|
18780
18822
|
const newValue = values.consume(matchKey);
|
|
@@ -18870,8 +18912,12 @@ async function fillWithUniqueGuard(values, run) {
|
|
|
18870
18912
|
};
|
|
18871
18913
|
const dup = new Set([...counts].filter(([k, n]) => n >= 2 && !isArrayValue(k)).map(([k]) => k));
|
|
18872
18914
|
if (dup.size === 0) return { ...first, rejected: [] };
|
|
18915
|
+
const blockedLabels = /* @__PURE__ */ new Set();
|
|
18916
|
+
for (const f of first.filled) {
|
|
18917
|
+
if (f.key && dup.has(f.key)) blockedLabels.add(normalizeLabel(f.label));
|
|
18918
|
+
}
|
|
18873
18919
|
const filtered = Object.fromEntries(Object.entries(values).filter(([label]) => !dup.has(normalizeLabel(label))));
|
|
18874
|
-
const second = await run(filtered);
|
|
18920
|
+
const second = await run(filtered, blockedLabels);
|
|
18875
18921
|
const rejected = Object.keys(values).filter((label) => dup.has(normalizeLabel(label)));
|
|
18876
18922
|
return { ...second, rejected };
|
|
18877
18923
|
}
|
|
@@ -19126,7 +19172,7 @@ function extractFormSchema(blocks) {
|
|
|
19126
19172
|
}
|
|
19127
19173
|
|
|
19128
19174
|
// src/form/filler.ts
|
|
19129
|
-
function fillFormFields(blocks, values) {
|
|
19175
|
+
function fillFormFields(blocks, values, blockedLabels) {
|
|
19130
19176
|
const cloned = structuredClone(blocks);
|
|
19131
19177
|
const filled = [];
|
|
19132
19178
|
const matchedLabels = /* @__PURE__ */ new Set();
|
|
@@ -19139,7 +19185,7 @@ function fillFormFields(blocks, values) {
|
|
|
19139
19185
|
for (let c = 0; c < table.cols; c++) {
|
|
19140
19186
|
const cell = table.cells[r]?.[c];
|
|
19141
19187
|
if (!cell) continue;
|
|
19142
|
-
const result = fillInCellPatterns(cell.text, cursor, matchedLabels);
|
|
19188
|
+
const result = fillInCellPatterns(cell.text, cursor, matchedLabels, blockedLabels);
|
|
19143
19189
|
if (result) {
|
|
19144
19190
|
cell.text = result.text;
|
|
19145
19191
|
patternFilledCells.add(cell);
|
|
@@ -19151,11 +19197,11 @@ function fillFormFields(blocks, values) {
|
|
|
19151
19197
|
}
|
|
19152
19198
|
}
|
|
19153
19199
|
for (const table of allTables) {
|
|
19154
|
-
fillTable(table, cursor, filled, matchedLabels, patternFilledCells);
|
|
19200
|
+
fillTable(table, cursor, filled, matchedLabels, patternFilledCells, blockedLabels);
|
|
19155
19201
|
}
|
|
19156
19202
|
for (const block of cloned) {
|
|
19157
19203
|
if (block.type !== "paragraph" || !block.text) continue;
|
|
19158
|
-
const newText = fillInlineFields(block.text, cursor, filled, matchedLabels);
|
|
19204
|
+
const newText = fillInlineFields(block.text, cursor, filled, matchedLabels, blockedLabels);
|
|
19159
19205
|
if (newText !== block.text) block.text = newText;
|
|
19160
19206
|
}
|
|
19161
19207
|
const unmatched = resolveUnmatched(normalizedValues, matchedLabels, values);
|
|
@@ -19193,7 +19239,7 @@ function coveredPositions(table) {
|
|
|
19193
19239
|
}
|
|
19194
19240
|
return covered;
|
|
19195
19241
|
}
|
|
19196
|
-
function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
19242
|
+
function fillTable(table, values, filled, matchedLabels, patternFilledCells, blockedLabels) {
|
|
19197
19243
|
if (table.cols < 2) return;
|
|
19198
19244
|
const covered = coveredPositions(table);
|
|
19199
19245
|
for (let r = 0; r < table.rows; r++) {
|
|
@@ -19210,6 +19256,7 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19210
19256
|
if (isKeywordLabel(valueCell.text)) continue;
|
|
19211
19257
|
const normalizedCellLabel = normalizeLabel(labelCell.text);
|
|
19212
19258
|
if (!normalizedCellLabel) continue;
|
|
19259
|
+
if (blockedLabels?.has(normalizedCellLabel)) continue;
|
|
19213
19260
|
const matchKey = findMatchingKey(normalizedCellLabel, values);
|
|
19214
19261
|
if (matchKey === void 0) continue;
|
|
19215
19262
|
const newValue = values.consume(matchKey);
|
|
@@ -19243,6 +19290,7 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19243
19290
|
const valueCell = table.cells[r]?.[c];
|
|
19244
19291
|
if (!headerCell || !valueCell) continue;
|
|
19245
19292
|
const headerLabel = normalizeLabel(headerCell.text);
|
|
19293
|
+
if (blockedLabels?.has(headerLabel)) continue;
|
|
19246
19294
|
const matchKey = findMatchingKey(headerLabel, values);
|
|
19247
19295
|
if (matchKey === void 0) continue;
|
|
19248
19296
|
if (!values.isArray(matchKey) && matchedLabels.has(matchKey)) continue;
|
|
@@ -19261,13 +19309,15 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19261
19309
|
}
|
|
19262
19310
|
}
|
|
19263
19311
|
}
|
|
19264
|
-
function fillInlineFields(text, values, filled, matchedLabels) {
|
|
19312
|
+
function fillInlineFields(text, values, filled, matchedLabels, blockedLabels) {
|
|
19265
19313
|
const segments = scanInlineSegments(text);
|
|
19266
19314
|
if (segments.length === 0) return text;
|
|
19267
19315
|
let out = "";
|
|
19268
19316
|
let pos = 0;
|
|
19269
19317
|
for (const seg of segments) {
|
|
19270
|
-
const
|
|
19318
|
+
const nlabel = normalizeLabel(seg.label);
|
|
19319
|
+
if (blockedLabels?.has(nlabel)) continue;
|
|
19320
|
+
const matchKey = findMatchingKey(nlabel, values);
|
|
19271
19321
|
if (matchKey === void 0) continue;
|
|
19272
19322
|
const newValue = values.consume(matchKey);
|
|
19273
19323
|
if (newValue === void 0) continue;
|
|
@@ -19283,678 +19333,7 @@ function fillInlineFields(text, values, filled, matchedLabels) {
|
|
|
19283
19333
|
|
|
19284
19334
|
// src/form/filler-hwpx.ts
|
|
19285
19335
|
import JSZip5 from "jszip";
|
|
19286
|
-
|
|
19287
|
-
// src/roundtrip/source-map.ts
|
|
19288
|
-
function escapeXmlText(text) {
|
|
19289
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
19290
|
-
}
|
|
19291
|
-
function decodeXmlEntities(text) {
|
|
19292
|
-
return text.replace(/&(lt|gt|amp|quot|apos|#x?[0-9a-fA-F]+);/g, (m, ent) => {
|
|
19293
|
-
switch (ent) {
|
|
19294
|
-
case "lt":
|
|
19295
|
-
return "<";
|
|
19296
|
-
case "gt":
|
|
19297
|
-
return ">";
|
|
19298
|
-
case "amp":
|
|
19299
|
-
return "&";
|
|
19300
|
-
case "quot":
|
|
19301
|
-
return '"';
|
|
19302
|
-
case "apos":
|
|
19303
|
-
return "'";
|
|
19304
|
-
}
|
|
19305
|
-
try {
|
|
19306
|
-
const code = ent[1] === "x" || ent[1] === "X" ? parseInt(ent.slice(2), 16) : parseInt(ent.slice(1), 10);
|
|
19307
|
-
if (!isNaN(code) && code >= 0 && code <= 1114111) return String.fromCodePoint(code);
|
|
19308
|
-
} catch {
|
|
19309
|
-
}
|
|
19310
|
-
return m;
|
|
19311
|
-
});
|
|
19312
|
-
}
|
|
19313
|
-
function tContentToText(raw) {
|
|
19314
|
-
return decodeXmlEntities(
|
|
19315
|
-
raw.replace(/<\/?(?:[A-Za-z0-9_]+:)?(?:tab|fwSpace|hwSpace|br|lineBreak)(?:\s[^>]*)?\/?>/g, " ").replace(/<[^>]*>/g, "")
|
|
19316
|
-
);
|
|
19317
|
-
}
|
|
19318
|
-
var TAG_RE = /<!--[\s\S]*?-->|<!\[CDATA\[[\s\S]*?\]\]>|<\?[\s\S]*?\?>|<!(?:"[^"]*"|'[^']*'|[^>"'])*>|<\/([^\s>]+)\s*>|<([^\s/>!?]+)((?:"[^"]*"|'[^']*'|[^>"'])*?)(\/?)>/g;
|
|
19319
|
-
var T_BARRIER = /* @__PURE__ */ new Set([
|
|
19320
|
-
"tbl",
|
|
19321
|
-
"ctrl",
|
|
19322
|
-
"caption",
|
|
19323
|
-
"pic",
|
|
19324
|
-
"shape",
|
|
19325
|
-
"drawingObject",
|
|
19326
|
-
"drawText",
|
|
19327
|
-
"shapeComment",
|
|
19328
|
-
"memogroup",
|
|
19329
|
-
"memo",
|
|
19330
|
-
"hiddenComment",
|
|
19331
|
-
"equation",
|
|
19332
|
-
"parameters",
|
|
19333
|
-
"subList",
|
|
19334
|
-
"p"
|
|
19335
|
-
]);
|
|
19336
|
-
var PARA_CONTAINER = /* @__PURE__ */ new Set([
|
|
19337
|
-
"tc",
|
|
19338
|
-
"ctrl",
|
|
19339
|
-
"caption",
|
|
19340
|
-
"drawText",
|
|
19341
|
-
"pic",
|
|
19342
|
-
"shape",
|
|
19343
|
-
"drawingObject",
|
|
19344
|
-
"memogroup",
|
|
19345
|
-
"memo",
|
|
19346
|
-
"hiddenComment",
|
|
19347
|
-
"footNote",
|
|
19348
|
-
"endNote",
|
|
19349
|
-
"fn",
|
|
19350
|
-
"en"
|
|
19351
|
-
// 각주/미주 — 파서는 호스트 블록 footnoteText로만 흡수
|
|
19352
|
-
]);
|
|
19353
|
-
var TABLE_BARRIER = /* @__PURE__ */ new Set([
|
|
19354
|
-
"tbl",
|
|
19355
|
-
"ctrl",
|
|
19356
|
-
"caption",
|
|
19357
|
-
"memogroup",
|
|
19358
|
-
"memo",
|
|
19359
|
-
"hiddenComment"
|
|
19360
|
-
]);
|
|
19361
|
-
function localOf(qname) {
|
|
19362
|
-
const i = qname.indexOf(":");
|
|
19363
|
-
return i >= 0 ? qname.slice(i + 1) : qname;
|
|
19364
|
-
}
|
|
19365
|
-
function prefixOf(qname) {
|
|
19366
|
-
const i = qname.indexOf(":");
|
|
19367
|
-
return i >= 0 ? qname.slice(0, i) : "";
|
|
19368
|
-
}
|
|
19369
|
-
function scanSectionXml(xml, sectionIndex) {
|
|
19370
|
-
const stack = [];
|
|
19371
|
-
const bodyParagraphs = [];
|
|
19372
|
-
const tables = [];
|
|
19373
|
-
const headerTexts = [];
|
|
19374
|
-
const footerTexts = [];
|
|
19375
|
-
const excludedParagraphs = [];
|
|
19376
|
-
const orphanTables = [];
|
|
19377
|
-
const paraStack = [];
|
|
19378
|
-
const tableStack = [];
|
|
19379
|
-
const rowStack = [];
|
|
19380
|
-
const trStartStack = [];
|
|
19381
|
-
const cellStack = [];
|
|
19382
|
-
let pendingT = null;
|
|
19383
|
-
const ctrlSubStack = [];
|
|
19384
|
-
const classifyPara = () => {
|
|
19385
|
-
let sawDrawText = false;
|
|
19386
|
-
for (let i = stack.length - 1; i >= 0; i--) {
|
|
19387
|
-
const l = stack[i].local;
|
|
19388
|
-
if (l === "tc") return { kind: "cell", inTextbox: sawDrawText };
|
|
19389
|
-
if (l === "drawText") {
|
|
19390
|
-
sawDrawText = true;
|
|
19391
|
-
continue;
|
|
19392
|
-
}
|
|
19393
|
-
if (PARA_CONTAINER.has(l)) return { kind: "excluded", inTextbox: sawDrawText };
|
|
19394
|
-
}
|
|
19395
|
-
return sawDrawText ? { kind: "draw", inTextbox: true } : { kind: "body", inTextbox: false };
|
|
19396
|
-
};
|
|
19397
|
-
const owningPara = () => {
|
|
19398
|
-
if (paraStack.length === 0) return null;
|
|
19399
|
-
for (let i = stack.length - 1; i >= 0; i--) {
|
|
19400
|
-
const l = stack[i].local;
|
|
19401
|
-
if (l === "p") return paraStack[paraStack.length - 1];
|
|
19402
|
-
if (T_BARRIER.has(l)) return null;
|
|
19403
|
-
}
|
|
19404
|
-
return null;
|
|
19405
|
-
};
|
|
19406
|
-
const isTableTopLevel = () => {
|
|
19407
|
-
for (let i = stack.length - 1; i >= 0; i--) {
|
|
19408
|
-
if (TABLE_BARRIER.has(stack[i].local)) return false;
|
|
19409
|
-
}
|
|
19410
|
-
return true;
|
|
19411
|
-
};
|
|
19412
|
-
const currentCtrlSub = () => ctrlSubStack.length > 0 ? ctrlSubStack[ctrlSubStack.length - 1] : null;
|
|
19413
|
-
TAG_RE.lastIndex = 0;
|
|
19414
|
-
let m;
|
|
19415
|
-
while ((m = TAG_RE.exec(xml)) !== null) {
|
|
19416
|
-
const [full, closeName, openName, , selfClose] = m;
|
|
19417
|
-
if (closeName === void 0 && openName === void 0) continue;
|
|
19418
|
-
if (closeName !== void 0) {
|
|
19419
|
-
const local2 = localOf(closeName);
|
|
19420
|
-
if (local2 === "t" && pendingT) {
|
|
19421
|
-
const { para, contentStart: contentStart2 } = pendingT;
|
|
19422
|
-
para.tRanges.push({ contentStart: contentStart2, contentEnd: m.index });
|
|
19423
|
-
para.text += tContentToText(xml.slice(contentStart2, m.index));
|
|
19424
|
-
pendingT = null;
|
|
19425
|
-
}
|
|
19426
|
-
for (let i = stack.length - 1; i >= 0; i--) {
|
|
19427
|
-
if (stack[i].local === local2) {
|
|
19428
|
-
stack.length = i;
|
|
19429
|
-
break;
|
|
19430
|
-
}
|
|
19431
|
-
}
|
|
19432
|
-
if (local2 === "p") {
|
|
19433
|
-
const para = paraStack.pop();
|
|
19434
|
-
if (para && para.kind === "excluded") {
|
|
19435
|
-
const sub = currentCtrlSub();
|
|
19436
|
-
if (sub && para.text.trim()) sub.texts.push(para.text);
|
|
19437
|
-
}
|
|
19438
|
-
} else if (local2 === "tc") {
|
|
19439
|
-
const cell = cellStack.pop();
|
|
19440
|
-
const row = rowStack[rowStack.length - 1];
|
|
19441
|
-
if (cell && row) row.push(cell);
|
|
19442
|
-
} else if (local2 === "tr") {
|
|
19443
|
-
const row = rowStack[rowStack.length - 1];
|
|
19444
|
-
const table = tableStack[tableStack.length - 1];
|
|
19445
|
-
if (row && table && row.length > 0) {
|
|
19446
|
-
table.rows.push(row);
|
|
19447
|
-
const trStart = trStartStack[trStartStack.length - 1];
|
|
19448
|
-
if (trStart >= 0) table.rowRanges.push({ start: trStart, end: m.index + full.length });
|
|
19449
|
-
}
|
|
19450
|
-
if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
|
|
19451
|
-
if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = -1;
|
|
19452
|
-
} else if (local2 === "tbl") {
|
|
19453
|
-
const table = tableStack.pop();
|
|
19454
|
-
rowStack.pop();
|
|
19455
|
-
trStartStack.pop();
|
|
19456
|
-
if (table) {
|
|
19457
|
-
finalizeTable(table);
|
|
19458
|
-
if (!table.topLevel) {
|
|
19459
|
-
const cell = cellStack[cellStack.length - 1];
|
|
19460
|
-
if (cell) cell.tables.push(table);
|
|
19461
|
-
else orphanTables.push(table);
|
|
19462
|
-
}
|
|
19463
|
-
}
|
|
19464
|
-
} else if (local2 === "header" || local2 === "footer") {
|
|
19465
|
-
const sub = ctrlSubStack[ctrlSubStack.length - 1];
|
|
19466
|
-
if (sub) {
|
|
19467
|
-
ctrlSubStack.pop();
|
|
19468
|
-
const joined = sub.texts.join("\n").trim();
|
|
19469
|
-
if (joined) (sub.kind === "header" ? headerTexts : footerTexts).push(joined);
|
|
19470
|
-
}
|
|
19471
|
-
}
|
|
19472
|
-
continue;
|
|
19473
|
-
}
|
|
19474
|
-
const qname = openName;
|
|
19475
|
-
const local = localOf(qname);
|
|
19476
|
-
const attrsRaw = m[3] || "";
|
|
19477
|
-
const isSelfClose = selfClose === "/";
|
|
19478
|
-
const contentStart = m.index + full.length;
|
|
19479
|
-
if (isSelfClose) {
|
|
19480
|
-
if (local === "t") {
|
|
19481
|
-
const para = owningPara();
|
|
19482
|
-
if (para) para.tRanges.push({ contentStart: m.index, contentEnd: m.index + full.length, selfClosing: true, prefix: prefixOf(qname) });
|
|
19483
|
-
} else if (local === "tab" || local === "fwSpace" || local === "hwSpace" || local === "br" || local === "lineBreak") {
|
|
19484
|
-
if (!pendingT) {
|
|
19485
|
-
const para = owningPara();
|
|
19486
|
-
if (para) para.text += " ";
|
|
19487
|
-
}
|
|
19488
|
-
} else if (local === "run" || local === "r") {
|
|
19489
|
-
const para = owningPara();
|
|
19490
|
-
if (para && !para.selfCloseRun) para.selfCloseRun = { start: m.index, end: m.index + full.length };
|
|
19491
|
-
} else if (local === "cellAddr") {
|
|
19492
|
-
const cell = cellStack[cellStack.length - 1];
|
|
19493
|
-
if (cell && insideCurrentTable(stack, tableStack)) {
|
|
19494
|
-
const ca = parseInt(getAttr2(attrsRaw, "colAddr") || "", 10);
|
|
19495
|
-
const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
|
|
19496
|
-
if (!isNaN(ca)) cell.colAddr = ca;
|
|
19497
|
-
if (!isNaN(ra)) cell.rowAddr = ra;
|
|
19498
|
-
cell.addrTagRange = { start: m.index, end: m.index + full.length };
|
|
19499
|
-
}
|
|
19500
|
-
} else if (local === "cellSpan") {
|
|
19501
|
-
const cell = cellStack[cellStack.length - 1];
|
|
19502
|
-
if (cell && insideCurrentTable(stack, tableStack)) {
|
|
19503
|
-
const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
|
|
19504
|
-
const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
|
|
19505
|
-
cell.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
|
|
19506
|
-
cell.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
|
|
19507
|
-
}
|
|
19508
|
-
}
|
|
19509
|
-
continue;
|
|
19510
|
-
}
|
|
19511
|
-
if (local === "t") {
|
|
19512
|
-
const para = owningPara();
|
|
19513
|
-
if (para) pendingT = { para, contentStart };
|
|
19514
|
-
stack.push({ local, qname, contentStart });
|
|
19515
|
-
continue;
|
|
19516
|
-
}
|
|
19517
|
-
stack.push({ local, qname, contentStart });
|
|
19518
|
-
if (local === "p") {
|
|
19519
|
-
const para = {
|
|
19520
|
-
sectionIndex,
|
|
19521
|
-
kind: "excluded",
|
|
19522
|
-
// 분류는 push 직후 스택 기준 (자기 자신 제외)
|
|
19523
|
-
start: m.index,
|
|
19524
|
-
tRanges: [],
|
|
19525
|
-
text: ""
|
|
19526
|
-
};
|
|
19527
|
-
stack.pop();
|
|
19528
|
-
const cls = classifyPara();
|
|
19529
|
-
para.kind = cls.kind;
|
|
19530
|
-
if (cls.inTextbox) para.inTextbox = true;
|
|
19531
|
-
stack.push({ local, qname, contentStart });
|
|
19532
|
-
paraStack.push(para);
|
|
19533
|
-
if (para.kind === "body" || para.kind === "draw") bodyParagraphs.push(para);
|
|
19534
|
-
else if (para.kind === "cell") {
|
|
19535
|
-
const cell = cellStack[cellStack.length - 1];
|
|
19536
|
-
if (cell) cell.paragraphs.push(para);
|
|
19537
|
-
} else if (para.kind === "excluded") {
|
|
19538
|
-
excludedParagraphs.push(para);
|
|
19539
|
-
}
|
|
19540
|
-
} else if (local === "run" || local === "r") {
|
|
19541
|
-
const para = owningPara();
|
|
19542
|
-
if (para && para.runPrefix === void 0) para.runPrefix = prefixOf(qname);
|
|
19543
|
-
} else if (local === "tbl") {
|
|
19544
|
-
const table = {
|
|
19545
|
-
sectionIndex,
|
|
19546
|
-
start: m.index,
|
|
19547
|
-
topLevel: false,
|
|
19548
|
-
rows: [],
|
|
19549
|
-
rowRanges: [],
|
|
19550
|
-
cellByAnchor: /* @__PURE__ */ new Map()
|
|
19551
|
-
};
|
|
19552
|
-
stack.pop();
|
|
19553
|
-
table.topLevel = isTableTopLevel();
|
|
19554
|
-
stack.push({ local, qname, contentStart });
|
|
19555
|
-
tableStack.push(table);
|
|
19556
|
-
rowStack.push([]);
|
|
19557
|
-
trStartStack.push(-1);
|
|
19558
|
-
if (table.topLevel) tables.push(table);
|
|
19559
|
-
} else if (local === "tr") {
|
|
19560
|
-
if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
|
|
19561
|
-
if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = m.index;
|
|
19562
|
-
} else if (local === "tc") {
|
|
19563
|
-
cellStack.push({ colSpan: 1, rowSpan: 1, paragraphs: [], tables: [] });
|
|
19564
|
-
} else if (local === "cellAddr" || local === "cellSpan") {
|
|
19565
|
-
const cell = cellStack[cellStack.length - 1];
|
|
19566
|
-
if (cell && insideCurrentTable(stack, tableStack)) {
|
|
19567
|
-
if (local === "cellAddr") {
|
|
19568
|
-
const ca = parseInt(getAttr2(attrsRaw, "colAddr") || "", 10);
|
|
19569
|
-
const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
|
|
19570
|
-
if (!isNaN(ca)) cell.colAddr = ca;
|
|
19571
|
-
if (!isNaN(ra)) cell.rowAddr = ra;
|
|
19572
|
-
cell.addrTagRange = { start: m.index, end: contentStart };
|
|
19573
|
-
} else {
|
|
19574
|
-
const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
|
|
19575
|
-
const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
|
|
19576
|
-
cell.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
|
|
19577
|
-
cell.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
|
|
19578
|
-
}
|
|
19579
|
-
}
|
|
19580
|
-
} else if (local === "header" || local === "footer") {
|
|
19581
|
-
if (stack.some((f) => f.local === "ctrl")) {
|
|
19582
|
-
ctrlSubStack.push({ kind: local, texts: [] });
|
|
19583
|
-
}
|
|
19584
|
-
} else if (local === "tab" || local === "fwSpace" || local === "hwSpace" || local === "br" || local === "lineBreak") {
|
|
19585
|
-
const para = owningPara();
|
|
19586
|
-
if (para) para.text += " ";
|
|
19587
|
-
}
|
|
19588
|
-
}
|
|
19589
|
-
for (const para of bodyParagraphs) fillRunInsertPos(para, xml);
|
|
19590
|
-
for (const para of excludedParagraphs) fillRunInsertPos(para, xml);
|
|
19591
|
-
const fillTableInsertPos = (table, depth = 0) => {
|
|
19592
|
-
if (depth > 16) return;
|
|
19593
|
-
for (const row of table.rows) {
|
|
19594
|
-
for (const cell of row) {
|
|
19595
|
-
for (const para of cell.paragraphs) fillRunInsertPos(para, xml);
|
|
19596
|
-
for (const nested of cell.tables) fillTableInsertPos(nested, depth + 1);
|
|
19597
|
-
}
|
|
19598
|
-
}
|
|
19599
|
-
};
|
|
19600
|
-
for (const table of tables) fillTableInsertPos(table);
|
|
19601
|
-
for (const table of orphanTables) fillTableInsertPos(table);
|
|
19602
|
-
return { sectionIndex, xml, bodyParagraphs, tables, headerTexts, footerTexts, excludedParagraphs, orphanTables };
|
|
19603
|
-
}
|
|
19604
|
-
function getAttr2(attrsRaw, name) {
|
|
19605
|
-
const re = new RegExp(`(?:^|\\s)${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)')`);
|
|
19606
|
-
const m = attrsRaw.match(re);
|
|
19607
|
-
return m ? m[1] ?? m[2] : void 0;
|
|
19608
|
-
}
|
|
19609
|
-
function insideCurrentTable(stack, tableStack) {
|
|
19610
|
-
if (tableStack.length === 0) return false;
|
|
19611
|
-
for (let i = stack.length - 1; i >= 0; i--) {
|
|
19612
|
-
const l = stack[i].local;
|
|
19613
|
-
if (l === "tc") return true;
|
|
19614
|
-
if (l === "tbl") return false;
|
|
19615
|
-
}
|
|
19616
|
-
return false;
|
|
19617
|
-
}
|
|
19618
|
-
function fillRunInsertPos(para, xml) {
|
|
19619
|
-
if (para.tRanges.length > 0) return;
|
|
19620
|
-
const pEnd = findElementEnd(xml, para.start);
|
|
19621
|
-
if (pEnd < 0) return;
|
|
19622
|
-
const slice = xml.slice(para.start, pEnd);
|
|
19623
|
-
const runOpen = slice.match(/<((?:[A-Za-z0-9_]+:)?run)(?:\s(?:"[^"]*"|'[^']*'|[^>"'])*?)?(\/?)>/);
|
|
19624
|
-
if (!runOpen || runOpen.index === void 0) return;
|
|
19625
|
-
if (runOpen[2] === "/") return;
|
|
19626
|
-
const qname = runOpen[1];
|
|
19627
|
-
const closeIdx = slice.indexOf(`</${qname}>`, runOpen.index);
|
|
19628
|
-
if (closeIdx < 0) return;
|
|
19629
|
-
para.runInsertPos = para.start + closeIdx;
|
|
19630
|
-
para.runPrefix = prefixOf(qname);
|
|
19631
|
-
}
|
|
19632
|
-
function findElementEnd(xml, start) {
|
|
19633
|
-
const open = xml.slice(start).match(/^<([^\s/>!?]+)/);
|
|
19634
|
-
if (!open) return -1;
|
|
19635
|
-
const qname = open[1];
|
|
19636
|
-
const re = new RegExp(`<${qname}(?=[\\s/>])(?:"[^"]*"|'[^']*'|[^>"'])*?(/?)>|</${qname}\\s*>`, "g");
|
|
19637
|
-
re.lastIndex = start;
|
|
19638
|
-
let depth = 0;
|
|
19639
|
-
let mm;
|
|
19640
|
-
while ((mm = re.exec(xml)) !== null) {
|
|
19641
|
-
if (mm[0].startsWith("</")) {
|
|
19642
|
-
depth--;
|
|
19643
|
-
if (depth === 0) return mm.index + mm[0].length;
|
|
19644
|
-
} else if (mm[1] !== "/") {
|
|
19645
|
-
depth++;
|
|
19646
|
-
}
|
|
19647
|
-
}
|
|
19648
|
-
return -1;
|
|
19649
|
-
}
|
|
19650
|
-
function finalizeTable(table) {
|
|
19651
|
-
const hasAddr = table.rows.some((row) => row.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0));
|
|
19652
|
-
if (hasAddr) {
|
|
19653
|
-
for (const row of table.rows) {
|
|
19654
|
-
for (const cell of row) {
|
|
19655
|
-
if (cell.rowAddr !== void 0 && cell.colAddr !== void 0) {
|
|
19656
|
-
table.cellByAnchor.set(`${cell.rowAddr},${cell.colAddr}`, cell);
|
|
19657
|
-
}
|
|
19658
|
-
}
|
|
19659
|
-
}
|
|
19660
|
-
return;
|
|
19661
|
-
}
|
|
19662
|
-
const numRows = table.rows.length;
|
|
19663
|
-
const occupied = Array.from({ length: numRows }, () => []);
|
|
19664
|
-
for (let rowIdx = 0; rowIdx < numRows; rowIdx++) {
|
|
19665
|
-
let colIdx = 0;
|
|
19666
|
-
for (const cell of table.rows[rowIdx]) {
|
|
19667
|
-
while (occupied[rowIdx][colIdx]) colIdx++;
|
|
19668
|
-
cell.rowAddr = rowIdx;
|
|
19669
|
-
cell.colAddr = colIdx;
|
|
19670
|
-
table.cellByAnchor.set(`${rowIdx},${colIdx}`, cell);
|
|
19671
|
-
for (let r = rowIdx; r < Math.min(rowIdx + cell.rowSpan, numRows); r++) {
|
|
19672
|
-
for (let c = colIdx; c < colIdx + cell.colSpan; c++) {
|
|
19673
|
-
occupied[r][c] = true;
|
|
19674
|
-
}
|
|
19675
|
-
}
|
|
19676
|
-
colIdx += cell.colSpan;
|
|
19677
|
-
}
|
|
19678
|
-
}
|
|
19679
|
-
}
|
|
19680
|
-
function buildParagraphSplices(para, newText, xml) {
|
|
19681
|
-
if (newText && xml) {
|
|
19682
|
-
const orig = paraTText(para, xml);
|
|
19683
|
-
if (orig && orig.trim() !== "") {
|
|
19684
|
-
const lead = orig.match(/^\s*/)[0];
|
|
19685
|
-
const trail = orig.match(/\s*$/)[0];
|
|
19686
|
-
if ((lead || trail) && newText.trim() !== "") {
|
|
19687
|
-
newText = lead + newText.replace(/^\s+|\s+$/g, "") + trail;
|
|
19688
|
-
}
|
|
19689
|
-
}
|
|
19690
|
-
}
|
|
19691
|
-
const escaped = escapeXmlText(newText);
|
|
19692
|
-
if (para.tRanges.length > 0) {
|
|
19693
|
-
const splices = [];
|
|
19694
|
-
const first = para.tRanges[0];
|
|
19695
|
-
if (first.selfClosing) {
|
|
19696
|
-
const prefix = first.prefix ? first.prefix + ":" : "";
|
|
19697
|
-
splices.push({ start: first.contentStart, end: first.contentEnd, replacement: `<${prefix}t>${escaped}</${prefix}t>` });
|
|
19698
|
-
} else {
|
|
19699
|
-
splices.push({ start: first.contentStart, end: first.contentEnd, replacement: escaped });
|
|
19700
|
-
}
|
|
19701
|
-
for (let i = 1; i < para.tRanges.length; i++) {
|
|
19702
|
-
const r = para.tRanges[i];
|
|
19703
|
-
if (!r.selfClosing && r.contentStart < r.contentEnd) {
|
|
19704
|
-
splices.push({ start: r.contentStart, end: r.contentEnd, replacement: "" });
|
|
19705
|
-
}
|
|
19706
|
-
}
|
|
19707
|
-
return splices;
|
|
19708
|
-
}
|
|
19709
|
-
if (para.runInsertPos !== void 0) {
|
|
19710
|
-
if (!newText) return [];
|
|
19711
|
-
const prefix = para.runPrefix ? para.runPrefix + ":" : "";
|
|
19712
|
-
return [{ start: para.runInsertPos, end: para.runInsertPos, replacement: `<${prefix}t>${escaped}</${prefix}t>` }];
|
|
19713
|
-
}
|
|
19714
|
-
if (para.selfCloseRun && xml) {
|
|
19715
|
-
if (!newText) return [];
|
|
19716
|
-
const { start, end } = para.selfCloseRun;
|
|
19717
|
-
const tag = xml.slice(start, end);
|
|
19718
|
-
const qm = tag.match(/^<([^\s/>]+)/);
|
|
19719
|
-
if (!qm || !tag.endsWith("/>")) return null;
|
|
19720
|
-
const qname = qm[1];
|
|
19721
|
-
const colon = qname.indexOf(":");
|
|
19722
|
-
const prefix = colon >= 0 ? qname.slice(0, colon) + ":" : "";
|
|
19723
|
-
const opened = tag.slice(0, tag.length - 2).trimEnd() + ">";
|
|
19724
|
-
return [{ start, end, replacement: `${opened}<${prefix}t>${escaped}</${prefix}t></${qname}>` }];
|
|
19725
|
-
}
|
|
19726
|
-
return newText ? null : [];
|
|
19727
|
-
}
|
|
19728
|
-
function paraTText(para, xml) {
|
|
19729
|
-
let text = "";
|
|
19730
|
-
for (const t of para.tRanges) {
|
|
19731
|
-
if (t.selfClosing) continue;
|
|
19732
|
-
const raw = xml.slice(t.contentStart, t.contentEnd);
|
|
19733
|
-
if (/[<&]/.test(raw)) return null;
|
|
19734
|
-
text += raw;
|
|
19735
|
-
}
|
|
19736
|
-
return text;
|
|
19737
|
-
}
|
|
19738
|
-
function paraTextPureT(para, xml) {
|
|
19739
|
-
let len = 0;
|
|
19740
|
-
for (const t of para.tRanges) {
|
|
19741
|
-
if (t.selfClosing) continue;
|
|
19742
|
-
len += tContentToText(xml.slice(t.contentStart, t.contentEnd)).length;
|
|
19743
|
-
}
|
|
19744
|
-
return len === para.text.length;
|
|
19745
|
-
}
|
|
19746
|
-
function buildRangeSplices(para, xml, start, end, replacement) {
|
|
19747
|
-
if (start < 0 || end < start) return null;
|
|
19748
|
-
const segs = [];
|
|
19749
|
-
let offset = 0;
|
|
19750
|
-
for (const t of para.tRanges) {
|
|
19751
|
-
if (t.selfClosing) continue;
|
|
19752
|
-
const raw = xml.slice(t.contentStart, t.contentEnd);
|
|
19753
|
-
if (/[<&]/.test(raw)) return null;
|
|
19754
|
-
segs.push({ contentStart: t.contentStart, from: offset, to: offset + raw.length });
|
|
19755
|
-
offset += raw.length;
|
|
19756
|
-
}
|
|
19757
|
-
if (segs.length === 0 || end > offset) return null;
|
|
19758
|
-
const escaped = escapeXmlText(replacement);
|
|
19759
|
-
if (start === end) {
|
|
19760
|
-
for (const seg of segs) {
|
|
19761
|
-
if (start >= seg.from && start <= seg.to) {
|
|
19762
|
-
const at = seg.contentStart + (start - seg.from);
|
|
19763
|
-
return [{ start: at, end: at, replacement: escaped }];
|
|
19764
|
-
}
|
|
19765
|
-
}
|
|
19766
|
-
return null;
|
|
19767
|
-
}
|
|
19768
|
-
const splices = [];
|
|
19769
|
-
let placed = false;
|
|
19770
|
-
for (const seg of segs) {
|
|
19771
|
-
if (seg.to <= start || seg.from >= end) continue;
|
|
19772
|
-
const localStart = Math.max(seg.from, start) - seg.from;
|
|
19773
|
-
const localEnd = Math.min(seg.to, end) - seg.from;
|
|
19774
|
-
splices.push({
|
|
19775
|
-
start: seg.contentStart + localStart,
|
|
19776
|
-
end: seg.contentStart + localEnd,
|
|
19777
|
-
replacement: placed ? "" : escaped
|
|
19778
|
-
});
|
|
19779
|
-
placed = true;
|
|
19780
|
-
}
|
|
19781
|
-
return placed ? splices : null;
|
|
19782
|
-
}
|
|
19783
|
-
function allLinesegRemovalSplices(xml) {
|
|
19784
|
-
const segRe = /<(\w+:)?linesegarray\b[^>]*?(?:\/>|>[\s\S]*?<\/\1linesegarray>)/g;
|
|
19785
|
-
const splices = [];
|
|
19786
|
-
let m;
|
|
19787
|
-
while ((m = segRe.exec(xml)) !== null) {
|
|
19788
|
-
splices.push({ start: m.index, end: m.index + m[0].length, replacement: "" });
|
|
19789
|
-
}
|
|
19790
|
-
return splices;
|
|
19791
|
-
}
|
|
19792
|
-
function applySplices(xml, splices) {
|
|
19793
|
-
const sorted = [...splices].sort((a, b) => a.start - b.start);
|
|
19794
|
-
for (let i = 1; i < sorted.length; i++) {
|
|
19795
|
-
if (sorted[i].start < sorted[i - 1].end) {
|
|
19796
|
-
throw new Error("\uC18C\uC2A4\uB9F5 splice \uBC94\uC704 \uACB9\uCE68 \u2014 \uB0B4\uBD80 \uC624\uB958");
|
|
19797
|
-
}
|
|
19798
|
-
}
|
|
19799
|
-
let result = xml;
|
|
19800
|
-
for (let i = sorted.length - 1; i >= 0; i--) {
|
|
19801
|
-
const s = sorted[i];
|
|
19802
|
-
result = result.slice(0, s.start) + s.replacement + result.slice(s.end);
|
|
19803
|
-
}
|
|
19804
|
-
return result;
|
|
19805
|
-
}
|
|
19806
|
-
|
|
19807
|
-
// src/roundtrip/zip-patch.ts
|
|
19808
|
-
import { deflateRawSync } from "zlib";
|
|
19809
|
-
var EOCD_SIG = 101010256;
|
|
19810
|
-
var CD_SIG = 33639248;
|
|
19811
|
-
var LOCAL_SIG = 67324752;
|
|
19812
|
-
var ZIP64_EOCD_LOC_SIG = 117853008;
|
|
19813
|
-
function copyBytes(buf, start, end) {
|
|
19814
|
-
return new Uint8Array(buf.subarray(start, end));
|
|
19815
|
-
}
|
|
19816
|
-
function parseCentralDirectory(buf) {
|
|
19817
|
-
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
19818
|
-
const minEocd = Math.max(0, buf.length - 22 - 65535);
|
|
19819
|
-
let eocdOffset = -1;
|
|
19820
|
-
for (let i = buf.length - 22; i >= minEocd; i--) {
|
|
19821
|
-
if (view.getUint32(i, true) === EOCD_SIG && i + 22 + view.getUint16(i + 20, true) === buf.length) {
|
|
19822
|
-
eocdOffset = i;
|
|
19823
|
-
break;
|
|
19824
|
-
}
|
|
19825
|
-
}
|
|
19826
|
-
if (eocdOffset < 0) {
|
|
19827
|
-
for (let i = buf.length - 22; i >= minEocd; i--) {
|
|
19828
|
-
if (view.getUint32(i, true) !== EOCD_SIG) continue;
|
|
19829
|
-
if (i + 22 + view.getUint16(i + 20, true) > buf.length) continue;
|
|
19830
|
-
const cand = view.getUint32(i + 16, true);
|
|
19831
|
-
if (cand < buf.length - 4 && view.getUint32(cand, true) === CD_SIG) {
|
|
19832
|
-
eocdOffset = i;
|
|
19833
|
-
break;
|
|
19834
|
-
}
|
|
19835
|
-
}
|
|
19836
|
-
}
|
|
19837
|
-
if (eocdOffset < 0) throw new KordocError("ZIP EOCD\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
19838
|
-
const totalEntries = view.getUint16(eocdOffset + 10, true);
|
|
19839
|
-
const cdSize = view.getUint32(eocdOffset + 12, true);
|
|
19840
|
-
const cdOffset = view.getUint32(eocdOffset + 16, true);
|
|
19841
|
-
if (cdOffset === 4294967295 || totalEntries === 65535) throw new KordocError("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
19842
|
-
if (eocdOffset >= 20 && view.getUint32(eocdOffset - 20, true) === ZIP64_EOCD_LOC_SIG) {
|
|
19843
|
-
throw new KordocError("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
19844
|
-
}
|
|
19845
|
-
const decoder = new TextDecoder("utf-8");
|
|
19846
|
-
const entries = [];
|
|
19847
|
-
let pos = cdOffset;
|
|
19848
|
-
for (let i = 0; i < totalEntries; i++) {
|
|
19849
|
-
if (view.getUint32(pos, true) !== CD_SIG) throw new KordocError("ZIP Central Directory \uC190\uC0C1");
|
|
19850
|
-
const flags = view.getUint16(pos + 8, true);
|
|
19851
|
-
const method = view.getUint16(pos + 10, true);
|
|
19852
|
-
const crc = view.getUint32(pos + 16, true);
|
|
19853
|
-
const compSize = view.getUint32(pos + 20, true);
|
|
19854
|
-
const uncompSize = view.getUint32(pos + 24, true);
|
|
19855
|
-
const nameLen = view.getUint16(pos + 28, true);
|
|
19856
|
-
const extraLen = view.getUint16(pos + 30, true);
|
|
19857
|
-
const commentLen = view.getUint16(pos + 32, true);
|
|
19858
|
-
const localOffset = view.getUint32(pos + 42, true);
|
|
19859
|
-
if (compSize === 4294967295 || uncompSize === 4294967295 || localOffset === 4294967295) {
|
|
19860
|
-
throw new KordocError("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
19861
|
-
}
|
|
19862
|
-
const name = decoder.decode(buf.subarray(pos + 46, pos + 46 + nameLen));
|
|
19863
|
-
const cdEnd = pos + 46 + nameLen + extraLen + commentLen;
|
|
19864
|
-
entries.push({ cdStart: pos, cdEnd, name, flags, method, crc, compSize, uncompSize, localOffset });
|
|
19865
|
-
pos = cdEnd;
|
|
19866
|
-
}
|
|
19867
|
-
return { entries, cdOffset, cdSize, eocdOffset };
|
|
19868
|
-
}
|
|
19869
|
-
var CRC_TABLE = (() => {
|
|
19870
|
-
const table = new Uint32Array(256);
|
|
19871
|
-
for (let n = 0; n < 256; n++) {
|
|
19872
|
-
let c = n;
|
|
19873
|
-
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
19874
|
-
table[n] = c >>> 0;
|
|
19875
|
-
}
|
|
19876
|
-
return table;
|
|
19877
|
-
})();
|
|
19878
|
-
function crc32(data) {
|
|
19879
|
-
let crc = 4294967295;
|
|
19880
|
-
for (let i = 0; i < data.length; i++) {
|
|
19881
|
-
crc = CRC_TABLE[(crc ^ data[i]) & 255] ^ crc >>> 8;
|
|
19882
|
-
}
|
|
19883
|
-
return (crc ^ 4294967295) >>> 0;
|
|
19884
|
-
}
|
|
19885
|
-
function patchZipEntries(original, replacements) {
|
|
19886
|
-
const { entries, cdOffset, eocdOffset } = parseCentralDirectory(original);
|
|
19887
|
-
const view = new DataView(original.buffer, original.byteOffset, original.byteLength);
|
|
19888
|
-
for (const name of replacements.keys()) {
|
|
19889
|
-
if (!entries.some((e) => e.name === name)) throw new KordocError(`ZIP\uC5D0 \uC5C6\uB294 \uC5D4\uD2B8\uB9AC: ${name}`);
|
|
19890
|
-
}
|
|
19891
|
-
const byLocal = [...entries].sort((a, b) => a.localOffset - b.localOffset);
|
|
19892
|
-
const segments = [];
|
|
19893
|
-
const newLocalOffset = /* @__PURE__ */ new Map();
|
|
19894
|
-
const newMeta = /* @__PURE__ */ new Map();
|
|
19895
|
-
let offset = 0;
|
|
19896
|
-
for (let i = 0; i < byLocal.length; i++) {
|
|
19897
|
-
const e = byLocal[i];
|
|
19898
|
-
const segEnd = i + 1 < byLocal.length ? byLocal[i + 1].localOffset : cdOffset;
|
|
19899
|
-
newLocalOffset.set(e, offset);
|
|
19900
|
-
const newData = replacements.get(e.name);
|
|
19901
|
-
if (newData === void 0) {
|
|
19902
|
-
const seg = original.subarray(e.localOffset, segEnd);
|
|
19903
|
-
segments.push(seg);
|
|
19904
|
-
offset += seg.length;
|
|
19905
|
-
continue;
|
|
19906
|
-
}
|
|
19907
|
-
if (view.getUint32(e.localOffset, true) !== LOCAL_SIG) throw new KordocError("ZIP \uB85C\uCEEC \uD5E4\uB354 \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
|
|
19908
|
-
const nameLen = view.getUint16(e.localOffset + 26, true);
|
|
19909
|
-
const extraLen = view.getUint16(e.localOffset + 28, true);
|
|
19910
|
-
const headerLen = 30 + nameLen + extraLen;
|
|
19911
|
-
const header = copyBytes(original, e.localOffset, e.localOffset + headerLen);
|
|
19912
|
-
const hview = new DataView(header.buffer, header.byteOffset, header.byteLength);
|
|
19913
|
-
const method = e.method;
|
|
19914
|
-
const compData = method === 0 ? newData : new Uint8Array(deflateRawSync(newData));
|
|
19915
|
-
const crc = crc32(newData);
|
|
19916
|
-
const flags = e.flags & ~8;
|
|
19917
|
-
hview.setUint16(6, flags, true);
|
|
19918
|
-
hview.setUint32(14, crc, true);
|
|
19919
|
-
hview.setUint32(18, compData.length, true);
|
|
19920
|
-
hview.setUint32(22, newData.length, true);
|
|
19921
|
-
segments.push(header, compData);
|
|
19922
|
-
offset += headerLen + compData.length;
|
|
19923
|
-
newMeta.set(e, { crc, compSize: compData.length, uncompSize: newData.length, flags });
|
|
19924
|
-
}
|
|
19925
|
-
const newCdOffset = offset;
|
|
19926
|
-
for (const e of entries) {
|
|
19927
|
-
const cd = copyBytes(original, e.cdStart, e.cdEnd);
|
|
19928
|
-
const cview = new DataView(cd.buffer, cd.byteOffset, cd.byteLength);
|
|
19929
|
-
cview.setUint32(42, newLocalOffset.get(e), true);
|
|
19930
|
-
const meta = newMeta.get(e);
|
|
19931
|
-
if (meta) {
|
|
19932
|
-
cview.setUint16(8, meta.flags, true);
|
|
19933
|
-
cview.setUint32(16, meta.crc, true);
|
|
19934
|
-
cview.setUint32(20, meta.compSize, true);
|
|
19935
|
-
cview.setUint32(24, meta.uncompSize, true);
|
|
19936
|
-
}
|
|
19937
|
-
segments.push(cd);
|
|
19938
|
-
offset += cd.length;
|
|
19939
|
-
}
|
|
19940
|
-
const newCdSize = offset - newCdOffset;
|
|
19941
|
-
const eocd = copyBytes(original, eocdOffset);
|
|
19942
|
-
const eview = new DataView(eocd.buffer, eocd.byteOffset, eocd.byteLength);
|
|
19943
|
-
eview.setUint32(12, newCdSize, true);
|
|
19944
|
-
eview.setUint32(16, newCdOffset, true);
|
|
19945
|
-
segments.push(eocd);
|
|
19946
|
-
offset += eocd.length;
|
|
19947
|
-
const result = new Uint8Array(offset);
|
|
19948
|
-
let pos = 0;
|
|
19949
|
-
for (const seg of segments) {
|
|
19950
|
-
result.set(seg, pos);
|
|
19951
|
-
pos += seg.length;
|
|
19952
|
-
}
|
|
19953
|
-
return result;
|
|
19954
|
-
}
|
|
19955
|
-
|
|
19956
|
-
// src/form/filler-hwpx.ts
|
|
19957
|
-
async function fillHwpx(hwpxBuffer, values) {
|
|
19336
|
+
async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
19958
19337
|
const u8 = new Uint8Array(hwpxBuffer);
|
|
19959
19338
|
const zip = await JSZip5.loadAsync(hwpxBuffer);
|
|
19960
19339
|
const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
|
|
@@ -19998,7 +19377,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
19998
19377
|
for (const cell of row) {
|
|
19999
19378
|
for (const para of cell.paragraphs) {
|
|
20000
19379
|
const text = matchText(para);
|
|
20001
|
-
const result = fillInCellPatterns(text, cursor, matchedLabels);
|
|
19380
|
+
const result = fillInCellPatterns(text, cursor, matchedLabels, blockedLabels);
|
|
20002
19381
|
if (!result) continue;
|
|
20003
19382
|
const l = led(para);
|
|
20004
19383
|
if (l.fullText !== void 0) continue;
|
|
@@ -20016,7 +19395,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20016
19395
|
for (const m of result.matches) {
|
|
20017
19396
|
l.filledIdx.push(filled.length);
|
|
20018
19397
|
l.matchKeys.push(m.key);
|
|
20019
|
-
filled.push({ label: m.label, value: m.value, row: -1, col: -1 });
|
|
19398
|
+
filled.push({ label: m.label, value: m.value, row: -1, col: -1, key: m.key });
|
|
20020
19399
|
}
|
|
20021
19400
|
}
|
|
20022
19401
|
}
|
|
@@ -20032,6 +19411,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20032
19411
|
if (isKeywordLabel(cellLabelText(valueCell))) continue;
|
|
20033
19412
|
const normalizedCellLabel = normalizeLabel(labelText);
|
|
20034
19413
|
if (!normalizedCellLabel) continue;
|
|
19414
|
+
if (blockedLabels?.has(normalizedCellLabel)) continue;
|
|
20035
19415
|
const matchKey = findMatchingKey(normalizedCellLabel, cursor);
|
|
20036
19416
|
if (matchKey === void 0) continue;
|
|
20037
19417
|
if (patternApplied.has(valueCell)) {
|
|
@@ -20049,7 +19429,8 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20049
19429
|
label: labelText.trim().replace(/[::]\s*$/, ""),
|
|
20050
19430
|
value: newValue,
|
|
20051
19431
|
row: rowIdx,
|
|
20052
|
-
col: colIdx
|
|
19432
|
+
col: colIdx,
|
|
19433
|
+
key: matchKey
|
|
20053
19434
|
});
|
|
20054
19435
|
} else {
|
|
20055
19436
|
const paras = valueCell.paragraphs;
|
|
@@ -20071,7 +19452,8 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20071
19452
|
label: labelText.trim().replace(/[::]\s*$/, ""),
|
|
20072
19453
|
value: newValue,
|
|
20073
19454
|
row: rowIdx,
|
|
20074
|
-
col: colIdx
|
|
19455
|
+
col: colIdx,
|
|
19456
|
+
key: matchKey
|
|
20075
19457
|
});
|
|
20076
19458
|
}
|
|
20077
19459
|
}
|
|
@@ -20087,6 +19469,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20087
19469
|
const dataCells = table.rows[rowIdx];
|
|
20088
19470
|
for (let colIdx = 0; colIdx < Math.min(headerCells.length, dataCells.length); colIdx++) {
|
|
20089
19471
|
const headerLabel = normalizeLabel(cellLabelText(headerCells[colIdx]));
|
|
19472
|
+
if (blockedLabels?.has(headerLabel)) continue;
|
|
20090
19473
|
const matchKey = findMatchingKey(headerLabel, cursor);
|
|
20091
19474
|
if (matchKey === void 0) continue;
|
|
20092
19475
|
if (!cursor.isArray(matchKey) && matchedLabels.has(matchKey)) continue;
|
|
@@ -20122,7 +19505,9 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20122
19505
|
if (existing?.fullText !== void 0) continue;
|
|
20123
19506
|
const text = matchText(para);
|
|
20124
19507
|
for (const seg of scanInlineSegments(text)) {
|
|
20125
|
-
const
|
|
19508
|
+
const nlabel = normalizeLabel(seg.label);
|
|
19509
|
+
if (blockedLabels?.has(nlabel)) continue;
|
|
19510
|
+
const matchKey = findMatchingKey(nlabel, cursor);
|
|
20126
19511
|
if (matchKey === void 0) continue;
|
|
20127
19512
|
const newValue = cursor.consume(matchKey);
|
|
20128
19513
|
if (newValue === void 0) continue;
|
|
@@ -20132,7 +19517,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20132
19517
|
matchedLabels.add(matchKey);
|
|
20133
19518
|
l.filledIdx.push(filled.length);
|
|
20134
19519
|
l.matchKeys.push(matchKey);
|
|
20135
|
-
filled.push({ label: seg.label.trim(), value: newValue, row: -1, col: -1 });
|
|
19520
|
+
filled.push({ label: seg.label.trim(), value: newValue, row: -1, col: -1, key: matchKey });
|
|
20136
19521
|
}
|
|
20137
19522
|
}
|
|
20138
19523
|
const splices = [];
|
|
@@ -20426,7 +19811,8 @@ function buildPrvText(blocks) {
|
|
|
20426
19811
|
let bytes = 0;
|
|
20427
19812
|
for (const b of blocks) {
|
|
20428
19813
|
let text = b.text || (b.rows ? b.rows.map((r) => r.join(" ")).join("\n") : "");
|
|
20429
|
-
if (b.type === "
|
|
19814
|
+
if (b.type === "code_block" && (b.lang || "").toLowerCase() === "chart") text = "[\uCC28\uD2B8]";
|
|
19815
|
+
else if (b.type === "html_table") text = text.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
20430
19816
|
if (!text) continue;
|
|
20431
19817
|
lines.push(text);
|
|
20432
19818
|
bytes += text.length * 3;
|
|
@@ -20445,7 +19831,7 @@ function findMathDelim(s, from) {
|
|
|
20445
19831
|
return i;
|
|
20446
19832
|
}
|
|
20447
19833
|
function parseMarkdownToBlocks(md2) {
|
|
20448
|
-
const lines = md2.split("\n");
|
|
19834
|
+
const lines = md2.replace(/\r\n?/g, "\n").split("\n");
|
|
20449
19835
|
const blocks = [];
|
|
20450
19836
|
let i = 0;
|
|
20451
19837
|
while (i < lines.length) {
|
|
@@ -20493,13 +19879,13 @@ function parseMarkdownToBlocks(md2) {
|
|
|
20493
19879
|
continue;
|
|
20494
19880
|
}
|
|
20495
19881
|
}
|
|
20496
|
-
const fenceMatch = line.match(/^(`{3,}|~{3,})(.*)$/);
|
|
19882
|
+
const fenceMatch = line.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
|
|
20497
19883
|
if (fenceMatch) {
|
|
20498
19884
|
const fence = fenceMatch[1];
|
|
20499
19885
|
const lang = fenceMatch[2].trim();
|
|
20500
19886
|
const codeLines = [];
|
|
20501
19887
|
i++;
|
|
20502
|
-
while (i < lines.length && !lines[i].startsWith(fence)) {
|
|
19888
|
+
while (i < lines.length && !lines[i].replace(/^ {0,3}/, "").startsWith(fence)) {
|
|
20503
19889
|
codeLines.push(lines[i]);
|
|
20504
19890
|
i++;
|
|
20505
19891
|
}
|
|
@@ -20647,12 +20033,14 @@ function generateContainerXml() {
|
|
|
20647
20033
|
</ocf:rootfiles>
|
|
20648
20034
|
</ocf:container>`;
|
|
20649
20035
|
}
|
|
20650
|
-
function generateManifest() {
|
|
20036
|
+
function generateManifest(chartParts = []) {
|
|
20037
|
+
const chartItems = chartParts.map((p, i) => `
|
|
20038
|
+
<opf:item id="chart${i + 1}" href="${p.name}" media-type="application/xml"/>`).join("");
|
|
20651
20039
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
|
20652
20040
|
<opf:package xmlns:opf="${NS_OPF}" xmlns:hpf="${NS_HPF}" xmlns:hh="${NS_HEAD}">
|
|
20653
20041
|
<opf:manifest>
|
|
20654
20042
|
<opf:item id="header" href="Contents/header.xml" media-type="application/xml"/>
|
|
20655
|
-
<opf:item id="section0" href="Contents/section0.xml" media-type="application/xml"
|
|
20043
|
+
<opf:item id="section0" href="Contents/section0.xml" media-type="application/xml"/>${chartItems}
|
|
20656
20044
|
</opf:manifest>
|
|
20657
20045
|
<opf:spine>
|
|
20658
20046
|
<opf:itemref idref="header" linear="no"/>
|
|
@@ -20833,6 +20221,219 @@ function generateHeaderXml(theme, gongmun, ratioVariants = []) {
|
|
|
20833
20221
|
</hh:head>`;
|
|
20834
20222
|
}
|
|
20835
20223
|
|
|
20224
|
+
// src/hwpx/chart-gen.ts
|
|
20225
|
+
var XML_ESC = { "&": "&", "<": "<", ">": ">" };
|
|
20226
|
+
var xmlEscape = (s) => s.replace(/[&<>]/g, (c) => XML_ESC[c]);
|
|
20227
|
+
var CHART_TYPES = {
|
|
20228
|
+
0: { el: "barChart", dir: "col", grp: "clustered" },
|
|
20229
|
+
1: { el: "barChart", dir: "col", grp: "stacked", overlap: 100 },
|
|
20230
|
+
2: { el: "lineChart", grp: "standard", marker: true },
|
|
20231
|
+
3: { el: "barChart", dir: "bar", grp: "clustered" },
|
|
20232
|
+
4: { el: "barChart", dir: "bar", grp: "stacked", overlap: 100 },
|
|
20233
|
+
5: { el: "scatterChart", scatter: true },
|
|
20234
|
+
6: { el: "pieChart", pie: true },
|
|
20235
|
+
7: { el: "pieChart", pie: true, explode: true },
|
|
20236
|
+
8: { el: "doughnutChart", pie: true, hole: 50 },
|
|
20237
|
+
9: { el: "areaChart", grp: "standard" },
|
|
20238
|
+
10: { el: "areaChart", grp: "stacked" },
|
|
20239
|
+
11: { el: "radarChart", radar: true },
|
|
20240
|
+
12: { el: "bar3DChart", dir: "col", grp: "clustered" },
|
|
20241
|
+
13: { el: "bar3DChart", dir: "col", grp: "stacked", overlap: 100 },
|
|
20242
|
+
14: { el: "bar3DChart", dir: "bar", grp: "clustered" },
|
|
20243
|
+
15: { el: "bar3DChart", dir: "bar", grp: "stacked", overlap: 100 },
|
|
20244
|
+
16: { el: "pie3DChart", pie: true },
|
|
20245
|
+
17: { el: "pie3DChart", pie: true, explode: true },
|
|
20246
|
+
18: { el: "area3DChart", grp: "standard" },
|
|
20247
|
+
19: { el: "area3DChart", grp: "stacked" }
|
|
20248
|
+
};
|
|
20249
|
+
var CHART_ALIAS = {
|
|
20250
|
+
column: 0,
|
|
20251
|
+
col: 0,
|
|
20252
|
+
\uC138\uB85C\uB9C9\uB300: 0,
|
|
20253
|
+
\uB9C9\uB300: 0,
|
|
20254
|
+
column_stacked: 1,
|
|
20255
|
+
\uC138\uB85C\uB9C9\uB300_\uB204\uC801: 1,
|
|
20256
|
+
line: 2,
|
|
20257
|
+
\uC120: 2,
|
|
20258
|
+
\uAEBE\uC740\uC120: 2,
|
|
20259
|
+
bar: 3,
|
|
20260
|
+
\uAC00\uB85C\uB9C9\uB300: 3,
|
|
20261
|
+
bar_stacked: 4,
|
|
20262
|
+
scatter: 5,
|
|
20263
|
+
\uBD84\uC0B0: 5,
|
|
20264
|
+
pie: 6,
|
|
20265
|
+
\uC6D0: 6,
|
|
20266
|
+
\uD30C\uC774: 6,
|
|
20267
|
+
pie_explode: 7,
|
|
20268
|
+
doughnut: 8,
|
|
20269
|
+
donut: 8,
|
|
20270
|
+
\uB3C4\uB11B: 8,
|
|
20271
|
+
area: 9,
|
|
20272
|
+
\uC601\uC5ED: 9,
|
|
20273
|
+
area_stacked: 10,
|
|
20274
|
+
radar: 11,
|
|
20275
|
+
\uBC29\uC0AC\uD615: 11,
|
|
20276
|
+
bar3d: 12,
|
|
20277
|
+
column3d: 12,
|
|
20278
|
+
pie3d: 16
|
|
20279
|
+
};
|
|
20280
|
+
function chartSpec(t) {
|
|
20281
|
+
if (!t) return CHART_TYPES[0];
|
|
20282
|
+
const key = CHART_ALIAS[t.toLowerCase()] ?? Number(t);
|
|
20283
|
+
return CHART_TYPES[key] ?? CHART_TYPES[0];
|
|
20284
|
+
}
|
|
20285
|
+
var HU_PER_MM = 7200 / 25.4;
|
|
20286
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set(["type", "cat", "size", "colors", "point_colors", "title"]);
|
|
20287
|
+
function parseChartFence(text) {
|
|
20288
|
+
let type;
|
|
20289
|
+
let cat = null;
|
|
20290
|
+
let widthMm = 32250 / HU_PER_MM;
|
|
20291
|
+
let heightMm = 18750 / HU_PER_MM;
|
|
20292
|
+
let colors = null;
|
|
20293
|
+
let pointColors = null;
|
|
20294
|
+
const series = [];
|
|
20295
|
+
for (const rawLine of text.split("\n")) {
|
|
20296
|
+
const line = rawLine.trim();
|
|
20297
|
+
if (!line || line.startsWith("#")) continue;
|
|
20298
|
+
const colon = line.search(/[::]/);
|
|
20299
|
+
if (colon <= 0) continue;
|
|
20300
|
+
const key = line.slice(0, colon).trim();
|
|
20301
|
+
const value = line.slice(colon + 1).trim();
|
|
20302
|
+
const keyLower = key.toLowerCase();
|
|
20303
|
+
if (keyLower === "type") {
|
|
20304
|
+
type = value;
|
|
20305
|
+
} else if (keyLower === "cat") {
|
|
20306
|
+
cat = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
20307
|
+
} else if (keyLower === "size") {
|
|
20308
|
+
const m = value.match(/^(\d+(?:\.\d+)?)\s*[x×]\s*(\d+(?:\.\d+)?)$/i);
|
|
20309
|
+
if (m) {
|
|
20310
|
+
const clamp = (n) => Math.min(500, Math.max(10, n));
|
|
20311
|
+
widthMm = clamp(Number(m[1]));
|
|
20312
|
+
heightMm = clamp(Number(m[2]));
|
|
20313
|
+
}
|
|
20314
|
+
} else if (keyLower === "colors") {
|
|
20315
|
+
colors = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
20316
|
+
} else if (keyLower === "point_colors") {
|
|
20317
|
+
pointColors = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
20318
|
+
} else if (keyLower === "title") {
|
|
20319
|
+
} else if (!RESERVED_KEYS.has(keyLower)) {
|
|
20320
|
+
const segs = value.replace(/(\d),(?=\d{3}(?:\D|$))/g, "$1").split(",").map((s) => s.trim()).filter(Boolean);
|
|
20321
|
+
if (segs.length === 0) continue;
|
|
20322
|
+
const nums = segs.map(Number);
|
|
20323
|
+
if (nums.every((n) => Number.isFinite(n))) {
|
|
20324
|
+
series.push({ name: key, values: nums });
|
|
20325
|
+
} else {
|
|
20326
|
+
return null;
|
|
20327
|
+
}
|
|
20328
|
+
}
|
|
20329
|
+
}
|
|
20330
|
+
if (series.length === 0) return null;
|
|
20331
|
+
const spec = chartSpec(type);
|
|
20332
|
+
let finalSeries = spec.pie ? [series[0]] : series;
|
|
20333
|
+
finalSeries = finalSeries.map((s) => ({ ...s }));
|
|
20334
|
+
const ptLen = Math.max(cat?.length ?? 0, ...finalSeries.map((s) => s.values.length));
|
|
20335
|
+
const catFinal = Array.from({ length: ptLen }, (_, i) => cat?.[i] ?? `\uD56D\uBAA9 ${i + 1}`);
|
|
20336
|
+
if (!spec.scatter) {
|
|
20337
|
+
finalSeries = finalSeries.map((s) => ({ ...s, values: catFinal.map((_, i) => s.values[i] ?? 0) }));
|
|
20338
|
+
}
|
|
20339
|
+
if (spec.pie) {
|
|
20340
|
+
const slice = colors ?? pointColors;
|
|
20341
|
+
if (slice) finalSeries[0].pointColors = slice;
|
|
20342
|
+
} else {
|
|
20343
|
+
if (colors) finalSeries.forEach((s, i) => {
|
|
20344
|
+
s.color = colors[i % colors.length];
|
|
20345
|
+
});
|
|
20346
|
+
if (pointColors && finalSeries[0]) finalSeries[0].pointColors = pointColors;
|
|
20347
|
+
}
|
|
20348
|
+
return {
|
|
20349
|
+
spec,
|
|
20350
|
+
cat: catFinal,
|
|
20351
|
+
series: finalSeries,
|
|
20352
|
+
widthHu: Math.round(widthMm * HU_PER_MM),
|
|
20353
|
+
heightHu: Math.round(heightMm * HU_PER_MM)
|
|
20354
|
+
};
|
|
20355
|
+
}
|
|
20356
|
+
var colLetter = (i) => String.fromCharCode(66 + i);
|
|
20357
|
+
function strCachePts(vals) {
|
|
20358
|
+
return `<c:ptCount val="${vals.length}"/>` + vals.map((v, i) => `<c:pt idx="${i}"><c:v>${xmlEscape(v)}</c:v></c:pt>`).join("");
|
|
20359
|
+
}
|
|
20360
|
+
function numCachePts(vals) {
|
|
20361
|
+
return `<c:formatCode>General</c:formatCode><c:ptCount val="${vals.length}"/>` + vals.map((v, i) => `<c:pt idx="${i}"><c:v>${Number(v) || 0}</c:v></c:pt>`).join("");
|
|
20362
|
+
}
|
|
20363
|
+
function chartColorFill(color) {
|
|
20364
|
+
if (color == null) return null;
|
|
20365
|
+
const c = color.trim();
|
|
20366
|
+
if (/^accent[1-6]$/i.test(c)) return `<a:solidFill><a:schemeClr val="${c.toLowerCase()}"/></a:solidFill>`;
|
|
20367
|
+
const hex = c.replace(/^#/, "").toUpperCase();
|
|
20368
|
+
if (/^[0-9A-F]{6}$/.test(hex)) return `<a:solidFill><a:srgbClr val="${hex}"/></a:solidFill>`;
|
|
20369
|
+
return null;
|
|
20370
|
+
}
|
|
20371
|
+
function serSpPr(color, stroke) {
|
|
20372
|
+
const f = chartColorFill(color);
|
|
20373
|
+
if (!f) return "<c:spPr/>";
|
|
20374
|
+
return stroke ? `<c:spPr><a:ln w="28575" cap="flat" cmpd="sng" algn="ctr">${f}<a:prstDash val="solid"/><a:round/></a:ln></c:spPr>` : `<c:spPr>${f}</c:spPr>`;
|
|
20375
|
+
}
|
|
20376
|
+
function dPtXml(pointColors, pie) {
|
|
20377
|
+
if (!pointColors?.length) return "";
|
|
20378
|
+
return pointColors.map((col, i) => {
|
|
20379
|
+
const f = chartColorFill(col);
|
|
20380
|
+
if (!f) return "";
|
|
20381
|
+
const mid = pie ? '<c:invertIfNegative val="0"/><c:bubble3D val="0"/><c:explosion val="0"/>' : '<c:bubble3D val="0"/>';
|
|
20382
|
+
return `<c:dPt><c:idx val="${i}"/>${mid}<c:spPr>${f}</c:spPr></c:dPt>`;
|
|
20383
|
+
}).join("");
|
|
20384
|
+
}
|
|
20385
|
+
function stdSer(idx, name, cat, values, explode, color, pointColors, stroke, pie) {
|
|
20386
|
+
const cl = colLetter(idx);
|
|
20387
|
+
return `<c:ser><c:idx val="${idx}"/><c:order val="${idx}"/><c:tx><c:strRef><c:f>Sheet1!$${cl}$1</c:f><c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>${xmlEscape(name)}</c:v></c:pt></c:strCache></c:strRef></c:tx>${serSpPr(color, stroke)}<c:invertIfNegative val="0"/>` + (explode ? `<c:explosion val="25"/>` : "") + dPtXml(pointColors, pie) + `<c:cat><c:strRef><c:f>Sheet1!$A$2:$A$${cat.length + 1}</c:f><c:strCache>${strCachePts(cat)}</c:strCache></c:strRef></c:cat><c:val><c:numRef><c:f>Sheet1!$${cl}$2:$${cl}$${values.length + 1}</c:f><c:numCache>${numCachePts(values)}</c:numCache></c:numRef></c:val></c:ser>`;
|
|
20388
|
+
}
|
|
20389
|
+
function scatterSer(idx, name, xvals, yvals) {
|
|
20390
|
+
const cl = colLetter(idx);
|
|
20391
|
+
return `<c:ser><c:idx val="${idx}"/><c:order val="${idx}"/><c:tx><c:strRef><c:f>Sheet1!$${cl}$1</c:f><c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>${xmlEscape(name)}</c:v></c:pt></c:strCache></c:strRef></c:tx><c:spPr><a:ln w="28575"><a:noFill/></a:ln></c:spPr><c:marker><c:symbol val="circle"/><c:size val="7"/></c:marker><c:xVal><c:numRef><c:f>Sheet1!$A$2:$A$${xvals.length + 1}</c:f><c:numCache>${numCachePts(xvals)}</c:numCache></c:numRef></c:xVal><c:yVal><c:numRef><c:f>Sheet1!$${cl}$2:$${cl}$${yvals.length + 1}</c:f><c:numCache>${numCachePts(yvals)}</c:numCache></c:numRef></c:yVal></c:ser>`;
|
|
20392
|
+
}
|
|
20393
|
+
function catAxXml(id, pos, cross) {
|
|
20394
|
+
return `<c:catAx><c:axId val="${id}"/><c:scaling><c:orientation val="minMax"/></c:scaling><c:axPos val="${pos}"/><c:crossAx val="${cross}"/><c:delete val="0"/><c:majorTickMark val="out"/><c:minorTickMark val="none"/><c:tickLblPos val="nextTo"/><c:crosses val="autoZero"/><c:auto val="1"/><c:lblAlgn val="ctr"/><c:lblOffset val="100"/><c:noMultiLvlLbl val="0"/></c:catAx>`;
|
|
20395
|
+
}
|
|
20396
|
+
function valAxXml(id, pos, cross) {
|
|
20397
|
+
return `<c:valAx><c:axId val="${id}"/><c:scaling><c:orientation val="minMax"/></c:scaling><c:axPos val="${pos}"/><c:majorGridlines/><c:numFmt formatCode="General" sourceLinked="1"/><c:crossAx val="${cross}"/><c:delete val="0"/><c:majorTickMark val="out"/><c:minorTickMark val="none"/><c:tickLblPos val="nextTo"/><c:crosses val="autoZero"/><c:crossBetween val="between"/></c:valAx>`;
|
|
20398
|
+
}
|
|
20399
|
+
function buildChartSpaceXml(fence) {
|
|
20400
|
+
const { spec, cat, series } = fence;
|
|
20401
|
+
const NS = 'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart"';
|
|
20402
|
+
const ax1 = "111111111";
|
|
20403
|
+
const ax2 = "222222222";
|
|
20404
|
+
let plot;
|
|
20405
|
+
if (spec.scatter) {
|
|
20406
|
+
const n = Math.max(0, ...series.map((s) => s.values.length));
|
|
20407
|
+
const xs = Array.from({ length: n }, (_, i) => {
|
|
20408
|
+
const c = cat[i];
|
|
20409
|
+
const v = Number(c);
|
|
20410
|
+
return c !== void 0 && c !== "" && Number.isFinite(v) ? v : i + 1;
|
|
20411
|
+
});
|
|
20412
|
+
const sers = series.map((s, i) => scatterSer(i, s.name, xs, s.values)).join("");
|
|
20413
|
+
plot = `<c:scatterChart><c:scatterStyle val="lineMarker"/><c:varyColors val="0"/>${sers}<c:axId val="${ax1}"/><c:axId val="${ax2}"/></c:scatterChart>` + valAxXml(ax1, "b", ax2) + valAxXml(ax2, "l", ax1);
|
|
20414
|
+
} else if (spec.pie) {
|
|
20415
|
+
const s0 = series[0];
|
|
20416
|
+
plot = `<c:${spec.el}><c:varyColors val="1"/>${stdSer(0, s0.name, cat, s0.values, !!spec.explode, s0.color, s0.pointColors, false, true)}<c:firstSliceAng val="0"/>` + (spec.hole != null ? `<c:holeSize val="${spec.hole}"/>` : "") + `</c:${spec.el}>`;
|
|
20417
|
+
} else {
|
|
20418
|
+
const stroke = spec.el === "lineChart" || spec.el === "radarChart" || !!spec.radar;
|
|
20419
|
+
const sers = series.map((s, i) => stdSer(i, s.name, cat, s.values, false, s.color, s.pointColors, stroke, false)).join("");
|
|
20420
|
+
const horiz = spec.dir === "bar";
|
|
20421
|
+
let inner = "";
|
|
20422
|
+
if (spec.dir) inner += `<c:barDir val="${spec.dir}"/>`;
|
|
20423
|
+
if (spec.grp) inner += `<c:grouping val="${spec.grp}"/>`;
|
|
20424
|
+
if (spec.radar) inner += `<c:radarStyle val="standard"/>`;
|
|
20425
|
+
inner += `<c:varyColors val="0"/>${sers}`;
|
|
20426
|
+
if (spec.marker) inner += `<c:marker val="1"/>`;
|
|
20427
|
+
if (spec.el.startsWith("bar")) inner += `<c:gapWidth val="150"/><c:overlap val="${spec.overlap ?? 0}"/>`;
|
|
20428
|
+
inner += `<c:axId val="${ax1}"/><c:axId val="${ax2}"/>`;
|
|
20429
|
+
plot = `<c:${spec.el}>${inner}</c:${spec.el}>` + catAxXml(ax1, horiz ? "l" : "b", ax2) + valAxXml(ax2, horiz ? "b" : "l", ax1);
|
|
20430
|
+
}
|
|
20431
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><c:chartSpace ${NS}><c:date1904 val="0"/><c:roundedCorners val="0"/><c:chart><c:autoTitleDeleted val="0"/><c:plotArea><c:layout/>${plot}</c:plotArea><c:legend><c:legendPos val="r"/><c:overlay val="0"/></c:legend><c:plotVisOnly val="1"/><c:dispBlanksAs val="gap"/></c:chart></c:chartSpace>`;
|
|
20432
|
+
}
|
|
20433
|
+
function buildChartElementXml(partName, widthHu, heightHu, id) {
|
|
20434
|
+
return `<hp:chart id="${id}" zOrder="0" numberingType="PICTURE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" chartIDRef="${partName}"><hp:sz width="${widthHu}" widthRelTo="ABSOLUTE" height="${heightHu}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="1" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="709" right="709" top="709" bottom="709"/></hp:chart>`;
|
|
20435
|
+
}
|
|
20436
|
+
|
|
20836
20437
|
// src/hwpx/gen-gongmun-fit.ts
|
|
20837
20438
|
function plainRenderText(text) {
|
|
20838
20439
|
return parseInlineMarkdown(text).map((s) => s.text).join("");
|
|
@@ -20885,18 +20486,18 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
20885
20486
|
i++;
|
|
20886
20487
|
continue;
|
|
20887
20488
|
}
|
|
20888
|
-
const passThrough = (
|
|
20489
|
+
const passThrough = (b) => b.type === "table" || b.type === "html_table" || b.type === "equation" || b.type === "code_block" && (b.lang || "").toLowerCase() === "chart" && parseChartFence(b.text || "") !== null;
|
|
20889
20490
|
const run = [];
|
|
20890
20491
|
while (i < blocks.length) {
|
|
20891
|
-
const
|
|
20892
|
-
if (
|
|
20492
|
+
const b = blocks[i];
|
|
20493
|
+
if (b.type === "list_item") {
|
|
20893
20494
|
run.push(i);
|
|
20894
20495
|
i++;
|
|
20895
20496
|
continue;
|
|
20896
20497
|
}
|
|
20897
|
-
if (passThrough(
|
|
20498
|
+
if (passThrough(b)) {
|
|
20898
20499
|
let j = i + 1;
|
|
20899
|
-
while (j < blocks.length && passThrough(blocks[j]
|
|
20500
|
+
while (j < blocks.length && passThrough(blocks[j])) j++;
|
|
20900
20501
|
if (j < blocks.length && blocks[j].type === "list_item") {
|
|
20901
20502
|
i = j;
|
|
20902
20503
|
continue;
|
|
@@ -21711,7 +21312,7 @@ function generateSecPr(gongmun) {
|
|
|
21711
21312
|
} : { top: 8504, bottom: 4252, left: 5670, right: 4252, header: 2835, footer: 2835 };
|
|
21712
21313
|
return `<hp:secPr textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="1" memoShapeIDRef="0" textVerticalWidthHead="0" masterPageCnt="0"><hp:grid lineGrid="0" charGrid="0" wonggojiFormat="0"/><hp:startNum pageStartsOn="BOTH" page="0" pic="0" tbl="0" equation="0"/><hp:visibility hideFirstHeader="0" hideFirstFooter="0" hideFirstMasterPage="0" border="SHOW_ALL" fill="SHOW_ALL" hideFirstPageNum="0" hideFirstEmptyLine="0" showLineNumber="0"/><hp:pagePr landscape="WIDELY" width="59528" height="84188" gutterType="LEFT_ONLY"><hp:margin header="${m.header}" footer="${m.footer}" gutter="0" left="${m.left}" right="${m.right}" top="${m.top}" bottom="${m.bottom}"/></hp:pagePr><hp:footNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="-1" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="283" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="EACH_COLUMN" beneathText="0"/></hp:footNotePr><hp:endNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="14692344" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="0" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="END_OF_DOCUMENT" beneathText="0"/></hp:endNotePr></hp:secPr>`;
|
|
21713
21314
|
}
|
|
21714
|
-
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null) {
|
|
21315
|
+
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null) {
|
|
21715
21316
|
const paraXmls = [];
|
|
21716
21317
|
let isFirst = true;
|
|
21717
21318
|
const orderedCounters = {};
|
|
@@ -21742,6 +21343,21 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21742
21343
|
break;
|
|
21743
21344
|
}
|
|
21744
21345
|
case "code_block": {
|
|
21346
|
+
if (chartParts !== null && (block.lang || "").toLowerCase() === "chart") {
|
|
21347
|
+
const fence = parseChartFence(block.text || "");
|
|
21348
|
+
if (fence) {
|
|
21349
|
+
const partName = `Chart/chart${chartParts.length + 1}.xml`;
|
|
21350
|
+
chartParts.push({ name: partName, xml: buildChartSpaceXml(fence) });
|
|
21351
|
+
const chartEl = buildChartElementXml(partName, fence.widthHu, fence.heightHu, 91e5 + blockIdx);
|
|
21352
|
+
if (isFirst) {
|
|
21353
|
+
const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
|
|
21354
|
+
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
21355
|
+
isFirst = false;
|
|
21356
|
+
}
|
|
21357
|
+
xml = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${chartEl}</hp:run></hp:p>`;
|
|
21358
|
+
break;
|
|
21359
|
+
}
|
|
21360
|
+
}
|
|
21745
21361
|
const codeLines = (block.text || "").split("\n");
|
|
21746
21362
|
xml = codeLines.map((line) => generateParagraph(line || " ", PARA_CODE)).join("\n ");
|
|
21747
21363
|
break;
|
|
@@ -21851,13 +21467,15 @@ async function markdownToHwpx(markdown, options) {
|
|
|
21851
21467
|
const blocks = parseMarkdownToBlocks(markdown);
|
|
21852
21468
|
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
21853
21469
|
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
21854
|
-
const
|
|
21470
|
+
const chartParts = [];
|
|
21471
|
+
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts);
|
|
21855
21472
|
const zip = new JSZip6();
|
|
21856
21473
|
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
21857
21474
|
zip.file("META-INF/container.xml", generateContainerXml());
|
|
21858
|
-
zip.file("Contents/content.hpf", generateManifest());
|
|
21475
|
+
zip.file("Contents/content.hpf", generateManifest(chartParts));
|
|
21859
21476
|
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? []));
|
|
21860
21477
|
zip.file("Contents/section0.xml", sectionXml);
|
|
21478
|
+
for (const part of chartParts) zip.file(part.name, part.xml);
|
|
21861
21479
|
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
21862
21480
|
return await zip.generateAsync({ type: "arraybuffer" });
|
|
21863
21481
|
}
|
|
@@ -22976,7 +22594,7 @@ async function resolveHeaderEntryName(zip) {
|
|
|
22976
22594
|
}
|
|
22977
22595
|
|
|
22978
22596
|
// src/roundtrip/hwp5-patch.ts
|
|
22979
|
-
import { deflateRawSync
|
|
22597
|
+
import { deflateRawSync } from "zlib";
|
|
22980
22598
|
import { createRequire as createRequire2 } from "module";
|
|
22981
22599
|
|
|
22982
22600
|
// src/roundtrip/ole-surgeon.ts
|
|
@@ -23491,7 +23109,7 @@ async function patchHwp(original, editedMarkdown, options) {
|
|
|
23491
23109
|
for (let i = 0; i < scans.length; i++) {
|
|
23492
23110
|
if (scans[i].repl.size === 0 && scans[i].inserts.size === 0) continue;
|
|
23493
23111
|
const newStream = serializeRecords(scans[i].records, scans[i].repl, scans[i].inserts);
|
|
23494
|
-
const content = compressed ?
|
|
23112
|
+
const content = compressed ? deflateRawSync(newStream) : newStream;
|
|
23495
23113
|
out = replaceOleStream(out, sectionPaths[i], content);
|
|
23496
23114
|
}
|
|
23497
23115
|
data = new Uint8Array(out);
|
|
@@ -23503,7 +23121,8 @@ async function patchHwp(original, editedMarkdown, options) {
|
|
|
23503
23121
|
if (options?.verify !== false) {
|
|
23504
23122
|
try {
|
|
23505
23123
|
const reparsed = parseHwp5Document(Buffer.from(data));
|
|
23506
|
-
|
|
23124
|
+
const normBr = (u) => ({ ...u, raw: u.raw.replace(/<br\s*\/?\s*>/gi, "\n") });
|
|
23125
|
+
verification = diffUnitLists(splitMarkdownUnits(reparsed.markdown).map(normBr), editedUnits.map(normBr));
|
|
23507
23126
|
} catch (err) {
|
|
23508
23127
|
return { success: false, applied, skipped, error: `\uD328\uCE58\uBCF8 \uC7AC\uD30C\uC2F1 \uC2E4\uD328 \u2014 \uD328\uCE58 \uC911\uB2E8: ${msg(err)}` };
|
|
23509
23128
|
}
|
|
@@ -23626,7 +23245,7 @@ function handleModified(orig, edited, ctx) {
|
|
|
23626
23245
|
function patchParagraph(block, orig, edited, ctx, skip) {
|
|
23627
23246
|
const mapping = ctx.paraMap.get(orig.blockIdx);
|
|
23628
23247
|
if (!mapping?.para) return skip("\uBB38\uB2E8 \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328 (\uBA38\uB9AC\uB9D0/\uAE00\uC0C1\uC790/\uCEA1\uC158 \uC601\uC5ED\uC774\uAC70\uB098 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58)");
|
|
23629
|
-
const restoreBr = (s) => s.replace(
|
|
23248
|
+
const restoreBr = (s) => s.replace(/(?:\s*<br\s*\/?\s*>\s*)+/gi, "\n");
|
|
23630
23249
|
let newPlain = restoreBr(textUnitToPlain(edited.raw, block));
|
|
23631
23250
|
if (block.text && block.text.includes("\n") && !newPlain.includes("\n")) {
|
|
23632
23251
|
return skip("\uB2E4\uC911\uC904 \uBB38\uB2E8 \uC218\uC815\uC5D0 <br> \uC5C6\uC74C \u2014 \uC904\uBC14\uAFC8 \uC704\uCE58 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0 (\uC904\uBC14\uAFC8\uC740 <br>\uB85C \uD45C\uAE30)");
|
|
@@ -23652,7 +23271,7 @@ function patchParagraph(block, orig, edited, ctx, skip) {
|
|
|
23652
23271
|
ctx.skipped.push({ reason: "\uC790\uB3D9\uBC88\uD638 \uC811\uB450 \uC2DD\uBCC4 \uC2E4\uD328 \u2014 \uBC88\uD638 \uD3EC\uD568 \uD14D\uC2A4\uD2B8\uB85C \uC801\uC6A9 (\uBDF0\uC5B4\uC5D0\uC11C \uC911\uBCF5 \uD45C\uC2DC \uAC00\uB2A5)", after: summarize(newPlain) });
|
|
23653
23272
|
}
|
|
23654
23273
|
}
|
|
23655
|
-
const origPlain = restoreBr(textUnitToPlain(orig.raw, block));
|
|
23274
|
+
const origPlain = block.text != null ? block.text : restoreBr(textUnitToPlain(orig.raw, block));
|
|
23656
23275
|
if (newPlain === origPlain) return skip("\uD14D\uC2A4\uD2B8 \uC678 \uBCC0\uACBD(\uD5E4\uB529 \uB808\uBCA8/\uC11C\uC2DD)\uB9CC \uAC10\uC9C0 \u2014 \uC2A4\uD0C0\uC77C \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
|
|
23657
23276
|
if (sanitizeText(newPlain) !== newPlain) {
|
|
23658
23277
|
return skip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uD328\uCE58 \uC2DC \uC6D0\uBB38 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0");
|
|
@@ -24726,7 +24345,7 @@ async function parseHwp(buffer, options) {
|
|
|
24726
24345
|
async function parsePdf(buffer, options) {
|
|
24727
24346
|
let parsePdfDocument;
|
|
24728
24347
|
try {
|
|
24729
|
-
const mod = await import("./parser-
|
|
24348
|
+
const mod = await import("./parser-B4O7CW5Q.js");
|
|
24730
24349
|
parsePdfDocument = mod.parsePdfDocument;
|
|
24731
24350
|
} catch {
|
|
24732
24351
|
return {
|
|
@@ -24827,10 +24446,6 @@ export {
|
|
|
24827
24446
|
inferFieldType,
|
|
24828
24447
|
extractFormSchema,
|
|
24829
24448
|
fillFormFields,
|
|
24830
|
-
scanSectionXml,
|
|
24831
|
-
buildParagraphSplices,
|
|
24832
|
-
buildRangeSplices,
|
|
24833
|
-
applySplices,
|
|
24834
24449
|
fillHwpx,
|
|
24835
24450
|
PRESET_ALIAS,
|
|
24836
24451
|
normalizeGongmunPreset,
|
|
@@ -24857,4 +24472,4 @@ export {
|
|
|
24857
24472
|
parseHwpml,
|
|
24858
24473
|
fillForm
|
|
24859
24474
|
};
|
|
24860
|
-
//# sourceMappingURL=chunk-
|
|
24475
|
+
//# sourceMappingURL=chunk-I6T3DKYK.js.map
|