kordoc 3.16.0 → 3.16.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 +1 -1
- package/dist/{-H7N62NZU.js → -C4FVXHIP.js} +7 -7
- package/dist/{chunk-IC56KHBL.js → chunk-4WI7QXEG.js} +2 -2
- package/dist/{chunk-BIP4JAVG.cjs → chunk-72LLOLFX.cjs} +13 -6
- package/dist/chunk-72LLOLFX.cjs.map +1 -0
- package/dist/{chunk-5RHRQ7HK.js → chunk-E4Y73XRH.js} +8 -4
- package/dist/chunk-E4Y73XRH.js.map +1 -0
- package/dist/{chunk-Q7EGGW3H.js → chunk-EJ2ZIYTO.js} +13 -6
- package/dist/chunk-EJ2ZIYTO.js.map +1 -0
- package/dist/{chunk-WD5NUUU6.js → chunk-EUEKDZ7O.js} +315 -262
- package/dist/chunk-EUEKDZ7O.js.map +1 -0
- package/dist/{chunk-JFNWJFKP.js → chunk-HECUYZZK.js} +2 -2
- package/dist/{chunk-LYL4IL3E.js → chunk-IS3IK7UT.js} +13 -6
- package/dist/chunk-IS3IK7UT.js.map +1 -0
- package/dist/{chunk-FGL7BH4P.js → chunk-WR5LHRXO.js} +49 -20
- package/dist/chunk-WR5LHRXO.js.map +1 -0
- package/dist/cli.js +56 -17
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +586 -502
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +358 -274
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +25 -16
- package/dist/mcp.js.map +1 -1
- package/dist/{parser-HBHCD7TE.js → parser-CMPNM6ZL.js} +25 -12
- package/dist/parser-CMPNM6ZL.js.map +1 -0
- package/dist/{parser-5G247XYD.js → parser-GWL72XYS.js} +24 -11
- package/dist/parser-GWL72XYS.js.map +1 -0
- package/dist/{parser-6V7F3GET.cjs → parser-YVRTKGKO.cjs} +36 -23
- package/dist/parser-YVRTKGKO.cjs.map +1 -0
- package/dist/render-A2LFMJCP.js +10 -0
- package/dist/seal-KA4VAV2Z.js +10 -0
- package/dist/{watch-HIYNOSFD.js → watch-WLI6K3IR.js} +7 -7
- package/package.json +2 -5
- package/dist/chunk-5RHRQ7HK.js.map +0 -1
- package/dist/chunk-BIP4JAVG.cjs.map +0 -1
- package/dist/chunk-FGL7BH4P.js.map +0 -1
- package/dist/chunk-LYL4IL3E.js.map +0 -1
- package/dist/chunk-Q7EGGW3H.js.map +0 -1
- package/dist/chunk-WD5NUUU6.js.map +0 -1
- package/dist/parser-5G247XYD.js.map +0 -1
- package/dist/parser-6V7F3GET.cjs.map +0 -1
- package/dist/parser-HBHCD7TE.js.map +0 -1
- package/dist/render-VA4NHROW.js +0 -10
- package/dist/seal-UVDRGHEF.js +0 -10
- /package/dist/{-H7N62NZU.js.map → -C4FVXHIP.js.map} +0 -0
- /package/dist/{chunk-IC56KHBL.js.map → chunk-4WI7QXEG.js.map} +0 -0
- /package/dist/{chunk-JFNWJFKP.js.map → chunk-HECUYZZK.js.map} +0 -0
- /package/dist/{render-VA4NHROW.js.map → render-A2LFMJCP.js.map} +0 -0
- /package/dist/{seal-UVDRGHEF.js.map → seal-KA4VAV2Z.js.map} +0 -0
- /package/dist/{watch-HIYNOSFD.js.map → watch-WLI6K3IR.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
sanitizeHref,
|
|
20
20
|
stripDtd,
|
|
21
21
|
toArrayBuffer
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-EJ2ZIYTO.js";
|
|
23
23
|
import {
|
|
24
24
|
parsePageRange
|
|
25
25
|
} from "./chunk-GE43BE46.js";
|
|
@@ -926,8 +926,8 @@ function maskLiteralSpans(eqString) {
|
|
|
926
926
|
function findKeywordToken(eqString, word, from = 0) {
|
|
927
927
|
const masked = maskLiteralSpans(eqString);
|
|
928
928
|
for (let i = masked.indexOf(word, from); i !== -1; i = masked.indexOf(word, i + 1)) {
|
|
929
|
-
const okL = i === 0 || masked[i - 1]
|
|
930
|
-
const okR = i + word.length === masked.length || masked[i + word.length]
|
|
929
|
+
const okL = i === 0 || /\s/.test(masked[i - 1]);
|
|
930
|
+
const okR = i + word.length === masked.length || /\s/.test(masked[i + word.length]);
|
|
931
931
|
if (okL && okR) return i;
|
|
932
932
|
}
|
|
933
933
|
return -1;
|
|
@@ -938,11 +938,22 @@ function replaceFrac(eqString) {
|
|
|
938
938
|
const cursor = findKeywordToken(eqString, hmlFrac);
|
|
939
939
|
if (cursor === -1) break;
|
|
940
940
|
try {
|
|
941
|
-
|
|
942
|
-
|
|
941
|
+
let end = cursor;
|
|
942
|
+
while (end > 0 && /\s/.test(eqString[end - 1])) end--;
|
|
943
|
+
let numStart, numEnd, wrapped;
|
|
944
|
+
if (end > 0 && eqString[end - 1] === "}") {
|
|
945
|
+
[numStart, numEnd] = findBrackets(eqString, end - 1, 0);
|
|
946
|
+
wrapped = eqString.slice(numStart, numEnd);
|
|
947
|
+
} else {
|
|
948
|
+
numEnd = end;
|
|
949
|
+
numStart = end;
|
|
950
|
+
while (numStart > 0 && !/\s/.test(eqString[numStart - 1])) numStart--;
|
|
951
|
+
if (numStart === numEnd) throw new Error("empty numerator");
|
|
952
|
+
wrapped = "{" + eqString.slice(numStart, numEnd) + "}";
|
|
953
|
+
}
|
|
943
954
|
const beforeFrac = eqString.slice(0, numStart);
|
|
944
955
|
const afterFrac = eqString.slice(cursor + hmlFrac.length);
|
|
945
|
-
eqString = beforeFrac + "\\frac" +
|
|
956
|
+
eqString = beforeFrac + "\\frac" + wrapped + afterFrac;
|
|
946
957
|
} catch {
|
|
947
958
|
return eqString;
|
|
948
959
|
}
|
|
@@ -18348,7 +18359,7 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18348
18359
|
if (trPrEls.length > 0) {
|
|
18349
18360
|
const gridBeforeEls = getChildElements(trPrEls[0], "gridBefore");
|
|
18350
18361
|
if (gridBeforeEls.length > 0) {
|
|
18351
|
-
col = parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0;
|
|
18362
|
+
col = Math.max(0, parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0);
|
|
18352
18363
|
}
|
|
18353
18364
|
}
|
|
18354
18365
|
for (const tc of getChildElements(tr, "tc")) {
|
|
@@ -18877,34 +18888,47 @@ function countSections(body) {
|
|
|
18877
18888
|
|
|
18878
18889
|
// src/form/match.ts
|
|
18879
18890
|
function parseYMD(v) {
|
|
18880
|
-
const d = v.replace(/\D/g, "");
|
|
18881
18891
|
let y, m, day;
|
|
18882
|
-
|
|
18883
|
-
|
|
18884
|
-
|
|
18885
|
-
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
|
|
18890
|
-
|
|
18891
|
-
|
|
18892
|
+
const parts = v.split(/[^0-9]+/).filter(Boolean);
|
|
18893
|
+
if (parts.length === 3) {
|
|
18894
|
+
const [yp, mp, dp] = parts;
|
|
18895
|
+
const yn = +yp;
|
|
18896
|
+
y = yp.length >= 3 ? yp : String(yn <= 29 ? 2e3 + yn : 1900 + yn);
|
|
18897
|
+
m = mp.padStart(2, "0");
|
|
18898
|
+
day = dp.padStart(2, "0");
|
|
18899
|
+
} else {
|
|
18900
|
+
const d = v.replace(/\D/g, "");
|
|
18901
|
+
if (d.length >= 8) {
|
|
18902
|
+
y = d.slice(0, 4);
|
|
18903
|
+
m = d.slice(4, 6);
|
|
18904
|
+
day = d.slice(6, 8);
|
|
18905
|
+
} else if (d.length === 6) {
|
|
18906
|
+
const yy = +d.slice(0, 2);
|
|
18907
|
+
y = String(yy <= 29 ? 2e3 + yy : 1900 + yy);
|
|
18908
|
+
m = d.slice(2, 4);
|
|
18909
|
+
day = d.slice(4, 6);
|
|
18910
|
+
} else return null;
|
|
18911
|
+
}
|
|
18912
|
+
if (+m < 1 || +m > 12 || +day < 1 || +day > 31) return null;
|
|
18892
18913
|
return { y, yy: y.slice(2), m, d: day };
|
|
18893
18914
|
}
|
|
18894
18915
|
function fmtDate(v, style) {
|
|
18895
18916
|
const p = parseYMD(v);
|
|
18896
18917
|
if (!p) return v;
|
|
18897
|
-
return (style || "yyyy-mm-dd").replace(/yyyy/
|
|
18918
|
+
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));
|
|
18898
18919
|
}
|
|
18899
18920
|
function maskDigits(v, pattern) {
|
|
18900
18921
|
const ds = v.replace(/\D/g, "");
|
|
18922
|
+
const need = (pattern.match(/#/g) ?? []).length;
|
|
18923
|
+
if (need === 0 || ds.length !== need) return v;
|
|
18901
18924
|
let i = 0;
|
|
18902
|
-
return pattern.replace(/#/g, () => ds[i++]
|
|
18925
|
+
return pattern.replace(/#/g, () => ds[i++]);
|
|
18903
18926
|
}
|
|
18904
18927
|
function fmtPhone(v, style) {
|
|
18905
18928
|
const d = v.replace(/\D/g, "");
|
|
18906
18929
|
if (d.length < 9) return v;
|
|
18907
|
-
const
|
|
18930
|
+
const areaLen = d.startsWith("02") ? 2 : 3;
|
|
18931
|
+
const a = d.slice(0, areaLen), b = d.slice(areaLen, -4), c = d.slice(-4);
|
|
18908
18932
|
switch (style) {
|
|
18909
18933
|
case "digits":
|
|
18910
18934
|
return d;
|
|
@@ -18913,9 +18937,9 @@ function fmtPhone(v, style) {
|
|
|
18913
18937
|
case "space":
|
|
18914
18938
|
return `${a} ${b} ${c}`;
|
|
18915
18939
|
case "intl":
|
|
18916
|
-
return `+82-${d.slice(1,
|
|
18940
|
+
return `+82-${d.slice(1, areaLen)}-${b}-${c}`;
|
|
18917
18941
|
case "intl-paren":
|
|
18918
|
-
return `82)${d.slice(1,
|
|
18942
|
+
return `82)${d.slice(1, areaLen)}-${b}-${c}`;
|
|
18919
18943
|
default:
|
|
18920
18944
|
return `${a}-${b}-${c}`;
|
|
18921
18945
|
}
|
|
@@ -18943,7 +18967,10 @@ function formatFillValue(value, format) {
|
|
|
18943
18967
|
if (kind === "phone") return fmtPhone(value, style);
|
|
18944
18968
|
if (kind === "rrn") return fmtRRN(value, style);
|
|
18945
18969
|
if (kind === "mask") return maskDigits(value, style);
|
|
18946
|
-
if (kind === "digits")
|
|
18970
|
+
if (kind === "digits") {
|
|
18971
|
+
const only = value.replace(/\D/g, "");
|
|
18972
|
+
return only || value;
|
|
18973
|
+
}
|
|
18947
18974
|
if (kind === "upper") return value.toUpperCase();
|
|
18948
18975
|
if (kind === "lower") return value.toLowerCase();
|
|
18949
18976
|
if (kind === "nospace") return value.replace(/\s+/g, "");
|
|
@@ -19020,7 +19047,7 @@ function isKeywordLabel(text) {
|
|
|
19020
19047
|
}
|
|
19021
19048
|
return false;
|
|
19022
19049
|
}
|
|
19023
|
-
function fillInCellPatterns(cellText, values, matchedLabels) {
|
|
19050
|
+
function fillInCellPatterns(cellText, values, matchedLabels, blockedLabels) {
|
|
19024
19051
|
let text = cellText;
|
|
19025
19052
|
const matches = [];
|
|
19026
19053
|
text = text.replace(
|
|
@@ -19028,6 +19055,7 @@ function fillInCellPatterns(cellText, values, matchedLabels) {
|
|
|
19028
19055
|
(match, prefix, suffix) => {
|
|
19029
19056
|
const label = prefix + suffix;
|
|
19030
19057
|
const normalizedLabel = normalizeLabel(label);
|
|
19058
|
+
if (blockedLabels?.has(normalizedLabel)) return match;
|
|
19031
19059
|
const matchKey = values.available(normalizedLabel) ? normalizedLabel : values.available(normalizeLabel(prefix)) ? normalizeLabel(prefix) : void 0;
|
|
19032
19060
|
if (matchKey === void 0) return match;
|
|
19033
19061
|
const newValue = values.consume(matchKey);
|
|
@@ -19123,8 +19151,12 @@ async function fillWithUniqueGuard(values, run) {
|
|
|
19123
19151
|
};
|
|
19124
19152
|
const dup = new Set([...counts].filter(([k, n]) => n >= 2 && !isArrayValue(k)).map(([k]) => k));
|
|
19125
19153
|
if (dup.size === 0) return { ...first, rejected: [] };
|
|
19154
|
+
const blockedLabels = /* @__PURE__ */ new Set();
|
|
19155
|
+
for (const f of first.filled) {
|
|
19156
|
+
if (f.key && dup.has(f.key)) blockedLabels.add(normalizeLabel(f.label));
|
|
19157
|
+
}
|
|
19126
19158
|
const filtered = Object.fromEntries(Object.entries(values).filter(([label]) => !dup.has(normalizeLabel(label))));
|
|
19127
|
-
const second = await run(filtered);
|
|
19159
|
+
const second = await run(filtered, blockedLabels);
|
|
19128
19160
|
const rejected = Object.keys(values).filter((label) => dup.has(normalizeLabel(label)));
|
|
19129
19161
|
return { ...second, rejected };
|
|
19130
19162
|
}
|
|
@@ -19379,7 +19411,7 @@ function extractFormSchema(blocks) {
|
|
|
19379
19411
|
}
|
|
19380
19412
|
|
|
19381
19413
|
// src/form/filler.ts
|
|
19382
|
-
function fillFormFields(blocks, values) {
|
|
19414
|
+
function fillFormFields(blocks, values, blockedLabels) {
|
|
19383
19415
|
const cloned = structuredClone(blocks);
|
|
19384
19416
|
const filled = [];
|
|
19385
19417
|
const matchedLabels = /* @__PURE__ */ new Set();
|
|
@@ -19392,7 +19424,7 @@ function fillFormFields(blocks, values) {
|
|
|
19392
19424
|
for (let c = 0; c < table.cols; c++) {
|
|
19393
19425
|
const cell = table.cells[r]?.[c];
|
|
19394
19426
|
if (!cell) continue;
|
|
19395
|
-
const result = fillInCellPatterns(cell.text, cursor, matchedLabels);
|
|
19427
|
+
const result = fillInCellPatterns(cell.text, cursor, matchedLabels, blockedLabels);
|
|
19396
19428
|
if (result) {
|
|
19397
19429
|
cell.text = result.text;
|
|
19398
19430
|
patternFilledCells.add(cell);
|
|
@@ -19404,11 +19436,11 @@ function fillFormFields(blocks, values) {
|
|
|
19404
19436
|
}
|
|
19405
19437
|
}
|
|
19406
19438
|
for (const table of allTables) {
|
|
19407
|
-
fillTable(table, cursor, filled, matchedLabels, patternFilledCells);
|
|
19439
|
+
fillTable(table, cursor, filled, matchedLabels, patternFilledCells, blockedLabels);
|
|
19408
19440
|
}
|
|
19409
19441
|
for (const block of cloned) {
|
|
19410
19442
|
if (block.type !== "paragraph" || !block.text) continue;
|
|
19411
|
-
const newText = fillInlineFields(block.text, cursor, filled, matchedLabels);
|
|
19443
|
+
const newText = fillInlineFields(block.text, cursor, filled, matchedLabels, blockedLabels);
|
|
19412
19444
|
if (newText !== block.text) block.text = newText;
|
|
19413
19445
|
}
|
|
19414
19446
|
const unmatched = resolveUnmatched(normalizedValues, matchedLabels, values);
|
|
@@ -19446,7 +19478,7 @@ function coveredPositions(table) {
|
|
|
19446
19478
|
}
|
|
19447
19479
|
return covered;
|
|
19448
19480
|
}
|
|
19449
|
-
function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
19481
|
+
function fillTable(table, values, filled, matchedLabels, patternFilledCells, blockedLabels) {
|
|
19450
19482
|
if (table.cols < 2) return;
|
|
19451
19483
|
const covered = coveredPositions(table);
|
|
19452
19484
|
for (let r = 0; r < table.rows; r++) {
|
|
@@ -19463,6 +19495,7 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19463
19495
|
if (isKeywordLabel(valueCell.text)) continue;
|
|
19464
19496
|
const normalizedCellLabel = normalizeLabel(labelCell.text);
|
|
19465
19497
|
if (!normalizedCellLabel) continue;
|
|
19498
|
+
if (blockedLabels?.has(normalizedCellLabel)) continue;
|
|
19466
19499
|
const matchKey = findMatchingKey(normalizedCellLabel, values);
|
|
19467
19500
|
if (matchKey === void 0) continue;
|
|
19468
19501
|
const newValue = values.consume(matchKey);
|
|
@@ -19496,6 +19529,7 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19496
19529
|
const valueCell = table.cells[r]?.[c];
|
|
19497
19530
|
if (!headerCell || !valueCell) continue;
|
|
19498
19531
|
const headerLabel = normalizeLabel(headerCell.text);
|
|
19532
|
+
if (blockedLabels?.has(headerLabel)) continue;
|
|
19499
19533
|
const matchKey = findMatchingKey(headerLabel, values);
|
|
19500
19534
|
if (matchKey === void 0) continue;
|
|
19501
19535
|
if (!values.isArray(matchKey) && matchedLabels.has(matchKey)) continue;
|
|
@@ -19514,13 +19548,15 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19514
19548
|
}
|
|
19515
19549
|
}
|
|
19516
19550
|
}
|
|
19517
|
-
function fillInlineFields(text, values, filled, matchedLabels) {
|
|
19551
|
+
function fillInlineFields(text, values, filled, matchedLabels, blockedLabels) {
|
|
19518
19552
|
const segments = scanInlineSegments(text);
|
|
19519
19553
|
if (segments.length === 0) return text;
|
|
19520
19554
|
let out = "";
|
|
19521
19555
|
let pos = 0;
|
|
19522
19556
|
for (const seg of segments) {
|
|
19523
|
-
const
|
|
19557
|
+
const nlabel = normalizeLabel(seg.label);
|
|
19558
|
+
if (blockedLabels?.has(nlabel)) continue;
|
|
19559
|
+
const matchKey = findMatchingKey(nlabel, values);
|
|
19524
19560
|
if (matchKey === void 0) continue;
|
|
19525
19561
|
const newValue = values.consume(matchKey);
|
|
19526
19562
|
if (newValue === void 0) continue;
|
|
@@ -20263,7 +20299,7 @@ function patchZipEntries(original, replacements, additions) {
|
|
|
20263
20299
|
}
|
|
20264
20300
|
|
|
20265
20301
|
// src/form/filler-hwpx.ts
|
|
20266
|
-
async function fillHwpx(hwpxBuffer, values) {
|
|
20302
|
+
async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
20267
20303
|
const u8 = new Uint8Array(hwpxBuffer);
|
|
20268
20304
|
const zip = await JSZip6.loadAsync(hwpxBuffer);
|
|
20269
20305
|
const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
|
|
@@ -20307,7 +20343,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20307
20343
|
for (const cell of row) {
|
|
20308
20344
|
for (const para of cell.paragraphs) {
|
|
20309
20345
|
const text = matchText(para);
|
|
20310
|
-
const result = fillInCellPatterns(text, cursor, matchedLabels);
|
|
20346
|
+
const result = fillInCellPatterns(text, cursor, matchedLabels, blockedLabels);
|
|
20311
20347
|
if (!result) continue;
|
|
20312
20348
|
const l = led(para);
|
|
20313
20349
|
if (l.fullText !== void 0) continue;
|
|
@@ -20325,7 +20361,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20325
20361
|
for (const m of result.matches) {
|
|
20326
20362
|
l.filledIdx.push(filled.length);
|
|
20327
20363
|
l.matchKeys.push(m.key);
|
|
20328
|
-
filled.push({ label: m.label, value: m.value, row: -1, col: -1 });
|
|
20364
|
+
filled.push({ label: m.label, value: m.value, row: -1, col: -1, key: m.key });
|
|
20329
20365
|
}
|
|
20330
20366
|
}
|
|
20331
20367
|
}
|
|
@@ -20341,6 +20377,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20341
20377
|
if (isKeywordLabel(cellLabelText(valueCell))) continue;
|
|
20342
20378
|
const normalizedCellLabel = normalizeLabel(labelText);
|
|
20343
20379
|
if (!normalizedCellLabel) continue;
|
|
20380
|
+
if (blockedLabels?.has(normalizedCellLabel)) continue;
|
|
20344
20381
|
const matchKey = findMatchingKey(normalizedCellLabel, cursor);
|
|
20345
20382
|
if (matchKey === void 0) continue;
|
|
20346
20383
|
if (patternApplied.has(valueCell)) {
|
|
@@ -20358,7 +20395,8 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20358
20395
|
label: labelText.trim().replace(/[::]\s*$/, ""),
|
|
20359
20396
|
value: newValue,
|
|
20360
20397
|
row: rowIdx,
|
|
20361
|
-
col: colIdx
|
|
20398
|
+
col: colIdx,
|
|
20399
|
+
key: matchKey
|
|
20362
20400
|
});
|
|
20363
20401
|
} else {
|
|
20364
20402
|
const paras = valueCell.paragraphs;
|
|
@@ -20380,7 +20418,8 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20380
20418
|
label: labelText.trim().replace(/[::]\s*$/, ""),
|
|
20381
20419
|
value: newValue,
|
|
20382
20420
|
row: rowIdx,
|
|
20383
|
-
col: colIdx
|
|
20421
|
+
col: colIdx,
|
|
20422
|
+
key: matchKey
|
|
20384
20423
|
});
|
|
20385
20424
|
}
|
|
20386
20425
|
}
|
|
@@ -20396,6 +20435,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20396
20435
|
const dataCells = table.rows[rowIdx];
|
|
20397
20436
|
for (let colIdx = 0; colIdx < Math.min(headerCells.length, dataCells.length); colIdx++) {
|
|
20398
20437
|
const headerLabel = normalizeLabel(cellLabelText(headerCells[colIdx]));
|
|
20438
|
+
if (blockedLabels?.has(headerLabel)) continue;
|
|
20399
20439
|
const matchKey = findMatchingKey(headerLabel, cursor);
|
|
20400
20440
|
if (matchKey === void 0) continue;
|
|
20401
20441
|
if (!cursor.isArray(matchKey) && matchedLabels.has(matchKey)) continue;
|
|
@@ -20431,7 +20471,9 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20431
20471
|
if (existing?.fullText !== void 0) continue;
|
|
20432
20472
|
const text = matchText(para);
|
|
20433
20473
|
for (const seg of scanInlineSegments(text)) {
|
|
20434
|
-
const
|
|
20474
|
+
const nlabel = normalizeLabel(seg.label);
|
|
20475
|
+
if (blockedLabels?.has(nlabel)) continue;
|
|
20476
|
+
const matchKey = findMatchingKey(nlabel, cursor);
|
|
20435
20477
|
if (matchKey === void 0) continue;
|
|
20436
20478
|
const newValue = cursor.consume(matchKey);
|
|
20437
20479
|
if (newValue === void 0) continue;
|
|
@@ -20441,7 +20483,7 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
20441
20483
|
matchedLabels.add(matchKey);
|
|
20442
20484
|
l.filledIdx.push(filled.length);
|
|
20443
20485
|
l.matchKeys.push(matchKey);
|
|
20444
|
-
filled.push({ label: seg.label.trim(), value: newValue, row: -1, col: -1 });
|
|
20486
|
+
filled.push({ label: seg.label.trim(), value: newValue, row: -1, col: -1, key: matchKey });
|
|
20445
20487
|
}
|
|
20446
20488
|
}
|
|
20447
20489
|
const splices = [];
|
|
@@ -20974,7 +21016,8 @@ function buildPrvText(blocks) {
|
|
|
20974
21016
|
let bytes = 0;
|
|
20975
21017
|
for (const b of blocks) {
|
|
20976
21018
|
let text = b.text || (b.rows ? b.rows.map((r) => r.join(" ")).join("\n") : "");
|
|
20977
|
-
if (b.type === "
|
|
21019
|
+
if (b.type === "code_block" && (b.lang || "").toLowerCase() === "chart") text = "[\uCC28\uD2B8]";
|
|
21020
|
+
else if (b.type === "html_table") text = text.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
20978
21021
|
if (!text) continue;
|
|
20979
21022
|
lines.push(text);
|
|
20980
21023
|
bytes += text.length * 3;
|
|
@@ -20993,7 +21036,7 @@ function findMathDelim(s, from) {
|
|
|
20993
21036
|
return i;
|
|
20994
21037
|
}
|
|
20995
21038
|
function parseMarkdownToBlocks(md2) {
|
|
20996
|
-
const lines = md2.split("\n");
|
|
21039
|
+
const lines = md2.replace(/\r\n?/g, "\n").split("\n");
|
|
20997
21040
|
const blocks = [];
|
|
20998
21041
|
let i = 0;
|
|
20999
21042
|
while (i < lines.length) {
|
|
@@ -21041,13 +21084,13 @@ function parseMarkdownToBlocks(md2) {
|
|
|
21041
21084
|
continue;
|
|
21042
21085
|
}
|
|
21043
21086
|
}
|
|
21044
|
-
const fenceMatch = line.match(/^(`{3,}|~{3,})(.*)$/);
|
|
21087
|
+
const fenceMatch = line.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
|
|
21045
21088
|
if (fenceMatch) {
|
|
21046
21089
|
const fence = fenceMatch[1];
|
|
21047
21090
|
const lang = fenceMatch[2].trim();
|
|
21048
21091
|
const codeLines = [];
|
|
21049
21092
|
i++;
|
|
21050
|
-
while (i < lines.length && !lines[i].startsWith(fence)) {
|
|
21093
|
+
while (i < lines.length && !lines[i].replace(/^ {0,3}/, "").startsWith(fence)) {
|
|
21051
21094
|
codeLines.push(lines[i]);
|
|
21052
21095
|
i++;
|
|
21053
21096
|
}
|
|
@@ -21383,6 +21426,219 @@ function generateHeaderXml(theme, gongmun, ratioVariants = []) {
|
|
|
21383
21426
|
</hh:head>`;
|
|
21384
21427
|
}
|
|
21385
21428
|
|
|
21429
|
+
// src/hwpx/chart-gen.ts
|
|
21430
|
+
var XML_ESC = { "&": "&", "<": "<", ">": ">" };
|
|
21431
|
+
var xmlEscape = (s) => s.replace(/[&<>]/g, (c) => XML_ESC[c]);
|
|
21432
|
+
var CHART_TYPES = {
|
|
21433
|
+
0: { el: "barChart", dir: "col", grp: "clustered" },
|
|
21434
|
+
1: { el: "barChart", dir: "col", grp: "stacked", overlap: 100 },
|
|
21435
|
+
2: { el: "lineChart", grp: "standard", marker: true },
|
|
21436
|
+
3: { el: "barChart", dir: "bar", grp: "clustered" },
|
|
21437
|
+
4: { el: "barChart", dir: "bar", grp: "stacked", overlap: 100 },
|
|
21438
|
+
5: { el: "scatterChart", scatter: true },
|
|
21439
|
+
6: { el: "pieChart", pie: true },
|
|
21440
|
+
7: { el: "pieChart", pie: true, explode: true },
|
|
21441
|
+
8: { el: "doughnutChart", pie: true, hole: 50 },
|
|
21442
|
+
9: { el: "areaChart", grp: "standard" },
|
|
21443
|
+
10: { el: "areaChart", grp: "stacked" },
|
|
21444
|
+
11: { el: "radarChart", radar: true },
|
|
21445
|
+
12: { el: "bar3DChart", dir: "col", grp: "clustered" },
|
|
21446
|
+
13: { el: "bar3DChart", dir: "col", grp: "stacked", overlap: 100 },
|
|
21447
|
+
14: { el: "bar3DChart", dir: "bar", grp: "clustered" },
|
|
21448
|
+
15: { el: "bar3DChart", dir: "bar", grp: "stacked", overlap: 100 },
|
|
21449
|
+
16: { el: "pie3DChart", pie: true },
|
|
21450
|
+
17: { el: "pie3DChart", pie: true, explode: true },
|
|
21451
|
+
18: { el: "area3DChart", grp: "standard" },
|
|
21452
|
+
19: { el: "area3DChart", grp: "stacked" }
|
|
21453
|
+
};
|
|
21454
|
+
var CHART_ALIAS = {
|
|
21455
|
+
column: 0,
|
|
21456
|
+
col: 0,
|
|
21457
|
+
\uC138\uB85C\uB9C9\uB300: 0,
|
|
21458
|
+
\uB9C9\uB300: 0,
|
|
21459
|
+
column_stacked: 1,
|
|
21460
|
+
\uC138\uB85C\uB9C9\uB300_\uB204\uC801: 1,
|
|
21461
|
+
line: 2,
|
|
21462
|
+
\uC120: 2,
|
|
21463
|
+
\uAEBE\uC740\uC120: 2,
|
|
21464
|
+
bar: 3,
|
|
21465
|
+
\uAC00\uB85C\uB9C9\uB300: 3,
|
|
21466
|
+
bar_stacked: 4,
|
|
21467
|
+
scatter: 5,
|
|
21468
|
+
\uBD84\uC0B0: 5,
|
|
21469
|
+
pie: 6,
|
|
21470
|
+
\uC6D0: 6,
|
|
21471
|
+
\uD30C\uC774: 6,
|
|
21472
|
+
pie_explode: 7,
|
|
21473
|
+
doughnut: 8,
|
|
21474
|
+
donut: 8,
|
|
21475
|
+
\uB3C4\uB11B: 8,
|
|
21476
|
+
area: 9,
|
|
21477
|
+
\uC601\uC5ED: 9,
|
|
21478
|
+
area_stacked: 10,
|
|
21479
|
+
radar: 11,
|
|
21480
|
+
\uBC29\uC0AC\uD615: 11,
|
|
21481
|
+
bar3d: 12,
|
|
21482
|
+
column3d: 12,
|
|
21483
|
+
pie3d: 16
|
|
21484
|
+
};
|
|
21485
|
+
function chartSpec(t) {
|
|
21486
|
+
if (!t) return CHART_TYPES[0];
|
|
21487
|
+
const key = CHART_ALIAS[t.toLowerCase()] ?? Number(t);
|
|
21488
|
+
return CHART_TYPES[key] ?? CHART_TYPES[0];
|
|
21489
|
+
}
|
|
21490
|
+
var HU_PER_MM = 7200 / 25.4;
|
|
21491
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set(["type", "cat", "size", "colors", "point_colors", "title"]);
|
|
21492
|
+
function parseChartFence(text) {
|
|
21493
|
+
let type;
|
|
21494
|
+
let cat = null;
|
|
21495
|
+
let widthMm = 32250 / HU_PER_MM;
|
|
21496
|
+
let heightMm = 18750 / HU_PER_MM;
|
|
21497
|
+
let colors = null;
|
|
21498
|
+
let pointColors = null;
|
|
21499
|
+
const series = [];
|
|
21500
|
+
for (const rawLine of text.split("\n")) {
|
|
21501
|
+
const line = rawLine.trim();
|
|
21502
|
+
if (!line || line.startsWith("#")) continue;
|
|
21503
|
+
const colon = line.search(/[::]/);
|
|
21504
|
+
if (colon <= 0) continue;
|
|
21505
|
+
const key = line.slice(0, colon).trim();
|
|
21506
|
+
const value = line.slice(colon + 1).trim();
|
|
21507
|
+
const keyLower = key.toLowerCase();
|
|
21508
|
+
if (keyLower === "type") {
|
|
21509
|
+
type = value;
|
|
21510
|
+
} else if (keyLower === "cat") {
|
|
21511
|
+
cat = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
21512
|
+
} else if (keyLower === "size") {
|
|
21513
|
+
const m = value.match(/^(\d+(?:\.\d+)?)\s*[x×]\s*(\d+(?:\.\d+)?)$/i);
|
|
21514
|
+
if (m) {
|
|
21515
|
+
const clamp = (n) => Math.min(500, Math.max(10, n));
|
|
21516
|
+
widthMm = clamp(Number(m[1]));
|
|
21517
|
+
heightMm = clamp(Number(m[2]));
|
|
21518
|
+
}
|
|
21519
|
+
} else if (keyLower === "colors") {
|
|
21520
|
+
colors = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
21521
|
+
} else if (keyLower === "point_colors") {
|
|
21522
|
+
pointColors = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
21523
|
+
} else if (keyLower === "title") {
|
|
21524
|
+
} else if (!RESERVED_KEYS.has(keyLower)) {
|
|
21525
|
+
const segs = value.replace(/(\d),(?=\d{3}(?:\D|$))/g, "$1").split(",").map((s) => s.trim()).filter(Boolean);
|
|
21526
|
+
if (segs.length === 0) continue;
|
|
21527
|
+
const nums = segs.map(Number);
|
|
21528
|
+
if (nums.every((n) => Number.isFinite(n))) {
|
|
21529
|
+
series.push({ name: key, values: nums });
|
|
21530
|
+
} else {
|
|
21531
|
+
return null;
|
|
21532
|
+
}
|
|
21533
|
+
}
|
|
21534
|
+
}
|
|
21535
|
+
if (series.length === 0) return null;
|
|
21536
|
+
const spec = chartSpec(type);
|
|
21537
|
+
let finalSeries = spec.pie ? [series[0]] : series;
|
|
21538
|
+
finalSeries = finalSeries.map((s) => ({ ...s }));
|
|
21539
|
+
const ptLen = Math.max(cat?.length ?? 0, ...finalSeries.map((s) => s.values.length));
|
|
21540
|
+
const catFinal = Array.from({ length: ptLen }, (_, i) => cat?.[i] ?? `\uD56D\uBAA9 ${i + 1}`);
|
|
21541
|
+
if (!spec.scatter) {
|
|
21542
|
+
finalSeries = finalSeries.map((s) => ({ ...s, values: catFinal.map((_, i) => s.values[i] ?? 0) }));
|
|
21543
|
+
}
|
|
21544
|
+
if (spec.pie) {
|
|
21545
|
+
const slice = colors ?? pointColors;
|
|
21546
|
+
if (slice) finalSeries[0].pointColors = slice;
|
|
21547
|
+
} else {
|
|
21548
|
+
if (colors) finalSeries.forEach((s, i) => {
|
|
21549
|
+
s.color = colors[i % colors.length];
|
|
21550
|
+
});
|
|
21551
|
+
if (pointColors && finalSeries[0]) finalSeries[0].pointColors = pointColors;
|
|
21552
|
+
}
|
|
21553
|
+
return {
|
|
21554
|
+
spec,
|
|
21555
|
+
cat: catFinal,
|
|
21556
|
+
series: finalSeries,
|
|
21557
|
+
widthHu: Math.round(widthMm * HU_PER_MM),
|
|
21558
|
+
heightHu: Math.round(heightMm * HU_PER_MM)
|
|
21559
|
+
};
|
|
21560
|
+
}
|
|
21561
|
+
var colLetter = (i) => String.fromCharCode(66 + i);
|
|
21562
|
+
function strCachePts(vals) {
|
|
21563
|
+
return `<c:ptCount val="${vals.length}"/>` + vals.map((v, i) => `<c:pt idx="${i}"><c:v>${xmlEscape(v)}</c:v></c:pt>`).join("");
|
|
21564
|
+
}
|
|
21565
|
+
function numCachePts(vals) {
|
|
21566
|
+
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("");
|
|
21567
|
+
}
|
|
21568
|
+
function chartColorFill(color) {
|
|
21569
|
+
if (color == null) return null;
|
|
21570
|
+
const c = color.trim();
|
|
21571
|
+
if (/^accent[1-6]$/i.test(c)) return `<a:solidFill><a:schemeClr val="${c.toLowerCase()}"/></a:solidFill>`;
|
|
21572
|
+
const hex = c.replace(/^#/, "").toUpperCase();
|
|
21573
|
+
if (/^[0-9A-F]{6}$/.test(hex)) return `<a:solidFill><a:srgbClr val="${hex}"/></a:solidFill>`;
|
|
21574
|
+
return null;
|
|
21575
|
+
}
|
|
21576
|
+
function serSpPr(color, stroke) {
|
|
21577
|
+
const f = chartColorFill(color);
|
|
21578
|
+
if (!f) return "<c:spPr/>";
|
|
21579
|
+
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>`;
|
|
21580
|
+
}
|
|
21581
|
+
function dPtXml(pointColors, pie) {
|
|
21582
|
+
if (!pointColors?.length) return "";
|
|
21583
|
+
return pointColors.map((col, i) => {
|
|
21584
|
+
const f = chartColorFill(col);
|
|
21585
|
+
if (!f) return "";
|
|
21586
|
+
const mid = pie ? '<c:invertIfNegative val="0"/><c:bubble3D val="0"/><c:explosion val="0"/>' : '<c:bubble3D val="0"/>';
|
|
21587
|
+
return `<c:dPt><c:idx val="${i}"/>${mid}<c:spPr>${f}</c:spPr></c:dPt>`;
|
|
21588
|
+
}).join("");
|
|
21589
|
+
}
|
|
21590
|
+
function stdSer(idx, name, cat, values, explode, color, pointColors, stroke, pie) {
|
|
21591
|
+
const cl = colLetter(idx);
|
|
21592
|
+
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>`;
|
|
21593
|
+
}
|
|
21594
|
+
function scatterSer(idx, name, xvals, yvals) {
|
|
21595
|
+
const cl = colLetter(idx);
|
|
21596
|
+
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>`;
|
|
21597
|
+
}
|
|
21598
|
+
function catAxXml(id, pos, cross) {
|
|
21599
|
+
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>`;
|
|
21600
|
+
}
|
|
21601
|
+
function valAxXml(id, pos, cross) {
|
|
21602
|
+
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>`;
|
|
21603
|
+
}
|
|
21604
|
+
function buildChartSpaceXml(fence) {
|
|
21605
|
+
const { spec, cat, series } = fence;
|
|
21606
|
+
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"';
|
|
21607
|
+
const ax1 = "111111111";
|
|
21608
|
+
const ax2 = "222222222";
|
|
21609
|
+
let plot;
|
|
21610
|
+
if (spec.scatter) {
|
|
21611
|
+
const n = Math.max(0, ...series.map((s) => s.values.length));
|
|
21612
|
+
const xs = Array.from({ length: n }, (_, i) => {
|
|
21613
|
+
const c = cat[i];
|
|
21614
|
+
const v = Number(c);
|
|
21615
|
+
return c !== void 0 && c !== "" && Number.isFinite(v) ? v : i + 1;
|
|
21616
|
+
});
|
|
21617
|
+
const sers = series.map((s, i) => scatterSer(i, s.name, xs, s.values)).join("");
|
|
21618
|
+
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);
|
|
21619
|
+
} else if (spec.pie) {
|
|
21620
|
+
const s0 = series[0];
|
|
21621
|
+
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}>`;
|
|
21622
|
+
} else {
|
|
21623
|
+
const stroke = spec.el === "lineChart" || spec.el === "radarChart" || !!spec.radar;
|
|
21624
|
+
const sers = series.map((s, i) => stdSer(i, s.name, cat, s.values, false, s.color, s.pointColors, stroke, false)).join("");
|
|
21625
|
+
const horiz = spec.dir === "bar";
|
|
21626
|
+
let inner = "";
|
|
21627
|
+
if (spec.dir) inner += `<c:barDir val="${spec.dir}"/>`;
|
|
21628
|
+
if (spec.grp) inner += `<c:grouping val="${spec.grp}"/>`;
|
|
21629
|
+
if (spec.radar) inner += `<c:radarStyle val="standard"/>`;
|
|
21630
|
+
inner += `<c:varyColors val="0"/>${sers}`;
|
|
21631
|
+
if (spec.marker) inner += `<c:marker val="1"/>`;
|
|
21632
|
+
if (spec.el.startsWith("bar")) inner += `<c:gapWidth val="150"/><c:overlap val="${spec.overlap ?? 0}"/>`;
|
|
21633
|
+
inner += `<c:axId val="${ax1}"/><c:axId val="${ax2}"/>`;
|
|
21634
|
+
plot = `<c:${spec.el}>${inner}</c:${spec.el}>` + catAxXml(ax1, horiz ? "l" : "b", ax2) + valAxXml(ax2, horiz ? "b" : "l", ax1);
|
|
21635
|
+
}
|
|
21636
|
+
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>`;
|
|
21637
|
+
}
|
|
21638
|
+
function buildChartElementXml(partName, widthHu, heightHu, id) {
|
|
21639
|
+
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>`;
|
|
21640
|
+
}
|
|
21641
|
+
|
|
21386
21642
|
// src/hwpx/gen-gongmun-fit.ts
|
|
21387
21643
|
function plainRenderText(text) {
|
|
21388
21644
|
return parseInlineMarkdown(text).map((s) => s.text).join("");
|
|
@@ -21435,18 +21691,18 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
21435
21691
|
i++;
|
|
21436
21692
|
continue;
|
|
21437
21693
|
}
|
|
21438
|
-
const passThrough = (
|
|
21694
|
+
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;
|
|
21439
21695
|
const run = [];
|
|
21440
21696
|
while (i < blocks.length) {
|
|
21441
|
-
const
|
|
21442
|
-
if (
|
|
21697
|
+
const b = blocks[i];
|
|
21698
|
+
if (b.type === "list_item") {
|
|
21443
21699
|
run.push(i);
|
|
21444
21700
|
i++;
|
|
21445
21701
|
continue;
|
|
21446
21702
|
}
|
|
21447
|
-
if (passThrough(
|
|
21703
|
+
if (passThrough(b)) {
|
|
21448
21704
|
let j = i + 1;
|
|
21449
|
-
while (j < blocks.length && passThrough(blocks[j]
|
|
21705
|
+
while (j < blocks.length && passThrough(blocks[j])) j++;
|
|
21450
21706
|
if (j < blocks.length && blocks[j].type === "list_item") {
|
|
21451
21707
|
i = j;
|
|
21452
21708
|
continue;
|
|
@@ -22249,210 +22505,6 @@ function generateEquationParagraph(input, zOrder = 0) {
|
|
|
22249
22505
|
return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${generateEquationXml(script, zOrder)}</hp:run></hp:p>`;
|
|
22250
22506
|
}
|
|
22251
22507
|
|
|
22252
|
-
// src/hwpx/chart-gen.ts
|
|
22253
|
-
var XML_ESC = { "&": "&", "<": "<", ">": ">" };
|
|
22254
|
-
var xmlEscape = (s) => s.replace(/[&<>]/g, (c) => XML_ESC[c]);
|
|
22255
|
-
var CHART_TYPES = {
|
|
22256
|
-
0: { el: "barChart", dir: "col", grp: "clustered" },
|
|
22257
|
-
1: { el: "barChart", dir: "col", grp: "stacked", overlap: 100 },
|
|
22258
|
-
2: { el: "lineChart", grp: "standard", marker: true },
|
|
22259
|
-
3: { el: "barChart", dir: "bar", grp: "clustered" },
|
|
22260
|
-
4: { el: "barChart", dir: "bar", grp: "stacked", overlap: 100 },
|
|
22261
|
-
5: { el: "scatterChart", scatter: true },
|
|
22262
|
-
6: { el: "pieChart", pie: true },
|
|
22263
|
-
7: { el: "pieChart", pie: true, explode: true },
|
|
22264
|
-
8: { el: "doughnutChart", pie: true, hole: 50 },
|
|
22265
|
-
9: { el: "areaChart", grp: "standard" },
|
|
22266
|
-
10: { el: "areaChart", grp: "stacked" },
|
|
22267
|
-
11: { el: "radarChart", radar: true },
|
|
22268
|
-
12: { el: "bar3DChart", dir: "col", grp: "clustered" },
|
|
22269
|
-
13: { el: "bar3DChart", dir: "col", grp: "stacked", overlap: 100 },
|
|
22270
|
-
14: { el: "bar3DChart", dir: "bar", grp: "clustered" },
|
|
22271
|
-
15: { el: "bar3DChart", dir: "bar", grp: "stacked", overlap: 100 },
|
|
22272
|
-
16: { el: "pie3DChart", pie: true },
|
|
22273
|
-
17: { el: "pie3DChart", pie: true, explode: true },
|
|
22274
|
-
18: { el: "area3DChart", grp: "standard" },
|
|
22275
|
-
19: { el: "area3DChart", grp: "stacked" }
|
|
22276
|
-
};
|
|
22277
|
-
var CHART_ALIAS = {
|
|
22278
|
-
column: 0,
|
|
22279
|
-
col: 0,
|
|
22280
|
-
\uC138\uB85C\uB9C9\uB300: 0,
|
|
22281
|
-
\uB9C9\uB300: 0,
|
|
22282
|
-
column_stacked: 1,
|
|
22283
|
-
\uC138\uB85C\uB9C9\uB300_\uB204\uC801: 1,
|
|
22284
|
-
line: 2,
|
|
22285
|
-
\uC120: 2,
|
|
22286
|
-
\uAEBE\uC740\uC120: 2,
|
|
22287
|
-
bar: 3,
|
|
22288
|
-
\uAC00\uB85C\uB9C9\uB300: 3,
|
|
22289
|
-
bar_stacked: 4,
|
|
22290
|
-
scatter: 5,
|
|
22291
|
-
\uBD84\uC0B0: 5,
|
|
22292
|
-
pie: 6,
|
|
22293
|
-
\uC6D0: 6,
|
|
22294
|
-
\uD30C\uC774: 6,
|
|
22295
|
-
pie_explode: 7,
|
|
22296
|
-
doughnut: 8,
|
|
22297
|
-
donut: 8,
|
|
22298
|
-
\uB3C4\uB11B: 8,
|
|
22299
|
-
area: 9,
|
|
22300
|
-
\uC601\uC5ED: 9,
|
|
22301
|
-
area_stacked: 10,
|
|
22302
|
-
radar: 11,
|
|
22303
|
-
\uBC29\uC0AC\uD615: 11,
|
|
22304
|
-
bar3d: 12,
|
|
22305
|
-
column3d: 12,
|
|
22306
|
-
pie3d: 16
|
|
22307
|
-
};
|
|
22308
|
-
function chartSpec(t) {
|
|
22309
|
-
if (!t) return CHART_TYPES[0];
|
|
22310
|
-
const key = CHART_ALIAS[t.toLowerCase()] ?? Number(t);
|
|
22311
|
-
return CHART_TYPES[key] ?? CHART_TYPES[0];
|
|
22312
|
-
}
|
|
22313
|
-
var HU_PER_MM = 7200 / 25.4;
|
|
22314
|
-
var RESERVED_KEYS = /* @__PURE__ */ new Set(["type", "cat", "size", "colors", "point_colors", "title"]);
|
|
22315
|
-
function parseChartFence(text) {
|
|
22316
|
-
let type;
|
|
22317
|
-
let cat = null;
|
|
22318
|
-
let widthMm = 32250 / HU_PER_MM;
|
|
22319
|
-
let heightMm = 18750 / HU_PER_MM;
|
|
22320
|
-
let colors = null;
|
|
22321
|
-
let pointColors = null;
|
|
22322
|
-
const series = [];
|
|
22323
|
-
for (const rawLine of text.split("\n")) {
|
|
22324
|
-
const line = rawLine.trim();
|
|
22325
|
-
if (!line || line.startsWith("#")) continue;
|
|
22326
|
-
const colon = line.search(/[::]/);
|
|
22327
|
-
if (colon <= 0) continue;
|
|
22328
|
-
const key = line.slice(0, colon).trim();
|
|
22329
|
-
const value = line.slice(colon + 1).trim();
|
|
22330
|
-
const keyLower = key.toLowerCase();
|
|
22331
|
-
if (keyLower === "type") {
|
|
22332
|
-
type = value;
|
|
22333
|
-
} else if (keyLower === "cat") {
|
|
22334
|
-
cat = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
22335
|
-
} else if (keyLower === "size") {
|
|
22336
|
-
const m = value.match(/^(\d+(?:\.\d+)?)\s*[x×]\s*(\d+(?:\.\d+)?)$/i);
|
|
22337
|
-
if (m) {
|
|
22338
|
-
widthMm = Number(m[1]);
|
|
22339
|
-
heightMm = Number(m[2]);
|
|
22340
|
-
}
|
|
22341
|
-
} else if (keyLower === "colors") {
|
|
22342
|
-
colors = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
22343
|
-
} else if (keyLower === "point_colors") {
|
|
22344
|
-
pointColors = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
22345
|
-
} else if (keyLower === "title") {
|
|
22346
|
-
} else if (!RESERVED_KEYS.has(keyLower)) {
|
|
22347
|
-
const nums = value.split(",").map((s) => Number(s.trim()));
|
|
22348
|
-
if (nums.length > 0 && nums.every((n) => Number.isFinite(n))) {
|
|
22349
|
-
series.push({ name: key, values: nums });
|
|
22350
|
-
}
|
|
22351
|
-
}
|
|
22352
|
-
}
|
|
22353
|
-
if (series.length === 0) return null;
|
|
22354
|
-
const spec = chartSpec(type);
|
|
22355
|
-
const catFinal = cat ?? series[0].values.map((_, i) => `\uD56D\uBAA9 ${i + 1}`);
|
|
22356
|
-
let finalSeries = spec.pie ? [series[0]] : series;
|
|
22357
|
-
finalSeries = finalSeries.map((s) => ({ ...s }));
|
|
22358
|
-
if (spec.pie) {
|
|
22359
|
-
const slice = colors ?? pointColors;
|
|
22360
|
-
if (slice) finalSeries[0].pointColors = slice;
|
|
22361
|
-
} else {
|
|
22362
|
-
if (colors) finalSeries.forEach((s, i) => {
|
|
22363
|
-
s.color = colors[i % colors.length];
|
|
22364
|
-
});
|
|
22365
|
-
if (pointColors && finalSeries[0]) finalSeries[0].pointColors = pointColors;
|
|
22366
|
-
}
|
|
22367
|
-
return {
|
|
22368
|
-
spec,
|
|
22369
|
-
cat: catFinal,
|
|
22370
|
-
series: finalSeries,
|
|
22371
|
-
widthHu: Math.round(widthMm * HU_PER_MM),
|
|
22372
|
-
heightHu: Math.round(heightMm * HU_PER_MM)
|
|
22373
|
-
};
|
|
22374
|
-
}
|
|
22375
|
-
var colLetter = (i) => String.fromCharCode(66 + i);
|
|
22376
|
-
function strCachePts(vals) {
|
|
22377
|
-
return `<c:ptCount val="${vals.length}"/>` + vals.map((v, i) => `<c:pt idx="${i}"><c:v>${xmlEscape(v)}</c:v></c:pt>`).join("");
|
|
22378
|
-
}
|
|
22379
|
-
function numCachePts(vals) {
|
|
22380
|
-
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("");
|
|
22381
|
-
}
|
|
22382
|
-
function chartColorFill(color) {
|
|
22383
|
-
if (color == null) return null;
|
|
22384
|
-
const c = color.trim();
|
|
22385
|
-
if (/^accent[1-6]$/i.test(c)) return `<a:solidFill><a:schemeClr val="${c.toLowerCase()}"/></a:solidFill>`;
|
|
22386
|
-
const hex = c.replace(/^#/, "").toUpperCase();
|
|
22387
|
-
if (/^[0-9A-F]{6}$/.test(hex)) return `<a:solidFill><a:srgbClr val="${hex}"/></a:solidFill>`;
|
|
22388
|
-
return null;
|
|
22389
|
-
}
|
|
22390
|
-
function serSpPr(color, stroke) {
|
|
22391
|
-
const f = chartColorFill(color);
|
|
22392
|
-
if (!f) return "<c:spPr/>";
|
|
22393
|
-
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>`;
|
|
22394
|
-
}
|
|
22395
|
-
function dPtXml(pointColors, pie) {
|
|
22396
|
-
if (!pointColors?.length) return "";
|
|
22397
|
-
return pointColors.map((col, i) => {
|
|
22398
|
-
const f = chartColorFill(col);
|
|
22399
|
-
if (!f) return "";
|
|
22400
|
-
const mid = pie ? '<c:invertIfNegative val="0"/><c:bubble3D val="0"/><c:explosion val="0"/>' : '<c:bubble3D val="0"/>';
|
|
22401
|
-
return `<c:dPt><c:idx val="${i}"/>${mid}<c:spPr>${f}</c:spPr></c:dPt>`;
|
|
22402
|
-
}).join("");
|
|
22403
|
-
}
|
|
22404
|
-
function stdSer(idx, name, cat, values, explode, color, pointColors, stroke, pie) {
|
|
22405
|
-
const cl = colLetter(idx);
|
|
22406
|
-
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>`;
|
|
22407
|
-
}
|
|
22408
|
-
function scatterSer(idx, name, xvals, yvals) {
|
|
22409
|
-
const cl = colLetter(idx);
|
|
22410
|
-
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>`;
|
|
22411
|
-
}
|
|
22412
|
-
function catAxXml(id, pos, cross) {
|
|
22413
|
-
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>`;
|
|
22414
|
-
}
|
|
22415
|
-
function valAxXml(id, pos, cross) {
|
|
22416
|
-
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>`;
|
|
22417
|
-
}
|
|
22418
|
-
function buildChartSpaceXml(fence) {
|
|
22419
|
-
const { spec, cat, series } = fence;
|
|
22420
|
-
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"';
|
|
22421
|
-
const ax1 = "111111111";
|
|
22422
|
-
const ax2 = "222222222";
|
|
22423
|
-
let plot;
|
|
22424
|
-
if (spec.scatter) {
|
|
22425
|
-
const n = Math.max(0, ...series.map((s) => s.values.length));
|
|
22426
|
-
const xs = Array.from({ length: n }, (_, i) => {
|
|
22427
|
-
const c = cat[i];
|
|
22428
|
-
const v = Number(c);
|
|
22429
|
-
return c !== void 0 && c !== "" && Number.isFinite(v) ? v : i + 1;
|
|
22430
|
-
});
|
|
22431
|
-
const sers = series.map((s, i) => scatterSer(i, s.name, xs, s.values)).join("");
|
|
22432
|
-
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);
|
|
22433
|
-
} else if (spec.pie) {
|
|
22434
|
-
const s0 = series[0];
|
|
22435
|
-
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}>`;
|
|
22436
|
-
} else {
|
|
22437
|
-
const stroke = spec.el === "lineChart" || spec.el === "radarChart" || !!spec.radar;
|
|
22438
|
-
const sers = series.map((s, i) => stdSer(i, s.name, cat, s.values, false, s.color, s.pointColors, stroke, false)).join("");
|
|
22439
|
-
const horiz = spec.dir === "bar";
|
|
22440
|
-
let inner = "";
|
|
22441
|
-
if (spec.dir) inner += `<c:barDir val="${spec.dir}"/>`;
|
|
22442
|
-
if (spec.grp) inner += `<c:grouping val="${spec.grp}"/>`;
|
|
22443
|
-
if (spec.radar) inner += `<c:radarStyle val="standard"/>`;
|
|
22444
|
-
inner += `<c:varyColors val="0"/>${sers}`;
|
|
22445
|
-
if (spec.marker) inner += `<c:marker val="1"/>`;
|
|
22446
|
-
if (spec.el.startsWith("bar")) inner += `<c:gapWidth val="150"/><c:overlap val="${spec.overlap ?? 0}"/>`;
|
|
22447
|
-
inner += `<c:axId val="${ax1}"/><c:axId val="${ax2}"/>`;
|
|
22448
|
-
plot = `<c:${spec.el}>${inner}</c:${spec.el}>` + catAxXml(ax1, horiz ? "l" : "b", ax2) + valAxXml(ax2, horiz ? "b" : "l", ax1);
|
|
22449
|
-
}
|
|
22450
|
-
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>`;
|
|
22451
|
-
}
|
|
22452
|
-
function buildChartElementXml(partName, widthHu, heightHu, id) {
|
|
22453
|
-
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>`;
|
|
22454
|
-
}
|
|
22455
|
-
|
|
22456
22508
|
// src/hwpx/gen-section.ts
|
|
22457
22509
|
function generateSecPr(gongmun) {
|
|
22458
22510
|
const m = gongmun ? {
|
|
@@ -22894,6 +22946,21 @@ var MIME = {
|
|
|
22894
22946
|
bmp: "image/bmp",
|
|
22895
22947
|
gif: "image/gif"
|
|
22896
22948
|
};
|
|
22949
|
+
function imageMagicMatches(buf, ext) {
|
|
22950
|
+
switch (ext) {
|
|
22951
|
+
case "png":
|
|
22952
|
+
return buf.length >= 8 && buf[0] === 137 && buf[1] === 80 && buf[2] === 78 && buf[3] === 71;
|
|
22953
|
+
case "jpg":
|
|
22954
|
+
case "jpeg":
|
|
22955
|
+
return buf.length >= 3 && buf[0] === 255 && buf[1] === 216 && buf[2] === 255;
|
|
22956
|
+
case "bmp":
|
|
22957
|
+
return buf.length >= 2 && buf[0] === 66 && buf[1] === 77;
|
|
22958
|
+
case "gif":
|
|
22959
|
+
return buf.length >= 6 && buf[0] === 71 && buf[1] === 73 && buf[2] === 70;
|
|
22960
|
+
default:
|
|
22961
|
+
return false;
|
|
22962
|
+
}
|
|
22963
|
+
}
|
|
22897
22964
|
function glyphEm(code) {
|
|
22898
22965
|
if (code < 32) return 0;
|
|
22899
22966
|
if (code <= 126) return 0.5;
|
|
@@ -22908,19 +22975,19 @@ function measureMm(text, emMm) {
|
|
|
22908
22975
|
function collectSites(scan) {
|
|
22909
22976
|
const sites = [];
|
|
22910
22977
|
for (const p of scan.bodyParagraphs) sites.push({ para: p });
|
|
22911
|
-
const walkTables = (tables, depth) => {
|
|
22978
|
+
const walkTables = (tables, depth, outer) => {
|
|
22912
22979
|
if (depth > 16) return;
|
|
22913
22980
|
for (const t of tables) {
|
|
22914
22981
|
for (const row of t.rows) {
|
|
22915
22982
|
for (const cell of row) {
|
|
22916
|
-
for (const p of cell.paragraphs) sites.push({ para: p, cell, table: t });
|
|
22917
|
-
walkTables(cell.tables, depth + 1);
|
|
22983
|
+
for (const p of cell.paragraphs) sites.push({ para: p, cell, table: t, nested: depth > 0, outer: outer.length ? outer : void 0 });
|
|
22984
|
+
walkTables(cell.tables, depth + 1, [...outer, { cell, table: t }]);
|
|
22918
22985
|
}
|
|
22919
22986
|
}
|
|
22920
22987
|
}
|
|
22921
22988
|
};
|
|
22922
|
-
walkTables(scan.tables, 0);
|
|
22923
|
-
walkTables(scan.orphanTables, 0);
|
|
22989
|
+
walkTables(scan.tables, 0, []);
|
|
22990
|
+
walkTables(scan.orphanTables, 0, []);
|
|
22924
22991
|
sites.sort((a, b) => a.para.start - b.para.start);
|
|
22925
22992
|
return sites;
|
|
22926
22993
|
}
|
|
@@ -22934,7 +23001,10 @@ function paraOpenTag(xml, para) {
|
|
|
22934
23001
|
}
|
|
22935
23002
|
function anchorRunInfo(xml, para, anchor) {
|
|
22936
23003
|
let tr = para.tRanges.find((r) => !r.selfClosing && xml.slice(r.contentStart, r.contentEnd).includes(anchor));
|
|
22937
|
-
if (!tr)
|
|
23004
|
+
if (!tr) {
|
|
23005
|
+
const head = anchor[0];
|
|
23006
|
+
tr = para.tRanges.find((r) => !r.selfClosing && xml.slice(r.contentStart, r.contentEnd).includes(head)) ?? para.tRanges[para.tRanges.length - 1];
|
|
23007
|
+
}
|
|
22938
23008
|
if (!tr) return null;
|
|
22939
23009
|
const before = xml.slice(Math.max(0, para.start), tr.contentStart);
|
|
22940
23010
|
const runOpen = [...before.matchAll(/<([A-Za-z0-9]+):run\b[^>]*>/g)].pop();
|
|
@@ -22973,14 +23043,17 @@ function cellContentWidthMm(xml, cell) {
|
|
|
22973
23043
|
}
|
|
22974
23044
|
function cellLeftOffsetMm(xml, table, cell) {
|
|
22975
23045
|
if (cell.colAddr === void 0) return 0;
|
|
22976
|
-
const
|
|
22977
|
-
|
|
22978
|
-
|
|
22979
|
-
|
|
22980
|
-
|
|
22981
|
-
|
|
22982
|
-
|
|
23046
|
+
const colW = /* @__PURE__ */ new Map();
|
|
23047
|
+
for (const row of table.rows) {
|
|
23048
|
+
for (const c of row) {
|
|
23049
|
+
if (c.colAddr === void 0 || colW.has(c.colAddr)) continue;
|
|
23050
|
+
if (c.colSpan > 1) continue;
|
|
23051
|
+
const w = cellSzWidthHu(xml, c);
|
|
23052
|
+
if (w) colW.set(c.colAddr, w);
|
|
23053
|
+
}
|
|
22983
23054
|
}
|
|
23055
|
+
let sum = 0;
|
|
23056
|
+
for (let col = 0; col < cell.colAddr; col++) sum += colW.get(col) ?? 0;
|
|
22984
23057
|
return sum / HU_PER_MM2;
|
|
22985
23058
|
}
|
|
22986
23059
|
function bodyColumnWidthMm(xml) {
|
|
@@ -22999,7 +23072,7 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
22999
23072
|
if (ops.length === 0) throw new KordocError("place_seal: \uBC30\uCE58\uD560 \uB3C4\uC7A5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
23000
23073
|
const u8 = new Uint8Array(hwpxBuffer);
|
|
23001
23074
|
const zip = await JSZip8.loadAsync(hwpxBuffer);
|
|
23002
|
-
const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
|
|
23075
|
+
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));
|
|
23003
23076
|
if (sectionPaths.length === 0) throw new KordocError("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
23004
23077
|
const manifestPath = Object.keys(zip.files).find((name) => /\.hpf$/i.test(name));
|
|
23005
23078
|
const headerPath = Object.keys(zip.files).find((name) => /(^|\/)header\.xml$/i.test(name));
|
|
@@ -23045,6 +23118,7 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
23045
23118
|
if (!op.image || op.image.length === 0) throw new KordocError("place_seal: \uB3C4\uC7A5 \uC774\uBBF8\uC9C0\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4");
|
|
23046
23119
|
const ext = (op.ext ?? "png").toLowerCase();
|
|
23047
23120
|
if (!MIME[ext]) throw new KordocError(`place_seal: \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC774\uBBF8\uC9C0 \uD655\uC7A5\uC790 .${ext} (png/jpg/bmp/gif)`);
|
|
23121
|
+
if (!imageMagicMatches(op.image, ext)) throw new KordocError(`place_seal: \uC774\uBBF8\uC9C0 \uB0B4\uC6A9\uC774 .${ext} \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4 (\uB9E4\uC9C1\uBC14\uC774\uD2B8 \uBD88\uC77C\uCE58)`);
|
|
23048
23122
|
const wantOcc = op.occurrence ?? 0;
|
|
23049
23123
|
let found = null;
|
|
23050
23124
|
let total = 0;
|
|
@@ -23093,7 +23167,7 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
23093
23167
|
const lineHMm = emMm;
|
|
23094
23168
|
const startXMm = measureMm(site.para.text.slice(0, idxInText), emMm);
|
|
23095
23169
|
const anchorWMm = measureMm(op.anchor, emMm);
|
|
23096
|
-
const sizeMm = op.sizeMm
|
|
23170
|
+
const sizeMm = op.sizeMm != null && Number.isFinite(op.sizeMm) && op.sizeMm > 0 ? op.sizeMm : Math.max(7, Math.min(18, lineHMm * 1.6));
|
|
23097
23171
|
const availMm = (site.cell ? cellContentWidthMm(xml, site.cell) : null) ?? bodyColumnWidthMm(xml);
|
|
23098
23172
|
const paraPrId = attrOf(paraOpenTag(xml, site.para), "paraPrIDRef") ?? "0";
|
|
23099
23173
|
const align = styles?.paraAlign.get(paraPrId);
|
|
@@ -23107,7 +23181,7 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
23107
23181
|
if (mode === "auto") {
|
|
23108
23182
|
mode = availMm - (alignShiftMm + startXMm + anchorWMm) >= sizeMm + 2 ? "right" : "overlap";
|
|
23109
23183
|
}
|
|
23110
|
-
const cellShiftMm = site.cell && site.table ? cellLeftOffsetMm(xml, site.table, site.cell) : 0;
|
|
23184
|
+
const cellShiftMm = site.cell && site.table ? cellLeftOffsetMm(xml, site.table, site.cell) + (site.outer ?? []).reduce((s, o) => s + cellLeftOffsetMm(xml, o.table, o.cell), 0) : 0;
|
|
23111
23185
|
const posXMm = (mode === "right" ? startXMm + anchorWMm + 2 : startXMm + anchorWMm / 2 - sizeMm / 2) + alignShiftMm + cellShiftMm + (op.dxMm ?? 0);
|
|
23112
23186
|
const posYMm = -(sizeMm - lineHMm) / 2 + (op.dyMm ?? 0);
|
|
23113
23187
|
const n = nextImageNum();
|
|
@@ -23125,6 +23199,12 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
23125
23199
|
end: run.insertAt,
|
|
23126
23200
|
replacement: `<${run.prefix}:run charPrIDRef="${run.charPr}">${pic}</${run.prefix}:run>`
|
|
23127
23201
|
});
|
|
23202
|
+
const warnings = [];
|
|
23203
|
+
const paraSeg = xml.slice(site.para.start, run.insertAt);
|
|
23204
|
+
if (/<[A-Za-z0-9]+:tab\b/.test(paraSeg)) warnings.push("\uD0ED\uC774 \uB4E0 \uBB38\uB2E8 \u2014 \uB3C4\uC7A5 \uAC00\uB85C \uC704\uCE58\uAC00 \uADFC\uC0AC\uAC12\uC785\uB2C8\uB2E4 (dx \uB85C \uBCF4\uC815)");
|
|
23205
|
+
if (/<[A-Za-z0-9]+:(lineBreak|br)\b/.test(paraSeg)) warnings.push("\uC904\uBC14\uAFC8\uC774 \uB4E0 \uBB38\uB2E8 \u2014 \uC575\uCEE4\uAC00 2\uBC88\uC9F8 \uC904 \uC774\uD558\uBA74 \uC138\uB85C \uC704\uCE58\uAC00 \uC5B4\uAE0B\uB0A0 \uC218 \uC788\uC2B5\uB2C8\uB2E4 (dy \uB85C \uBCF4\uC815)");
|
|
23206
|
+
if (site.nested) warnings.push("\uC911\uCCA9\uD45C(\uD45C \uC548 \uD45C) \uC140 \uC575\uCEE4 \u2014 \uBC14\uAE65 \uC140 \uC624\uD504\uC14B\uC744 \uCCB4\uC778\uC73C\uB85C \uAC00\uC0B0\uD558\uB098 \uC140 \uC5EC\uBC31\xB7\uC815\uB82C\uC740 \uADFC\uC0AC\uC785\uB2C8\uB2E4 (\uD544\uC694 \uC2DC dx \uB85C \uBCF4\uC815)");
|
|
23207
|
+
if (site.para.inTextbox) warnings.push("\uAE00\uC0C1\uC790 \uC575\uCEE4 \u2014 \uAE00\uC0C1\uC790 \uAE30\uD558\uB97C \uBC18\uC601\uD558\uC9C0 \uC54A\uC544 \uC815\uB82C \uBCF4\uC815\uC774 \uADFC\uC0AC\uC785\uB2C8\uB2E4 (dx/dy \uB85C \uBCF4\uC815)");
|
|
23128
23208
|
placed.push({
|
|
23129
23209
|
anchor: op.anchor,
|
|
23130
23210
|
occurrence: wantOcc,
|
|
@@ -23133,7 +23213,8 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
23133
23213
|
posXMm: Math.round(posXMm * 100) / 100,
|
|
23134
23214
|
posYMm: Math.round(posYMm * 100) / 100,
|
|
23135
23215
|
sizeMm: Math.round(sizeMm * 100) / 100,
|
|
23136
|
-
entry
|
|
23216
|
+
entry,
|
|
23217
|
+
...warnings.length > 0 ? { warnings } : {}
|
|
23137
23218
|
});
|
|
23138
23219
|
}
|
|
23139
23220
|
const encoder = new TextEncoder();
|
|
@@ -24660,7 +24741,8 @@ async function patchHwp(original, editedMarkdown, options) {
|
|
|
24660
24741
|
if (options?.verify !== false) {
|
|
24661
24742
|
try {
|
|
24662
24743
|
const reparsed = parseHwp5Document(Buffer.from(data));
|
|
24663
|
-
|
|
24744
|
+
const normBr = (u) => ({ ...u, raw: u.raw.replace(/<br\s*\/?\s*>/gi, "\n") });
|
|
24745
|
+
verification = diffUnitLists(splitMarkdownUnits(reparsed.markdown).map(normBr), editedUnits.map(normBr));
|
|
24664
24746
|
} catch (err) {
|
|
24665
24747
|
return { success: false, applied, skipped, error: `\uD328\uCE58\uBCF8 \uC7AC\uD30C\uC2F1 \uC2E4\uD328 \u2014 \uD328\uCE58 \uC911\uB2E8: ${msg(err)}` };
|
|
24666
24748
|
}
|
|
@@ -24783,7 +24865,7 @@ function handleModified(orig, edited, ctx) {
|
|
|
24783
24865
|
function patchParagraph(block, orig, edited, ctx, skip) {
|
|
24784
24866
|
const mapping = ctx.paraMap.get(orig.blockIdx);
|
|
24785
24867
|
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)");
|
|
24786
|
-
const restoreBr = (s) => s.replace(
|
|
24868
|
+
const restoreBr = (s) => s.replace(/(?:\s*<br\s*\/?\s*>\s*)+/gi, "\n");
|
|
24787
24869
|
let newPlain = restoreBr(textUnitToPlain(edited.raw, block));
|
|
24788
24870
|
if (block.text && block.text.includes("\n") && !newPlain.includes("\n")) {
|
|
24789
24871
|
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)");
|
|
@@ -24809,7 +24891,7 @@ function patchParagraph(block, orig, edited, ctx, skip) {
|
|
|
24809
24891
|
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) });
|
|
24810
24892
|
}
|
|
24811
24893
|
}
|
|
24812
|
-
const origPlain = restoreBr(textUnitToPlain(orig.raw, block));
|
|
24894
|
+
const origPlain = block.text != null ? block.text : restoreBr(textUnitToPlain(orig.raw, block));
|
|
24813
24895
|
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");
|
|
24814
24896
|
if (sanitizeText(newPlain) !== newPlain) {
|
|
24815
24897
|
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");
|
|
@@ -26567,6 +26649,8 @@ function sniffMime(name, bytes) {
|
|
|
26567
26649
|
}
|
|
26568
26650
|
async function renderHwpxToSvg(input, options) {
|
|
26569
26651
|
const maxImg = options?.maxImageBytes ?? 40 * 1024 * 1024;
|
|
26652
|
+
const ab = input instanceof Uint8Array ? input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength) : input;
|
|
26653
|
+
precheckZipSize(ab, MAX_DECOMPRESS_SIZE, MAX_ZIP_ENTRIES);
|
|
26570
26654
|
let zip;
|
|
26571
26655
|
try {
|
|
26572
26656
|
zip = await JSZip12.loadAsync(input);
|
|
@@ -26779,7 +26863,7 @@ async function parseHwp(buffer, options) {
|
|
|
26779
26863
|
async function parsePdf(buffer, options) {
|
|
26780
26864
|
let parsePdfDocument;
|
|
26781
26865
|
try {
|
|
26782
|
-
const mod = await import("./parser-
|
|
26866
|
+
const mod = await import("./parser-GWL72XYS.js");
|
|
26783
26867
|
parsePdfDocument = mod.parsePdfDocument;
|
|
26784
26868
|
} catch {
|
|
26785
26869
|
return {
|