kordoc 3.18.0 → 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/{-OUCPI6B3.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-YWIYGXLI.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-4YEZTZAR.js → chunk-DVUNWK6W.js} +8 -2
- package/dist/chunk-DVUNWK6W.js.map +1 -0
- package/dist/{chunk-5HDBLRVP.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-GIXXV52X.js → chunk-IA5UZZKV.js} +2 -2
- package/dist/chunk-IA5UZZKV.js.map +1 -0
- package/dist/{chunk-ZTUQYITH.js → chunk-JUJEKFUF.js} +6 -4
- package/dist/chunk-JUJEKFUF.js.map +1 -0
- package/dist/chunk-MOL7MDBG.js +0 -0
- package/dist/{chunk-PWHM3KAA.js → chunk-PGWAF755.js} +1613 -673
- package/dist/chunk-PGWAF755.js.map +1 -0
- package/dist/{chunk-VP34RO24.js → chunk-THZVBYHE.js} +3 -3
- package/dist/chunk-THZVBYHE.js.map +1 -0
- package/dist/{chunk-6Y4KKPC3.js → chunk-ZKG6SBHV.js} +2 -2
- package/dist/chunk-ZKG6SBHV.js.map +1 -0
- package/dist/cli.js +42 -18
- 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 +1999 -1052
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +82 -9
- package/dist/index.d.ts +82 -9
- package/dist/index.js +1772 -825
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +57 -29
- 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-S34YR2SH.cjs → parser-6TV6JKHF.cjs} +15 -15
- package/dist/parser-6TV6JKHF.cjs.map +1 -0
- package/dist/{parser-NZAE7PBE.js → parser-LHUO6UUA.js} +4 -4
- package/dist/parser-LHUO6UUA.js.map +1 -0
- package/dist/{parser-5D6BQYTX.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-2EFXBRYK.js → watch-PNXTAWDR.js} +8 -8
- package/dist/watch-PNXTAWDR.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-4YEZTZAR.js.map +0 -1
- package/dist/chunk-5HDBLRVP.cjs.map +0 -1
- package/dist/chunk-6Y4KKPC3.js.map +0 -1
- package/dist/chunk-GIXXV52X.js.map +0 -1
- package/dist/chunk-MEPHGCPQ.js.map +0 -1
- package/dist/chunk-PWHM3KAA.js.map +0 -1
- package/dist/chunk-VP34RO24.js.map +0 -1
- package/dist/chunk-YWIYGXLI.js.map +0 -1
- package/dist/chunk-ZTUQYITH.js.map +0 -1
- package/dist/parser-5D6BQYTX.js.map +0 -1
- package/dist/parser-NZAE7PBE.js.map +0 -1
- package/dist/parser-S34YR2SH.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-HRAW7ASR.js +0 -10
- package/dist/seal-CK64CXWO.js +0 -10
- package/dist/watch-2EFXBRYK.js.map +0 -1
- /package/dist/{-OUCPI6B3.js.map → -URVKBXYK.js.map} +0 -0
- /package/dist/{detect-RI2MQ33K.js.map → detect-PJZMUL2Z.js.map} +0 -0
- /package/dist/{render-HRAW7ASR.js.map → render-T5O6QHBJ.js.map} +0 -0
- /package/dist/{seal-CK64CXWO.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;
|
|
@@ -2526,7 +2535,7 @@ function crc32(bytes) {
|
|
|
2526
2535
|
}
|
|
2527
2536
|
var BI_RGB = 0;
|
|
2528
2537
|
var MAX_DIM = 32767;
|
|
2529
|
-
var MAX_PIXELS =
|
|
2538
|
+
var MAX_PIXELS = 36e6;
|
|
2530
2539
|
function bmpToPng(bmp) {
|
|
2531
2540
|
if (bmp.length < 54) return null;
|
|
2532
2541
|
if (bmp[0] !== 66 || bmp[1] !== 77) return null;
|
|
@@ -2614,7 +2623,6 @@ function encodePng(width, height, rgba) {
|
|
|
2614
2623
|
out.set(iendChunk, o);
|
|
2615
2624
|
return out;
|
|
2616
2625
|
}
|
|
2617
|
-
var MAX_INLINE_MD_BYTES = 4 * 1024 * 1024;
|
|
2618
2626
|
function escapeRegExp(s) {
|
|
2619
2627
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2620
2628
|
}
|
|
@@ -2633,8 +2641,11 @@ function inlineImagesIntoMarkdown(markdown, images, opts) {
|
|
|
2633
2641
|
}
|
|
2634
2642
|
const base64 = Buffer.from(bytes).toString("base64");
|
|
2635
2643
|
const dataUri = `data:${mime};base64,${base64}`;
|
|
2636
|
-
const
|
|
2637
|
-
|
|
2644
|
+
const name = escapeRegExp(img.filename);
|
|
2645
|
+
const mdRe = new RegExp(`!\\[image\\]\\((?:images/)?${name}\\)`, "g");
|
|
2646
|
+
out = out.replace(mdRe, () => ``);
|
|
2647
|
+
const imgTagRe = new RegExp(`(<img\\b[^>]*\\bsrc=")(?:images/)?${name}(")`, "g");
|
|
2648
|
+
out = out.replace(imgTagRe, (_m, pre, post) => `${pre}${dataUri}${post}`);
|
|
2638
2649
|
}
|
|
2639
2650
|
return out;
|
|
2640
2651
|
}
|
|
@@ -4056,8 +4067,8 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
4056
4067
|
function applyCtrlEffect(ctrl, records, ctx) {
|
|
4057
4068
|
switch (ctrl.id) {
|
|
4058
4069
|
case CTRL_TBL: {
|
|
4059
|
-
const
|
|
4060
|
-
if (
|
|
4070
|
+
const table2 = parseTableControl(ctrl, records, ctx);
|
|
4071
|
+
if (table2) ctrl.afterBlocks = [{ type: "table", table: table2, pageNumber: ctx.sectionNum }];
|
|
4061
4072
|
return;
|
|
4062
4073
|
}
|
|
4063
4074
|
case CTRL_GSO: {
|
|
@@ -4276,14 +4287,14 @@ function parseTableControl(ctrl, records, ctx) {
|
|
|
4276
4287
|
if (c.isHeader) ir.isHeader = true;
|
|
4277
4288
|
return ir;
|
|
4278
4289
|
}));
|
|
4279
|
-
const
|
|
4280
|
-
if (caption)
|
|
4281
|
-
return
|
|
4290
|
+
const table3 = { rows, cols, cells: irCells, hasHeader: rows > 1 };
|
|
4291
|
+
if (caption) table3.caption = caption;
|
|
4292
|
+
return table3;
|
|
4282
4293
|
}
|
|
4283
4294
|
const cellRows = arrangeCells(rows, cols, cells);
|
|
4284
|
-
const
|
|
4285
|
-
if (caption &&
|
|
4286
|
-
return
|
|
4295
|
+
const table2 = buildTable(cellRows);
|
|
4296
|
+
if (caption && table2.rows > 0) table2.caption = caption;
|
|
4297
|
+
return table2.rows > 0 ? table2 : null;
|
|
4287
4298
|
}
|
|
4288
4299
|
function parseCell(records, lhIdx, end, ctx) {
|
|
4289
4300
|
const rec = records[lhIdx];
|
|
@@ -4321,22 +4332,22 @@ function parseCell(records, lhIdx, end, ctx) {
|
|
|
4321
4332
|
parts.push(t);
|
|
4322
4333
|
}
|
|
4323
4334
|
}
|
|
4324
|
-
const
|
|
4325
|
-
if (hasStructure && blocks.length > 0)
|
|
4326
|
-
if (isHeader)
|
|
4327
|
-
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;
|
|
4328
4339
|
}
|
|
4329
4340
|
function arrangeCells(rows, cols, cells) {
|
|
4330
4341
|
const grid = Array.from({ length: rows }, () => Array(cols).fill(null));
|
|
4331
4342
|
const hasAddr = cells.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0);
|
|
4332
4343
|
if (hasAddr) {
|
|
4333
|
-
for (const
|
|
4334
|
-
const r =
|
|
4335
|
-
const c =
|
|
4344
|
+
for (const cell2 of cells) {
|
|
4345
|
+
const r = cell2.rowAddr ?? 0;
|
|
4346
|
+
const c = cell2.colAddr ?? 0;
|
|
4336
4347
|
if (r >= rows || c >= cols) continue;
|
|
4337
|
-
grid[r][c] =
|
|
4338
|
-
for (let dr = 0; dr <
|
|
4339
|
-
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++) {
|
|
4340
4351
|
if (dr === 0 && dc === 0) continue;
|
|
4341
4352
|
if (r + dr < rows && c + dc < cols)
|
|
4342
4353
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -4348,10 +4359,10 @@ function arrangeCells(rows, cols, cells) {
|
|
|
4348
4359
|
for (let r = 0; r < rows && cellIdx < cells.length; r++) {
|
|
4349
4360
|
for (let c = 0; c < cols && cellIdx < cells.length; c++) {
|
|
4350
4361
|
if (grid[r][c] !== null) continue;
|
|
4351
|
-
const
|
|
4352
|
-
grid[r][c] =
|
|
4353
|
-
for (let dr = 0; dr <
|
|
4354
|
-
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++) {
|
|
4355
4366
|
if (dr === 0 && dc === 0) continue;
|
|
4356
4367
|
if (r + dr < rows && c + dc < cols)
|
|
4357
4368
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -16867,7 +16878,7 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
16867
16878
|
let lastRow = -1;
|
|
16868
16879
|
for (let r = 0; r <= maxRow; r++) {
|
|
16869
16880
|
const row = grid[r];
|
|
16870
|
-
if (row && row.some((
|
|
16881
|
+
if (row && row.some((cell2) => cell2 !== "")) {
|
|
16871
16882
|
if (firstRow === -1) firstRow = r;
|
|
16872
16883
|
lastRow = r;
|
|
16873
16884
|
}
|
|
@@ -16890,9 +16901,9 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
16890
16901
|
cellRows.push(row);
|
|
16891
16902
|
}
|
|
16892
16903
|
if (cellRows.length > 0) {
|
|
16893
|
-
const
|
|
16894
|
-
if (
|
|
16895
|
-
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 });
|
|
16896
16907
|
}
|
|
16897
16908
|
}
|
|
16898
16909
|
return blocks;
|
|
@@ -17510,9 +17521,9 @@ function sheetToBlocks2(sheetName, sheet, sheetIndex) {
|
|
|
17510
17521
|
cellRows.push(row);
|
|
17511
17522
|
}
|
|
17512
17523
|
if (cellRows.length > 0) {
|
|
17513
|
-
const
|
|
17514
|
-
if (
|
|
17515
|
-
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 });
|
|
17516
17527
|
}
|
|
17517
17528
|
}
|
|
17518
17529
|
return blocks;
|
|
@@ -18258,8 +18269,8 @@ function collectTextboxParagraphs(node, inTxbx = false, out = [], depth = 0) {
|
|
|
18258
18269
|
}
|
|
18259
18270
|
return out;
|
|
18260
18271
|
}
|
|
18261
|
-
function parseTable(
|
|
18262
|
-
const trElements = getChildElements(
|
|
18272
|
+
function parseTable(tbl2, styles, numbering, footnotes, rels) {
|
|
18273
|
+
const trElements = getChildElements(tbl2, "tr");
|
|
18263
18274
|
if (trElements.length === 0) return null;
|
|
18264
18275
|
const rawRows = [];
|
|
18265
18276
|
for (const tr of trElements) {
|
|
@@ -18272,10 +18283,10 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18272
18283
|
col = Math.max(0, parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0);
|
|
18273
18284
|
}
|
|
18274
18285
|
}
|
|
18275
|
-
for (const
|
|
18286
|
+
for (const tc2 of getChildElements(tr, "tc")) {
|
|
18276
18287
|
let colSpan = 1;
|
|
18277
18288
|
let vMerge = null;
|
|
18278
|
-
const tcPrEls = getChildElements(
|
|
18289
|
+
const tcPrEls = getChildElements(tc2, "tcPr");
|
|
18279
18290
|
if (tcPrEls.length > 0) {
|
|
18280
18291
|
const gridSpanEls = getChildElements(tcPrEls[0], "gridSpan");
|
|
18281
18292
|
if (gridSpanEls.length > 0) {
|
|
@@ -18286,48 +18297,48 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18286
18297
|
vMerge = getAttr(vMergeEls[0], "val") === "restart" ? "restart" : "continue";
|
|
18287
18298
|
}
|
|
18288
18299
|
}
|
|
18289
|
-
const text = collectCellText(
|
|
18300
|
+
const text = collectCellText(tc2, styles, numbering, footnotes, rels, 0).join("\n");
|
|
18290
18301
|
row.push({ col, colSpan, vMerge, text });
|
|
18291
18302
|
col += colSpan;
|
|
18292
18303
|
}
|
|
18293
18304
|
rawRows.push(row);
|
|
18294
18305
|
}
|
|
18295
18306
|
for (let r = 0; r < rawRows.length; r++) {
|
|
18296
|
-
for (const
|
|
18297
|
-
if (
|
|
18307
|
+
for (const cell2 of rawRows[r]) {
|
|
18308
|
+
if (cell2.vMerge !== "continue" || !cell2.text) continue;
|
|
18298
18309
|
let start;
|
|
18299
18310
|
for (let pr = r - 1; pr >= 0 && !start; pr--) {
|
|
18300
|
-
start = rawRows[pr].find((pc) => pc.col ===
|
|
18311
|
+
start = rawRows[pr].find((pc) => pc.col === cell2.col && pc.vMerge !== "continue");
|
|
18301
18312
|
}
|
|
18302
18313
|
if (start) {
|
|
18303
18314
|
start.text = start.text ? `${start.text}
|
|
18304
|
-
${
|
|
18305
|
-
|
|
18315
|
+
${cell2.text}` : cell2.text;
|
|
18316
|
+
cell2.text = "";
|
|
18306
18317
|
} else {
|
|
18307
|
-
|
|
18318
|
+
cell2.vMerge = null;
|
|
18308
18319
|
}
|
|
18309
18320
|
}
|
|
18310
18321
|
}
|
|
18311
18322
|
const cellRows = rawRows.map(
|
|
18312
|
-
(row, r) => row.filter((
|
|
18323
|
+
(row, r) => row.filter((cell2) => cell2.vMerge !== "continue").map((cell2) => {
|
|
18313
18324
|
let rowSpan = 1;
|
|
18314
|
-
if (
|
|
18325
|
+
if (cell2.vMerge === "restart") {
|
|
18315
18326
|
for (let nr = r + 1; nr < rawRows.length; nr++) {
|
|
18316
|
-
if (!rawRows[nr].some((nc) => nc.col ===
|
|
18327
|
+
if (!rawRows[nr].some((nc) => nc.col === cell2.col && nc.vMerge === "continue")) break;
|
|
18317
18328
|
rowSpan++;
|
|
18318
18329
|
}
|
|
18319
18330
|
}
|
|
18320
|
-
return { text:
|
|
18331
|
+
return { text: cell2.text, colSpan: cell2.colSpan, rowSpan, colAddr: cell2.col, rowAddr: r };
|
|
18321
18332
|
})
|
|
18322
18333
|
);
|
|
18323
|
-
const
|
|
18324
|
-
if (
|
|
18325
|
-
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 };
|
|
18326
18337
|
}
|
|
18327
|
-
function collectCellText(
|
|
18338
|
+
function collectCellText(tc2, styles, numbering, footnotes, rels, depth) {
|
|
18328
18339
|
const parts = [];
|
|
18329
18340
|
if (depth > 20) return parts;
|
|
18330
|
-
for (const el of effectiveChildElements(
|
|
18341
|
+
for (const el of effectiveChildElements(tc2)) {
|
|
18331
18342
|
if (matchesLocal(el, "p")) {
|
|
18332
18343
|
const block = parseParagraph2(el, styles, numbering, footnotes, rels);
|
|
18333
18344
|
if (block?.text) parts.push(block.text);
|
|
@@ -18688,13 +18699,13 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18688
18699
|
}
|
|
18689
18700
|
if (cells.length === 0) return;
|
|
18690
18701
|
const grid = Array.from({ length: rowCount }, () => Array(colCount).fill(null));
|
|
18691
|
-
for (const
|
|
18692
|
-
const r =
|
|
18693
|
-
const c =
|
|
18702
|
+
for (const cell2 of cells) {
|
|
18703
|
+
const r = cell2.rowAddr ?? 0;
|
|
18704
|
+
const c = cell2.colAddr ?? 0;
|
|
18694
18705
|
if (isNaN(r) || isNaN(c) || r >= rowCount || c >= colCount) continue;
|
|
18695
|
-
grid[r][c] =
|
|
18696
|
-
for (let dr = 0; dr <
|
|
18697
|
-
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++) {
|
|
18698
18709
|
if (dr === 0 && dc === 0) continue;
|
|
18699
18710
|
if (r + dr < rowCount && c + dc < colCount) {
|
|
18700
18711
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -18703,14 +18714,14 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18703
18714
|
}
|
|
18704
18715
|
}
|
|
18705
18716
|
const cellRows = grid.map(
|
|
18706
|
-
(row) => row.map((
|
|
18717
|
+
(row) => row.map((cell2) => cell2 ?? { text: "", colSpan: 1, rowSpan: 1 })
|
|
18707
18718
|
);
|
|
18708
|
-
const
|
|
18719
|
+
const table2 = buildTable(cellRows);
|
|
18709
18720
|
const caption = extractShapeCaption(el);
|
|
18710
18721
|
if (caption.text && caption.before) {
|
|
18711
18722
|
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18712
18723
|
}
|
|
18713
|
-
blocks.push({ type: "table", table, pageNumber: sectionNum });
|
|
18724
|
+
blocks.push({ type: "table", table: table2, pageNumber: sectionNum });
|
|
18714
18725
|
if (caption.text && !caption.before) {
|
|
18715
18726
|
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18716
18727
|
}
|
|
@@ -19210,13 +19221,13 @@ function extractFormFields(blocks) {
|
|
|
19210
19221
|
const confidence = totalTables > 0 ? formTables / totalTables : fields.length > 0 ? 0.3 : 0;
|
|
19211
19222
|
return { fields, confidence: Math.min(confidence, 1) };
|
|
19212
19223
|
}
|
|
19213
|
-
function extractFromTable(
|
|
19224
|
+
function extractFromTable(table2) {
|
|
19214
19225
|
const fields = [];
|
|
19215
|
-
if (
|
|
19216
|
-
for (let r = 0; r <
|
|
19217
|
-
for (let c = 0; c <
|
|
19218
|
-
const labelCell =
|
|
19219
|
-
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];
|
|
19220
19231
|
if (!labelCell || !valueCell) continue;
|
|
19221
19232
|
if (isLabelCell(labelCell.text)) {
|
|
19222
19233
|
fields.push({
|
|
@@ -19229,17 +19240,17 @@ function extractFromTable(table) {
|
|
|
19229
19240
|
}
|
|
19230
19241
|
}
|
|
19231
19242
|
}
|
|
19232
|
-
if (fields.length === 0 &&
|
|
19233
|
-
const headerRow =
|
|
19234
|
-
const allLabels = headerRow.every((
|
|
19235
|
-
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();
|
|
19236
19247
|
return t.length > 0 && t.length <= 20;
|
|
19237
19248
|
});
|
|
19238
19249
|
if (allLabels) {
|
|
19239
|
-
for (let r = 1; r <
|
|
19240
|
-
for (let c = 0; c <
|
|
19250
|
+
for (let r = 1; r < table2.rows; r++) {
|
|
19251
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19241
19252
|
const label = headerRow[c]?.text.trim() ?? "";
|
|
19242
|
-
const value =
|
|
19253
|
+
const value = table2.cells[r]?.[c]?.text.trim() ?? "";
|
|
19243
19254
|
if (label && value) {
|
|
19244
19255
|
fields.push({ label, value, row: r, col: c });
|
|
19245
19256
|
}
|
|
@@ -19276,9 +19287,9 @@ function inferFieldType(label, value) {
|
|
|
19276
19287
|
if (/^[\d,.\s]+(?:원|명|건|개|회|부|매|%)$/.test(v) && /\d/.test(v)) return "amount";
|
|
19277
19288
|
if (/^\d{1,3}(?:,\d{3})+$/.test(v)) return "amount";
|
|
19278
19289
|
}
|
|
19279
|
-
const
|
|
19290
|
+
const norm2 = label.replace(/\s/g, "");
|
|
19280
19291
|
for (const [re, type] of LABEL_TYPE_RULES) {
|
|
19281
|
-
if (re.test(
|
|
19292
|
+
if (re.test(norm2)) return type;
|
|
19282
19293
|
}
|
|
19283
19294
|
return "text";
|
|
19284
19295
|
}
|
|
@@ -19329,15 +19340,15 @@ function fillFormFields(blocks, values, blockedLabels) {
|
|
|
19329
19340
|
const cursor = new ValueCursor(normalizedValues);
|
|
19330
19341
|
const allTables = collectIRTables(cloned, 0);
|
|
19331
19342
|
const patternFilledCells = /* @__PURE__ */ new Set();
|
|
19332
|
-
for (const
|
|
19333
|
-
for (let r = 0; r <
|
|
19334
|
-
for (let c = 0; c <
|
|
19335
|
-
const
|
|
19336
|
-
if (!
|
|
19337
|
-
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);
|
|
19338
19349
|
if (result) {
|
|
19339
|
-
|
|
19340
|
-
patternFilledCells.add(
|
|
19350
|
+
cell2.text = result.text;
|
|
19351
|
+
patternFilledCells.add(cell2);
|
|
19341
19352
|
for (const m of result.matches) {
|
|
19342
19353
|
filled.push({ label: m.label, value: m.value, row: r, col: c, key: m.key });
|
|
19343
19354
|
}
|
|
@@ -19345,8 +19356,8 @@ function fillFormFields(blocks, values, blockedLabels) {
|
|
|
19345
19356
|
}
|
|
19346
19357
|
}
|
|
19347
19358
|
}
|
|
19348
|
-
for (const
|
|
19349
|
-
fillTable(
|
|
19359
|
+
for (const table2 of allTables) {
|
|
19360
|
+
fillTable(table2, cursor, filled, matchedLabels, patternFilledCells, blockedLabels);
|
|
19350
19361
|
}
|
|
19351
19362
|
for (const block of cloned) {
|
|
19352
19363
|
if (block.type !== "paragraph" || !block.text) continue;
|
|
@@ -19363,44 +19374,44 @@ function collectIRTables(blocks, depth) {
|
|
|
19363
19374
|
if (block.type !== "table" || !block.table) continue;
|
|
19364
19375
|
out.push(block.table);
|
|
19365
19376
|
for (const row of block.table.cells) {
|
|
19366
|
-
for (const
|
|
19367
|
-
if (
|
|
19377
|
+
for (const cell2 of row) {
|
|
19378
|
+
if (cell2?.blocks?.length) out.push(...collectIRTables(cell2.blocks, depth + 1));
|
|
19368
19379
|
}
|
|
19369
19380
|
}
|
|
19370
19381
|
}
|
|
19371
19382
|
return out;
|
|
19372
19383
|
}
|
|
19373
|
-
function coveredPositions(
|
|
19384
|
+
function coveredPositions(table2) {
|
|
19374
19385
|
const covered = /* @__PURE__ */ new Set();
|
|
19375
|
-
for (let r = 0; r <
|
|
19376
|
-
for (let c = 0; c <
|
|
19386
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19387
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19377
19388
|
if (covered.has(`${r},${c}`)) continue;
|
|
19378
|
-
const
|
|
19379
|
-
if (!
|
|
19380
|
-
for (let dr = 0; dr <
|
|
19381
|
-
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++) {
|
|
19382
19393
|
if (dr === 0 && dc === 0) continue;
|
|
19383
|
-
if (r + dr <
|
|
19394
|
+
if (r + dr < table2.rows && c + dc < table2.cols) covered.add(`${r + dr},${c + dc}`);
|
|
19384
19395
|
}
|
|
19385
19396
|
}
|
|
19386
|
-
c +=
|
|
19397
|
+
c += cell2.colSpan - 1;
|
|
19387
19398
|
}
|
|
19388
19399
|
}
|
|
19389
19400
|
return covered;
|
|
19390
19401
|
}
|
|
19391
|
-
function fillTable(
|
|
19392
|
-
if (
|
|
19393
|
-
const covered = coveredPositions(
|
|
19394
|
-
for (let r = 0; r <
|
|
19395
|
-
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++) {
|
|
19396
19407
|
if (covered.has(`${r},${c}`)) continue;
|
|
19397
|
-
const labelCell =
|
|
19408
|
+
const labelCell = table2.cells[r][c];
|
|
19398
19409
|
if (!labelCell) continue;
|
|
19399
19410
|
if (!isLabelCell(labelCell.text)) continue;
|
|
19400
19411
|
let vc = c + labelCell.colSpan;
|
|
19401
|
-
while (vc <
|
|
19402
|
-
if (vc >=
|
|
19403
|
-
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];
|
|
19404
19415
|
if (!valueCell) continue;
|
|
19405
19416
|
if (isKeywordLabel(valueCell.text)) continue;
|
|
19406
19417
|
const normalizedCellLabel = normalizeLabel(labelCell.text);
|
|
@@ -19425,18 +19436,18 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells, blo
|
|
|
19425
19436
|
});
|
|
19426
19437
|
}
|
|
19427
19438
|
}
|
|
19428
|
-
if (
|
|
19429
|
-
const headerRow =
|
|
19430
|
-
const allLabels = headerRow.every((
|
|
19431
|
-
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();
|
|
19432
19443
|
return t.length > 0 && t.length <= 20 && isLabelCell(t);
|
|
19433
19444
|
});
|
|
19434
19445
|
if (!allLabels) return;
|
|
19435
|
-
for (let r = 1; r <
|
|
19436
|
-
for (let c = 0; c <
|
|
19446
|
+
for (let r = 1; r < table2.rows; r++) {
|
|
19447
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19437
19448
|
if (covered.has(`${r},${c}`)) continue;
|
|
19438
19449
|
const headerCell = headerRow[c];
|
|
19439
|
-
const valueCell =
|
|
19450
|
+
const valueCell = table2.cells[r]?.[c];
|
|
19440
19451
|
if (!headerCell || !valueCell) continue;
|
|
19441
19452
|
const headerLabel = normalizeLabel(headerCell.text);
|
|
19442
19453
|
if (blockedLabels?.has(headerLabel)) continue;
|
|
@@ -19507,28 +19518,28 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19507
19518
|
return l;
|
|
19508
19519
|
};
|
|
19509
19520
|
const matchText = (p) => paraTText(p, xml) ?? p.text;
|
|
19510
|
-
const cellLabelText = (
|
|
19521
|
+
const cellLabelText = (cell2) => cell2.paragraphs.filter((p) => !p.inTextbox).map((p) => matchText(p)).join("");
|
|
19511
19522
|
const allTables = [];
|
|
19512
19523
|
const collectTables = (tables, depth) => {
|
|
19513
19524
|
if (depth > 16) return;
|
|
19514
19525
|
for (const t of tables) {
|
|
19515
19526
|
allTables.push(t);
|
|
19516
19527
|
for (const row of t.rows) {
|
|
19517
|
-
for (const
|
|
19528
|
+
for (const cell2 of row) collectTables(cell2.tables, depth + 1);
|
|
19518
19529
|
}
|
|
19519
19530
|
}
|
|
19520
19531
|
};
|
|
19521
19532
|
collectTables(scan.tables, 0);
|
|
19522
19533
|
collectTables(scan.orphanTables, 0);
|
|
19523
19534
|
const patternApplied = /* @__PURE__ */ new Set();
|
|
19524
|
-
for (const
|
|
19525
|
-
for (const row of
|
|
19526
|
-
for (const
|
|
19527
|
-
for (const
|
|
19528
|
-
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);
|
|
19529
19540
|
const result = fillInCellPatterns(text, cursor, matchedLabels, blockedLabels);
|
|
19530
19541
|
if (!result) continue;
|
|
19531
|
-
const l = led(
|
|
19542
|
+
const l = led(para2);
|
|
19532
19543
|
if (l.fullText !== void 0) continue;
|
|
19533
19544
|
const newT = result.text;
|
|
19534
19545
|
let s = 0;
|
|
@@ -19540,7 +19551,7 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19540
19551
|
en--;
|
|
19541
19552
|
}
|
|
19542
19553
|
l.ranges.push({ start: s, end: eo, replacement: newT.slice(s, en) });
|
|
19543
|
-
patternApplied.add(
|
|
19554
|
+
patternApplied.add(cell2);
|
|
19544
19555
|
for (const m of result.matches) {
|
|
19545
19556
|
l.filledIdx.push(filled.length);
|
|
19546
19557
|
l.matchKeys.push(m.key);
|
|
@@ -19550,9 +19561,9 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19550
19561
|
}
|
|
19551
19562
|
}
|
|
19552
19563
|
}
|
|
19553
|
-
for (const
|
|
19554
|
-
for (let rowIdx = 0; rowIdx <
|
|
19555
|
-
const cells =
|
|
19564
|
+
for (const table2 of allTables) {
|
|
19565
|
+
for (let rowIdx = 0; rowIdx < table2.rows.length; rowIdx++) {
|
|
19566
|
+
const cells = table2.rows[rowIdx];
|
|
19556
19567
|
for (let colIdx = 0; colIdx < cells.length - 1; colIdx++) {
|
|
19557
19568
|
const labelText = cellLabelText(cells[colIdx]);
|
|
19558
19569
|
if (!isLabelCell(labelText)) continue;
|
|
@@ -19607,15 +19618,15 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19607
19618
|
}
|
|
19608
19619
|
}
|
|
19609
19620
|
}
|
|
19610
|
-
if (
|
|
19611
|
-
const headerCells =
|
|
19612
|
-
const allLabels = headerCells.length > 0 && headerCells.every((
|
|
19613
|
-
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();
|
|
19614
19625
|
return t.length > 0 && t.length <= 20 && isLabelCell(t);
|
|
19615
19626
|
});
|
|
19616
19627
|
if (allLabels) {
|
|
19617
|
-
for (let rowIdx = 1; rowIdx <
|
|
19618
|
-
const dataCells =
|
|
19628
|
+
for (let rowIdx = 1; rowIdx < table2.rows.length; rowIdx++) {
|
|
19629
|
+
const dataCells = table2.rows[rowIdx];
|
|
19619
19630
|
for (let colIdx = 0; colIdx < Math.min(headerCells.length, dataCells.length); colIdx++) {
|
|
19620
19631
|
const headerLabel = normalizeLabel(cellLabelText(headerCells[colIdx]));
|
|
19621
19632
|
if (blockedLabels?.has(headerLabel)) continue;
|
|
@@ -19649,10 +19660,10 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19649
19660
|
}
|
|
19650
19661
|
}
|
|
19651
19662
|
}
|
|
19652
|
-
for (const
|
|
19653
|
-
const existing = ledger.get(
|
|
19663
|
+
for (const para2 of [...scan.bodyParagraphs, ...scan.excludedParagraphs]) {
|
|
19664
|
+
const existing = ledger.get(para2);
|
|
19654
19665
|
if (existing?.fullText !== void 0) continue;
|
|
19655
|
-
const text = matchText(
|
|
19666
|
+
const text = matchText(para2);
|
|
19656
19667
|
for (const seg of scanInlineSegments(text)) {
|
|
19657
19668
|
const nlabel = normalizeLabel(seg.label);
|
|
19658
19669
|
if (blockedLabels?.has(nlabel)) continue;
|
|
@@ -19661,7 +19672,7 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19661
19672
|
const newValue = cursor.consume(matchKey);
|
|
19662
19673
|
if (newValue === void 0) continue;
|
|
19663
19674
|
const replacement = seg.valueStart === seg.valueEnd ? padInsertion(text, seg.valueStart, newValue) : newValue;
|
|
19664
|
-
const l = led(
|
|
19675
|
+
const l = led(para2);
|
|
19665
19676
|
l.ranges.push({ start: seg.valueStart, end: seg.valueEnd, replacement });
|
|
19666
19677
|
matchedLabels.add(matchKey);
|
|
19667
19678
|
l.filledIdx.push(filled.length);
|
|
@@ -19670,10 +19681,10 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19670
19681
|
}
|
|
19671
19682
|
}
|
|
19672
19683
|
const splices = [];
|
|
19673
|
-
for (const [
|
|
19684
|
+
for (const [para2, l] of ledger) {
|
|
19674
19685
|
let paraSplices = null;
|
|
19675
19686
|
if (l.fullText !== void 0) {
|
|
19676
|
-
paraSplices = buildParagraphSplices(
|
|
19687
|
+
paraSplices = buildParagraphSplices(para2, l.fullText, xml);
|
|
19677
19688
|
} else if (l.ranges.length > 0) {
|
|
19678
19689
|
const sorted = [...l.ranges].sort((a, b) => a.start - b.start || a.end - b.end);
|
|
19679
19690
|
const merged = [];
|
|
@@ -19682,11 +19693,11 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19682
19693
|
if (prev && r.start < prev.end) continue;
|
|
19683
19694
|
merged.push(r);
|
|
19684
19695
|
}
|
|
19685
|
-
if (paraTText(
|
|
19696
|
+
if (paraTText(para2, xml) !== null) {
|
|
19686
19697
|
const precise = [];
|
|
19687
19698
|
let ok = true;
|
|
19688
19699
|
for (const r of merged) {
|
|
19689
|
-
const sp = buildRangeSplices(
|
|
19700
|
+
const sp = buildRangeSplices(para2, xml, r.start, r.end, r.replacement);
|
|
19690
19701
|
if (!sp) {
|
|
19691
19702
|
ok = false;
|
|
19692
19703
|
break;
|
|
@@ -19694,13 +19705,13 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19694
19705
|
precise.push(...sp);
|
|
19695
19706
|
}
|
|
19696
19707
|
paraSplices = ok ? precise : null;
|
|
19697
|
-
} else if (paraTextPureT(
|
|
19698
|
-
let text =
|
|
19708
|
+
} else if (paraTextPureT(para2, xml)) {
|
|
19709
|
+
let text = para2.text;
|
|
19699
19710
|
for (let k = merged.length - 1; k >= 0; k--) {
|
|
19700
19711
|
const r = merged[k];
|
|
19701
19712
|
text = text.slice(0, r.start) + r.replacement + text.slice(r.end);
|
|
19702
19713
|
}
|
|
19703
|
-
paraSplices = buildParagraphSplices(
|
|
19714
|
+
paraSplices = buildParagraphSplices(para2, text, xml);
|
|
19704
19715
|
} else {
|
|
19705
19716
|
paraSplices = null;
|
|
19706
19717
|
}
|
|
@@ -19734,14 +19745,126 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
19734
19745
|
// src/hwpx/generator.ts
|
|
19735
19746
|
import JSZip6 from "jszip";
|
|
19736
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
|
+
|
|
19737
19857
|
// src/hwpx/gongmun.ts
|
|
19738
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;
|
|
19739
19861
|
var PRESET_DEFAULTS = {
|
|
19740
19862
|
official: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
19741
19863
|
report: { bodyPt: 15, lineSpacing: 160, numbering: "report" },
|
|
19742
19864
|
plan: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
19743
19865
|
notice: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
19744
|
-
minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" }
|
|
19866
|
+
minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" },
|
|
19867
|
+
gaejosik: { bodyPt: 15, lineSpacing: 160, numbering: "gaejosik" }
|
|
19745
19868
|
};
|
|
19746
19869
|
var PRESET_ALIAS = {
|
|
19747
19870
|
official: "official",
|
|
@@ -19759,7 +19882,12 @@ var PRESET_ALIAS = {
|
|
|
19759
19882
|
\uC54C\uB9BC: "notice",
|
|
19760
19883
|
\uC548\uB0B4: "notice",
|
|
19761
19884
|
minutes: "minutes",
|
|
19762
|
-
\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"
|
|
19763
19891
|
};
|
|
19764
19892
|
function normalizeGongmunPreset(preset) {
|
|
19765
19893
|
if (!preset) return "official";
|
|
@@ -19770,15 +19898,30 @@ function resolveGongmun(opts) {
|
|
|
19770
19898
|
const d = PRESET_DEFAULTS[preset];
|
|
19771
19899
|
const bodyPt = opts.bodyPt ?? d.bodyPt;
|
|
19772
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";
|
|
19773
19904
|
return {
|
|
19774
19905
|
preset,
|
|
19775
19906
|
bodyFont: opts.bodyFont ?? "myeongjo",
|
|
19776
19907
|
bodyHeight: Math.round(bodyPt * 100),
|
|
19777
19908
|
lineSpacing: opts.lineSpacing ?? d.lineSpacing,
|
|
19778
19909
|
numbering: opts.numbering ?? d.numbering,
|
|
19779
|
-
margins: opts.margins ?? OFFICIAL_MARGINS,
|
|
19910
|
+
margins: opts.margins ?? (gaejosik ? GAEJOSIK_MARGINS : OFFICIAL_MARGINS),
|
|
19780
19911
|
centerTitle: opts.centerTitle ?? true,
|
|
19781
|
-
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)
|
|
19782
19925
|
};
|
|
19783
19926
|
}
|
|
19784
19927
|
var HANGUL_INITIALS = [0, 2, 3, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18];
|
|
@@ -19826,7 +19969,8 @@ function markerWidth(marker, bodyHeight) {
|
|
|
19826
19969
|
for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
|
|
19827
19970
|
return Math.round(em / 1e3 * bodyHeight);
|
|
19828
19971
|
}
|
|
19829
|
-
function levelIndent(depth, bodyHeight, numbering) {
|
|
19972
|
+
function levelIndent(depth, bodyHeight, numbering, sizes = {}) {
|
|
19973
|
+
if (numbering === "gaejosik") return gaejosikLevelIndent(depth, bodyHeight, sizes);
|
|
19830
19974
|
const marker = numbering === "report" ? reportMarker(depth) : standardMarker(depth, 0);
|
|
19831
19975
|
return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, bodyHeight) };
|
|
19832
19976
|
}
|
|
@@ -19854,6 +19998,7 @@ var GongmunNumberer = class {
|
|
|
19854
19998
|
const n = this.counts[depth] ?? 0;
|
|
19855
19999
|
this.counts[depth] = n + 1;
|
|
19856
20000
|
if (suppress) return "";
|
|
20001
|
+
if (this.numbering === "gaejosik") return gaejosikMarker(depth);
|
|
19857
20002
|
return this.numbering === "report" ? reportMarker(depth) : standardMarker(depth, n);
|
|
19858
20003
|
}
|
|
19859
20004
|
reset() {
|
|
@@ -19921,27 +20066,28 @@ function headingCharPrId(level) {
|
|
|
19921
20066
|
if (level === 3) return CHAR_H3;
|
|
19922
20067
|
return CHAR_H4;
|
|
19923
20068
|
}
|
|
19924
|
-
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) {
|
|
19925
20070
|
const boldAttr = bold ? ` bold="1"` : "";
|
|
19926
20071
|
const italicAttr = italic ? ` italic="1"` : "";
|
|
19927
|
-
const effFont = bold ? 2 : fontId;
|
|
20072
|
+
const effFont = bold && !keepFontOnBold ? 2 : fontId;
|
|
20073
|
+
const boldEl = bold ? `<hh:bold/>` : "";
|
|
19928
20074
|
return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
19929
20075
|
<hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
|
|
19930
20076
|
<hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
|
|
19931
20077
|
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
19932
20078
|
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
19933
|
-
<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}
|
|
19934
20080
|
</hh:charPr>`;
|
|
19935
20081
|
}
|
|
19936
20082
|
function paraPr(id, opts = {}) {
|
|
19937
|
-
const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, keepWord = false, outlineLevel } = opts;
|
|
19938
|
-
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";
|
|
19939
20085
|
const snapGrid = keepWord ? "0" : "1";
|
|
19940
20086
|
const heading = outlineLevel !== void 0 ? `<hh:heading type="OUTLINE" idRef="0" level="${outlineLevel}"/>` : `<hh:heading type="NONE" idRef="0" level="0"/>`;
|
|
19941
20087
|
return ` <hh:paraPr id="${id}" tabPrIDRef="0" condense="0" fontLineHeight="0" snapToGrid="${snapGrid}" suppressLineNumbers="0" checked="0" textDir="AUTO">
|
|
19942
20088
|
<hh:align horizontal="${align}" vertical="BASELINE"/>
|
|
19943
20089
|
${heading}
|
|
19944
|
-
<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"/>
|
|
19945
20091
|
<hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
|
|
19946
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>
|
|
19947
20093
|
<hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
|
|
@@ -19951,7 +20097,72 @@ function paraPr(id, opts = {}) {
|
|
|
19951
20097
|
var GONGMUN_LIST_BASE = 8;
|
|
19952
20098
|
var GONGMUN_LIST_LEVELS = 8;
|
|
19953
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
|
+
}
|
|
19954
20162
|
var CHAR_VARIANT_BASE = 11;
|
|
20163
|
+
function charVariantBase(gaejosik) {
|
|
20164
|
+
return gaejosik ? CHAR_VARIANT_BASE + GJ_CHAR_COUNT : CHAR_VARIANT_BASE;
|
|
20165
|
+
}
|
|
19955
20166
|
var GONGMUN_BODY_RATIO = 95;
|
|
19956
20167
|
|
|
19957
20168
|
// src/hwpx/md-runs.ts
|
|
@@ -20165,12 +20376,12 @@ function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
|
|
|
20165
20376
|
return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
|
|
20166
20377
|
}).join("");
|
|
20167
20378
|
}
|
|
20168
|
-
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId) {
|
|
20379
|
+
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId, styleId = 0) {
|
|
20169
20380
|
if (paraPrId === PARA_CODE) {
|
|
20170
20381
|
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
|
|
20171
20382
|
}
|
|
20172
20383
|
const runs = generateRuns(text, charPrId, mapCharId);
|
|
20173
|
-
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="
|
|
20384
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="${styleId}">${runs}</hp:p>`;
|
|
20174
20385
|
}
|
|
20175
20386
|
|
|
20176
20387
|
// src/hwpx/gen-header.ts
|
|
@@ -20198,6 +20409,7 @@ function generateManifest(chartParts = []) {
|
|
|
20198
20409
|
</opf:package>`;
|
|
20199
20410
|
}
|
|
20200
20411
|
function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls = []) {
|
|
20412
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
20201
20413
|
let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
|
|
20202
20414
|
if (gongmun) {
|
|
20203
20415
|
body = gongmun.bodyHeight;
|
|
@@ -20207,26 +20419,62 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
|
|
|
20207
20419
|
h3 = body;
|
|
20208
20420
|
h4 = Math.max(body - 100, 1300);
|
|
20209
20421
|
}
|
|
20422
|
+
const bodyFont = gaejosik ? 4 : 0;
|
|
20210
20423
|
const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
|
|
20211
20424
|
const rows = [
|
|
20212
|
-
charPr(0, body, false, false,
|
|
20213
|
-
charPr(1, body, true, false,
|
|
20214
|
-
charPr(2, body, false, true,
|
|
20215
|
-
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),
|
|
20216
20429
|
charPr(4, code, false, false, 1),
|
|
20217
20430
|
charPr(5, h1, true, false, 1, theme.h1),
|
|
20218
20431
|
charPr(6, h2, true, false, 1, theme.h2),
|
|
20219
20432
|
charPr(7, h3, true, false, 1, theme.h3),
|
|
20220
20433
|
charPr(8, h4, true, false, 1, theme.h4),
|
|
20221
|
-
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false,
|
|
20222
|
-
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)
|
|
20223
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
|
+
}
|
|
20224
20472
|
for (const r of ratioVariants) {
|
|
20225
20473
|
rows.push(
|
|
20226
|
-
charPr(rows.length, body, false, false,
|
|
20227
|
-
charPr(rows.length + 1, body, true, false,
|
|
20228
|
-
charPr(rows.length + 2, body, false, true,
|
|
20229
|
-
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)
|
|
20230
20478
|
);
|
|
20231
20479
|
}
|
|
20232
20480
|
rows.push(...extraCharPrXmls);
|
|
@@ -20237,14 +20485,14 @@ ${rows.join("\n")}
|
|
|
20237
20485
|
function buildParaProperties(gongmun) {
|
|
20238
20486
|
if (!gongmun) {
|
|
20239
20487
|
const base2 = [
|
|
20240
|
-
paraPr(0),
|
|
20241
|
-
paraPr(1, { align: "LEFT", spaceBefore: 800, spaceAfter: 200, lineSpacing: 180, outlineLevel: 0 }),
|
|
20242
|
-
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: 170, outlineLevel: 1 }),
|
|
20243
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: 160, outlineLevel: 2 }),
|
|
20244
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160, outlineLevel: 3 }),
|
|
20245
|
-
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400 }),
|
|
20246
|
-
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600 }),
|
|
20247
|
-
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 })
|
|
20248
20496
|
];
|
|
20249
20497
|
return `<hh:paraProperties itemCnt="${base2.length}">
|
|
20250
20498
|
${base2.join("\n")}
|
|
@@ -20254,20 +20502,37 @@ ${base2.join("\n")}
|
|
|
20254
20502
|
const titleAlign = gongmun.centerTitle ? "CENTER" : "LEFT";
|
|
20255
20503
|
const base = [
|
|
20256
20504
|
paraPr(0, { lineSpacing: ls, keepWord: true }),
|
|
20257
|
-
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true
|
|
20258
|
-
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: ls, keepWord: true
|
|
20259
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true
|
|
20260
|
-
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 }),
|
|
20261
20509
|
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
20262
20510
|
paraPr(6, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true }),
|
|
20263
20511
|
paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
|
|
20264
20512
|
];
|
|
20265
20513
|
for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
|
|
20266
|
-
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering);
|
|
20267
|
-
const sectionGap = gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
20268
|
-
|
|
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 }));
|
|
20269
20518
|
}
|
|
20270
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
|
+
}
|
|
20271
20536
|
return `<hh:paraProperties itemCnt="${base.length}">
|
|
20272
20537
|
${base.join("\n")}
|
|
20273
20538
|
</hh:paraProperties>`;
|
|
@@ -20283,25 +20548,37 @@ ${heads}
|
|
|
20283
20548
|
</hh:numbering>
|
|
20284
20549
|
</hh:numberings>`;
|
|
20285
20550
|
}
|
|
20286
|
-
function
|
|
20287
|
-
|
|
20288
|
-
|
|
20289
|
-
|
|
20290
|
-
|
|
20291
|
-
|
|
20292
|
-
|
|
20293
|
-
|
|
20294
|
-
|
|
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">
|
|
20295
20578
|
<hh:fontface lang="HANGUL" fontCnt="3">
|
|
20296
|
-
|
|
20297
|
-
|
|
20298
|
-
|
|
20299
|
-
<hh:font id="1" face="\uD568\uCD08\uB86C\uB3CB\uC6C0" type="TTF" isEmbedded="0">
|
|
20300
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20301
|
-
</hh:font>
|
|
20302
|
-
<hh:font id="2" face="HY\uACAC\uACE0\uB515" type="TTF" isEmbedded="0">
|
|
20303
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="9" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20304
|
-
</hh:font>
|
|
20579
|
+
${fontEntry(0, bodyFace)}
|
|
20580
|
+
${fontEntry(1, "\uD568\uCD08\uB86C\uB3CB\uC6C0")}
|
|
20581
|
+
${fontEntry(2, "HY\uACAC\uACE0\uB515", 9)}
|
|
20305
20582
|
</hh:fontface>
|
|
20306
20583
|
<hh:fontface lang="LATIN" fontCnt="3">
|
|
20307
20584
|
<hh:font id="0" face="Times New Roman" type="TTF" isEmbedded="0">
|
|
@@ -20315,57 +20592,87 @@ function generateHeaderXml(theme, gongmun, ratioVariants = [], remap = null) {
|
|
|
20315
20592
|
</hh:font>
|
|
20316
20593
|
</hh:fontface>
|
|
20317
20594
|
<hh:fontface lang="HANJA" fontCnt="1">
|
|
20318
|
-
|
|
20319
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20320
|
-
</hh:font>
|
|
20595
|
+
${fontEntry(0, "\uD568\uCD08\uB86C\uBC14\uD0D5")}
|
|
20321
20596
|
</hh:fontface>
|
|
20322
20597
|
<hh:fontface lang="JAPANESE" fontCnt="1">
|
|
20323
|
-
|
|
20324
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20325
|
-
</hh:font>
|
|
20598
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
20326
20599
|
</hh:fontface>
|
|
20327
20600
|
<hh:fontface lang="OTHER" fontCnt="1">
|
|
20328
|
-
|
|
20329
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20330
|
-
</hh:font>
|
|
20601
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
20331
20602
|
</hh:fontface>
|
|
20332
20603
|
<hh:fontface lang="SYMBOL" fontCnt="1">
|
|
20333
|
-
|
|
20334
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20335
|
-
</hh:font>
|
|
20604
|
+
${fontEntry(0, "Symbol")}
|
|
20336
20605
|
</hh:fontface>
|
|
20337
20606
|
<hh:fontface lang="USER" fontCnt="1">
|
|
20338
|
-
|
|
20339
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20340
|
-
</hh:font>
|
|
20607
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
20341
20608
|
</hh:fontface>
|
|
20342
|
-
</hh:fontfaces
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20354
|
-
|
|
20355
|
-
|
|
20356
|
-
|
|
20357
|
-
|
|
20358
|
-
|
|
20359
|
-
|
|
20360
|
-
|
|
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)}
|
|
20361
20670
|
${charPropsXml}
|
|
20362
20671
|
<hh:tabProperties itemCnt="0"/>
|
|
20363
20672
|
${buildNumberings()}
|
|
20364
20673
|
<hh:bullets itemCnt="0"/>
|
|
20365
20674
|
${paraPropsXml}
|
|
20366
|
-
|
|
20367
|
-
<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>
|
|
20368
|
-
</hh:styles>
|
|
20675
|
+
${buildStyles(gongmun)}
|
|
20369
20676
|
</hh:refList>
|
|
20370
20677
|
<hh:compatibleDocument targetProgram="HWP2018"><hh:layoutCompatibility/></hh:compatibleDocument>
|
|
20371
20678
|
</hh:head>`;
|
|
@@ -20601,6 +20908,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
20601
20908
|
let contW;
|
|
20602
20909
|
if (block.type === "list_item" && gongmunList.has(i)) {
|
|
20603
20910
|
const { marker, depth } = gongmunList.get(i);
|
|
20911
|
+
if (gongmun.numbering === "gaejosik" && (depth === 0 || (block.text || "").trimStart().startsWith("\u203B"))) continue;
|
|
20604
20912
|
const content = plainRenderText(block.text || "");
|
|
20605
20913
|
text = marker ? `${marker} ${content}` : content;
|
|
20606
20914
|
const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
|
|
@@ -20609,6 +20917,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
20609
20917
|
} else if (block.type === "paragraph") {
|
|
20610
20918
|
const raw = (block.text || "").trim();
|
|
20611
20919
|
if (/^<center>[\s\S]*<\/center>$/i.test(raw)) continue;
|
|
20920
|
+
if (gongmun.numbering === "gaejosik" && raw.startsWith("\u203B")) continue;
|
|
20612
20921
|
text = plainRenderText(raw);
|
|
20613
20922
|
firstW = contW = pageW;
|
|
20614
20923
|
} else {
|
|
@@ -20622,14 +20931,15 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
20622
20931
|
}
|
|
20623
20932
|
return ratioByBlock.size > 0 ? { ratioByBlock, variants } : null;
|
|
20624
20933
|
}
|
|
20625
|
-
function variantMapper(fit, blockIdx) {
|
|
20934
|
+
function variantMapper(fit, blockIdx, base = CHAR_VARIANT_BASE) {
|
|
20626
20935
|
const r = fit.ratioByBlock.get(blockIdx);
|
|
20627
20936
|
if (r === void 0) return void 0;
|
|
20628
20937
|
const vi = fit.variants.indexOf(r);
|
|
20629
|
-
return (id) => id >= 0 && id <= 3 ?
|
|
20938
|
+
return (id) => id >= 0 && id <= 3 ? base + vi * 4 + id : id;
|
|
20630
20939
|
}
|
|
20631
20940
|
function precomputeGongmunList(blocks, gongmun) {
|
|
20632
20941
|
const result = /* @__PURE__ */ new Map();
|
|
20942
|
+
const depthOffset = gongmun.numbering === "gaejosik" && blocks.some((b) => b.type === "heading" && b.level === 3) ? 1 : 0;
|
|
20633
20943
|
let i = 0;
|
|
20634
20944
|
while (i < blocks.length) {
|
|
20635
20945
|
if (blocks[i].type !== "list_item") {
|
|
@@ -20655,7 +20965,7 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
20655
20965
|
}
|
|
20656
20966
|
break;
|
|
20657
20967
|
}
|
|
20658
|
-
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));
|
|
20659
20969
|
const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
|
|
20660
20970
|
const numberer = new GongmunNumberer(gongmun.numbering);
|
|
20661
20971
|
run.forEach((bi, k) => {
|
|
@@ -20666,6 +20976,98 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
20666
20976
|
return result;
|
|
20667
20977
|
}
|
|
20668
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
|
+
|
|
20669
21071
|
// src/diff/text-diff.ts
|
|
20670
21072
|
function similarity(a, b) {
|
|
20671
21073
|
if (a === b) return 1;
|
|
@@ -20863,8 +21265,8 @@ function summarize(text) {
|
|
|
20863
21265
|
const t = text.replace(/\s+/g, " ").trim();
|
|
20864
21266
|
return t.length > 80 ? t.slice(0, 77) + "..." : t;
|
|
20865
21267
|
}
|
|
20866
|
-
function replicateGfmTable(
|
|
20867
|
-
const { cells, rows: numRows, cols: numCols } =
|
|
21268
|
+
function replicateGfmTable(table2) {
|
|
21269
|
+
const { cells, rows: numRows, cols: numCols } = table2;
|
|
20868
21270
|
if (numRows === 0 || numCols === 0) return null;
|
|
20869
21271
|
if (numRows === 1 && numCols === 1) return null;
|
|
20870
21272
|
if (numCols === 1) return null;
|
|
@@ -20873,28 +21275,28 @@ function replicateGfmTable(table) {
|
|
|
20873
21275
|
for (let r = 0; r < numRows; r++) {
|
|
20874
21276
|
for (let c = 0; c < numCols; c++) {
|
|
20875
21277
|
if (skip.has(`${r},${c}`)) continue;
|
|
20876
|
-
const
|
|
20877
|
-
if (!
|
|
21278
|
+
const cell2 = cells[r]?.[c];
|
|
21279
|
+
if (!cell2) continue;
|
|
20878
21280
|
display[r][c] = {
|
|
20879
|
-
text: escapeGfm(sanitizeText(
|
|
21281
|
+
text: escapeGfm(sanitizeText(cell2.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
|
|
20880
21282
|
gridR: r,
|
|
20881
21283
|
gridC: c
|
|
20882
21284
|
};
|
|
20883
|
-
for (let dr = 0; dr <
|
|
20884
|
-
for (let dc = 0; dc <
|
|
21285
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
21286
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
20885
21287
|
if (dr === 0 && dc === 0) continue;
|
|
20886
21288
|
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
20887
21289
|
}
|
|
20888
21290
|
}
|
|
20889
|
-
c +=
|
|
21291
|
+
c += cell2.colSpan - 1;
|
|
20890
21292
|
}
|
|
20891
21293
|
}
|
|
20892
21294
|
const uniqueRows = [];
|
|
20893
21295
|
let pendingLabelRow = null;
|
|
20894
21296
|
for (let r = 0; r < display.length; r++) {
|
|
20895
21297
|
const row = display[r];
|
|
20896
|
-
if (row.every((
|
|
20897
|
-
const nonEmptyCols = row.filter((
|
|
21298
|
+
if (row.every((cell2) => cell2.text === "")) continue;
|
|
21299
|
+
const nonEmptyCols = row.filter((cell2) => cell2.text !== "");
|
|
20898
21300
|
const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
|
|
20899
21301
|
if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
|
|
20900
21302
|
if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
|
|
@@ -20926,9 +21328,9 @@ function parseGfmTable(lines) {
|
|
|
20926
21328
|
function unescapeGfmCell(text) {
|
|
20927
21329
|
return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\([~*])/g, "$1");
|
|
20928
21330
|
}
|
|
20929
|
-
function replicateCellInnerHtml(
|
|
20930
|
-
if (
|
|
20931
|
-
return
|
|
21331
|
+
function replicateCellInnerHtml(cell2) {
|
|
21332
|
+
if (cell2.blocks?.length) {
|
|
21333
|
+
return cell2.blocks.map((b) => {
|
|
20932
21334
|
if (b.type === "table" && b.table) {
|
|
20933
21335
|
const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
|
|
20934
21336
|
return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
|
|
@@ -20938,27 +21340,27 @@ function replicateCellInnerHtml(cell) {
|
|
|
20938
21340
|
return t ? t.replace(/\n/g, "<br>") : "";
|
|
20939
21341
|
}).filter(Boolean).join("<br>");
|
|
20940
21342
|
}
|
|
20941
|
-
return sanitizeText(
|
|
21343
|
+
return sanitizeText(cell2.text).replace(/\n/g, "<br>");
|
|
20942
21344
|
}
|
|
20943
|
-
function replicateTableToHtml(
|
|
20944
|
-
const rows = replicateHtmlTable(
|
|
21345
|
+
function replicateTableToHtml(table2) {
|
|
21346
|
+
const rows = replicateHtmlTable(table2);
|
|
20945
21347
|
const lines = ["<table>"];
|
|
20946
21348
|
for (let r = 0; r < rows.length; r++) {
|
|
20947
21349
|
const tag = rows[r].tag;
|
|
20948
|
-
const rowHtml = rows[r].cells.map((
|
|
21350
|
+
const rowHtml = rows[r].cells.map((cell2) => {
|
|
20949
21351
|
const attrs = [];
|
|
20950
|
-
if (
|
|
20951
|
-
if (
|
|
21352
|
+
if (cell2.colSpan > 1) attrs.push(`colspan="${cell2.colSpan}"`);
|
|
21353
|
+
if (cell2.rowSpan > 1) attrs.push(`rowspan="${cell2.rowSpan}"`);
|
|
20952
21354
|
const attrStr = attrs.length ? " " + attrs.join(" ") : "";
|
|
20953
|
-
return `<${tag}${attrStr}>${
|
|
21355
|
+
return `<${tag}${attrStr}>${cell2.inner}</${tag}>`;
|
|
20954
21356
|
});
|
|
20955
21357
|
if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
|
|
20956
21358
|
}
|
|
20957
21359
|
lines.push("</table>");
|
|
20958
21360
|
return lines.join("\n");
|
|
20959
21361
|
}
|
|
20960
|
-
function replicateHtmlTable(
|
|
20961
|
-
const { cells, rows: numRows, cols: numCols } =
|
|
21362
|
+
function replicateHtmlTable(table2) {
|
|
21363
|
+
const { cells, rows: numRows, cols: numCols } = table2;
|
|
20962
21364
|
const skip = /* @__PURE__ */ new Set();
|
|
20963
21365
|
const result = [];
|
|
20964
21366
|
for (let r = 0; r < numRows; r++) {
|
|
@@ -20966,18 +21368,18 @@ function replicateHtmlTable(table) {
|
|
|
20966
21368
|
const rowCells = [];
|
|
20967
21369
|
for (let c = 0; c < numCols; c++) {
|
|
20968
21370
|
if (skip.has(`${r},${c}`)) continue;
|
|
20969
|
-
const
|
|
20970
|
-
if (!
|
|
20971
|
-
for (let dr = 0; dr <
|
|
20972
|
-
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++) {
|
|
20973
21375
|
if (dr === 0 && dc === 0) continue;
|
|
20974
21376
|
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
20975
21377
|
}
|
|
20976
21378
|
}
|
|
20977
21379
|
rowCells.push({
|
|
20978
|
-
inner: replicateCellInnerHtml(
|
|
20979
|
-
colSpan:
|
|
20980
|
-
rowSpan:
|
|
21380
|
+
inner: replicateCellInnerHtml(cell2),
|
|
21381
|
+
colSpan: cell2.colSpan,
|
|
21382
|
+
rowSpan: cell2.rowSpan,
|
|
20981
21383
|
gridR: r,
|
|
20982
21384
|
gridC: c
|
|
20983
21385
|
});
|
|
@@ -21082,59 +21484,302 @@ function removeNestedTables(html) {
|
|
|
21082
21484
|
return result;
|
|
21083
21485
|
}
|
|
21084
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
|
+
|
|
21535
|
+
// src/hwpx/gen-profile.ts
|
|
21536
|
+
function normalizeAnchor(s) {
|
|
21537
|
+
return s.toLowerCase().replace(/[^\p{L}\p{N}]/gu, "").slice(0, 24);
|
|
21538
|
+
}
|
|
21539
|
+
function takeProfile(remap, rows, cols, anchor, seq) {
|
|
21540
|
+
if (!remap) return null;
|
|
21541
|
+
for (const t of remap.tables) {
|
|
21542
|
+
if (t.used) continue;
|
|
21543
|
+
if (t.rows !== rows || t.cols !== cols) continue;
|
|
21544
|
+
if (t.anchor && anchor) {
|
|
21545
|
+
if (t.anchor !== anchor) continue;
|
|
21546
|
+
} else if (t.index !== seq) {
|
|
21547
|
+
continue;
|
|
21548
|
+
}
|
|
21549
|
+
t.used = true;
|
|
21550
|
+
return t;
|
|
21551
|
+
}
|
|
21552
|
+
return null;
|
|
21553
|
+
}
|
|
21554
|
+
function parseHu(s) {
|
|
21555
|
+
if (s == null) return void 0;
|
|
21556
|
+
const n = parseInt(String(s).trim(), 10);
|
|
21557
|
+
return Number.isFinite(n) ? n : void 0;
|
|
21558
|
+
}
|
|
21559
|
+
function edgeXml(tag, d) {
|
|
21560
|
+
return d ? `<hh:${tag} type="${d.type}" width="${d.width}" color="${d.color}"/>` : `<hh:${tag} type="NONE" width="0.1 mm" color="#000000"/>`;
|
|
21561
|
+
}
|
|
21562
|
+
function borderFillDefToXml(id, def) {
|
|
21563
|
+
const fill = def.fill?.faceColor ? `<hh:fillBrush><hh:winBrush faceColor="${def.fill.faceColor}" hatchColor="#000000" alpha="0"/></hh:fillBrush>` : "";
|
|
21564
|
+
return ` <hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
21565
|
+
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
21566
|
+
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
21567
|
+
${edgeXml("leftBorder", def.leftBorder)}
|
|
21568
|
+
${edgeXml("rightBorder", def.rightBorder)}
|
|
21569
|
+
${edgeXml("topBorder", def.topBorder)}
|
|
21570
|
+
${edgeXml("bottomBorder", def.bottomBorder)}${fill ? `
|
|
21571
|
+
${fill}` : ""}
|
|
21572
|
+
</hh:borderFill>`;
|
|
21573
|
+
}
|
|
21574
|
+
var PROFILE_FONT_MAX = 2;
|
|
21575
|
+
function profileCharPrXml(id, def) {
|
|
21576
|
+
const height = parseHu(def.height_hwpunit) ?? 1e3;
|
|
21577
|
+
const color = def.textColor ?? "#000000";
|
|
21578
|
+
const rawFont = def.fontRef_hangul != null ? parseInt(def.fontRef_hangul, 10) || 0 : 0;
|
|
21579
|
+
const font = rawFont >= 0 && rawFont <= PROFILE_FONT_MAX ? rawFont : 0;
|
|
21580
|
+
const boldAttr = def.bold ? ` bold="1"` : "";
|
|
21581
|
+
const italicAttr = def.italic ? ` italic="1"` : "";
|
|
21582
|
+
const underline = def.underline ? `
|
|
21583
|
+
<hh:underline type="BOTTOM" shape="SOLID" color="${color}"/>` : "";
|
|
21584
|
+
return ` <hh:charPr id="${id}" height="${height}" textColor="${color}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
21585
|
+
<hh:fontRef hangul="${font}" latin="${font}" hanja="${font}" japanese="${font}" other="${font}" symbol="${font}" user="${font}"/>
|
|
21586
|
+
<hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
21587
|
+
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
21588
|
+
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
21589
|
+
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>${underline}
|
|
21590
|
+
</hh:charPr>`;
|
|
21591
|
+
}
|
|
21592
|
+
function buildProfileRemap(profile, charPrBase, borderFillBase = 3) {
|
|
21593
|
+
const remap = { borderFillXmls: [], charPrXmls: [], tables: [] };
|
|
21594
|
+
let bfNext = borderFillBase;
|
|
21595
|
+
let charNext = charPrBase;
|
|
21596
|
+
for (const t of profile.tables) {
|
|
21597
|
+
const localBf = {};
|
|
21598
|
+
for (const [key, def] of Object.entries(t.used_border_fills ?? {})) {
|
|
21599
|
+
const gid = bfNext++;
|
|
21600
|
+
remap.borderFillXmls.push(borderFillDefToXml(gid, def));
|
|
21601
|
+
localBf[key] = gid;
|
|
21602
|
+
}
|
|
21603
|
+
const localChar = {};
|
|
21604
|
+
for (const [key, def] of Object.entries(t.used_char_prs ?? {})) {
|
|
21605
|
+
const gid = charNext++;
|
|
21606
|
+
remap.charPrXmls.push(profileCharPrXml(gid, def));
|
|
21607
|
+
localChar[key] = gid;
|
|
21608
|
+
}
|
|
21609
|
+
let colWidths;
|
|
21610
|
+
if (t.col_widths_hwpunit && t.col_widths_hwpunit.length === t.cols) {
|
|
21611
|
+
const parsed = t.col_widths_hwpunit.map(parseHu);
|
|
21612
|
+
if (parsed.every((n) => n != null)) colWidths = parsed;
|
|
21613
|
+
}
|
|
21614
|
+
const tr = {
|
|
21615
|
+
index: t.table_index,
|
|
21616
|
+
rows: t.rows,
|
|
21617
|
+
cols: t.cols,
|
|
21618
|
+
// 재정규화 — 추출기는 정규화해 담지만 손편집된 프로필 JSON도 같은 키 공간으로
|
|
21619
|
+
anchor: t.anchor_text ? normalizeAnchor(t.anchor_text) : void 0,
|
|
21620
|
+
width: parseHu(t.width_hwpunit),
|
|
21621
|
+
colWidths,
|
|
21622
|
+
cellBf: /* @__PURE__ */ new Map(),
|
|
21623
|
+
cellChar: /* @__PURE__ */ new Map(),
|
|
21624
|
+
cellH: /* @__PURE__ */ new Map()
|
|
21625
|
+
};
|
|
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]);
|
|
21630
|
+
}
|
|
21631
|
+
if (cell2.charPrIDRef != null && cell2.charPrIDRef in localChar) {
|
|
21632
|
+
tr.cellChar.set(k, localChar[cell2.charPrIDRef]);
|
|
21633
|
+
}
|
|
21634
|
+
const h = parseHu(cell2.height_hwpunit);
|
|
21635
|
+
if (h != null) tr.cellH.set(k, h);
|
|
21636
|
+
}
|
|
21637
|
+
remap.tables.push(tr);
|
|
21638
|
+
}
|
|
21639
|
+
return remap;
|
|
21640
|
+
}
|
|
21641
|
+
|
|
21085
21642
|
// src/hwpx/gen-table.ts
|
|
21086
21643
|
var TABLE_ID_BASE = 1e3;
|
|
21087
21644
|
var tableIdCounter = TABLE_ID_BASE;
|
|
21088
21645
|
function nextTableId() {
|
|
21089
21646
|
return ++tableIdCounter;
|
|
21090
21647
|
}
|
|
21091
|
-
var
|
|
21092
|
-
function
|
|
21093
|
-
|
|
21094
|
-
|
|
21095
|
-
|
|
21648
|
+
var DATA_TABLE_INSET = 1800;
|
|
21649
|
+
function anchorOfMarkdownCell(cell2) {
|
|
21650
|
+
return normalizeAnchor(cell2.replace(/!\[[^\]]*\]\([^)]*\)/g, ""));
|
|
21651
|
+
}
|
|
21652
|
+
function anchorOfHtmlCell(inner) {
|
|
21653
|
+
const noNested = inner.replace(/<table[\s\S]*?<\/table>/gi, "");
|
|
21654
|
+
const { lines } = htmlCellInnerToLines(noNested);
|
|
21655
|
+
return normalizeAnchor(lines.join(""));
|
|
21096
21656
|
}
|
|
21097
|
-
function
|
|
21657
|
+
function profileColWidths(tp, colCnt) {
|
|
21098
21658
|
if (!tp) return null;
|
|
21099
|
-
if (tp.
|
|
21100
|
-
|
|
21101
|
-
|
|
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);
|
|
21102
21706
|
}
|
|
21103
|
-
|
|
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;
|
|
21104
21711
|
}
|
|
21105
|
-
function
|
|
21106
|
-
|
|
21107
|
-
|
|
21108
|
-
|
|
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;
|
|
21109
21723
|
}
|
|
21110
|
-
function generateTable(rows, theme,
|
|
21724
|
+
function generateTable(rows, theme, style = null, remap = null, seq = 0) {
|
|
21111
21725
|
const rowCnt = rows.length;
|
|
21112
21726
|
const colCnt = Math.max(...rows.map((r) => r.length), 1);
|
|
21113
|
-
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;
|
|
21730
|
+
const prof = takeProfile(remap, rowCnt, colCnt, anchorOfMarkdownCell(rows[0]?.[0] ?? ""), seq);
|
|
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);
|
|
21114
21741
|
const tblId = nextTableId();
|
|
21115
|
-
const
|
|
21116
|
-
const
|
|
21117
|
-
const
|
|
21118
|
-
const tblH = cellH * rowCnt;
|
|
21119
|
-
const useHeaderStyle = theme.tableHeader !== theme.body || theme.tableHeaderBold;
|
|
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);
|
|
21120
21745
|
const trElements = rows.map((row, rowIdx) => {
|
|
21121
21746
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
21122
21747
|
const isHeaderRow = rowIdx === 0;
|
|
21123
|
-
const
|
|
21124
|
-
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) => {
|
|
21125
21752
|
const k = `${rowIdx},${colIdx}`;
|
|
21126
|
-
const
|
|
21127
|
-
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);
|
|
21128
21772
|
const h = prof?.cellH.get(k) ?? cellH;
|
|
21129
|
-
|
|
21130
|
-
const p = `<hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p>`;
|
|
21131
|
-
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>`;
|
|
21132
21774
|
}).join("");
|
|
21133
21775
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
21134
21776
|
}).join("");
|
|
21777
|
+
const tblW = colWidths.reduce((a, b) => a + b, 0);
|
|
21778
|
+
const tblH = rowHeights.reduce((a, b) => a + b, 0);
|
|
21135
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;
|
|
21136
|
-
const
|
|
21137
|
-
|
|
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>`;
|
|
21138
21783
|
}
|
|
21139
21784
|
function layoutHtmlRows(rows) {
|
|
21140
21785
|
const occupied = /* @__PURE__ */ new Set();
|
|
@@ -21142,11 +21787,11 @@ function layoutHtmlRows(rows) {
|
|
|
21142
21787
|
let colCnt = 0;
|
|
21143
21788
|
for (let r = 0; r < rows.length; r++) {
|
|
21144
21789
|
let c = 0;
|
|
21145
|
-
for (const
|
|
21790
|
+
for (const cell2 of rows[r].cells) {
|
|
21146
21791
|
while (occupied.has(`${r},${c}`)) c++;
|
|
21147
|
-
const colSpan = Math.max(1,
|
|
21148
|
-
const rowSpan = Math.max(1,
|
|
21149
|
-
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" });
|
|
21150
21795
|
for (let dr = 0; dr < rowSpan; dr++) {
|
|
21151
21796
|
for (let dc = 0; dc < colSpan; dc++) occupied.add(`${r + dr},${c + dc}`);
|
|
21152
21797
|
}
|
|
@@ -21159,49 +21804,135 @@ function layoutHtmlRows(rows) {
|
|
|
21159
21804
|
function unescapeHtml(s) {
|
|
21160
21805
|
return s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
21161
21806
|
}
|
|
21162
|
-
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3,
|
|
21807
|
+
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, remap = null, seq = 0) {
|
|
21163
21808
|
const rows = parseHtmlTable(rawHtml);
|
|
21164
21809
|
if (!rows || rows.length === 0) return null;
|
|
21165
21810
|
const { placed, rowCnt, colCnt } = layoutHtmlRows(rows);
|
|
21166
21811
|
if (rowCnt === 0 || colCnt === 0) return null;
|
|
21167
|
-
const
|
|
21812
|
+
const measureH = style?.charHeight ?? 1e3;
|
|
21813
|
+
const first = placed.find((p) => p.r === 0 && p.c === 0) ?? placed[0];
|
|
21814
|
+
const prof = takeProfile(remap, rowCnt, colCnt, first ? anchorOfHtmlCell(first.inner) : "", seq);
|
|
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);
|
|
21168
21830
|
const tblId = nextTableId();
|
|
21169
|
-
const
|
|
21170
|
-
const
|
|
21171
|
-
const
|
|
21172
|
-
|
|
21173
|
-
|
|
21174
|
-
const tcXmls = placed.map((
|
|
21175
|
-
const k = `${
|
|
21176
|
-
const
|
|
21177
|
-
const
|
|
21178
|
-
const
|
|
21179
|
-
const
|
|
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];
|
|
21180
21846
|
const paras = lines.map(
|
|
21181
|
-
(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>`
|
|
21182
21848
|
);
|
|
21183
|
-
const cellW = spanW(cell.c, cell.colSpan);
|
|
21184
21849
|
let nestedH = 0;
|
|
21185
|
-
for (const nested of extractTopLevelTables(
|
|
21186
|
-
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);
|
|
21187
21853
|
if (nestedXml) {
|
|
21188
21854
|
paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${nestedXml}</hp:run></hp:p>`);
|
|
21189
21855
|
nestedH += (nested.match(/<tr[\s>]/gi) ?? []).length * cellH + 300;
|
|
21190
21856
|
}
|
|
21191
21857
|
}
|
|
21192
21858
|
if (paras.length === 0) {
|
|
21193
|
-
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>`);
|
|
21194
21860
|
}
|
|
21195
|
-
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);
|
|
21196
21862
|
const cellHeight = Math.max(prof?.cellH.get(k) ?? 0, contentH);
|
|
21197
|
-
|
|
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>`;
|
|
21198
21874
|
});
|
|
21199
21875
|
const trXmls = [];
|
|
21200
21876
|
for (let r = 0; r < rowCnt; r++) {
|
|
21201
21877
|
const rowTcs = tcXmls.filter((_, i) => placed[i].r === r);
|
|
21202
21878
|
trXmls.push(`<hp:tr>${rowTcs.join("")}</hp:tr>`);
|
|
21203
21879
|
}
|
|
21204
|
-
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>`;
|
|
21205
21936
|
}
|
|
21206
21937
|
|
|
21207
21938
|
// src/hwpx/equation-generate.ts
|
|
@@ -21491,14 +22222,76 @@ function generateSecPr(gongmun) {
|
|
|
21491
22222
|
header: 0,
|
|
21492
22223
|
footer: 0
|
|
21493
22224
|
} : { top: 8504, bottom: 4252, left: 5670, right: 4252, header: 2835, footer: 2835 };
|
|
21494
|
-
|
|
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;
|
|
21495
22231
|
}
|
|
21496
|
-
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) {
|
|
21497
22233
|
const paraXmls = [];
|
|
21498
22234
|
let isFirst = true;
|
|
21499
22235
|
let tableSeq = 0;
|
|
21500
22236
|
const orderedCounters = {};
|
|
21501
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
|
+
}
|
|
21502
22295
|
for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
|
|
21503
22296
|
const block = blocks[blockIdx];
|
|
21504
22297
|
let xml = "";
|
|
@@ -21510,17 +22303,47 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21510
22303
|
}
|
|
21511
22304
|
switch (block.type) {
|
|
21512
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
|
+
}
|
|
21513
22328
|
const pId = headingParaPrId(block.level || 1);
|
|
21514
22329
|
const cId = headingCharPrId(block.level || 1);
|
|
21515
|
-
|
|
22330
|
+
const styleId = gongmun ? Math.min(block.level || 1, 4) : 0;
|
|
22331
|
+
xml = generateParagraph(block.text || "", pId, cId, void 0, styleId);
|
|
21516
22332
|
break;
|
|
21517
22333
|
}
|
|
21518
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
|
+
}
|
|
21519
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());
|
|
21520
22341
|
if (ctr) {
|
|
21521
22342
|
xml = generateParagraph(ctr[1].trim(), GONGMUN_CENTER);
|
|
22343
|
+
} else if (rgt) {
|
|
22344
|
+
xml = generateParagraph(rgt[1].trim(), GONGMUN_RIGHT);
|
|
21522
22345
|
} else {
|
|
21523
|
-
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);
|
|
21524
22347
|
}
|
|
21525
22348
|
break;
|
|
21526
22349
|
}
|
|
@@ -21553,22 +22376,37 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21553
22376
|
xml = generateEquationParagraph(block.text || "", blockIdx);
|
|
21554
22377
|
break;
|
|
21555
22378
|
}
|
|
21556
|
-
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
|
+
}
|
|
21557
22385
|
xml = generateParagraph(
|
|
21558
22386
|
block.text || "",
|
|
21559
22387
|
PARA_QUOTE,
|
|
21560
22388
|
theme.hasQuoteOption ? CHAR_QUOTE : CHAR_NORMAL
|
|
21561
22389
|
);
|
|
21562
22390
|
break;
|
|
22391
|
+
}
|
|
21563
22392
|
case "list_item": {
|
|
21564
22393
|
if (gongmun && gongmunList) {
|
|
21565
22394
|
const info = gongmunList.get(blockIdx);
|
|
21566
22395
|
const depth = info?.depth ?? 0;
|
|
21567
22396
|
const marker2 = info?.marker ?? "";
|
|
21568
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
|
+
}
|
|
21569
22402
|
const text = marker2 ? `${marker2} ${content}` : content;
|
|
21570
|
-
|
|
21571
|
-
|
|
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);
|
|
21572
22410
|
break;
|
|
21573
22411
|
}
|
|
21574
22412
|
const indent = block.indent || 0;
|
|
@@ -21595,7 +22433,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21595
22433
|
break;
|
|
21596
22434
|
}
|
|
21597
22435
|
case "hr":
|
|
21598
|
-
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>`;
|
|
21599
22437
|
break;
|
|
21600
22438
|
case "table":
|
|
21601
22439
|
if (block.rows) {
|
|
@@ -21604,20 +22442,19 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21604
22442
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
21605
22443
|
isFirst = false;
|
|
21606
22444
|
}
|
|
21607
|
-
xml = generateTable(block.rows, theme, remap
|
|
21608
|
-
tableSeq++;
|
|
22445
|
+
xml = generateTable(block.rows, theme, tableStyle, remap, tableSeq++);
|
|
21609
22446
|
}
|
|
21610
22447
|
break;
|
|
21611
22448
|
case "html_table": {
|
|
21612
|
-
const
|
|
21613
|
-
|
|
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) {
|
|
21614
22452
|
if (isFirst) {
|
|
21615
22453
|
const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
|
|
21616
22454
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
21617
22455
|
isFirst = false;
|
|
21618
22456
|
}
|
|
21619
|
-
xml = `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${
|
|
21620
|
-
tableSeq++;
|
|
22457
|
+
xml = `<hp:p paraPrIDRef="${tableStyle && bfReg ? GONGMUN_RIGHT : 0}" styleIDRef="0"><hp:run charPrIDRef="0">${tbl2}</hp:run></hp:p>`;
|
|
21621
22458
|
} else {
|
|
21622
22459
|
const plain = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
21623
22460
|
xml = plain ? generateParagraph(plain) : "";
|
|
@@ -21633,8 +22470,20 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21633
22470
|
);
|
|
21634
22471
|
isFirst = false;
|
|
21635
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
|
+
}
|
|
21636
22481
|
paraXmls.push(xml);
|
|
21637
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
|
+
}
|
|
21638
22487
|
if (paraXmls.length === 0) {
|
|
21639
22488
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run></hp:p>`);
|
|
21640
22489
|
}
|
|
@@ -21644,108 +22493,31 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21644
22493
|
</hs:sec>`;
|
|
21645
22494
|
}
|
|
21646
22495
|
|
|
21647
|
-
// src/hwpx/gen-profile.ts
|
|
21648
|
-
function parseHu(s) {
|
|
21649
|
-
if (s == null) return void 0;
|
|
21650
|
-
const n = parseInt(String(s).trim(), 10);
|
|
21651
|
-
return Number.isFinite(n) ? n : void 0;
|
|
21652
|
-
}
|
|
21653
|
-
function edgeXml(tag, d) {
|
|
21654
|
-
return d ? `<hh:${tag} type="${d.type}" width="${d.width}" color="${d.color}"/>` : `<hh:${tag} type="NONE" width="0.1 mm" color="#000000"/>`;
|
|
21655
|
-
}
|
|
21656
|
-
function borderFillDefToXml(id, def) {
|
|
21657
|
-
const fill = def.fill?.faceColor ? `<hh:fillBrush><hh:winBrush faceColor="${def.fill.faceColor}" hatchColor="#000000" alpha="0"/></hh:fillBrush>` : "";
|
|
21658
|
-
return ` <hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
21659
|
-
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
21660
|
-
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
21661
|
-
${edgeXml("leftBorder", def.leftBorder)}
|
|
21662
|
-
${edgeXml("rightBorder", def.rightBorder)}
|
|
21663
|
-
${edgeXml("topBorder", def.topBorder)}
|
|
21664
|
-
${edgeXml("bottomBorder", def.bottomBorder)}${fill ? `
|
|
21665
|
-
${fill}` : ""}
|
|
21666
|
-
</hh:borderFill>`;
|
|
21667
|
-
}
|
|
21668
|
-
function profileCharPrXml(id, def) {
|
|
21669
|
-
const height = parseHu(def.height_hwpunit) ?? 1e3;
|
|
21670
|
-
const color = def.textColor ?? "#000000";
|
|
21671
|
-
const font = def.fontRef_hangul != null ? parseInt(def.fontRef_hangul, 10) || 0 : 0;
|
|
21672
|
-
const boldAttr = def.bold ? ` bold="1"` : "";
|
|
21673
|
-
const italicAttr = def.italic ? ` italic="1"` : "";
|
|
21674
|
-
const underline = def.underline ? `
|
|
21675
|
-
<hh:underline type="BOTTOM" shape="SOLID" color="${color}"/>` : "";
|
|
21676
|
-
return ` <hh:charPr id="${id}" height="${height}" textColor="${color}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
21677
|
-
<hh:fontRef hangul="${font}" latin="${font}" hanja="${font}" japanese="${font}" other="${font}" symbol="${font}" user="${font}"/>
|
|
21678
|
-
<hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
21679
|
-
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
21680
|
-
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
21681
|
-
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>${underline}
|
|
21682
|
-
</hh:charPr>`;
|
|
21683
|
-
}
|
|
21684
|
-
function buildProfileRemap(profile, charPrBase, borderFillBase = 3) {
|
|
21685
|
-
const remap = { borderFillXmls: [], charPrXmls: [], tables: /* @__PURE__ */ new Map() };
|
|
21686
|
-
let bfNext = borderFillBase;
|
|
21687
|
-
let charNext = charPrBase;
|
|
21688
|
-
for (const t of profile.tables) {
|
|
21689
|
-
const localBf = {};
|
|
21690
|
-
for (const [key, def] of Object.entries(t.used_border_fills ?? {})) {
|
|
21691
|
-
const gid = bfNext++;
|
|
21692
|
-
remap.borderFillXmls.push(borderFillDefToXml(gid, def));
|
|
21693
|
-
localBf[key] = gid;
|
|
21694
|
-
}
|
|
21695
|
-
const localChar = {};
|
|
21696
|
-
for (const [key, def] of Object.entries(t.used_char_prs ?? {})) {
|
|
21697
|
-
const gid = charNext++;
|
|
21698
|
-
remap.charPrXmls.push(profileCharPrXml(gid, def));
|
|
21699
|
-
localChar[key] = gid;
|
|
21700
|
-
}
|
|
21701
|
-
let colWidths;
|
|
21702
|
-
if (t.col_widths_hwpunit && t.col_widths_hwpunit.length === t.cols) {
|
|
21703
|
-
const parsed = t.col_widths_hwpunit.map(parseHu);
|
|
21704
|
-
if (parsed.every((n) => n != null)) colWidths = parsed;
|
|
21705
|
-
}
|
|
21706
|
-
const tr = {
|
|
21707
|
-
rows: t.rows,
|
|
21708
|
-
cols: t.cols,
|
|
21709
|
-
width: parseHu(t.width_hwpunit),
|
|
21710
|
-
colWidths,
|
|
21711
|
-
cellBf: /* @__PURE__ */ new Map(),
|
|
21712
|
-
cellChar: /* @__PURE__ */ new Map(),
|
|
21713
|
-
cellH: /* @__PURE__ */ new Map()
|
|
21714
|
-
};
|
|
21715
|
-
for (const cell of t.cells) {
|
|
21716
|
-
const k = `${cell.row},${cell.col}`;
|
|
21717
|
-
if (cell.borderFillIDRef != null && cell.borderFillIDRef in localBf) {
|
|
21718
|
-
tr.cellBf.set(k, localBf[cell.borderFillIDRef]);
|
|
21719
|
-
}
|
|
21720
|
-
if (cell.charPrIDRef != null && cell.charPrIDRef in localChar) {
|
|
21721
|
-
tr.cellChar.set(k, localChar[cell.charPrIDRef]);
|
|
21722
|
-
}
|
|
21723
|
-
const h = parseHu(cell.height_hwpunit);
|
|
21724
|
-
if (h != null) tr.cellH.set(k, h);
|
|
21725
|
-
}
|
|
21726
|
-
remap.tables.set(t.table_index, tr);
|
|
21727
|
-
}
|
|
21728
|
-
return remap;
|
|
21729
|
-
}
|
|
21730
|
-
function profileCharPrBase(ratioVariantCount) {
|
|
21731
|
-
return CHAR_VARIANT_BASE + ratioVariantCount * 4;
|
|
21732
|
-
}
|
|
21733
|
-
|
|
21734
22496
|
// src/hwpx/generator.ts
|
|
21735
22497
|
async function markdownToHwpx(markdown, options) {
|
|
21736
22498
|
const theme = resolveTheme(options?.theme);
|
|
21737
22499
|
const gongmun = options?.gongmun ? resolveGongmun(options.gongmun) : null;
|
|
22500
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
21738
22501
|
const blocks = parseMarkdownToBlocks(markdown);
|
|
21739
22502
|
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
21740
22503
|
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
21741
|
-
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;
|
|
21742
22507
|
const chartParts = [];
|
|
21743
|
-
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, remap);
|
|
22508
|
+
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap);
|
|
22509
|
+
if (remap && remap.tables.length > 0) {
|
|
22510
|
+
const unused = remap.tables.filter((t) => !t.used).length;
|
|
22511
|
+
if (unused === remap.tables.length) {
|
|
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)`);
|
|
22513
|
+
}
|
|
22514
|
+
}
|
|
22515
|
+
const extraBorderFills = [...remap?.borderFillXmls ?? [], ...bfReg?.emit() ?? []];
|
|
21744
22516
|
const zip = new JSZip6();
|
|
21745
22517
|
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
21746
22518
|
zip.file("META-INF/container.xml", generateContainerXml());
|
|
21747
22519
|
zip.file("Contents/content.hpf", generateManifest(chartParts));
|
|
21748
|
-
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 ?? []));
|
|
21749
22521
|
zip.file("Contents/section0.xml", sectionXml);
|
|
21750
22522
|
for (const part of chartParts) zip.file(part.name, part.xml);
|
|
21751
22523
|
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
@@ -21944,8 +22716,8 @@ function parseCharPrs(headerDoc) {
|
|
|
21944
22716
|
}
|
|
21945
22717
|
return map;
|
|
21946
22718
|
}
|
|
21947
|
-
function isTopLevelTable(
|
|
21948
|
-
let p =
|
|
22719
|
+
function isTopLevelTable(tbl2) {
|
|
22720
|
+
let p = tbl2.parentNode;
|
|
21949
22721
|
while (p) {
|
|
21950
22722
|
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
21951
22723
|
if (tag === "tbl") return false;
|
|
@@ -21958,57 +22730,61 @@ function num(s) {
|
|
|
21958
22730
|
const n = parseInt(s, 10);
|
|
21959
22731
|
return Number.isFinite(n) ? n : void 0;
|
|
21960
22732
|
}
|
|
21961
|
-
function parseTable3(
|
|
21962
|
-
const rows = num(
|
|
21963
|
-
const cols = num(
|
|
21964
|
-
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");
|
|
21965
22737
|
const width = sz?.getAttribute("width") || void 0;
|
|
21966
22738
|
const cells = [];
|
|
21967
22739
|
const usedBf = /* @__PURE__ */ new Set();
|
|
21968
22740
|
const usedCp = /* @__PURE__ */ new Set();
|
|
21969
22741
|
const colWidths = new Array(cols).fill(void 0);
|
|
21970
|
-
|
|
21971
|
-
|
|
21972
|
-
|
|
21973
|
-
const
|
|
21974
|
-
const
|
|
22742
|
+
let anchorText = "";
|
|
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");
|
|
21975
22748
|
const row = num(addr?.getAttribute("rowAddr")) ?? 0;
|
|
21976
22749
|
const col = num(addr?.getAttribute("colAddr")) ?? 0;
|
|
22750
|
+
if (row === 0 && col === 0 && !anchorText) anchorText = directCellText(tc2);
|
|
21977
22751
|
const colSpan = num(span?.getAttribute("colSpan")) ?? 1;
|
|
21978
22752
|
const rowSpan = num(span?.getAttribute("rowSpan")) ?? 1;
|
|
21979
|
-
const bfId =
|
|
21980
|
-
const cpId = firstRunCharPr(
|
|
21981
|
-
const
|
|
22753
|
+
const bfId = tc2.getAttribute("borderFillIDRef") || void 0;
|
|
22754
|
+
const cpId = firstRunCharPr(tc2);
|
|
22755
|
+
const cell2 = { row, col, rowSpan, colSpan };
|
|
21982
22756
|
const w = csz?.getAttribute("width");
|
|
21983
22757
|
const hh = csz?.getAttribute("height");
|
|
21984
|
-
if (w)
|
|
21985
|
-
if (hh)
|
|
22758
|
+
if (w) cell2.width_hwpunit = w;
|
|
22759
|
+
if (hh) cell2.height_hwpunit = hh;
|
|
21986
22760
|
if (bfId) {
|
|
21987
|
-
|
|
22761
|
+
cell2.borderFillIDRef = bfId;
|
|
21988
22762
|
usedBf.add(bfId);
|
|
21989
22763
|
}
|
|
21990
22764
|
if (cpId) {
|
|
21991
|
-
|
|
22765
|
+
cell2.charPrIDRef = cpId;
|
|
21992
22766
|
usedCp.add(cpId);
|
|
21993
22767
|
}
|
|
21994
|
-
cells.push(
|
|
22768
|
+
cells.push(cell2);
|
|
21995
22769
|
if (row === 0 && colSpan === 1 && col < cols && w) colWidths[col] = w;
|
|
21996
22770
|
}
|
|
21997
|
-
const
|
|
22771
|
+
const table2 = {
|
|
21998
22772
|
table_index: tableIndex,
|
|
21999
22773
|
rows,
|
|
22000
22774
|
cols,
|
|
22001
22775
|
cells,
|
|
22002
22776
|
used_border_fills: pick(borderFills, usedBf)
|
|
22003
22777
|
};
|
|
22004
|
-
|
|
22005
|
-
if (
|
|
22778
|
+
const anchor = normalizeAnchor(anchorText);
|
|
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;
|
|
22006
22782
|
const cp = pick(charPrs, usedCp);
|
|
22007
|
-
if (Object.keys(cp).length)
|
|
22008
|
-
return
|
|
22783
|
+
if (Object.keys(cp).length) table2.used_char_prs = cp;
|
|
22784
|
+
return table2;
|
|
22009
22785
|
}
|
|
22010
|
-
function nearestTable(
|
|
22011
|
-
let p =
|
|
22786
|
+
function nearestTable(tc2) {
|
|
22787
|
+
let p = tc2.parentNode;
|
|
22012
22788
|
while (p) {
|
|
22013
22789
|
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
22014
22790
|
if (tag === "tbl") return p;
|
|
@@ -22016,9 +22792,9 @@ function nearestTable(tc) {
|
|
|
22016
22792
|
}
|
|
22017
22793
|
return null;
|
|
22018
22794
|
}
|
|
22019
|
-
function firstRunCharPr(
|
|
22020
|
-
for (const run of elemsByLocal(
|
|
22021
|
-
if (nearestCell(run) !==
|
|
22795
|
+
function firstRunCharPr(tc2) {
|
|
22796
|
+
for (const run of elemsByLocal(tc2, "run")) {
|
|
22797
|
+
if (nearestCell(run) !== tc2) continue;
|
|
22022
22798
|
const id = run.getAttribute("charPrIDRef");
|
|
22023
22799
|
if (id) return id;
|
|
22024
22800
|
}
|
|
@@ -22033,6 +22809,15 @@ function nearestCell(el) {
|
|
|
22033
22809
|
}
|
|
22034
22810
|
return null;
|
|
22035
22811
|
}
|
|
22812
|
+
function directCellText(tc2) {
|
|
22813
|
+
let out = "";
|
|
22814
|
+
for (const t of elemsByLocal(tc2, "t")) {
|
|
22815
|
+
if (nearestCell(t) !== tc2) continue;
|
|
22816
|
+
out += t.textContent ?? "";
|
|
22817
|
+
if (out.length >= 64) break;
|
|
22818
|
+
}
|
|
22819
|
+
return out;
|
|
22820
|
+
}
|
|
22036
22821
|
function pick(map, keys) {
|
|
22037
22822
|
const out = {};
|
|
22038
22823
|
for (const k of keys) {
|
|
@@ -22056,12 +22841,166 @@ async function hwpxToProfile(input) {
|
|
|
22056
22841
|
let tableIndex = 0;
|
|
22057
22842
|
for (const f of sectionFiles) {
|
|
22058
22843
|
const doc = parser.parseFromString(await f.async("text"), "text/xml");
|
|
22059
|
-
for (const
|
|
22060
|
-
if (!isTopLevelTable(
|
|
22061
|
-
tables.push(parseTable3(
|
|
22844
|
+
for (const tbl2 of elemsByLocal(doc, "tbl")) {
|
|
22845
|
+
if (!isTopLevelTable(tbl2)) continue;
|
|
22846
|
+
tables.push(parseTable3(tbl2, tableIndex++, borderFills, charPrs));
|
|
22062
22847
|
}
|
|
22063
22848
|
}
|
|
22064
|
-
return { schema_version: "0.
|
|
22849
|
+
return { schema_version: "0.2.0", tables };
|
|
22850
|
+
}
|
|
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;
|
|
22065
23004
|
}
|
|
22066
23005
|
|
|
22067
23006
|
// src/roundtrip/patcher.ts
|
|
@@ -22071,10 +23010,10 @@ import JSZip8 from "jszip";
|
|
|
22071
23010
|
var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
|
|
22072
23011
|
var TAG_AT_RE = /<[A-Za-z0-9_:]+(?:"[^"]*"|'[^']*'|[^>"'])*>/y;
|
|
22073
23012
|
function patchTableRows(input) {
|
|
22074
|
-
const { table, scanTable, ctx, skip, origKeys, editedKeys } = input;
|
|
23013
|
+
const { table: table2, scanTable, ctx, skip, origKeys, editedKeys } = input;
|
|
22075
23014
|
const xml = ctx.scans[scanTable.sectionIndex]?.xml;
|
|
22076
23015
|
if (!xml) return skip("\uC139\uC158 XML \uB9E4\uD551 \uC2E4\uD328");
|
|
22077
|
-
const numRows =
|
|
23016
|
+
const numRows = table2.rows;
|
|
22078
23017
|
if (origKeys.length !== numRows) return skip("\uD45C \uD589 \uC88C\uD45C \uBD88\uC77C\uCE58 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
22079
23018
|
if (scanTable.rows.length !== numRows || scanTable.rowRanges.length !== numRows) {
|
|
22080
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");
|
|
@@ -22145,8 +23084,8 @@ function patchTableRows(input) {
|
|
|
22145
23084
|
if (template < 0) template = kept[0];
|
|
22146
23085
|
const cells = input.editedCells(ins.ei);
|
|
22147
23086
|
if (!cells) return skip("\uC0BD\uC785 \uD589\uC5D0 \uC774\uBBF8\uC9C0/\uC911\uCCA9\uD45C \uD3EC\uD568 \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
|
|
22148
|
-
for (const
|
|
22149
|
-
const unstable =
|
|
23087
|
+
for (const cell2 of cells) {
|
|
23088
|
+
const unstable = cell2.lines.find((l) => sanitizeText(l) !== l);
|
|
22150
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");
|
|
22151
23090
|
}
|
|
22152
23091
|
const tmplCells = scanTable.rows[template];
|
|
@@ -22156,7 +23095,7 @@ function patchTableRows(input) {
|
|
|
22156
23095
|
}
|
|
22157
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");
|
|
22158
23097
|
const tmplWidth = tmplCells.reduce((s, c) => s + c.colSpan, 0);
|
|
22159
|
-
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");
|
|
22160
23099
|
if (cells.length !== tmplCells.length) {
|
|
22161
23100
|
return skip(`\uC0BD\uC785 \uD589 \uC140 \uC218(${cells.length}) \u2260 \uAE30\uC900 \uD589 \uC140 \uC218(${tmplCells.length}) \u2014 \uBBF8\uC9C0\uC6D0`);
|
|
22162
23101
|
}
|
|
@@ -22213,8 +23152,8 @@ function patchTableRows(input) {
|
|
|
22213
23152
|
for (const k of keeps) {
|
|
22214
23153
|
const fi = finalIndex.get(k);
|
|
22215
23154
|
if (fi === k.oi) continue;
|
|
22216
|
-
for (const
|
|
22217
|
-
const sp = rowAddrRewrite(xml,
|
|
23155
|
+
for (const cell2 of scanTable.rows[k.oi]) {
|
|
23156
|
+
const sp = rowAddrRewrite(xml, cell2, fi);
|
|
22218
23157
|
if (sp) splices.push(sp);
|
|
22219
23158
|
}
|
|
22220
23159
|
}
|
|
@@ -22263,13 +23202,13 @@ function buildRowFragment(xml, scanTable, template, cells, finalRow, hasExplicit
|
|
|
22263
23202
|
const patched = applySplices(wrapped, splices);
|
|
22264
23203
|
return patched.slice(FRAG_OPEN.length, patched.length - FRAG_CLOSE.length);
|
|
22265
23204
|
}
|
|
22266
|
-
function rowAddrRewrite(xml,
|
|
22267
|
-
if (!
|
|
22268
|
-
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);
|
|
22269
23208
|
const m = tag.match(/\browAddr\s*=\s*"(\d+)"/);
|
|
22270
23209
|
if (!m || m.index === void 0) return null;
|
|
22271
23210
|
if (parseInt(m[1], 10) === newRow) return null;
|
|
22272
|
-
const valStart =
|
|
23211
|
+
const valStart = cell2.addrTagRange.start + m.index + m[0].indexOf('"') + 1;
|
|
22273
23212
|
return { start: valStart, end: valStart + m[1].length, replacement: String(newRow) };
|
|
22274
23213
|
}
|
|
22275
23214
|
function rowHeightOf(fragment) {
|
|
@@ -22295,8 +23234,8 @@ function tableSzHeightSplice(xml, scanTable, tblOpenLen, delta) {
|
|
|
22295
23234
|
}
|
|
22296
23235
|
|
|
22297
23236
|
// src/roundtrip/table-patch.ts
|
|
22298
|
-
function patchGfmTable(
|
|
22299
|
-
const replica = replicateGfmTable(
|
|
23237
|
+
function patchGfmTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
23238
|
+
const replica = replicateGfmTable(table2);
|
|
22300
23239
|
if (!replica) return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
22301
23240
|
const origRows = parseGfmTable(orig.lines);
|
|
22302
23241
|
const editedRows = parseGfmTable(edited.lines);
|
|
@@ -22304,15 +23243,15 @@ function patchGfmTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
22304
23243
|
return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
22305
23244
|
}
|
|
22306
23245
|
if (editedRows.length !== origRows.length) {
|
|
22307
|
-
return patchGfmTableRows(
|
|
23246
|
+
return patchGfmTableRows(table2, scanTable, origRows, editedRows, replica, ctx, skip);
|
|
22308
23247
|
}
|
|
22309
23248
|
let applied = 0;
|
|
22310
23249
|
for (let r = 0; r < origRows.length; r++) {
|
|
22311
|
-
applied += patchGfmRowPair(
|
|
23250
|
+
applied += patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, r, r, ctx, skip);
|
|
22312
23251
|
}
|
|
22313
23252
|
return applied;
|
|
22314
23253
|
}
|
|
22315
|
-
function patchGfmRowPair(
|
|
23254
|
+
function patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, r, er, ctx, skip) {
|
|
22316
23255
|
if (editedRows[er].length !== origRows[r].length) {
|
|
22317
23256
|
skip(`\uD45C ${r + 1}\uD589 \uC5F4 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
|
|
22318
23257
|
return 0;
|
|
@@ -22329,7 +23268,7 @@ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er,
|
|
|
22329
23268
|
}
|
|
22330
23269
|
const newLines = unescapeGfmCell(stripCellTokens(editedRows[er][c])).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
22331
23270
|
const origLines = unescapeGfmCell(stripCellTokens(origRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
22332
|
-
const n = applyCellEdit(
|
|
23271
|
+
const n = applyCellEdit(table2, scanTable, gridR, gridC, newLines, ctx, origRows[r][c], editedRows[er][c], origLines.length);
|
|
22333
23272
|
if (n > 0 && origTokens) {
|
|
22334
23273
|
ctx.skipped.push({
|
|
22335
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)",
|
|
@@ -22342,19 +23281,19 @@ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er,
|
|
|
22342
23281
|
}
|
|
22343
23282
|
return applied;
|
|
22344
23283
|
}
|
|
22345
|
-
function patchGfmTableRows(
|
|
22346
|
-
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))) {
|
|
22347
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");
|
|
22348
23287
|
}
|
|
22349
|
-
if (
|
|
23288
|
+
if (table2.cells.some((row) => row.some((c) => c && (c.colSpan > 1 || c.rowSpan > 1)))) {
|
|
22350
23289
|
return skip("\uBCD1\uD569 \uC140 \uD45C \u2014 GFM \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
22351
23290
|
}
|
|
22352
|
-
if (!gfmRenderStable(editedRows,
|
|
23291
|
+
if (!gfmRenderStable(editedRows, table2.cols)) {
|
|
22353
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");
|
|
22354
23293
|
}
|
|
22355
23294
|
const key = (row) => row.join("\0");
|
|
22356
23295
|
return patchTableRows({
|
|
22357
|
-
table,
|
|
23296
|
+
table: table2,
|
|
22358
23297
|
scanTable,
|
|
22359
23298
|
ctx,
|
|
22360
23299
|
skip,
|
|
@@ -22369,7 +23308,7 @@ function patchGfmTableRows(table, scanTable, origRows, editedRows, replica, ctx,
|
|
|
22369
23308
|
}
|
|
22370
23309
|
return cells;
|
|
22371
23310
|
},
|
|
22372
|
-
patchMatched: (oi, ei) => patchGfmRowPair(
|
|
23311
|
+
patchMatched: (oi, ei) => patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, oi, ei, ctx, skip)
|
|
22373
23312
|
});
|
|
22374
23313
|
}
|
|
22375
23314
|
function gfmRenderStable(editedRows, cols) {
|
|
@@ -22386,13 +23325,13 @@ function gfmRenderStable(editedRows, cols) {
|
|
|
22386
23325
|
if (!replica || replica.length !== editedRows.length) return false;
|
|
22387
23326
|
return replica.every((row, r) => row.length === editedRows[r].length && row.every((c, j) => c.text === editedRows[r][j]));
|
|
22388
23327
|
}
|
|
22389
|
-
function patchHtmlTable(
|
|
22390
|
-
return patchHtmlTableRaw(
|
|
23328
|
+
function patchHtmlTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
23329
|
+
return patchHtmlTableRaw(table2, scanTable, orig.raw, edited.raw, ctx, skip, 0);
|
|
22391
23330
|
}
|
|
22392
|
-
function patchHtmlTableRaw(
|
|
23331
|
+
function patchHtmlTableRaw(table2, scanTable, origRaw, editedRaw, ctx, skip, depth) {
|
|
22393
23332
|
if (depth > 8) return skip("\uC911\uCCA9\uD45C \uAE4A\uC774 \uCD08\uACFC");
|
|
22394
|
-
if (replicateTableToHtml(
|
|
22395
|
-
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);
|
|
22396
23335
|
const origRows = parseHtmlTable(origRaw);
|
|
22397
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))) {
|
|
22398
23337
|
return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -22400,15 +23339,15 @@ function patchHtmlTableRaw(table, scanTable, origRaw, editedRaw, ctx, skip, dept
|
|
|
22400
23339
|
const editedRows = parseHtmlTable(editedRaw);
|
|
22401
23340
|
if (!editedRows) return skip("\uD3B8\uC9D1\uB41C HTML \uD45C \uD30C\uC2F1 \uC2E4\uD328");
|
|
22402
23341
|
if (editedRows.length !== replica.length) {
|
|
22403
|
-
return patchHtmlTableRows(
|
|
23342
|
+
return patchHtmlTableRows(table2, scanTable, replica, editedRows, ctx, skip, depth);
|
|
22404
23343
|
}
|
|
22405
23344
|
let applied = 0;
|
|
22406
23345
|
for (let r = 0; r < replica.length; r++) {
|
|
22407
|
-
applied += patchHtmlRowPair(
|
|
23346
|
+
applied += patchHtmlRowPair(table2, scanTable, replica, editedRows, r, r, ctx, skip, depth);
|
|
22408
23347
|
}
|
|
22409
23348
|
return applied;
|
|
22410
23349
|
}
|
|
22411
|
-
function patchHtmlRowPair(
|
|
23350
|
+
function patchHtmlRowPair(table2, scanTable, replica, editedRows, r, er, ctx, skip, depth) {
|
|
22412
23351
|
if (editedRows[er].cells.length !== replica[r].cells.length) {
|
|
22413
23352
|
skip(`\uD45C ${r + 1}\uD589 \uC140 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
|
|
22414
23353
|
return 0;
|
|
@@ -22436,23 +23375,23 @@ function patchHtmlRowPair(table, scanTable, replica, editedRows, r, er, ctx, ski
|
|
|
22436
23375
|
continue;
|
|
22437
23376
|
}
|
|
22438
23377
|
if (origTables.join("\n") !== editedTables.join("\n")) {
|
|
22439
|
-
applied += patchNestedTables(
|
|
23378
|
+
applied += patchNestedTables(table2, scanTable, oc, origTables, editedTables, ctx, skip, depth);
|
|
22440
23379
|
}
|
|
22441
23380
|
}
|
|
22442
23381
|
if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
|
|
22443
23382
|
const newLines = editedContent.lines.map((l) => unescapeGfm(l));
|
|
22444
|
-
applied += applyCellEdit(
|
|
23383
|
+
applied += applyCellEdit(table2, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
|
|
22445
23384
|
}
|
|
22446
23385
|
}
|
|
22447
23386
|
return applied;
|
|
22448
23387
|
}
|
|
22449
|
-
function patchHtmlTableRows(
|
|
22450
|
-
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))) {
|
|
22451
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");
|
|
22452
23391
|
}
|
|
22453
23392
|
const key = (row) => row.cells.map((c) => `${c.colSpan}x${c.rowSpan}:${c.inner}`).join("\0");
|
|
22454
23393
|
return patchTableRows({
|
|
22455
|
-
table,
|
|
23394
|
+
table: table2,
|
|
22456
23395
|
scanTable,
|
|
22457
23396
|
ctx,
|
|
22458
23397
|
skip,
|
|
@@ -22460,18 +23399,18 @@ function patchHtmlTableRows(table, scanTable, replica, editedRows, ctx, skip, de
|
|
|
22460
23399
|
editedKeys: editedRows.map(key),
|
|
22461
23400
|
editedCells: (ei) => {
|
|
22462
23401
|
const cells = [];
|
|
22463
|
-
for (const
|
|
22464
|
-
const content = htmlCellInnerToLines(
|
|
23402
|
+
for (const cell2 of editedRows[ei].cells) {
|
|
23403
|
+
const content = htmlCellInnerToLines(cell2.inner);
|
|
22465
23404
|
if (content.hadNonText) return null;
|
|
22466
|
-
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 });
|
|
22467
23406
|
}
|
|
22468
23407
|
return cells;
|
|
22469
23408
|
},
|
|
22470
|
-
patchMatched: (oi, ei) => patchHtmlRowPair(
|
|
23409
|
+
patchMatched: (oi, ei) => patchHtmlRowPair(table2, scanTable, replica, editedRows, oi, ei, ctx, skip, depth)
|
|
22471
23410
|
});
|
|
22472
23411
|
}
|
|
22473
|
-
function patchNestedTables(
|
|
22474
|
-
const irCell =
|
|
23412
|
+
function patchNestedTables(table2, scanTable, oc, origTables, editedTables, ctx, skip, depth) {
|
|
23413
|
+
const irCell = table2.cells[oc.gridR]?.[oc.gridC];
|
|
22475
23414
|
const scanCell = scanTable.cellByAnchor.get(`${oc.gridR},${oc.gridC}`);
|
|
22476
23415
|
const nestedIRs = (irCell?.blocks ?? []).filter((b) => b.type === "table" && b.table).map((b) => b.table);
|
|
22477
23416
|
if (!scanCell || nestedIRs.length !== origTables.length || scanCell.tables.length !== origTables.length) {
|
|
@@ -22494,9 +23433,9 @@ function extractCellTokens(text) {
|
|
|
22494
23433
|
function stripCellTokens(text) {
|
|
22495
23434
|
return text.replace(CELL_TOKEN_RE, "");
|
|
22496
23435
|
}
|
|
22497
|
-
function patchTextChunkTable(
|
|
22498
|
-
if (
|
|
22499
|
-
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);
|
|
22500
23439
|
const replicaLines = content.split(/\n/).map((line) => {
|
|
22501
23440
|
const t = line.trim();
|
|
22502
23441
|
if (!t) return "";
|
|
@@ -22510,12 +23449,12 @@ function patchTextChunkTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
22510
23449
|
const unwrap = m && /^\d+\.\s/.test(unescapeGfm(m[1]));
|
|
22511
23450
|
return stripCellTokens(unescapeGfm(unwrap ? m[1] : l)).trim();
|
|
22512
23451
|
}).filter(Boolean);
|
|
22513
|
-
return applyCellEdit(
|
|
23452
|
+
return applyCellEdit(table2, scanTable, 0, 0, newLines, ctx, orig.raw, edited.raw, orig.lines.length);
|
|
22514
23453
|
}
|
|
22515
|
-
if (
|
|
23454
|
+
if (table2.cols === 1 && table2.rows >= 2) {
|
|
22516
23455
|
const replica = [];
|
|
22517
|
-
for (let r = 0; r <
|
|
22518
|
-
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, " ");
|
|
22519
23458
|
if (line) replica.push({ line, gridR: r });
|
|
22520
23459
|
}
|
|
22521
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");
|
|
@@ -22528,21 +23467,21 @@ function patchTextChunkTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
22528
23467
|
continue;
|
|
22529
23468
|
}
|
|
22530
23469
|
const newLines = [stripCellTokens(unescapeGfm(edited.lines[i])).trim()].filter(Boolean);
|
|
22531
|
-
applied += applyCellEdit(
|
|
23470
|
+
applied += applyCellEdit(table2, scanTable, replica[i].gridR, 0, newLines, ctx, replica[i].line, edited.lines[i], 1);
|
|
22532
23471
|
}
|
|
22533
23472
|
return applied;
|
|
22534
23473
|
}
|
|
22535
23474
|
return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
22536
23475
|
}
|
|
22537
|
-
function applyCellEdit(
|
|
23476
|
+
function applyCellEdit(table2, scanTable, gridR, gridC, newLines, ctx, before, after, origLineCount) {
|
|
22538
23477
|
const skip = (reason) => {
|
|
22539
23478
|
ctx.skipped.push({ reason, before: summarize(before), after: summarize(after) });
|
|
22540
23479
|
return 0;
|
|
22541
23480
|
};
|
|
22542
|
-
const
|
|
22543
|
-
if (!
|
|
22544
|
-
const irCell =
|
|
22545
|
-
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");
|
|
22546
23485
|
if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
22547
23486
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
22548
23487
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -22552,7 +23491,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
|
|
|
22552
23491
|
}
|
|
22553
23492
|
}
|
|
22554
23493
|
}
|
|
22555
|
-
const nonEmpty =
|
|
23494
|
+
const nonEmpty = cell2.paragraphs.filter((p) => normForMatch(p.text) !== "");
|
|
22556
23495
|
if (origLineCount !== void 0 && nonEmpty.length > 0 && origLineCount !== nonEmpty.length) {
|
|
22557
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");
|
|
22558
23497
|
}
|
|
@@ -22562,7 +23501,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
|
|
|
22562
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");
|
|
22563
23502
|
if (nonEmpty.length === 0) {
|
|
22564
23503
|
if (newLines.length === 0) return 0;
|
|
22565
|
-
const target =
|
|
23504
|
+
const target = cell2.paragraphs[0];
|
|
22566
23505
|
if (!target) return skip("\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00");
|
|
22567
23506
|
const sp = buildParagraphSplices(target, newLines.join(" "), ctx.scans[target.sectionIndex]?.xml);
|
|
22568
23507
|
if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
|
|
@@ -22647,16 +23586,16 @@ function buildTableParagraphXml(rows, opts) {
|
|
|
22647
23586
|
const trElements = rows.map((row, rowIdx) => {
|
|
22648
23587
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
22649
23588
|
const isHeaderRow = rowIdx === 0;
|
|
22650
|
-
const tdElements = cells.map((
|
|
22651
|
-
const text = escapeXmlText(cellPlainText(
|
|
23589
|
+
const tdElements = cells.map((cell2, colIdx) => {
|
|
23590
|
+
const text = escapeXmlText(cellPlainText(cell2));
|
|
22652
23591
|
const cellP = `<hp:p paraPrIDRef="${cellParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}"><hp:t>${text}</hp:t></hp:run></hp:p>`;
|
|
22653
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>`;
|
|
22654
23593
|
}).join("");
|
|
22655
23594
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
22656
23595
|
}).join("");
|
|
22657
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;
|
|
22658
|
-
const
|
|
22659
|
-
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>`;
|
|
22660
23599
|
}
|
|
22661
23600
|
|
|
22662
23601
|
// src/roundtrip/hwpx-entries.ts
|
|
@@ -22828,12 +23767,12 @@ function buildTableOrdinals(blocks) {
|
|
|
22828
23767
|
function resolveParagraphMappings(blocks, scans) {
|
|
22829
23768
|
const buckets = /* @__PURE__ */ new Map();
|
|
22830
23769
|
for (const scan of scans) {
|
|
22831
|
-
for (const
|
|
22832
|
-
const key = normForMatch(
|
|
23770
|
+
for (const para2 of scan.bodyParagraphs) {
|
|
23771
|
+
const key = normForMatch(para2.text);
|
|
22833
23772
|
if (!key) continue;
|
|
22834
23773
|
let list = buckets.get(key);
|
|
22835
23774
|
if (!list) buckets.set(key, list = []);
|
|
22836
|
-
list.push(
|
|
23775
|
+
list.push(para2);
|
|
22837
23776
|
}
|
|
22838
23777
|
}
|
|
22839
23778
|
const headerNorms = new Set(scans.flatMap((s) => s.headerTexts.map(normForMatch)).filter(Boolean));
|
|
@@ -22919,11 +23858,11 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
22919
23858
|
if (!ti) return skip("\uBB38\uB2E8\u2192\uD45C \uBCC0\uD658 \uBD88\uAC00 \u2014 header \uC5D4\uD2B8\uB9AC(borderFills) \uD574\uC11D \uC2E4\uD328");
|
|
22920
23859
|
const mapping = ctx.paraMap.get(orig.blockIdx);
|
|
22921
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");
|
|
22922
|
-
const
|
|
22923
|
-
if (
|
|
22924
|
-
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];
|
|
22925
23864
|
if (!scan) return skip("\uC139\uC158 \uB9E4\uD551 \uC2E4\uD328");
|
|
22926
|
-
const pEnd = findElementEnd(scan.xml,
|
|
23865
|
+
const pEnd = findElementEnd(scan.xml, para2.start);
|
|
22927
23866
|
if (pEnd < 0) return skip("\uBB38\uB2E8 \uB05D \uC704\uCE58 \uD0D0\uC0C9 \uC2E4\uD328");
|
|
22928
23867
|
const rows = parseGfmTable(edited.lines);
|
|
22929
23868
|
if (rows.length === 0 || rows.every((r) => r.length === 0)) return skip("\uD45C \uB0B4\uC6A9\uC774 \uBE44\uC5B4 \uC788\uC74C");
|
|
@@ -22933,7 +23872,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
22933
23872
|
ti.borderFillId = inj.borderFillId;
|
|
22934
23873
|
ti.headerSplices.push(...inj.headerSplices);
|
|
22935
23874
|
}
|
|
22936
|
-
const outerParaPrId = extractParaPrIdRef(scan.xml,
|
|
23875
|
+
const outerParaPrId = extractParaPrIdRef(scan.xml, para2.start) ?? 0;
|
|
22937
23876
|
const tableXml = buildTableParagraphXml(rows, {
|
|
22938
23877
|
borderFillId: ti.borderFillId,
|
|
22939
23878
|
outerParaPrId,
|
|
@@ -22941,7 +23880,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
22941
23880
|
cellCharPrId: 0,
|
|
22942
23881
|
tableId: ti.nextId++
|
|
22943
23882
|
});
|
|
22944
|
-
ctx.sectionSplices[
|
|
23883
|
+
ctx.sectionSplices[para2.sectionIndex].push({ start: para2.start, end: pEnd, replacement: tableXml });
|
|
22945
23884
|
return 1;
|
|
22946
23885
|
}
|
|
22947
23886
|
function patchParagraphUnit(block, orig, edited, ctx, skip) {
|
|
@@ -23422,7 +24361,7 @@ function scanSection(stream, sectionIndex, compressed) {
|
|
|
23422
24361
|
}
|
|
23423
24362
|
}
|
|
23424
24363
|
const kind = !ctrlSeen || !nonGso ? "body" : "other";
|
|
23425
|
-
const
|
|
24364
|
+
const para2 = {
|
|
23426
24365
|
sectionIndex,
|
|
23427
24366
|
headerIdx: i,
|
|
23428
24367
|
kind,
|
|
@@ -23434,8 +24373,8 @@ function scanSection(stream, sectionIndex, compressed) {
|
|
|
23434
24373
|
nCharsRaw: rec.data.readUInt32LE(0),
|
|
23435
24374
|
rawText: state.text
|
|
23436
24375
|
};
|
|
23437
|
-
paras.push(
|
|
23438
|
-
parasByHeader.set(i,
|
|
24376
|
+
paras.push(para2);
|
|
24377
|
+
parasByHeader.set(i, para2);
|
|
23439
24378
|
}
|
|
23440
24379
|
const tables = [];
|
|
23441
24380
|
for (let i = 0; i < records.length; i++) {
|
|
@@ -23588,13 +24527,13 @@ function msg(err) {
|
|
|
23588
24527
|
function resolveParaMappings(blocks, scans) {
|
|
23589
24528
|
const buckets = /* @__PURE__ */ new Map();
|
|
23590
24529
|
for (const scan of scans) {
|
|
23591
|
-
for (const
|
|
23592
|
-
if (
|
|
23593
|
-
const key = normForMatch(
|
|
24530
|
+
for (const para2 of scan.paras) {
|
|
24531
|
+
if (para2.kind === "other") continue;
|
|
24532
|
+
const key = normForMatch(para2.rawText);
|
|
23594
24533
|
if (!key) continue;
|
|
23595
24534
|
let list = buckets.get(key);
|
|
23596
24535
|
if (!list) buckets.set(key, list = []);
|
|
23597
|
-
list.push(
|
|
24536
|
+
list.push(para2);
|
|
23598
24537
|
}
|
|
23599
24538
|
}
|
|
23600
24539
|
const usable = (list) => list.length === 1 || list.every((p) => p.kind === "body");
|
|
@@ -23630,18 +24569,18 @@ function resolveTableMappings(blocks, scanTables) {
|
|
|
23630
24569
|
const result = /* @__PURE__ */ new Map();
|
|
23631
24570
|
let si = 0;
|
|
23632
24571
|
for (let i = 0; i < blocks.length; i++) {
|
|
23633
|
-
const
|
|
23634
|
-
if (blocks[i].type !== "table" || !
|
|
24572
|
+
const table2 = blocks[i].table;
|
|
24573
|
+
if (blocks[i].type !== "table" || !table2) continue;
|
|
23635
24574
|
const cands = [];
|
|
23636
24575
|
for (let k = si; k < scanTables.length; k++) {
|
|
23637
|
-
if (scanTables[k].rows ===
|
|
24576
|
+
if (scanTables[k].rows === table2.rows && scanTables[k].cols === table2.cols) cands.push(k);
|
|
23638
24577
|
}
|
|
23639
24578
|
if (cands.length === 0) continue;
|
|
23640
24579
|
let pick2 = cands[0];
|
|
23641
24580
|
if (cands.length > 1) {
|
|
23642
|
-
let best = tableContentScore(
|
|
24581
|
+
let best = tableContentScore(table2, scanTables[cands[0]]);
|
|
23643
24582
|
for (let ci = 1; ci < cands.length; ci++) {
|
|
23644
|
-
const sc = tableContentScore(
|
|
24583
|
+
const sc = tableContentScore(table2, scanTables[cands[ci]]);
|
|
23645
24584
|
if (sc > best) {
|
|
23646
24585
|
best = sc;
|
|
23647
24586
|
pick2 = cands[ci];
|
|
@@ -23742,14 +24681,14 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23742
24681
|
ctx.skipped.push({ reason, before: summarize(origRows[r][c]), after: summarize(editedRows[r][c]) });
|
|
23743
24682
|
return 0;
|
|
23744
24683
|
};
|
|
23745
|
-
const
|
|
23746
|
-
if (!
|
|
24684
|
+
const cell2 = scanTable.cells.get(`${r},${c}`);
|
|
24685
|
+
if (!cell2) {
|
|
23747
24686
|
cellSkip("\uBCD1\uD569 \uC601\uC5ED \uC140 \u2014 \uC575\uCEE4 \uC140\uC774 \uC544\uB2C8\uBBC0\uB85C \uBBF8\uC9C0\uC6D0");
|
|
23748
24687
|
continue;
|
|
23749
24688
|
}
|
|
23750
24689
|
const beforeParts = origRows[r][c].split(/<br\s*\/?>/i);
|
|
23751
24690
|
const afterParts = editedRows[r][c].split(/<br\s*\/?>/i);
|
|
23752
|
-
if (
|
|
24691
|
+
if (cell2.paras.length === 1) {
|
|
23753
24692
|
const beforeEach = beforeParts.map(gfmCellToPlain);
|
|
23754
24693
|
const afterEach = afterParts.map(gfmCellToPlain);
|
|
23755
24694
|
if (beforeEach.some((p) => p === null) || afterEach.some((p) => p === null)) {
|
|
@@ -23759,8 +24698,8 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23759
24698
|
const before = beforeEach.join("\n");
|
|
23760
24699
|
const after = afterEach.join("\n");
|
|
23761
24700
|
if (before === after) continue;
|
|
23762
|
-
const
|
|
23763
|
-
if (normForMatch(
|
|
24701
|
+
const para2 = cell2.paras[0];
|
|
24702
|
+
if (normForMatch(para2.rawText) !== normForMatch(before)) {
|
|
23764
24703
|
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
23765
24704
|
continue;
|
|
23766
24705
|
}
|
|
@@ -23768,14 +24707,14 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23768
24707
|
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23769
24708
|
continue;
|
|
23770
24709
|
}
|
|
23771
|
-
applied += stageParaPatch(ctx.scans[
|
|
24710
|
+
applied += stageParaPatch(ctx.scans[para2.sectionIndex], para2, after, cellSkip);
|
|
23772
24711
|
continue;
|
|
23773
24712
|
}
|
|
23774
|
-
if (beforeParts.length !==
|
|
24713
|
+
if (beforeParts.length !== cell2.paras.length || afterParts.length !== cell2.paras.length) {
|
|
23775
24714
|
cellSkip("\uC140 \uBB38\uB2E8 \uC218 \uBCC0\uACBD \u2014 \uBBF8\uC9C0\uC6D0 (\uBB38\uB2E8 \uCD94\uAC00/\uC0AD\uC81C)");
|
|
23776
24715
|
continue;
|
|
23777
24716
|
}
|
|
23778
|
-
for (let k = 0; k <
|
|
24717
|
+
for (let k = 0; k < cell2.paras.length; k++) {
|
|
23779
24718
|
const before = gfmCellToPlain(beforeParts[k]);
|
|
23780
24719
|
const after = gfmCellToPlain(afterParts[k]);
|
|
23781
24720
|
if (before === null || after === null) {
|
|
@@ -23787,8 +24726,8 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23787
24726
|
cellSkip("\uC140 \uB0B4 \uC904\uBC14\uAFC8 \uCD94\uAC00\uB294 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
23788
24727
|
break;
|
|
23789
24728
|
}
|
|
23790
|
-
const
|
|
23791
|
-
if (normForMatch(
|
|
24729
|
+
const para2 = cell2.paras[k];
|
|
24730
|
+
if (normForMatch(para2.rawText) !== normForMatch(before)) {
|
|
23792
24731
|
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
23793
24732
|
break;
|
|
23794
24733
|
}
|
|
@@ -23796,15 +24735,15 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
23796
24735
|
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23797
24736
|
break;
|
|
23798
24737
|
}
|
|
23799
|
-
applied += stageParaPatch(ctx.scans[
|
|
24738
|
+
applied += stageParaPatch(ctx.scans[para2.sectionIndex], para2, after, cellSkip);
|
|
23800
24739
|
}
|
|
23801
24740
|
}
|
|
23802
24741
|
}
|
|
23803
24742
|
return applied;
|
|
23804
24743
|
}
|
|
23805
|
-
function patchHtmlCells5(
|
|
23806
|
-
if (replicateTableToHtml(
|
|
23807
|
-
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);
|
|
23808
24747
|
const origRows = parseHtmlTable(orig.raw);
|
|
23809
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))) {
|
|
23810
24749
|
return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -23840,15 +24779,15 @@ function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
23840
24779
|
}
|
|
23841
24780
|
if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
|
|
23842
24781
|
const newLines = editedContent.lines.map((l) => unescapeGfm(l));
|
|
23843
|
-
applied += applyCellEdit5(
|
|
24782
|
+
applied += applyCellEdit5(table2, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
|
|
23844
24783
|
}
|
|
23845
24784
|
}
|
|
23846
24785
|
}
|
|
23847
24786
|
return applied;
|
|
23848
24787
|
}
|
|
23849
|
-
function patchTextChunk5(
|
|
23850
|
-
if (
|
|
23851
|
-
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);
|
|
23852
24791
|
const replicaLines = content.split(/\n/).map((line) => {
|
|
23853
24792
|
const t = line.trim();
|
|
23854
24793
|
if (!t) return "";
|
|
@@ -23862,12 +24801,12 @@ function patchTextChunk5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
23862
24801
|
const unwrap = m && /^\d+\.\s/.test(unescapeGfm(m[1]));
|
|
23863
24802
|
return stripCellTokens(unescapeGfm(unwrap ? m[1] : l)).trim();
|
|
23864
24803
|
}).filter(Boolean);
|
|
23865
|
-
return applyCellEdit5(
|
|
24804
|
+
return applyCellEdit5(table2, scanTable, 0, 0, newLines, ctx, orig.raw, edited.raw, orig.lines.length);
|
|
23866
24805
|
}
|
|
23867
|
-
if (
|
|
24806
|
+
if (table2.cols === 1 && table2.rows >= 2) {
|
|
23868
24807
|
const replica = [];
|
|
23869
|
-
for (let r = 0; r <
|
|
23870
|
-
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, " ");
|
|
23871
24810
|
if (line) replica.push({ line, gridR: r });
|
|
23872
24811
|
}
|
|
23873
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");
|
|
@@ -23880,21 +24819,21 @@ function patchTextChunk5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
23880
24819
|
continue;
|
|
23881
24820
|
}
|
|
23882
24821
|
const newLines = [stripCellTokens(unescapeGfm(edited.lines[i])).trim()].filter(Boolean);
|
|
23883
|
-
applied += applyCellEdit5(
|
|
24822
|
+
applied += applyCellEdit5(table2, scanTable, replica[i].gridR, 0, newLines, ctx, replica[i].line, edited.lines[i], 1);
|
|
23884
24823
|
}
|
|
23885
24824
|
return applied;
|
|
23886
24825
|
}
|
|
23887
24826
|
return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
23888
24827
|
}
|
|
23889
|
-
function applyCellEdit5(
|
|
24828
|
+
function applyCellEdit5(table2, scanTable, gridR, gridC, newLines, ctx, before, after, origLineCount) {
|
|
23890
24829
|
const skip = (reason) => {
|
|
23891
24830
|
ctx.skipped.push({ reason, before: summarize(before), after: summarize(after) });
|
|
23892
24831
|
return 0;
|
|
23893
24832
|
};
|
|
23894
|
-
const
|
|
23895
|
-
if (!
|
|
23896
|
-
const irCell =
|
|
23897
|
-
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");
|
|
23898
24837
|
if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
23899
24838
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
23900
24839
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -23904,13 +24843,13 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
|
|
|
23904
24843
|
}
|
|
23905
24844
|
}
|
|
23906
24845
|
}
|
|
23907
|
-
const nonEmpty =
|
|
24846
|
+
const nonEmpty = cell2.paras.filter((p) => normForMatch(p.rawText) !== "");
|
|
23908
24847
|
if (origLineCount !== void 0 && nonEmpty.length > 0 && origLineCount !== nonEmpty.length) {
|
|
23909
24848
|
return skip("\uC140 \uC904 \uACBD\uACC4 \uB9E4\uD551 \uBAA8\uD638 (\uBB38\uB2E8 \uB0B4 \uC904\uBC14\uAFC8) \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23910
24849
|
}
|
|
23911
24850
|
const unstable = newLines.find((l) => sanitizeText(l) !== l);
|
|
23912
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");
|
|
23913
|
-
const targets = nonEmpty.length > 0 ? nonEmpty :
|
|
24852
|
+
const targets = nonEmpty.length > 0 ? nonEmpty : cell2.paras;
|
|
23914
24853
|
if (targets.length === 0) return skip("\uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC74C \u2014 \uBBF8\uC9C0\uC6D0");
|
|
23915
24854
|
const assigned = [];
|
|
23916
24855
|
for (let i = 0; i < targets.length; i++) {
|
|
@@ -24060,67 +24999,67 @@ function synthesizeLineSegs(lineSegData, newRaw, startUnits) {
|
|
|
24060
24999
|
}
|
|
24061
25000
|
return { buf: Buffer.concat(segs), count: lines.length };
|
|
24062
25001
|
}
|
|
24063
|
-
function stageParaPatch(scan,
|
|
25002
|
+
function stageParaPatch(scan, para2, newPlain, skip) {
|
|
24064
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");
|
|
24065
|
-
if (
|
|
24066
|
-
if (
|
|
24067
|
-
if (
|
|
24068
|
-
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");
|
|
24069
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");
|
|
24070
25009
|
const records = scan.records;
|
|
24071
|
-
const headerRec = records[
|
|
24072
|
-
const charShapeRec = records[
|
|
25010
|
+
const headerRec = records[para2.headerIdx];
|
|
25011
|
+
const charShapeRec = records[para2.charShapeIdx];
|
|
24073
25012
|
if (charShapeRec.data.length < 8) {
|
|
24074
25013
|
return skip("CHAR_SHAPE \uB808\uCF54\uB4DC \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
24075
25014
|
}
|
|
24076
|
-
if (
|
|
24077
|
-
const nCharsLow =
|
|
25015
|
+
if (para2.textIdx === -1) {
|
|
25016
|
+
const nCharsLow = para2.nCharsRaw & 2147483647;
|
|
24078
25017
|
if (nCharsLow > 1) return skip("PARA_TEXT \uC5C6\uB294 \uBB38\uB2E8\uC758 nChars \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
24079
25018
|
const paraEnd = nCharsLow === 1 ? Buffer.from([13, 0]) : Buffer.alloc(0);
|
|
24080
|
-
const at =
|
|
25019
|
+
const at = para2.headerIdx + 1;
|
|
24081
25020
|
const list = scan.inserts.get(at) ?? [];
|
|
24082
25021
|
list.push({ tagId: TAG_PARA_TEXT, level: headerRec.level + 1, data: Buffer.concat([Buffer.from(newPlain, "utf16le"), paraEnd]) });
|
|
24083
25022
|
scan.inserts.set(at, list);
|
|
24084
25023
|
const newHeader2 = Buffer.from(headerRec.data);
|
|
24085
|
-
newHeader2.writeUInt32LE((
|
|
25024
|
+
newHeader2.writeUInt32LE((para2.nCharsRaw & 2147483648 | newPlain.length + nCharsLow) >>> 0, 0);
|
|
24086
25025
|
const cs2 = rebuildCharShape(charShapeRec.data, 0);
|
|
24087
|
-
scan.repl.set(
|
|
25026
|
+
scan.repl.set(para2.charShapeIdx, cs2.buf);
|
|
24088
25027
|
newHeader2.writeUInt16LE(cs2.count, 12);
|
|
24089
25028
|
if (newPlain.includes("\n")) {
|
|
24090
|
-
const synth = synthesizeLineSegs(records[
|
|
25029
|
+
const synth = synthesizeLineSegs(records[para2.lineSegIdx].data, newPlain, 0);
|
|
24091
25030
|
if (synth) {
|
|
24092
|
-
scan.repl.set(
|
|
25031
|
+
scan.repl.set(para2.lineSegIdx, synth.buf);
|
|
24093
25032
|
newHeader2.writeUInt16LE(synth.count, 16);
|
|
24094
25033
|
}
|
|
24095
25034
|
}
|
|
24096
|
-
scan.repl.set(
|
|
25035
|
+
scan.repl.set(para2.headerIdx, newHeader2);
|
|
24097
25036
|
return 1;
|
|
24098
25037
|
}
|
|
24099
|
-
const textRec = records[
|
|
25038
|
+
const textRec = records[para2.textIdx];
|
|
24100
25039
|
const seg = splitParaText(textRec.data);
|
|
24101
25040
|
if (!seg) {
|
|
24102
|
-
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");
|
|
24103
25042
|
}
|
|
24104
|
-
if (seg.core !==
|
|
24105
|
-
const lead =
|
|
24106
|
-
const trail =
|
|
24107
|
-
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;
|
|
24108
25047
|
const newText = Buffer.concat([seg.prefix, Buffer.from(newRaw, "utf16le"), seg.suffix]);
|
|
24109
|
-
scan.repl.set(
|
|
25048
|
+
scan.repl.set(para2.textIdx, newText);
|
|
24110
25049
|
const newHeader = Buffer.from(headerRec.data);
|
|
24111
25050
|
const nChars = seg.prefixUnits + newRaw.length + seg.suffixUnits;
|
|
24112
|
-
newHeader.writeUInt32LE((
|
|
25051
|
+
newHeader.writeUInt32LE((para2.nCharsRaw & 2147483648 | nChars) >>> 0, 0);
|
|
24113
25052
|
const cs = rebuildCharShape(charShapeRec.data, seg.prefixUnits);
|
|
24114
|
-
scan.repl.set(
|
|
25053
|
+
scan.repl.set(para2.charShapeIdx, cs.buf);
|
|
24115
25054
|
newHeader.writeUInt16LE(cs.count, 12);
|
|
24116
25055
|
if (newRaw.includes("\n")) {
|
|
24117
|
-
const synth = synthesizeLineSegs(records[
|
|
25056
|
+
const synth = synthesizeLineSegs(records[para2.lineSegIdx].data, newRaw, seg.prefixUnits);
|
|
24118
25057
|
if (synth) {
|
|
24119
|
-
scan.repl.set(
|
|
25058
|
+
scan.repl.set(para2.lineSegIdx, synth.buf);
|
|
24120
25059
|
newHeader.writeUInt16LE(synth.count, 16);
|
|
24121
25060
|
}
|
|
24122
25061
|
}
|
|
24123
|
-
scan.repl.set(
|
|
25062
|
+
scan.repl.set(para2.headerIdx, newHeader);
|
|
24124
25063
|
return 1;
|
|
24125
25064
|
}
|
|
24126
25065
|
|
|
@@ -24285,9 +25224,9 @@ var HwpxSession = class _HwpxSession {
|
|
|
24285
25224
|
const block = st.blocks[blockIndex];
|
|
24286
25225
|
if (!block) return void 0;
|
|
24287
25226
|
if (block.type === "paragraph" || block.type === "heading") {
|
|
24288
|
-
const
|
|
24289
|
-
if (!
|
|
24290
|
-
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 };
|
|
24291
25230
|
}
|
|
24292
25231
|
if (block.type === "table" && block.table) {
|
|
24293
25232
|
if (st.tableOrdinals.size !== st.scanTables.length) return void 0;
|
|
@@ -24324,13 +25263,13 @@ var HwpxSession = class _HwpxSession {
|
|
|
24324
25263
|
if (!scanTable) {
|
|
24325
25264
|
return { capability: "locked", reason: "\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328" };
|
|
24326
25265
|
}
|
|
24327
|
-
const
|
|
25266
|
+
const table2 = block.table;
|
|
24328
25267
|
const cells = [];
|
|
24329
25268
|
let anyEditable = false;
|
|
24330
|
-
for (let r = 0; r <
|
|
25269
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
24331
25270
|
const row = [];
|
|
24332
|
-
for (let c = 0; c <
|
|
24333
|
-
const info = cellStaticCheck(
|
|
25271
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
25272
|
+
const info = cellStaticCheck(table2, scanTable, r, c);
|
|
24334
25273
|
if (info.editable) anyEditable = true;
|
|
24335
25274
|
row.push(info);
|
|
24336
25275
|
}
|
|
@@ -24519,12 +25458,12 @@ var HwpxSession = class _HwpxSession {
|
|
|
24519
25458
|
return 1;
|
|
24520
25459
|
}
|
|
24521
25460
|
};
|
|
24522
|
-
function cellStaticCheck(
|
|
24523
|
-
const irCell =
|
|
25461
|
+
function cellStaticCheck(table2, scanTable, r, c) {
|
|
25462
|
+
const irCell = table2.cells[r]?.[c];
|
|
24524
25463
|
if (!irCell) return { editable: false, reason: "\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16" };
|
|
24525
|
-
const
|
|
24526
|
-
if (!
|
|
24527
|
-
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");
|
|
24528
25467
|
if (normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
24529
25468
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
24530
25469
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -24534,9 +25473,9 @@ function cellStaticCheck(table, scanTable, r, c) {
|
|
|
24534
25473
|
}
|
|
24535
25474
|
}
|
|
24536
25475
|
}
|
|
24537
|
-
const nonEmpty =
|
|
25476
|
+
const nonEmpty = cell2.paragraphs.filter((p) => normForMatch(p.text) !== "");
|
|
24538
25477
|
if (nonEmpty.length === 0) {
|
|
24539
|
-
if (
|
|
25478
|
+
if (cell2.paragraphs.length === 0) {
|
|
24540
25479
|
return { editable: false, reason: "\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00" };
|
|
24541
25480
|
}
|
|
24542
25481
|
return { editable: true };
|
|
@@ -24795,7 +25734,7 @@ async function parseHwp(buffer, options) {
|
|
|
24795
25734
|
async function parsePdf(buffer, options) {
|
|
24796
25735
|
let parsePdfDocument;
|
|
24797
25736
|
try {
|
|
24798
|
-
const mod = await import("./parser-
|
|
25737
|
+
const mod = await import("./parser-LHUO6UUA.js");
|
|
24799
25738
|
parsePdfDocument = mod.parsePdfDocument;
|
|
24800
25739
|
} catch {
|
|
24801
25740
|
return {
|
|
@@ -24887,7 +25826,6 @@ async function fillForm(input, values, outputFormat = "markdown") {
|
|
|
24887
25826
|
|
|
24888
25827
|
export {
|
|
24889
25828
|
extractHwpxMetadataOnly,
|
|
24890
|
-
MAX_INLINE_MD_BYTES,
|
|
24891
25829
|
extractHwp5MetadataOnly,
|
|
24892
25830
|
formatFillValue,
|
|
24893
25831
|
ValueCursor,
|
|
@@ -24904,6 +25842,8 @@ export {
|
|
|
24904
25842
|
compare,
|
|
24905
25843
|
diffBlocks,
|
|
24906
25844
|
hwpxToProfile,
|
|
25845
|
+
isKnownFont,
|
|
25846
|
+
unknownFontWarnings,
|
|
24907
25847
|
patchHwpx,
|
|
24908
25848
|
patchHwp,
|
|
24909
25849
|
validateHwpx,
|
|
@@ -24924,4 +25864,4 @@ export {
|
|
|
24924
25864
|
parseHwpml,
|
|
24925
25865
|
fillForm
|
|
24926
25866
|
};
|
|
24927
|
-
//# sourceMappingURL=chunk-
|
|
25867
|
+
//# sourceMappingURL=chunk-PGWAF755.js.map
|