kordoc 3.18.1 → 4.0.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 +768 -752
- package/dist/{-V66QW3WA.js → -URVKBXYK.js} +12 -8
- package/dist/{chunk-MEPHGCPQ.js → chunk-5CJGKKMZ.js} +1 -1
- package/dist/chunk-5CJGKKMZ.js.map +1 -0
- package/dist/{chunk-2IBFK5ZO.js → chunk-7ETIIYGI.js} +2 -2
- package/dist/chunk-7ETIIYGI.js.map +1 -0
- package/dist/chunk-DCZVOIEO.cjs.map +1 -1
- package/dist/{chunk-4RGDFDQ2.js → chunk-DVUNWK6W.js} +8 -2
- package/dist/chunk-DVUNWK6W.js.map +1 -0
- package/dist/{chunk-R2H34FY5.cjs → chunk-EBSCV3JC.cjs} +2 -2
- package/dist/chunk-EBSCV3JC.cjs.map +1 -0
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-UHYPUIRH.js → chunk-IA5UZZKV.js} +2 -2
- package/dist/chunk-IA5UZZKV.js.map +1 -0
- package/dist/{chunk-QMJJI6TD.js → chunk-JUJEKFUF.js} +6 -4
- package/dist/chunk-JUJEKFUF.js.map +1 -0
- package/dist/chunk-MOL7MDBG.js +0 -0
- package/dist/{chunk-7K5P4RNT.js → chunk-PGWAF755.js} +1489 -585
- package/dist/chunk-PGWAF755.js.map +1 -0
- package/dist/{chunk-NZJAXMN7.js → chunk-THZVBYHE.js} +3 -3
- package/dist/chunk-THZVBYHE.js.map +1 -0
- package/dist/{chunk-UNV7F3FK.js → chunk-ZKG6SBHV.js} +2 -2
- package/dist/chunk-ZKG6SBHV.js.map +1 -0
- package/dist/cli.js +40 -16
- package/dist/cli.js.map +1 -1
- package/dist/{detect-RI2MQ33K.js → detect-PJZMUL2Z.js} +2 -2
- package/dist/formula-5NKVS2LR.cjs.map +1 -1
- package/dist/formula-JCNF43NE.js +0 -0
- package/dist/index.cjs +1876 -966
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -9
- package/dist/index.d.ts +76 -9
- package/dist/index.js +1648 -738
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +55 -16
- package/dist/mcp.js.map +1 -1
- package/dist/page-range-737B4EZW.js +0 -0
- package/dist/page-range-P7SDW6LR.cjs.map +1 -1
- package/dist/{parser-XEY5MRGV.cjs → parser-6TV6JKHF.cjs} +15 -15
- package/dist/parser-6TV6JKHF.cjs.map +1 -0
- package/dist/{parser-DOBK652H.js → parser-LHUO6UUA.js} +4 -4
- package/dist/parser-LHUO6UUA.js.map +1 -0
- package/dist/{parser-JBBA5A5E.js → parser-NXHY37WH.js} +3 -3
- package/dist/parser-NXHY37WH.js.map +1 -0
- package/dist/{provider-G4C2V2PD.cjs → provider-5K7O3Z2O.cjs} +1 -1
- package/dist/provider-5K7O3Z2O.cjs.map +1 -0
- package/dist/{provider-AKROB7WQ.js → provider-7H4CPZYS.js} +1 -1
- package/dist/provider-7H4CPZYS.js.map +1 -0
- package/dist/{provider-4ZJKV3DC.js → provider-H4WWSPOV.js} +1 -1
- package/dist/provider-H4WWSPOV.js.map +1 -0
- package/dist/render-T5O6QHBJ.js +10 -0
- package/dist/seal-7KNR5WFH.js +10 -0
- package/dist/setup-57FB3LSP.js +0 -0
- package/dist/{watch-2MNRQWGV.js → watch-PNXTAWDR.js} +8 -8
- package/dist/watch-PNXTAWDR.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2IBFK5ZO.js.map +0 -1
- package/dist/chunk-4RGDFDQ2.js.map +0 -1
- package/dist/chunk-7K5P4RNT.js.map +0 -1
- package/dist/chunk-MEPHGCPQ.js.map +0 -1
- package/dist/chunk-NZJAXMN7.js.map +0 -1
- package/dist/chunk-QMJJI6TD.js.map +0 -1
- package/dist/chunk-R2H34FY5.cjs.map +0 -1
- package/dist/chunk-UHYPUIRH.js.map +0 -1
- package/dist/chunk-UNV7F3FK.js.map +0 -1
- package/dist/parser-DOBK652H.js.map +0 -1
- package/dist/parser-JBBA5A5E.js.map +0 -1
- package/dist/parser-XEY5MRGV.cjs.map +0 -1
- package/dist/provider-4ZJKV3DC.js.map +0 -1
- package/dist/provider-AKROB7WQ.js.map +0 -1
- package/dist/provider-G4C2V2PD.cjs.map +0 -1
- package/dist/render-VX4H2S4F.js +0 -10
- package/dist/seal-6Z6H4YXN.js +0 -10
- package/dist/watch-2MNRQWGV.js.map +0 -1
- /package/dist/{-V66QW3WA.js.map → -URVKBXYK.js.map} +0 -0
- /package/dist/{detect-RI2MQ33K.js.map → detect-PJZMUL2Z.js.map} +0 -0
- /package/dist/{render-VX4H2S4F.js.map → render-T5O6QHBJ.js.map} +0 -0
- /package/dist/{seal-6Z6H4YXN.js.map → seal-7KNR5WFH.js.map} +0 -0
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
dedupeRunningHeaders,
|
|
12
12
|
flattenLayoutTables,
|
|
13
13
|
mapPuaText
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-7ETIIYGI.js";
|
|
15
15
|
import {
|
|
16
16
|
detectFormat,
|
|
17
17
|
detectOle2Format,
|
|
18
18
|
detectZipFormat,
|
|
19
19
|
parseLenientCfb
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-5CJGKKMZ.js";
|
|
21
21
|
import {
|
|
22
22
|
parsePageRange
|
|
23
23
|
} from "./chunk-MOL7MDBG.js";
|
|
@@ -32,12 +32,14 @@ import {
|
|
|
32
32
|
paraTextPureT,
|
|
33
33
|
patchZipEntries,
|
|
34
34
|
scanSectionXml
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-THZVBYHE.js";
|
|
36
36
|
import {
|
|
37
37
|
SPACE_EM_FIXED,
|
|
38
38
|
charWidthEm1000,
|
|
39
|
-
fitRatioForFewerLines
|
|
40
|
-
|
|
39
|
+
fitRatioForFewerLines,
|
|
40
|
+
measureTextWidth,
|
|
41
|
+
simulateWrap
|
|
42
|
+
} from "./chunk-JUJEKFUF.js";
|
|
41
43
|
import {
|
|
42
44
|
MAX_DECOMPRESS_SIZE,
|
|
43
45
|
MAX_XML_DEPTH,
|
|
@@ -48,7 +50,7 @@ import {
|
|
|
48
50
|
createXmlParser,
|
|
49
51
|
extractTextFromNode,
|
|
50
52
|
findChildByLocalName
|
|
51
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-DVUNWK6W.js";
|
|
52
54
|
import {
|
|
53
55
|
KordocError,
|
|
54
56
|
classifyError,
|
|
@@ -59,7 +61,7 @@ import {
|
|
|
59
61
|
sanitizeHref,
|
|
60
62
|
stripDtd,
|
|
61
63
|
toArrayBuffer
|
|
62
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-ZKG6SBHV.js";
|
|
63
65
|
|
|
64
66
|
// src/index.ts
|
|
65
67
|
import { readFile } from "fs/promises";
|
|
@@ -153,8 +155,8 @@ function comResultToParseResult(pages, pageCount, warnings) {
|
|
|
153
155
|
const text = (pages[i] ?? "").trim();
|
|
154
156
|
if (!text) continue;
|
|
155
157
|
const paragraphs = text.split(/\n/);
|
|
156
|
-
for (const
|
|
157
|
-
const trimmed =
|
|
158
|
+
for (const para2 of paragraphs) {
|
|
159
|
+
const trimmed = para2.trim();
|
|
158
160
|
if (!trimmed) continue;
|
|
159
161
|
blocks.push({ type: "paragraph", text: trimmed, pageNumber: i + 1 });
|
|
160
162
|
lines.push(trimmed);
|
|
@@ -835,7 +837,7 @@ var HANGUL_SYLLABLE_SEQ = "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC\uC544\uC79
|
|
|
835
837
|
var HANGUL_JAMO_SEQ = "\u3131\u3134\u3137\u3139\u3141\u3142\u3145\u3147\u3148\u314A\u314B\u314C\u314D\u314E";
|
|
836
838
|
function toRoman(n) {
|
|
837
839
|
if (n <= 0 || n >= 4e3) return String(n);
|
|
838
|
-
const
|
|
840
|
+
const table2 = [
|
|
839
841
|
[1e3, "M"],
|
|
840
842
|
[900, "CM"],
|
|
841
843
|
[500, "D"],
|
|
@@ -851,7 +853,7 @@ function toRoman(n) {
|
|
|
851
853
|
[1, "I"]
|
|
852
854
|
];
|
|
853
855
|
let out = "";
|
|
854
|
-
for (const [v, s] of
|
|
856
|
+
for (const [v, s] of table2) {
|
|
855
857
|
while (n >= v) {
|
|
856
858
|
out += s;
|
|
857
859
|
n -= v;
|
|
@@ -893,10 +895,17 @@ function formatHeadNumber(n, numFormat) {
|
|
|
893
895
|
function resolveParaHeading(paraEl, ctx) {
|
|
894
896
|
const sm = ctx.styleMap;
|
|
895
897
|
if (!sm) return null;
|
|
898
|
+
const styleId = paraEl.getAttribute("styleIDRef");
|
|
899
|
+
let styleHeading;
|
|
900
|
+
if (styleId && styleId !== "0") {
|
|
901
|
+
const st = sm.styles.get(styleId);
|
|
902
|
+
const m = st && /^개요\s*([1-6])$/.exec(st.name);
|
|
903
|
+
if (m) styleHeading = Math.min(parseInt(m[1], 10), 6);
|
|
904
|
+
}
|
|
896
905
|
const prId = paraEl.getAttribute("paraPrIDRef");
|
|
897
|
-
if (!prId) return null;
|
|
906
|
+
if (!prId) return styleHeading ? { headingLevel: styleHeading } : null;
|
|
898
907
|
const ref = sm.paraHeadings.get(prId);
|
|
899
|
-
if (!ref) return null;
|
|
908
|
+
if (!ref) return styleHeading ? { headingLevel: styleHeading } : null;
|
|
900
909
|
if (ref.type === "BULLET") {
|
|
901
910
|
const char = sm.bullets.get(ref.idRef);
|
|
902
911
|
return char ? { prefix: char } : null;
|
|
@@ -926,24 +935,24 @@ function resolveParaHeading(paraEl, ctx) {
|
|
|
926
935
|
|
|
927
936
|
// src/hwpx/table-build.ts
|
|
928
937
|
function buildTableWithCellMeta(state) {
|
|
929
|
-
const
|
|
930
|
-
if (state.caption)
|
|
938
|
+
const table2 = buildTable(state.rows);
|
|
939
|
+
if (state.caption) table2.caption = state.caption;
|
|
931
940
|
const anchors = [];
|
|
932
941
|
{
|
|
933
942
|
const covered = /* @__PURE__ */ new Set();
|
|
934
|
-
for (let r = 0; r <
|
|
935
|
-
for (let c = 0; c <
|
|
943
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
944
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
936
945
|
if (covered.has(`${r},${c}`)) continue;
|
|
937
|
-
const
|
|
938
|
-
if (!
|
|
939
|
-
for (let dr = 0; dr <
|
|
940
|
-
for (let dc = 0; dc <
|
|
946
|
+
const cell2 = table2.cells[r]?.[c];
|
|
947
|
+
if (!cell2) continue;
|
|
948
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
949
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
941
950
|
if (dr === 0 && dc === 0) continue;
|
|
942
|
-
if (r + dr <
|
|
951
|
+
if (r + dr < table2.rows && c + dc < table2.cols) covered.add(`${r + dr},${c + dc}`);
|
|
943
952
|
}
|
|
944
953
|
}
|
|
945
|
-
anchors.push(
|
|
946
|
-
c +=
|
|
954
|
+
anchors.push(cell2);
|
|
955
|
+
c += cell2.colSpan - 1;
|
|
947
956
|
}
|
|
948
957
|
}
|
|
949
958
|
}
|
|
@@ -959,11 +968,11 @@ function buildTableWithCellMeta(state) {
|
|
|
959
968
|
let target;
|
|
960
969
|
const trimmed = src.text.trim();
|
|
961
970
|
if (src.rowAddr !== void 0 && src.colAddr !== void 0) {
|
|
962
|
-
const cand =
|
|
971
|
+
const cand = table2.cells[src.rowAddr]?.[src.colAddr];
|
|
963
972
|
if (cand && cand.text === trimmed && !claimed.has(cand)) target = cand;
|
|
964
973
|
}
|
|
965
974
|
if (!target) {
|
|
966
|
-
outer: for (const irRow of
|
|
975
|
+
outer: for (const irRow of table2.cells) {
|
|
967
976
|
for (const cand of irRow) {
|
|
968
977
|
if (!claimed.has(cand) && cand.text === trimmed && cand.colSpan === src.colSpan && cand.rowSpan === src.rowSpan) {
|
|
969
978
|
target = cand;
|
|
@@ -982,7 +991,7 @@ function buildTableWithCellMeta(state) {
|
|
|
982
991
|
if (src.isHeader) target.isHeader = true;
|
|
983
992
|
}
|
|
984
993
|
}
|
|
985
|
-
return
|
|
994
|
+
return table2;
|
|
986
995
|
}
|
|
987
996
|
function completeTable(newTable, tableStack, blocks, ctx) {
|
|
988
997
|
const parentTable = tableStack.length > 0 ? tableStack.pop() : null;
|
|
@@ -993,12 +1002,12 @@ function completeTable(newTable, tableStack, blocks, ctx) {
|
|
|
993
1002
|
const ir = buildTableWithCellMeta(newTable);
|
|
994
1003
|
const block = { type: "table", table: ir, pageNumber: ctx.sectionNum };
|
|
995
1004
|
if (parentTable?.cell) {
|
|
996
|
-
const
|
|
997
|
-
(
|
|
998
|
-
|
|
1005
|
+
const cell2 = parentTable.cell;
|
|
1006
|
+
(cell2.blocks ??= []).push(block);
|
|
1007
|
+
cell2.hasStructure = true;
|
|
999
1008
|
let flat = convertTableToText(newTable.rows);
|
|
1000
1009
|
if (newTable.caption) flat = newTable.caption + (flat ? "\n" + flat : "");
|
|
1001
|
-
if (flat)
|
|
1010
|
+
if (flat) cell2.text += (cell2.text ? "\n" : "") + flat;
|
|
1002
1011
|
} else {
|
|
1003
1012
|
blocks.push(block);
|
|
1004
1013
|
}
|
|
@@ -1114,10 +1123,10 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
|
|
|
1114
1123
|
}
|
|
1115
1124
|
if (text) {
|
|
1116
1125
|
if (tableCtx?.cell) {
|
|
1117
|
-
const
|
|
1126
|
+
const cell2 = tableCtx.cell;
|
|
1118
1127
|
if (footnote) text += ` (\uC8FC: ${footnote})`;
|
|
1119
|
-
|
|
1120
|
-
(
|
|
1128
|
+
cell2.text += (cell2.text ? "\n" : "") + text;
|
|
1129
|
+
(cell2.blocks ??= []).push({ type: "paragraph", text, pageNumber: ctx.sectionNum });
|
|
1121
1130
|
} else if (!tableCtx) {
|
|
1122
1131
|
const block = { type: headingLevel ? "heading" : "paragraph", text, pageNumber: ctx.sectionNum };
|
|
1123
1132
|
if (headingLevel) block.level = headingLevel;
|
|
@@ -1190,18 +1199,18 @@ function userShapeComment(el) {
|
|
|
1190
1199
|
if (/^(?:모서리가 둥근 |둥근 )?[^\n]{1,20}입니다\.?$/.test(text)) return void 0;
|
|
1191
1200
|
return text;
|
|
1192
1201
|
}
|
|
1193
|
-
function mergeBlocksIntoCell(
|
|
1202
|
+
function mergeBlocksIntoCell(cell2, sink) {
|
|
1194
1203
|
for (const b of sink) {
|
|
1195
1204
|
if ((b.type === "paragraph" || b.type === "heading") && b.text) {
|
|
1196
|
-
|
|
1197
|
-
(
|
|
1205
|
+
cell2.text += (cell2.text ? "\n" : "") + b.text;
|
|
1206
|
+
(cell2.blocks ??= []).push(b);
|
|
1198
1207
|
} else if (b.type === "image" || b.type === "table") {
|
|
1199
1208
|
if (b.type === "image" && b.text) {
|
|
1200
|
-
|
|
1209
|
+
cell2.text += (cell2.text ? "\n" : "") + ``;
|
|
1201
1210
|
}
|
|
1202
1211
|
;
|
|
1203
|
-
(
|
|
1204
|
-
|
|
1212
|
+
(cell2.blocks ??= []).push(b);
|
|
1213
|
+
cell2.hasStructure = true;
|
|
1205
1214
|
}
|
|
1206
1215
|
}
|
|
1207
1216
|
}
|
|
@@ -1330,7 +1339,7 @@ function extractHyperlinkHref(fieldBegin) {
|
|
|
1330
1339
|
function isInDeletedRange(ctx) {
|
|
1331
1340
|
return (ctx?.shared.track.deleteDepth ?? 0) > 0;
|
|
1332
1341
|
}
|
|
1333
|
-
function extractParagraphInfo(
|
|
1342
|
+
function extractParagraphInfo(para2, styleMap, ctx) {
|
|
1334
1343
|
let text = "";
|
|
1335
1344
|
let href;
|
|
1336
1345
|
let footnote;
|
|
@@ -1540,7 +1549,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
|
|
|
1540
1549
|
}
|
|
1541
1550
|
}
|
|
1542
1551
|
};
|
|
1543
|
-
walk(
|
|
1552
|
+
walk(para2);
|
|
1544
1553
|
const leaderIdx = text.indexOf("");
|
|
1545
1554
|
if (leaderIdx >= 0) text = text.substring(0, leaderIdx);
|
|
1546
1555
|
let cleanText = text.replace(/[ \t]+/g, " ").trim();
|
|
@@ -1605,8 +1614,8 @@ function collectImageBlocks(blocks, out, ownerCell, depth = 0) {
|
|
|
1605
1614
|
out.push({ block, ownerCell });
|
|
1606
1615
|
} else if (block.type === "table" && block.table) {
|
|
1607
1616
|
for (const row of block.table.cells) {
|
|
1608
|
-
for (const
|
|
1609
|
-
if (
|
|
1617
|
+
for (const cell2 of row) {
|
|
1618
|
+
if (cell2.blocks?.length) collectImageBlocks(cell2.blocks, out, cell2, depth + 1);
|
|
1610
1619
|
}
|
|
1611
1620
|
}
|
|
1612
1621
|
}
|
|
@@ -2267,8 +2276,8 @@ var GANADA = "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC\uC544\uC790\uCC28\uCE74
|
|
|
2267
2276
|
var CIRCLED_GANADA = "\u326E\u326F\u3270\u3271\u3272\u3273\u3274\u3275\u3276\u3277\u3278\u3279\u327A\u327B";
|
|
2268
2277
|
var JAMO = "\u3131\u3134\u3137\u3139\u3141\u3142\u3145\u3147\u3148\u314A\u314B\u314C\u314D\u314E";
|
|
2269
2278
|
var CIRCLED_JAMO = "\u3260\u3261\u3262\u3263\u3264\u3265\u3266\u3267\u3268\u3269\u326A\u326B\u326C\u326D";
|
|
2270
|
-
function fromTable(n,
|
|
2271
|
-
return n >= 1 && n <=
|
|
2279
|
+
function fromTable(n, table2) {
|
|
2280
|
+
return n >= 1 && n <= table2.length ? table2[n - 1] : String(n);
|
|
2272
2281
|
}
|
|
2273
2282
|
function formatRoman(n, upper) {
|
|
2274
2283
|
if (n <= 0 || n > 3999) return String(n);
|
|
@@ -2391,8 +2400,8 @@ function collectImageBlocks2(blocks, out) {
|
|
|
2391
2400
|
if (b.type === "image") out.push(b);
|
|
2392
2401
|
if (b.table) {
|
|
2393
2402
|
for (const row of b.table.cells) {
|
|
2394
|
-
for (const
|
|
2395
|
-
if (
|
|
2403
|
+
for (const cell2 of row) {
|
|
2404
|
+
if (cell2.blocks) collectImageBlocks2(cell2.blocks, out);
|
|
2396
2405
|
}
|
|
2397
2406
|
}
|
|
2398
2407
|
}
|
|
@@ -2403,9 +2412,9 @@ function forEachTableCell(blocks, fn) {
|
|
|
2403
2412
|
for (const b of blocks) {
|
|
2404
2413
|
if (b.table) {
|
|
2405
2414
|
for (const row of b.table.cells) {
|
|
2406
|
-
for (const
|
|
2407
|
-
fn(
|
|
2408
|
-
if (
|
|
2415
|
+
for (const cell2 of row) {
|
|
2416
|
+
fn(cell2);
|
|
2417
|
+
if (cell2.blocks) forEachTableCell(cell2.blocks, fn);
|
|
2409
2418
|
}
|
|
2410
2419
|
}
|
|
2411
2420
|
}
|
|
@@ -2414,9 +2423,9 @@ function forEachTableCell(blocks, fn) {
|
|
|
2414
2423
|
}
|
|
2415
2424
|
var CELL_IMAGE_SENTINEL_RE = /!\[image\]\(hwp5bin:(\d+)\)/g;
|
|
2416
2425
|
function resolveCellImageSentinels(blocks, renamed) {
|
|
2417
|
-
forEachTableCell(blocks, (
|
|
2418
|
-
if (!
|
|
2419
|
-
|
|
2426
|
+
forEachTableCell(blocks, (cell2) => {
|
|
2427
|
+
if (!cell2.text.includes("hwp5bin:")) return;
|
|
2428
|
+
cell2.text = cell2.text.replace(CELL_IMAGE_SENTINEL_RE, (_m, idStr) => {
|
|
2420
2429
|
const filename = renamed.get(Number(idStr));
|
|
2421
2430
|
return filename ? `` : "[\uC774\uBBF8\uC9C0]";
|
|
2422
2431
|
});
|
|
@@ -2507,15 +2516,15 @@ function extractHwp5ImagesLenient(lcfb, blocks, warnings) {
|
|
|
2507
2516
|
// src/image/transcode.ts
|
|
2508
2517
|
import { deflateSync } from "zlib";
|
|
2509
2518
|
var CRC_TABLE = (() => {
|
|
2510
|
-
const
|
|
2519
|
+
const table2 = new Uint32Array(256);
|
|
2511
2520
|
for (let n = 0; n < 256; n++) {
|
|
2512
2521
|
let c = n;
|
|
2513
2522
|
for (let k = 0; k < 8; k++) {
|
|
2514
2523
|
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
2515
2524
|
}
|
|
2516
|
-
|
|
2525
|
+
table2[n] = c >>> 0;
|
|
2517
2526
|
}
|
|
2518
|
-
return
|
|
2527
|
+
return table2;
|
|
2519
2528
|
})();
|
|
2520
2529
|
function crc32(bytes) {
|
|
2521
2530
|
let c = 4294967295;
|
|
@@ -4058,8 +4067,8 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
4058
4067
|
function applyCtrlEffect(ctrl, records, ctx) {
|
|
4059
4068
|
switch (ctrl.id) {
|
|
4060
4069
|
case CTRL_TBL: {
|
|
4061
|
-
const
|
|
4062
|
-
if (
|
|
4070
|
+
const table2 = parseTableControl(ctrl, records, ctx);
|
|
4071
|
+
if (table2) ctrl.afterBlocks = [{ type: "table", table: table2, pageNumber: ctx.sectionNum }];
|
|
4063
4072
|
return;
|
|
4064
4073
|
}
|
|
4065
4074
|
case CTRL_GSO: {
|
|
@@ -4278,14 +4287,14 @@ function parseTableControl(ctrl, records, ctx) {
|
|
|
4278
4287
|
if (c.isHeader) ir.isHeader = true;
|
|
4279
4288
|
return ir;
|
|
4280
4289
|
}));
|
|
4281
|
-
const
|
|
4282
|
-
if (caption)
|
|
4283
|
-
return
|
|
4290
|
+
const table3 = { rows, cols, cells: irCells, hasHeader: rows > 1 };
|
|
4291
|
+
if (caption) table3.caption = caption;
|
|
4292
|
+
return table3;
|
|
4284
4293
|
}
|
|
4285
4294
|
const cellRows = arrangeCells(rows, cols, cells);
|
|
4286
|
-
const
|
|
4287
|
-
if (caption &&
|
|
4288
|
-
return
|
|
4295
|
+
const table2 = buildTable(cellRows);
|
|
4296
|
+
if (caption && table2.rows > 0) table2.caption = caption;
|
|
4297
|
+
return table2.rows > 0 ? table2 : null;
|
|
4289
4298
|
}
|
|
4290
4299
|
function parseCell(records, lhIdx, end, ctx) {
|
|
4291
4300
|
const rec = records[lhIdx];
|
|
@@ -4323,22 +4332,22 @@ function parseCell(records, lhIdx, end, ctx) {
|
|
|
4323
4332
|
parts.push(t);
|
|
4324
4333
|
}
|
|
4325
4334
|
}
|
|
4326
|
-
const
|
|
4327
|
-
if (hasStructure && blocks.length > 0)
|
|
4328
|
-
if (isHeader)
|
|
4329
|
-
return
|
|
4335
|
+
const cell2 = { text: parts.join("\n"), colSpan, rowSpan, colAddr, rowAddr };
|
|
4336
|
+
if (hasStructure && blocks.length > 0) cell2.blocks = blocks;
|
|
4337
|
+
if (isHeader) cell2.isHeader = true;
|
|
4338
|
+
return cell2;
|
|
4330
4339
|
}
|
|
4331
4340
|
function arrangeCells(rows, cols, cells) {
|
|
4332
4341
|
const grid = Array.from({ length: rows }, () => Array(cols).fill(null));
|
|
4333
4342
|
const hasAddr = cells.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0);
|
|
4334
4343
|
if (hasAddr) {
|
|
4335
|
-
for (const
|
|
4336
|
-
const r =
|
|
4337
|
-
const c =
|
|
4344
|
+
for (const cell2 of cells) {
|
|
4345
|
+
const r = cell2.rowAddr ?? 0;
|
|
4346
|
+
const c = cell2.colAddr ?? 0;
|
|
4338
4347
|
if (r >= rows || c >= cols) continue;
|
|
4339
|
-
grid[r][c] =
|
|
4340
|
-
for (let dr = 0; dr <
|
|
4341
|
-
for (let dc = 0; dc <
|
|
4348
|
+
grid[r][c] = cell2;
|
|
4349
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
4350
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
4342
4351
|
if (dr === 0 && dc === 0) continue;
|
|
4343
4352
|
if (r + dr < rows && c + dc < cols)
|
|
4344
4353
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -4350,10 +4359,10 @@ function arrangeCells(rows, cols, cells) {
|
|
|
4350
4359
|
for (let r = 0; r < rows && cellIdx < cells.length; r++) {
|
|
4351
4360
|
for (let c = 0; c < cols && cellIdx < cells.length; c++) {
|
|
4352
4361
|
if (grid[r][c] !== null) continue;
|
|
4353
|
-
const
|
|
4354
|
-
grid[r][c] =
|
|
4355
|
-
for (let dr = 0; dr <
|
|
4356
|
-
for (let dc = 0; dc <
|
|
4362
|
+
const cell2 = cells[cellIdx++];
|
|
4363
|
+
grid[r][c] = cell2;
|
|
4364
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
4365
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
4357
4366
|
if (dr === 0 && dc === 0) continue;
|
|
4358
4367
|
if (r + dr < rows && c + dc < cols)
|
|
4359
4368
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -16869,7 +16878,7 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
16869
16878
|
let lastRow = -1;
|
|
16870
16879
|
for (let r = 0; r <= maxRow; r++) {
|
|
16871
16880
|
const row = grid[r];
|
|
16872
|
-
if (row && row.some((
|
|
16881
|
+
if (row && row.some((cell2) => cell2 !== "")) {
|
|
16873
16882
|
if (firstRow === -1) firstRow = r;
|
|
16874
16883
|
lastRow = r;
|
|
16875
16884
|
}
|
|
@@ -16892,9 +16901,9 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
16892
16901
|
cellRows.push(row);
|
|
16893
16902
|
}
|
|
16894
16903
|
if (cellRows.length > 0) {
|
|
16895
|
-
const
|
|
16896
|
-
if (
|
|
16897
|
-
blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
|
|
16904
|
+
const table2 = buildTable(cellRows);
|
|
16905
|
+
if (table2.rows > 0) {
|
|
16906
|
+
blocks.push({ type: "table", table: table2, pageNumber: sheetIndex + 1 });
|
|
16898
16907
|
}
|
|
16899
16908
|
}
|
|
16900
16909
|
return blocks;
|
|
@@ -17512,9 +17521,9 @@ function sheetToBlocks2(sheetName, sheet, sheetIndex) {
|
|
|
17512
17521
|
cellRows.push(row);
|
|
17513
17522
|
}
|
|
17514
17523
|
if (cellRows.length > 0) {
|
|
17515
|
-
const
|
|
17516
|
-
if (
|
|
17517
|
-
blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
|
|
17524
|
+
const table2 = buildTable(cellRows);
|
|
17525
|
+
if (table2.rows > 0) {
|
|
17526
|
+
blocks.push({ type: "table", table: table2, pageNumber: sheetIndex + 1 });
|
|
17518
17527
|
}
|
|
17519
17528
|
}
|
|
17520
17529
|
return blocks;
|
|
@@ -18260,8 +18269,8 @@ function collectTextboxParagraphs(node, inTxbx = false, out = [], depth = 0) {
|
|
|
18260
18269
|
}
|
|
18261
18270
|
return out;
|
|
18262
18271
|
}
|
|
18263
|
-
function parseTable(
|
|
18264
|
-
const trElements = getChildElements(
|
|
18272
|
+
function parseTable(tbl2, styles, numbering, footnotes, rels) {
|
|
18273
|
+
const trElements = getChildElements(tbl2, "tr");
|
|
18265
18274
|
if (trElements.length === 0) return null;
|
|
18266
18275
|
const rawRows = [];
|
|
18267
18276
|
for (const tr of trElements) {
|
|
@@ -18274,10 +18283,10 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18274
18283
|
col = Math.max(0, parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0);
|
|
18275
18284
|
}
|
|
18276
18285
|
}
|
|
18277
|
-
for (const
|
|
18286
|
+
for (const tc2 of getChildElements(tr, "tc")) {
|
|
18278
18287
|
let colSpan = 1;
|
|
18279
18288
|
let vMerge = null;
|
|
18280
|
-
const tcPrEls = getChildElements(
|
|
18289
|
+
const tcPrEls = getChildElements(tc2, "tcPr");
|
|
18281
18290
|
if (tcPrEls.length > 0) {
|
|
18282
18291
|
const gridSpanEls = getChildElements(tcPrEls[0], "gridSpan");
|
|
18283
18292
|
if (gridSpanEls.length > 0) {
|
|
@@ -18288,48 +18297,48 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18288
18297
|
vMerge = getAttr(vMergeEls[0], "val") === "restart" ? "restart" : "continue";
|
|
18289
18298
|
}
|
|
18290
18299
|
}
|
|
18291
|
-
const text = collectCellText(
|
|
18300
|
+
const text = collectCellText(tc2, styles, numbering, footnotes, rels, 0).join("\n");
|
|
18292
18301
|
row.push({ col, colSpan, vMerge, text });
|
|
18293
18302
|
col += colSpan;
|
|
18294
18303
|
}
|
|
18295
18304
|
rawRows.push(row);
|
|
18296
18305
|
}
|
|
18297
18306
|
for (let r = 0; r < rawRows.length; r++) {
|
|
18298
|
-
for (const
|
|
18299
|
-
if (
|
|
18307
|
+
for (const cell2 of rawRows[r]) {
|
|
18308
|
+
if (cell2.vMerge !== "continue" || !cell2.text) continue;
|
|
18300
18309
|
let start;
|
|
18301
18310
|
for (let pr = r - 1; pr >= 0 && !start; pr--) {
|
|
18302
|
-
start = rawRows[pr].find((pc) => pc.col ===
|
|
18311
|
+
start = rawRows[pr].find((pc) => pc.col === cell2.col && pc.vMerge !== "continue");
|
|
18303
18312
|
}
|
|
18304
18313
|
if (start) {
|
|
18305
18314
|
start.text = start.text ? `${start.text}
|
|
18306
|
-
${
|
|
18307
|
-
|
|
18315
|
+
${cell2.text}` : cell2.text;
|
|
18316
|
+
cell2.text = "";
|
|
18308
18317
|
} else {
|
|
18309
|
-
|
|
18318
|
+
cell2.vMerge = null;
|
|
18310
18319
|
}
|
|
18311
18320
|
}
|
|
18312
18321
|
}
|
|
18313
18322
|
const cellRows = rawRows.map(
|
|
18314
|
-
(row, r) => row.filter((
|
|
18323
|
+
(row, r) => row.filter((cell2) => cell2.vMerge !== "continue").map((cell2) => {
|
|
18315
18324
|
let rowSpan = 1;
|
|
18316
|
-
if (
|
|
18325
|
+
if (cell2.vMerge === "restart") {
|
|
18317
18326
|
for (let nr = r + 1; nr < rawRows.length; nr++) {
|
|
18318
|
-
if (!rawRows[nr].some((nc) => nc.col ===
|
|
18327
|
+
if (!rawRows[nr].some((nc) => nc.col === cell2.col && nc.vMerge === "continue")) break;
|
|
18319
18328
|
rowSpan++;
|
|
18320
18329
|
}
|
|
18321
18330
|
}
|
|
18322
|
-
return { text:
|
|
18331
|
+
return { text: cell2.text, colSpan: cell2.colSpan, rowSpan, colAddr: cell2.col, rowAddr: r };
|
|
18323
18332
|
})
|
|
18324
18333
|
);
|
|
18325
|
-
const
|
|
18326
|
-
if (
|
|
18327
|
-
return { type: "table", table };
|
|
18334
|
+
const table2 = buildTable(cellRows);
|
|
18335
|
+
if (table2.rows === 0 || table2.cols === 0) return null;
|
|
18336
|
+
return { type: "table", table: table2 };
|
|
18328
18337
|
}
|
|
18329
|
-
function collectCellText(
|
|
18338
|
+
function collectCellText(tc2, styles, numbering, footnotes, rels, depth) {
|
|
18330
18339
|
const parts = [];
|
|
18331
18340
|
if (depth > 20) return parts;
|
|
18332
|
-
for (const el of effectiveChildElements(
|
|
18341
|
+
for (const el of effectiveChildElements(tc2)) {
|
|
18333
18342
|
if (matchesLocal(el, "p")) {
|
|
18334
18343
|
const block = parseParagraph2(el, styles, numbering, footnotes, rels);
|
|
18335
18344
|
if (block?.text) parts.push(block.text);
|
|
@@ -18690,13 +18699,13 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18690
18699
|
}
|
|
18691
18700
|
if (cells.length === 0) return;
|
|
18692
18701
|
const grid = Array.from({ length: rowCount }, () => Array(colCount).fill(null));
|
|
18693
|
-
for (const
|
|
18694
|
-
const r =
|
|
18695
|
-
const c =
|
|
18702
|
+
for (const cell2 of cells) {
|
|
18703
|
+
const r = cell2.rowAddr ?? 0;
|
|
18704
|
+
const c = cell2.colAddr ?? 0;
|
|
18696
18705
|
if (isNaN(r) || isNaN(c) || r >= rowCount || c >= colCount) continue;
|
|
18697
|
-
grid[r][c] =
|
|
18698
|
-
for (let dr = 0; dr <
|
|
18699
|
-
for (let dc = 0; dc <
|
|
18706
|
+
grid[r][c] = cell2;
|
|
18707
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
18708
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
18700
18709
|
if (dr === 0 && dc === 0) continue;
|
|
18701
18710
|
if (r + dr < rowCount && c + dc < colCount) {
|
|
18702
18711
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -18705,14 +18714,14 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18705
18714
|
}
|
|
18706
18715
|
}
|
|
18707
18716
|
const cellRows = grid.map(
|
|
18708
|
-
(row) => row.map((
|
|
18717
|
+
(row) => row.map((cell2) => cell2 ?? { text: "", colSpan: 1, rowSpan: 1 })
|
|
18709
18718
|
);
|
|
18710
|
-
const
|
|
18719
|
+
const table2 = buildTable(cellRows);
|
|
18711
18720
|
const caption = extractShapeCaption(el);
|
|
18712
18721
|
if (caption.text && caption.before) {
|
|
18713
18722
|
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18714
18723
|
}
|
|
18715
|
-
blocks.push({ type: "table", table, pageNumber: sectionNum });
|
|
18724
|
+
blocks.push({ type: "table", table: table2, pageNumber: sectionNum });
|
|
18716
18725
|
if (caption.text && !caption.before) {
|
|
18717
18726
|
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18718
18727
|
}
|
|
@@ -19212,13 +19221,13 @@ function extractFormFields(blocks) {
|
|
|
19212
19221
|
const confidence = totalTables > 0 ? formTables / totalTables : fields.length > 0 ? 0.3 : 0;
|
|
19213
19222
|
return { fields, confidence: Math.min(confidence, 1) };
|
|
19214
19223
|
}
|
|
19215
|
-
function extractFromTable(
|
|
19224
|
+
function extractFromTable(table2) {
|
|
19216
19225
|
const fields = [];
|
|
19217
|
-
if (
|
|
19218
|
-
for (let r = 0; r <
|
|
19219
|
-
for (let c = 0; c <
|
|
19220
|
-
const labelCell =
|
|
19221
|
-
const valueCell =
|
|
19226
|
+
if (table2.cols >= 2) {
|
|
19227
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19228
|
+
for (let c = 0; c < table2.cols - 1; c++) {
|
|
19229
|
+
const labelCell = table2.cells[r]?.[c];
|
|
19230
|
+
const valueCell = table2.cells[r]?.[c + 1];
|
|
19222
19231
|
if (!labelCell || !valueCell) continue;
|
|
19223
19232
|
if (isLabelCell(labelCell.text)) {
|
|
19224
19233
|
fields.push({
|
|
@@ -19231,17 +19240,17 @@ function extractFromTable(table) {
|
|
|
19231
19240
|
}
|
|
19232
19241
|
}
|
|
19233
19242
|
}
|
|
19234
|
-
if (fields.length === 0 &&
|
|
19235
|
-
const headerRow =
|
|
19236
|
-
const allLabels = headerRow.every((
|
|
19237
|
-
const t =
|
|
19243
|
+
if (fields.length === 0 && table2.rows >= 2 && table2.cols >= 2) {
|
|
19244
|
+
const headerRow = table2.cells[0];
|
|
19245
|
+
const allLabels = headerRow.every((cell2) => {
|
|
19246
|
+
const t = cell2.text.trim();
|
|
19238
19247
|
return t.length > 0 && t.length <= 20;
|
|
19239
19248
|
});
|
|
19240
19249
|
if (allLabels) {
|
|
19241
|
-
for (let r = 1; r <
|
|
19242
|
-
for (let c = 0; c <
|
|
19250
|
+
for (let r = 1; r < table2.rows; r++) {
|
|
19251
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19243
19252
|
const label = headerRow[c]?.text.trim() ?? "";
|
|
19244
|
-
const value =
|
|
19253
|
+
const value = table2.cells[r]?.[c]?.text.trim() ?? "";
|
|
19245
19254
|
if (label && value) {
|
|
19246
19255
|
fields.push({ label, value, row: r, col: c });
|
|
19247
19256
|
}
|
|
@@ -19278,9 +19287,9 @@ function inferFieldType(label, value) {
|
|
|
19278
19287
|
if (/^[\d,.\s]+(?:원|명|건|개|회|부|매|%)$/.test(v) && /\d/.test(v)) return "amount";
|
|
19279
19288
|
if (/^\d{1,3}(?:,\d{3})+$/.test(v)) return "amount";
|
|
19280
19289
|
}
|
|
19281
|
-
const
|
|
19290
|
+
const norm2 = label.replace(/\s/g, "");
|
|
19282
19291
|
for (const [re, type] of LABEL_TYPE_RULES) {
|
|
19283
|
-
if (re.test(
|
|
19292
|
+
if (re.test(norm2)) return type;
|
|
19284
19293
|
}
|
|
19285
19294
|
return "text";
|
|
19286
19295
|
}
|
|
@@ -19331,15 +19340,15 @@ function fillFormFields(blocks, values, blockedLabels) {
|
|
|
19331
19340
|
const cursor = new ValueCursor(normalizedValues);
|
|
19332
19341
|
const allTables = collectIRTables(cloned, 0);
|
|
19333
19342
|
const patternFilledCells = /* @__PURE__ */ new Set();
|
|
19334
|
-
for (const
|
|
19335
|
-
for (let r = 0; r <
|
|
19336
|
-
for (let c = 0; c <
|
|
19337
|
-
const
|
|
19338
|
-
if (!
|
|
19339
|
-
const result = fillInCellPatterns(
|
|
19343
|
+
for (const table2 of allTables) {
|
|
19344
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19345
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19346
|
+
const cell2 = table2.cells[r]?.[c];
|
|
19347
|
+
if (!cell2) continue;
|
|
19348
|
+
const result = fillInCellPatterns(cell2.text, cursor, matchedLabels, blockedLabels);
|
|
19340
19349
|
if (result) {
|
|
19341
|
-
|
|
19342
|
-
patternFilledCells.add(
|
|
19350
|
+
cell2.text = result.text;
|
|
19351
|
+
patternFilledCells.add(cell2);
|
|
19343
19352
|
for (const m of result.matches) {
|
|
19344
19353
|
filled.push({ label: m.label, value: m.value, row: r, col: c, key: m.key });
|
|
19345
19354
|
}
|
|
@@ -19347,8 +19356,8 @@ function fillFormFields(blocks, values, blockedLabels) {
|
|
|
19347
19356
|
}
|
|
19348
19357
|
}
|
|
19349
19358
|
}
|
|
19350
|
-
for (const
|
|
19351
|
-
fillTable(
|
|
19359
|
+
for (const table2 of allTables) {
|
|
19360
|
+
fillTable(table2, cursor, filled, matchedLabels, patternFilledCells, blockedLabels);
|
|
19352
19361
|
}
|
|
19353
19362
|
for (const block of cloned) {
|
|
19354
19363
|
if (block.type !== "paragraph" || !block.text) continue;
|
|
@@ -19365,44 +19374,44 @@ function collectIRTables(blocks, depth) {
|
|
|
19365
19374
|
if (block.type !== "table" || !block.table) continue;
|
|
19366
19375
|
out.push(block.table);
|
|
19367
19376
|
for (const row of block.table.cells) {
|
|
19368
|
-
for (const
|
|
19369
|
-
if (
|
|
19377
|
+
for (const cell2 of row) {
|
|
19378
|
+
if (cell2?.blocks?.length) out.push(...collectIRTables(cell2.blocks, depth + 1));
|
|
19370
19379
|
}
|
|
19371
19380
|
}
|
|
19372
19381
|
}
|
|
19373
19382
|
return out;
|
|
19374
19383
|
}
|
|
19375
|
-
function coveredPositions(
|
|
19384
|
+
function coveredPositions(table2) {
|
|
19376
19385
|
const covered = /* @__PURE__ */ new Set();
|
|
19377
|
-
for (let r = 0; r <
|
|
19378
|
-
for (let c = 0; c <
|
|
19386
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19387
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19379
19388
|
if (covered.has(`${r},${c}`)) continue;
|
|
19380
|
-
const
|
|
19381
|
-
if (!
|
|
19382
|
-
for (let dr = 0; dr <
|
|
19383
|
-
for (let dc = 0; dc <
|
|
19389
|
+
const cell2 = table2.cells[r]?.[c];
|
|
19390
|
+
if (!cell2) continue;
|
|
19391
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
19392
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
19384
19393
|
if (dr === 0 && dc === 0) continue;
|
|
19385
|
-
if (r + dr <
|
|
19394
|
+
if (r + dr < table2.rows && c + dc < table2.cols) covered.add(`${r + dr},${c + dc}`);
|
|
19386
19395
|
}
|
|
19387
19396
|
}
|
|
19388
|
-
c +=
|
|
19397
|
+
c += cell2.colSpan - 1;
|
|
19389
19398
|
}
|
|
19390
19399
|
}
|
|
19391
19400
|
return covered;
|
|
19392
19401
|
}
|
|
19393
|
-
function fillTable(
|
|
19394
|
-
if (
|
|
19395
|
-
const covered = coveredPositions(
|
|
19396
|
-
for (let r = 0; r <
|
|
19397
|
-
for (let c = 0; c <
|
|
19402
|
+
function fillTable(table2, values, filled, matchedLabels, patternFilledCells, blockedLabels) {
|
|
19403
|
+
if (table2.cols < 2) return;
|
|
19404
|
+
const covered = coveredPositions(table2);
|
|
19405
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19406
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19398
19407
|
if (covered.has(`${r},${c}`)) continue;
|
|
19399
|
-
const labelCell =
|
|
19408
|
+
const labelCell = table2.cells[r][c];
|
|
19400
19409
|
if (!labelCell) continue;
|
|
19401
19410
|
if (!isLabelCell(labelCell.text)) continue;
|
|
19402
19411
|
let vc = c + labelCell.colSpan;
|
|
19403
|
-
while (vc <
|
|
19404
|
-
if (vc >=
|
|
19405
|
-
const valueCell =
|
|
19412
|
+
while (vc < table2.cols && covered.has(`${r},${vc}`)) vc++;
|
|
19413
|
+
if (vc >= table2.cols) continue;
|
|
19414
|
+
const valueCell = table2.cells[r][vc];
|
|
19406
19415
|
if (!valueCell) continue;
|
|
19407
19416
|
if (isKeywordLabel(valueCell.text)) continue;
|
|
19408
19417
|
const normalizedCellLabel = normalizeLabel(labelCell.text);
|
|
@@ -19427,18 +19436,18 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells, blo
|
|
|
19427
19436
|
});
|
|
19428
19437
|
}
|
|
19429
19438
|
}
|
|
19430
|
-
if (
|
|
19431
|
-
const headerRow =
|
|
19432
|
-
const allLabels = headerRow.every((
|
|
19433
|
-
const t =
|
|
19439
|
+
if (table2.rows >= 2 && table2.cols >= 2) {
|
|
19440
|
+
const headerRow = table2.cells[0];
|
|
19441
|
+
const allLabels = headerRow.every((cell2) => {
|
|
19442
|
+
const t = cell2.text.trim();
|
|
19434
19443
|
return t.length > 0 && t.length <= 20 && isLabelCell(t);
|
|
19435
19444
|
});
|
|
19436
19445
|
if (!allLabels) return;
|
|
19437
|
-
for (let r = 1; r <
|
|
19438
|
-
for (let c = 0; c <
|
|
19446
|
+
for (let r = 1; r < table2.rows; r++) {
|
|
19447
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19439
19448
|
if (covered.has(`${r},${c}`)) continue;
|
|
19440
19449
|
const headerCell = headerRow[c];
|
|
19441
|
-
const valueCell =
|
|
19450
|
+
const valueCell = table2.cells[r]?.[c];
|
|
19442
19451
|
if (!headerCell || !valueCell) continue;
|
|
19443
19452
|
const headerLabel = normalizeLabel(headerCell.text);
|
|
19444
19453
|
if (blockedLabels?.has(headerLabel)) continue;
|
|
@@ -19509,28 +19518,28 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19509
19518
|
return l;
|
|
19510
19519
|
};
|
|
19511
19520
|
const matchText = (p) => paraTText(p, xml) ?? p.text;
|
|
19512
|
-
const cellLabelText = (
|
|
19521
|
+
const cellLabelText = (cell2) => cell2.paragraphs.filter((p) => !p.inTextbox).map((p) => matchText(p)).join("");
|
|
19513
19522
|
const allTables = [];
|
|
19514
19523
|
const collectTables = (tables, depth) => {
|
|
19515
19524
|
if (depth > 16) return;
|
|
19516
19525
|
for (const t of tables) {
|
|
19517
19526
|
allTables.push(t);
|
|
19518
19527
|
for (const row of t.rows) {
|
|
19519
|
-
for (const
|
|
19528
|
+
for (const cell2 of row) collectTables(cell2.tables, depth + 1);
|
|
19520
19529
|
}
|
|
19521
19530
|
}
|
|
19522
19531
|
};
|
|
19523
19532
|
collectTables(scan.tables, 0);
|
|
19524
19533
|
collectTables(scan.orphanTables, 0);
|
|
19525
19534
|
const patternApplied = /* @__PURE__ */ new Set();
|
|
19526
|
-
for (const
|
|
19527
|
-
for (const row of
|
|
19528
|
-
for (const
|
|
19529
|
-
for (const
|
|
19530
|
-
const text = matchText(
|
|
19535
|
+
for (const table2 of allTables) {
|
|
19536
|
+
for (const row of table2.rows) {
|
|
19537
|
+
for (const cell2 of row) {
|
|
19538
|
+
for (const para2 of cell2.paragraphs) {
|
|
19539
|
+
const text = matchText(para2);
|
|
19531
19540
|
const result = fillInCellPatterns(text, cursor, matchedLabels, blockedLabels);
|
|
19532
19541
|
if (!result) continue;
|
|
19533
|
-
const l = led(
|
|
19542
|
+
const l = led(para2);
|
|
19534
19543
|
if (l.fullText !== void 0) continue;
|
|
19535
19544
|
const newT = result.text;
|
|
19536
19545
|
let s = 0;
|
|
@@ -19542,7 +19551,7 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19542
19551
|
en--;
|
|
19543
19552
|
}
|
|
19544
19553
|
l.ranges.push({ start: s, end: eo, replacement: newT.slice(s, en) });
|
|
19545
|
-
patternApplied.add(
|
|
19554
|
+
patternApplied.add(cell2);
|
|
19546
19555
|
for (const m of result.matches) {
|
|
19547
19556
|
l.filledIdx.push(filled.length);
|
|
19548
19557
|
l.matchKeys.push(m.key);
|
|
@@ -19552,9 +19561,9 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19552
19561
|
}
|
|
19553
19562
|
}
|
|
19554
19563
|
}
|
|
19555
|
-
for (const
|
|
19556
|
-
for (let rowIdx = 0; rowIdx <
|
|
19557
|
-
const cells =
|
|
19564
|
+
for (const table2 of allTables) {
|
|
19565
|
+
for (let rowIdx = 0; rowIdx < table2.rows.length; rowIdx++) {
|
|
19566
|
+
const cells = table2.rows[rowIdx];
|
|
19558
19567
|
for (let colIdx = 0; colIdx < cells.length - 1; colIdx++) {
|
|
19559
19568
|
const labelText = cellLabelText(cells[colIdx]);
|
|
19560
19569
|
if (!isLabelCell(labelText)) continue;
|
|
@@ -19609,15 +19618,15 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19609
19618
|
}
|
|
19610
19619
|
}
|
|
19611
19620
|
}
|
|
19612
|
-
if (
|
|
19613
|
-
const headerCells =
|
|
19614
|
-
const allLabels = headerCells.length > 0 && headerCells.every((
|
|
19615
|
-
const t = cellLabelText(
|
|
19621
|
+
if (table2.rows.length >= 2) {
|
|
19622
|
+
const headerCells = table2.rows[0];
|
|
19623
|
+
const allLabels = headerCells.length > 0 && headerCells.every((cell2) => {
|
|
19624
|
+
const t = cellLabelText(cell2).trim();
|
|
19616
19625
|
return t.length > 0 && t.length <= 20 && isLabelCell(t);
|
|
19617
19626
|
});
|
|
19618
19627
|
if (allLabels) {
|
|
19619
|
-
for (let rowIdx = 1; rowIdx <
|
|
19620
|
-
const dataCells =
|
|
19628
|
+
for (let rowIdx = 1; rowIdx < table2.rows.length; rowIdx++) {
|
|
19629
|
+
const dataCells = table2.rows[rowIdx];
|
|
19621
19630
|
for (let colIdx = 0; colIdx < Math.min(headerCells.length, dataCells.length); colIdx++) {
|
|
19622
19631
|
const headerLabel = normalizeLabel(cellLabelText(headerCells[colIdx]));
|
|
19623
19632
|
if (blockedLabels?.has(headerLabel)) continue;
|
|
@@ -19651,10 +19660,10 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19651
19660
|
}
|
|
19652
19661
|
}
|
|
19653
19662
|
}
|
|
19654
|
-
for (const
|
|
19655
|
-
const existing = ledger.get(
|
|
19663
|
+
for (const para2 of [...scan.bodyParagraphs, ...scan.excludedParagraphs]) {
|
|
19664
|
+
const existing = ledger.get(para2);
|
|
19656
19665
|
if (existing?.fullText !== void 0) continue;
|
|
19657
|
-
const text = matchText(
|
|
19666
|
+
const text = matchText(para2);
|
|
19658
19667
|
for (const seg of scanInlineSegments(text)) {
|
|
19659
19668
|
const nlabel = normalizeLabel(seg.label);
|
|
19660
19669
|
if (blockedLabels?.has(nlabel)) continue;
|
|
@@ -19663,7 +19672,7 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19663
19672
|
const newValue = cursor.consume(matchKey);
|
|
19664
19673
|
if (newValue === void 0) continue;
|
|
19665
19674
|
const replacement = seg.valueStart === seg.valueEnd ? padInsertion(text, seg.valueStart, newValue) : newValue;
|
|
19666
|
-
const l = led(
|
|
19675
|
+
const l = led(para2);
|
|
19667
19676
|
l.ranges.push({ start: seg.valueStart, end: seg.valueEnd, replacement });
|
|
19668
19677
|
matchedLabels.add(matchKey);
|
|
19669
19678
|
l.filledIdx.push(filled.length);
|
|
@@ -19672,10 +19681,10 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19672
19681
|
}
|
|
19673
19682
|
}
|
|
19674
19683
|
const splices = [];
|
|
19675
|
-
for (const [
|
|
19684
|
+
for (const [para2, l] of ledger) {
|
|
19676
19685
|
let paraSplices = null;
|
|
19677
19686
|
if (l.fullText !== void 0) {
|
|
19678
|
-
paraSplices = buildParagraphSplices(
|
|
19687
|
+
paraSplices = buildParagraphSplices(para2, l.fullText, xml);
|
|
19679
19688
|
} else if (l.ranges.length > 0) {
|
|
19680
19689
|
const sorted = [...l.ranges].sort((a, b) => a.start - b.start || a.end - b.end);
|
|
19681
19690
|
const merged = [];
|
|
@@ -19684,11 +19693,11 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19684
19693
|
if (prev && r.start < prev.end) continue;
|
|
19685
19694
|
merged.push(r);
|
|
19686
19695
|
}
|
|
19687
|
-
if (paraTText(
|
|
19696
|
+
if (paraTText(para2, xml) !== null) {
|
|
19688
19697
|
const precise = [];
|
|
19689
19698
|
let ok = true;
|
|
19690
19699
|
for (const r of merged) {
|
|
19691
|
-
const sp = buildRangeSplices(
|
|
19700
|
+
const sp = buildRangeSplices(para2, xml, r.start, r.end, r.replacement);
|
|
19692
19701
|
if (!sp) {
|
|
19693
19702
|
ok = false;
|
|
19694
19703
|
break;
|
|
@@ -19696,13 +19705,13 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19696
19705
|
precise.push(...sp);
|
|
19697
19706
|
}
|
|
19698
19707
|
paraSplices = ok ? precise : null;
|
|
19699
|
-
} else if (paraTextPureT(
|
|
19700
|
-
let text =
|
|
19708
|
+
} else if (paraTextPureT(para2, xml)) {
|
|
19709
|
+
let text = para2.text;
|
|
19701
19710
|
for (let k = merged.length - 1; k >= 0; k--) {
|
|
19702
19711
|
const r = merged[k];
|
|
19703
19712
|
text = text.slice(0, r.start) + r.replacement + text.slice(r.end);
|
|
19704
19713
|
}
|
|
19705
|
-
paraSplices = buildParagraphSplices(
|
|
19714
|
+
paraSplices = buildParagraphSplices(para2, text, xml);
|
|
19706
19715
|
} else {
|
|
19707
19716
|
paraSplices = null;
|
|
19708
19717
|
}
|
|
@@ -19736,14 +19745,126 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19736
19745
|
// src/hwpx/generator.ts
|
|
19737
19746
|
import JSZip6 from "jszip";
|
|
19738
19747
|
|
|
19748
|
+
// src/hwpx/gaejosik.ts
|
|
19749
|
+
var GAEJOSIK_BULLETS = ["\u25A1", "\u25CB", "\u2015", "\u318D"];
|
|
19750
|
+
function gaejosikMarker(depth) {
|
|
19751
|
+
return GAEJOSIK_BULLETS[Math.min(depth, GAEJOSIK_BULLETS.length - 1)];
|
|
19752
|
+
}
|
|
19753
|
+
function gaejosikSizes(bodyHeight, ov = {}) {
|
|
19754
|
+
const s = bodyHeight / 1500;
|
|
19755
|
+
const r = (v, pt) => pt ? Math.round(pt * 100) : Math.round(v * s);
|
|
19756
|
+
return {
|
|
19757
|
+
/** □ 대항목 — HY헤드라인M 16pt */
|
|
19758
|
+
dae: r(1600, ov.dae),
|
|
19759
|
+
/** ※ 참고 — 한양중고딕 13pt */
|
|
19760
|
+
cham: r(1300, ov.cham),
|
|
19761
|
+
/** 장 헤더(로마숫자·제목) 17pt */
|
|
19762
|
+
chapter: r(1700, ov.chapter),
|
|
19763
|
+
/** 표지 제목 30pt */
|
|
19764
|
+
coverTitle: r(3e3, ov.coverTitle),
|
|
19765
|
+
/** 표지 날짜·기관명 25pt */
|
|
19766
|
+
coverSub: r(2500, ov.coverSub),
|
|
19767
|
+
/** 목차 라벨 "목 차" 28pt */
|
|
19768
|
+
tocLabel: r(2800, ov.tocLabel),
|
|
19769
|
+
/** 목차 로마숫자 21pt(한양신명조) */
|
|
19770
|
+
tocRoman: r(2100, ov.tocRoman),
|
|
19771
|
+
/** 목차 항목 18pt */
|
|
19772
|
+
tocItem: r(1800, ov.tocItem),
|
|
19773
|
+
/** 표 셀 — 맑은 고딕 12pt (실측: 정부 양식 표) */
|
|
19774
|
+
table: r(1200, ov.table),
|
|
19775
|
+
/** 표지 장식 바 셀 빈 문단 — 6pt (실측: 바 높이 818 안에 줄높이 수납) */
|
|
19776
|
+
bar: r(600),
|
|
19777
|
+
/** 본문 첫 페이지 제목 박스 — HY헤드라인M 22pt (실측: GT3 표④) */
|
|
19778
|
+
bodyTitle: r(2200, ov.bodyTitle)
|
|
19779
|
+
};
|
|
19780
|
+
}
|
|
19781
|
+
function gaejosikSpaceBefore(depth, bodyHeight) {
|
|
19782
|
+
const s = bodyHeight / 1500;
|
|
19783
|
+
const ui = [3e3, 2e3, 1200, 600][Math.min(depth, 3)];
|
|
19784
|
+
return Math.round(ui * s);
|
|
19785
|
+
}
|
|
19786
|
+
function gaejosikLevelIndent(depth, bodyHeight, sizes = {}) {
|
|
19787
|
+
const lefts = [0, 1, 1.5, 2];
|
|
19788
|
+
const left = depth <= 3 ? Math.round(lefts[depth] * bodyHeight) : Math.round((2 + (depth - 3) * 0.5) * bodyHeight);
|
|
19789
|
+
const h = depth === 0 ? gaejosikSizes(bodyHeight, sizes).dae : bodyHeight;
|
|
19790
|
+
return { left, indent: -markerWidth(gaejosikMarker(depth), h) };
|
|
19791
|
+
}
|
|
19792
|
+
function gaejosikChamIndent(bodyHeight, sizes = {}) {
|
|
19793
|
+
const cham = gaejosikSizes(bodyHeight, sizes).cham;
|
|
19794
|
+
return { left: Math.round(2.5 * cham), indent: -markerWidth("\u203B", cham) };
|
|
19795
|
+
}
|
|
19796
|
+
function gaejosikTocItemIndent(bodyHeight, sizes = {}) {
|
|
19797
|
+
const sz = gaejosikSizes(bodyHeight, sizes);
|
|
19798
|
+
const hang = markerWidth("\u2167.", sz.tocRoman);
|
|
19799
|
+
return { left: 2e3 + hang, indent: -hang };
|
|
19800
|
+
}
|
|
19801
|
+
function formatGaejosikDate(d) {
|
|
19802
|
+
return `${d.getFullYear()}. ${d.getMonth() + 1}. ${d.getDate()}.`;
|
|
19803
|
+
}
|
|
19804
|
+
function stripChapterNumber(title) {
|
|
19805
|
+
return title.replace(/^\s*(?:\d+|[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ]+)\s*[.)]\s*/u, "").trim();
|
|
19806
|
+
}
|
|
19807
|
+
var GAEJOSIK_COLORS = {
|
|
19808
|
+
/** 장헤더 로마숫자 셀·표지 진한 바 음영 */
|
|
19809
|
+
primary: "#193AAA",
|
|
19810
|
+
/** 장헤더 셀 테두리 */
|
|
19811
|
+
border: "#006699",
|
|
19812
|
+
/** 표지 연한 바 */
|
|
19813
|
+
accent: "#A0B4E6",
|
|
19814
|
+
/** 장헤더 제목 셀 음영 */
|
|
19815
|
+
titleFill: "#F2F2F2",
|
|
19816
|
+
/** 장헤더 제목 셀 상하선 */
|
|
19817
|
+
titleLine: "#A6A6A6",
|
|
19818
|
+
/** 목차 박스 테두리 */
|
|
19819
|
+
tocBorder: "#514BAC",
|
|
19820
|
+
/** 목차 배너 라벤더 스트라이프 (실측: GT3 표②) */
|
|
19821
|
+
tocStripe: "#E0E5FA"
|
|
19822
|
+
};
|
|
19823
|
+
var CHAPTER_GEOM = { numW: 3327, gapW: 848, titleW: 43513, rowH: 2832 };
|
|
19824
|
+
var COVER_GEOM = {
|
|
19825
|
+
totalW: 48180,
|
|
19826
|
+
topDarkW: 38219,
|
|
19827
|
+
topLightW: 9961,
|
|
19828
|
+
barH: 818,
|
|
19829
|
+
titleH: 11060,
|
|
19830
|
+
botDarkW: 10466,
|
|
19831
|
+
botLightW: 37714,
|
|
19832
|
+
botBarH: 812
|
|
19833
|
+
};
|
|
19834
|
+
var TOC_GEOM = { boxW: 46492, boxH: 57840 };
|
|
19835
|
+
function chapterGeom(bodyHeight, ov = {}) {
|
|
19836
|
+
const s = gaejosikSizes(bodyHeight, ov).chapter / 1700;
|
|
19837
|
+
return { ...CHAPTER_GEOM, rowH: Math.round(CHAPTER_GEOM.rowH * s) };
|
|
19838
|
+
}
|
|
19839
|
+
function coverGeom(bodyHeight, ov = {}) {
|
|
19840
|
+
const s = gaejosikSizes(bodyHeight, ov).coverTitle / 3e3;
|
|
19841
|
+
return { ...COVER_GEOM, titleH: Math.round(COVER_GEOM.titleH * s) };
|
|
19842
|
+
}
|
|
19843
|
+
var TOC_BANNER_GEOM = {
|
|
19844
|
+
colWs: [565, 565, 1414, 13191, 1414, 565, 565],
|
|
19845
|
+
h: 3931
|
|
19846
|
+
};
|
|
19847
|
+
function tocBannerGeom(bodyHeight, ov = {}) {
|
|
19848
|
+
const s = gaejosikSizes(bodyHeight, ov).tocLabel / 2800;
|
|
19849
|
+
return { colWs: TOC_BANNER_GEOM.colWs, h: Math.round(TOC_BANNER_GEOM.h * s) };
|
|
19850
|
+
}
|
|
19851
|
+
var BODY_TITLE_GEOM = { barH: 600, titleH: 3566 };
|
|
19852
|
+
function bodyTitleGeom(bodyHeight, ov = {}) {
|
|
19853
|
+
const s = gaejosikSizes(bodyHeight, ov).bodyTitle / 2200;
|
|
19854
|
+
return { barH: BODY_TITLE_GEOM.barH, titleH: Math.round(BODY_TITLE_GEOM.titleH * s) };
|
|
19855
|
+
}
|
|
19856
|
+
|
|
19739
19857
|
// src/hwpx/gongmun.ts
|
|
19740
19858
|
var OFFICIAL_MARGINS = { top: 20, bottom: 10, left: 20, right: 20 };
|
|
19859
|
+
var GAEJOSIK_MARGINS = { top: 15, bottom: 15, left: 20, right: 20 };
|
|
19860
|
+
var GAEJOSIK_HEADER_FOOTER = 4251;
|
|
19741
19861
|
var PRESET_DEFAULTS = {
|
|
19742
19862
|
official: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
19743
19863
|
report: { bodyPt: 15, lineSpacing: 160, numbering: "report" },
|
|
19744
19864
|
plan: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
19745
19865
|
notice: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
19746
|
-
minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" }
|
|
19866
|
+
minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" },
|
|
19867
|
+
gaejosik: { bodyPt: 15, lineSpacing: 160, numbering: "gaejosik" }
|
|
19747
19868
|
};
|
|
19748
19869
|
var PRESET_ALIAS = {
|
|
19749
19870
|
official: "official",
|
|
@@ -19761,7 +19882,12 @@ var PRESET_ALIAS = {
|
|
|
19761
19882
|
\uC54C\uB9BC: "notice",
|
|
19762
19883
|
\uC548\uB0B4: "notice",
|
|
19763
19884
|
minutes: "minutes",
|
|
19764
|
-
\uD68C\uC758\uB85D: "minutes"
|
|
19885
|
+
\uD68C\uC758\uB85D: "minutes",
|
|
19886
|
+
gaejosik: "gaejosik",
|
|
19887
|
+
\uAC1C\uC870\uC2DD: "gaejosik",
|
|
19888
|
+
\uAC1C\uC870\uC2DD\uBCF4\uACE0\uC11C: "gaejosik",
|
|
19889
|
+
\uC815\uBD80\uBCF4\uACE0\uC11C: "gaejosik",
|
|
19890
|
+
\uC815\uBD80\uD45C\uC900\uAC1C\uC870\uC2DD\uBCF4\uACE0\uC11C: "gaejosik"
|
|
19765
19891
|
};
|
|
19766
19892
|
function normalizeGongmunPreset(preset) {
|
|
19767
19893
|
if (!preset) return "official";
|
|
@@ -19772,15 +19898,30 @@ function resolveGongmun(opts) {
|
|
|
19772
19898
|
const d = PRESET_DEFAULTS[preset];
|
|
19773
19899
|
const bodyPt = opts.bodyPt ?? d.bodyPt;
|
|
19774
19900
|
const autoFitMinRatio = opts.autoFit === false ? null : typeof opts.autoFit === "object" ? Math.min(Math.max(opts.autoFit.minRatio ?? 90, 50), 99) : 90;
|
|
19901
|
+
const coverOn = opts.cover !== void 0 ? opts.cover !== false : preset === "gaejosik";
|
|
19902
|
+
const coverOpts = typeof opts.cover === "object" ? opts.cover : {};
|
|
19903
|
+
const gaejosik = preset === "gaejosik";
|
|
19775
19904
|
return {
|
|
19776
19905
|
preset,
|
|
19777
19906
|
bodyFont: opts.bodyFont ?? "myeongjo",
|
|
19778
19907
|
bodyHeight: Math.round(bodyPt * 100),
|
|
19779
19908
|
lineSpacing: opts.lineSpacing ?? d.lineSpacing,
|
|
19780
19909
|
numbering: opts.numbering ?? d.numbering,
|
|
19781
|
-
margins: opts.margins ?? OFFICIAL_MARGINS,
|
|
19910
|
+
margins: opts.margins ?? (gaejosik ? GAEJOSIK_MARGINS : OFFICIAL_MARGINS),
|
|
19782
19911
|
centerTitle: opts.centerTitle ?? true,
|
|
19783
|
-
autoFitMinRatio
|
|
19912
|
+
autoFitMinRatio,
|
|
19913
|
+
cover: coverOn ? { date: coverOpts.date ?? null, org: coverOpts.org ?? "" } : null,
|
|
19914
|
+
toc: opts.toc ?? gaejosik,
|
|
19915
|
+
fonts: opts.fonts ?? {},
|
|
19916
|
+
sizes: opts.sizes ?? {},
|
|
19917
|
+
// 쪽번호 — 보고서 계열 관행(실측: 2_보고서 양식·추진계획·공고문 전부 하단 중앙)
|
|
19918
|
+
pageNumbers: opts.pageNumbers ?? (gaejosik || preset === "report" || preset === "plan"),
|
|
19919
|
+
headerFooter: gaejosik ? GAEJOSIK_HEADER_FOOTER : 0,
|
|
19920
|
+
// "끝." — 기안문 규정(본문 끝 2타+"끝."). 그 외는 opt-in
|
|
19921
|
+
endMark: opts.endMark ?? preset === "official",
|
|
19922
|
+
approval: opts.approval && opts.approval.length > 0 ? opts.approval : null,
|
|
19923
|
+
// 본문 제목박스 — 실측(GT3·GT12): 목차 뒤 본문 시작에 제목 반복. 표지 켜진 개조식 기본
|
|
19924
|
+
bodyTitleBox: opts.bodyTitleBox ?? (gaejosik && coverOn)
|
|
19784
19925
|
};
|
|
19785
19926
|
}
|
|
19786
19927
|
var HANGUL_INITIALS = [0, 2, 3, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18];
|
|
@@ -19828,7 +19969,8 @@ function markerWidth(marker, bodyHeight) {
|
|
|
19828
19969
|
for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
|
|
19829
19970
|
return Math.round(em / 1e3 * bodyHeight);
|
|
19830
19971
|
}
|
|
19831
|
-
function levelIndent(depth, bodyHeight, numbering) {
|
|
19972
|
+
function levelIndent(depth, bodyHeight, numbering, sizes = {}) {
|
|
19973
|
+
if (numbering === "gaejosik") return gaejosikLevelIndent(depth, bodyHeight, sizes);
|
|
19832
19974
|
const marker = numbering === "report" ? reportMarker(depth) : standardMarker(depth, 0);
|
|
19833
19975
|
return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, bodyHeight) };
|
|
19834
19976
|
}
|
|
@@ -19856,6 +19998,7 @@ var GongmunNumberer = class {
|
|
|
19856
19998
|
const n = this.counts[depth] ?? 0;
|
|
19857
19999
|
this.counts[depth] = n + 1;
|
|
19858
20000
|
if (suppress) return "";
|
|
20001
|
+
if (this.numbering === "gaejosik") return gaejosikMarker(depth);
|
|
19859
20002
|
return this.numbering === "report" ? reportMarker(depth) : standardMarker(depth, n);
|
|
19860
20003
|
}
|
|
19861
20004
|
reset() {
|
|
@@ -19923,27 +20066,28 @@ function headingCharPrId(level) {
|
|
|
19923
20066
|
if (level === 3) return CHAR_H3;
|
|
19924
20067
|
return CHAR_H4;
|
|
19925
20068
|
}
|
|
19926
|
-
function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100) {
|
|
20069
|
+
function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100, keepFontOnBold = false) {
|
|
19927
20070
|
const boldAttr = bold ? ` bold="1"` : "";
|
|
19928
20071
|
const italicAttr = italic ? ` italic="1"` : "";
|
|
19929
|
-
const effFont = bold ? 2 : fontId;
|
|
20072
|
+
const effFont = bold && !keepFontOnBold ? 2 : fontId;
|
|
20073
|
+
const boldEl = bold ? `<hh:bold/>` : "";
|
|
19930
20074
|
return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
19931
20075
|
<hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
|
|
19932
20076
|
<hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
|
|
19933
20077
|
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
19934
20078
|
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
19935
|
-
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"
|
|
20079
|
+
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>${boldEl}
|
|
19936
20080
|
</hh:charPr>`;
|
|
19937
20081
|
}
|
|
19938
20082
|
function paraPr(id, opts = {}) {
|
|
19939
|
-
const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, keepWord = false, outlineLevel } = opts;
|
|
19940
|
-
const breakNonLatin = keepWord ? "
|
|
20083
|
+
const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, keepWord = false, keepWithNext = false, outlineLevel } = opts;
|
|
20084
|
+
const breakNonLatin = keepWord ? "BREAK_WORD" : "KEEP_WORD";
|
|
19941
20085
|
const snapGrid = keepWord ? "0" : "1";
|
|
19942
20086
|
const heading = outlineLevel !== void 0 ? `<hh:heading type="OUTLINE" idRef="0" level="${outlineLevel}"/>` : `<hh:heading type="NONE" idRef="0" level="0"/>`;
|
|
19943
20087
|
return ` <hh:paraPr id="${id}" tabPrIDRef="0" condense="0" fontLineHeight="0" snapToGrid="${snapGrid}" suppressLineNumbers="0" checked="0" textDir="AUTO">
|
|
19944
20088
|
<hh:align horizontal="${align}" vertical="BASELINE"/>
|
|
19945
20089
|
${heading}
|
|
19946
|
-
<hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="0" keepWithNext="0" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
|
|
20090
|
+
<hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="0" keepWithNext="${keepWithNext ? 1 : 0}" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
|
|
19947
20091
|
<hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
|
|
19948
20092
|
<hh:margin><hc:intent value="${indent}" unit="HWPUNIT"/><hc:left value="${left}" unit="HWPUNIT"/><hc:right value="0" unit="HWPUNIT"/><hc:prev value="${spaceBefore}" unit="HWPUNIT"/><hc:next value="${spaceAfter}" unit="HWPUNIT"/></hh:margin>
|
|
19949
20093
|
<hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
|
|
@@ -19953,7 +20097,72 @@ function paraPr(id, opts = {}) {
|
|
|
19953
20097
|
var GONGMUN_LIST_BASE = 8;
|
|
19954
20098
|
var GONGMUN_LIST_LEVELS = 8;
|
|
19955
20099
|
var GONGMUN_CENTER = GONGMUN_LIST_BASE + GONGMUN_LIST_LEVELS;
|
|
20100
|
+
var GONGMUN_RIGHT = GONGMUN_CENTER + 1;
|
|
20101
|
+
var GONGMUN_TBL_CENTER = GONGMUN_RIGHT + 1;
|
|
20102
|
+
var GONGMUN_TBL_LEFT = GONGMUN_TBL_CENTER + 1;
|
|
20103
|
+
var GJ_CHAR_DAE = 11;
|
|
20104
|
+
var GJ_CHAR_DAE_BOLD = 12;
|
|
20105
|
+
var GJ_CHAR_CHAM = 13;
|
|
20106
|
+
var GJ_CHAR_CHAM_BOLD = 14;
|
|
20107
|
+
var GJ_CHAR_CHAPTER_NUM = 15;
|
|
20108
|
+
var GJ_CHAR_CHAPTER_TITLE = 16;
|
|
20109
|
+
var GJ_CHAR_COVER_TITLE = 17;
|
|
20110
|
+
var GJ_CHAR_COVER_SUB = 18;
|
|
20111
|
+
var GJ_CHAR_TOC_LABEL = 19;
|
|
20112
|
+
var GJ_CHAR_TOC_ROMAN = 20;
|
|
20113
|
+
var GJ_CHAR_TOC_ITEM = 21;
|
|
20114
|
+
var GJ_CHAR_TABLE = 22;
|
|
20115
|
+
var GJ_CHAR_TABLE_BOLD = 23;
|
|
20116
|
+
var GJ_CHAR_BAR = 24;
|
|
20117
|
+
var GJ_CHAR_BODY_TITLE = 25;
|
|
20118
|
+
var GJ_CHAR_COUNT = 15;
|
|
20119
|
+
var GJ_PARA_CHAM = 20;
|
|
20120
|
+
var GJ_PARA_COVER = 21;
|
|
20121
|
+
var GJ_PARA_TOC_ITEM = 22;
|
|
20122
|
+
var GJ_PARA_CHAPTER = 23;
|
|
20123
|
+
var GJ_PARA_BAR = 24;
|
|
20124
|
+
var GJ_BF_CHAPTER_NUM = 3;
|
|
20125
|
+
var GJ_BF_CHAPTER_GAP = 4;
|
|
20126
|
+
var GJ_BF_CHAPTER_TITLE = 5;
|
|
20127
|
+
var GJ_BF_BAR_DARK = 6;
|
|
20128
|
+
var GJ_BF_BAR_LIGHT = 7;
|
|
20129
|
+
var GJ_BF_TOC_BOX = 8;
|
|
20130
|
+
var GJ_BF_TOC_STRIPE = 9;
|
|
20131
|
+
function gongmunTableHeaderBf(gaejosik) {
|
|
20132
|
+
return gaejosik ? 10 : 3;
|
|
20133
|
+
}
|
|
20134
|
+
function borderFillEntry(id, b, fill) {
|
|
20135
|
+
const side = (name, v) => v ? ` <hh:${name} type="${v[2] ?? "SOLID"}" width="${v[0]}" color="${v[1]}"/>` : ` <hh:${name} type="NONE" width="0.1 mm" color="#000000"/>`;
|
|
20136
|
+
let brush = "";
|
|
20137
|
+
if (typeof fill === "string") {
|
|
20138
|
+
brush = `
|
|
20139
|
+
<hc:fillBrush><hc:winBrush faceColor="${fill}" hatchColor="#000000" alpha="0"/></hc:fillBrush>`;
|
|
20140
|
+
} else if (fill) {
|
|
20141
|
+
brush = `
|
|
20142
|
+
<hc:fillBrush><hc:gradation type="RADIAL" angle="0" centerX="0" centerY="0" step="50" colorNum="2" stepCenter="50" alpha="0"><hc:color value="${fill.gradient[0]}"/><hc:color value="${fill.gradient[1]}"/></hc:gradation></hc:fillBrush>`;
|
|
20143
|
+
}
|
|
20144
|
+
return ` <hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
20145
|
+
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
20146
|
+
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
20147
|
+
${side("leftBorder", b.l)}
|
|
20148
|
+
${side("rightBorder", b.r)}
|
|
20149
|
+
${side("topBorder", b.t)}
|
|
20150
|
+
${side("bottomBorder", b.b)}${brush}
|
|
20151
|
+
</hh:borderFill>`;
|
|
20152
|
+
}
|
|
20153
|
+
function pageNumCtrl() {
|
|
20154
|
+
return `<hp:ctrl><hp:pageNum pos="BOTTOM_CENTER" formatType="DIGIT" sideChar="-"/></hp:ctrl>`;
|
|
20155
|
+
}
|
|
20156
|
+
function newPageNumCtrl(num2 = 1) {
|
|
20157
|
+
return `<hp:ctrl><hp:newNum num="${num2}" numType="PAGE"/></hp:ctrl>`;
|
|
20158
|
+
}
|
|
20159
|
+
function pageHidingCtrl(hideHeader = false) {
|
|
20160
|
+
return `<hp:ctrl><hp:pageHiding hideHeader="${hideHeader ? 1 : 0}" hideFooter="0" hideMasterPage="0" hideBorder="0" hideFill="0" hidePageNum="1"/></hp:ctrl>`;
|
|
20161
|
+
}
|
|
19956
20162
|
var CHAR_VARIANT_BASE = 11;
|
|
20163
|
+
function charVariantBase(gaejosik) {
|
|
20164
|
+
return gaejosik ? CHAR_VARIANT_BASE + GJ_CHAR_COUNT : CHAR_VARIANT_BASE;
|
|
20165
|
+
}
|
|
19957
20166
|
var GONGMUN_BODY_RATIO = 95;
|
|
19958
20167
|
|
|
19959
20168
|
// src/hwpx/md-runs.ts
|
|
@@ -20167,12 +20376,12 @@ function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
|
|
|
20167
20376
|
return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
|
|
20168
20377
|
}).join("");
|
|
20169
20378
|
}
|
|
20170
|
-
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId) {
|
|
20379
|
+
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId, styleId = 0) {
|
|
20171
20380
|
if (paraPrId === PARA_CODE) {
|
|
20172
20381
|
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
|
|
20173
20382
|
}
|
|
20174
20383
|
const runs = generateRuns(text, charPrId, mapCharId);
|
|
20175
|
-
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="
|
|
20384
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="${styleId}">${runs}</hp:p>`;
|
|
20176
20385
|
}
|
|
20177
20386
|
|
|
20178
20387
|
// src/hwpx/gen-header.ts
|
|
@@ -20200,6 +20409,7 @@ function generateManifest(chartParts = []) {
|
|
|
20200
20409
|
</opf:package>`;
|
|
20201
20410
|
}
|
|
20202
20411
|
function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls = []) {
|
|
20412
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
20203
20413
|
let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
|
|
20204
20414
|
if (gongmun) {
|
|
20205
20415
|
body = gongmun.bodyHeight;
|
|
@@ -20209,26 +20419,62 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
|
|
|
20209
20419
|
h3 = body;
|
|
20210
20420
|
h4 = Math.max(body - 100, 1300);
|
|
20211
20421
|
}
|
|
20422
|
+
const bodyFont = gaejosik ? 4 : 0;
|
|
20212
20423
|
const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
|
|
20213
20424
|
const rows = [
|
|
20214
|
-
charPr(0, body, false, false,
|
|
20215
|
-
charPr(1, body, true, false,
|
|
20216
|
-
charPr(2, body, false, true,
|
|
20217
|
-
charPr(3, body, true, true,
|
|
20425
|
+
charPr(0, body, false, false, bodyFont, theme.body, bodyRatio),
|
|
20426
|
+
charPr(1, body, true, false, bodyFont, theme.body, bodyRatio),
|
|
20427
|
+
charPr(2, body, false, true, bodyFont, theme.body, bodyRatio),
|
|
20428
|
+
charPr(3, body, true, true, bodyFont, theme.body, bodyRatio),
|
|
20218
20429
|
charPr(4, code, false, false, 1),
|
|
20219
20430
|
charPr(5, h1, true, false, 1, theme.h1),
|
|
20220
20431
|
charPr(6, h2, true, false, 1, theme.h2),
|
|
20221
20432
|
charPr(7, h3, true, false, 1, theme.h3),
|
|
20222
20433
|
charPr(8, h4, true, false, 1, theme.h4),
|
|
20223
|
-
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false,
|
|
20224
|
-
charPr(CHAR_QUOTE, body, false, true,
|
|
20434
|
+
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, bodyFont, theme.tableHeader),
|
|
20435
|
+
charPr(CHAR_QUOTE, body, false, true, bodyFont, theme.quote)
|
|
20225
20436
|
];
|
|
20437
|
+
if (gaejosik) {
|
|
20438
|
+
const sz = gaejosikSizes(body, gongmun.sizes);
|
|
20439
|
+
rows.push(
|
|
20440
|
+
charPr(11, sz.dae, false, false, 3),
|
|
20441
|
+
// □ HY헤드라인M
|
|
20442
|
+
charPr(12, sz.dae, true, false, 3, "#000000", 100, true),
|
|
20443
|
+
// □ bold
|
|
20444
|
+
charPr(13, sz.cham, false, false, 5),
|
|
20445
|
+
// ※ 한양중고딕
|
|
20446
|
+
charPr(14, sz.cham, true, false, 5, "#000000", 100, true),
|
|
20447
|
+
// ※ bold
|
|
20448
|
+
charPr(15, sz.chapter, true, false, 4, "#FFFFFF", 100, true),
|
|
20449
|
+
// 장 로마숫자(흰)
|
|
20450
|
+
charPr(16, sz.chapter, false, false, 3),
|
|
20451
|
+
// 장 제목
|
|
20452
|
+
charPr(17, sz.coverTitle, false, false, 3),
|
|
20453
|
+
// 표지 제목
|
|
20454
|
+
charPr(18, sz.coverSub, false, false, 3),
|
|
20455
|
+
// 표지 날짜·기관명
|
|
20456
|
+
charPr(19, sz.tocLabel, true, false, 3, "#000000", 100, true),
|
|
20457
|
+
// 목 차
|
|
20458
|
+
charPr(20, sz.tocRoman, true, false, 6, "#000000", 100, true),
|
|
20459
|
+
// 목차 로마숫자(한양신명조)
|
|
20460
|
+
charPr(21, sz.tocItem, false, false, 3),
|
|
20461
|
+
// 목차 항목
|
|
20462
|
+
charPr(22, sz.table, false, false, 7),
|
|
20463
|
+
// 표 셀(맑은 고딕 12pt)
|
|
20464
|
+
charPr(23, sz.table, true, false, 7, "#000000", 100, true),
|
|
20465
|
+
// 표 셀 bold
|
|
20466
|
+
charPr(24, sz.bar, false, false, 4),
|
|
20467
|
+
// 표지 바 셀 빈 문단(6pt)
|
|
20468
|
+
charPr(25, sz.bodyTitle, false, false, 3)
|
|
20469
|
+
// 본문 제목박스(HY헤드라인M 22pt, 실측 GT3 표④)
|
|
20470
|
+
);
|
|
20471
|
+
}
|
|
20226
20472
|
for (const r of ratioVariants) {
|
|
20227
20473
|
rows.push(
|
|
20228
|
-
charPr(rows.length, body, false, false,
|
|
20229
|
-
charPr(rows.length + 1, body, true, false,
|
|
20230
|
-
charPr(rows.length + 2, body, false, true,
|
|
20231
|
-
charPr(rows.length + 3, body, true, true,
|
|
20474
|
+
charPr(rows.length, body, false, false, bodyFont, theme.body, r),
|
|
20475
|
+
charPr(rows.length + 1, body, true, false, bodyFont, theme.body, r),
|
|
20476
|
+
charPr(rows.length + 2, body, false, true, bodyFont, theme.body, r),
|
|
20477
|
+
charPr(rows.length + 3, body, true, true, bodyFont, theme.body, r)
|
|
20232
20478
|
);
|
|
20233
20479
|
}
|
|
20234
20480
|
rows.push(...extraCharPrXmls);
|
|
@@ -20239,14 +20485,14 @@ ${rows.join("\n")}
|
|
|
20239
20485
|
function buildParaProperties(gongmun) {
|
|
20240
20486
|
if (!gongmun) {
|
|
20241
20487
|
const base2 = [
|
|
20242
|
-
paraPr(0),
|
|
20243
|
-
paraPr(1, { align: "LEFT", spaceBefore: 800, spaceAfter: 200, lineSpacing: 180, outlineLevel: 0 }),
|
|
20244
|
-
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: 170, outlineLevel: 1 }),
|
|
20245
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: 160, outlineLevel: 2 }),
|
|
20246
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160, outlineLevel: 3 }),
|
|
20247
|
-
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400 }),
|
|
20248
|
-
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600 }),
|
|
20249
|
-
paraPr(7, { align: "LEFT", lineSpacing: 160, indent: 600 })
|
|
20488
|
+
paraPr(0, { keepWord: true }),
|
|
20489
|
+
paraPr(1, { align: "LEFT", spaceBefore: 800, spaceAfter: 200, lineSpacing: 180, outlineLevel: 0, keepWord: true }),
|
|
20490
|
+
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: 170, outlineLevel: 1, keepWord: true }),
|
|
20491
|
+
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: 160, outlineLevel: 2, keepWord: true }),
|
|
20492
|
+
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160, outlineLevel: 3, keepWord: true }),
|
|
20493
|
+
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
20494
|
+
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600, keepWord: true }),
|
|
20495
|
+
paraPr(7, { align: "LEFT", lineSpacing: 160, indent: 600, keepWord: true })
|
|
20250
20496
|
];
|
|
20251
20497
|
return `<hh:paraProperties itemCnt="${base2.length}">
|
|
20252
20498
|
${base2.join("\n")}
|
|
@@ -20256,20 +20502,37 @@ ${base2.join("\n")}
|
|
|
20256
20502
|
const titleAlign = gongmun.centerTitle ? "CENTER" : "LEFT";
|
|
20257
20503
|
const base = [
|
|
20258
20504
|
paraPr(0, { lineSpacing: ls, keepWord: true }),
|
|
20259
|
-
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true
|
|
20260
|
-
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: ls, keepWord: true
|
|
20261
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true
|
|
20262
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true
|
|
20505
|
+
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true }),
|
|
20506
|
+
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: ls, keepWord: true }),
|
|
20507
|
+
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
20508
|
+
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
20263
20509
|
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
20264
20510
|
paraPr(6, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true }),
|
|
20265
20511
|
paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
|
|
20266
20512
|
];
|
|
20267
20513
|
for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
|
|
20268
|
-
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering);
|
|
20269
|
-
const sectionGap = gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
20270
|
-
|
|
20514
|
+
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes);
|
|
20515
|
+
const sectionGap = gongmun.numbering === "gaejosik" ? gaejosikSpaceBefore(d, gongmun.bodyHeight) : gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
20516
|
+
const keepNext = gongmun.numbering === "gaejosik" && d === 0;
|
|
20517
|
+
base.push(paraPr(GONGMUN_LIST_BASE + d, { align: "JUSTIFY", lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext }));
|
|
20271
20518
|
}
|
|
20272
20519
|
base.push(paraPr(GONGMUN_CENTER, { align: "CENTER", lineSpacing: ls, keepWord: true }));
|
|
20520
|
+
base.push(paraPr(GONGMUN_RIGHT, { align: "RIGHT", lineSpacing: ls, keepWord: true }));
|
|
20521
|
+
base.push(paraPr(GONGMUN_TBL_CENTER, { align: "CENTER", lineSpacing: 130, keepWord: true }));
|
|
20522
|
+
base.push(paraPr(GONGMUN_TBL_LEFT, { align: "LEFT", lineSpacing: 130, keepWord: true }));
|
|
20523
|
+
if (gongmun.preset === "gaejosik") {
|
|
20524
|
+
const cham = gaejosikChamIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
20525
|
+
const toc = gaejosikTocItemIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
20526
|
+
base.push(
|
|
20527
|
+
paraPr(GJ_PARA_CHAM, { align: "JUSTIFY", lineSpacing: ls, left: cham.left, indent: cham.indent, spaceBefore: gaejosikSpaceBefore(3, gongmun.bodyHeight), keepWord: true }),
|
|
20528
|
+
paraPr(GJ_PARA_COVER, { align: "CENTER", lineSpacing: 130, keepWord: true }),
|
|
20529
|
+
paraPr(GJ_PARA_TOC_ITEM, { align: "LEFT", lineSpacing: 160, left: toc.left, indent: toc.indent, spaceBefore: 1800, keepWord: true }),
|
|
20530
|
+
// 장 헤더는 다음 문단과 같은 쪽에 — 쪽 하단 고아 헤더 방지 (실렌더 확인 이슈)
|
|
20531
|
+
paraPr(GJ_PARA_CHAPTER, { align: "LEFT", lineSpacing: ls, spaceBefore: 2400, spaceAfter: 600, keepWord: true, keepWithNext: true }),
|
|
20532
|
+
// 표지 장식 바 셀 빈 문단 — 저줄간격(실측 71%)으로 바 높이 818 안에 수납
|
|
20533
|
+
paraPr(GJ_PARA_BAR, { align: "CENTER", lineSpacing: 70, keepWord: true })
|
|
20534
|
+
);
|
|
20535
|
+
}
|
|
20273
20536
|
return `<hh:paraProperties itemCnt="${base.length}">
|
|
20274
20537
|
${base.join("\n")}
|
|
20275
20538
|
</hh:paraProperties>`;
|
|
@@ -20285,25 +20548,37 @@ ${heads}
|
|
|
20285
20548
|
</hh:numbering>
|
|
20286
20549
|
</hh:numberings>`;
|
|
20287
20550
|
}
|
|
20288
|
-
function
|
|
20289
|
-
|
|
20290
|
-
|
|
20291
|
-
|
|
20292
|
-
|
|
20293
|
-
|
|
20294
|
-
|
|
20295
|
-
|
|
20296
|
-
|
|
20551
|
+
function fontEntry(id, face, weight = 6) {
|
|
20552
|
+
return ` <hh:font id="${id}" face="${face}" type="TTF" isEmbedded="0">
|
|
20553
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="${weight}" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20554
|
+
</hh:font>`;
|
|
20555
|
+
}
|
|
20556
|
+
function buildFontFaces(gongmun, bodyFace) {
|
|
20557
|
+
if (gongmun?.preset === "gaejosik") {
|
|
20558
|
+
const ov = gongmun.fonts;
|
|
20559
|
+
const faces = [
|
|
20560
|
+
"\uD568\uCD08\uB86C\uBC14\uD0D5",
|
|
20561
|
+
"\uD568\uCD08\uB86C\uB3CB\uC6C0",
|
|
20562
|
+
"HY\uACAC\uACE0\uB515",
|
|
20563
|
+
ov.heading ?? "HY\uD5E4\uB4DC\uB77C\uC778M",
|
|
20564
|
+
ov.body ?? "\uD734\uBA3C\uBA85\uC870",
|
|
20565
|
+
ov.ref ?? "\uD55C\uC591\uC911\uACE0\uB515",
|
|
20566
|
+
"\uD55C\uC591\uC2E0\uBA85\uC870",
|
|
20567
|
+
ov.table ?? "\uB9D1\uC740 \uACE0\uB515"
|
|
20568
|
+
];
|
|
20569
|
+
const list = faces.map((f, i) => fontEntry(i, f, i === 2 || i === 3 ? 9 : 6)).join("\n");
|
|
20570
|
+
const langs = ["HANGUL", "LATIN", "HANJA", "JAPANESE", "OTHER", "SYMBOL", "USER"];
|
|
20571
|
+
return `<hh:fontfaces itemCnt="${langs.length}">
|
|
20572
|
+
` + langs.map((l) => ` <hh:fontface lang="${l}" fontCnt="${faces.length}">
|
|
20573
|
+
${list}
|
|
20574
|
+
</hh:fontface>`).join("\n") + `
|
|
20575
|
+
</hh:fontfaces>`;
|
|
20576
|
+
}
|
|
20577
|
+
return `<hh:fontfaces itemCnt="7">
|
|
20297
20578
|
<hh:fontface lang="HANGUL" fontCnt="3">
|
|
20298
|
-
|
|
20299
|
-
|
|
20300
|
-
|
|
20301
|
-
<hh:font id="1" face="\uD568\uCD08\uB86C\uB3CB\uC6C0" type="TTF" isEmbedded="0">
|
|
20302
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20303
|
-
</hh:font>
|
|
20304
|
-
<hh:font id="2" face="HY\uACAC\uACE0\uB515" type="TTF" isEmbedded="0">
|
|
20305
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="9" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20306
|
-
</hh:font>
|
|
20579
|
+
${fontEntry(0, bodyFace)}
|
|
20580
|
+
${fontEntry(1, "\uD568\uCD08\uB86C\uB3CB\uC6C0")}
|
|
20581
|
+
${fontEntry(2, "HY\uACAC\uACE0\uB515", 9)}
|
|
20307
20582
|
</hh:fontface>
|
|
20308
20583
|
<hh:fontface lang="LATIN" fontCnt="3">
|
|
20309
20584
|
<hh:font id="0" face="Times New Roman" type="TTF" isEmbedded="0">
|
|
@@ -20317,57 +20592,87 @@ function generateHeaderXml(theme, gongmun, ratioVariants = [], remap = null) {
|
|
|
20317
20592
|
</hh:font>
|
|
20318
20593
|
</hh:fontface>
|
|
20319
20594
|
<hh:fontface lang="HANJA" fontCnt="1">
|
|
20320
|
-
|
|
20321
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20322
|
-
</hh:font>
|
|
20595
|
+
${fontEntry(0, "\uD568\uCD08\uB86C\uBC14\uD0D5")}
|
|
20323
20596
|
</hh:fontface>
|
|
20324
20597
|
<hh:fontface lang="JAPANESE" fontCnt="1">
|
|
20325
|
-
|
|
20326
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20327
|
-
</hh:font>
|
|
20598
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
20328
20599
|
</hh:fontface>
|
|
20329
20600
|
<hh:fontface lang="OTHER" fontCnt="1">
|
|
20330
|
-
|
|
20331
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20332
|
-
</hh:font>
|
|
20601
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
20333
20602
|
</hh:fontface>
|
|
20334
20603
|
<hh:fontface lang="SYMBOL" fontCnt="1">
|
|
20335
|
-
|
|
20336
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20337
|
-
</hh:font>
|
|
20604
|
+
${fontEntry(0, "Symbol")}
|
|
20338
20605
|
</hh:fontface>
|
|
20339
20606
|
<hh:fontface lang="USER" fontCnt="1">
|
|
20340
|
-
|
|
20341
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20342
|
-
</hh:font>
|
|
20607
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
20343
20608
|
</hh:fontface>
|
|
20344
|
-
</hh:fontfaces
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20354
|
-
|
|
20355
|
-
|
|
20356
|
-
|
|
20357
|
-
|
|
20358
|
-
|
|
20359
|
-
|
|
20360
|
-
|
|
20361
|
-
|
|
20362
|
-
|
|
20609
|
+
</hh:fontfaces>`;
|
|
20610
|
+
}
|
|
20611
|
+
function buildBorderFills(gongmun, extra = []) {
|
|
20612
|
+
const thin = ["0.12 mm", "#000000"];
|
|
20613
|
+
const items = [
|
|
20614
|
+
borderFillEntry(1, {}),
|
|
20615
|
+
borderFillEntry(2, { l: thin, r: thin, t: thin, b: thin })
|
|
20616
|
+
];
|
|
20617
|
+
if (gongmun?.preset === "gaejosik") {
|
|
20618
|
+
const c = GAEJOSIK_COLORS;
|
|
20619
|
+
const edge = ["0.12 mm", c.border];
|
|
20620
|
+
const grayLine = ["0.1 mm", c.titleLine];
|
|
20621
|
+
const tocEdge = ["0.4 mm", c.tocBorder];
|
|
20622
|
+
items.push(
|
|
20623
|
+
borderFillEntry(3, { l: edge, r: edge, t: edge, b: edge }, c.primary),
|
|
20624
|
+
// 장 로마숫자 셀
|
|
20625
|
+
borderFillEntry(4, { l: edge }),
|
|
20626
|
+
// 장 간격 셀(좌선)
|
|
20627
|
+
borderFillEntry(5, { t: grayLine, b: grayLine }, c.titleFill),
|
|
20628
|
+
// 장 제목 셀
|
|
20629
|
+
borderFillEntry(6, {}, c.primary),
|
|
20630
|
+
// 표지 진한 바
|
|
20631
|
+
borderFillEntry(7, {}, c.accent),
|
|
20632
|
+
// 표지 연한 바
|
|
20633
|
+
borderFillEntry(8, { l: tocEdge, r: tocEdge, t: tocEdge, b: tocEdge }),
|
|
20634
|
+
// 목차 박스
|
|
20635
|
+
borderFillEntry(9, {}, c.tocStripe)
|
|
20636
|
+
// 목차 배너 라벤더 스트라이프
|
|
20637
|
+
);
|
|
20638
|
+
}
|
|
20639
|
+
if (gongmun) {
|
|
20640
|
+
items.push(borderFillEntry(items.length + 1, { l: thin, r: thin, t: thin, b: thin }, "#E6E6E6"));
|
|
20641
|
+
}
|
|
20642
|
+
items.push(...extra);
|
|
20643
|
+
return `<hh:borderFills itemCnt="${items.length}">
|
|
20644
|
+
${items.join("\n")}
|
|
20645
|
+
</hh:borderFills>`;
|
|
20646
|
+
}
|
|
20647
|
+
function buildStyles(gongmun) {
|
|
20648
|
+
const items = [
|
|
20649
|
+
`<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>`
|
|
20650
|
+
];
|
|
20651
|
+
if (gongmun) {
|
|
20652
|
+
for (let lvl = 1; lvl <= 4; lvl++) {
|
|
20653
|
+
items.push(`<hh:style id="${lvl}" type="PARA" name="\uAC1C\uC694 ${lvl}" engName="Outline ${lvl}" paraPrIDRef="${lvl}" charPrIDRef="${4 + lvl}" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>`);
|
|
20654
|
+
}
|
|
20655
|
+
}
|
|
20656
|
+
return `<hh:styles itemCnt="${items.length}">
|
|
20657
|
+
${items.join("\n ")}
|
|
20658
|
+
</hh:styles>`;
|
|
20659
|
+
}
|
|
20660
|
+
function generateHeaderXml(theme, gongmun, ratioVariants = [], extraBorderFills = [], extraCharPrXmls = []) {
|
|
20661
|
+
const bodyFace = gongmun?.fonts.body ?? (gongmun?.bodyFont === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5");
|
|
20662
|
+
const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants, extraCharPrXmls);
|
|
20663
|
+
const paraPropsXml = buildParaProperties(gongmun);
|
|
20664
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
|
20665
|
+
<hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" xmlns:hc="${NS_CORE}" version="1.4" secCnt="1">
|
|
20666
|
+
<hh:beginNum page="1" footnote="1" endnote="1" pic="1" tbl="1" equation="1"/>
|
|
20667
|
+
<hh:refList>
|
|
20668
|
+
${buildFontFaces(gongmun, bodyFace)}
|
|
20669
|
+
${buildBorderFills(gongmun, extraBorderFills)}
|
|
20363
20670
|
${charPropsXml}
|
|
20364
20671
|
<hh:tabProperties itemCnt="0"/>
|
|
20365
20672
|
${buildNumberings()}
|
|
20366
20673
|
<hh:bullets itemCnt="0"/>
|
|
20367
20674
|
${paraPropsXml}
|
|
20368
|
-
|
|
20369
|
-
<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>
|
|
20370
|
-
</hh:styles>
|
|
20675
|
+
${buildStyles(gongmun)}
|
|
20371
20676
|
</hh:refList>
|
|
20372
20677
|
<hh:compatibleDocument targetProgram="HWP2018"><hh:layoutCompatibility/></hh:compatibleDocument>
|
|
20373
20678
|
</hh:head>`;
|
|
@@ -20603,6 +20908,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
20603
20908
|
let contW;
|
|
20604
20909
|
if (block.type === "list_item" && gongmunList.has(i)) {
|
|
20605
20910
|
const { marker, depth } = gongmunList.get(i);
|
|
20911
|
+
if (gongmun.numbering === "gaejosik" && (depth === 0 || (block.text || "").trimStart().startsWith("\u203B"))) continue;
|
|
20606
20912
|
const content = plainRenderText(block.text || "");
|
|
20607
20913
|
text = marker ? `${marker} ${content}` : content;
|
|
20608
20914
|
const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
|
|
@@ -20611,6 +20917,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
20611
20917
|
} else if (block.type === "paragraph") {
|
|
20612
20918
|
const raw = (block.text || "").trim();
|
|
20613
20919
|
if (/^<center>[\s\S]*<\/center>$/i.test(raw)) continue;
|
|
20920
|
+
if (gongmun.numbering === "gaejosik" && raw.startsWith("\u203B")) continue;
|
|
20614
20921
|
text = plainRenderText(raw);
|
|
20615
20922
|
firstW = contW = pageW;
|
|
20616
20923
|
} else {
|
|
@@ -20624,14 +20931,15 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
20624
20931
|
}
|
|
20625
20932
|
return ratioByBlock.size > 0 ? { ratioByBlock, variants } : null;
|
|
20626
20933
|
}
|
|
20627
|
-
function variantMapper(fit, blockIdx) {
|
|
20934
|
+
function variantMapper(fit, blockIdx, base = CHAR_VARIANT_BASE) {
|
|
20628
20935
|
const r = fit.ratioByBlock.get(blockIdx);
|
|
20629
20936
|
if (r === void 0) return void 0;
|
|
20630
20937
|
const vi = fit.variants.indexOf(r);
|
|
20631
|
-
return (id) => id >= 0 && id <= 3 ?
|
|
20938
|
+
return (id) => id >= 0 && id <= 3 ? base + vi * 4 + id : id;
|
|
20632
20939
|
}
|
|
20633
20940
|
function precomputeGongmunList(blocks, gongmun) {
|
|
20634
20941
|
const result = /* @__PURE__ */ new Map();
|
|
20942
|
+
const depthOffset = gongmun.numbering === "gaejosik" && blocks.some((b) => b.type === "heading" && b.level === 3) ? 1 : 0;
|
|
20635
20943
|
let i = 0;
|
|
20636
20944
|
while (i < blocks.length) {
|
|
20637
20945
|
if (blocks[i].type !== "list_item") {
|
|
@@ -20657,7 +20965,7 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
20657
20965
|
}
|
|
20658
20966
|
break;
|
|
20659
20967
|
}
|
|
20660
|
-
const depths = run.map((bi) => Math.min(Math.max(blocks[bi].indent || 0, 0), GONGMUN_LIST_LEVELS - 1));
|
|
20968
|
+
const depths = run.map((bi) => Math.min(Math.max((blocks[bi].indent || 0) + depthOffset, 0), GONGMUN_LIST_LEVELS - 1));
|
|
20661
20969
|
const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
|
|
20662
20970
|
const numberer = new GongmunNumberer(gongmun.numbering);
|
|
20663
20971
|
run.forEach((bi, k) => {
|
|
@@ -20668,6 +20976,98 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
20668
20976
|
return result;
|
|
20669
20977
|
}
|
|
20670
20978
|
|
|
20979
|
+
// src/hwpx/gen-gaejosik.ts
|
|
20980
|
+
function chapterRoman(n) {
|
|
20981
|
+
if (n >= 1 && n <= 12) return String.fromCodePoint(8543 + n);
|
|
20982
|
+
const t = [[10, "\u2169"], [9, "\u2168"], [5, "\u2164"], [4, "\u2163"], [1, "\u2160"]];
|
|
20983
|
+
let s = "";
|
|
20984
|
+
for (const [v, r] of t) while (n >= v) {
|
|
20985
|
+
s += r;
|
|
20986
|
+
n -= v;
|
|
20987
|
+
}
|
|
20988
|
+
return s;
|
|
20989
|
+
}
|
|
20990
|
+
function emptyPara(paraPrId = PARA_NORMAL, pageBreak = false, charPrId = CHAR_NORMAL) {
|
|
20991
|
+
const brk = pageBreak ? ` pageBreak="1"` : "";
|
|
20992
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"${brk}><hp:run charPrIDRef="${charPrId}"><hp:t></hp:t></hp:run></hp:p>`;
|
|
20993
|
+
}
|
|
20994
|
+
var gjTableId = 92e5;
|
|
20995
|
+
function cell(opts) {
|
|
20996
|
+
const paras = opts.paras ?? emptyPara();
|
|
20997
|
+
return `<hp:tc name="" header="0" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${opts.bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="${opts.vertAlign ?? "CENTER"}" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${paras}</hp:subList><hp:cellAddr colAddr="${opts.col}" rowAddr="${opts.row ?? 0}"/><hp:cellSpan colSpan="${opts.colSpan ?? 1}" rowSpan="1"/><hp:cellSz width="${opts.w}" height="${opts.h}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
|
|
20998
|
+
}
|
|
20999
|
+
function table(rows, w, h, cols, tblBf = 1) {
|
|
21000
|
+
return `<hp:tbl id="${++gjTableId}" zOrder="0" numberingType="TABLE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" pageBreak="CELL" repeatHeader="0" rowCnt="${rows.length}" colCnt="${cols}" cellSpacing="0" borderFillIDRef="${tblBf}" noAdjust="1"><hp:sz width="${w}" widthRelTo="ABSOLUTE" height="${h}" 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="283" right="283" top="283" bottom="283"/><hp:inMargin left="141" right="141" top="141" bottom="141"/>` + rows.map((r) => `<hp:tr>${r}</hp:tr>`).join("") + `</hp:tbl>`;
|
|
21001
|
+
}
|
|
21002
|
+
function buildGaejosikCover(title, gongmun) {
|
|
21003
|
+
const g = coverGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
21004
|
+
const sz = gaejosikSizes(gongmun.bodyHeight, gongmun.sizes);
|
|
21005
|
+
const innerW = g.totalW - 282;
|
|
21006
|
+
const titleCharPr = simulateWrap(title, innerW, innerW, sz.coverTitle, 100, "keep").lines > 2 ? GJ_CHAR_COVER_SUB : GJ_CHAR_COVER_TITLE;
|
|
21007
|
+
const titlePara = `<hp:p paraPrIDRef="${GJ_PARA_COVER}" styleIDRef="0"><hp:run charPrIDRef="${titleCharPr}"><hp:t>${escapeXml(title)}</hp:t></hp:run></hp:p>`;
|
|
21008
|
+
const barEmpty = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
21009
|
+
const topRow = cell({ bf: GJ_BF_BAR_DARK, col: 0, colSpan: 2, row: 0, w: g.topDarkW, h: g.barH, paras: barEmpty }) + cell({ bf: GJ_BF_BAR_LIGHT, col: 2, row: 0, w: g.topLightW, h: g.barH, paras: barEmpty });
|
|
21010
|
+
const titleRow = cell({ bf: 1, col: 0, colSpan: 3, row: 1, w: g.totalW, h: g.titleH, paras: titlePara });
|
|
21011
|
+
const botRow = cell({ bf: GJ_BF_BAR_DARK, col: 0, row: 2, w: g.botDarkW, h: g.botBarH, paras: barEmpty }) + cell({ bf: GJ_BF_BAR_LIGHT, col: 1, colSpan: 2, row: 2, w: g.botLightW, h: g.botBarH, paras: barEmpty });
|
|
21012
|
+
const tbl2 = table([topRow, titleRow, botRow], g.totalW, g.barH + g.titleH + g.botBarH, 3);
|
|
21013
|
+
const host = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${tbl2}</hp:run></hp:p>`;
|
|
21014
|
+
const date = gongmun.cover?.date ?? formatGaejosikDate(/* @__PURE__ */ new Date());
|
|
21015
|
+
const org = gongmun.cover?.org ?? "";
|
|
21016
|
+
const sub = (t) => `<hp:p paraPrIDRef="${GJ_PARA_COVER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_COVER_SUB}"><hp:t>${escapeXml(t)}</hp:t></hp:run></hp:p>`;
|
|
21017
|
+
const subEmpty = emptyPara(GJ_PARA_COVER, false, GJ_CHAR_COVER_SUB);
|
|
21018
|
+
return [
|
|
21019
|
+
...Array(5).fill(emptyPara()),
|
|
21020
|
+
host,
|
|
21021
|
+
...Array(5).fill(emptyPara()),
|
|
21022
|
+
sub(date),
|
|
21023
|
+
...org ? [...Array(4).fill(subEmpty), sub(org)] : []
|
|
21024
|
+
];
|
|
21025
|
+
}
|
|
21026
|
+
function buildTocBanner(gongmun) {
|
|
21027
|
+
const g = tocBannerGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
21028
|
+
const bfs = [GJ_BF_BAR_DARK, 1, GJ_BF_TOC_STRIPE, 1, GJ_BF_TOC_STRIPE, 1, GJ_BF_BAR_DARK];
|
|
21029
|
+
const filler = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
21030
|
+
const label = `<hp:p paraPrIDRef="${GONGMUN_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_TOC_LABEL}"><hp:t>\uBAA9 \uCC28</hp:t></hp:run></hp:p>`;
|
|
21031
|
+
const row = g.colWs.map(
|
|
21032
|
+
(w, c) => cell({ bf: bfs[c], col: c, w, h: g.h, paras: c === 3 ? label : filler })
|
|
21033
|
+
).join("");
|
|
21034
|
+
const banner = table([row], g.colWs.reduce((a, b) => a + b, 0), g.h, 7, 2);
|
|
21035
|
+
return `<hp:p paraPrIDRef="${GJ_PARA_BAR}" styleIDRef="0" pageBreak="1"><hp:run charPrIDRef="${CHAR_NORMAL}">${banner}</hp:run></hp:p>`;
|
|
21036
|
+
}
|
|
21037
|
+
function buildGaejosikToc(chapters, gongmun) {
|
|
21038
|
+
const label = buildTocBanner(gongmun);
|
|
21039
|
+
const items = chapters.map(
|
|
21040
|
+
(title, i) => `<hp:p paraPrIDRef="${GJ_PARA_TOC_ITEM}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_TOC_ROMAN}"><hp:t>${chapterRoman(i + 1)}</hp:t></hp:run><hp:run charPrIDRef="${GJ_CHAR_TOC_ITEM}"><hp:t>. ${escapeXml(title)}</hp:t></hp:run></hp:p>`
|
|
21041
|
+
).join("");
|
|
21042
|
+
const box = table(
|
|
21043
|
+
[cell({ bf: GJ_BF_TOC_BOX, col: 0, w: TOC_GEOM.boxW, h: TOC_GEOM.boxH, paras: items })],
|
|
21044
|
+
TOC_GEOM.boxW,
|
|
21045
|
+
TOC_GEOM.boxH,
|
|
21046
|
+
1
|
|
21047
|
+
);
|
|
21048
|
+
const host = `<hp:p paraPrIDRef="${GJ_PARA_BAR}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${box}</hp:run></hp:p>`;
|
|
21049
|
+
return [label, emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR), host];
|
|
21050
|
+
}
|
|
21051
|
+
function buildGaejosikBodyTitle(title, gongmun) {
|
|
21052
|
+
const g = COVER_GEOM;
|
|
21053
|
+
const bt = bodyTitleGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
21054
|
+
const barEmpty = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
21055
|
+
const titlePara = `<hp:p paraPrIDRef="${GONGMUN_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_BODY_TITLE}"><hp:t>${escapeXml(title)}</hp:t></hp:run></hp:p>`;
|
|
21056
|
+
const topRow = cell({ bf: GJ_BF_BAR_DARK, col: 0, colSpan: 2, row: 0, w: g.topDarkW, h: bt.barH, paras: barEmpty }) + cell({ bf: GJ_BF_BAR_LIGHT, col: 2, row: 0, w: g.topLightW, h: bt.barH, paras: barEmpty });
|
|
21057
|
+
const titleRow = cell({ bf: 1, col: 0, colSpan: 3, row: 1, w: g.totalW, h: bt.titleH, paras: titlePara });
|
|
21058
|
+
const botRow = cell({ bf: GJ_BF_BAR_DARK, col: 0, row: 2, w: g.botDarkW, h: bt.barH, paras: barEmpty }) + cell({ bf: GJ_BF_BAR_LIGHT, col: 1, colSpan: 2, row: 2, w: g.botLightW, h: bt.barH, paras: barEmpty });
|
|
21059
|
+
const box = table([topRow, titleRow, botRow], g.totalW, bt.barH * 2 + bt.titleH, 3);
|
|
21060
|
+
return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${box}</hp:run></hp:p>`;
|
|
21061
|
+
}
|
|
21062
|
+
function buildGaejosikChapter(n, title, gongmun) {
|
|
21063
|
+
const g = gongmun ? chapterGeom(gongmun.bodyHeight, gongmun.sizes) : chapterGeom(1500);
|
|
21064
|
+
const numPara = `<hp:p paraPrIDRef="${GONGMUN_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_CHAPTER_NUM}"><hp:t>${chapterRoman(n)}</hp:t></hp:run></hp:p>`;
|
|
21065
|
+
const titlePara = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_CHAPTER_TITLE}"><hp:t> ${escapeXml(title)}</hp:t></hp:run></hp:p>`;
|
|
21066
|
+
const row = cell({ bf: GJ_BF_CHAPTER_NUM, col: 0, w: g.numW, h: g.rowH, paras: numPara }) + cell({ bf: GJ_BF_CHAPTER_GAP, col: 1, w: g.gapW, h: g.rowH }) + cell({ bf: GJ_BF_CHAPTER_TITLE, col: 2, w: g.titleW, h: g.rowH, paras: titlePara });
|
|
21067
|
+
const tbl2 = table([row], g.numW + g.gapW + g.titleW, g.rowH, 3);
|
|
21068
|
+
return `<hp:p paraPrIDRef="${GJ_PARA_CHAPTER}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${tbl2}</hp:run></hp:p>`;
|
|
21069
|
+
}
|
|
21070
|
+
|
|
20671
21071
|
// src/diff/text-diff.ts
|
|
20672
21072
|
function similarity(a, b) {
|
|
20673
21073
|
if (a === b) return 1;
|
|
@@ -20865,8 +21265,8 @@ function summarize(text) {
|
|
|
20865
21265
|
const t = text.replace(/\s+/g, " ").trim();
|
|
20866
21266
|
return t.length > 80 ? t.slice(0, 77) + "..." : t;
|
|
20867
21267
|
}
|
|
20868
|
-
function replicateGfmTable(
|
|
20869
|
-
const { cells, rows: numRows, cols: numCols } =
|
|
21268
|
+
function replicateGfmTable(table2) {
|
|
21269
|
+
const { cells, rows: numRows, cols: numCols } = table2;
|
|
20870
21270
|
if (numRows === 0 || numCols === 0) return null;
|
|
20871
21271
|
if (numRows === 1 && numCols === 1) return null;
|
|
20872
21272
|
if (numCols === 1) return null;
|
|
@@ -20875,28 +21275,28 @@ function replicateGfmTable(table) {
|
|
|
20875
21275
|
for (let r = 0; r < numRows; r++) {
|
|
20876
21276
|
for (let c = 0; c < numCols; c++) {
|
|
20877
21277
|
if (skip.has(`${r},${c}`)) continue;
|
|
20878
|
-
const
|
|
20879
|
-
if (!
|
|
21278
|
+
const cell2 = cells[r]?.[c];
|
|
21279
|
+
if (!cell2) continue;
|
|
20880
21280
|
display[r][c] = {
|
|
20881
|
-
text: escapeGfm(sanitizeText(
|
|
21281
|
+
text: escapeGfm(sanitizeText(cell2.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
|
|
20882
21282
|
gridR: r,
|
|
20883
21283
|
gridC: c
|
|
20884
21284
|
};
|
|
20885
|
-
for (let dr = 0; dr <
|
|
20886
|
-
for (let dc = 0; dc <
|
|
21285
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
21286
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
20887
21287
|
if (dr === 0 && dc === 0) continue;
|
|
20888
21288
|
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
20889
21289
|
}
|
|
20890
21290
|
}
|
|
20891
|
-
c +=
|
|
21291
|
+
c += cell2.colSpan - 1;
|
|
20892
21292
|
}
|
|
20893
21293
|
}
|
|
20894
21294
|
const uniqueRows = [];
|
|
20895
21295
|
let pendingLabelRow = null;
|
|
20896
21296
|
for (let r = 0; r < display.length; r++) {
|
|
20897
21297
|
const row = display[r];
|
|
20898
|
-
if (row.every((
|
|
20899
|
-
const nonEmptyCols = row.filter((
|
|
21298
|
+
if (row.every((cell2) => cell2.text === "")) continue;
|
|
21299
|
+
const nonEmptyCols = row.filter((cell2) => cell2.text !== "");
|
|
20900
21300
|
const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
|
|
20901
21301
|
if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
|
|
20902
21302
|
if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
|
|
@@ -20928,9 +21328,9 @@ function parseGfmTable(lines) {
|
|
|
20928
21328
|
function unescapeGfmCell(text) {
|
|
20929
21329
|
return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\([~*])/g, "$1");
|
|
20930
21330
|
}
|
|
20931
|
-
function replicateCellInnerHtml(
|
|
20932
|
-
if (
|
|
20933
|
-
return
|
|
21331
|
+
function replicateCellInnerHtml(cell2) {
|
|
21332
|
+
if (cell2.blocks?.length) {
|
|
21333
|
+
return cell2.blocks.map((b) => {
|
|
20934
21334
|
if (b.type === "table" && b.table) {
|
|
20935
21335
|
const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
|
|
20936
21336
|
return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
|
|
@@ -20940,27 +21340,27 @@ function replicateCellInnerHtml(cell) {
|
|
|
20940
21340
|
return t ? t.replace(/\n/g, "<br>") : "";
|
|
20941
21341
|
}).filter(Boolean).join("<br>");
|
|
20942
21342
|
}
|
|
20943
|
-
return sanitizeText(
|
|
21343
|
+
return sanitizeText(cell2.text).replace(/\n/g, "<br>");
|
|
20944
21344
|
}
|
|
20945
|
-
function replicateTableToHtml(
|
|
20946
|
-
const rows = replicateHtmlTable(
|
|
21345
|
+
function replicateTableToHtml(table2) {
|
|
21346
|
+
const rows = replicateHtmlTable(table2);
|
|
20947
21347
|
const lines = ["<table>"];
|
|
20948
21348
|
for (let r = 0; r < rows.length; r++) {
|
|
20949
21349
|
const tag = rows[r].tag;
|
|
20950
|
-
const rowHtml = rows[r].cells.map((
|
|
21350
|
+
const rowHtml = rows[r].cells.map((cell2) => {
|
|
20951
21351
|
const attrs = [];
|
|
20952
|
-
if (
|
|
20953
|
-
if (
|
|
21352
|
+
if (cell2.colSpan > 1) attrs.push(`colspan="${cell2.colSpan}"`);
|
|
21353
|
+
if (cell2.rowSpan > 1) attrs.push(`rowspan="${cell2.rowSpan}"`);
|
|
20954
21354
|
const attrStr = attrs.length ? " " + attrs.join(" ") : "";
|
|
20955
|
-
return `<${tag}${attrStr}>${
|
|
21355
|
+
return `<${tag}${attrStr}>${cell2.inner}</${tag}>`;
|
|
20956
21356
|
});
|
|
20957
21357
|
if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
|
|
20958
21358
|
}
|
|
20959
21359
|
lines.push("</table>");
|
|
20960
21360
|
return lines.join("\n");
|
|
20961
21361
|
}
|
|
20962
|
-
function replicateHtmlTable(
|
|
20963
|
-
const { cells, rows: numRows, cols: numCols } =
|
|
21362
|
+
function replicateHtmlTable(table2) {
|
|
21363
|
+
const { cells, rows: numRows, cols: numCols } = table2;
|
|
20964
21364
|
const skip = /* @__PURE__ */ new Set();
|
|
20965
21365
|
const result = [];
|
|
20966
21366
|
for (let r = 0; r < numRows; r++) {
|
|
@@ -20968,18 +21368,18 @@ function replicateHtmlTable(table) {
|
|
|
20968
21368
|
const rowCells = [];
|
|
20969
21369
|
for (let c = 0; c < numCols; c++) {
|
|
20970
21370
|
if (skip.has(`${r},${c}`)) continue;
|
|
20971
|
-
const
|
|
20972
|
-
if (!
|
|
20973
|
-
for (let dr = 0; dr <
|
|
20974
|
-
for (let dc = 0; dc <
|
|
21371
|
+
const cell2 = cells[r]?.[c];
|
|
21372
|
+
if (!cell2) continue;
|
|
21373
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
21374
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
20975
21375
|
if (dr === 0 && dc === 0) continue;
|
|
20976
21376
|
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
20977
21377
|
}
|
|
20978
21378
|
}
|
|
20979
21379
|
rowCells.push({
|
|
20980
|
-
inner: replicateCellInnerHtml(
|
|
20981
|
-
colSpan:
|
|
20982
|
-
rowSpan:
|
|
21380
|
+
inner: replicateCellInnerHtml(cell2),
|
|
21381
|
+
colSpan: cell2.colSpan,
|
|
21382
|
+
rowSpan: cell2.rowSpan,
|
|
20983
21383
|
gridR: r,
|
|
20984
21384
|
gridC: c
|
|
20985
21385
|
});
|
|
@@ -21084,6 +21484,54 @@ function removeNestedTables(html) {
|
|
|
21084
21484
|
return result;
|
|
21085
21485
|
}
|
|
21086
21486
|
|
|
21487
|
+
// src/hwpx/gen-table-bf.ts
|
|
21488
|
+
var THIN = ["0.12 mm", "#000000"];
|
|
21489
|
+
var THICK = ["0.4 mm", "#000000"];
|
|
21490
|
+
var DOUBLE = ["0.5 mm", "#000000", "DOUBLE_SLIM"];
|
|
21491
|
+
var EDGE = { thin: THIN, thick: THICK, double: DOUBLE };
|
|
21492
|
+
function sideOf(kind) {
|
|
21493
|
+
return kind === "none" ? void 0 : EDGE[kind];
|
|
21494
|
+
}
|
|
21495
|
+
var TableBfRegistry = class {
|
|
21496
|
+
constructor(nextId) {
|
|
21497
|
+
this.nextId = nextId;
|
|
21498
|
+
}
|
|
21499
|
+
map = /* @__PURE__ */ new Map();
|
|
21500
|
+
xmls = [];
|
|
21501
|
+
get(spec) {
|
|
21502
|
+
const key = `${spec.t}|${spec.b}|${spec.l}|${spec.r}|${typeof spec.fill === "string" ? spec.fill : spec.fill ? spec.fill.gradient.join("-") : ""}`;
|
|
21503
|
+
const hit = this.map.get(key);
|
|
21504
|
+
if (hit !== void 0) return hit;
|
|
21505
|
+
const id = this.nextId++;
|
|
21506
|
+
this.map.set(key, id);
|
|
21507
|
+
this.xmls.push(
|
|
21508
|
+
borderFillEntry(id, { t: sideOf(spec.t), b: sideOf(spec.b), l: sideOf(spec.l), r: sideOf(spec.r) }, spec.fill)
|
|
21509
|
+
);
|
|
21510
|
+
return id;
|
|
21511
|
+
}
|
|
21512
|
+
/** 등록된 borderFill XML 목록 (등록 순서 = id 순서) */
|
|
21513
|
+
emit() {
|
|
21514
|
+
return this.xmls;
|
|
21515
|
+
}
|
|
21516
|
+
get count() {
|
|
21517
|
+
return this.xmls.length;
|
|
21518
|
+
}
|
|
21519
|
+
};
|
|
21520
|
+
function dataCellSpec(opts) {
|
|
21521
|
+
const { row, rowEnd, col, colEnd, rowCnt, colCnt, headerRows, fill } = opts;
|
|
21522
|
+
const isTop = row === 0;
|
|
21523
|
+
const isBottom = rowEnd === rowCnt - 1;
|
|
21524
|
+
const isHeaderBottom = headerRows > 0 && rowEnd === headerRows - 1;
|
|
21525
|
+
const isBelowHeader = headerRows > 0 && row === headerRows;
|
|
21526
|
+
return {
|
|
21527
|
+
t: isTop ? "thick" : isBelowHeader ? "double" : "thin",
|
|
21528
|
+
b: isBottom ? "thick" : isHeaderBottom ? "double" : "thin",
|
|
21529
|
+
l: col === 0 ? "thick" : "thin",
|
|
21530
|
+
r: colEnd === colCnt - 1 ? "thick" : "thin",
|
|
21531
|
+
fill
|
|
21532
|
+
};
|
|
21533
|
+
}
|
|
21534
|
+
|
|
21087
21535
|
// src/hwpx/gen-profile.ts
|
|
21088
21536
|
function normalizeAnchor(s) {
|
|
21089
21537
|
return s.toLowerCase().replace(/[^\p{L}\p{N}]/gu, "").slice(0, 24);
|
|
@@ -21175,24 +21623,21 @@ function buildProfileRemap(profile, charPrBase, borderFillBase = 3) {
|
|
|
21175
21623
|
cellChar: /* @__PURE__ */ new Map(),
|
|
21176
21624
|
cellH: /* @__PURE__ */ new Map()
|
|
21177
21625
|
};
|
|
21178
|
-
for (const
|
|
21179
|
-
const k = `${
|
|
21180
|
-
if (
|
|
21181
|
-
tr.cellBf.set(k, localBf[
|
|
21626
|
+
for (const cell2 of t.cells) {
|
|
21627
|
+
const k = `${cell2.row},${cell2.col}`;
|
|
21628
|
+
if (cell2.borderFillIDRef != null && cell2.borderFillIDRef in localBf) {
|
|
21629
|
+
tr.cellBf.set(k, localBf[cell2.borderFillIDRef]);
|
|
21182
21630
|
}
|
|
21183
|
-
if (
|
|
21184
|
-
tr.cellChar.set(k, localChar[
|
|
21631
|
+
if (cell2.charPrIDRef != null && cell2.charPrIDRef in localChar) {
|
|
21632
|
+
tr.cellChar.set(k, localChar[cell2.charPrIDRef]);
|
|
21185
21633
|
}
|
|
21186
|
-
const h = parseHu(
|
|
21634
|
+
const h = parseHu(cell2.height_hwpunit);
|
|
21187
21635
|
if (h != null) tr.cellH.set(k, h);
|
|
21188
21636
|
}
|
|
21189
21637
|
remap.tables.push(tr);
|
|
21190
21638
|
}
|
|
21191
21639
|
return remap;
|
|
21192
21640
|
}
|
|
21193
|
-
function profileCharPrBase(ratioVariantCount) {
|
|
21194
|
-
return CHAR_VARIANT_BASE + ratioVariantCount * 4;
|
|
21195
|
-
}
|
|
21196
21641
|
|
|
21197
21642
|
// src/hwpx/gen-table.ts
|
|
21198
21643
|
var TABLE_ID_BASE = 1e3;
|
|
@@ -21200,47 +21645,141 @@ var tableIdCounter = TABLE_ID_BASE;
|
|
|
21200
21645
|
function nextTableId() {
|
|
21201
21646
|
return ++tableIdCounter;
|
|
21202
21647
|
}
|
|
21203
|
-
|
|
21204
|
-
|
|
21648
|
+
var DATA_TABLE_INSET = 1800;
|
|
21649
|
+
function anchorOfMarkdownCell(cell2) {
|
|
21650
|
+
return normalizeAnchor(cell2.replace(/!\[[^\]]*\]\([^)]*\)/g, ""));
|
|
21205
21651
|
}
|
|
21206
21652
|
function anchorOfHtmlCell(inner) {
|
|
21207
21653
|
const noNested = inner.replace(/<table[\s\S]*?<\/table>/gi, "");
|
|
21208
21654
|
const { lines } = htmlCellInnerToLines(noNested);
|
|
21209
21655
|
return normalizeAnchor(lines.join(""));
|
|
21210
21656
|
}
|
|
21211
|
-
function
|
|
21212
|
-
if (tp
|
|
21213
|
-
|
|
21214
|
-
return Array(colCnt).fill(
|
|
21657
|
+
function profileColWidths(tp, colCnt) {
|
|
21658
|
+
if (!tp) return null;
|
|
21659
|
+
if (tp.colWidths && tp.colWidths.length === colCnt) return tp.colWidths;
|
|
21660
|
+
if (tp.width) return Array(colCnt).fill(Math.floor(tp.width / colCnt));
|
|
21661
|
+
return null;
|
|
21662
|
+
}
|
|
21663
|
+
var CELL_PAD = 582;
|
|
21664
|
+
function cellContentWidth(text, charHeight) {
|
|
21665
|
+
let max = 0;
|
|
21666
|
+
for (const seg of text.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
|
|
21667
|
+
const w = measureTextWidth(seg.trim(), charHeight, 100);
|
|
21668
|
+
if (w > max) max = w;
|
|
21669
|
+
}
|
|
21670
|
+
return max;
|
|
21671
|
+
}
|
|
21672
|
+
function computeColWidths(colMax, totalWidth) {
|
|
21673
|
+
const colCnt = colMax.length;
|
|
21674
|
+
const minW = Math.min(Math.max(2e3, Math.round(totalWidth * 0.06)), Math.floor(totalWidth / colCnt));
|
|
21675
|
+
const cap = Math.round(totalWidth * 0.8);
|
|
21676
|
+
const raw = colMax.map((w) => Math.min(Math.max(w + CELL_PAD, minW), cap));
|
|
21677
|
+
const widths = Array(colCnt).fill(0);
|
|
21678
|
+
const free = new Set(raw.map((_, i) => i));
|
|
21679
|
+
let budget = totalWidth;
|
|
21680
|
+
const evenShare = Math.floor(totalWidth / colCnt);
|
|
21681
|
+
for (let i = 0; i < colCnt; i++) {
|
|
21682
|
+
const fixed = Math.min(Math.round(raw[i] * 1.12), evenShare);
|
|
21683
|
+
if (raw[i] <= evenShare && free.size > 1) {
|
|
21684
|
+
widths[i] = fixed;
|
|
21685
|
+
free.delete(i);
|
|
21686
|
+
budget -= fixed;
|
|
21687
|
+
}
|
|
21688
|
+
}
|
|
21689
|
+
if (free.size === 0) {
|
|
21690
|
+
const sumRaw = raw.reduce((a, b) => a + b, 0);
|
|
21691
|
+
for (let i = 0; i < colCnt; i++) widths[i] += Math.floor(raw[i] / sumRaw * (totalWidth - sumRaw));
|
|
21692
|
+
} else {
|
|
21693
|
+
for (; ; ) {
|
|
21694
|
+
const sum2 = [...free].reduce((a, i) => a + raw[i], 0);
|
|
21695
|
+
const short = [...free].filter((i) => raw[i] / sum2 * budget < minW);
|
|
21696
|
+
if (short.length === 0) break;
|
|
21697
|
+
for (const i of short) {
|
|
21698
|
+
widths[i] = minW;
|
|
21699
|
+
free.delete(i);
|
|
21700
|
+
budget -= minW;
|
|
21701
|
+
}
|
|
21702
|
+
if (free.size === 0) break;
|
|
21703
|
+
}
|
|
21704
|
+
const sum = [...free].reduce((a, i) => a + raw[i], 0);
|
|
21705
|
+
for (const i of free) widths[i] = Math.floor(raw[i] / sum * budget);
|
|
21706
|
+
}
|
|
21707
|
+
let rem = totalWidth - widths.reduce((a, b) => a + b, 0);
|
|
21708
|
+
const order = [...raw.keys()].sort((a, b) => raw[b] - raw[a]);
|
|
21709
|
+
for (let k = 0; rem > 0; k = (k + 1) % colCnt, rem--) widths[order[k]]++;
|
|
21710
|
+
return widths;
|
|
21215
21711
|
}
|
|
21216
|
-
function
|
|
21712
|
+
function estimateRowHeight(cells, widths, charHeight) {
|
|
21713
|
+
let maxLines = 1;
|
|
21714
|
+
cells.forEach((cell2, c) => {
|
|
21715
|
+
const usable = Math.max((widths[c] ?? widths[widths.length - 1]) - CELL_PAD, 1e3);
|
|
21716
|
+
let lines = 0;
|
|
21717
|
+
for (const seg of cell2.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
|
|
21718
|
+
lines += Math.max(1, Math.ceil(measureTextWidth(seg.trim(), charHeight, 100) / usable));
|
|
21719
|
+
}
|
|
21720
|
+
if (lines > maxLines) maxLines = lines;
|
|
21721
|
+
});
|
|
21722
|
+
return maxLines * Math.round(charHeight * 1.6) + 282;
|
|
21723
|
+
}
|
|
21724
|
+
function generateTable(rows, theme, style = null, remap = null, seq = 0) {
|
|
21217
21725
|
const rowCnt = rows.length;
|
|
21218
21726
|
const colCnt = Math.max(...rows.map((r) => r.length), 1);
|
|
21219
|
-
const
|
|
21220
|
-
const
|
|
21727
|
+
const reg = style?.bfRegistry ?? null;
|
|
21728
|
+
const totalW = style ? reg ? style.totalWidth - DATA_TABLE_INSET : style.totalWidth : 44e3;
|
|
21729
|
+
const measureH = style?.charHeight ?? 1e3;
|
|
21221
21730
|
const prof = takeProfile(remap, rowCnt, colCnt, anchorOfMarkdownCell(rows[0]?.[0] ?? ""), seq);
|
|
21222
|
-
const
|
|
21223
|
-
const
|
|
21224
|
-
|
|
21225
|
-
|
|
21731
|
+
const colMax = Array(colCnt).fill(0);
|
|
21732
|
+
const colMaxBody = Array(colCnt).fill(0);
|
|
21733
|
+
rows.forEach((row, r) => row.forEach((cell2, c) => {
|
|
21734
|
+
const w = cellContentWidth(cell2, measureH);
|
|
21735
|
+
if (w > colMax[c]) colMax[c] = w;
|
|
21736
|
+
if (r > 0 && w > colMaxBody[c]) colMaxBody[c] = w;
|
|
21737
|
+
}));
|
|
21738
|
+
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW);
|
|
21739
|
+
const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
|
|
21740
|
+
const labelCol0 = !!reg && colCnt === 2 && colCentered[0] && rows.every((r) => (r[0] ?? "").replace(/\*\*|__|`/g, "").length <= 12);
|
|
21741
|
+
const tblId = nextTableId();
|
|
21742
|
+
const useHeaderStyle = !style && (theme.tableHeader !== theme.body || theme.tableHeaderBold);
|
|
21743
|
+
const mapId = style ? (id) => id === CHAR_NORMAL ? style.charPr : id === CHAR_BOLD ? style.boldCharPr : id : void 0;
|
|
21744
|
+
const rowHeights = rows.map((row) => style ? estimateRowHeight(row, colWidths, measureH) : 1500);
|
|
21226
21745
|
const trElements = rows.map((row, rowIdx) => {
|
|
21227
21746
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
21228
21747
|
const isHeaderRow = rowIdx === 0;
|
|
21229
|
-
const
|
|
21230
|
-
const
|
|
21748
|
+
const cellH = rowHeights[rowIdx];
|
|
21749
|
+
const baseCharPr = style ? style.charPr : CHAR_NORMAL;
|
|
21750
|
+
const headerCharPr = isHeaderRow && useHeaderStyle ? CHAR_TABLE_HEADER : baseCharPr;
|
|
21751
|
+
const tdElements = cells.map((cell2, colIdx) => {
|
|
21231
21752
|
const k = `${rowIdx},${colIdx}`;
|
|
21232
|
-
const
|
|
21233
|
-
const
|
|
21753
|
+
const isLabelCell2 = labelCol0 && colIdx === 0;
|
|
21754
|
+
const defaultCharPr = style ? reg && (isHeaderRow || isLabelCell2) ? style.boldCharPr : style.charPr : isHeaderRow ? headerCharPr : baseCharPr;
|
|
21755
|
+
const cellCharPr = prof?.cellChar.get(k) ?? defaultCharPr;
|
|
21756
|
+
const centered = isHeaderRow || colCentered[colIdx];
|
|
21757
|
+
const paraPrId = style ? centered ? style.tblCenterParaPr ?? style.centerParaPr : reg ? style.tblLeftParaPr ?? PARA_NORMAL : PARA_NORMAL : PARA_NORMAL;
|
|
21758
|
+
const p = cell2.split(/<br\s*\/?>/i).map((seg) => {
|
|
21759
|
+
const runs = generateRuns(seg, cellCharPr, prof?.cellChar.has(k) ? void 0 : mapId);
|
|
21760
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0">${runs || `<hp:run charPrIDRef="${cellCharPr}"><hp:t></hp:t></hp:run>`}</hp:p>`;
|
|
21761
|
+
}).join("");
|
|
21762
|
+
const bf = prof?.cellBf.get(k) ?? (reg ? reg.get(dataCellSpec({
|
|
21763
|
+
row: rowIdx,
|
|
21764
|
+
rowEnd: rowIdx,
|
|
21765
|
+
col: colIdx,
|
|
21766
|
+
colEnd: colIdx,
|
|
21767
|
+
rowCnt,
|
|
21768
|
+
colCnt,
|
|
21769
|
+
headerRows: 1,
|
|
21770
|
+
fill: isHeaderRow ? style.headerFill ?? "#E6E6E6" : isLabelCell2 ? style.labelFill ?? "#E7E7E7" : void 0
|
|
21771
|
+
})) : style && isHeaderRow ? style.headerBf : 2);
|
|
21234
21772
|
const h = prof?.cellH.get(k) ?? cellH;
|
|
21235
|
-
|
|
21236
|
-
const p = `<hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p>`;
|
|
21237
|
-
return `<hp:tc name="" header="${isHeaderRow ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${p}</hp:subList><hp:cellAddr colAddr="${colIdx}" rowAddr="${rowIdx}"/><hp:cellSpan colSpan="1" rowSpan="1"/><hp:cellSz width="${colW[colIdx]}" height="${h}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
|
|
21773
|
+
return `<hp:tc name="" header="${isHeaderRow ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="${style ? "CENTER" : "TOP"}" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${p}</hp:subList><hp:cellAddr colAddr="${colIdx}" rowAddr="${rowIdx}"/><hp:cellSpan colSpan="1" rowSpan="1"/><hp:cellSz width="${colWidths[colIdx]}" height="${h}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
|
|
21238
21774
|
}).join("");
|
|
21239
21775
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
21240
21776
|
}).join("");
|
|
21777
|
+
const tblW = colWidths.reduce((a, b) => a + b, 0);
|
|
21778
|
+
const tblH = rowHeights.reduce((a, b) => a + b, 0);
|
|
21241
21779
|
const tblInner = `<hp:sz width="${tblW}" widthRelTo="ABSOLUTE" height="${tblH}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="0" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="0" right="0" top="0" bottom="0"/><hp:inMargin left="510" right="510" top="141" bottom="141"/>` + trElements;
|
|
21242
|
-
const
|
|
21243
|
-
|
|
21780
|
+
const tbl2 = `<hp:tbl id="${tblId}" zOrder="0" numberingType="TABLE" pageBreak="CELL" repeatHeader="${style ? 1 : 0}" rowCnt="${rowCnt}" colCnt="${colCnt}" cellSpacing="0" borderFillIDRef="2" noShading="0">${tblInner}</hp:tbl>`;
|
|
21781
|
+
const hostPr = reg && style?.rightParaPr !== void 0 ? style.rightParaPr : 0;
|
|
21782
|
+
return `<hp:p paraPrIDRef="${hostPr}" styleIDRef="0"><hp:run charPrIDRef="0">${tbl2}</hp:run></hp:p>`;
|
|
21244
21783
|
}
|
|
21245
21784
|
function layoutHtmlRows(rows) {
|
|
21246
21785
|
const occupied = /* @__PURE__ */ new Set();
|
|
@@ -21248,11 +21787,11 @@ function layoutHtmlRows(rows) {
|
|
|
21248
21787
|
let colCnt = 0;
|
|
21249
21788
|
for (let r = 0; r < rows.length; r++) {
|
|
21250
21789
|
let c = 0;
|
|
21251
|
-
for (const
|
|
21790
|
+
for (const cell2 of rows[r].cells) {
|
|
21252
21791
|
while (occupied.has(`${r},${c}`)) c++;
|
|
21253
|
-
const colSpan = Math.max(1,
|
|
21254
|
-
const rowSpan = Math.max(1,
|
|
21255
|
-
placed.push({ r, c, colSpan, rowSpan, inner:
|
|
21792
|
+
const colSpan = Math.max(1, cell2.colSpan);
|
|
21793
|
+
const rowSpan = Math.max(1, cell2.rowSpan);
|
|
21794
|
+
placed.push({ r, c, colSpan, rowSpan, inner: cell2.inner, isHeader: rows[r].tag === "th" });
|
|
21256
21795
|
for (let dr = 0; dr < rowSpan; dr++) {
|
|
21257
21796
|
for (let dc = 0; dc < colSpan; dc++) occupied.add(`${r + dr},${c + dc}`);
|
|
21258
21797
|
}
|
|
@@ -21265,50 +21804,135 @@ function layoutHtmlRows(rows) {
|
|
|
21265
21804
|
function unescapeHtml(s) {
|
|
21266
21805
|
return s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
21267
21806
|
}
|
|
21268
|
-
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, remap = null, seq = 0) {
|
|
21807
|
+
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, remap = null, seq = 0) {
|
|
21269
21808
|
const rows = parseHtmlTable(rawHtml);
|
|
21270
21809
|
if (!rows || rows.length === 0) return null;
|
|
21271
21810
|
const { placed, rowCnt, colCnt } = layoutHtmlRows(rows);
|
|
21272
21811
|
if (rowCnt === 0 || colCnt === 0) return null;
|
|
21273
|
-
const
|
|
21274
|
-
const tblId = nextTableId();
|
|
21812
|
+
const measureH = style?.charHeight ?? 1e3;
|
|
21275
21813
|
const first = placed.find((p) => p.r === 0 && p.c === 0) ?? placed[0];
|
|
21276
21814
|
const prof = takeProfile(remap, rowCnt, colCnt, first ? anchorOfHtmlCell(first.inner) : "", seq);
|
|
21277
|
-
const
|
|
21278
|
-
const
|
|
21279
|
-
const
|
|
21280
|
-
|
|
21281
|
-
|
|
21282
|
-
|
|
21283
|
-
|
|
21284
|
-
|
|
21285
|
-
|
|
21286
|
-
|
|
21815
|
+
const colMax = Array(colCnt).fill(0);
|
|
21816
|
+
const colMaxBody = Array(colCnt).fill(0);
|
|
21817
|
+
const cellLines = placed.map((cell2) => htmlCellInnerToLines(cell2.inner).lines);
|
|
21818
|
+
placed.forEach((cell2, i) => {
|
|
21819
|
+
const w = Math.max(...cellLines[i].map((l) => measureTextWidth(unescapeHtml(l).trim(), measureH, 100)), 0) / cell2.colSpan;
|
|
21820
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
21821
|
+
const c = cell2.c + dc;
|
|
21822
|
+
if (w > colMax[c]) colMax[c] = w;
|
|
21823
|
+
if (!cell2.isHeader && w > colMaxBody[c]) colMaxBody[c] = w;
|
|
21824
|
+
}
|
|
21825
|
+
});
|
|
21826
|
+
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth);
|
|
21827
|
+
const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
|
|
21828
|
+
const cellH = style ? Math.round(measureH * 1.6) + 282 : 1500;
|
|
21829
|
+
const tblW = colWidths.reduce((a, b) => a + b, 0);
|
|
21830
|
+
const tblId = nextTableId();
|
|
21831
|
+
const useHeaderStyle = !style && (theme.tableHeader !== theme.body || theme.tableHeaderBold);
|
|
21832
|
+
const spanW = (cell2) => colWidths.slice(cell2.c, cell2.c + cell2.colSpan).reduce((a, b) => a + b, 0);
|
|
21833
|
+
const reg = style?.bfRegistry ?? null;
|
|
21834
|
+
let htmlHeaderRows = 0;
|
|
21835
|
+
while (htmlHeaderRows < rows.length && rows[htmlHeaderRows].tag === "th") htmlHeaderRows++;
|
|
21836
|
+
const tcXmls = placed.map((cell2, i) => {
|
|
21837
|
+
const k = `${cell2.r},${cell2.c}`;
|
|
21838
|
+
const isHeader = cell2.isHeader;
|
|
21839
|
+
const baseCharPr = style ? style.charPr : CHAR_NORMAL;
|
|
21840
|
+
const headerCharPr = isHeader && useHeaderStyle ? CHAR_TABLE_HEADER : baseCharPr;
|
|
21841
|
+
const defaultCharPr = style && reg && isHeader ? style.boldCharPr : isHeader ? headerCharPr : baseCharPr;
|
|
21842
|
+
const charPrId = prof?.cellChar.get(k) ?? defaultCharPr;
|
|
21843
|
+
const centered = isHeader || colCentered[cell2.c];
|
|
21844
|
+
const paraPrId = style ? centered ? reg ? style.tblCenterParaPr ?? style.centerParaPr : style.centerParaPr : reg ? style.tblLeftParaPr ?? PARA_NORMAL : PARA_NORMAL : PARA_NORMAL;
|
|
21845
|
+
const lines = cellLines[i];
|
|
21287
21846
|
const paras = lines.map(
|
|
21288
|
-
(line) => `<hp:p paraPrIDRef="
|
|
21847
|
+
(line) => `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(unescapeHtml(line))}</hp:t></hp:run></hp:p>`
|
|
21289
21848
|
);
|
|
21290
|
-
const cellW = spanW(cell.c, cell.colSpan);
|
|
21291
21849
|
let nestedH = 0;
|
|
21292
|
-
for (const nested of extractTopLevelTables(
|
|
21293
|
-
const
|
|
21850
|
+
for (const nested of extractTopLevelTables(cell2.inner)) {
|
|
21851
|
+
const nestedW = Math.max(spanW(cell2) - 1020, 4e3);
|
|
21852
|
+
const nestedXml = generateHtmlTableXml(nested, theme, nestedW, style ? { ...style, totalWidth: nestedW } : null);
|
|
21294
21853
|
if (nestedXml) {
|
|
21295
21854
|
paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${nestedXml}</hp:run></hp:p>`);
|
|
21296
21855
|
nestedH += (nested.match(/<tr[\s>]/gi) ?? []).length * cellH + 300;
|
|
21297
21856
|
}
|
|
21298
21857
|
}
|
|
21299
21858
|
if (paras.length === 0) {
|
|
21300
|
-
paras.push(`<hp:p paraPrIDRef="
|
|
21859
|
+
paras.push(`<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t></hp:t></hp:run></hp:p>`);
|
|
21301
21860
|
}
|
|
21302
|
-
const contentH = Math.max(cellH *
|
|
21861
|
+
const contentH = Math.max(cellH * cell2.rowSpan, Math.max(lines.length, 1) * (style ? Math.round(measureH * 1.6) : 800) + nestedH);
|
|
21303
21862
|
const cellHeight = Math.max(prof?.cellH.get(k) ?? 0, contentH);
|
|
21304
|
-
|
|
21863
|
+
const bf = prof?.cellBf.get(k) ?? (reg ? reg.get(dataCellSpec({
|
|
21864
|
+
row: cell2.r,
|
|
21865
|
+
rowEnd: cell2.r + cell2.rowSpan - 1,
|
|
21866
|
+
col: cell2.c,
|
|
21867
|
+
colEnd: cell2.c + cell2.colSpan - 1,
|
|
21868
|
+
rowCnt,
|
|
21869
|
+
colCnt,
|
|
21870
|
+
headerRows: htmlHeaderRows,
|
|
21871
|
+
fill: isHeader ? style.headerFill ?? "#E6E6E6" : void 0
|
|
21872
|
+
})) : style && isHeader ? style.headerBf : 2);
|
|
21873
|
+
return `<hp:tc name="" header="${isHeader ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="${style ? "CENTER" : "TOP"}" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${paras.join("")}</hp:subList><hp:cellAddr colAddr="${cell2.c}" rowAddr="${cell2.r}"/><hp:cellSpan colSpan="${cell2.colSpan}" rowSpan="${cell2.rowSpan}"/><hp:cellSz width="${spanW(cell2)}" height="${cellHeight}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
|
|
21305
21874
|
});
|
|
21306
21875
|
const trXmls = [];
|
|
21307
21876
|
for (let r = 0; r < rowCnt; r++) {
|
|
21308
21877
|
const rowTcs = tcXmls.filter((_, i) => placed[i].r === r);
|
|
21309
21878
|
trXmls.push(`<hp:tr>${rowTcs.join("")}</hp:tr>`);
|
|
21310
21879
|
}
|
|
21311
|
-
return `<hp:tbl id="${tblId}" zOrder="0" numberingType="TABLE" pageBreak="CELL" repeatHeader="0" rowCnt="${rowCnt}" colCnt="${colCnt}" cellSpacing="0" borderFillIDRef="2" noShading="0"><hp:sz width="${tblW}" widthRelTo="ABSOLUTE" height="${cellH * rowCnt}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="0" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="0" right="0" top="0" bottom="0"/><hp:inMargin left="510" right="510" top="141" bottom="141"/>` + trXmls.join("") + `</hp:tbl>`;
|
|
21880
|
+
return `<hp:tbl id="${tblId}" zOrder="0" numberingType="TABLE" pageBreak="CELL" repeatHeader="${style ? 1 : 0}" rowCnt="${rowCnt}" colCnt="${colCnt}" cellSpacing="0" borderFillIDRef="2" noShading="0"><hp:sz width="${tblW}" widthRelTo="ABSOLUTE" height="${cellH * rowCnt}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="0" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="0" right="0" top="0" bottom="0"/><hp:inMargin left="510" right="510" top="141" bottom="141"/>` + trXmls.join("") + `</hp:tbl>`;
|
|
21881
|
+
}
|
|
21882
|
+
|
|
21883
|
+
// src/hwpx/gen-gongmun-extra.ts
|
|
21884
|
+
var extraTableId = 93e5;
|
|
21885
|
+
function tbl(rows, w, h, cols) {
|
|
21886
|
+
return `<hp:tbl id="${++extraTableId}" zOrder="0" numberingType="TABLE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" pageBreak="CELL" repeatHeader="0" rowCnt="${rows.length}" colCnt="${cols}" cellSpacing="0" borderFillIDRef="1" noAdjust="1"><hp:sz width="${w}" widthRelTo="ABSOLUTE" height="${h}" 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="283" right="283" top="283" bottom="283"/><hp:inMargin left="141" right="141" top="141" bottom="141"/>` + rows.map((r) => `<hp:tr>${r}</hp:tr>`).join("") + `</hp:tbl>`;
|
|
21887
|
+
}
|
|
21888
|
+
function tc(opts) {
|
|
21889
|
+
return `<hp:tc name="" header="0" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${opts.bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="CENTER" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${opts.paras}</hp:subList><hp:cellAddr colAddr="${opts.col}" rowAddr="${opts.row}"/><hp:cellSpan colSpan="${opts.colSpan ?? 1}" rowSpan="1"/><hp:cellSz width="${opts.w}" height="${opts.h}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
|
|
21890
|
+
}
|
|
21891
|
+
function para(text, paraPrId, charPrId) {
|
|
21892
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
|
|
21893
|
+
}
|
|
21894
|
+
var APPROVAL_COL_W = 7085;
|
|
21895
|
+
var APPROVAL_LABEL_H = 1100;
|
|
21896
|
+
var APPROVAL_SIGN_H = 4200;
|
|
21897
|
+
function buildApprovalTable(labels, gongmun, reg) {
|
|
21898
|
+
const n = labels.length;
|
|
21899
|
+
const w = APPROVAL_COL_W * n;
|
|
21900
|
+
const bfAt = (row, col) => reg.get({
|
|
21901
|
+
t: row === 0 ? "thick" : "thin",
|
|
21902
|
+
b: row === 1 ? "thick" : "thin",
|
|
21903
|
+
l: col === 0 ? "thick" : "thin",
|
|
21904
|
+
r: col === n - 1 ? "thick" : "thin"
|
|
21905
|
+
});
|
|
21906
|
+
const labelRow = labels.map(
|
|
21907
|
+
(label, c) => tc({ bf: bfAt(0, c), row: 0, col: c, w: APPROVAL_COL_W, h: APPROVAL_LABEL_H, paras: para(label, GONGMUN_TBL_CENTER, CHAR_NORMAL) })
|
|
21908
|
+
).join("");
|
|
21909
|
+
const signRow = labels.map(
|
|
21910
|
+
(_, c) => tc({ bf: bfAt(1, c), row: 1, col: c, w: APPROVAL_COL_W, h: APPROVAL_SIGN_H, paras: para("", GONGMUN_TBL_CENTER, CHAR_NORMAL) })
|
|
21911
|
+
).join("");
|
|
21912
|
+
const table2 = tbl([labelRow, signRow], w, APPROVAL_LABEL_H + APPROVAL_SIGN_H, n);
|
|
21913
|
+
return `<hp:p paraPrIDRef="${GONGMUN_RIGHT}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`;
|
|
21914
|
+
}
|
|
21915
|
+
function hasEndMark(lastText) {
|
|
21916
|
+
return /끝\s*\.?\s*$/.test(lastText.trim());
|
|
21917
|
+
}
|
|
21918
|
+
function buildEndMark() {
|
|
21919
|
+
return para(" \uB05D.", PARA_NORMAL, CHAR_NORMAL);
|
|
21920
|
+
}
|
|
21921
|
+
var TITLE_BOX = { barH: 382, titleH: 2850, color: "#0080C0", gradient: ["#0080C0", "#3CBFFF"] };
|
|
21922
|
+
function buildTitleBox(title, titleCharPr, bodyWidth, reg) {
|
|
21923
|
+
const w = bodyWidth - 280;
|
|
21924
|
+
const outer = { t: "thin", b: "thin", l: "thin", r: "thin" };
|
|
21925
|
+
const barTop = reg.get({ ...outer, fill: TITLE_BOX.color });
|
|
21926
|
+
const barBottom = reg.get({ ...outer, fill: { gradient: TITLE_BOX.gradient } });
|
|
21927
|
+
const mid = reg.get(outer);
|
|
21928
|
+
const barPara = `<hp:p paraPrIDRef="${GONGMUN_TBL_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t></hp:t></hp:run></hp:p>`;
|
|
21929
|
+
const rows = [
|
|
21930
|
+
tc({ bf: barTop, row: 0, col: 0, w, h: TITLE_BOX.barH, paras: barPara }),
|
|
21931
|
+
tc({ bf: mid, row: 1, col: 0, w, h: TITLE_BOX.titleH, paras: para(title, GONGMUN_TBL_CENTER, titleCharPr) }),
|
|
21932
|
+
tc({ bf: barBottom, row: 2, col: 0, w, h: TITLE_BOX.barH, paras: barPara })
|
|
21933
|
+
];
|
|
21934
|
+
const table2 = tbl(rows, w, TITLE_BOX.barH * 2 + TITLE_BOX.titleH, 1);
|
|
21935
|
+
return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`;
|
|
21312
21936
|
}
|
|
21313
21937
|
|
|
21314
21938
|
// src/hwpx/equation-generate.ts
|
|
@@ -21598,14 +22222,76 @@ function generateSecPr(gongmun) {
|
|
|
21598
22222
|
header: 0,
|
|
21599
22223
|
footer: 0
|
|
21600
22224
|
} : { top: 8504, bottom: 4252, left: 5670, right: 4252, header: 2835, footer: 2835 };
|
|
21601
|
-
|
|
22225
|
+
if (gongmun) {
|
|
22226
|
+
m.header = gongmun.headerFooter;
|
|
22227
|
+
m.footer = gongmun.headerFooter;
|
|
22228
|
+
}
|
|
22229
|
+
const secPr = `<hp:secPr textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="1" memoShapeIDRef="0" textVerticalWidthHead="0" masterPageCnt="0"><hp:grid lineGrid="0" charGrid="0" wonggojiFormat="0"/><hp:startNum pageStartsOn="BOTH" page="0" pic="0" tbl="0" equation="0"/><hp:visibility hideFirstHeader="0" hideFirstFooter="0" hideFirstMasterPage="0" border="SHOW_ALL" fill="SHOW_ALL" hideFirstPageNum="0" hideFirstEmptyLine="0" showLineNumber="0"/><hp:pagePr landscape="WIDELY" width="59528" height="84188" gutterType="LEFT_ONLY"><hp:margin header="${m.header}" footer="${m.footer}" gutter="0" left="${m.left}" right="${m.right}" top="${m.top}" bottom="${m.bottom}"/></hp:pagePr><hp:footNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="-1" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="283" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="EACH_COLUMN" beneathText="0"/></hp:footNotePr><hp:endNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="14692344" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="0" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="END_OF_DOCUMENT" beneathText="0"/></hp:endNotePr></hp:secPr>`;
|
|
22230
|
+
return gongmun?.pageNumbers ? secPr + pageNumCtrl() : secPr;
|
|
21602
22231
|
}
|
|
21603
|
-
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, remap = null) {
|
|
22232
|
+
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null) {
|
|
21604
22233
|
const paraXmls = [];
|
|
21605
22234
|
let isFirst = true;
|
|
21606
22235
|
let tableSeq = 0;
|
|
21607
22236
|
const orderedCounters = {};
|
|
21608
22237
|
let prevWasOrdered = false;
|
|
22238
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
22239
|
+
const vBase = charVariantBase(gaejosik);
|
|
22240
|
+
const tableStyle = gongmun ? {
|
|
22241
|
+
totalWidth: mmToHwpunit(210 - gongmun.margins.left - gongmun.margins.right),
|
|
22242
|
+
charPr: gaejosik ? GJ_CHAR_TABLE : CHAR_NORMAL,
|
|
22243
|
+
boldCharPr: gaejosik ? GJ_CHAR_TABLE_BOLD : CHAR_BOLD,
|
|
22244
|
+
charHeight: gaejosik ? gaejosikSizes(gongmun.bodyHeight, gongmun.sizes).table : gongmun.bodyHeight,
|
|
22245
|
+
headerBf: gongmunTableHeaderBf(gaejosik),
|
|
22246
|
+
centerParaPr: GONGMUN_CENTER,
|
|
22247
|
+
tblCenterParaPr: GONGMUN_TBL_CENTER,
|
|
22248
|
+
tblLeftParaPr: GONGMUN_TBL_LEFT,
|
|
22249
|
+
bfRegistry: bfReg ?? void 0,
|
|
22250
|
+
rightParaPr: GONGMUN_RIGHT
|
|
22251
|
+
} : null;
|
|
22252
|
+
const chamMap = (id) => id === CHAR_BOLD ? GJ_CHAR_CHAM_BOLD : id;
|
|
22253
|
+
let chapterNo = 0;
|
|
22254
|
+
let coverH1Idx = -1;
|
|
22255
|
+
let pendingPageBreak = false;
|
|
22256
|
+
let pendingNewNum = false;
|
|
22257
|
+
let titleBoxH1Idx = -1;
|
|
22258
|
+
let hasFrontPages = false;
|
|
22259
|
+
const preamble = [];
|
|
22260
|
+
if (gongmun?.approval && bfReg) {
|
|
22261
|
+
preamble.push(buildApprovalTable(gongmun.approval, gongmun, bfReg));
|
|
22262
|
+
}
|
|
22263
|
+
if (gaejosik && gongmun) {
|
|
22264
|
+
const h1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
|
|
22265
|
+
const chapters = blocks.filter((b) => b.type === "heading" && b.level === 2).map((b) => stripChapterNumber(b.text || ""));
|
|
22266
|
+
let coverTitle = "";
|
|
22267
|
+
const hide = (xml, hideHeader) => gongmun.pageNumbers ? xml.replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${pageHidingCtrl(hideHeader)}`) : xml;
|
|
22268
|
+
if (gongmun.cover && h1Idx >= 0) {
|
|
22269
|
+
coverTitle = (blocks[h1Idx].text || "").trim();
|
|
22270
|
+
const coverPart = buildGaejosikCover(coverTitle, gongmun);
|
|
22271
|
+
coverPart[0] = hide(coverPart[0], true);
|
|
22272
|
+
preamble.push(...coverPart);
|
|
22273
|
+
coverH1Idx = h1Idx;
|
|
22274
|
+
hasFrontPages = true;
|
|
22275
|
+
}
|
|
22276
|
+
if (gongmun.toc && chapters.length > 0) {
|
|
22277
|
+
const tocPart = buildGaejosikToc(chapters, gongmun);
|
|
22278
|
+
tocPart[0] = hide(tocPart[0], false);
|
|
22279
|
+
preamble.push(...tocPart);
|
|
22280
|
+
hasFrontPages = true;
|
|
22281
|
+
}
|
|
22282
|
+
if (gongmun.bodyTitleBox && coverTitle && hasFrontPages) {
|
|
22283
|
+
preamble.push(buildGaejosikBodyTitle(coverTitle, gongmun).replace(/^<hp:p /, `<hp:p pageBreak="1" `));
|
|
22284
|
+
}
|
|
22285
|
+
} else if (gongmun && !gaejosik && bfReg && (gongmun.preset === "report" || gongmun.preset === "plan" || gongmun.preset === "notice")) {
|
|
22286
|
+
titleBoxH1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
|
|
22287
|
+
}
|
|
22288
|
+
if (preamble.length > 0) {
|
|
22289
|
+
preamble[0] = preamble[0].replace(` pageBreak="1"`, "").replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${generateSecPr(gongmun)}`);
|
|
22290
|
+
isFirst = false;
|
|
22291
|
+
pendingPageBreak = hasFrontPages && !preamble[preamble.length - 1].includes(`pageBreak="1"`);
|
|
22292
|
+
pendingNewNum = !!gongmun.pageNumbers && hasFrontPages;
|
|
22293
|
+
paraXmls.push(...preamble);
|
|
22294
|
+
}
|
|
21609
22295
|
for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
|
|
21610
22296
|
const block = blocks[blockIdx];
|
|
21611
22297
|
let xml = "";
|
|
@@ -21617,17 +22303,47 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21617
22303
|
}
|
|
21618
22304
|
switch (block.type) {
|
|
21619
22305
|
case "heading": {
|
|
22306
|
+
if (gongmun && blockIdx === titleBoxH1Idx && tableStyle && bfReg) {
|
|
22307
|
+
xml = buildTitleBox((block.text || "").trim(), CHAR_H1, tableStyle.totalWidth, bfReg);
|
|
22308
|
+
break;
|
|
22309
|
+
}
|
|
22310
|
+
if (gaejosik) {
|
|
22311
|
+
const lvl = block.level || 1;
|
|
22312
|
+
if (blockIdx === coverH1Idx) break;
|
|
22313
|
+
if (lvl <= 2) {
|
|
22314
|
+
chapterNo++;
|
|
22315
|
+
xml = buildGaejosikChapter(chapterNo, stripChapterNumber(block.text || ""), gongmun);
|
|
22316
|
+
} else if (lvl === 3) {
|
|
22317
|
+
xml = generateParagraph(
|
|
22318
|
+
`\u25A1 ${block.text || ""}`,
|
|
22319
|
+
GONGMUN_LIST_BASE,
|
|
22320
|
+
GJ_CHAR_DAE,
|
|
22321
|
+
(id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id
|
|
22322
|
+
);
|
|
22323
|
+
} else {
|
|
22324
|
+
xml = generateParagraph(`\u25CB ${block.text || ""}`, GONGMUN_LIST_BASE + 1, CHAR_NORMAL);
|
|
22325
|
+
}
|
|
22326
|
+
break;
|
|
22327
|
+
}
|
|
21620
22328
|
const pId = headingParaPrId(block.level || 1);
|
|
21621
22329
|
const cId = headingCharPrId(block.level || 1);
|
|
21622
|
-
|
|
22330
|
+
const styleId = gongmun ? Math.min(block.level || 1, 4) : 0;
|
|
22331
|
+
xml = generateParagraph(block.text || "", pId, cId, void 0, styleId);
|
|
21623
22332
|
break;
|
|
21624
22333
|
}
|
|
21625
22334
|
case "paragraph": {
|
|
22335
|
+
if (gaejosik && (block.text || "").trimStart().startsWith("\u203B")) {
|
|
22336
|
+
xml = generateParagraph((block.text || "").trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
22337
|
+
break;
|
|
22338
|
+
}
|
|
21626
22339
|
const ctr = gongmun && /^<center>([\s\S]*)<\/center>$/i.exec((block.text || "").trim());
|
|
22340
|
+
const rgt = gongmun && /^<right>([\s\S]*)<\/right>$/i.exec((block.text || "").trim());
|
|
21627
22341
|
if (ctr) {
|
|
21628
22342
|
xml = generateParagraph(ctr[1].trim(), GONGMUN_CENTER);
|
|
22343
|
+
} else if (rgt) {
|
|
22344
|
+
xml = generateParagraph(rgt[1].trim(), GONGMUN_RIGHT);
|
|
21629
22345
|
} else {
|
|
21630
|
-
xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx) : void 0);
|
|
22346
|
+
xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx, vBase) : void 0);
|
|
21631
22347
|
}
|
|
21632
22348
|
break;
|
|
21633
22349
|
}
|
|
@@ -21660,22 +22376,37 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21660
22376
|
xml = generateEquationParagraph(block.text || "", blockIdx);
|
|
21661
22377
|
break;
|
|
21662
22378
|
}
|
|
21663
|
-
case "blockquote":
|
|
22379
|
+
case "blockquote": {
|
|
22380
|
+
if (gaejosik) {
|
|
22381
|
+
const t = (block.text || "").trim();
|
|
22382
|
+
if (t) xml = generateParagraph(t.startsWith("\u203B") ? t : `\u203B ${t}`, GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
22383
|
+
break;
|
|
22384
|
+
}
|
|
21664
22385
|
xml = generateParagraph(
|
|
21665
22386
|
block.text || "",
|
|
21666
22387
|
PARA_QUOTE,
|
|
21667
22388
|
theme.hasQuoteOption ? CHAR_QUOTE : CHAR_NORMAL
|
|
21668
22389
|
);
|
|
21669
22390
|
break;
|
|
22391
|
+
}
|
|
21670
22392
|
case "list_item": {
|
|
21671
22393
|
if (gongmun && gongmunList) {
|
|
21672
22394
|
const info = gongmunList.get(blockIdx);
|
|
21673
22395
|
const depth = info?.depth ?? 0;
|
|
21674
22396
|
const marker2 = info?.marker ?? "";
|
|
21675
22397
|
const content = block.text || "";
|
|
22398
|
+
if (gaejosik && content.trimStart().startsWith("\u203B")) {
|
|
22399
|
+
xml = generateParagraph(content.trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
22400
|
+
break;
|
|
22401
|
+
}
|
|
21676
22402
|
const text = marker2 ? `${marker2} ${content}` : content;
|
|
21677
|
-
|
|
21678
|
-
|
|
22403
|
+
let listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
|
|
22404
|
+
let mapId = fit ? variantMapper(fit, blockIdx, vBase) : void 0;
|
|
22405
|
+
if (gaejosik && depth === 0) {
|
|
22406
|
+
listCharPr = GJ_CHAR_DAE;
|
|
22407
|
+
mapId = (id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id;
|
|
22408
|
+
}
|
|
22409
|
+
xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr, mapId);
|
|
21679
22410
|
break;
|
|
21680
22411
|
}
|
|
21681
22412
|
const indent = block.indent || 0;
|
|
@@ -21702,7 +22433,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21702
22433
|
break;
|
|
21703
22434
|
}
|
|
21704
22435
|
case "hr":
|
|
21705
|
-
xml = `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0"><hp:t>\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500</hp:t></hp:run></hp:p>`;
|
|
22436
|
+
xml = gongmun ? `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t></hp:t></hp:run></hp:p>` : `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0"><hp:t>\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500</hp:t></hp:run></hp:p>`;
|
|
21706
22437
|
break;
|
|
21707
22438
|
case "table":
|
|
21708
22439
|
if (block.rows) {
|
|
@@ -21711,18 +22442,19 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21711
22442
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
21712
22443
|
isFirst = false;
|
|
21713
22444
|
}
|
|
21714
|
-
xml = generateTable(block.rows, theme, remap, tableSeq++);
|
|
22445
|
+
xml = generateTable(block.rows, theme, tableStyle, remap, tableSeq++);
|
|
21715
22446
|
}
|
|
21716
22447
|
break;
|
|
21717
22448
|
case "html_table": {
|
|
21718
|
-
const
|
|
21719
|
-
|
|
22449
|
+
const htmlW = tableStyle ? bfReg ? tableStyle.totalWidth - DATA_TABLE_INSET : tableStyle.totalWidth : 44e3;
|
|
22450
|
+
const tbl2 = generateHtmlTableXml(block.text || "", theme, htmlW, tableStyle, remap, tableSeq++);
|
|
22451
|
+
if (tbl2) {
|
|
21720
22452
|
if (isFirst) {
|
|
21721
22453
|
const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
|
|
21722
22454
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
21723
22455
|
isFirst = false;
|
|
21724
22456
|
}
|
|
21725
|
-
xml = `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${
|
|
22457
|
+
xml = `<hp:p paraPrIDRef="${tableStyle && bfReg ? GONGMUN_RIGHT : 0}" styleIDRef="0"><hp:run charPrIDRef="0">${tbl2}</hp:run></hp:p>`;
|
|
21726
22458
|
} else {
|
|
21727
22459
|
const plain = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
21728
22460
|
xml = plain ? generateParagraph(plain) : "";
|
|
@@ -21738,8 +22470,20 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21738
22470
|
);
|
|
21739
22471
|
isFirst = false;
|
|
21740
22472
|
}
|
|
22473
|
+
if (pendingPageBreak) {
|
|
22474
|
+
xml = xml.replace(/^<hp:p /, `<hp:p pageBreak="1" `);
|
|
22475
|
+
pendingPageBreak = false;
|
|
22476
|
+
}
|
|
22477
|
+
if (pendingNewNum) {
|
|
22478
|
+
xml = xml.replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${newPageNumCtrl(1)}`);
|
|
22479
|
+
pendingNewNum = false;
|
|
22480
|
+
}
|
|
21741
22481
|
paraXmls.push(xml);
|
|
21742
22482
|
}
|
|
22483
|
+
if (gongmun?.endMark && paraXmls.length > 0) {
|
|
22484
|
+
const lastText = [...blocks].reverse().find((b) => (b.type === "paragraph" || b.type === "list_item") && (b.text || "").trim())?.text ?? "";
|
|
22485
|
+
if (!hasEndMark(lastText)) paraXmls.push(buildEndMark());
|
|
22486
|
+
}
|
|
21743
22487
|
if (paraXmls.length === 0) {
|
|
21744
22488
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run></hp:p>`);
|
|
21745
22489
|
}
|
|
@@ -21753,23 +22497,27 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21753
22497
|
async function markdownToHwpx(markdown, options) {
|
|
21754
22498
|
const theme = resolveTheme(options?.theme);
|
|
21755
22499
|
const gongmun = options?.gongmun ? resolveGongmun(options.gongmun) : null;
|
|
22500
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
21756
22501
|
const blocks = parseMarkdownToBlocks(markdown);
|
|
21757
22502
|
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
21758
22503
|
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
21759
|
-
const
|
|
22504
|
+
const staticBfEnd = gongmun ? gaejosik ? 11 : 4 : 3;
|
|
22505
|
+
const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(gaejosik) + (fit?.variants?.length ?? 0) * 4, staticBfEnd) : null;
|
|
22506
|
+
const bfReg = gongmun ? new TableBfRegistry(staticBfEnd + (remap?.borderFillXmls.length ?? 0)) : null;
|
|
21760
22507
|
const chartParts = [];
|
|
21761
|
-
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, remap);
|
|
22508
|
+
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap);
|
|
21762
22509
|
if (remap && remap.tables.length > 0) {
|
|
21763
22510
|
const unused = remap.tables.filter((t) => !t.used).length;
|
|
21764
22511
|
if (unused === remap.tables.length) {
|
|
21765
22512
|
console.warn(`[kordoc] format profile: \uD504\uB85C\uD544 \uD45C ${unused}\uAC1C\uAC00 \uBB38\uC11C \uD45C\uC640 \uB9E4\uCE6D\uB418\uC9C0 \uC54A\uC544 \uBBF8\uC801\uC6A9 (\uD589\xB7\uC5F4/\uCCAB \uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58)`);
|
|
21766
22513
|
}
|
|
21767
22514
|
}
|
|
22515
|
+
const extraBorderFills = [...remap?.borderFillXmls ?? [], ...bfReg?.emit() ?? []];
|
|
21768
22516
|
const zip = new JSZip6();
|
|
21769
22517
|
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
21770
22518
|
zip.file("META-INF/container.xml", generateContainerXml());
|
|
21771
22519
|
zip.file("Contents/content.hpf", generateManifest(chartParts));
|
|
21772
|
-
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? [], remap));
|
|
22520
|
+
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? [], extraBorderFills, remap?.charPrXmls ?? []));
|
|
21773
22521
|
zip.file("Contents/section0.xml", sectionXml);
|
|
21774
22522
|
for (const part of chartParts) zip.file(part.name, part.xml);
|
|
21775
22523
|
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
@@ -21968,8 +22716,8 @@ function parseCharPrs(headerDoc) {
|
|
|
21968
22716
|
}
|
|
21969
22717
|
return map;
|
|
21970
22718
|
}
|
|
21971
|
-
function isTopLevelTable(
|
|
21972
|
-
let p =
|
|
22719
|
+
function isTopLevelTable(tbl2) {
|
|
22720
|
+
let p = tbl2.parentNode;
|
|
21973
22721
|
while (p) {
|
|
21974
22722
|
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
21975
22723
|
if (tag === "tbl") return false;
|
|
@@ -21982,45 +22730,45 @@ function num(s) {
|
|
|
21982
22730
|
const n = parseInt(s, 10);
|
|
21983
22731
|
return Number.isFinite(n) ? n : void 0;
|
|
21984
22732
|
}
|
|
21985
|
-
function parseTable3(
|
|
21986
|
-
const rows = num(
|
|
21987
|
-
const cols = num(
|
|
21988
|
-
const sz = findChildByLocalName(
|
|
22733
|
+
function parseTable3(tbl2, tableIndex, borderFills, charPrs) {
|
|
22734
|
+
const rows = num(tbl2.getAttribute("rowCnt")) ?? 0;
|
|
22735
|
+
const cols = num(tbl2.getAttribute("colCnt")) ?? 0;
|
|
22736
|
+
const sz = findChildByLocalName(tbl2, "sz");
|
|
21989
22737
|
const width = sz?.getAttribute("width") || void 0;
|
|
21990
22738
|
const cells = [];
|
|
21991
22739
|
const usedBf = /* @__PURE__ */ new Set();
|
|
21992
22740
|
const usedCp = /* @__PURE__ */ new Set();
|
|
21993
22741
|
const colWidths = new Array(cols).fill(void 0);
|
|
21994
22742
|
let anchorText = "";
|
|
21995
|
-
for (const
|
|
21996
|
-
if (nearestTable(
|
|
21997
|
-
const addr = findChildByLocalName(
|
|
21998
|
-
const span = findChildByLocalName(
|
|
21999
|
-
const csz = findChildByLocalName(
|
|
22743
|
+
for (const tc2 of elemsByLocal(tbl2, "tc")) {
|
|
22744
|
+
if (nearestTable(tc2) !== tbl2) continue;
|
|
22745
|
+
const addr = findChildByLocalName(tc2, "cellAddr");
|
|
22746
|
+
const span = findChildByLocalName(tc2, "cellSpan");
|
|
22747
|
+
const csz = findChildByLocalName(tc2, "cellSz");
|
|
22000
22748
|
const row = num(addr?.getAttribute("rowAddr")) ?? 0;
|
|
22001
22749
|
const col = num(addr?.getAttribute("colAddr")) ?? 0;
|
|
22002
|
-
if (row === 0 && col === 0 && !anchorText) anchorText = directCellText(
|
|
22750
|
+
if (row === 0 && col === 0 && !anchorText) anchorText = directCellText(tc2);
|
|
22003
22751
|
const colSpan = num(span?.getAttribute("colSpan")) ?? 1;
|
|
22004
22752
|
const rowSpan = num(span?.getAttribute("rowSpan")) ?? 1;
|
|
22005
|
-
const bfId =
|
|
22006
|
-
const cpId = firstRunCharPr(
|
|
22007
|
-
const
|
|
22753
|
+
const bfId = tc2.getAttribute("borderFillIDRef") || void 0;
|
|
22754
|
+
const cpId = firstRunCharPr(tc2);
|
|
22755
|
+
const cell2 = { row, col, rowSpan, colSpan };
|
|
22008
22756
|
const w = csz?.getAttribute("width");
|
|
22009
22757
|
const hh = csz?.getAttribute("height");
|
|
22010
|
-
if (w)
|
|
22011
|
-
if (hh)
|
|
22758
|
+
if (w) cell2.width_hwpunit = w;
|
|
22759
|
+
if (hh) cell2.height_hwpunit = hh;
|
|
22012
22760
|
if (bfId) {
|
|
22013
|
-
|
|
22761
|
+
cell2.borderFillIDRef = bfId;
|
|
22014
22762
|
usedBf.add(bfId);
|
|
22015
22763
|
}
|
|
22016
22764
|
if (cpId) {
|
|
22017
|
-
|
|
22765
|
+
cell2.charPrIDRef = cpId;
|
|
22018
22766
|
usedCp.add(cpId);
|
|
22019
22767
|
}
|
|
22020
|
-
cells.push(
|
|
22768
|
+
cells.push(cell2);
|
|
22021
22769
|
if (row === 0 && colSpan === 1 && col < cols && w) colWidths[col] = w;
|
|
22022
22770
|
}
|
|
22023
|
-
const
|
|
22771
|
+
const table2 = {
|
|
22024
22772
|
table_index: tableIndex,
|
|
22025
22773
|
rows,
|
|
22026
22774
|
cols,
|
|
@@ -22028,15 +22776,15 @@ function parseTable3(tbl, tableIndex, borderFills, charPrs) {
|
|
|
22028
22776
|
used_border_fills: pick(borderFills, usedBf)
|
|
22029
22777
|
};
|
|
22030
22778
|
const anchor = normalizeAnchor(anchorText);
|
|
22031
|
-
if (anchor)
|
|
22032
|
-
if (width)
|
|
22033
|
-
if (colWidths.every((w) => w != null))
|
|
22779
|
+
if (anchor) table2.anchor_text = anchor;
|
|
22780
|
+
if (width) table2.width_hwpunit = width;
|
|
22781
|
+
if (colWidths.every((w) => w != null)) table2.col_widths_hwpunit = colWidths;
|
|
22034
22782
|
const cp = pick(charPrs, usedCp);
|
|
22035
|
-
if (Object.keys(cp).length)
|
|
22036
|
-
return
|
|
22783
|
+
if (Object.keys(cp).length) table2.used_char_prs = cp;
|
|
22784
|
+
return table2;
|
|
22037
22785
|
}
|
|
22038
|
-
function nearestTable(
|
|
22039
|
-
let p =
|
|
22786
|
+
function nearestTable(tc2) {
|
|
22787
|
+
let p = tc2.parentNode;
|
|
22040
22788
|
while (p) {
|
|
22041
22789
|
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
22042
22790
|
if (tag === "tbl") return p;
|
|
@@ -22044,9 +22792,9 @@ function nearestTable(tc) {
|
|
|
22044
22792
|
}
|
|
22045
22793
|
return null;
|
|
22046
22794
|
}
|
|
22047
|
-
function firstRunCharPr(
|
|
22048
|
-
for (const run of elemsByLocal(
|
|
22049
|
-
if (nearestCell(run) !==
|
|
22795
|
+
function firstRunCharPr(tc2) {
|
|
22796
|
+
for (const run of elemsByLocal(tc2, "run")) {
|
|
22797
|
+
if (nearestCell(run) !== tc2) continue;
|
|
22050
22798
|
const id = run.getAttribute("charPrIDRef");
|
|
22051
22799
|
if (id) return id;
|
|
22052
22800
|
}
|
|
@@ -22061,10 +22809,10 @@ function nearestCell(el) {
|
|
|
22061
22809
|
}
|
|
22062
22810
|
return null;
|
|
22063
22811
|
}
|
|
22064
|
-
function directCellText(
|
|
22812
|
+
function directCellText(tc2) {
|
|
22065
22813
|
let out = "";
|
|
22066
|
-
for (const t of elemsByLocal(
|
|
22067
|
-
if (nearestCell(t) !==
|
|
22814
|
+
for (const t of elemsByLocal(tc2, "t")) {
|
|
22815
|
+
if (nearestCell(t) !== tc2) continue;
|
|
22068
22816
|
out += t.textContent ?? "";
|
|
22069
22817
|
if (out.length >= 64) break;
|
|
22070
22818
|
}
|
|
@@ -22093,14 +22841,168 @@ async function hwpxToProfile(input) {
|
|
|
22093
22841
|
let tableIndex = 0;
|
|
22094
22842
|
for (const f of sectionFiles) {
|
|
22095
22843
|
const doc = parser.parseFromString(await f.async("text"), "text/xml");
|
|
22096
|
-
for (const
|
|
22097
|
-
if (!isTopLevelTable(
|
|
22098
|
-
tables.push(parseTable3(
|
|
22844
|
+
for (const tbl2 of elemsByLocal(doc, "tbl")) {
|
|
22845
|
+
if (!isTopLevelTable(tbl2)) continue;
|
|
22846
|
+
tables.push(parseTable3(tbl2, tableIndex++, borderFills, charPrs));
|
|
22099
22847
|
}
|
|
22100
22848
|
}
|
|
22101
22849
|
return { schema_version: "0.2.0", tables };
|
|
22102
22850
|
}
|
|
22103
22851
|
|
|
22852
|
+
// src/hwpx/font-catalog.ts
|
|
22853
|
+
var HANCOM_BUNDLED = [
|
|
22854
|
+
"\uD568\uCD08\uB86C\uBC14\uD0D5",
|
|
22855
|
+
"\uD568\uCD08\uB86C\uB3CB\uC6C0",
|
|
22856
|
+
"\uD55C\uCEF4\uBC14\uD0D5",
|
|
22857
|
+
"\uD55C\uCEF4\uB3CB\uC6C0",
|
|
22858
|
+
"\uD55C\uCEF4 \uACE0\uB515",
|
|
22859
|
+
"\uD55C\uCEF4\uACE0\uB515",
|
|
22860
|
+
"\uD55C\uCEF4 \uB9D0\uB791\uB9D0\uB791",
|
|
22861
|
+
"\uD55C\uCEF4\uC0B0\uB73B\uB3CB\uC6C0",
|
|
22862
|
+
"\uD55C\uCEF4\uC194\uC78E",
|
|
22863
|
+
"HY\uD5E4\uB4DC\uB77C\uC778M",
|
|
22864
|
+
"HY\uACAC\uACE0\uB515",
|
|
22865
|
+
"HY\uACAC\uBA85\uC870",
|
|
22866
|
+
"HY\uC911\uACE0\uB515",
|
|
22867
|
+
"HY\uC2E0\uBA85\uC870",
|
|
22868
|
+
"HY\uBA85\uC870",
|
|
22869
|
+
"HY\uADF8\uB798\uD53DM",
|
|
22870
|
+
"HY\uAD81\uC11C",
|
|
22871
|
+
"HY\uAC15M",
|
|
22872
|
+
"HY\uAC15B",
|
|
22873
|
+
"HY\uC6B8\uB989\uB3C4M",
|
|
22874
|
+
"HY\uC6B8\uB989\uB3C4B",
|
|
22875
|
+
"HY\uD0DC\uBC31B",
|
|
22876
|
+
"HY\uC218\uD3C9\uC120M",
|
|
22877
|
+
"HY\uC218\uD3C9\uC120B",
|
|
22878
|
+
"HY\uC13C\uC2A4L",
|
|
22879
|
+
"HY\uC595\uC740\uC0D8\uBB3CM",
|
|
22880
|
+
"HY\uBAA9\uD310L",
|
|
22881
|
+
"HY\uC5FD\uC11CM",
|
|
22882
|
+
"HY\uC5FD\uC11CL",
|
|
22883
|
+
"HY\uB3D9\uB158M",
|
|
22884
|
+
"HY\uB3D9\uB158B",
|
|
22885
|
+
"\uD55C\uC591\uC2E0\uBA85\uC870",
|
|
22886
|
+
"\uD55C\uC591\uC911\uACE0\uB515",
|
|
22887
|
+
"\uD55C\uC591\uACAC\uBA85\uC870",
|
|
22888
|
+
"\uD55C\uC591\uACAC\uACE0\uB515",
|
|
22889
|
+
"\uD55C\uC591\uAD81\uC11C",
|
|
22890
|
+
"\uD55C\uC591\uADF8\uB798\uD53D",
|
|
22891
|
+
"\uD734\uBA3C\uBA85\uC870",
|
|
22892
|
+
"\uD734\uBA3C\uACE0\uB515",
|
|
22893
|
+
"\uD734\uBA3C\uAD75\uC740\uD338\uCCB4",
|
|
22894
|
+
"\uD734\uBA3C\uAC00\uB294\uD338\uCCB4",
|
|
22895
|
+
"\uD734\uBA3C\uAD75\uC740\uC0D8\uCCB4",
|
|
22896
|
+
"\uD734\uBA3C\uAC00\uB294\uC0D8\uCCB4",
|
|
22897
|
+
"\uD734\uBA3C\uC61B\uCCB4",
|
|
22898
|
+
"\uD734\uBA3C\uC544\uBBF8\uCCB4",
|
|
22899
|
+
"\uD734\uBA3C\uD3B8\uC9C0\uCCB4",
|
|
22900
|
+
"\uD734\uBA3C\uB465\uADFC\uD5E4\uB4DC\uB77C\uC778",
|
|
22901
|
+
"\uD734\uBA3C\uBAA8\uC74CT",
|
|
22902
|
+
"\uD0DC \uB098\uBB34",
|
|
22903
|
+
"\uD0DC \uADF8\uB298",
|
|
22904
|
+
"\uC591\uC7AC\uAE68\uBE44\uCCB4B",
|
|
22905
|
+
"\uC591\uC7AC\uB09C\uCD08\uCCB4M",
|
|
22906
|
+
"\uC591\uC7AC\uB458\uAE30\uCCB4M",
|
|
22907
|
+
"\uC591\uC7AC\uBE14\uB7ED\uCCB4",
|
|
22908
|
+
"\uBB38\uCCB4\uBD80 \uAD81\uCCB4 \uC815\uC790\uCCB4",
|
|
22909
|
+
"\uBB38\uCCB4\uBD80 \uAD81\uCCB4 \uD758\uB9BC\uCCB4",
|
|
22910
|
+
"\uBB38\uCCB4\uBD80 \uB3CB\uC6C0\uCCB4",
|
|
22911
|
+
"\uBB38\uCCB4\uBD80 \uBC14\uD0D5\uCCB4",
|
|
22912
|
+
"\uBB38\uCCB4\uBD80 \uC4F0\uAE30 \uC815\uCCB4",
|
|
22913
|
+
"\uBB38\uCCB4\uBD80 \uC81C\uBAA9 \uB3CB\uC6C0\uCCB4",
|
|
22914
|
+
"\uBB38\uCCB4\uBD80 \uC81C\uBAA9 \uBC14\uD0D5\uCCB4",
|
|
22915
|
+
"\uC2E0\uBA85 \uC2E0\uBA85\uC870",
|
|
22916
|
+
"\uC2E0\uBA85 \uC2E0\uC2E0\uBA85\uC870",
|
|
22917
|
+
"\uC2E0\uBA85 \uACAC\uBA85\uC870",
|
|
22918
|
+
"\uC2E0\uBA85 \uC911\uACE0\uB515",
|
|
22919
|
+
"\uC2E0\uBA85 \uD0DC\uACE0\uB515",
|
|
22920
|
+
"\uC2E0\uBA85 \uACAC\uACE0\uB515",
|
|
22921
|
+
"\uC2E0\uBA85 \uC2E0\uBB38\uBA85\uC870",
|
|
22922
|
+
"MD\uAC1C\uC131\uCCB4",
|
|
22923
|
+
"MD\uC544\uB871\uCCB4",
|
|
22924
|
+
"MD\uC194\uCCB4",
|
|
22925
|
+
"MD\uC774\uC19D\uCCB4",
|
|
22926
|
+
"MD\uC544\uD2B8\uCCB4",
|
|
22927
|
+
"\uAC00\uB294\uC548\uC0C1\uC218\uCCB4",
|
|
22928
|
+
"\uC911\uAC04\uC548\uC0C1\uC218\uCCB4",
|
|
22929
|
+
"\uAD75\uC740\uC548\uC0C1\uC218\uCCB4",
|
|
22930
|
+
"HCI Poppy",
|
|
22931
|
+
"HCI Tulip",
|
|
22932
|
+
"-\uC544\uC774\uB9AC\uC2A4M"
|
|
22933
|
+
];
|
|
22934
|
+
var WINDOWS_DEFAULT = [
|
|
22935
|
+
"\uB9D1\uC740 \uACE0\uB515",
|
|
22936
|
+
"\uB9D1\uC740\uACE0\uB515",
|
|
22937
|
+
"Malgun Gothic",
|
|
22938
|
+
"\uAD74\uB9BC",
|
|
22939
|
+
"\uAD74\uB9BC\uCCB4",
|
|
22940
|
+
"\uB3CB\uC6C0",
|
|
22941
|
+
"\uB3CB\uC6C0\uCCB4",
|
|
22942
|
+
"\uBC14\uD0D5",
|
|
22943
|
+
"\uBC14\uD0D5\uCCB4",
|
|
22944
|
+
"\uAD81\uC11C",
|
|
22945
|
+
"\uAD81\uC11C\uCCB4",
|
|
22946
|
+
"Arial",
|
|
22947
|
+
"Arial Black",
|
|
22948
|
+
"Times New Roman",
|
|
22949
|
+
"Courier New",
|
|
22950
|
+
"Consolas",
|
|
22951
|
+
"Calibri",
|
|
22952
|
+
"Cambria",
|
|
22953
|
+
"Segoe UI",
|
|
22954
|
+
"Tahoma",
|
|
22955
|
+
"Verdana",
|
|
22956
|
+
"Georgia",
|
|
22957
|
+
"Symbol"
|
|
22958
|
+
];
|
|
22959
|
+
var COMMON_FREE = [
|
|
22960
|
+
"\uB098\uB214\uACE0\uB515",
|
|
22961
|
+
"\uB098\uB214\uBA85\uC870",
|
|
22962
|
+
"\uB098\uB214\uBC14\uB978\uACE0\uB515",
|
|
22963
|
+
"\uB098\uB214\uC2A4\uD018\uC5B4",
|
|
22964
|
+
"\uB098\uB214\uC190\uAE00\uC528 \uBD93",
|
|
22965
|
+
"\uB098\uB214\uC190\uAE00\uC528 \uD39C",
|
|
22966
|
+
"NanumGothic",
|
|
22967
|
+
"NanumMyeongjo",
|
|
22968
|
+
"Noto Sans KR",
|
|
22969
|
+
"Noto Serif KR",
|
|
22970
|
+
"\uBCF8\uACE0\uB515",
|
|
22971
|
+
"\uBCF8\uBA85\uC870",
|
|
22972
|
+
"Pretendard",
|
|
22973
|
+
"\uD504\uB9AC\uD150\uB2E4\uB4DC",
|
|
22974
|
+
"KoPub\uB3CB\uC6C0",
|
|
22975
|
+
"KoPub\uBC14\uD0D5",
|
|
22976
|
+
"KoPubWorld\uB3CB\uC6C0",
|
|
22977
|
+
"KoPubWorld\uBC14\uD0D5",
|
|
22978
|
+
"\uC5D0\uC2A4\uCF54\uC5B4 \uB4DC\uB9BC",
|
|
22979
|
+
"S-Core Dream",
|
|
22980
|
+
"G\uB9C8\uCF13 \uC0B0\uC2A4",
|
|
22981
|
+
"Gmarket Sans",
|
|
22982
|
+
"\uC724\uACE0\uB515",
|
|
22983
|
+
"\uC724\uACE0\uB515320",
|
|
22984
|
+
"\uC724\uACE0\uB515330",
|
|
22985
|
+
"\uC724\uACE0\uB515340",
|
|
22986
|
+
"\uC724\uBA85\uC870"
|
|
22987
|
+
];
|
|
22988
|
+
function norm(name) {
|
|
22989
|
+
return name.replace(/\s+/g, "").toLowerCase();
|
|
22990
|
+
}
|
|
22991
|
+
var KNOWN = new Set([...HANCOM_BUNDLED, ...WINDOWS_DEFAULT, ...COMMON_FREE].map(norm));
|
|
22992
|
+
function isKnownFont(name) {
|
|
22993
|
+
return KNOWN.has(norm(name));
|
|
22994
|
+
}
|
|
22995
|
+
function unknownFontWarnings(fonts) {
|
|
22996
|
+
const warnings = [];
|
|
22997
|
+
for (const [role, name] of Object.entries(fonts)) {
|
|
22998
|
+
if (!name || isKnownFont(name)) continue;
|
|
22999
|
+
warnings.push(
|
|
23000
|
+
`\uD3F0\uD2B8 \uACBD\uACE0: ${role}="${name}" \u2014 \uD55C\uCEF4 \uBC88\uB4E4\xB7\uD1B5\uC0C1 \uC124\uCE58 \uBAA9\uB85D\uC5D0 \uC5C6\uB294 \uD3F0\uD2B8\uBA85\uC785\uB2C8\uB2E4. \uC624\uD0C0\uC774\uAC70\uB098 \uB300\uC0C1 PC\uC5D0 \uBBF8\uC124\uCE58\uBA74 \uD55C\uAE00\uC774 \uAE30\uBCF8 \uD3F0\uD2B8\uB85C \uB300\uCCB4 \uB80C\uB354\uD569\uB2C8\uB2E4 (\uC0DD\uC131\uC740 \uC9C4\uD589\uB428)`
|
|
23001
|
+
);
|
|
23002
|
+
}
|
|
23003
|
+
return warnings;
|
|
23004
|
+
}
|
|
23005
|
+
|
|
22104
23006
|
// src/roundtrip/patcher.ts
|
|
22105
23007
|
import JSZip8 from "jszip";
|
|
22106
23008
|
|
|
@@ -22108,10 +23010,10 @@ import JSZip8 from "jszip";
|
|
|
22108
23010
|
var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
|
|
22109
23011
|
var TAG_AT_RE = /<[A-Za-z0-9_:]+(?:"[^"]*"|'[^']*'|[^>"'])*>/y;
|
|
22110
23012
|
function patchTableRows(input) {
|
|
22111
|
-
const { table, scanTable, ctx, skip, origKeys, editedKeys } = input;
|
|
23013
|
+
const { table: table2, scanTable, ctx, skip, origKeys, editedKeys } = input;
|
|
22112
23014
|
const xml = ctx.scans[scanTable.sectionIndex]?.xml;
|
|
22113
23015
|
if (!xml) return skip("\uC139\uC158 XML \uB9E4\uD551 \uC2E4\uD328");
|
|
22114
|
-
const numRows =
|
|
23016
|
+
const numRows = table2.rows;
|
|
22115
23017
|
if (origKeys.length !== numRows) return skip("\uD45C \uD589 \uC88C\uD45C \uBD88\uC77C\uCE58 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
22116
23018
|
if (scanTable.rows.length !== numRows || scanTable.rowRanges.length !== numRows) {
|
|
22117
23019
|
return skip("\uD45C \uD589 \uAD6C\uC870 \uC88C\uD45C \uBD88\uC77C\uCE58 (\uBE48 \uD589/\uBCD1\uD569 \uC18C\uC2E4) \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
@@ -22182,8 +23084,8 @@ function patchTableRows(input) {
|
|
|
22182
23084
|
if (template < 0) template = kept[0];
|
|
22183
23085
|
const cells = input.editedCells(ins.ei);
|
|
22184
23086
|
if (!cells) return skip("\uC0BD\uC785 \uD589\uC5D0 \uC774\uBBF8\uC9C0/\uC911\uCCA9\uD45C \uD3EC\uD568 \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
|
|
22185
|
-
for (const
|
|
22186
|
-
const unstable =
|
|
23087
|
+
for (const cell2 of cells) {
|
|
23088
|
+
const unstable = cell2.lines.find((l) => sanitizeText(l) !== l);
|
|
22187
23089
|
if (unstable !== void 0) return skip("\uC0BD\uC785 \uD589\uC5D0 \uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
22188
23090
|
}
|
|
22189
23091
|
const tmplCells = scanTable.rows[template];
|
|
@@ -22193,7 +23095,7 @@ function patchTableRows(input) {
|
|
|
22193
23095
|
}
|
|
22194
23096
|
if (tmplCells.some((c) => c.rowSpan > 1)) return skip("\uC11C\uC2DD \uAE30\uC900 \uD589\uC5D0 \uC138\uB85C \uBCD1\uD569 \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
|
|
22195
23097
|
const tmplWidth = tmplCells.reduce((s, c) => s + c.colSpan, 0);
|
|
22196
|
-
if (tmplWidth !==
|
|
23098
|
+
if (tmplWidth !== table2.cols) return skip("\uC11C\uC2DD \uAE30\uC900 \uD589\uC774 \uACA9\uC790 \uC804\uCCB4\uB97C \uB36E\uC9C0 \uC54A\uC74C \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
|
|
22197
23099
|
if (cells.length !== tmplCells.length) {
|
|
22198
23100
|
return skip(`\uC0BD\uC785 \uD589 \uC140 \uC218(${cells.length}) \u2260 \uAE30\uC900 \uD589 \uC140 \uC218(${tmplCells.length}) \u2014 \uBBF8\uC9C0\uC6D0`);
|
|
22199
23101
|
}
|
|
@@ -22250,8 +23152,8 @@ function patchTableRows(input) {
|
|
|
22250
23152
|
for (const k of keeps) {
|
|
22251
23153
|
const fi = finalIndex.get(k);
|
|
22252
23154
|
if (fi === k.oi) continue;
|
|
22253
|
-
for (const
|
|
22254
|
-
const sp = rowAddrRewrite(xml,
|
|
23155
|
+
for (const cell2 of scanTable.rows[k.oi]) {
|
|
23156
|
+
const sp = rowAddrRewrite(xml, cell2, fi);
|
|
22255
23157
|
if (sp) splices.push(sp);
|
|
22256
23158
|
}
|
|
22257
23159
|
}
|
|
@@ -22300,13 +23202,13 @@ function buildRowFragment(xml, scanTable, template, cells, finalRow, hasExplicit
|
|
|
22300
23202
|
const patched = applySplices(wrapped, splices);
|
|
22301
23203
|
return patched.slice(FRAG_OPEN.length, patched.length - FRAG_CLOSE.length);
|
|
22302
23204
|
}
|
|
22303
|
-
function rowAddrRewrite(xml,
|
|
22304
|
-
if (!
|
|
22305
|
-
const tag = xml.slice(
|
|
23205
|
+
function rowAddrRewrite(xml, cell2, newRow) {
|
|
23206
|
+
if (!cell2.addrTagRange) return null;
|
|
23207
|
+
const tag = xml.slice(cell2.addrTagRange.start, cell2.addrTagRange.end);
|
|
22306
23208
|
const m = tag.match(/\browAddr\s*=\s*"(\d+)"/);
|
|
22307
23209
|
if (!m || m.index === void 0) return null;
|
|
22308
23210
|
if (parseInt(m[1], 10) === newRow) return null;
|
|
22309
|
-
const valStart =
|
|
23211
|
+
const valStart = cell2.addrTagRange.start + m.index + m[0].indexOf('"') + 1;
|
|
22310
23212
|
return { start: valStart, end: valStart + m[1].length, replacement: String(newRow) };
|
|
22311
23213
|
}
|
|
22312
23214
|
function rowHeightOf(fragment) {
|
|
@@ -22332,8 +23234,8 @@ function tableSzHeightSplice(xml, scanTable, tblOpenLen, delta) {
|
|
|
22332
23234
|
}
|
|
22333
23235
|
|
|
22334
23236
|
// src/roundtrip/table-patch.ts
|
|
22335
|
-
function patchGfmTable(
|
|
22336
|
-
const replica = replicateGfmTable(
|
|
23237
|
+
function patchGfmTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
23238
|
+
const replica = replicateGfmTable(table2);
|
|
22337
23239
|
if (!replica) return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
22338
23240
|
const origRows = parseGfmTable(orig.lines);
|
|
22339
23241
|
const editedRows = parseGfmTable(edited.lines);
|
|
@@ -22341,15 +23243,15 @@ function patchGfmTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
22341
23243
|
return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
22342
23244
|
}
|
|
22343
23245
|
if (editedRows.length !== origRows.length) {
|
|
22344
|
-
return patchGfmTableRows(
|
|
23246
|
+
return patchGfmTableRows(table2, scanTable, origRows, editedRows, replica, ctx, skip);
|
|
22345
23247
|
}
|
|
22346
23248
|
let applied = 0;
|
|
22347
23249
|
for (let r = 0; r < origRows.length; r++) {
|
|
22348
|
-
applied += patchGfmRowPair(
|
|
23250
|
+
applied += patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, r, r, ctx, skip);
|
|
22349
23251
|
}
|
|
22350
23252
|
return applied;
|
|
22351
23253
|
}
|
|
22352
|
-
function patchGfmRowPair(
|
|
23254
|
+
function patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, r, er, ctx, skip) {
|
|
22353
23255
|
if (editedRows[er].length !== origRows[r].length) {
|
|
22354
23256
|
skip(`\uD45C ${r + 1}\uD589 \uC5F4 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
|
|
22355
23257
|
return 0;
|
|
@@ -22366,7 +23268,7 @@ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er,
|
|
|
22366
23268
|
}
|
|
22367
23269
|
const newLines = unescapeGfmCell(stripCellTokens(editedRows[er][c])).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
22368
23270
|
const origLines = unescapeGfmCell(stripCellTokens(origRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
22369
|
-
const n = applyCellEdit(
|
|
23271
|
+
const n = applyCellEdit(table2, scanTable, gridR, gridC, newLines, ctx, origRows[r][c], editedRows[er][c], origLines.length);
|
|
22370
23272
|
if (n > 0 && origTokens) {
|
|
22371
23273
|
ctx.skipped.push({
|
|
22372
23274
|
reason: "\uC140 \uB0B4 \uC774\uBBF8\uC9C0\xB7\uD14D\uC2A4\uD2B8 \uD63C\uC7AC \u2014 \uD14D\uC2A4\uD2B8\uB9CC \uC801\uC6A9 (\uC774\uBBF8\uC9C0 \uC778\uC811 \uBC30\uCE58\uB294 <br> \uBD84\uB9AC\uB85C \uC7AC\uD604\uB428)",
|
|
@@ -22379,19 +23281,19 @@ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er,
|
|
|
22379
23281
|
}
|
|
22380
23282
|
return applied;
|
|
22381
23283
|
}
|
|
22382
|
-
function patchGfmTableRows(
|
|
22383
|
-
if (replica.length !==
|
|
23284
|
+
function patchGfmTableRows(table2, scanTable, origRows, editedRows, replica, ctx, skip) {
|
|
23285
|
+
if (replica.length !== table2.rows || replica.some((row, r) => row.some((c) => c.gridR !== r))) {
|
|
22384
23286
|
return skip("\uD45C \uB80C\uB354 \uD589\uACFC \uACA9\uC790 \uD589 \uBD88\uC77C\uCE58 (\uBE48 \uD589/\uBCD1\uD569) \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
22385
23287
|
}
|
|
22386
|
-
if (
|
|
23288
|
+
if (table2.cells.some((row) => row.some((c) => c && (c.colSpan > 1 || c.rowSpan > 1)))) {
|
|
22387
23289
|
return skip("\uBCD1\uD569 \uC140 \uD45C \u2014 GFM \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
22388
23290
|
}
|
|
22389
|
-
if (!gfmRenderStable(editedRows,
|
|
23291
|
+
if (!gfmRenderStable(editedRows, table2.cols)) {
|
|
22390
23292
|
return skip("\uD589 \uBCC0\uACBD \uACB0\uACFC\uAC00 \uD45C \uB80C\uB354\uC5D0\uC11C \uBCC0\uD615\uB428 (\uBE48 \uD589/\uCCAB \uC5F4 \uC804\uD30C/\uC5F4 \uC218 \uBD88\uC77C\uCE58) \u2014 \uBBF8\uC9C0\uC6D0");
|
|
22391
23293
|
}
|
|
22392
23294
|
const key = (row) => row.join("\0");
|
|
22393
23295
|
return patchTableRows({
|
|
22394
|
-
table,
|
|
23296
|
+
table: table2,
|
|
22395
23297
|
scanTable,
|
|
22396
23298
|
ctx,
|
|
22397
23299
|
skip,
|
|
@@ -22406,7 +23308,7 @@ function patchGfmTableRows(table, scanTable, origRows, editedRows, replica, ctx,
|
|
|
22406
23308
|
}
|
|
22407
23309
|
return cells;
|
|
22408
23310
|
},
|
|
22409
|
-
patchMatched: (oi, ei) => patchGfmRowPair(
|
|
23311
|
+
patchMatched: (oi, ei) => patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, oi, ei, ctx, skip)
|
|
22410
23312
|
});
|
|
22411
23313
|
}
|
|
22412
23314
|
function gfmRenderStable(editedRows, cols) {
|
|
@@ -22423,13 +23325,13 @@ function gfmRenderStable(editedRows, cols) {
|
|
|
22423
23325
|
if (!replica || replica.length !== editedRows.length) return false;
|
|
22424
23326
|
return replica.every((row, r) => row.length === editedRows[r].length && row.every((c, j) => c.text === editedRows[r][j]));
|
|
22425
23327
|
}
|
|
22426
|
-
function patchHtmlTable(
|
|
22427
|
-
return patchHtmlTableRaw(
|
|
23328
|
+
function patchHtmlTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
23329
|
+
return patchHtmlTableRaw(table2, scanTable, orig.raw, edited.raw, ctx, skip, 0);
|
|
22428
23330
|
}
|
|
22429
|
-
function patchHtmlTableRaw(
|
|
23331
|
+
function patchHtmlTableRaw(table2, scanTable, origRaw, editedRaw, ctx, skip, depth) {
|
|
22430
23332
|
if (depth > 8) return skip("\uC911\uCCA9\uD45C \uAE4A\uC774 \uCD08\uACFC");
|
|
22431
|
-
if (replicateTableToHtml(
|
|
22432
|
-
const replica = replicateHtmlTable(
|
|
23333
|
+
if (replicateTableToHtml(table2) !== origRaw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
23334
|
+
const replica = replicateHtmlTable(table2);
|
|
22433
23335
|
const origRows = parseHtmlTable(origRaw);
|
|
22434
23336
|
if (!origRows || origRows.length !== replica.length || origRows.some((r, i) => r.cells.length !== replica[i].cells.length || r.cells.some((c, j) => c.inner !== replica[i].cells[j].inner))) {
|
|
22435
23337
|
return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -22437,15 +23339,15 @@ function patchHtmlTableRaw(table, scanTable, origRaw, editedRaw, ctx, skip, dept
|
|
|
22437
23339
|
const editedRows = parseHtmlTable(editedRaw);
|
|
22438
23340
|
if (!editedRows) return skip("\uD3B8\uC9D1\uB41C HTML \uD45C \uD30C\uC2F1 \uC2E4\uD328");
|
|
22439
23341
|
if (editedRows.length !== replica.length) {
|
|
22440
|
-
return patchHtmlTableRows(
|
|
23342
|
+
return patchHtmlTableRows(table2, scanTable, replica, editedRows, ctx, skip, depth);
|
|
22441
23343
|
}
|
|
22442
23344
|
let applied = 0;
|
|
22443
23345
|
for (let r = 0; r < replica.length; r++) {
|
|
22444
|
-
applied += patchHtmlRowPair(
|
|
23346
|
+
applied += patchHtmlRowPair(table2, scanTable, replica, editedRows, r, r, ctx, skip, depth);
|
|
22445
23347
|
}
|
|
22446
23348
|
return applied;
|
|
22447
23349
|
}
|
|
22448
|
-
function patchHtmlRowPair(
|
|
23350
|
+
function patchHtmlRowPair(table2, scanTable, replica, editedRows, r, er, ctx, skip, depth) {
|
|
22449
23351
|
if (editedRows[er].cells.length !== replica[r].cells.length) {
|
|
22450
23352
|
skip(`\uD45C ${r + 1}\uD589 \uC140 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
|
|
22451
23353
|
return 0;
|
|
@@ -22473,23 +23375,23 @@ function patchHtmlRowPair(table, scanTable, replica, editedRows, r, er, ctx, ski
|
|
|
22473
23375
|
continue;
|
|
22474
23376
|
}
|
|
22475
23377
|
if (origTables.join("\n") !== editedTables.join("\n")) {
|
|
22476
|
-
applied += patchNestedTables(
|
|
23378
|
+
applied += patchNestedTables(table2, scanTable, oc, origTables, editedTables, ctx, skip, depth);
|
|
22477
23379
|
}
|
|
22478
23380
|
}
|
|
22479
23381
|
if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
|
|
22480
23382
|
const newLines = editedContent.lines.map((l) => unescapeGfm(l));
|
|
22481
|
-
applied += applyCellEdit(
|
|
23383
|
+
applied += applyCellEdit(table2, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
|
|
22482
23384
|
}
|
|
22483
23385
|
}
|
|
22484
23386
|
return applied;
|
|
22485
23387
|
}
|
|
22486
|
-
function patchHtmlTableRows(
|
|
22487
|
-
if (replica.length !==
|
|
23388
|
+
function patchHtmlTableRows(table2, scanTable, replica, editedRows, ctx, skip, depth) {
|
|
23389
|
+
if (replica.length !== table2.rows || replica.some((row, r) => row.cells.some((c) => c.gridR !== r))) {
|
|
22488
23390
|
return skip("\uD45C \uB80C\uB354 \uD589\uACFC \uACA9\uC790 \uD589 \uBD88\uC77C\uCE58 (\uBCD1\uD569 \uC18C\uC2E4 \uD589) \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
22489
23391
|
}
|
|
22490
23392
|
const key = (row) => row.cells.map((c) => `${c.colSpan}x${c.rowSpan}:${c.inner}`).join("\0");
|
|
22491
23393
|
return patchTableRows({
|
|
22492
|
-
table,
|
|
23394
|
+
table: table2,
|
|
22493
23395
|
scanTable,
|
|
22494
23396
|
ctx,
|
|
22495
23397
|
skip,
|
|
@@ -22497,18 +23399,18 @@ function patchHtmlTableRows(table, scanTable, replica, editedRows, ctx, skip, de
|
|
|
22497
23399
|
editedKeys: editedRows.map(key),
|
|
22498
23400
|
editedCells: (ei) => {
|
|
22499
23401
|
const cells = [];
|
|
22500
|
-
for (const
|
|
22501
|
-
const content = htmlCellInnerToLines(
|
|
23402
|
+
for (const cell2 of editedRows[ei].cells) {
|
|
23403
|
+
const content = htmlCellInnerToLines(cell2.inner);
|
|
22502
23404
|
if (content.hadNonText) return null;
|
|
22503
|
-
cells.push({ lines: content.lines.map((l) => unescapeGfm(l)), colSpan:
|
|
23405
|
+
cells.push({ lines: content.lines.map((l) => unescapeGfm(l)), colSpan: cell2.colSpan, rowSpan: cell2.rowSpan });
|
|
22504
23406
|
}
|
|
22505
23407
|
return cells;
|
|
22506
23408
|
},
|
|
22507
|
-
patchMatched: (oi, ei) => patchHtmlRowPair(
|
|
23409
|
+
patchMatched: (oi, ei) => patchHtmlRowPair(table2, scanTable, replica, editedRows, oi, ei, ctx, skip, depth)
|
|
22508
23410
|
});
|
|
22509
23411
|
}
|
|
22510
|
-
function patchNestedTables(
|
|
22511
|
-
const irCell =
|
|
23412
|
+
function patchNestedTables(table2, scanTable, oc, origTables, editedTables, ctx, skip, depth) {
|
|
23413
|
+
const irCell = table2.cells[oc.gridR]?.[oc.gridC];
|
|
22512
23414
|
const scanCell = scanTable.cellByAnchor.get(`${oc.gridR},${oc.gridC}`);
|
|
22513
23415
|
const nestedIRs = (irCell?.blocks ?? []).filter((b) => b.type === "table" && b.table).map((b) => b.table);
|
|
22514
23416
|
if (!scanCell || nestedIRs.length !== origTables.length || scanCell.tables.length !== origTables.length) {
|
|
@@ -22531,9 +23433,9 @@ function extractCellTokens(text) {
|
|
|
22531
23433
|
function stripCellTokens(text) {
|
|
22532
23434
|
return text.replace(CELL_TOKEN_RE, "");
|
|
22533
23435
|
}
|
|
22534
|
-
function patchTextChunkTable(
|
|
22535
|
-
if (
|
|
22536
|
-
const content = sanitizeText(
|
|
23436
|
+
function patchTextChunkTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
23437
|
+
if (table2.rows === 1 && table2.cols === 1) {
|
|
23438
|
+
const content = sanitizeText(table2.cells[0][0].text);
|
|
22537
23439
|
const replicaLines = content.split(/\n/).map((line) => {
|
|
22538
23440
|
const t = line.trim();
|
|
22539
23441
|
if (!t) return "";
|
|
@@ -22547,12 +23449,12 @@ function patchTextChunkTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
22547
23449
|
const unwrap = m && /^\d+\.\s/.test(unescapeGfm(m[1]));
|
|
22548
23450
|
return stripCellTokens(unescapeGfm(unwrap ? m[1] : l)).trim();
|
|
22549
23451
|
}).filter(Boolean);
|
|
22550
|
-
return applyCellEdit(
|
|
23452
|
+
return applyCellEdit(table2, scanTable, 0, 0, newLines, ctx, orig.raw, edited.raw, orig.lines.length);
|
|
22551
23453
|
}
|
|
22552
|
-
if (
|
|
23454
|
+
if (table2.cols === 1 && table2.rows >= 2) {
|
|
22553
23455
|
const replica = [];
|
|
22554
|
-
for (let r = 0; r <
|
|
22555
|
-
const line = escapeGfm(sanitizeText(
|
|
23456
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
23457
|
+
const line = escapeGfm(sanitizeText(table2.cells[r][0].text)).replace(/\n/g, " ");
|
|
22556
23458
|
if (line) replica.push({ line, gridR: r });
|
|
22557
23459
|
}
|
|
22558
23460
|
if (replica.map((x) => x.line).join("\n") !== orig.lines.join("\n")) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -22565,21 +23467,21 @@ function patchTextChunkTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
22565
23467
|
continue;
|
|
22566
23468
|
}
|
|
22567
23469
|
const newLines = [stripCellTokens(unescapeGfm(edited.lines[i])).trim()].filter(Boolean);
|
|
22568
|
-
applied += applyCellEdit(
|
|
23470
|
+
applied += applyCellEdit(table2, scanTable, replica[i].gridR, 0, newLines, ctx, replica[i].line, edited.lines[i], 1);
|
|
22569
23471
|
}
|
|
22570
23472
|
return applied;
|
|
22571
23473
|
}
|
|
22572
23474
|
return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
22573
23475
|
}
|
|
22574
|
-
function applyCellEdit(
|
|
23476
|
+
function applyCellEdit(table2, scanTable, gridR, gridC, newLines, ctx, before, after, origLineCount) {
|
|
22575
23477
|
const skip = (reason) => {
|
|
22576
23478
|
ctx.skipped.push({ reason, before: summarize(before), after: summarize(after) });
|
|
22577
23479
|
return 0;
|
|
22578
23480
|
};
|
|
22579
|
-
const
|
|
22580
|
-
if (!
|
|
22581
|
-
const irCell =
|
|
22582
|
-
const scanJoined =
|
|
23481
|
+
const cell2 = scanTable.cellByAnchor.get(`${gridR},${gridC}`);
|
|
23482
|
+
if (!cell2) return skip("\uC140 \uC88C\uD45C \uB9E4\uD551 \uC2E4\uD328 (\uBCD1\uD569 \uC601\uC5ED\uC758 \uBE48 \uCE78\uC774\uAC70\uB098 \uC88C\uD45C \uBD88\uC77C\uCE58)");
|
|
23483
|
+
const irCell = table2.cells[gridR]?.[gridC];
|
|
23484
|
+
const scanJoined = cell2.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
|
|
22583
23485
|
if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
22584
23486
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
22585
23487
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -22589,7 +23491,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
|
|
|
22589
23491
|
}
|
|
22590
23492
|
}
|
|
22591
23493
|
}
|
|
22592
|
-
const nonEmpty =
|
|
23494
|
+
const nonEmpty = cell2.paragraphs.filter((p) => normForMatch(p.text) !== "");
|
|
22593
23495
|
if (origLineCount !== void 0 && nonEmpty.length > 0 && origLineCount !== nonEmpty.length) {
|
|
22594
23496
|
return skip("\uC140 \uC904 \uACBD\uACC4 \uB9E4\uD551 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 <br>/\uBB38\uB2E8 \uB0B4 \uC904\uBC14\uAFC8) \u2014 \uBBF8\uC9C0\uC6D0");
|
|
22595
23497
|
}
|
|
@@ -22599,7 +23501,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
|
|
|
22599
23501
|
if (unstable !== void 0) 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");
|
|
22600
23502
|
if (nonEmpty.length === 0) {
|
|
22601
23503
|
if (newLines.length === 0) return 0;
|
|
22602
|
-
const target =
|
|
23504
|
+
const target = cell2.paragraphs[0];
|
|
22603
23505
|
if (!target) return skip("\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00");
|
|
22604
23506
|
const sp = buildParagraphSplices(target, newLines.join(" "), ctx.scans[target.sectionIndex]?.xml);
|
|
22605
23507
|
if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
|
|
@@ -22684,16 +23586,16 @@ function buildTableParagraphXml(rows, opts) {
|
|
|
22684
23586
|
const trElements = rows.map((row, rowIdx) => {
|
|
22685
23587
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
22686
23588
|
const isHeaderRow = rowIdx === 0;
|
|
22687
|
-
const tdElements = cells.map((
|
|
22688
|
-
const text = escapeXmlText(cellPlainText(
|
|
23589
|
+
const tdElements = cells.map((cell2, colIdx) => {
|
|
23590
|
+
const text = escapeXmlText(cellPlainText(cell2));
|
|
22689
23591
|
const cellP = `<hp:p paraPrIDRef="${cellParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}"><hp:t>${text}</hp:t></hp:run></hp:p>`;
|
|
22690
23592
|
return `<hp:tc name="" header="${isHeaderRow ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${borderFillId}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${cellP}</hp:subList><hp:cellAddr colAddr="${colIdx}" rowAddr="${rowIdx}"/><hp:cellSpan colSpan="1" rowSpan="1"/><hp:cellSz width="${cellW}" height="${cellH}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
|
|
22691
23593
|
}).join("");
|
|
22692
23594
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
22693
23595
|
}).join("");
|
|
22694
23596
|
const tblInner = `<hp:sz width="${tblW}" widthRelTo="ABSOLUTE" height="${tblH}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="0" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="0" right="0" top="0" bottom="0"/><hp:inMargin left="510" right="510" top="141" bottom="141"/>` + trElements;
|
|
22695
|
-
const
|
|
22696
|
-
return `<hp:p paraPrIDRef="${outerParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}">${
|
|
23597
|
+
const tbl2 = `<hp:tbl id="${tableId}" zOrder="0" numberingType="TABLE" pageBreak="CELL" repeatHeader="0" rowCnt="${rowCnt}" colCnt="${colCnt}" cellSpacing="0" borderFillIDRef="${borderFillId}" noShading="0">${tblInner}</hp:tbl>`;
|
|
23598
|
+
return `<hp:p paraPrIDRef="${outerParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}">${tbl2}</hp:run></hp:p>`;
|
|
22697
23599
|
}
|
|
22698
23600
|
|
|
22699
23601
|
// src/roundtrip/hwpx-entries.ts
|
|
@@ -22865,12 +23767,12 @@ function buildTableOrdinals(blocks) {
|
|
|
22865
23767
|
function resolveParagraphMappings(blocks, scans) {
|
|
22866
23768
|
const buckets = /* @__PURE__ */ new Map();
|
|
22867
23769
|
for (const scan of scans) {
|
|
22868
|
-
for (const
|
|
22869
|
-
const key = normForMatch(
|
|
23770
|
+
for (const para2 of scan.bodyParagraphs) {
|
|
23771
|
+
const key = normForMatch(para2.text);
|
|
22870
23772
|
if (!key) continue;
|
|
22871
23773
|
let list = buckets.get(key);
|
|
22872
23774
|
if (!list) buckets.set(key, list = []);
|
|
22873
|
-
list.push(
|
|
23775
|
+
list.push(para2);
|
|
22874
23776
|
}
|
|
22875
23777
|
}
|
|
22876
23778
|
const headerNorms = new Set(scans.flatMap((s) => s.headerTexts.map(normForMatch)).filter(Boolean));
|
|
@@ -22956,11 +23858,11 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
22956
23858
|
if (!ti) return skip("\uBB38\uB2E8\u2192\uD45C \uBCC0\uD658 \uBD88\uAC00 \u2014 header \uC5D4\uD2B8\uB9AC(borderFills) \uD574\uC11D \uC2E4\uD328");
|
|
22957
23859
|
const mapping = ctx.paraMap.get(orig.blockIdx);
|
|
22958
23860
|
if (!mapping?.para) return skip("\uBB38\uB2E8 \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328 (\uBA38\uB9AC\uB9D0/\uAE00\uC0C1\uC790/\uCEA1\uC158 \uC601\uC5ED) \u2014 \uD45C \uBCC0\uD658 \uBD88\uAC00");
|
|
22959
|
-
const
|
|
22960
|
-
if (
|
|
22961
|
-
const scan = ctx.scans[
|
|
23861
|
+
const para2 = mapping.para;
|
|
23862
|
+
if (para2.kind !== "body") return skip("\uBCF8\uBB38 \uC678 \uC601\uC5ED(\uD45C \uC140/\uAE00\uC0C1\uC790) \uBB38\uB2E8\uC758 \uD45C \uBCC0\uD658\uC740 \uBBF8\uC9C0\uC6D0");
|
|
23863
|
+
const scan = ctx.scans[para2.sectionIndex];
|
|
22962
23864
|
if (!scan) return skip("\uC139\uC158 \uB9E4\uD551 \uC2E4\uD328");
|
|
22963
|
-
const pEnd = findElementEnd(scan.xml,
|
|
23865
|
+
const pEnd = findElementEnd(scan.xml, para2.start);
|
|
22964
23866
|
if (pEnd < 0) return skip("\uBB38\uB2E8 \uB05D \uC704\uCE58 \uD0D0\uC0C9 \uC2E4\uD328");
|
|
22965
23867
|
const rows = parseGfmTable(edited.lines);
|
|
22966
23868
|
if (rows.length === 0 || rows.every((r) => r.length === 0)) return skip("\uD45C \uB0B4\uC6A9\uC774 \uBE44\uC5B4 \uC788\uC74C");
|
|
@@ -22970,7 +23872,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
22970
23872
|
ti.borderFillId = inj.borderFillId;
|
|
22971
23873
|
ti.headerSplices.push(...inj.headerSplices);
|
|
22972
23874
|
}
|
|
22973
|
-
const outerParaPrId = extractParaPrIdRef(scan.xml,
|
|
23875
|
+
const outerParaPrId = extractParaPrIdRef(scan.xml, para2.start) ?? 0;
|
|
22974
23876
|
const tableXml = buildTableParagraphXml(rows, {
|
|
22975
23877
|
borderFillId: ti.borderFillId,
|
|
22976
23878
|
outerParaPrId,
|
|
@@ -22978,7 +23880,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
22978
23880
|
cellCharPrId: 0,
|
|
22979
23881
|
tableId: ti.nextId++
|
|
22980
23882
|
});
|
|
22981
|
-
ctx.sectionSplices[
|
|
23883
|
+
ctx.sectionSplices[para2.sectionIndex].push({ start: para2.start, end: pEnd, replacement: tableXml });
|
|
22982
23884
|
return 1;
|
|
22983
23885
|
}
|
|
22984
23886
|
function patchParagraphUnit(block, orig, edited, ctx, skip) {
|
|
@@ -23459,7 +24361,7 @@ function scanSection(stream, sectionIndex, compressed) {
|
|
|
23459
24361
|
}
|
|
23460
24362
|
}
|
|
23461
24363
|
const kind = !ctrlSeen || !nonGso ? "body" : "other";
|
|
23462
|
-
const
|
|
24364
|
+
const para2 = {
|
|
23463
24365
|
sectionIndex,
|
|
23464
24366
|
headerIdx: i,
|
|
23465
24367
|
kind,
|
|
@@ -23471,8 +24373,8 @@ function scanSection(stream, sectionIndex, compressed) {
|
|
|
23471
24373
|
nCharsRaw: rec.data.readUInt32LE(0),
|
|
23472
24374
|
rawText: state.text
|
|
23473
24375
|
};
|
|
23474
|
-
paras.push(
|
|
23475
|
-
parasByHeader.set(i,
|
|
24376
|
+
paras.push(para2);
|
|
24377
|
+
parasByHeader.set(i, para2);
|
|
23476
24378
|
}
|
|
23477
24379
|
const tables = [];
|
|
23478
24380
|
for (let i = 0; i < records.length; i++) {
|
|
@@ -23625,13 +24527,13 @@ function msg(err) {
|
|
|
23625
24527
|
function resolveParaMappings(blocks, scans) {
|
|
23626
24528
|
const buckets = /* @__PURE__ */ new Map();
|
|
23627
24529
|
for (const scan of scans) {
|
|
23628
|
-
for (const
|
|
23629
|
-
if (
|
|
23630
|
-
const key = normForMatch(
|
|
24530
|
+
for (const para2 of scan.paras) {
|
|
24531
|
+
if (para2.kind === "other") continue;
|
|
24532
|
+
const key = normForMatch(para2.rawText);
|
|
23631
24533
|
if (!key) continue;
|
|
23632
24534
|
let list = buckets.get(key);
|
|
23633
24535
|
if (!list) buckets.set(key, list = []);
|
|
23634
|
-
list.push(
|
|
24536
|
+
list.push(para2);
|
|
23635
24537
|
}
|
|
23636
24538
|
}
|
|
23637
24539
|
const usable = (list) => list.length === 1 || list.every((p) => p.kind === "body");
|
|
@@ -23667,18 +24569,18 @@ function resolveTableMappings(blocks, scanTables) {
|
|
|
23667
24569
|
const result = /* @__PURE__ */ new Map();
|
|
23668
24570
|
let si = 0;
|
|
23669
24571
|
for (let i = 0; i < blocks.length; i++) {
|
|
23670
|
-
const
|
|
23671
|
-
if (blocks[i].type !== "table" || !
|
|
24572
|
+
const table2 = blocks[i].table;
|
|
24573
|
+
if (blocks[i].type !== "table" || !table2) continue;
|
|
23672
24574
|
const cands = [];
|
|
23673
24575
|
for (let k = si; k < scanTables.length; k++) {
|
|
23674
|
-
if (scanTables[k].rows ===
|
|
24576
|
+
if (scanTables[k].rows === table2.rows && scanTables[k].cols === table2.cols) cands.push(k);
|
|
23675
24577
|
}
|
|
23676
24578
|
if (cands.length === 0) continue;
|
|
23677
24579
|
let pick2 = cands[0];
|
|
23678
24580
|
if (cands.length > 1) {
|
|
23679
|
-
let best = tableContentScore(
|
|
24581
|
+
let best = tableContentScore(table2, scanTables[cands[0]]);
|
|
23680
24582
|
for (let ci = 1; ci < cands.length; ci++) {
|
|
23681
|
-
const sc = tableContentScore(
|
|
24583
|
+
const sc = tableContentScore(table2, scanTables[cands[ci]]);
|
|
23682
24584
|
if (sc > best) {
|
|
23683
24585
|
best = sc;
|
|
23684
24586
|
pick2 = cands[ci];
|
|
@@ -23779,14 +24681,14 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23779
24681
|
ctx.skipped.push({ reason, before: summarize(origRows[r][c]), after: summarize(editedRows[r][c]) });
|
|
23780
24682
|
return 0;
|
|
23781
24683
|
};
|
|
23782
|
-
const
|
|
23783
|
-
if (!
|
|
24684
|
+
const cell2 = scanTable.cells.get(`${r},${c}`);
|
|
24685
|
+
if (!cell2) {
|
|
23784
24686
|
cellSkip("\uBCD1\uD569 \uC601\uC5ED \uC140 \u2014 \uC575\uCEE4 \uC140\uC774 \uC544\uB2C8\uBBC0\uB85C \uBBF8\uC9C0\uC6D0");
|
|
23785
24687
|
continue;
|
|
23786
24688
|
}
|
|
23787
24689
|
const beforeParts = origRows[r][c].split(/<br\s*\/?>/i);
|
|
23788
24690
|
const afterParts = editedRows[r][c].split(/<br\s*\/?>/i);
|
|
23789
|
-
if (
|
|
24691
|
+
if (cell2.paras.length === 1) {
|
|
23790
24692
|
const beforeEach = beforeParts.map(gfmCellToPlain);
|
|
23791
24693
|
const afterEach = afterParts.map(gfmCellToPlain);
|
|
23792
24694
|
if (beforeEach.some((p) => p === null) || afterEach.some((p) => p === null)) {
|
|
@@ -23796,8 +24698,8 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23796
24698
|
const before = beforeEach.join("\n");
|
|
23797
24699
|
const after = afterEach.join("\n");
|
|
23798
24700
|
if (before === after) continue;
|
|
23799
|
-
const
|
|
23800
|
-
if (normForMatch(
|
|
24701
|
+
const para2 = cell2.paras[0];
|
|
24702
|
+
if (normForMatch(para2.rawText) !== normForMatch(before)) {
|
|
23801
24703
|
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
23802
24704
|
continue;
|
|
23803
24705
|
}
|
|
@@ -23805,14 +24707,14 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23805
24707
|
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23806
24708
|
continue;
|
|
23807
24709
|
}
|
|
23808
|
-
applied += stageParaPatch(ctx.scans[
|
|
24710
|
+
applied += stageParaPatch(ctx.scans[para2.sectionIndex], para2, after, cellSkip);
|
|
23809
24711
|
continue;
|
|
23810
24712
|
}
|
|
23811
|
-
if (beforeParts.length !==
|
|
24713
|
+
if (beforeParts.length !== cell2.paras.length || afterParts.length !== cell2.paras.length) {
|
|
23812
24714
|
cellSkip("\uC140 \uBB38\uB2E8 \uC218 \uBCC0\uACBD \u2014 \uBBF8\uC9C0\uC6D0 (\uBB38\uB2E8 \uCD94\uAC00/\uC0AD\uC81C)");
|
|
23813
24715
|
continue;
|
|
23814
24716
|
}
|
|
23815
|
-
for (let k = 0; k <
|
|
24717
|
+
for (let k = 0; k < cell2.paras.length; k++) {
|
|
23816
24718
|
const before = gfmCellToPlain(beforeParts[k]);
|
|
23817
24719
|
const after = gfmCellToPlain(afterParts[k]);
|
|
23818
24720
|
if (before === null || after === null) {
|
|
@@ -23824,8 +24726,8 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23824
24726
|
cellSkip("\uC140 \uB0B4 \uC904\uBC14\uAFC8 \uCD94\uAC00\uB294 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
23825
24727
|
break;
|
|
23826
24728
|
}
|
|
23827
|
-
const
|
|
23828
|
-
if (normForMatch(
|
|
24729
|
+
const para2 = cell2.paras[k];
|
|
24730
|
+
if (normForMatch(para2.rawText) !== normForMatch(before)) {
|
|
23829
24731
|
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
23830
24732
|
break;
|
|
23831
24733
|
}
|
|
@@ -23833,15 +24735,15 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23833
24735
|
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23834
24736
|
break;
|
|
23835
24737
|
}
|
|
23836
|
-
applied += stageParaPatch(ctx.scans[
|
|
24738
|
+
applied += stageParaPatch(ctx.scans[para2.sectionIndex], para2, after, cellSkip);
|
|
23837
24739
|
}
|
|
23838
24740
|
}
|
|
23839
24741
|
}
|
|
23840
24742
|
return applied;
|
|
23841
24743
|
}
|
|
23842
|
-
function patchHtmlCells5(
|
|
23843
|
-
if (replicateTableToHtml(
|
|
23844
|
-
const replica = replicateHtmlTable(
|
|
24744
|
+
function patchHtmlCells5(table2, scanTable, orig, edited, ctx, skip) {
|
|
24745
|
+
if (replicateTableToHtml(table2) !== orig.raw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
24746
|
+
const replica = replicateHtmlTable(table2);
|
|
23845
24747
|
const origRows = parseHtmlTable(orig.raw);
|
|
23846
24748
|
if (!origRows || origRows.length !== replica.length || origRows.some((r, i) => r.cells.length !== replica[i].cells.length || r.cells.some((c, j) => c.inner !== replica[i].cells[j].inner))) {
|
|
23847
24749
|
return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -23877,15 +24779,15 @@ function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
23877
24779
|
}
|
|
23878
24780
|
if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
|
|
23879
24781
|
const newLines = editedContent.lines.map((l) => unescapeGfm(l));
|
|
23880
|
-
applied += applyCellEdit5(
|
|
24782
|
+
applied += applyCellEdit5(table2, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
|
|
23881
24783
|
}
|
|
23882
24784
|
}
|
|
23883
24785
|
}
|
|
23884
24786
|
return applied;
|
|
23885
24787
|
}
|
|
23886
|
-
function patchTextChunk5(
|
|
23887
|
-
if (
|
|
23888
|
-
const content = sanitizeText(
|
|
24788
|
+
function patchTextChunk5(table2, scanTable, orig, edited, ctx, skip) {
|
|
24789
|
+
if (table2.rows === 1 && table2.cols === 1) {
|
|
24790
|
+
const content = sanitizeText(table2.cells[0][0].text);
|
|
23889
24791
|
const replicaLines = content.split(/\n/).map((line) => {
|
|
23890
24792
|
const t = line.trim();
|
|
23891
24793
|
if (!t) return "";
|
|
@@ -23899,12 +24801,12 @@ function patchTextChunk5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
23899
24801
|
const unwrap = m && /^\d+\.\s/.test(unescapeGfm(m[1]));
|
|
23900
24802
|
return stripCellTokens(unescapeGfm(unwrap ? m[1] : l)).trim();
|
|
23901
24803
|
}).filter(Boolean);
|
|
23902
|
-
return applyCellEdit5(
|
|
24804
|
+
return applyCellEdit5(table2, scanTable, 0, 0, newLines, ctx, orig.raw, edited.raw, orig.lines.length);
|
|
23903
24805
|
}
|
|
23904
|
-
if (
|
|
24806
|
+
if (table2.cols === 1 && table2.rows >= 2) {
|
|
23905
24807
|
const replica = [];
|
|
23906
|
-
for (let r = 0; r <
|
|
23907
|
-
const line = escapeGfm(sanitizeText(
|
|
24808
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
24809
|
+
const line = escapeGfm(sanitizeText(table2.cells[r][0].text)).replace(/\n/g, " ");
|
|
23908
24810
|
if (line) replica.push({ line, gridR: r });
|
|
23909
24811
|
}
|
|
23910
24812
|
if (replica.map((x) => x.line).join("\n") !== orig.lines.join("\n")) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -23917,21 +24819,21 @@ function patchTextChunk5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
23917
24819
|
continue;
|
|
23918
24820
|
}
|
|
23919
24821
|
const newLines = [stripCellTokens(unescapeGfm(edited.lines[i])).trim()].filter(Boolean);
|
|
23920
|
-
applied += applyCellEdit5(
|
|
24822
|
+
applied += applyCellEdit5(table2, scanTable, replica[i].gridR, 0, newLines, ctx, replica[i].line, edited.lines[i], 1);
|
|
23921
24823
|
}
|
|
23922
24824
|
return applied;
|
|
23923
24825
|
}
|
|
23924
24826
|
return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
23925
24827
|
}
|
|
23926
|
-
function applyCellEdit5(
|
|
24828
|
+
function applyCellEdit5(table2, scanTable, gridR, gridC, newLines, ctx, before, after, origLineCount) {
|
|
23927
24829
|
const skip = (reason) => {
|
|
23928
24830
|
ctx.skipped.push({ reason, before: summarize(before), after: summarize(after) });
|
|
23929
24831
|
return 0;
|
|
23930
24832
|
};
|
|
23931
|
-
const
|
|
23932
|
-
if (!
|
|
23933
|
-
const irCell =
|
|
23934
|
-
const scanJoined =
|
|
24833
|
+
const cell2 = scanTable.cells.get(`${gridR},${gridC}`);
|
|
24834
|
+
if (!cell2) return skip("\uC140 \uC88C\uD45C \uB9E4\uD551 \uC2E4\uD328 (\uBCD1\uD569 \uC601\uC5ED\uC758 \uBE48 \uCE78\uC774\uAC70\uB098 \uC88C\uD45C \uBD88\uC77C\uCE58)");
|
|
24835
|
+
const irCell = table2.cells[gridR]?.[gridC];
|
|
24836
|
+
const scanJoined = cell2.paras.map((p) => p.rawText).filter((t) => normForMatch(t)).join("\n");
|
|
23935
24837
|
if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
23936
24838
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
23937
24839
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -23941,13 +24843,13 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
|
|
|
23941
24843
|
}
|
|
23942
24844
|
}
|
|
23943
24845
|
}
|
|
23944
|
-
const nonEmpty =
|
|
24846
|
+
const nonEmpty = cell2.paras.filter((p) => normForMatch(p.rawText) !== "");
|
|
23945
24847
|
if (origLineCount !== void 0 && nonEmpty.length > 0 && origLineCount !== nonEmpty.length) {
|
|
23946
24848
|
return skip("\uC140 \uC904 \uACBD\uACC4 \uB9E4\uD551 \uBAA8\uD638 (\uBB38\uB2E8 \uB0B4 \uC904\uBC14\uAFC8) \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23947
24849
|
}
|
|
23948
24850
|
const unstable = newLines.find((l) => sanitizeText(l) !== l);
|
|
23949
24851
|
if (unstable !== void 0) 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");
|
|
23950
|
-
const targets = nonEmpty.length > 0 ? nonEmpty :
|
|
24852
|
+
const targets = nonEmpty.length > 0 ? nonEmpty : cell2.paras;
|
|
23951
24853
|
if (targets.length === 0) return skip("\uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC74C \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23952
24854
|
const assigned = [];
|
|
23953
24855
|
for (let i = 0; i < targets.length; i++) {
|
|
@@ -24097,67 +24999,67 @@ function synthesizeLineSegs(lineSegData, newRaw, startUnits) {
|
|
|
24097
24999
|
}
|
|
24098
25000
|
return { buf: Buffer.concat(segs), count: lines.length };
|
|
24099
25001
|
}
|
|
24100
|
-
function stageParaPatch(scan,
|
|
25002
|
+
function stageParaPatch(scan, para2, newPlain, skip) {
|
|
24101
25003
|
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");
|
|
24102
|
-
if (
|
|
24103
|
-
if (
|
|
24104
|
-
if (
|
|
24105
|
-
if (scan.repl.has(
|
|
25004
|
+
if (para2.textIdx === -2) return skip("\uBCF5\uC218 PARA_TEXT \uB808\uCF54\uB4DC \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
25005
|
+
if (para2.rangeTagCount > 0) return skip("\uBC94\uC704 \uD0DC\uADF8(\uD615\uAD11\uD39C/\uAD50\uC815\uBD80\uD638) \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
25006
|
+
if (para2.charShapeIdx < 0 || para2.lineSegIdx < 0) return skip("\uBB38\uB2E8 \uB808\uCF54\uB4DC \uAD6C\uC131 \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25007
|
+
if (scan.repl.has(para2.headerIdx)) return skip("\uB3D9\uC77C \uBB38\uB2E8 \uC911\uBCF5 \uC218\uC815 \u2014 \uCCAB \uC218\uC815\uB9CC \uC801\uC6A9");
|
|
24106
25008
|
if (/[\u0000-\u0009\u000b-\u001f]/.test(newPlain)) return skip("\uC0C8 \uD14D\uC2A4\uD2B8\uC5D0 \uC81C\uC5B4\uBB38\uC790 \uD3EC\uD568 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
24107
25009
|
const records = scan.records;
|
|
24108
|
-
const headerRec = records[
|
|
24109
|
-
const charShapeRec = records[
|
|
25010
|
+
const headerRec = records[para2.headerIdx];
|
|
25011
|
+
const charShapeRec = records[para2.charShapeIdx];
|
|
24110
25012
|
if (charShapeRec.data.length < 8) {
|
|
24111
25013
|
return skip("CHAR_SHAPE \uB808\uCF54\uB4DC \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
24112
25014
|
}
|
|
24113
|
-
if (
|
|
24114
|
-
const nCharsLow =
|
|
25015
|
+
if (para2.textIdx === -1) {
|
|
25016
|
+
const nCharsLow = para2.nCharsRaw & 2147483647;
|
|
24115
25017
|
if (nCharsLow > 1) return skip("PARA_TEXT \uC5C6\uB294 \uBB38\uB2E8\uC758 nChars \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
24116
25018
|
const paraEnd = nCharsLow === 1 ? Buffer.from([13, 0]) : Buffer.alloc(0);
|
|
24117
|
-
const at =
|
|
25019
|
+
const at = para2.headerIdx + 1;
|
|
24118
25020
|
const list = scan.inserts.get(at) ?? [];
|
|
24119
25021
|
list.push({ tagId: TAG_PARA_TEXT, level: headerRec.level + 1, data: Buffer.concat([Buffer.from(newPlain, "utf16le"), paraEnd]) });
|
|
24120
25022
|
scan.inserts.set(at, list);
|
|
24121
25023
|
const newHeader2 = Buffer.from(headerRec.data);
|
|
24122
|
-
newHeader2.writeUInt32LE((
|
|
25024
|
+
newHeader2.writeUInt32LE((para2.nCharsRaw & 2147483648 | newPlain.length + nCharsLow) >>> 0, 0);
|
|
24123
25025
|
const cs2 = rebuildCharShape(charShapeRec.data, 0);
|
|
24124
|
-
scan.repl.set(
|
|
25026
|
+
scan.repl.set(para2.charShapeIdx, cs2.buf);
|
|
24125
25027
|
newHeader2.writeUInt16LE(cs2.count, 12);
|
|
24126
25028
|
if (newPlain.includes("\n")) {
|
|
24127
|
-
const synth = synthesizeLineSegs(records[
|
|
25029
|
+
const synth = synthesizeLineSegs(records[para2.lineSegIdx].data, newPlain, 0);
|
|
24128
25030
|
if (synth) {
|
|
24129
|
-
scan.repl.set(
|
|
25031
|
+
scan.repl.set(para2.lineSegIdx, synth.buf);
|
|
24130
25032
|
newHeader2.writeUInt16LE(synth.count, 16);
|
|
24131
25033
|
}
|
|
24132
25034
|
}
|
|
24133
|
-
scan.repl.set(
|
|
25035
|
+
scan.repl.set(para2.headerIdx, newHeader2);
|
|
24134
25036
|
return 1;
|
|
24135
25037
|
}
|
|
24136
|
-
const textRec = records[
|
|
25038
|
+
const textRec = records[para2.textIdx];
|
|
24137
25039
|
const seg = splitParaText(textRec.data);
|
|
24138
25040
|
if (!seg) {
|
|
24139
|
-
return skip(
|
|
25041
|
+
return skip(para2.ctrlMask !== 0 ? "\uCEE8\uD2B8\uB864 \uBB38\uC790(\uD0ED/\uD544\uB4DC/\uD2B9\uC218\uACF5\uBC31 \uB4F1 \uD14D\uC2A4\uD2B8 \uC911\uAC04) \uD3EC\uD568 \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)" : "PARA_TEXT \uC7AC\uAD6C\uC131 \uBD88\uC77C\uCE58 \u2014 \uC6D0\uBB38 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0");
|
|
24140
25042
|
}
|
|
24141
|
-
if (seg.core !==
|
|
24142
|
-
const lead =
|
|
24143
|
-
const trail =
|
|
24144
|
-
const newRaw =
|
|
25043
|
+
if (seg.core !== para2.rawText) return skip("PARA_TEXT \uC7AC\uAD6C\uC131 \uBD88\uC77C\uCE58 \u2014 \uC6D0\uBB38 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0");
|
|
25044
|
+
const lead = para2.rawText.match(/^\s*/)[0];
|
|
25045
|
+
const trail = para2.rawText.match(/\s*$/)[0];
|
|
25046
|
+
const newRaw = para2.rawText.trim() === para2.rawText ? newPlain : lead + newPlain + trail;
|
|
24145
25047
|
const newText = Buffer.concat([seg.prefix, Buffer.from(newRaw, "utf16le"), seg.suffix]);
|
|
24146
|
-
scan.repl.set(
|
|
25048
|
+
scan.repl.set(para2.textIdx, newText);
|
|
24147
25049
|
const newHeader = Buffer.from(headerRec.data);
|
|
24148
25050
|
const nChars = seg.prefixUnits + newRaw.length + seg.suffixUnits;
|
|
24149
|
-
newHeader.writeUInt32LE((
|
|
25051
|
+
newHeader.writeUInt32LE((para2.nCharsRaw & 2147483648 | nChars) >>> 0, 0);
|
|
24150
25052
|
const cs = rebuildCharShape(charShapeRec.data, seg.prefixUnits);
|
|
24151
|
-
scan.repl.set(
|
|
25053
|
+
scan.repl.set(para2.charShapeIdx, cs.buf);
|
|
24152
25054
|
newHeader.writeUInt16LE(cs.count, 12);
|
|
24153
25055
|
if (newRaw.includes("\n")) {
|
|
24154
|
-
const synth = synthesizeLineSegs(records[
|
|
25056
|
+
const synth = synthesizeLineSegs(records[para2.lineSegIdx].data, newRaw, seg.prefixUnits);
|
|
24155
25057
|
if (synth) {
|
|
24156
|
-
scan.repl.set(
|
|
25058
|
+
scan.repl.set(para2.lineSegIdx, synth.buf);
|
|
24157
25059
|
newHeader.writeUInt16LE(synth.count, 16);
|
|
24158
25060
|
}
|
|
24159
25061
|
}
|
|
24160
|
-
scan.repl.set(
|
|
25062
|
+
scan.repl.set(para2.headerIdx, newHeader);
|
|
24161
25063
|
return 1;
|
|
24162
25064
|
}
|
|
24163
25065
|
|
|
@@ -24322,9 +25224,9 @@ var HwpxSession = class _HwpxSession {
|
|
|
24322
25224
|
const block = st.blocks[blockIndex];
|
|
24323
25225
|
if (!block) return void 0;
|
|
24324
25226
|
if (block.type === "paragraph" || block.type === "heading") {
|
|
24325
|
-
const
|
|
24326
|
-
if (!
|
|
24327
|
-
return { kind: "paragraph", sectionIndex:
|
|
25227
|
+
const para2 = st.paraMap.get(blockIndex)?.para;
|
|
25228
|
+
if (!para2) return void 0;
|
|
25229
|
+
return { kind: "paragraph", sectionIndex: para2.sectionIndex, xmlStart: para2.start };
|
|
24328
25230
|
}
|
|
24329
25231
|
if (block.type === "table" && block.table) {
|
|
24330
25232
|
if (st.tableOrdinals.size !== st.scanTables.length) return void 0;
|
|
@@ -24361,13 +25263,13 @@ var HwpxSession = class _HwpxSession {
|
|
|
24361
25263
|
if (!scanTable) {
|
|
24362
25264
|
return { capability: "locked", reason: "\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328" };
|
|
24363
25265
|
}
|
|
24364
|
-
const
|
|
25266
|
+
const table2 = block.table;
|
|
24365
25267
|
const cells = [];
|
|
24366
25268
|
let anyEditable = false;
|
|
24367
|
-
for (let r = 0; r <
|
|
25269
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
24368
25270
|
const row = [];
|
|
24369
|
-
for (let c = 0; c <
|
|
24370
|
-
const info = cellStaticCheck(
|
|
25271
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
25272
|
+
const info = cellStaticCheck(table2, scanTable, r, c);
|
|
24371
25273
|
if (info.editable) anyEditable = true;
|
|
24372
25274
|
row.push(info);
|
|
24373
25275
|
}
|
|
@@ -24556,12 +25458,12 @@ var HwpxSession = class _HwpxSession {
|
|
|
24556
25458
|
return 1;
|
|
24557
25459
|
}
|
|
24558
25460
|
};
|
|
24559
|
-
function cellStaticCheck(
|
|
24560
|
-
const irCell =
|
|
25461
|
+
function cellStaticCheck(table2, scanTable, r, c) {
|
|
25462
|
+
const irCell = table2.cells[r]?.[c];
|
|
24561
25463
|
if (!irCell) return { editable: false, reason: "\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16" };
|
|
24562
|
-
const
|
|
24563
|
-
if (!
|
|
24564
|
-
const scanJoined =
|
|
25464
|
+
const cell2 = scanTable.cellByAnchor.get(`${r},${c}`);
|
|
25465
|
+
if (!cell2) return { editable: false, reason: "\uBCD1\uD569 \uC601\uC5ED\uC758 \uBE48 \uCE78\uC774\uAC70\uB098 \uC88C\uD45C \uBD88\uC77C\uCE58" };
|
|
25466
|
+
const scanJoined = cell2.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
|
|
24565
25467
|
if (normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
24566
25468
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
24567
25469
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -24571,9 +25473,9 @@ function cellStaticCheck(table, scanTable, r, c) {
|
|
|
24571
25473
|
}
|
|
24572
25474
|
}
|
|
24573
25475
|
}
|
|
24574
|
-
const nonEmpty =
|
|
25476
|
+
const nonEmpty = cell2.paragraphs.filter((p) => normForMatch(p.text) !== "");
|
|
24575
25477
|
if (nonEmpty.length === 0) {
|
|
24576
|
-
if (
|
|
25478
|
+
if (cell2.paragraphs.length === 0) {
|
|
24577
25479
|
return { editable: false, reason: "\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00" };
|
|
24578
25480
|
}
|
|
24579
25481
|
return { editable: true };
|
|
@@ -24832,7 +25734,7 @@ async function parseHwp(buffer, options) {
|
|
|
24832
25734
|
async function parsePdf(buffer, options) {
|
|
24833
25735
|
let parsePdfDocument;
|
|
24834
25736
|
try {
|
|
24835
|
-
const mod = await import("./parser-
|
|
25737
|
+
const mod = await import("./parser-LHUO6UUA.js");
|
|
24836
25738
|
parsePdfDocument = mod.parsePdfDocument;
|
|
24837
25739
|
} catch {
|
|
24838
25740
|
return {
|
|
@@ -24940,6 +25842,8 @@ export {
|
|
|
24940
25842
|
compare,
|
|
24941
25843
|
diffBlocks,
|
|
24942
25844
|
hwpxToProfile,
|
|
25845
|
+
isKnownFont,
|
|
25846
|
+
unknownFontWarnings,
|
|
24943
25847
|
patchHwpx,
|
|
24944
25848
|
patchHwp,
|
|
24945
25849
|
validateHwpx,
|
|
@@ -24960,4 +25864,4 @@ export {
|
|
|
24960
25864
|
parseHwpml,
|
|
24961
25865
|
fillForm
|
|
24962
25866
|
};
|
|
24963
|
-
//# sourceMappingURL=chunk-
|
|
25867
|
+
//# sourceMappingURL=chunk-PGWAF755.js.map
|