kordoc 3.13.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 +14 -1
- package/dist/{-MRPDPE2X.js → -EYPKRLMN.js} +13 -7
- package/dist/{chunk-33CIKNL4.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-MEXUFQVC.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-TWACKS3K.js → chunk-Q3IHI3E6.js} +309 -29
- package/dist/chunk-Q3IHI3E6.js.map +1 -0
- package/dist/{chunk-YXOT7P5B.js → chunk-Q5ZPWQID.js} +5 -5
- package/dist/{chunk-YXOT7P5B.js.map → chunk-Q5ZPWQID.js.map} +1 -1
- package/dist/{chunk-Q6UXVJXI.js → chunk-SCFFABCT.js} +2 -2
- package/dist/{chunk-O4WFPOFN.js → chunk-ZRNYYEE6.js} +5 -5
- package/dist/{chunk-O4WFPOFN.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 +1002 -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 +881 -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-XUNGOH76.js → parser-76JSTEP3.js} +55 -7
- package/dist/parser-76JSTEP3.js.map +1 -0
- package/dist/{parser-DZBI3EA2.cjs → parser-O2SD4DFR.cjs} +66 -18
- package/dist/parser-O2SD4DFR.cjs.map +1 -0
- package/dist/{parser-Z3IL2ESY.js → parser-SNBQZO5E.js} +54 -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-G5NFIT5L.js → watch-LEK5U5P6.js} +5 -5
- package/package.json +4 -3
- package/dist/chunk-33CIKNL4.js.map +0 -1
- package/dist/chunk-MEXUFQVC.cjs.map +0 -1
- package/dist/chunk-TWACKS3K.js.map +0 -1
- package/dist/parser-DZBI3EA2.cjs.map +0 -1
- package/dist/parser-XUNGOH76.js.map +0 -1
- package/dist/parser-Z3IL2ESY.js.map +0 -1
- package/dist/render-VZ4OGHZU.js +0 -9
- /package/dist/{-MRPDPE2X.js.map → -EYPKRLMN.js.map} +0 -0
- /package/dist/{chunk-Q6UXVJXI.js.map → chunk-SCFFABCT.js.map} +0 -0
- /package/dist/{render-VZ4OGHZU.js.map → render-LDI3LO2P.js.map} +0 -0
- /package/dist/{watch-G5NFIT5L.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;
|
|
@@ -18588,6 +18623,81 @@ function countSections(body) {
|
|
|
18588
18623
|
}
|
|
18589
18624
|
|
|
18590
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
|
+
}
|
|
18591
18701
|
var ValueCursor = class {
|
|
18592
18702
|
constructor(values) {
|
|
18593
18703
|
this.values = values;
|
|
@@ -18739,11 +18849,32 @@ function padInsertion(text, pos, value) {
|
|
|
18739
18849
|
}
|
|
18740
18850
|
function normalizeValues(values) {
|
|
18741
18851
|
const map = /* @__PURE__ */ new Map();
|
|
18742
|
-
for (const [label,
|
|
18743
|
-
|
|
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));
|
|
18744
18855
|
}
|
|
18745
18856
|
return map;
|
|
18746
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
|
+
}
|
|
18747
18878
|
function resolveUnmatched(normalizedValues, matchedLabels, originalValues) {
|
|
18748
18879
|
return [...normalizedValues.keys()].filter((k) => !matchedLabels.has(k)).map((k) => {
|
|
18749
18880
|
for (const orig of Object.keys(originalValues)) {
|
|
@@ -19013,7 +19144,7 @@ function fillFormFields(blocks, values) {
|
|
|
19013
19144
|
cell.text = result.text;
|
|
19014
19145
|
patternFilledCells.add(cell);
|
|
19015
19146
|
for (const m of result.matches) {
|
|
19016
|
-
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 });
|
|
19017
19148
|
}
|
|
19018
19149
|
}
|
|
19019
19150
|
}
|
|
@@ -19093,7 +19224,8 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19093
19224
|
label: labelCell.text.trim().replace(/[::]\s*$/, ""),
|
|
19094
19225
|
value: newValue,
|
|
19095
19226
|
row: r,
|
|
19096
|
-
col: c
|
|
19227
|
+
col: c,
|
|
19228
|
+
key: matchKey
|
|
19097
19229
|
});
|
|
19098
19230
|
}
|
|
19099
19231
|
}
|
|
@@ -19122,7 +19254,8 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
|
|
|
19122
19254
|
label: headerCell.text.trim(),
|
|
19123
19255
|
value: newValue,
|
|
19124
19256
|
row: r,
|
|
19125
|
-
col: c
|
|
19257
|
+
col: c,
|
|
19258
|
+
key: matchKey
|
|
19126
19259
|
});
|
|
19127
19260
|
}
|
|
19128
19261
|
}
|
|
@@ -19139,7 +19272,7 @@ function fillInlineFields(text, values, filled, matchedLabels) {
|
|
|
19139
19272
|
const newValue = values.consume(matchKey);
|
|
19140
19273
|
if (newValue === void 0) continue;
|
|
19141
19274
|
matchedLabels.add(matchKey);
|
|
19142
|
-
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 });
|
|
19143
19276
|
out += text.slice(pos, seg.valueStart);
|
|
19144
19277
|
out += seg.valueStart === seg.valueEnd ? padInsertion(text, seg.valueStart, newValue) : newValue;
|
|
19145
19278
|
pos = seg.valueEnd;
|
|
@@ -19976,7 +20109,8 @@ async function fillHwpx(hwpxBuffer, values) {
|
|
|
19976
20109
|
label: cellLabelText(headerCells[colIdx]).trim(),
|
|
19977
20110
|
value: newValue,
|
|
19978
20111
|
row: rowIdx,
|
|
19979
|
-
col: colIdx
|
|
20112
|
+
col: colIdx,
|
|
20113
|
+
key: matchKey
|
|
19980
20114
|
});
|
|
19981
20115
|
}
|
|
19982
20116
|
}
|
|
@@ -21487,6 +21621,9 @@ function readCommand(input, idx, depth) {
|
|
|
21487
21621
|
const body = readGroupOrToken(input, name.next, depth);
|
|
21488
21622
|
return { value: `${ACCENT_COMMANDS[command]}{${body.value}}`, next: body.next };
|
|
21489
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 };
|
|
21490
21627
|
if (command === "mathrm" || command === "text") {
|
|
21491
21628
|
const start = skipSpaces(input, name.next);
|
|
21492
21629
|
if (input[start] === "{") {
|
|
@@ -23489,10 +23626,11 @@ function handleModified(orig, edited, ctx) {
|
|
|
23489
23626
|
function patchParagraph(block, orig, edited, ctx, skip) {
|
|
23490
23627
|
const mapping = ctx.paraMap.get(orig.blockIdx);
|
|
23491
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)");
|
|
23492
|
-
|
|
23493
|
-
|
|
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)");
|
|
23494
23633
|
}
|
|
23495
|
-
let newPlain = textUnitToPlain(edited.raw, block);
|
|
23496
23634
|
if (block.footnoteText) {
|
|
23497
23635
|
const noteMatch = newPlain.match(/\s*\(주: ([\s\S]*)\)$/);
|
|
23498
23636
|
if (noteMatch) {
|
|
@@ -23514,7 +23652,7 @@ function patchParagraph(block, orig, edited, ctx, skip) {
|
|
|
23514
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) });
|
|
23515
23653
|
}
|
|
23516
23654
|
}
|
|
23517
|
-
const origPlain = textUnitToPlain(orig.raw, block);
|
|
23655
|
+
const origPlain = restoreBr(textUnitToPlain(orig.raw, block));
|
|
23518
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");
|
|
23519
23657
|
if (sanitizeText(newPlain) !== newPlain) {
|
|
23520
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");
|
|
@@ -23542,6 +23680,28 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23542
23680
|
}
|
|
23543
23681
|
const beforeParts = origRows[r][c].split(/<br\s*\/?>/i);
|
|
23544
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
|
+
}
|
|
23545
23705
|
if (beforeParts.length !== cell.paras.length || afterParts.length !== cell.paras.length) {
|
|
23546
23706
|
cellSkip("\uC140 \uBB38\uB2E8 \uC218 \uBCC0\uACBD \u2014 \uBBF8\uC9C0\uC6D0 (\uBB38\uB2E8 \uCD94\uAC00/\uC0AD\uC81C)");
|
|
23547
23707
|
continue;
|
|
@@ -23686,13 +23846,13 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
|
|
|
23686
23846
|
const assigned = [];
|
|
23687
23847
|
for (let i = 0; i < targets.length; i++) {
|
|
23688
23848
|
if (i < newLines.length) {
|
|
23689
|
-
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]);
|
|
23690
23850
|
} else {
|
|
23691
23851
|
assigned.push("");
|
|
23692
23852
|
}
|
|
23693
23853
|
}
|
|
23694
23854
|
if (newLines.length > targets.length) {
|
|
23695
|
-
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 });
|
|
23696
23856
|
} else if (newLines.length < nonEmpty.length && nonEmpty.length > 1) {
|
|
23697
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 });
|
|
23698
23858
|
}
|
|
@@ -23750,8 +23910,7 @@ function splitParaText(data) {
|
|
|
23750
23910
|
i += 16;
|
|
23751
23911
|
toks.push({ start, end: i, units: 1, plain: false, visible: false });
|
|
23752
23912
|
} else {
|
|
23753
|
-
|
|
23754
|
-
toks.push({ start, end: i, units: 1, plain: false, visible: true });
|
|
23913
|
+
toks.push({ start, end: i, units: 1, plain: true, visible: true });
|
|
23755
23914
|
}
|
|
23756
23915
|
break;
|
|
23757
23916
|
default: {
|
|
@@ -23814,13 +23973,31 @@ function rebuildCharShape(csData, coreStartUnit) {
|
|
|
23814
23973
|
});
|
|
23815
23974
|
return { buf, count: kept.length };
|
|
23816
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
|
+
}
|
|
23817
23994
|
function stageParaPatch(scan, para, newPlain, skip) {
|
|
23818
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");
|
|
23819
23996
|
if (para.textIdx === -2) return skip("\uBCF5\uC218 PARA_TEXT \uB808\uCF54\uB4DC \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
23820
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)");
|
|
23821
23998
|
if (para.charShapeIdx < 0 || para.lineSegIdx < 0) return skip("\uBB38\uB2E8 \uB808\uCF54\uB4DC \uAD6C\uC131 \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23822
23999
|
if (scan.repl.has(para.headerIdx)) return skip("\uB3D9\uC77C \uBB38\uB2E8 \uC911\uBCF5 \uC218\uC815 \u2014 \uCCAB \uC218\uC815\uB9CC \uC801\uC6A9");
|
|
23823
|
-
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");
|
|
23824
24001
|
const records = scan.records;
|
|
23825
24002
|
const headerRec = records[para.headerIdx];
|
|
23826
24003
|
const charShapeRec = records[para.charShapeIdx];
|
|
@@ -23840,6 +24017,13 @@ function stageParaPatch(scan, para, newPlain, skip) {
|
|
|
23840
24017
|
const cs2 = rebuildCharShape(charShapeRec.data, 0);
|
|
23841
24018
|
scan.repl.set(para.charShapeIdx, cs2.buf);
|
|
23842
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
|
+
}
|
|
23843
24027
|
scan.repl.set(para.headerIdx, newHeader2);
|
|
23844
24028
|
return 1;
|
|
23845
24029
|
}
|
|
@@ -23860,15 +24044,108 @@ function stageParaPatch(scan, para, newPlain, skip) {
|
|
|
23860
24044
|
const cs = rebuildCharShape(charShapeRec.data, seg.prefixUnits);
|
|
23861
24045
|
scan.repl.set(para.charShapeIdx, cs.buf);
|
|
23862
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
|
+
}
|
|
23863
24054
|
scan.repl.set(para.headerIdx, newHeader);
|
|
23864
24055
|
return 1;
|
|
23865
24056
|
}
|
|
23866
24057
|
|
|
23867
|
-
// src/
|
|
24058
|
+
// src/validate.ts
|
|
23868
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";
|
|
23869
24146
|
async function buildState(bytes) {
|
|
23870
24147
|
const parsed = await parseHwpxDocument(u8ToArrayBuffer2(bytes));
|
|
23871
|
-
const zip = await
|
|
24148
|
+
const zip = await JSZip9.loadAsync(bytes);
|
|
23872
24149
|
const sectionPaths = await resolveSectionEntryNames(zip);
|
|
23873
24150
|
if (sectionPaths.length === 0) {
|
|
23874
24151
|
throw new Error("HWPX \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
@@ -24449,7 +24726,7 @@ async function parseHwp(buffer, options) {
|
|
|
24449
24726
|
async function parsePdf(buffer, options) {
|
|
24450
24727
|
let parsePdfDocument;
|
|
24451
24728
|
try {
|
|
24452
|
-
const mod = await import("./parser-
|
|
24729
|
+
const mod = await import("./parser-76JSTEP3.js");
|
|
24453
24730
|
parsePdfDocument = mod.parsePdfDocument;
|
|
24454
24731
|
} catch {
|
|
24455
24732
|
return {
|
|
@@ -24542,7 +24819,9 @@ async function fillForm(input, values, outputFormat = "markdown") {
|
|
|
24542
24819
|
export {
|
|
24543
24820
|
extractHwpxMetadataOnly,
|
|
24544
24821
|
extractHwp5MetadataOnly,
|
|
24822
|
+
formatFillValue,
|
|
24545
24823
|
ValueCursor,
|
|
24824
|
+
fillWithUniqueGuard,
|
|
24546
24825
|
isLabelCell,
|
|
24547
24826
|
extractFormFields,
|
|
24548
24827
|
inferFieldType,
|
|
@@ -24560,6 +24839,7 @@ export {
|
|
|
24560
24839
|
diffBlocks,
|
|
24561
24840
|
patchHwpx,
|
|
24562
24841
|
patchHwp,
|
|
24842
|
+
validateHwpx,
|
|
24563
24843
|
HwpxSession,
|
|
24564
24844
|
openHwpxDocument,
|
|
24565
24845
|
patchHwpxBlocks,
|
|
@@ -24577,4 +24857,4 @@ export {
|
|
|
24577
24857
|
parseHwpml,
|
|
24578
24858
|
fillForm
|
|
24579
24859
|
};
|
|
24580
|
-
//# sourceMappingURL=chunk-
|
|
24860
|
+
//# sourceMappingURL=chunk-Q3IHI3E6.js.map
|