kordoc 3.12.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -1
- package/dist/{-OPZIF3QT.js → -EYPKRLMN.js} +13 -7
- package/dist/{chunk-ILR7GF3W.js → chunk-734GJLXH.js} +522 -135
- package/dist/chunk-734GJLXH.js.map +1 -0
- package/dist/chunk-DCZVOIEO.cjs.map +1 -1
- package/dist/{chunk-2C5GCXPJ.cjs → chunk-DMBTOJK4.cjs} +5 -5
- package/dist/chunk-DMBTOJK4.cjs.map +1 -0
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-RUYSNNYZ.js → chunk-Q3IHI3E6.js} +325 -29
- package/dist/chunk-Q3IHI3E6.js.map +1 -0
- package/dist/{chunk-BUDM6ULT.js → chunk-Q5ZPWQID.js} +5 -5
- package/dist/{chunk-BUDM6ULT.js.map → chunk-Q5ZPWQID.js.map} +1 -1
- package/dist/{chunk-7Z43WEML.js → chunk-SCFFABCT.js} +2 -2
- package/dist/{chunk-NGKIAZ6G.js → chunk-ZRNYYEE6.js} +5 -5
- package/dist/{chunk-NGKIAZ6G.js.map → chunk-ZRNYYEE6.js.map} +1 -1
- package/dist/cli.js +71 -10
- package/dist/cli.js.map +1 -1
- package/dist/formula-5NKVS2LR.cjs.map +1 -1
- package/dist/index.cjs +1018 -335
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -6
- package/dist/index.d.ts +80 -6
- package/dist/index.js +897 -214
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +33 -10
- package/dist/mcp.js.map +1 -1
- package/dist/page-range-P7SDW6LR.cjs.map +1 -1
- package/dist/{parser-5FSEFR3R.js → parser-76JSTEP3.js} +107 -7
- package/dist/parser-76JSTEP3.js.map +1 -0
- package/dist/{parser-PCTX7LGN.cjs → parser-O2SD4DFR.cjs} +118 -18
- package/dist/parser-O2SD4DFR.cjs.map +1 -0
- package/dist/{parser-AWEGMHHV.js → parser-SNBQZO5E.js} +106 -6
- package/dist/parser-SNBQZO5E.js.map +1 -0
- package/dist/provider-G4C2V2PD.cjs.map +1 -1
- package/dist/render-LDI3LO2P.js +9 -0
- package/dist/{watch-Y7BAYXJE.js → watch-LEK5U5P6.js} +5 -5
- package/package.json +4 -3
- package/dist/chunk-2C5GCXPJ.cjs.map +0 -1
- package/dist/chunk-ILR7GF3W.js.map +0 -1
- package/dist/chunk-RUYSNNYZ.js.map +0 -1
- package/dist/parser-5FSEFR3R.js.map +0 -1
- package/dist/parser-AWEGMHHV.js.map +0 -1
- package/dist/parser-PCTX7LGN.cjs.map +0 -1
- package/dist/render-ATQNKOT2.js +0 -9
- /package/dist/{-OPZIF3QT.js.map → -EYPKRLMN.js.map} +0 -0
- /package/dist/{chunk-7Z43WEML.js.map → chunk-SCFFABCT.js.map} +0 -0
- /package/dist/{render-ATQNKOT2.js.map → render-LDI3LO2P.js.map} +0 -0
- /package/dist/{watch-Y7BAYXJE.js.map → watch-LEK5U5P6.js.map} +0 -0
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
extractTextFromNode,
|
|
19
19
|
findChildByLocalName,
|
|
20
20
|
fitRatioForFewerLines
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-734GJLXH.js";
|
|
22
22
|
import {
|
|
23
23
|
HEADING_RATIO_H1,
|
|
24
24
|
HEADING_RATIO_H2,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
convertTableToText,
|
|
31
31
|
flattenLayoutTables,
|
|
32
32
|
mapPuaText
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-Q5ZPWQID.js";
|
|
34
34
|
import {
|
|
35
35
|
parsePageRange
|
|
36
36
|
} from "./chunk-MOL7MDBG.js";
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
sanitizeHref,
|
|
45
45
|
stripDtd,
|
|
46
46
|
toArrayBuffer
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-SCFFABCT.js";
|
|
48
48
|
|
|
49
49
|
// src/index.ts
|
|
50
50
|
import { readFile } from "fs/promises";
|
|
@@ -640,10 +640,22 @@ function findEnclosingBrackets(eqString, startIdx) {
|
|
|
640
640
|
}
|
|
641
641
|
return null;
|
|
642
642
|
}
|
|
643
|
+
function maskLiteralSpans(eqString) {
|
|
644
|
+
return eqString.replace(/"[^"]*"/g, (m) => "\uFFFF".repeat(m.length)).replace(/\\text\{[^}]*\}/g, (m) => "\uFFFF".repeat(m.length));
|
|
645
|
+
}
|
|
646
|
+
function findKeywordToken(eqString, word, from = 0) {
|
|
647
|
+
const masked = maskLiteralSpans(eqString);
|
|
648
|
+
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] === " ";
|
|
651
|
+
if (okL && okR) return i;
|
|
652
|
+
}
|
|
653
|
+
return -1;
|
|
654
|
+
}
|
|
643
655
|
function replaceFrac(eqString) {
|
|
644
656
|
const hmlFrac = "over";
|
|
645
657
|
while (true) {
|
|
646
|
-
const cursor = eqString
|
|
658
|
+
const cursor = findKeywordToken(eqString, hmlFrac);
|
|
647
659
|
if (cursor === -1) break;
|
|
648
660
|
try {
|
|
649
661
|
const [numStart, numEnd] = findBrackets(eqString, cursor, 0);
|
|
@@ -659,12 +671,12 @@ function replaceFrac(eqString) {
|
|
|
659
671
|
}
|
|
660
672
|
function replaceRootOf(eqString) {
|
|
661
673
|
while (true) {
|
|
662
|
-
const rootCursor = eqString
|
|
674
|
+
const rootCursor = findKeywordToken(eqString, "root");
|
|
663
675
|
if (rootCursor === -1) break;
|
|
664
676
|
try {
|
|
665
|
-
const ofCursor = eqString.indexOf("of");
|
|
666
|
-
if (ofCursor === -1) return eqString;
|
|
667
677
|
const elem1 = findBrackets(eqString, rootCursor, 1);
|
|
678
|
+
const ofCursor = findKeywordToken(eqString, "of", elem1[1]);
|
|
679
|
+
if (ofCursor === -1) return eqString;
|
|
668
680
|
const elem2 = findBrackets(eqString, ofCursor, 1);
|
|
669
681
|
const e1 = eqString.slice(elem1[0] + 1, elem1[1] - 1);
|
|
670
682
|
const e2 = eqString.slice(elem2[0] + 1, elem2[1] - 1);
|
|
@@ -2082,7 +2094,6 @@ function appendParaText(state, data, resolveControl) {
|
|
|
2082
2094
|
break;
|
|
2083
2095
|
}
|
|
2084
2096
|
result += "\n";
|
|
2085
|
-
if (i + 14 <= data.length) i += 14;
|
|
2086
2097
|
break;
|
|
2087
2098
|
}
|
|
2088
2099
|
case CHAR_PARA:
|
|
@@ -17955,6 +17966,7 @@ function collectOmmlRoots(p) {
|
|
|
17955
17966
|
const tag = el.localName || el.tagName?.replace(/^[^:]+:/, "") || "";
|
|
17956
17967
|
if (tag === "oMath" || tag === "oMathPara") {
|
|
17957
17968
|
out.push(el);
|
|
17969
|
+
} else if (tag === "txbxContent" || tag === "Fallback") {
|
|
17958
17970
|
} else {
|
|
17959
17971
|
walk(el);
|
|
17960
17972
|
}
|
|
@@ -18079,6 +18091,13 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18079
18091
|
for (const tr of trElements) {
|
|
18080
18092
|
const row = [];
|
|
18081
18093
|
let col = 0;
|
|
18094
|
+
const trPrEls = getChildElements(tr, "trPr");
|
|
18095
|
+
if (trPrEls.length > 0) {
|
|
18096
|
+
const gridBeforeEls = getChildElements(trPrEls[0], "gridBefore");
|
|
18097
|
+
if (gridBeforeEls.length > 0) {
|
|
18098
|
+
col = parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0;
|
|
18099
|
+
}
|
|
18100
|
+
}
|
|
18082
18101
|
for (const tc of getChildElements(tr, "tc")) {
|
|
18083
18102
|
let colSpan = 1;
|
|
18084
18103
|
let vMerge = null;
|
|
@@ -18093,12 +18112,28 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18093
18112
|
vMerge = getAttr(vMergeEls[0], "val") === "restart" ? "restart" : "continue";
|
|
18094
18113
|
}
|
|
18095
18114
|
}
|
|
18096
|
-
const text =
|
|
18115
|
+
const text = collectCellText(tc, styles, numbering, footnotes, rels, 0).join("\n");
|
|
18097
18116
|
row.push({ col, colSpan, vMerge, text });
|
|
18098
18117
|
col += colSpan;
|
|
18099
18118
|
}
|
|
18100
18119
|
rawRows.push(row);
|
|
18101
18120
|
}
|
|
18121
|
+
for (let r = 0; r < rawRows.length; r++) {
|
|
18122
|
+
for (const cell of rawRows[r]) {
|
|
18123
|
+
if (cell.vMerge !== "continue" || !cell.text) continue;
|
|
18124
|
+
let start;
|
|
18125
|
+
for (let pr = r - 1; pr >= 0 && !start; pr--) {
|
|
18126
|
+
start = rawRows[pr].find((pc) => pc.col === cell.col && pc.vMerge !== "continue");
|
|
18127
|
+
}
|
|
18128
|
+
if (start) {
|
|
18129
|
+
start.text = start.text ? `${start.text}
|
|
18130
|
+
${cell.text}` : cell.text;
|
|
18131
|
+
cell.text = "";
|
|
18132
|
+
} else {
|
|
18133
|
+
cell.vMerge = null;
|
|
18134
|
+
}
|
|
18135
|
+
}
|
|
18136
|
+
}
|
|
18102
18137
|
const cellRows = rawRows.map(
|
|
18103
18138
|
(row, r) => row.filter((cell) => cell.vMerge !== "continue").map((cell) => {
|
|
18104
18139
|
let rowSpan = 1;
|
|
@@ -18497,7 +18532,23 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18497
18532
|
(row) => row.map((cell) => cell ?? { text: "", colSpan: 1, rowSpan: 1 })
|
|
18498
18533
|
);
|
|
18499
18534
|
const table = buildTable(cellRows);
|
|
18535
|
+
const caption = extractShapeCaption(el);
|
|
18536
|
+
if (caption.text && caption.before) {
|
|
18537
|
+
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18538
|
+
}
|
|
18500
18539
|
blocks.push({ type: "table", table, pageNumber: sectionNum });
|
|
18540
|
+
if (caption.text && !caption.before) {
|
|
18541
|
+
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18542
|
+
}
|
|
18543
|
+
}
|
|
18544
|
+
function extractShapeCaption(tableEl) {
|
|
18545
|
+
const shape = findChild(tableEl, "SHAPEOBJECT");
|
|
18546
|
+
const caption = shape && findChild(shape, "CAPTION");
|
|
18547
|
+
if (!caption) return { text: "", before: false };
|
|
18548
|
+
const parts = [];
|
|
18549
|
+
collectCellText2(caption, parts, 0);
|
|
18550
|
+
const side = caption.getAttribute("Side") ?? "";
|
|
18551
|
+
return { text: parts.filter(Boolean).join("\n").trim(), before: side === "Top" || side === "Left" };
|
|
18501
18552
|
}
|
|
18502
18553
|
function extractCellText(cellEl) {
|
|
18503
18554
|
const textParts = [];
|
|
@@ -18572,6 +18623,81 @@ function countSections(body) {
|
|
|
18572
18623
|
}
|
|
18573
18624
|
|
|
18574
18625
|
// src/form/match.ts
|
|
18626
|
+
function parseYMD(v) {
|
|
18627
|
+
const d = v.replace(/\D/g, "");
|
|
18628
|
+
let y, m, day;
|
|
18629
|
+
if (d.length >= 8) {
|
|
18630
|
+
y = d.slice(0, 4);
|
|
18631
|
+
m = d.slice(4, 6);
|
|
18632
|
+
day = d.slice(6, 8);
|
|
18633
|
+
} else if (d.length === 6) {
|
|
18634
|
+
const yy = +d.slice(0, 2);
|
|
18635
|
+
y = String(yy <= 29 ? 2e3 + yy : 1900 + yy);
|
|
18636
|
+
m = d.slice(2, 4);
|
|
18637
|
+
day = d.slice(4, 6);
|
|
18638
|
+
} else return null;
|
|
18639
|
+
return { y, yy: y.slice(2), m, d: day };
|
|
18640
|
+
}
|
|
18641
|
+
function fmtDate(v, style) {
|
|
18642
|
+
const p = parseYMD(v);
|
|
18643
|
+
if (!p) return v;
|
|
18644
|
+
return (style || "yyyy-mm-dd").replace(/yyyy/g, p.y).replace(/yy/g, p.yy).replace(/mm/g, p.m).replace(/dd/g, p.d).replace(/m/g, String(+p.m)).replace(/d/g, String(+p.d));
|
|
18645
|
+
}
|
|
18646
|
+
function maskDigits(v, pattern) {
|
|
18647
|
+
const ds = v.replace(/\D/g, "");
|
|
18648
|
+
let i = 0;
|
|
18649
|
+
return pattern.replace(/#/g, () => ds[i++] ?? "");
|
|
18650
|
+
}
|
|
18651
|
+
function fmtPhone(v, style) {
|
|
18652
|
+
const d = v.replace(/\D/g, "");
|
|
18653
|
+
if (d.length < 9) return v;
|
|
18654
|
+
const a = d.slice(0, 3), b = d.slice(3, -4), c = d.slice(-4);
|
|
18655
|
+
switch (style) {
|
|
18656
|
+
case "digits":
|
|
18657
|
+
return d;
|
|
18658
|
+
case "dot":
|
|
18659
|
+
return `${a}.${b}.${c}`;
|
|
18660
|
+
case "space":
|
|
18661
|
+
return `${a} ${b} ${c}`;
|
|
18662
|
+
case "intl":
|
|
18663
|
+
return `+82-${d.slice(1, 3)}-${b}-${c}`;
|
|
18664
|
+
case "intl-paren":
|
|
18665
|
+
return `82)${d.slice(1, 3)}-${b}-${c}`;
|
|
18666
|
+
default:
|
|
18667
|
+
return `${a}-${b}-${c}`;
|
|
18668
|
+
}
|
|
18669
|
+
}
|
|
18670
|
+
function fmtRRN(v, style) {
|
|
18671
|
+
const d = v.replace(/\D/g, "");
|
|
18672
|
+
if (d.length !== 13) return v;
|
|
18673
|
+
switch (style) {
|
|
18674
|
+
case "digits":
|
|
18675
|
+
return d;
|
|
18676
|
+
case "front":
|
|
18677
|
+
return d.slice(0, 6);
|
|
18678
|
+
case "masked":
|
|
18679
|
+
return `${d.slice(0, 6)}-${d[6]}******`;
|
|
18680
|
+
default:
|
|
18681
|
+
return `${d.slice(0, 6)}-${d.slice(6)}`;
|
|
18682
|
+
}
|
|
18683
|
+
}
|
|
18684
|
+
function formatFillValue(value, format) {
|
|
18685
|
+
if (!format) return value;
|
|
18686
|
+
const ci = format.indexOf(":");
|
|
18687
|
+
const kind = ci >= 0 ? format.slice(0, ci) : format;
|
|
18688
|
+
const style = ci >= 0 ? format.slice(ci + 1) : "";
|
|
18689
|
+
if (kind === "date") return fmtDate(value, style);
|
|
18690
|
+
if (kind === "phone") return fmtPhone(value, style);
|
|
18691
|
+
if (kind === "rrn") return fmtRRN(value, style);
|
|
18692
|
+
if (kind === "mask") return maskDigits(value, style);
|
|
18693
|
+
if (kind === "digits") return value.replace(/\D/g, "");
|
|
18694
|
+
if (kind === "upper") return value.toUpperCase();
|
|
18695
|
+
if (kind === "lower") return value.toLowerCase();
|
|
18696
|
+
if (kind === "nospace") return value.replace(/\s+/g, "");
|
|
18697
|
+
if (format.includes("#")) return maskDigits(value, format);
|
|
18698
|
+
if (/(yyyy|yy|mm|dd)/.test(format)) return fmtDate(value, format);
|
|
18699
|
+
return value;
|
|
18700
|
+
}
|
|
18575
18701
|
var ValueCursor = class {
|
|
18576
18702
|
constructor(values) {
|
|
18577
18703
|
this.values = values;
|
|
@@ -18723,11 +18849,32 @@ function padInsertion(text, pos, value) {
|
|
|
18723
18849
|
}
|
|
18724
18850
|
function normalizeValues(values) {
|
|
18725
18851
|
const map = /* @__PURE__ */ new Map();
|
|
18726
|
-
for (const [label,
|
|
18727
|
-
|
|
18852
|
+
for (const [label, raw] of Object.entries(values)) {
|
|
18853
|
+
const { value, format } = typeof raw === "object" && !Array.isArray(raw) ? raw : { value: raw, format: void 0 };
|
|
18854
|
+
map.set(normalizeLabel(label), Array.isArray(value) ? value.map((v) => formatFillValue(v, format)) : formatFillValue(value, format));
|
|
18728
18855
|
}
|
|
18729
18856
|
return map;
|
|
18730
18857
|
}
|
|
18858
|
+
async function fillWithUniqueGuard(values, run) {
|
|
18859
|
+
const first = await run(values);
|
|
18860
|
+
const counts = /* @__PURE__ */ new Map();
|
|
18861
|
+
for (const f of first.filled) {
|
|
18862
|
+
if (f.key) counts.set(f.key, (counts.get(f.key) ?? 0) + 1);
|
|
18863
|
+
}
|
|
18864
|
+
const isArrayValue = (normKey) => {
|
|
18865
|
+
for (const [label, raw] of Object.entries(values)) {
|
|
18866
|
+
if (normalizeLabel(label) !== normKey) continue;
|
|
18867
|
+
return Array.isArray(typeof raw === "object" && !Array.isArray(raw) ? raw.value : raw);
|
|
18868
|
+
}
|
|
18869
|
+
return false;
|
|
18870
|
+
};
|
|
18871
|
+
const dup = new Set([...counts].filter(([k, n]) => n >= 2 && !isArrayValue(k)).map(([k]) => k));
|
|
18872
|
+
if (dup.size === 0) return { ...first, rejected: [] };
|
|
18873
|
+
const filtered = Object.fromEntries(Object.entries(values).filter(([label]) => !dup.has(normalizeLabel(label))));
|
|
18874
|
+
const second = await run(filtered);
|
|
18875
|
+
const rejected = Object.keys(values).filter((label) => dup.has(normalizeLabel(label)));
|
|
18876
|
+
return { ...second, rejected };
|
|
18877
|
+
}
|
|
18731
18878
|
function resolveUnmatched(normalizedValues, matchedLabels, originalValues) {
|
|
18732
18879
|
return [...normalizedValues.keys()].filter((k) => !matchedLabels.has(k)).map((k) => {
|
|
18733
18880
|
for (const orig of Object.keys(originalValues)) {
|
|
@@ -18997,7 +19144,7 @@ function fillFormFields(blocks, values) {
|
|
|
18997
19144
|
cell.text = result.text;
|
|
18998
19145
|
patternFilledCells.add(cell);
|
|
18999
19146
|
for (const m of result.matches) {
|
|
19000
|
-
filled.push({ label: m.label, value: m.value, row: r, col: c });
|
|
19147
|
+
filled.push({ label: m.label, value: m.value, row: r, col: c, key: m.key });
|
|
19001
19148
|
}
|
|
19002
19149
|
}
|
|
19003
19150
|
}
|
|
@@ -19077,7 +19224,8 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19077
19224
|
label: labelCell.text.trim().replace(/[::]\s*$/, ""),
|
|
19078
19225
|
value: newValue,
|
|
19079
19226
|
row: r,
|
|
19080
|
-
col: c
|
|
19227
|
+
col: c,
|
|
19228
|
+
key: matchKey
|
|
19081
19229
|
});
|
|
19082
19230
|
}
|
|
19083
19231
|
}
|
|
@@ -19106,7 +19254,8 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19106
19254
|
label: headerCell.text.trim(),
|
|
19107
19255
|
value: newValue,
|
|
19108
19256
|
row: r,
|
|
19109
|
-
col: c
|
|
19257
|
+
col: c,
|
|
19258
|
+
key: matchKey
|
|
19110
19259
|
});
|
|
19111
19260
|
}
|
|
19112
19261
|
}
|
|
@@ -19123,7 +19272,7 @@ function fillInlineFields(text, values, filled, matchedLabels) {
|
|
|
19123
19272
|
const newValue = values.consume(matchKey);
|
|
19124
19273
|
if (newValue === void 0) continue;
|
|
19125
19274
|
matchedLabels.add(matchKey);
|
|
19126
|
-
filled.push({ label: seg.label.trim(), value: newValue, row: -1, col: -1 });
|
|
19275
|
+
filled.push({ label: seg.label.trim(), value: newValue, row: -1, col: -1, key: matchKey });
|
|
19127
19276
|
out += text.slice(pos, seg.valueStart);
|
|
19128
19277
|
out += seg.valueStart === seg.valueEnd ? padInsertion(text, seg.valueStart, newValue) : newValue;
|
|
19129
19278
|
pos = seg.valueEnd;
|
|
@@ -19960,7 +20109,8 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
19960
20109
|
label: cellLabelText(headerCells[colIdx]).trim(),
|
|
19961
20110
|
value: newValue,
|
|
19962
20111
|
row: rowIdx,
|
|
19963
|
-
col: colIdx
|
|
20112
|
+
col: colIdx,
|
|
20113
|
+
key: matchKey
|
|
19964
20114
|
});
|
|
19965
20115
|
}
|
|
19966
20116
|
}
|
|
@@ -21471,6 +21621,9 @@ function readCommand(input, idx, depth) {
|
|
|
21471
21621
|
const body = readGroupOrToken(input, name.next, depth);
|
|
21472
21622
|
return { value: `${ACCENT_COMMANDS[command]}{${body.value}}`, next: body.next };
|
|
21473
21623
|
}
|
|
21624
|
+
if (command === ",") return { value: "`", next: name.next };
|
|
21625
|
+
if (command === ";" || command === ":") return { value: "~", next: name.next };
|
|
21626
|
+
if (command === "!") return { value: "", next: name.next };
|
|
21474
21627
|
if (command === "mathrm" || command === "text") {
|
|
21475
21628
|
const start = skipSpaces(input, name.next);
|
|
21476
21629
|
if (input[start] === "{") {
|
|
@@ -23473,10 +23626,11 @@ function handleModified(orig, edited, ctx) {
|
|
|
23473
23626
|
function patchParagraph(block, orig, edited, ctx, skip) {
|
|
23474
23627
|
const mapping = ctx.paraMap.get(orig.blockIdx);
|
|
23475
23628
|
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)");
|
|
23476
|
-
|
|
23477
|
-
|
|
23629
|
+
const restoreBr = (s) => s.replace(/\s*<br\s*\/?\s*>\s*/gi, "\n");
|
|
23630
|
+
let newPlain = restoreBr(textUnitToPlain(edited.raw, block));
|
|
23631
|
+
if (block.text && block.text.includes("\n") && !newPlain.includes("\n")) {
|
|
23632
|
+
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)");
|
|
23478
23633
|
}
|
|
23479
|
-
let newPlain = textUnitToPlain(edited.raw, block);
|
|
23480
23634
|
if (block.footnoteText) {
|
|
23481
23635
|
const noteMatch = newPlain.match(/\s*\(주: ([\s\S]*)\)$/);
|
|
23482
23636
|
if (noteMatch) {
|
|
@@ -23498,7 +23652,7 @@ function patchParagraph(block, orig, edited, ctx, skip) {
|
|
|
23498
23652
|
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) });
|
|
23499
23653
|
}
|
|
23500
23654
|
}
|
|
23501
|
-
const origPlain = textUnitToPlain(orig.raw, block);
|
|
23655
|
+
const origPlain = restoreBr(textUnitToPlain(orig.raw, block));
|
|
23502
23656
|
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");
|
|
23503
23657
|
if (sanitizeText(newPlain) !== newPlain) {
|
|
23504
23658
|
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");
|
|
@@ -23526,6 +23680,28 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23526
23680
|
}
|
|
23527
23681
|
const beforeParts = origRows[r][c].split(/<br\s*\/?>/i);
|
|
23528
23682
|
const afterParts = editedRows[r][c].split(/<br\s*\/?>/i);
|
|
23683
|
+
if (cell.paras.length === 1) {
|
|
23684
|
+
const beforeEach = beforeParts.map(gfmCellToPlain);
|
|
23685
|
+
const afterEach = afterParts.map(gfmCellToPlain);
|
|
23686
|
+
if (beforeEach.some((p) => p === null) || afterEach.some((p) => p === null)) {
|
|
23687
|
+
cellSkip("\uC11C\uC2DD/\uB9C1\uD06C/\uC774\uBBF8\uC9C0 \uD3EC\uD568 \uC140 \uC218\uC815\uC740 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
23688
|
+
continue;
|
|
23689
|
+
}
|
|
23690
|
+
const before = beforeEach.join("\n");
|
|
23691
|
+
const after = afterEach.join("\n");
|
|
23692
|
+
if (before === after) continue;
|
|
23693
|
+
const para = cell.paras[0];
|
|
23694
|
+
if (normForMatch(para.rawText) !== normForMatch(before)) {
|
|
23695
|
+
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
23696
|
+
continue;
|
|
23697
|
+
}
|
|
23698
|
+
if (afterEach.some((l) => sanitizeText(l) !== l)) {
|
|
23699
|
+
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23700
|
+
continue;
|
|
23701
|
+
}
|
|
23702
|
+
applied += stageParaPatch(ctx.scans[para.sectionIndex], para, after, cellSkip);
|
|
23703
|
+
continue;
|
|
23704
|
+
}
|
|
23529
23705
|
if (beforeParts.length !== cell.paras.length || afterParts.length !== cell.paras.length) {
|
|
23530
23706
|
cellSkip("\uC140 \uBB38\uB2E8 \uC218 \uBCC0\uACBD \u2014 \uBBF8\uC9C0\uC6D0 (\uBB38\uB2E8 \uCD94\uAC00/\uC0AD\uC81C)");
|
|
23531
23707
|
continue;
|
|
@@ -23670,13 +23846,13 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
|
|
|
23670
23846
|
const assigned = [];
|
|
23671
23847
|
for (let i = 0; i < targets.length; i++) {
|
|
23672
23848
|
if (i < newLines.length) {
|
|
23673
|
-
assigned.push(i === targets.length - 1 && newLines.length > targets.length ? newLines.slice(i).join("
|
|
23849
|
+
assigned.push(i === targets.length - 1 && newLines.length > targets.length ? newLines.slice(i).join("\n") : newLines[i]);
|
|
23674
23850
|
} else {
|
|
23675
23851
|
assigned.push("");
|
|
23676
23852
|
}
|
|
23677
23853
|
}
|
|
23678
23854
|
if (newLines.length > targets.length) {
|
|
23679
|
-
ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \
|
|
23855
|
+
ctx.skipped.push({ reason: "\uC140 \uB0B4 \uCD94\uAC00 \uC904\uC744 \uB9C8\uC9C0\uB9C9 \uBB38\uB2E8\uC5D0 \uAC15\uC81C \uC904\uBC14\uAFC8\uC73C\uB85C \uBCD1\uD569(\uBB38\uB2E8 \uC0DD\uC131 \uB300\uC2E0)", after: summarize(after), partial: true });
|
|
23680
23856
|
} else if (newLines.length < nonEmpty.length && nonEmpty.length > 1) {
|
|
23681
23857
|
ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uC0AD\uC81C\uB294 \uBB38\uB2E8 \uC81C\uAC70 \uBBF8\uC9C0\uC6D0 \u2014 \uBE48 \uBB38\uB2E8 \uC794\uC874(\uBDF0\uC5B4\uC5D0 \uBE48 \uC904 \uD45C\uC2DC \uAC00\uB2A5)", before: summarize(before), after: summarize(after), partial: true });
|
|
23682
23858
|
}
|
|
@@ -23734,8 +23910,7 @@ function splitParaText(data) {
|
|
|
23734
23910
|
i += 16;
|
|
23735
23911
|
toks.push({ start, end: i, units: 1, plain: false, visible: false });
|
|
23736
23912
|
} else {
|
|
23737
|
-
|
|
23738
|
-
toks.push({ start, end: i, units: 1, plain: false, visible: true });
|
|
23913
|
+
toks.push({ start, end: i, units: 1, plain: true, visible: true });
|
|
23739
23914
|
}
|
|
23740
23915
|
break;
|
|
23741
23916
|
default: {
|
|
@@ -23798,13 +23973,31 @@ function rebuildCharShape(csData, coreStartUnit) {
|
|
|
23798
23973
|
});
|
|
23799
23974
|
return { buf, count: kept.length };
|
|
23800
23975
|
}
|
|
23976
|
+
function synthesizeLineSegs(lineSegData, newRaw, startUnits) {
|
|
23977
|
+
if (lineSegData.length < 36) return null;
|
|
23978
|
+
const seg0 = lineSegData.subarray(0, 36);
|
|
23979
|
+
const vPos0 = seg0.readInt32LE(4);
|
|
23980
|
+
const pitch = seg0.readInt32LE(8) + seg0.readInt32LE(20);
|
|
23981
|
+
if (pitch <= 0) return null;
|
|
23982
|
+
const lines = newRaw.split("\n");
|
|
23983
|
+
const segs = [];
|
|
23984
|
+
let pos = startUnits;
|
|
23985
|
+
for (let k = 0; k < lines.length; k++) {
|
|
23986
|
+
const s = Buffer.from(seg0);
|
|
23987
|
+
s.writeUInt32LE((k === 0 ? 0 : pos) >>> 0, 0);
|
|
23988
|
+
s.writeInt32LE(vPos0 + k * pitch, 4);
|
|
23989
|
+
segs.push(s);
|
|
23990
|
+
pos += lines[k].length + 1;
|
|
23991
|
+
}
|
|
23992
|
+
return { buf: Buffer.concat(segs), count: lines.length };
|
|
23993
|
+
}
|
|
23801
23994
|
function stageParaPatch(scan, para, newPlain, skip) {
|
|
23802
23995
|
if (!scan.safe) return skip("\uC139\uC158 \uB808\uCF54\uB4DC \uC7AC\uC9C1\uB82C\uD654 \uBD88\uC77C\uCE58 \u2014 \uC548\uC804\uC744 \uC704\uD574 \uC774 \uC139\uC158\uC740 \uBBF8\uC9C0\uC6D0");
|
|
23803
23996
|
if (para.textIdx === -2) return skip("\uBCF5\uC218 PARA_TEXT \uB808\uCF54\uB4DC \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
23804
23997
|
if (para.rangeTagCount > 0) return skip("\uBC94\uC704 \uD0DC\uADF8(\uD615\uAD11\uD39C/\uAD50\uC815\uBD80\uD638) \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
23805
23998
|
if (para.charShapeIdx < 0 || para.lineSegIdx < 0) return skip("\uBB38\uB2E8 \uB808\uCF54\uB4DC \uAD6C\uC131 \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23806
23999
|
if (scan.repl.has(para.headerIdx)) return skip("\uB3D9\uC77C \uBB38\uB2E8 \uC911\uBCF5 \uC218\uC815 \u2014 \uCCAB \uC218\uC815\uB9CC \uC801\uC6A9");
|
|
23807
|
-
if (/[\u0000-\u001f]/.test(newPlain)) return skip("\uC0C8 \uD14D\uC2A4\uD2B8\uC5D0 \uC81C\uC5B4\uBB38\uC790 \uD3EC\uD568 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
24000
|
+
if (/[\u0000-\u0009\u000b-\u001f]/.test(newPlain)) return skip("\uC0C8 \uD14D\uC2A4\uD2B8\uC5D0 \uC81C\uC5B4\uBB38\uC790 \uD3EC\uD568 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23808
24001
|
const records = scan.records;
|
|
23809
24002
|
const headerRec = records[para.headerIdx];
|
|
23810
24003
|
const charShapeRec = records[para.charShapeIdx];
|
|
@@ -23824,6 +24017,13 @@ function stageParaPatch(scan, para, newPlain, skip) {
|
|
|
23824
24017
|
const cs2 = rebuildCharShape(charShapeRec.data, 0);
|
|
23825
24018
|
scan.repl.set(para.charShapeIdx, cs2.buf);
|
|
23826
24019
|
newHeader2.writeUInt16LE(cs2.count, 12);
|
|
24020
|
+
if (newPlain.includes("\n")) {
|
|
24021
|
+
const synth = synthesizeLineSegs(records[para.lineSegIdx].data, newPlain, 0);
|
|
24022
|
+
if (synth) {
|
|
24023
|
+
scan.repl.set(para.lineSegIdx, synth.buf);
|
|
24024
|
+
newHeader2.writeUInt16LE(synth.count, 16);
|
|
24025
|
+
}
|
|
24026
|
+
}
|
|
23827
24027
|
scan.repl.set(para.headerIdx, newHeader2);
|
|
23828
24028
|
return 1;
|
|
23829
24029
|
}
|
|
@@ -23844,15 +24044,108 @@ function stageParaPatch(scan, para, newPlain, skip) {
|
|
|
23844
24044
|
const cs = rebuildCharShape(charShapeRec.data, seg.prefixUnits);
|
|
23845
24045
|
scan.repl.set(para.charShapeIdx, cs.buf);
|
|
23846
24046
|
newHeader.writeUInt16LE(cs.count, 12);
|
|
24047
|
+
if (newRaw.includes("\n")) {
|
|
24048
|
+
const synth = synthesizeLineSegs(records[para.lineSegIdx].data, newRaw, seg.prefixUnits);
|
|
24049
|
+
if (synth) {
|
|
24050
|
+
scan.repl.set(para.lineSegIdx, synth.buf);
|
|
24051
|
+
newHeader.writeUInt16LE(synth.count, 16);
|
|
24052
|
+
}
|
|
24053
|
+
}
|
|
23847
24054
|
scan.repl.set(para.headerIdx, newHeader);
|
|
23848
24055
|
return 1;
|
|
23849
24056
|
}
|
|
23850
24057
|
|
|
23851
|
-
// src/
|
|
24058
|
+
// src/validate.ts
|
|
23852
24059
|
import JSZip8 from "jszip";
|
|
24060
|
+
import { DOMParser as DOMParser4 } from "@xmldom/xmldom";
|
|
24061
|
+
var REQUIRED_FILES = [
|
|
24062
|
+
"mimetype",
|
|
24063
|
+
"META-INF/container.xml",
|
|
24064
|
+
"Contents/content.hpf",
|
|
24065
|
+
"Contents/header.xml",
|
|
24066
|
+
"Contents/section0.xml"
|
|
24067
|
+
];
|
|
24068
|
+
var EXPECTED_MIMETYPE = "application/hwp+zip";
|
|
24069
|
+
var XML_SUFFIXES = [".xml", ".hpf", ".rdf"];
|
|
24070
|
+
var SECTION_FILE_RE = /^Contents\/section\d+\.xml$/;
|
|
24071
|
+
var SECCNT_RE = /<(?:\w+:)?head\b[^>]*?\bsecCnt="(\d+)"/;
|
|
24072
|
+
var OPF_HREF_RE = /<opf:item\b[^>]*?\bhref="([^"]*)"/g;
|
|
24073
|
+
async function validateHwpx(buffer) {
|
|
24074
|
+
const issues = [];
|
|
24075
|
+
let zip;
|
|
24076
|
+
try {
|
|
24077
|
+
zip = await JSZip8.loadAsync(buffer);
|
|
24078
|
+
} catch (err) {
|
|
24079
|
+
return {
|
|
24080
|
+
ok: false,
|
|
24081
|
+
issues: [{ message: `\uC720\uD6A8\uD55C ZIP\uC774 \uC544\uB2D8: ${err instanceof Error ? err.message : String(err)}` }],
|
|
24082
|
+
entryCount: 0
|
|
24083
|
+
};
|
|
24084
|
+
}
|
|
24085
|
+
const rawNames = Object.keys(zip.files);
|
|
24086
|
+
const names = rawNames.filter((n) => !zip.files[n].dir);
|
|
24087
|
+
if (names.length === 0) return { ok: false, issues: [{ message: "\uBE48 ZIP" }], entryCount: 0 };
|
|
24088
|
+
if (rawNames[0] !== "mimetype") {
|
|
24089
|
+
issues.push({ message: `\uCCAB zip \uC5D4\uD2B8\uB9AC\uAC00 '${rawNames[0]}' \u2014 'mimetype'\uC774\uC5B4\uC57C \uD568` });
|
|
24090
|
+
}
|
|
24091
|
+
const nameset = new Set(names);
|
|
24092
|
+
if (nameset.has("mimetype")) {
|
|
24093
|
+
const mt = (await zip.files["mimetype"].async("string")).trim();
|
|
24094
|
+
if (mt !== EXPECTED_MIMETYPE) {
|
|
24095
|
+
issues.push({ path: "mimetype", message: `\uB0B4\uC6A9\uC774 '${mt}' \u2014 '${EXPECTED_MIMETYPE}'\uC774\uC5B4\uC57C \uD568` });
|
|
24096
|
+
}
|
|
24097
|
+
}
|
|
24098
|
+
for (const req of REQUIRED_FILES) {
|
|
24099
|
+
if (!nameset.has(req)) issues.push({ message: `\uD544\uC218 \uD30C\uC77C \uB204\uB77D: ${req}` });
|
|
24100
|
+
}
|
|
24101
|
+
for (const name of names) {
|
|
24102
|
+
if (!XML_SUFFIXES.some((s) => name.endsWith(s))) continue;
|
|
24103
|
+
const text = await zip.files[name].async("string");
|
|
24104
|
+
let firstError = null;
|
|
24105
|
+
try {
|
|
24106
|
+
new DOMParser4({
|
|
24107
|
+
onError(level, msg2) {
|
|
24108
|
+
if (level !== "warning" && firstError === null) firstError = String(msg2);
|
|
24109
|
+
}
|
|
24110
|
+
}).parseFromString(text, "text/xml");
|
|
24111
|
+
} catch (err) {
|
|
24112
|
+
firstError ??= err instanceof Error ? err.message : String(err);
|
|
24113
|
+
}
|
|
24114
|
+
if (firstError !== null) {
|
|
24115
|
+
issues.push({ path: name, message: `XML \uC6F0\uD3FC\uB4DC \uC704\uBC18: ${firstError.split("\n")[0]}` });
|
|
24116
|
+
}
|
|
24117
|
+
}
|
|
24118
|
+
if (nameset.has("Contents/header.xml")) {
|
|
24119
|
+
const header = await zip.files["Contents/header.xml"].async("string");
|
|
24120
|
+
const m = SECCNT_RE.exec(header);
|
|
24121
|
+
if (m) {
|
|
24122
|
+
const declared = Number(m[1]);
|
|
24123
|
+
const actual = names.filter((n) => SECTION_FILE_RE.test(n)).length;
|
|
24124
|
+
if (declared !== actual) {
|
|
24125
|
+
issues.push({
|
|
24126
|
+
path: "Contents/header.xml",
|
|
24127
|
+
message: `secCnt=${declared}\uC778\uB370 \uC2E4\uC81C sectionN.xml\uC740 ${actual}\uAC1C \u2014 \uD55C\uCEF4\uB3C5\uC2A4\uAC00 \uC5F4\uAE30\uB97C \uAC70\uBD80\uD568`
|
|
24128
|
+
});
|
|
24129
|
+
}
|
|
24130
|
+
}
|
|
24131
|
+
}
|
|
24132
|
+
if (nameset.has("Contents/content.hpf")) {
|
|
24133
|
+
const hpf = await zip.files["Contents/content.hpf"].async("string");
|
|
24134
|
+
for (const m of hpf.matchAll(OPF_HREF_RE)) {
|
|
24135
|
+
const href = m[1];
|
|
24136
|
+
if (!nameset.has(href) && !nameset.has(`Contents/${href}`)) {
|
|
24137
|
+
issues.push({ path: "Contents/content.hpf", message: `manifest\uAC00 \uC5C6\uB294 \uD30C\uC77C\uC744 \uCC38\uC870: ${href}` });
|
|
24138
|
+
}
|
|
24139
|
+
}
|
|
24140
|
+
}
|
|
24141
|
+
return { ok: issues.length === 0, issues, entryCount: names.length };
|
|
24142
|
+
}
|
|
24143
|
+
|
|
24144
|
+
// src/roundtrip/session.ts
|
|
24145
|
+
import JSZip9 from "jszip";
|
|
23853
24146
|
async function buildState(bytes) {
|
|
23854
24147
|
const parsed = await parseHwpxDocument(u8ToArrayBuffer2(bytes));
|
|
23855
|
-
const zip = await
|
|
24148
|
+
const zip = await JSZip9.loadAsync(bytes);
|
|
23856
24149
|
const sectionPaths = await resolveSectionEntryNames(zip);
|
|
23857
24150
|
if (sectionPaths.length === 0) {
|
|
23858
24151
|
throw new Error("HWPX \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
@@ -24433,7 +24726,7 @@ async function parseHwp(buffer, options) {
|
|
|
24433
24726
|
async function parsePdf(buffer, options) {
|
|
24434
24727
|
let parsePdfDocument;
|
|
24435
24728
|
try {
|
|
24436
|
-
const mod = await import("./parser-
|
|
24729
|
+
const mod = await import("./parser-76JSTEP3.js");
|
|
24437
24730
|
parsePdfDocument = mod.parsePdfDocument;
|
|
24438
24731
|
} catch {
|
|
24439
24732
|
return {
|
|
@@ -24526,7 +24819,9 @@ async function fillForm(input, values, outputFormat = "markdown") {
|
|
|
24526
24819
|
export {
|
|
24527
24820
|
extractHwpxMetadataOnly,
|
|
24528
24821
|
extractHwp5MetadataOnly,
|
|
24822
|
+
formatFillValue,
|
|
24529
24823
|
ValueCursor,
|
|
24824
|
+
fillWithUniqueGuard,
|
|
24530
24825
|
isLabelCell,
|
|
24531
24826
|
extractFormFields,
|
|
24532
24827
|
inferFieldType,
|
|
@@ -24544,6 +24839,7 @@ export {
|
|
|
24544
24839
|
diffBlocks,
|
|
24545
24840
|
patchHwpx,
|
|
24546
24841
|
patchHwp,
|
|
24842
|
+
validateHwpx,
|
|
24547
24843
|
HwpxSession,
|
|
24548
24844
|
openHwpxDocument,
|
|
24549
24845
|
patchHwpxBlocks,
|
|
@@ -24561,4 +24857,4 @@ export {
|
|
|
24561
24857
|
parseHwpml,
|
|
24562
24858
|
fillForm
|
|
24563
24859
|
};
|
|
24564
|
-
//# sourceMappingURL=chunk-
|
|
24860
|
+
//# sourceMappingURL=chunk-Q3IHI3E6.js.map
|