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
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
sanitizeHref,
|
|
21
21
|
stripDtd,
|
|
22
22
|
toArrayBuffer
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-IA5UZZKV.js";
|
|
24
24
|
import {
|
|
25
25
|
parsePageRange
|
|
26
26
|
} from "./chunk-GE43BE46.js";
|
|
@@ -368,8 +368,8 @@ function comResultToParseResult(pages, pageCount, warnings) {
|
|
|
368
368
|
const text = (pages[i] ?? "").trim();
|
|
369
369
|
if (!text) continue;
|
|
370
370
|
const paragraphs = text.split(/\n/);
|
|
371
|
-
for (const
|
|
372
|
-
const trimmed =
|
|
371
|
+
for (const para2 of paragraphs) {
|
|
372
|
+
const trimmed = para2.trim();
|
|
373
373
|
if (!trimmed) continue;
|
|
374
374
|
blocks.push({ type: "paragraph", text: trimmed, pageNumber: i + 1 });
|
|
375
375
|
lines.push(trimmed);
|
|
@@ -1101,7 +1101,7 @@ var HANGUL_SYLLABLE_SEQ = "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC\uC544\uC79
|
|
|
1101
1101
|
var HANGUL_JAMO_SEQ = "\u3131\u3134\u3137\u3139\u3141\u3142\u3145\u3147\u3148\u314A\u314B\u314C\u314D\u314E";
|
|
1102
1102
|
function toRoman(n) {
|
|
1103
1103
|
if (n <= 0 || n >= 4e3) return String(n);
|
|
1104
|
-
const
|
|
1104
|
+
const table2 = [
|
|
1105
1105
|
[1e3, "M"],
|
|
1106
1106
|
[900, "CM"],
|
|
1107
1107
|
[500, "D"],
|
|
@@ -1117,7 +1117,7 @@ function toRoman(n) {
|
|
|
1117
1117
|
[1, "I"]
|
|
1118
1118
|
];
|
|
1119
1119
|
let out = "";
|
|
1120
|
-
for (const [v, s] of
|
|
1120
|
+
for (const [v, s] of table2) {
|
|
1121
1121
|
while (n >= v) {
|
|
1122
1122
|
out += s;
|
|
1123
1123
|
n -= v;
|
|
@@ -1159,10 +1159,17 @@ function formatHeadNumber(n, numFormat) {
|
|
|
1159
1159
|
function resolveParaHeading(paraEl, ctx) {
|
|
1160
1160
|
const sm = ctx.styleMap;
|
|
1161
1161
|
if (!sm) return null;
|
|
1162
|
+
const styleId = paraEl.getAttribute("styleIDRef");
|
|
1163
|
+
let styleHeading;
|
|
1164
|
+
if (styleId && styleId !== "0") {
|
|
1165
|
+
const st = sm.styles.get(styleId);
|
|
1166
|
+
const m = st && /^개요\s*([1-6])$/.exec(st.name);
|
|
1167
|
+
if (m) styleHeading = Math.min(parseInt(m[1], 10), 6);
|
|
1168
|
+
}
|
|
1162
1169
|
const prId = paraEl.getAttribute("paraPrIDRef");
|
|
1163
|
-
if (!prId) return null;
|
|
1170
|
+
if (!prId) return styleHeading ? { headingLevel: styleHeading } : null;
|
|
1164
1171
|
const ref = sm.paraHeadings.get(prId);
|
|
1165
|
-
if (!ref) return null;
|
|
1172
|
+
if (!ref) return styleHeading ? { headingLevel: styleHeading } : null;
|
|
1166
1173
|
if (ref.type === "BULLET") {
|
|
1167
1174
|
const char = sm.bullets.get(ref.idRef);
|
|
1168
1175
|
return char ? { prefix: char } : null;
|
|
@@ -1192,24 +1199,24 @@ function resolveParaHeading(paraEl, ctx) {
|
|
|
1192
1199
|
|
|
1193
1200
|
// src/hwpx/table-build.ts
|
|
1194
1201
|
function buildTableWithCellMeta(state) {
|
|
1195
|
-
const
|
|
1196
|
-
if (state.caption)
|
|
1202
|
+
const table2 = buildTable(state.rows);
|
|
1203
|
+
if (state.caption) table2.caption = state.caption;
|
|
1197
1204
|
const anchors = [];
|
|
1198
1205
|
{
|
|
1199
1206
|
const covered = /* @__PURE__ */ new Set();
|
|
1200
|
-
for (let r = 0; r <
|
|
1201
|
-
for (let c = 0; c <
|
|
1207
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
1208
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
1202
1209
|
if (covered.has(`${r},${c}`)) continue;
|
|
1203
|
-
const
|
|
1204
|
-
if (!
|
|
1205
|
-
for (let dr = 0; dr <
|
|
1206
|
-
for (let dc = 0; dc <
|
|
1210
|
+
const cell2 = table2.cells[r]?.[c];
|
|
1211
|
+
if (!cell2) continue;
|
|
1212
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
1213
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
1207
1214
|
if (dr === 0 && dc === 0) continue;
|
|
1208
|
-
if (r + dr <
|
|
1215
|
+
if (r + dr < table2.rows && c + dc < table2.cols) covered.add(`${r + dr},${c + dc}`);
|
|
1209
1216
|
}
|
|
1210
1217
|
}
|
|
1211
|
-
anchors.push(
|
|
1212
|
-
c +=
|
|
1218
|
+
anchors.push(cell2);
|
|
1219
|
+
c += cell2.colSpan - 1;
|
|
1213
1220
|
}
|
|
1214
1221
|
}
|
|
1215
1222
|
}
|
|
@@ -1225,11 +1232,11 @@ function buildTableWithCellMeta(state) {
|
|
|
1225
1232
|
let target;
|
|
1226
1233
|
const trimmed = src.text.trim();
|
|
1227
1234
|
if (src.rowAddr !== void 0 && src.colAddr !== void 0) {
|
|
1228
|
-
const cand =
|
|
1235
|
+
const cand = table2.cells[src.rowAddr]?.[src.colAddr];
|
|
1229
1236
|
if (cand && cand.text === trimmed && !claimed.has(cand)) target = cand;
|
|
1230
1237
|
}
|
|
1231
1238
|
if (!target) {
|
|
1232
|
-
outer: for (const irRow of
|
|
1239
|
+
outer: for (const irRow of table2.cells) {
|
|
1233
1240
|
for (const cand of irRow) {
|
|
1234
1241
|
if (!claimed.has(cand) && cand.text === trimmed && cand.colSpan === src.colSpan && cand.rowSpan === src.rowSpan) {
|
|
1235
1242
|
target = cand;
|
|
@@ -1248,7 +1255,7 @@ function buildTableWithCellMeta(state) {
|
|
|
1248
1255
|
if (src.isHeader) target.isHeader = true;
|
|
1249
1256
|
}
|
|
1250
1257
|
}
|
|
1251
|
-
return
|
|
1258
|
+
return table2;
|
|
1252
1259
|
}
|
|
1253
1260
|
function completeTable(newTable, tableStack, blocks, ctx) {
|
|
1254
1261
|
const parentTable = tableStack.length > 0 ? tableStack.pop() : null;
|
|
@@ -1259,12 +1266,12 @@ function completeTable(newTable, tableStack, blocks, ctx) {
|
|
|
1259
1266
|
const ir = buildTableWithCellMeta(newTable);
|
|
1260
1267
|
const block = { type: "table", table: ir, pageNumber: ctx.sectionNum };
|
|
1261
1268
|
if (parentTable?.cell) {
|
|
1262
|
-
const
|
|
1263
|
-
(
|
|
1264
|
-
|
|
1269
|
+
const cell2 = parentTable.cell;
|
|
1270
|
+
(cell2.blocks ??= []).push(block);
|
|
1271
|
+
cell2.hasStructure = true;
|
|
1265
1272
|
let flat = convertTableToText(newTable.rows);
|
|
1266
1273
|
if (newTable.caption) flat = newTable.caption + (flat ? "\n" + flat : "");
|
|
1267
|
-
if (flat)
|
|
1274
|
+
if (flat) cell2.text += (cell2.text ? "\n" : "") + flat;
|
|
1268
1275
|
} else {
|
|
1269
1276
|
blocks.push(block);
|
|
1270
1277
|
}
|
|
@@ -1380,10 +1387,10 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
|
|
|
1380
1387
|
}
|
|
1381
1388
|
if (text) {
|
|
1382
1389
|
if (tableCtx?.cell) {
|
|
1383
|
-
const
|
|
1390
|
+
const cell2 = tableCtx.cell;
|
|
1384
1391
|
if (footnote) text += ` (\uC8FC: ${footnote})`;
|
|
1385
|
-
|
|
1386
|
-
(
|
|
1392
|
+
cell2.text += (cell2.text ? "\n" : "") + text;
|
|
1393
|
+
(cell2.blocks ??= []).push({ type: "paragraph", text, pageNumber: ctx.sectionNum });
|
|
1387
1394
|
} else if (!tableCtx) {
|
|
1388
1395
|
const block = { type: headingLevel ? "heading" : "paragraph", text, pageNumber: ctx.sectionNum };
|
|
1389
1396
|
if (headingLevel) block.level = headingLevel;
|
|
@@ -1456,18 +1463,18 @@ function userShapeComment(el) {
|
|
|
1456
1463
|
if (/^(?:모서리가 둥근 |둥근 )?[^\n]{1,20}입니다\.?$/.test(text)) return void 0;
|
|
1457
1464
|
return text;
|
|
1458
1465
|
}
|
|
1459
|
-
function mergeBlocksIntoCell(
|
|
1466
|
+
function mergeBlocksIntoCell(cell2, sink) {
|
|
1460
1467
|
for (const b of sink) {
|
|
1461
1468
|
if ((b.type === "paragraph" || b.type === "heading") && b.text) {
|
|
1462
|
-
|
|
1463
|
-
(
|
|
1469
|
+
cell2.text += (cell2.text ? "\n" : "") + b.text;
|
|
1470
|
+
(cell2.blocks ??= []).push(b);
|
|
1464
1471
|
} else if (b.type === "image" || b.type === "table") {
|
|
1465
1472
|
if (b.type === "image" && b.text) {
|
|
1466
|
-
|
|
1473
|
+
cell2.text += (cell2.text ? "\n" : "") + ``;
|
|
1467
1474
|
}
|
|
1468
1475
|
;
|
|
1469
|
-
(
|
|
1470
|
-
|
|
1476
|
+
(cell2.blocks ??= []).push(b);
|
|
1477
|
+
cell2.hasStructure = true;
|
|
1471
1478
|
}
|
|
1472
1479
|
}
|
|
1473
1480
|
}
|
|
@@ -1596,7 +1603,7 @@ function extractHyperlinkHref(fieldBegin) {
|
|
|
1596
1603
|
function isInDeletedRange(ctx) {
|
|
1597
1604
|
return (ctx?.shared.track.deleteDepth ?? 0) > 0;
|
|
1598
1605
|
}
|
|
1599
|
-
function extractParagraphInfo(
|
|
1606
|
+
function extractParagraphInfo(para2, styleMap, ctx) {
|
|
1600
1607
|
let text = "";
|
|
1601
1608
|
let href;
|
|
1602
1609
|
let footnote;
|
|
@@ -1806,7 +1813,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
|
|
|
1806
1813
|
}
|
|
1807
1814
|
}
|
|
1808
1815
|
};
|
|
1809
|
-
walk(
|
|
1816
|
+
walk(para2);
|
|
1810
1817
|
const leaderIdx = text.indexOf("");
|
|
1811
1818
|
if (leaderIdx >= 0) text = text.substring(0, leaderIdx);
|
|
1812
1819
|
let cleanText = text.replace(/[ \t]+/g, " ").trim();
|
|
@@ -1871,8 +1878,8 @@ function collectImageBlocks(blocks, out, ownerCell, depth = 0) {
|
|
|
1871
1878
|
out.push({ block, ownerCell });
|
|
1872
1879
|
} else if (block.type === "table" && block.table) {
|
|
1873
1880
|
for (const row of block.table.cells) {
|
|
1874
|
-
for (const
|
|
1875
|
-
if (
|
|
1881
|
+
for (const cell2 of row) {
|
|
1882
|
+
if (cell2.blocks?.length) collectImageBlocks(cell2.blocks, out, cell2, depth + 1);
|
|
1876
1883
|
}
|
|
1877
1884
|
}
|
|
1878
1885
|
}
|
|
@@ -2520,8 +2527,8 @@ var GANADA = "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC\uC544\uC790\uCC28\uCE74
|
|
|
2520
2527
|
var CIRCLED_GANADA = "\u326E\u326F\u3270\u3271\u3272\u3273\u3274\u3275\u3276\u3277\u3278\u3279\u327A\u327B";
|
|
2521
2528
|
var JAMO = "\u3131\u3134\u3137\u3139\u3141\u3142\u3145\u3147\u3148\u314A\u314B\u314C\u314D\u314E";
|
|
2522
2529
|
var CIRCLED_JAMO = "\u3260\u3261\u3262\u3263\u3264\u3265\u3266\u3267\u3268\u3269\u326A\u326B\u326C\u326D";
|
|
2523
|
-
function fromTable(n,
|
|
2524
|
-
return n >= 1 && n <=
|
|
2530
|
+
function fromTable(n, table2) {
|
|
2531
|
+
return n >= 1 && n <= table2.length ? table2[n - 1] : String(n);
|
|
2525
2532
|
}
|
|
2526
2533
|
function formatRoman(n, upper) {
|
|
2527
2534
|
if (n <= 0 || n > 3999) return String(n);
|
|
@@ -2644,8 +2651,8 @@ function collectImageBlocks2(blocks, out) {
|
|
|
2644
2651
|
if (b.type === "image") out.push(b);
|
|
2645
2652
|
if (b.table) {
|
|
2646
2653
|
for (const row of b.table.cells) {
|
|
2647
|
-
for (const
|
|
2648
|
-
if (
|
|
2654
|
+
for (const cell2 of row) {
|
|
2655
|
+
if (cell2.blocks) collectImageBlocks2(cell2.blocks, out);
|
|
2649
2656
|
}
|
|
2650
2657
|
}
|
|
2651
2658
|
}
|
|
@@ -2656,9 +2663,9 @@ function forEachTableCell(blocks, fn) {
|
|
|
2656
2663
|
for (const b of blocks) {
|
|
2657
2664
|
if (b.table) {
|
|
2658
2665
|
for (const row of b.table.cells) {
|
|
2659
|
-
for (const
|
|
2660
|
-
fn(
|
|
2661
|
-
if (
|
|
2666
|
+
for (const cell2 of row) {
|
|
2667
|
+
fn(cell2);
|
|
2668
|
+
if (cell2.blocks) forEachTableCell(cell2.blocks, fn);
|
|
2662
2669
|
}
|
|
2663
2670
|
}
|
|
2664
2671
|
}
|
|
@@ -2667,9 +2674,9 @@ function forEachTableCell(blocks, fn) {
|
|
|
2667
2674
|
}
|
|
2668
2675
|
var CELL_IMAGE_SENTINEL_RE = /!\[image\]\(hwp5bin:(\d+)\)/g;
|
|
2669
2676
|
function resolveCellImageSentinels(blocks, renamed) {
|
|
2670
|
-
forEachTableCell(blocks, (
|
|
2671
|
-
if (!
|
|
2672
|
-
|
|
2677
|
+
forEachTableCell(blocks, (cell2) => {
|
|
2678
|
+
if (!cell2.text.includes("hwp5bin:")) return;
|
|
2679
|
+
cell2.text = cell2.text.replace(CELL_IMAGE_SENTINEL_RE, (_m, idStr) => {
|
|
2673
2680
|
const filename = renamed.get(Number(idStr));
|
|
2674
2681
|
return filename ? `` : "[\uC774\uBBF8\uC9C0]";
|
|
2675
2682
|
});
|
|
@@ -2760,15 +2767,15 @@ function extractHwp5ImagesLenient(lcfb, blocks, warnings) {
|
|
|
2760
2767
|
// src/image/transcode.ts
|
|
2761
2768
|
import { deflateSync } from "zlib";
|
|
2762
2769
|
var CRC_TABLE = (() => {
|
|
2763
|
-
const
|
|
2770
|
+
const table2 = new Uint32Array(256);
|
|
2764
2771
|
for (let n = 0; n < 256; n++) {
|
|
2765
2772
|
let c = n;
|
|
2766
2773
|
for (let k = 0; k < 8; k++) {
|
|
2767
2774
|
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
2768
2775
|
}
|
|
2769
|
-
|
|
2776
|
+
table2[n] = c >>> 0;
|
|
2770
2777
|
}
|
|
2771
|
-
return
|
|
2778
|
+
return table2;
|
|
2772
2779
|
})();
|
|
2773
2780
|
function crc32(bytes) {
|
|
2774
2781
|
let c = 4294967295;
|
|
@@ -2779,7 +2786,7 @@ function crc32(bytes) {
|
|
|
2779
2786
|
}
|
|
2780
2787
|
var BI_RGB = 0;
|
|
2781
2788
|
var MAX_DIM = 32767;
|
|
2782
|
-
var MAX_PIXELS =
|
|
2789
|
+
var MAX_PIXELS = 36e6;
|
|
2783
2790
|
function bmpToPng(bmp) {
|
|
2784
2791
|
if (bmp.length < 54) return null;
|
|
2785
2792
|
if (bmp[0] !== 66 || bmp[1] !== 77) return null;
|
|
@@ -2867,7 +2874,6 @@ function encodePng(width, height, rgba) {
|
|
|
2867
2874
|
out.set(iendChunk, o);
|
|
2868
2875
|
return out;
|
|
2869
2876
|
}
|
|
2870
|
-
var MAX_INLINE_MD_BYTES = 4 * 1024 * 1024;
|
|
2871
2877
|
function escapeRegExp(s) {
|
|
2872
2878
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2873
2879
|
}
|
|
@@ -2886,8 +2892,11 @@ function inlineImagesIntoMarkdown(markdown, images, opts) {
|
|
|
2886
2892
|
}
|
|
2887
2893
|
const base64 = Buffer.from(bytes).toString("base64");
|
|
2888
2894
|
const dataUri = `data:${mime};base64,${base64}`;
|
|
2889
|
-
const
|
|
2890
|
-
|
|
2895
|
+
const name = escapeRegExp(img.filename);
|
|
2896
|
+
const mdRe = new RegExp(`!\\[image\\]\\((?:images/)?${name}\\)`, "g");
|
|
2897
|
+
out = out.replace(mdRe, () => ``);
|
|
2898
|
+
const imgTagRe = new RegExp(`(<img\\b[^>]*\\bsrc=")(?:images/)?${name}(")`, "g");
|
|
2899
|
+
out = out.replace(imgTagRe, (_m, pre, post) => `${pre}${dataUri}${post}`);
|
|
2891
2900
|
}
|
|
2892
2901
|
return out;
|
|
2893
2902
|
}
|
|
@@ -4295,8 +4304,8 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
4295
4304
|
function applyCtrlEffect(ctrl, records, ctx) {
|
|
4296
4305
|
switch (ctrl.id) {
|
|
4297
4306
|
case CTRL_TBL: {
|
|
4298
|
-
const
|
|
4299
|
-
if (
|
|
4307
|
+
const table2 = parseTableControl(ctrl, records, ctx);
|
|
4308
|
+
if (table2) ctrl.afterBlocks = [{ type: "table", table: table2, pageNumber: ctx.sectionNum }];
|
|
4300
4309
|
return;
|
|
4301
4310
|
}
|
|
4302
4311
|
case CTRL_GSO: {
|
|
@@ -4515,14 +4524,14 @@ function parseTableControl(ctrl, records, ctx) {
|
|
|
4515
4524
|
if (c.isHeader) ir.isHeader = true;
|
|
4516
4525
|
return ir;
|
|
4517
4526
|
}));
|
|
4518
|
-
const
|
|
4519
|
-
if (caption)
|
|
4520
|
-
return
|
|
4527
|
+
const table3 = { rows, cols, cells: irCells, hasHeader: rows > 1 };
|
|
4528
|
+
if (caption) table3.caption = caption;
|
|
4529
|
+
return table3;
|
|
4521
4530
|
}
|
|
4522
4531
|
const cellRows = arrangeCells(rows, cols, cells);
|
|
4523
|
-
const
|
|
4524
|
-
if (caption &&
|
|
4525
|
-
return
|
|
4532
|
+
const table2 = buildTable(cellRows);
|
|
4533
|
+
if (caption && table2.rows > 0) table2.caption = caption;
|
|
4534
|
+
return table2.rows > 0 ? table2 : null;
|
|
4526
4535
|
}
|
|
4527
4536
|
function parseCell(records, lhIdx, end, ctx) {
|
|
4528
4537
|
const rec = records[lhIdx];
|
|
@@ -4560,22 +4569,22 @@ function parseCell(records, lhIdx, end, ctx) {
|
|
|
4560
4569
|
parts.push(t);
|
|
4561
4570
|
}
|
|
4562
4571
|
}
|
|
4563
|
-
const
|
|
4564
|
-
if (hasStructure && blocks.length > 0)
|
|
4565
|
-
if (isHeader)
|
|
4566
|
-
return
|
|
4572
|
+
const cell2 = { text: parts.join("\n"), colSpan, rowSpan, colAddr, rowAddr };
|
|
4573
|
+
if (hasStructure && blocks.length > 0) cell2.blocks = blocks;
|
|
4574
|
+
if (isHeader) cell2.isHeader = true;
|
|
4575
|
+
return cell2;
|
|
4567
4576
|
}
|
|
4568
4577
|
function arrangeCells(rows, cols, cells) {
|
|
4569
4578
|
const grid = Array.from({ length: rows }, () => Array(cols).fill(null));
|
|
4570
4579
|
const hasAddr = cells.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0);
|
|
4571
4580
|
if (hasAddr) {
|
|
4572
|
-
for (const
|
|
4573
|
-
const r =
|
|
4574
|
-
const c =
|
|
4581
|
+
for (const cell2 of cells) {
|
|
4582
|
+
const r = cell2.rowAddr ?? 0;
|
|
4583
|
+
const c = cell2.colAddr ?? 0;
|
|
4575
4584
|
if (r >= rows || c >= cols) continue;
|
|
4576
|
-
grid[r][c] =
|
|
4577
|
-
for (let dr = 0; dr <
|
|
4578
|
-
for (let dc = 0; dc <
|
|
4585
|
+
grid[r][c] = cell2;
|
|
4586
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
4587
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
4579
4588
|
if (dr === 0 && dc === 0) continue;
|
|
4580
4589
|
if (r + dr < rows && c + dc < cols)
|
|
4581
4590
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -4587,10 +4596,10 @@ function arrangeCells(rows, cols, cells) {
|
|
|
4587
4596
|
for (let r = 0; r < rows && cellIdx < cells.length; r++) {
|
|
4588
4597
|
for (let c = 0; c < cols && cellIdx < cells.length; c++) {
|
|
4589
4598
|
if (grid[r][c] !== null) continue;
|
|
4590
|
-
const
|
|
4591
|
-
grid[r][c] =
|
|
4592
|
-
for (let dr = 0; dr <
|
|
4593
|
-
for (let dc = 0; dc <
|
|
4599
|
+
const cell2 = cells[cellIdx++];
|
|
4600
|
+
grid[r][c] = cell2;
|
|
4601
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
4602
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
4594
4603
|
if (dr === 0 && dc === 0) continue;
|
|
4595
4604
|
if (r + dr < rows && c + dc < cols)
|
|
4596
4605
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -17106,7 +17115,7 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
17106
17115
|
let lastRow = -1;
|
|
17107
17116
|
for (let r = 0; r <= maxRow; r++) {
|
|
17108
17117
|
const row = grid[r];
|
|
17109
|
-
if (row && row.some((
|
|
17118
|
+
if (row && row.some((cell2) => cell2 !== "")) {
|
|
17110
17119
|
if (firstRow === -1) firstRow = r;
|
|
17111
17120
|
lastRow = r;
|
|
17112
17121
|
}
|
|
@@ -17129,9 +17138,9 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
17129
17138
|
cellRows.push(row);
|
|
17130
17139
|
}
|
|
17131
17140
|
if (cellRows.length > 0) {
|
|
17132
|
-
const
|
|
17133
|
-
if (
|
|
17134
|
-
blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
|
|
17141
|
+
const table2 = buildTable(cellRows);
|
|
17142
|
+
if (table2.rows > 0) {
|
|
17143
|
+
blocks.push({ type: "table", table: table2, pageNumber: sheetIndex + 1 });
|
|
17135
17144
|
}
|
|
17136
17145
|
}
|
|
17137
17146
|
return blocks;
|
|
@@ -17749,9 +17758,9 @@ function sheetToBlocks2(sheetName, sheet, sheetIndex) {
|
|
|
17749
17758
|
cellRows.push(row);
|
|
17750
17759
|
}
|
|
17751
17760
|
if (cellRows.length > 0) {
|
|
17752
|
-
const
|
|
17753
|
-
if (
|
|
17754
|
-
blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
|
|
17761
|
+
const table2 = buildTable(cellRows);
|
|
17762
|
+
if (table2.rows > 0) {
|
|
17763
|
+
blocks.push({ type: "table", table: table2, pageNumber: sheetIndex + 1 });
|
|
17755
17764
|
}
|
|
17756
17765
|
}
|
|
17757
17766
|
return blocks;
|
|
@@ -18497,8 +18506,8 @@ function collectTextboxParagraphs(node, inTxbx = false, out = [], depth = 0) {
|
|
|
18497
18506
|
}
|
|
18498
18507
|
return out;
|
|
18499
18508
|
}
|
|
18500
|
-
function parseTable(
|
|
18501
|
-
const trElements = getChildElements(
|
|
18509
|
+
function parseTable(tbl2, styles, numbering, footnotes, rels) {
|
|
18510
|
+
const trElements = getChildElements(tbl2, "tr");
|
|
18502
18511
|
if (trElements.length === 0) return null;
|
|
18503
18512
|
const rawRows = [];
|
|
18504
18513
|
for (const tr of trElements) {
|
|
@@ -18511,10 +18520,10 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18511
18520
|
col = Math.max(0, parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0);
|
|
18512
18521
|
}
|
|
18513
18522
|
}
|
|
18514
|
-
for (const
|
|
18523
|
+
for (const tc2 of getChildElements(tr, "tc")) {
|
|
18515
18524
|
let colSpan = 1;
|
|
18516
18525
|
let vMerge = null;
|
|
18517
|
-
const tcPrEls = getChildElements(
|
|
18526
|
+
const tcPrEls = getChildElements(tc2, "tcPr");
|
|
18518
18527
|
if (tcPrEls.length > 0) {
|
|
18519
18528
|
const gridSpanEls = getChildElements(tcPrEls[0], "gridSpan");
|
|
18520
18529
|
if (gridSpanEls.length > 0) {
|
|
@@ -18525,48 +18534,48 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18525
18534
|
vMerge = getAttr(vMergeEls[0], "val") === "restart" ? "restart" : "continue";
|
|
18526
18535
|
}
|
|
18527
18536
|
}
|
|
18528
|
-
const text = collectCellText(
|
|
18537
|
+
const text = collectCellText(tc2, styles, numbering, footnotes, rels, 0).join("\n");
|
|
18529
18538
|
row.push({ col, colSpan, vMerge, text });
|
|
18530
18539
|
col += colSpan;
|
|
18531
18540
|
}
|
|
18532
18541
|
rawRows.push(row);
|
|
18533
18542
|
}
|
|
18534
18543
|
for (let r = 0; r < rawRows.length; r++) {
|
|
18535
|
-
for (const
|
|
18536
|
-
if (
|
|
18544
|
+
for (const cell2 of rawRows[r]) {
|
|
18545
|
+
if (cell2.vMerge !== "continue" || !cell2.text) continue;
|
|
18537
18546
|
let start;
|
|
18538
18547
|
for (let pr = r - 1; pr >= 0 && !start; pr--) {
|
|
18539
|
-
start = rawRows[pr].find((pc) => pc.col ===
|
|
18548
|
+
start = rawRows[pr].find((pc) => pc.col === cell2.col && pc.vMerge !== "continue");
|
|
18540
18549
|
}
|
|
18541
18550
|
if (start) {
|
|
18542
18551
|
start.text = start.text ? `${start.text}
|
|
18543
|
-
${
|
|
18544
|
-
|
|
18552
|
+
${cell2.text}` : cell2.text;
|
|
18553
|
+
cell2.text = "";
|
|
18545
18554
|
} else {
|
|
18546
|
-
|
|
18555
|
+
cell2.vMerge = null;
|
|
18547
18556
|
}
|
|
18548
18557
|
}
|
|
18549
18558
|
}
|
|
18550
18559
|
const cellRows = rawRows.map(
|
|
18551
|
-
(row, r) => row.filter((
|
|
18560
|
+
(row, r) => row.filter((cell2) => cell2.vMerge !== "continue").map((cell2) => {
|
|
18552
18561
|
let rowSpan = 1;
|
|
18553
|
-
if (
|
|
18562
|
+
if (cell2.vMerge === "restart") {
|
|
18554
18563
|
for (let nr = r + 1; nr < rawRows.length; nr++) {
|
|
18555
|
-
if (!rawRows[nr].some((nc) => nc.col ===
|
|
18564
|
+
if (!rawRows[nr].some((nc) => nc.col === cell2.col && nc.vMerge === "continue")) break;
|
|
18556
18565
|
rowSpan++;
|
|
18557
18566
|
}
|
|
18558
18567
|
}
|
|
18559
|
-
return { text:
|
|
18568
|
+
return { text: cell2.text, colSpan: cell2.colSpan, rowSpan, colAddr: cell2.col, rowAddr: r };
|
|
18560
18569
|
})
|
|
18561
18570
|
);
|
|
18562
|
-
const
|
|
18563
|
-
if (
|
|
18564
|
-
return { type: "table", table };
|
|
18571
|
+
const table2 = buildTable(cellRows);
|
|
18572
|
+
if (table2.rows === 0 || table2.cols === 0) return null;
|
|
18573
|
+
return { type: "table", table: table2 };
|
|
18565
18574
|
}
|
|
18566
|
-
function collectCellText(
|
|
18575
|
+
function collectCellText(tc2, styles, numbering, footnotes, rels, depth) {
|
|
18567
18576
|
const parts = [];
|
|
18568
18577
|
if (depth > 20) return parts;
|
|
18569
|
-
for (const el of effectiveChildElements(
|
|
18578
|
+
for (const el of effectiveChildElements(tc2)) {
|
|
18570
18579
|
if (matchesLocal(el, "p")) {
|
|
18571
18580
|
const block = parseParagraph2(el, styles, numbering, footnotes, rels);
|
|
18572
18581
|
if (block?.text) parts.push(block.text);
|
|
@@ -18927,13 +18936,13 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18927
18936
|
}
|
|
18928
18937
|
if (cells.length === 0) return;
|
|
18929
18938
|
const grid = Array.from({ length: rowCount }, () => Array(colCount).fill(null));
|
|
18930
|
-
for (const
|
|
18931
|
-
const r =
|
|
18932
|
-
const c =
|
|
18939
|
+
for (const cell2 of cells) {
|
|
18940
|
+
const r = cell2.rowAddr ?? 0;
|
|
18941
|
+
const c = cell2.colAddr ?? 0;
|
|
18933
18942
|
if (isNaN(r) || isNaN(c) || r >= rowCount || c >= colCount) continue;
|
|
18934
|
-
grid[r][c] =
|
|
18935
|
-
for (let dr = 0; dr <
|
|
18936
|
-
for (let dc = 0; dc <
|
|
18943
|
+
grid[r][c] = cell2;
|
|
18944
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
18945
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
18937
18946
|
if (dr === 0 && dc === 0) continue;
|
|
18938
18947
|
if (r + dr < rowCount && c + dc < colCount) {
|
|
18939
18948
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -18942,14 +18951,14 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18942
18951
|
}
|
|
18943
18952
|
}
|
|
18944
18953
|
const cellRows = grid.map(
|
|
18945
|
-
(row) => row.map((
|
|
18954
|
+
(row) => row.map((cell2) => cell2 ?? { text: "", colSpan: 1, rowSpan: 1 })
|
|
18946
18955
|
);
|
|
18947
|
-
const
|
|
18956
|
+
const table2 = buildTable(cellRows);
|
|
18948
18957
|
const caption = extractShapeCaption(el);
|
|
18949
18958
|
if (caption.text && caption.before) {
|
|
18950
18959
|
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18951
18960
|
}
|
|
18952
|
-
blocks.push({ type: "table", table, pageNumber: sectionNum });
|
|
18961
|
+
blocks.push({ type: "table", table: table2, pageNumber: sectionNum });
|
|
18953
18962
|
if (caption.text && !caption.before) {
|
|
18954
18963
|
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18955
18964
|
}
|
|
@@ -19449,13 +19458,13 @@ function extractFormFields(blocks) {
|
|
|
19449
19458
|
const confidence = totalTables > 0 ? formTables / totalTables : fields.length > 0 ? 0.3 : 0;
|
|
19450
19459
|
return { fields, confidence: Math.min(confidence, 1) };
|
|
19451
19460
|
}
|
|
19452
|
-
function extractFromTable(
|
|
19461
|
+
function extractFromTable(table2) {
|
|
19453
19462
|
const fields = [];
|
|
19454
|
-
if (
|
|
19455
|
-
for (let r = 0; r <
|
|
19456
|
-
for (let c = 0; c <
|
|
19457
|
-
const labelCell =
|
|
19458
|
-
const valueCell =
|
|
19463
|
+
if (table2.cols >= 2) {
|
|
19464
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19465
|
+
for (let c = 0; c < table2.cols - 1; c++) {
|
|
19466
|
+
const labelCell = table2.cells[r]?.[c];
|
|
19467
|
+
const valueCell = table2.cells[r]?.[c + 1];
|
|
19459
19468
|
if (!labelCell || !valueCell) continue;
|
|
19460
19469
|
if (isLabelCell(labelCell.text)) {
|
|
19461
19470
|
fields.push({
|
|
@@ -19468,17 +19477,17 @@ function extractFromTable(table) {
|
|
|
19468
19477
|
}
|
|
19469
19478
|
}
|
|
19470
19479
|
}
|
|
19471
|
-
if (fields.length === 0 &&
|
|
19472
|
-
const headerRow =
|
|
19473
|
-
const allLabels = headerRow.every((
|
|
19474
|
-
const t =
|
|
19480
|
+
if (fields.length === 0 && table2.rows >= 2 && table2.cols >= 2) {
|
|
19481
|
+
const headerRow = table2.cells[0];
|
|
19482
|
+
const allLabels = headerRow.every((cell2) => {
|
|
19483
|
+
const t = cell2.text.trim();
|
|
19475
19484
|
return t.length > 0 && t.length <= 20;
|
|
19476
19485
|
});
|
|
19477
19486
|
if (allLabels) {
|
|
19478
|
-
for (let r = 1; r <
|
|
19479
|
-
for (let c = 0; c <
|
|
19487
|
+
for (let r = 1; r < table2.rows; r++) {
|
|
19488
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19480
19489
|
const label = headerRow[c]?.text.trim() ?? "";
|
|
19481
|
-
const value =
|
|
19490
|
+
const value = table2.cells[r]?.[c]?.text.trim() ?? "";
|
|
19482
19491
|
if (label && value) {
|
|
19483
19492
|
fields.push({ label, value, row: r, col: c });
|
|
19484
19493
|
}
|
|
@@ -19515,9 +19524,9 @@ function inferFieldType(label, value) {
|
|
|
19515
19524
|
if (/^[\d,.\s]+(?:원|명|건|개|회|부|매|%)$/.test(v) && /\d/.test(v)) return "amount";
|
|
19516
19525
|
if (/^\d{1,3}(?:,\d{3})+$/.test(v)) return "amount";
|
|
19517
19526
|
}
|
|
19518
|
-
const
|
|
19527
|
+
const norm2 = label.replace(/\s/g, "");
|
|
19519
19528
|
for (const [re, type] of LABEL_TYPE_RULES) {
|
|
19520
|
-
if (re.test(
|
|
19529
|
+
if (re.test(norm2)) return type;
|
|
19521
19530
|
}
|
|
19522
19531
|
return "text";
|
|
19523
19532
|
}
|
|
@@ -19568,15 +19577,15 @@ function fillFormFields(blocks, values, blockedLabels) {
|
|
|
19568
19577
|
const cursor = new ValueCursor(normalizedValues);
|
|
19569
19578
|
const allTables = collectIRTables(cloned, 0);
|
|
19570
19579
|
const patternFilledCells = /* @__PURE__ */ new Set();
|
|
19571
|
-
for (const
|
|
19572
|
-
for (let r = 0; r <
|
|
19573
|
-
for (let c = 0; c <
|
|
19574
|
-
const
|
|
19575
|
-
if (!
|
|
19576
|
-
const result = fillInCellPatterns(
|
|
19580
|
+
for (const table2 of allTables) {
|
|
19581
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19582
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19583
|
+
const cell2 = table2.cells[r]?.[c];
|
|
19584
|
+
if (!cell2) continue;
|
|
19585
|
+
const result = fillInCellPatterns(cell2.text, cursor, matchedLabels, blockedLabels);
|
|
19577
19586
|
if (result) {
|
|
19578
|
-
|
|
19579
|
-
patternFilledCells.add(
|
|
19587
|
+
cell2.text = result.text;
|
|
19588
|
+
patternFilledCells.add(cell2);
|
|
19580
19589
|
for (const m of result.matches) {
|
|
19581
19590
|
filled.push({ label: m.label, value: m.value, row: r, col: c, key: m.key });
|
|
19582
19591
|
}
|
|
@@ -19584,8 +19593,8 @@ function fillFormFields(blocks, values, blockedLabels) {
|
|
|
19584
19593
|
}
|
|
19585
19594
|
}
|
|
19586
19595
|
}
|
|
19587
|
-
for (const
|
|
19588
|
-
fillTable(
|
|
19596
|
+
for (const table2 of allTables) {
|
|
19597
|
+
fillTable(table2, cursor, filled, matchedLabels, patternFilledCells, blockedLabels);
|
|
19589
19598
|
}
|
|
19590
19599
|
for (const block of cloned) {
|
|
19591
19600
|
if (block.type !== "paragraph" || !block.text) continue;
|
|
@@ -19602,44 +19611,44 @@ function collectIRTables(blocks, depth) {
|
|
|
19602
19611
|
if (block.type !== "table" || !block.table) continue;
|
|
19603
19612
|
out.push(block.table);
|
|
19604
19613
|
for (const row of block.table.cells) {
|
|
19605
|
-
for (const
|
|
19606
|
-
if (
|
|
19614
|
+
for (const cell2 of row) {
|
|
19615
|
+
if (cell2?.blocks?.length) out.push(...collectIRTables(cell2.blocks, depth + 1));
|
|
19607
19616
|
}
|
|
19608
19617
|
}
|
|
19609
19618
|
}
|
|
19610
19619
|
return out;
|
|
19611
19620
|
}
|
|
19612
|
-
function coveredPositions(
|
|
19621
|
+
function coveredPositions(table2) {
|
|
19613
19622
|
const covered = /* @__PURE__ */ new Set();
|
|
19614
|
-
for (let r = 0; r <
|
|
19615
|
-
for (let c = 0; c <
|
|
19623
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19624
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19616
19625
|
if (covered.has(`${r},${c}`)) continue;
|
|
19617
|
-
const
|
|
19618
|
-
if (!
|
|
19619
|
-
for (let dr = 0; dr <
|
|
19620
|
-
for (let dc = 0; dc <
|
|
19626
|
+
const cell2 = table2.cells[r]?.[c];
|
|
19627
|
+
if (!cell2) continue;
|
|
19628
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
19629
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
19621
19630
|
if (dr === 0 && dc === 0) continue;
|
|
19622
|
-
if (r + dr <
|
|
19631
|
+
if (r + dr < table2.rows && c + dc < table2.cols) covered.add(`${r + dr},${c + dc}`);
|
|
19623
19632
|
}
|
|
19624
19633
|
}
|
|
19625
|
-
c +=
|
|
19634
|
+
c += cell2.colSpan - 1;
|
|
19626
19635
|
}
|
|
19627
19636
|
}
|
|
19628
19637
|
return covered;
|
|
19629
19638
|
}
|
|
19630
|
-
function fillTable(
|
|
19631
|
-
if (
|
|
19632
|
-
const covered = coveredPositions(
|
|
19633
|
-
for (let r = 0; r <
|
|
19634
|
-
for (let c = 0; c <
|
|
19639
|
+
function fillTable(table2, values, filled, matchedLabels, patternFilledCells, blockedLabels) {
|
|
19640
|
+
if (table2.cols < 2) return;
|
|
19641
|
+
const covered = coveredPositions(table2);
|
|
19642
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19643
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19635
19644
|
if (covered.has(`${r},${c}`)) continue;
|
|
19636
|
-
const labelCell =
|
|
19645
|
+
const labelCell = table2.cells[r][c];
|
|
19637
19646
|
if (!labelCell) continue;
|
|
19638
19647
|
if (!isLabelCell(labelCell.text)) continue;
|
|
19639
19648
|
let vc = c + labelCell.colSpan;
|
|
19640
|
-
while (vc <
|
|
19641
|
-
if (vc >=
|
|
19642
|
-
const valueCell =
|
|
19649
|
+
while (vc < table2.cols && covered.has(`${r},${vc}`)) vc++;
|
|
19650
|
+
if (vc >= table2.cols) continue;
|
|
19651
|
+
const valueCell = table2.cells[r][vc];
|
|
19643
19652
|
if (!valueCell) continue;
|
|
19644
19653
|
if (isKeywordLabel(valueCell.text)) continue;
|
|
19645
19654
|
const normalizedCellLabel = normalizeLabel(labelCell.text);
|
|
@@ -19664,18 +19673,18 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells, blo
|
|
|
19664
19673
|
});
|
|
19665
19674
|
}
|
|
19666
19675
|
}
|
|
19667
|
-
if (
|
|
19668
|
-
const headerRow =
|
|
19669
|
-
const allLabels = headerRow.every((
|
|
19670
|
-
const t =
|
|
19676
|
+
if (table2.rows >= 2 && table2.cols >= 2) {
|
|
19677
|
+
const headerRow = table2.cells[0];
|
|
19678
|
+
const allLabels = headerRow.every((cell2) => {
|
|
19679
|
+
const t = cell2.text.trim();
|
|
19671
19680
|
return t.length > 0 && t.length <= 20 && isLabelCell(t);
|
|
19672
19681
|
});
|
|
19673
19682
|
if (!allLabels) return;
|
|
19674
|
-
for (let r = 1; r <
|
|
19675
|
-
for (let c = 0; c <
|
|
19683
|
+
for (let r = 1; r < table2.rows; r++) {
|
|
19684
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19676
19685
|
if (covered.has(`${r},${c}`)) continue;
|
|
19677
19686
|
const headerCell = headerRow[c];
|
|
19678
|
-
const valueCell =
|
|
19687
|
+
const valueCell = table2.cells[r]?.[c];
|
|
19679
19688
|
if (!headerCell || !valueCell) continue;
|
|
19680
19689
|
const headerLabel = normalizeLabel(headerCell.text);
|
|
19681
19690
|
if (blockedLabels?.has(headerLabel)) continue;
|
|
@@ -19856,9 +19865,9 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19856
19865
|
if (closeName !== void 0) {
|
|
19857
19866
|
const local2 = localOf(closeName);
|
|
19858
19867
|
if (local2 === "t" && pendingT) {
|
|
19859
|
-
const { para, contentStart: contentStart2 } = pendingT;
|
|
19860
|
-
|
|
19861
|
-
|
|
19868
|
+
const { para: para2, contentStart: contentStart2 } = pendingT;
|
|
19869
|
+
para2.tRanges.push({ contentStart: contentStart2, contentEnd: m.index });
|
|
19870
|
+
para2.text += tContentToText(xml.slice(contentStart2, m.index));
|
|
19862
19871
|
pendingT = null;
|
|
19863
19872
|
}
|
|
19864
19873
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
@@ -19868,35 +19877,35 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19868
19877
|
}
|
|
19869
19878
|
}
|
|
19870
19879
|
if (local2 === "p") {
|
|
19871
|
-
const
|
|
19872
|
-
if (
|
|
19880
|
+
const para2 = paraStack.pop();
|
|
19881
|
+
if (para2 && para2.kind === "excluded") {
|
|
19873
19882
|
const sub = currentCtrlSub();
|
|
19874
|
-
if (sub &&
|
|
19883
|
+
if (sub && para2.text.trim()) sub.texts.push(para2.text);
|
|
19875
19884
|
}
|
|
19876
19885
|
} else if (local2 === "tc") {
|
|
19877
|
-
const
|
|
19886
|
+
const cell2 = cellStack.pop();
|
|
19878
19887
|
const row = rowStack[rowStack.length - 1];
|
|
19879
|
-
if (
|
|
19888
|
+
if (cell2 && row) row.push(cell2);
|
|
19880
19889
|
} else if (local2 === "tr") {
|
|
19881
19890
|
const row = rowStack[rowStack.length - 1];
|
|
19882
|
-
const
|
|
19883
|
-
if (row &&
|
|
19884
|
-
|
|
19891
|
+
const table2 = tableStack[tableStack.length - 1];
|
|
19892
|
+
if (row && table2 && row.length > 0) {
|
|
19893
|
+
table2.rows.push(row);
|
|
19885
19894
|
const trStart = trStartStack[trStartStack.length - 1];
|
|
19886
|
-
if (trStart >= 0)
|
|
19895
|
+
if (trStart >= 0) table2.rowRanges.push({ start: trStart, end: m.index + full.length });
|
|
19887
19896
|
}
|
|
19888
19897
|
if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
|
|
19889
19898
|
if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = -1;
|
|
19890
19899
|
} else if (local2 === "tbl") {
|
|
19891
|
-
const
|
|
19900
|
+
const table2 = tableStack.pop();
|
|
19892
19901
|
rowStack.pop();
|
|
19893
19902
|
trStartStack.pop();
|
|
19894
|
-
if (
|
|
19895
|
-
finalizeTable(
|
|
19896
|
-
if (!
|
|
19897
|
-
const
|
|
19898
|
-
if (
|
|
19899
|
-
else orphanTables.push(
|
|
19903
|
+
if (table2) {
|
|
19904
|
+
finalizeTable(table2);
|
|
19905
|
+
if (!table2.topLevel) {
|
|
19906
|
+
const cell2 = cellStack[cellStack.length - 1];
|
|
19907
|
+
if (cell2) cell2.tables.push(table2);
|
|
19908
|
+
else orphanTables.push(table2);
|
|
19900
19909
|
}
|
|
19901
19910
|
}
|
|
19902
19911
|
} else if (local2 === "header" || local2 === "footer") {
|
|
@@ -19916,45 +19925,45 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19916
19925
|
const contentStart = m.index + full.length;
|
|
19917
19926
|
if (isSelfClose) {
|
|
19918
19927
|
if (local === "t") {
|
|
19919
|
-
const
|
|
19920
|
-
if (
|
|
19928
|
+
const para2 = owningPara();
|
|
19929
|
+
if (para2) para2.tRanges.push({ contentStart: m.index, contentEnd: m.index + full.length, selfClosing: true, prefix: prefixOf(qname) });
|
|
19921
19930
|
} else if (local === "tab" || local === "fwSpace" || local === "hwSpace" || local === "br" || local === "lineBreak") {
|
|
19922
19931
|
if (!pendingT) {
|
|
19923
|
-
const
|
|
19924
|
-
if (
|
|
19932
|
+
const para2 = owningPara();
|
|
19933
|
+
if (para2) para2.text += " ";
|
|
19925
19934
|
}
|
|
19926
19935
|
} else if (local === "run" || local === "r") {
|
|
19927
|
-
const
|
|
19928
|
-
if (
|
|
19936
|
+
const para2 = owningPara();
|
|
19937
|
+
if (para2 && !para2.selfCloseRun) para2.selfCloseRun = { start: m.index, end: m.index + full.length };
|
|
19929
19938
|
} else if (local === "cellAddr") {
|
|
19930
|
-
const
|
|
19931
|
-
if (
|
|
19939
|
+
const cell2 = cellStack[cellStack.length - 1];
|
|
19940
|
+
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
19932
19941
|
const ca = parseInt(getAttr2(attrsRaw, "colAddr") || "", 10);
|
|
19933
19942
|
const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
|
|
19934
|
-
if (!isNaN(ca))
|
|
19935
|
-
if (!isNaN(ra))
|
|
19936
|
-
|
|
19943
|
+
if (!isNaN(ca)) cell2.colAddr = ca;
|
|
19944
|
+
if (!isNaN(ra)) cell2.rowAddr = ra;
|
|
19945
|
+
cell2.addrTagRange = { start: m.index, end: m.index + full.length };
|
|
19937
19946
|
}
|
|
19938
19947
|
} else if (local === "cellSpan") {
|
|
19939
|
-
const
|
|
19940
|
-
if (
|
|
19948
|
+
const cell2 = cellStack[cellStack.length - 1];
|
|
19949
|
+
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
19941
19950
|
const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
|
|
19942
19951
|
const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
|
|
19943
|
-
|
|
19944
|
-
|
|
19952
|
+
cell2.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
|
|
19953
|
+
cell2.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
|
|
19945
19954
|
}
|
|
19946
19955
|
}
|
|
19947
19956
|
continue;
|
|
19948
19957
|
}
|
|
19949
19958
|
if (local === "t") {
|
|
19950
|
-
const
|
|
19951
|
-
if (
|
|
19959
|
+
const para2 = owningPara();
|
|
19960
|
+
if (para2) pendingT = { para: para2, contentStart };
|
|
19952
19961
|
stack.push({ local, qname, contentStart });
|
|
19953
19962
|
continue;
|
|
19954
19963
|
}
|
|
19955
19964
|
stack.push({ local, qname, contentStart });
|
|
19956
19965
|
if (local === "p") {
|
|
19957
|
-
const
|
|
19966
|
+
const para2 = {
|
|
19958
19967
|
sectionIndex,
|
|
19959
19968
|
kind: "excluded",
|
|
19960
19969
|
// 분류는 push 직후 스택 기준 (자기 자신 제외)
|
|
@@ -19964,22 +19973,22 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19964
19973
|
};
|
|
19965
19974
|
stack.pop();
|
|
19966
19975
|
const cls = classifyPara();
|
|
19967
|
-
|
|
19968
|
-
if (cls.inTextbox)
|
|
19976
|
+
para2.kind = cls.kind;
|
|
19977
|
+
if (cls.inTextbox) para2.inTextbox = true;
|
|
19969
19978
|
stack.push({ local, qname, contentStart });
|
|
19970
|
-
paraStack.push(
|
|
19971
|
-
if (
|
|
19972
|
-
else if (
|
|
19973
|
-
const
|
|
19974
|
-
if (
|
|
19975
|
-
} else if (
|
|
19976
|
-
excludedParagraphs.push(
|
|
19979
|
+
paraStack.push(para2);
|
|
19980
|
+
if (para2.kind === "body" || para2.kind === "draw") bodyParagraphs.push(para2);
|
|
19981
|
+
else if (para2.kind === "cell") {
|
|
19982
|
+
const cell2 = cellStack[cellStack.length - 1];
|
|
19983
|
+
if (cell2) cell2.paragraphs.push(para2);
|
|
19984
|
+
} else if (para2.kind === "excluded") {
|
|
19985
|
+
excludedParagraphs.push(para2);
|
|
19977
19986
|
}
|
|
19978
19987
|
} else if (local === "run" || local === "r") {
|
|
19979
|
-
const
|
|
19980
|
-
if (
|
|
19988
|
+
const para2 = owningPara();
|
|
19989
|
+
if (para2 && para2.runPrefix === void 0) para2.runPrefix = prefixOf(qname);
|
|
19981
19990
|
} else if (local === "tbl") {
|
|
19982
|
-
const
|
|
19991
|
+
const table2 = {
|
|
19983
19992
|
sectionIndex,
|
|
19984
19993
|
start: m.index,
|
|
19985
19994
|
topLevel: false,
|
|
@@ -19988,31 +19997,31 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19988
19997
|
cellByAnchor: /* @__PURE__ */ new Map()
|
|
19989
19998
|
};
|
|
19990
19999
|
stack.pop();
|
|
19991
|
-
|
|
20000
|
+
table2.topLevel = isTableTopLevel();
|
|
19992
20001
|
stack.push({ local, qname, contentStart });
|
|
19993
|
-
tableStack.push(
|
|
20002
|
+
tableStack.push(table2);
|
|
19994
20003
|
rowStack.push([]);
|
|
19995
20004
|
trStartStack.push(-1);
|
|
19996
|
-
if (
|
|
20005
|
+
if (table2.topLevel) tables.push(table2);
|
|
19997
20006
|
} else if (local === "tr") {
|
|
19998
20007
|
if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
|
|
19999
20008
|
if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = m.index;
|
|
20000
20009
|
} else if (local === "tc") {
|
|
20001
20010
|
cellStack.push({ colSpan: 1, rowSpan: 1, paragraphs: [], tables: [] });
|
|
20002
20011
|
} else if (local === "cellAddr" || local === "cellSpan") {
|
|
20003
|
-
const
|
|
20004
|
-
if (
|
|
20012
|
+
const cell2 = cellStack[cellStack.length - 1];
|
|
20013
|
+
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
20005
20014
|
if (local === "cellAddr") {
|
|
20006
20015
|
const ca = parseInt(getAttr2(attrsRaw, "colAddr") || "", 10);
|
|
20007
20016
|
const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
|
|
20008
|
-
if (!isNaN(ca))
|
|
20009
|
-
if (!isNaN(ra))
|
|
20010
|
-
|
|
20017
|
+
if (!isNaN(ca)) cell2.colAddr = ca;
|
|
20018
|
+
if (!isNaN(ra)) cell2.rowAddr = ra;
|
|
20019
|
+
cell2.addrTagRange = { start: m.index, end: contentStart };
|
|
20011
20020
|
} else {
|
|
20012
20021
|
const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
|
|
20013
20022
|
const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
|
|
20014
|
-
|
|
20015
|
-
|
|
20023
|
+
cell2.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
|
|
20024
|
+
cell2.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
|
|
20016
20025
|
}
|
|
20017
20026
|
}
|
|
20018
20027
|
} else if (local === "header" || local === "footer") {
|
|
@@ -20020,23 +20029,23 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
20020
20029
|
ctrlSubStack.push({ kind: local, texts: [] });
|
|
20021
20030
|
}
|
|
20022
20031
|
} else if (local === "tab" || local === "fwSpace" || local === "hwSpace" || local === "br" || local === "lineBreak") {
|
|
20023
|
-
const
|
|
20024
|
-
if (
|
|
20032
|
+
const para2 = owningPara();
|
|
20033
|
+
if (para2) para2.text += " ";
|
|
20025
20034
|
}
|
|
20026
20035
|
}
|
|
20027
|
-
for (const
|
|
20028
|
-
for (const
|
|
20029
|
-
const fillTableInsertPos = (
|
|
20036
|
+
for (const para2 of bodyParagraphs) fillRunInsertPos(para2, xml);
|
|
20037
|
+
for (const para2 of excludedParagraphs) fillRunInsertPos(para2, xml);
|
|
20038
|
+
const fillTableInsertPos = (table2, depth = 0) => {
|
|
20030
20039
|
if (depth > 16) return;
|
|
20031
|
-
for (const row of
|
|
20032
|
-
for (const
|
|
20033
|
-
for (const
|
|
20034
|
-
for (const nested of
|
|
20040
|
+
for (const row of table2.rows) {
|
|
20041
|
+
for (const cell2 of row) {
|
|
20042
|
+
for (const para2 of cell2.paragraphs) fillRunInsertPos(para2, xml);
|
|
20043
|
+
for (const nested of cell2.tables) fillTableInsertPos(nested, depth + 1);
|
|
20035
20044
|
}
|
|
20036
20045
|
}
|
|
20037
20046
|
};
|
|
20038
|
-
for (const
|
|
20039
|
-
for (const
|
|
20047
|
+
for (const table2 of tables) fillTableInsertPos(table2);
|
|
20048
|
+
for (const table2 of orphanTables) fillTableInsertPos(table2);
|
|
20040
20049
|
return { sectionIndex, xml, bodyParagraphs, tables, headerTexts, footerTexts, excludedParagraphs, orphanTables };
|
|
20041
20050
|
}
|
|
20042
20051
|
function getAttr2(attrsRaw, name) {
|
|
@@ -20053,19 +20062,19 @@ function insideCurrentTable(stack, tableStack) {
|
|
|
20053
20062
|
}
|
|
20054
20063
|
return false;
|
|
20055
20064
|
}
|
|
20056
|
-
function fillRunInsertPos(
|
|
20057
|
-
if (
|
|
20058
|
-
const pEnd = findElementEnd(xml,
|
|
20065
|
+
function fillRunInsertPos(para2, xml) {
|
|
20066
|
+
if (para2.tRanges.length > 0) return;
|
|
20067
|
+
const pEnd = findElementEnd(xml, para2.start);
|
|
20059
20068
|
if (pEnd < 0) return;
|
|
20060
|
-
const slice = xml.slice(
|
|
20069
|
+
const slice = xml.slice(para2.start, pEnd);
|
|
20061
20070
|
const runOpen = slice.match(/<((?:[A-Za-z0-9_]+:)?run)(?:\s(?:"[^"]*"|'[^']*'|[^>"'])*?)?(\/?)>/);
|
|
20062
20071
|
if (!runOpen || runOpen.index === void 0) return;
|
|
20063
20072
|
if (runOpen[2] === "/") return;
|
|
20064
20073
|
const qname = runOpen[1];
|
|
20065
20074
|
const closeIdx = slice.indexOf(`</${qname}>`, runOpen.index);
|
|
20066
20075
|
if (closeIdx < 0) return;
|
|
20067
|
-
|
|
20068
|
-
|
|
20076
|
+
para2.runInsertPos = para2.start + closeIdx;
|
|
20077
|
+
para2.runPrefix = prefixOf(qname);
|
|
20069
20078
|
}
|
|
20070
20079
|
function findElementEnd(xml, start) {
|
|
20071
20080
|
const open = xml.slice(start).match(/^<([^\s/>!?]+)/);
|
|
@@ -20085,39 +20094,39 @@ function findElementEnd(xml, start) {
|
|
|
20085
20094
|
}
|
|
20086
20095
|
return -1;
|
|
20087
20096
|
}
|
|
20088
|
-
function finalizeTable(
|
|
20089
|
-
const hasAddr =
|
|
20097
|
+
function finalizeTable(table2) {
|
|
20098
|
+
const hasAddr = table2.rows.some((row) => row.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0));
|
|
20090
20099
|
if (hasAddr) {
|
|
20091
|
-
for (const row of
|
|
20092
|
-
for (const
|
|
20093
|
-
if (
|
|
20094
|
-
|
|
20100
|
+
for (const row of table2.rows) {
|
|
20101
|
+
for (const cell2 of row) {
|
|
20102
|
+
if (cell2.rowAddr !== void 0 && cell2.colAddr !== void 0) {
|
|
20103
|
+
table2.cellByAnchor.set(`${cell2.rowAddr},${cell2.colAddr}`, cell2);
|
|
20095
20104
|
}
|
|
20096
20105
|
}
|
|
20097
20106
|
}
|
|
20098
20107
|
return;
|
|
20099
20108
|
}
|
|
20100
|
-
const numRows =
|
|
20109
|
+
const numRows = table2.rows.length;
|
|
20101
20110
|
const occupied = Array.from({ length: numRows }, () => []);
|
|
20102
20111
|
for (let rowIdx = 0; rowIdx < numRows; rowIdx++) {
|
|
20103
20112
|
let colIdx = 0;
|
|
20104
|
-
for (const
|
|
20113
|
+
for (const cell2 of table2.rows[rowIdx]) {
|
|
20105
20114
|
while (occupied[rowIdx][colIdx]) colIdx++;
|
|
20106
|
-
|
|
20107
|
-
|
|
20108
|
-
|
|
20109
|
-
for (let r = rowIdx; r < Math.min(rowIdx +
|
|
20110
|
-
for (let c = colIdx; c < colIdx +
|
|
20115
|
+
cell2.rowAddr = rowIdx;
|
|
20116
|
+
cell2.colAddr = colIdx;
|
|
20117
|
+
table2.cellByAnchor.set(`${rowIdx},${colIdx}`, cell2);
|
|
20118
|
+
for (let r = rowIdx; r < Math.min(rowIdx + cell2.rowSpan, numRows); r++) {
|
|
20119
|
+
for (let c = colIdx; c < colIdx + cell2.colSpan; c++) {
|
|
20111
20120
|
occupied[r][c] = true;
|
|
20112
20121
|
}
|
|
20113
20122
|
}
|
|
20114
|
-
colIdx +=
|
|
20123
|
+
colIdx += cell2.colSpan;
|
|
20115
20124
|
}
|
|
20116
20125
|
}
|
|
20117
20126
|
}
|
|
20118
|
-
function buildParagraphSplices(
|
|
20127
|
+
function buildParagraphSplices(para2, newText, xml) {
|
|
20119
20128
|
if (newText && xml) {
|
|
20120
|
-
const orig = paraTText(
|
|
20129
|
+
const orig = paraTText(para2, xml);
|
|
20121
20130
|
if (orig && orig.trim() !== "") {
|
|
20122
20131
|
const lead = orig.match(/^\s*/)[0];
|
|
20123
20132
|
const trail = orig.match(/\s*$/)[0];
|
|
@@ -20127,31 +20136,31 @@ function buildParagraphSplices(para, newText, xml) {
|
|
|
20127
20136
|
}
|
|
20128
20137
|
}
|
|
20129
20138
|
const escaped = escapeXmlText(newText);
|
|
20130
|
-
if (
|
|
20139
|
+
if (para2.tRanges.length > 0) {
|
|
20131
20140
|
const splices = [];
|
|
20132
|
-
const first =
|
|
20141
|
+
const first = para2.tRanges[0];
|
|
20133
20142
|
if (first.selfClosing) {
|
|
20134
20143
|
const prefix = first.prefix ? first.prefix + ":" : "";
|
|
20135
20144
|
splices.push({ start: first.contentStart, end: first.contentEnd, replacement: `<${prefix}t>${escaped}</${prefix}t>` });
|
|
20136
20145
|
} else {
|
|
20137
20146
|
splices.push({ start: first.contentStart, end: first.contentEnd, replacement: escaped });
|
|
20138
20147
|
}
|
|
20139
|
-
for (let i = 1; i <
|
|
20140
|
-
const r =
|
|
20148
|
+
for (let i = 1; i < para2.tRanges.length; i++) {
|
|
20149
|
+
const r = para2.tRanges[i];
|
|
20141
20150
|
if (!r.selfClosing && r.contentStart < r.contentEnd) {
|
|
20142
20151
|
splices.push({ start: r.contentStart, end: r.contentEnd, replacement: "" });
|
|
20143
20152
|
}
|
|
20144
20153
|
}
|
|
20145
20154
|
return splices;
|
|
20146
20155
|
}
|
|
20147
|
-
if (
|
|
20156
|
+
if (para2.runInsertPos !== void 0) {
|
|
20148
20157
|
if (!newText) return [];
|
|
20149
|
-
const prefix =
|
|
20150
|
-
return [{ start:
|
|
20158
|
+
const prefix = para2.runPrefix ? para2.runPrefix + ":" : "";
|
|
20159
|
+
return [{ start: para2.runInsertPos, end: para2.runInsertPos, replacement: `<${prefix}t>${escaped}</${prefix}t>` }];
|
|
20151
20160
|
}
|
|
20152
|
-
if (
|
|
20161
|
+
if (para2.selfCloseRun && xml) {
|
|
20153
20162
|
if (!newText) return [];
|
|
20154
|
-
const { start, end } =
|
|
20163
|
+
const { start, end } = para2.selfCloseRun;
|
|
20155
20164
|
const tag = xml.slice(start, end);
|
|
20156
20165
|
const qm = tag.match(/^<([^\s/>]+)/);
|
|
20157
20166
|
if (!qm || !tag.endsWith("/>")) return null;
|
|
@@ -20163,9 +20172,9 @@ function buildParagraphSplices(para, newText, xml) {
|
|
|
20163
20172
|
}
|
|
20164
20173
|
return newText ? null : [];
|
|
20165
20174
|
}
|
|
20166
|
-
function paraTText(
|
|
20175
|
+
function paraTText(para2, xml) {
|
|
20167
20176
|
let text = "";
|
|
20168
|
-
for (const t of
|
|
20177
|
+
for (const t of para2.tRanges) {
|
|
20169
20178
|
if (t.selfClosing) continue;
|
|
20170
20179
|
const raw = xml.slice(t.contentStart, t.contentEnd);
|
|
20171
20180
|
if (/[<&]/.test(raw)) return null;
|
|
@@ -20173,19 +20182,19 @@ function paraTText(para, xml) {
|
|
|
20173
20182
|
}
|
|
20174
20183
|
return text;
|
|
20175
20184
|
}
|
|
20176
|
-
function paraTextPureT(
|
|
20185
|
+
function paraTextPureT(para2, xml) {
|
|
20177
20186
|
let len = 0;
|
|
20178
|
-
for (const t of
|
|
20187
|
+
for (const t of para2.tRanges) {
|
|
20179
20188
|
if (t.selfClosing) continue;
|
|
20180
20189
|
len += tContentToText(xml.slice(t.contentStart, t.contentEnd)).length;
|
|
20181
20190
|
}
|
|
20182
|
-
return len ===
|
|
20191
|
+
return len === para2.text.length;
|
|
20183
20192
|
}
|
|
20184
|
-
function buildRangeSplices(
|
|
20193
|
+
function buildRangeSplices(para2, xml, start, end, replacement) {
|
|
20185
20194
|
if (start < 0 || end < start) return null;
|
|
20186
20195
|
const segs = [];
|
|
20187
20196
|
let offset = 0;
|
|
20188
|
-
for (const t of
|
|
20197
|
+
for (const t of para2.tRanges) {
|
|
20189
20198
|
if (t.selfClosing) continue;
|
|
20190
20199
|
const raw = xml.slice(t.contentStart, t.contentEnd);
|
|
20191
20200
|
if (/[<&]/.test(raw)) return null;
|
|
@@ -20305,13 +20314,13 @@ function parseCentralDirectory(buf) {
|
|
|
20305
20314
|
return { entries, cdOffset, cdSize, eocdOffset };
|
|
20306
20315
|
}
|
|
20307
20316
|
var CRC_TABLE2 = (() => {
|
|
20308
|
-
const
|
|
20317
|
+
const table2 = new Uint32Array(256);
|
|
20309
20318
|
for (let n = 0; n < 256; n++) {
|
|
20310
20319
|
let c = n;
|
|
20311
20320
|
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
20312
|
-
|
|
20321
|
+
table2[n] = c >>> 0;
|
|
20313
20322
|
}
|
|
20314
|
-
return
|
|
20323
|
+
return table2;
|
|
20315
20324
|
})();
|
|
20316
20325
|
function crc322(data) {
|
|
20317
20326
|
let crc = 4294967295;
|
|
@@ -20473,28 +20482,28 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20473
20482
|
return l;
|
|
20474
20483
|
};
|
|
20475
20484
|
const matchText = (p) => paraTText(p, xml) ?? p.text;
|
|
20476
|
-
const cellLabelText = (
|
|
20485
|
+
const cellLabelText = (cell2) => cell2.paragraphs.filter((p) => !p.inTextbox).map((p) => matchText(p)).join("");
|
|
20477
20486
|
const allTables = [];
|
|
20478
20487
|
const collectTables = (tables, depth) => {
|
|
20479
20488
|
if (depth > 16) return;
|
|
20480
20489
|
for (const t of tables) {
|
|
20481
20490
|
allTables.push(t);
|
|
20482
20491
|
for (const row of t.rows) {
|
|
20483
|
-
for (const
|
|
20492
|
+
for (const cell2 of row) collectTables(cell2.tables, depth + 1);
|
|
20484
20493
|
}
|
|
20485
20494
|
}
|
|
20486
20495
|
};
|
|
20487
20496
|
collectTables(scan.tables, 0);
|
|
20488
20497
|
collectTables(scan.orphanTables, 0);
|
|
20489
20498
|
const patternApplied = /* @__PURE__ */ new Set();
|
|
20490
|
-
for (const
|
|
20491
|
-
for (const row of
|
|
20492
|
-
for (const
|
|
20493
|
-
for (const
|
|
20494
|
-
const text = matchText(
|
|
20499
|
+
for (const table2 of allTables) {
|
|
20500
|
+
for (const row of table2.rows) {
|
|
20501
|
+
for (const cell2 of row) {
|
|
20502
|
+
for (const para2 of cell2.paragraphs) {
|
|
20503
|
+
const text = matchText(para2);
|
|
20495
20504
|
const result = fillInCellPatterns(text, cursor, matchedLabels, blockedLabels);
|
|
20496
20505
|
if (!result) continue;
|
|
20497
|
-
const l = led(
|
|
20506
|
+
const l = led(para2);
|
|
20498
20507
|
if (l.fullText !== void 0) continue;
|
|
20499
20508
|
const newT = result.text;
|
|
20500
20509
|
let s = 0;
|
|
@@ -20506,7 +20515,7 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20506
20515
|
en--;
|
|
20507
20516
|
}
|
|
20508
20517
|
l.ranges.push({ start: s, end: eo, replacement: newT.slice(s, en) });
|
|
20509
|
-
patternApplied.add(
|
|
20518
|
+
patternApplied.add(cell2);
|
|
20510
20519
|
for (const m of result.matches) {
|
|
20511
20520
|
l.filledIdx.push(filled.length);
|
|
20512
20521
|
l.matchKeys.push(m.key);
|
|
@@ -20516,9 +20525,9 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20516
20525
|
}
|
|
20517
20526
|
}
|
|
20518
20527
|
}
|
|
20519
|
-
for (const
|
|
20520
|
-
for (let rowIdx = 0; rowIdx <
|
|
20521
|
-
const cells =
|
|
20528
|
+
for (const table2 of allTables) {
|
|
20529
|
+
for (let rowIdx = 0; rowIdx < table2.rows.length; rowIdx++) {
|
|
20530
|
+
const cells = table2.rows[rowIdx];
|
|
20522
20531
|
for (let colIdx = 0; colIdx < cells.length - 1; colIdx++) {
|
|
20523
20532
|
const labelText = cellLabelText(cells[colIdx]);
|
|
20524
20533
|
if (!isLabelCell(labelText)) continue;
|
|
@@ -20573,15 +20582,15 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20573
20582
|
}
|
|
20574
20583
|
}
|
|
20575
20584
|
}
|
|
20576
|
-
if (
|
|
20577
|
-
const headerCells =
|
|
20578
|
-
const allLabels = headerCells.length > 0 && headerCells.every((
|
|
20579
|
-
const t = cellLabelText(
|
|
20585
|
+
if (table2.rows.length >= 2) {
|
|
20586
|
+
const headerCells = table2.rows[0];
|
|
20587
|
+
const allLabels = headerCells.length > 0 && headerCells.every((cell2) => {
|
|
20588
|
+
const t = cellLabelText(cell2).trim();
|
|
20580
20589
|
return t.length > 0 && t.length <= 20 && isLabelCell(t);
|
|
20581
20590
|
});
|
|
20582
20591
|
if (allLabels) {
|
|
20583
|
-
for (let rowIdx = 1; rowIdx <
|
|
20584
|
-
const dataCells =
|
|
20592
|
+
for (let rowIdx = 1; rowIdx < table2.rows.length; rowIdx++) {
|
|
20593
|
+
const dataCells = table2.rows[rowIdx];
|
|
20585
20594
|
for (let colIdx = 0; colIdx < Math.min(headerCells.length, dataCells.length); colIdx++) {
|
|
20586
20595
|
const headerLabel = normalizeLabel(cellLabelText(headerCells[colIdx]));
|
|
20587
20596
|
if (blockedLabels?.has(headerLabel)) continue;
|
|
@@ -20615,10 +20624,10 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20615
20624
|
}
|
|
20616
20625
|
}
|
|
20617
20626
|
}
|
|
20618
|
-
for (const
|
|
20619
|
-
const existing = ledger.get(
|
|
20627
|
+
for (const para2 of [...scan.bodyParagraphs, ...scan.excludedParagraphs]) {
|
|
20628
|
+
const existing = ledger.get(para2);
|
|
20620
20629
|
if (existing?.fullText !== void 0) continue;
|
|
20621
|
-
const text = matchText(
|
|
20630
|
+
const text = matchText(para2);
|
|
20622
20631
|
for (const seg of scanInlineSegments(text)) {
|
|
20623
20632
|
const nlabel = normalizeLabel(seg.label);
|
|
20624
20633
|
if (blockedLabels?.has(nlabel)) continue;
|
|
@@ -20627,7 +20636,7 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20627
20636
|
const newValue = cursor.consume(matchKey);
|
|
20628
20637
|
if (newValue === void 0) continue;
|
|
20629
20638
|
const replacement = seg.valueStart === seg.valueEnd ? padInsertion(text, seg.valueStart, newValue) : newValue;
|
|
20630
|
-
const l = led(
|
|
20639
|
+
const l = led(para2);
|
|
20631
20640
|
l.ranges.push({ start: seg.valueStart, end: seg.valueEnd, replacement });
|
|
20632
20641
|
matchedLabels.add(matchKey);
|
|
20633
20642
|
l.filledIdx.push(filled.length);
|
|
@@ -20636,10 +20645,10 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20636
20645
|
}
|
|
20637
20646
|
}
|
|
20638
20647
|
const splices = [];
|
|
20639
|
-
for (const [
|
|
20648
|
+
for (const [para2, l] of ledger) {
|
|
20640
20649
|
let paraSplices = null;
|
|
20641
20650
|
if (l.fullText !== void 0) {
|
|
20642
|
-
paraSplices = buildParagraphSplices(
|
|
20651
|
+
paraSplices = buildParagraphSplices(para2, l.fullText, xml);
|
|
20643
20652
|
} else if (l.ranges.length > 0) {
|
|
20644
20653
|
const sorted = [...l.ranges].sort((a, b) => a.start - b.start || a.end - b.end);
|
|
20645
20654
|
const merged = [];
|
|
@@ -20648,11 +20657,11 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20648
20657
|
if (prev && r.start < prev.end) continue;
|
|
20649
20658
|
merged.push(r);
|
|
20650
20659
|
}
|
|
20651
|
-
if (paraTText(
|
|
20660
|
+
if (paraTText(para2, xml) !== null) {
|
|
20652
20661
|
const precise = [];
|
|
20653
20662
|
let ok = true;
|
|
20654
20663
|
for (const r of merged) {
|
|
20655
|
-
const sp = buildRangeSplices(
|
|
20664
|
+
const sp = buildRangeSplices(para2, xml, r.start, r.end, r.replacement);
|
|
20656
20665
|
if (!sp) {
|
|
20657
20666
|
ok = false;
|
|
20658
20667
|
break;
|
|
@@ -20660,13 +20669,13 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20660
20669
|
precise.push(...sp);
|
|
20661
20670
|
}
|
|
20662
20671
|
paraSplices = ok ? precise : null;
|
|
20663
|
-
} else if (paraTextPureT(
|
|
20664
|
-
let text =
|
|
20672
|
+
} else if (paraTextPureT(para2, xml)) {
|
|
20673
|
+
let text = para2.text;
|
|
20665
20674
|
for (let k = merged.length - 1; k >= 0; k--) {
|
|
20666
20675
|
const r = merged[k];
|
|
20667
20676
|
text = text.slice(0, r.start) + r.replacement + text.slice(r.end);
|
|
20668
20677
|
}
|
|
20669
|
-
paraSplices = buildParagraphSplices(
|
|
20678
|
+
paraSplices = buildParagraphSplices(para2, text, xml);
|
|
20670
20679
|
} else {
|
|
20671
20680
|
paraSplices = null;
|
|
20672
20681
|
}
|
|
@@ -20848,6 +20857,7 @@ function charWidthEm1000(cp) {
|
|
|
20848
20857
|
if (cp >= 19968 && cp <= 40959 || cp >= 63744 && cp <= 64255) return 1e3;
|
|
20849
20858
|
if (cp >= 12296 && cp <= 12305 || cp >= 12308 && cp <= 12315) return 500;
|
|
20850
20859
|
if (cp === 12288) return 970;
|
|
20860
|
+
if (cp >= 8544 && cp <= 8579) return 970;
|
|
20851
20861
|
if (cp >= 8592 && cp <= 8959) return 970;
|
|
20852
20862
|
if (cp >= 9312 && cp <= 9471) return 970;
|
|
20853
20863
|
if (cp >= 9632 && cp <= 9983) return 970;
|
|
@@ -20939,14 +20949,126 @@ function fitRatioForFewerLines(text, firstWidth, contWidth, height, baseRatio, m
|
|
|
20939
20949
|
return null;
|
|
20940
20950
|
}
|
|
20941
20951
|
|
|
20952
|
+
// src/hwpx/gaejosik.ts
|
|
20953
|
+
var GAEJOSIK_BULLETS = ["\u25A1", "\u25CB", "\u2015", "\u318D"];
|
|
20954
|
+
function gaejosikMarker(depth) {
|
|
20955
|
+
return GAEJOSIK_BULLETS[Math.min(depth, GAEJOSIK_BULLETS.length - 1)];
|
|
20956
|
+
}
|
|
20957
|
+
function gaejosikSizes(bodyHeight, ov = {}) {
|
|
20958
|
+
const s = bodyHeight / 1500;
|
|
20959
|
+
const r = (v, pt2) => pt2 ? Math.round(pt2 * 100) : Math.round(v * s);
|
|
20960
|
+
return {
|
|
20961
|
+
/** □ 대항목 — HY헤드라인M 16pt */
|
|
20962
|
+
dae: r(1600, ov.dae),
|
|
20963
|
+
/** ※ 참고 — 한양중고딕 13pt */
|
|
20964
|
+
cham: r(1300, ov.cham),
|
|
20965
|
+
/** 장 헤더(로마숫자·제목) 17pt */
|
|
20966
|
+
chapter: r(1700, ov.chapter),
|
|
20967
|
+
/** 표지 제목 30pt */
|
|
20968
|
+
coverTitle: r(3e3, ov.coverTitle),
|
|
20969
|
+
/** 표지 날짜·기관명 25pt */
|
|
20970
|
+
coverSub: r(2500, ov.coverSub),
|
|
20971
|
+
/** 목차 라벨 "목 차" 28pt */
|
|
20972
|
+
tocLabel: r(2800, ov.tocLabel),
|
|
20973
|
+
/** 목차 로마숫자 21pt(한양신명조) */
|
|
20974
|
+
tocRoman: r(2100, ov.tocRoman),
|
|
20975
|
+
/** 목차 항목 18pt */
|
|
20976
|
+
tocItem: r(1800, ov.tocItem),
|
|
20977
|
+
/** 표 셀 — 맑은 고딕 12pt (실측: 정부 양식 표) */
|
|
20978
|
+
table: r(1200, ov.table),
|
|
20979
|
+
/** 표지 장식 바 셀 빈 문단 — 6pt (실측: 바 높이 818 안에 줄높이 수납) */
|
|
20980
|
+
bar: r(600),
|
|
20981
|
+
/** 본문 첫 페이지 제목 박스 — HY헤드라인M 22pt (실측: GT3 표④) */
|
|
20982
|
+
bodyTitle: r(2200, ov.bodyTitle)
|
|
20983
|
+
};
|
|
20984
|
+
}
|
|
20985
|
+
function gaejosikSpaceBefore(depth, bodyHeight) {
|
|
20986
|
+
const s = bodyHeight / 1500;
|
|
20987
|
+
const ui = [3e3, 2e3, 1200, 600][Math.min(depth, 3)];
|
|
20988
|
+
return Math.round(ui * s);
|
|
20989
|
+
}
|
|
20990
|
+
function gaejosikLevelIndent(depth, bodyHeight, sizes = {}) {
|
|
20991
|
+
const lefts = [0, 1, 1.5, 2];
|
|
20992
|
+
const left = depth <= 3 ? Math.round(lefts[depth] * bodyHeight) : Math.round((2 + (depth - 3) * 0.5) * bodyHeight);
|
|
20993
|
+
const h = depth === 0 ? gaejosikSizes(bodyHeight, sizes).dae : bodyHeight;
|
|
20994
|
+
return { left, indent: -markerWidth(gaejosikMarker(depth), h) };
|
|
20995
|
+
}
|
|
20996
|
+
function gaejosikChamIndent(bodyHeight, sizes = {}) {
|
|
20997
|
+
const cham = gaejosikSizes(bodyHeight, sizes).cham;
|
|
20998
|
+
return { left: Math.round(2.5 * cham), indent: -markerWidth("\u203B", cham) };
|
|
20999
|
+
}
|
|
21000
|
+
function gaejosikTocItemIndent(bodyHeight, sizes = {}) {
|
|
21001
|
+
const sz = gaejosikSizes(bodyHeight, sizes);
|
|
21002
|
+
const hang = markerWidth("\u2167.", sz.tocRoman);
|
|
21003
|
+
return { left: 2e3 + hang, indent: -hang };
|
|
21004
|
+
}
|
|
21005
|
+
function formatGaejosikDate(d) {
|
|
21006
|
+
return `${d.getFullYear()}. ${d.getMonth() + 1}. ${d.getDate()}.`;
|
|
21007
|
+
}
|
|
21008
|
+
function stripChapterNumber(title) {
|
|
21009
|
+
return title.replace(/^\s*(?:\d+|[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ]+)\s*[.)]\s*/u, "").trim();
|
|
21010
|
+
}
|
|
21011
|
+
var GAEJOSIK_COLORS = {
|
|
21012
|
+
/** 장헤더 로마숫자 셀·표지 진한 바 음영 */
|
|
21013
|
+
primary: "#193AAA",
|
|
21014
|
+
/** 장헤더 셀 테두리 */
|
|
21015
|
+
border: "#006699",
|
|
21016
|
+
/** 표지 연한 바 */
|
|
21017
|
+
accent: "#A0B4E6",
|
|
21018
|
+
/** 장헤더 제목 셀 음영 */
|
|
21019
|
+
titleFill: "#F2F2F2",
|
|
21020
|
+
/** 장헤더 제목 셀 상하선 */
|
|
21021
|
+
titleLine: "#A6A6A6",
|
|
21022
|
+
/** 목차 박스 테두리 */
|
|
21023
|
+
tocBorder: "#514BAC",
|
|
21024
|
+
/** 목차 배너 라벤더 스트라이프 (실측: GT3 표②) */
|
|
21025
|
+
tocStripe: "#E0E5FA"
|
|
21026
|
+
};
|
|
21027
|
+
var CHAPTER_GEOM = { numW: 3327, gapW: 848, titleW: 43513, rowH: 2832 };
|
|
21028
|
+
var COVER_GEOM = {
|
|
21029
|
+
totalW: 48180,
|
|
21030
|
+
topDarkW: 38219,
|
|
21031
|
+
topLightW: 9961,
|
|
21032
|
+
barH: 818,
|
|
21033
|
+
titleH: 11060,
|
|
21034
|
+
botDarkW: 10466,
|
|
21035
|
+
botLightW: 37714,
|
|
21036
|
+
botBarH: 812
|
|
21037
|
+
};
|
|
21038
|
+
var TOC_GEOM = { boxW: 46492, boxH: 57840 };
|
|
21039
|
+
function chapterGeom(bodyHeight, ov = {}) {
|
|
21040
|
+
const s = gaejosikSizes(bodyHeight, ov).chapter / 1700;
|
|
21041
|
+
return { ...CHAPTER_GEOM, rowH: Math.round(CHAPTER_GEOM.rowH * s) };
|
|
21042
|
+
}
|
|
21043
|
+
function coverGeom(bodyHeight, ov = {}) {
|
|
21044
|
+
const s = gaejosikSizes(bodyHeight, ov).coverTitle / 3e3;
|
|
21045
|
+
return { ...COVER_GEOM, titleH: Math.round(COVER_GEOM.titleH * s) };
|
|
21046
|
+
}
|
|
21047
|
+
var TOC_BANNER_GEOM = {
|
|
21048
|
+
colWs: [565, 565, 1414, 13191, 1414, 565, 565],
|
|
21049
|
+
h: 3931
|
|
21050
|
+
};
|
|
21051
|
+
function tocBannerGeom(bodyHeight, ov = {}) {
|
|
21052
|
+
const s = gaejosikSizes(bodyHeight, ov).tocLabel / 2800;
|
|
21053
|
+
return { colWs: TOC_BANNER_GEOM.colWs, h: Math.round(TOC_BANNER_GEOM.h * s) };
|
|
21054
|
+
}
|
|
21055
|
+
var BODY_TITLE_GEOM = { barH: 600, titleH: 3566 };
|
|
21056
|
+
function bodyTitleGeom(bodyHeight, ov = {}) {
|
|
21057
|
+
const s = gaejosikSizes(bodyHeight, ov).bodyTitle / 2200;
|
|
21058
|
+
return { barH: BODY_TITLE_GEOM.barH, titleH: Math.round(BODY_TITLE_GEOM.titleH * s) };
|
|
21059
|
+
}
|
|
21060
|
+
|
|
20942
21061
|
// src/hwpx/gongmun.ts
|
|
20943
21062
|
var OFFICIAL_MARGINS = { top: 20, bottom: 10, left: 20, right: 20 };
|
|
21063
|
+
var GAEJOSIK_MARGINS = { top: 15, bottom: 15, left: 20, right: 20 };
|
|
21064
|
+
var GAEJOSIK_HEADER_FOOTER = 4251;
|
|
20944
21065
|
var PRESET_DEFAULTS = {
|
|
20945
21066
|
official: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
20946
21067
|
report: { bodyPt: 15, lineSpacing: 160, numbering: "report" },
|
|
20947
21068
|
plan: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
20948
21069
|
notice: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
20949
|
-
minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" }
|
|
21070
|
+
minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" },
|
|
21071
|
+
gaejosik: { bodyPt: 15, lineSpacing: 160, numbering: "gaejosik" }
|
|
20950
21072
|
};
|
|
20951
21073
|
var PRESET_ALIAS = {
|
|
20952
21074
|
official: "official",
|
|
@@ -20964,7 +21086,12 @@ var PRESET_ALIAS = {
|
|
|
20964
21086
|
\uC54C\uB9BC: "notice",
|
|
20965
21087
|
\uC548\uB0B4: "notice",
|
|
20966
21088
|
minutes: "minutes",
|
|
20967
|
-
\uD68C\uC758\uB85D: "minutes"
|
|
21089
|
+
\uD68C\uC758\uB85D: "minutes",
|
|
21090
|
+
gaejosik: "gaejosik",
|
|
21091
|
+
\uAC1C\uC870\uC2DD: "gaejosik",
|
|
21092
|
+
\uAC1C\uC870\uC2DD\uBCF4\uACE0\uC11C: "gaejosik",
|
|
21093
|
+
\uC815\uBD80\uBCF4\uACE0\uC11C: "gaejosik",
|
|
21094
|
+
\uC815\uBD80\uD45C\uC900\uAC1C\uC870\uC2DD\uBCF4\uACE0\uC11C: "gaejosik"
|
|
20968
21095
|
};
|
|
20969
21096
|
function normalizeGongmunPreset(preset) {
|
|
20970
21097
|
if (!preset) return "official";
|
|
@@ -20975,15 +21102,30 @@ function resolveGongmun(opts) {
|
|
|
20975
21102
|
const d = PRESET_DEFAULTS[preset];
|
|
20976
21103
|
const bodyPt = opts.bodyPt ?? d.bodyPt;
|
|
20977
21104
|
const autoFitMinRatio = opts.autoFit === false ? null : typeof opts.autoFit === "object" ? Math.min(Math.max(opts.autoFit.minRatio ?? 90, 50), 99) : 90;
|
|
21105
|
+
const coverOn = opts.cover !== void 0 ? opts.cover !== false : preset === "gaejosik";
|
|
21106
|
+
const coverOpts = typeof opts.cover === "object" ? opts.cover : {};
|
|
21107
|
+
const gaejosik = preset === "gaejosik";
|
|
20978
21108
|
return {
|
|
20979
21109
|
preset,
|
|
20980
21110
|
bodyFont: opts.bodyFont ?? "myeongjo",
|
|
20981
21111
|
bodyHeight: Math.round(bodyPt * 100),
|
|
20982
21112
|
lineSpacing: opts.lineSpacing ?? d.lineSpacing,
|
|
20983
21113
|
numbering: opts.numbering ?? d.numbering,
|
|
20984
|
-
margins: opts.margins ?? OFFICIAL_MARGINS,
|
|
21114
|
+
margins: opts.margins ?? (gaejosik ? GAEJOSIK_MARGINS : OFFICIAL_MARGINS),
|
|
20985
21115
|
centerTitle: opts.centerTitle ?? true,
|
|
20986
|
-
autoFitMinRatio
|
|
21116
|
+
autoFitMinRatio,
|
|
21117
|
+
cover: coverOn ? { date: coverOpts.date ?? null, org: coverOpts.org ?? "" } : null,
|
|
21118
|
+
toc: opts.toc ?? gaejosik,
|
|
21119
|
+
fonts: opts.fonts ?? {},
|
|
21120
|
+
sizes: opts.sizes ?? {},
|
|
21121
|
+
// 쪽번호 — 보고서 계열 관행(실측: 2_보고서 양식·추진계획·공고문 전부 하단 중앙)
|
|
21122
|
+
pageNumbers: opts.pageNumbers ?? (gaejosik || preset === "report" || preset === "plan"),
|
|
21123
|
+
headerFooter: gaejosik ? GAEJOSIK_HEADER_FOOTER : 0,
|
|
21124
|
+
// "끝." — 기안문 규정(본문 끝 2타+"끝."). 그 외는 opt-in
|
|
21125
|
+
endMark: opts.endMark ?? preset === "official",
|
|
21126
|
+
approval: opts.approval && opts.approval.length > 0 ? opts.approval : null,
|
|
21127
|
+
// 본문 제목박스 — 실측(GT3·GT12): 목차 뒤 본문 시작에 제목 반복. 표지 켜진 개조식 기본
|
|
21128
|
+
bodyTitleBox: opts.bodyTitleBox ?? (gaejosik && coverOn)
|
|
20987
21129
|
};
|
|
20988
21130
|
}
|
|
20989
21131
|
var HANGUL_INITIALS = [0, 2, 3, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18];
|
|
@@ -21031,7 +21173,8 @@ function markerWidth(marker, bodyHeight) {
|
|
|
21031
21173
|
for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
|
|
21032
21174
|
return Math.round(em / 1e3 * bodyHeight);
|
|
21033
21175
|
}
|
|
21034
|
-
function levelIndent(depth, bodyHeight, numbering) {
|
|
21176
|
+
function levelIndent(depth, bodyHeight, numbering, sizes = {}) {
|
|
21177
|
+
if (numbering === "gaejosik") return gaejosikLevelIndent(depth, bodyHeight, sizes);
|
|
21035
21178
|
const marker = numbering === "report" ? reportMarker(depth) : standardMarker(depth, 0);
|
|
21036
21179
|
return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, bodyHeight) };
|
|
21037
21180
|
}
|
|
@@ -21059,6 +21202,7 @@ var GongmunNumberer = class {
|
|
|
21059
21202
|
const n = this.counts[depth] ?? 0;
|
|
21060
21203
|
this.counts[depth] = n + 1;
|
|
21061
21204
|
if (suppress) return "";
|
|
21205
|
+
if (this.numbering === "gaejosik") return gaejosikMarker(depth);
|
|
21062
21206
|
return this.numbering === "report" ? reportMarker(depth) : standardMarker(depth, n);
|
|
21063
21207
|
}
|
|
21064
21208
|
reset() {
|
|
@@ -21126,27 +21270,28 @@ function headingCharPrId(level) {
|
|
|
21126
21270
|
if (level === 3) return CHAR_H3;
|
|
21127
21271
|
return CHAR_H4;
|
|
21128
21272
|
}
|
|
21129
|
-
function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100) {
|
|
21273
|
+
function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100, keepFontOnBold = false) {
|
|
21130
21274
|
const boldAttr = bold ? ` bold="1"` : "";
|
|
21131
21275
|
const italicAttr = italic ? ` italic="1"` : "";
|
|
21132
|
-
const effFont = bold ? 2 : fontId;
|
|
21276
|
+
const effFont = bold && !keepFontOnBold ? 2 : fontId;
|
|
21277
|
+
const boldEl = bold ? `<hh:bold/>` : "";
|
|
21133
21278
|
return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
21134
21279
|
<hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
|
|
21135
21280
|
<hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
|
|
21136
21281
|
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
21137
21282
|
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
21138
|
-
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"
|
|
21283
|
+
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>${boldEl}
|
|
21139
21284
|
</hh:charPr>`;
|
|
21140
21285
|
}
|
|
21141
21286
|
function paraPr(id, opts = {}) {
|
|
21142
|
-
const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, keepWord = false, outlineLevel } = opts;
|
|
21143
|
-
const breakNonLatin = keepWord ? "
|
|
21287
|
+
const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, keepWord = false, keepWithNext = false, outlineLevel } = opts;
|
|
21288
|
+
const breakNonLatin = keepWord ? "BREAK_WORD" : "KEEP_WORD";
|
|
21144
21289
|
const snapGrid = keepWord ? "0" : "1";
|
|
21145
21290
|
const heading = outlineLevel !== void 0 ? `<hh:heading type="OUTLINE" idRef="0" level="${outlineLevel}"/>` : `<hh:heading type="NONE" idRef="0" level="0"/>`;
|
|
21146
21291
|
return ` <hh:paraPr id="${id}" tabPrIDRef="0" condense="0" fontLineHeight="0" snapToGrid="${snapGrid}" suppressLineNumbers="0" checked="0" textDir="AUTO">
|
|
21147
21292
|
<hh:align horizontal="${align}" vertical="BASELINE"/>
|
|
21148
21293
|
${heading}
|
|
21149
|
-
<hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="0" keepWithNext="0" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
|
|
21294
|
+
<hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="0" keepWithNext="${keepWithNext ? 1 : 0}" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
|
|
21150
21295
|
<hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
|
|
21151
21296
|
<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>
|
|
21152
21297
|
<hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
|
|
@@ -21156,7 +21301,72 @@ function paraPr(id, opts = {}) {
|
|
|
21156
21301
|
var GONGMUN_LIST_BASE = 8;
|
|
21157
21302
|
var GONGMUN_LIST_LEVELS = 8;
|
|
21158
21303
|
var GONGMUN_CENTER = GONGMUN_LIST_BASE + GONGMUN_LIST_LEVELS;
|
|
21304
|
+
var GONGMUN_RIGHT = GONGMUN_CENTER + 1;
|
|
21305
|
+
var GONGMUN_TBL_CENTER = GONGMUN_RIGHT + 1;
|
|
21306
|
+
var GONGMUN_TBL_LEFT = GONGMUN_TBL_CENTER + 1;
|
|
21307
|
+
var GJ_CHAR_DAE = 11;
|
|
21308
|
+
var GJ_CHAR_DAE_BOLD = 12;
|
|
21309
|
+
var GJ_CHAR_CHAM = 13;
|
|
21310
|
+
var GJ_CHAR_CHAM_BOLD = 14;
|
|
21311
|
+
var GJ_CHAR_CHAPTER_NUM = 15;
|
|
21312
|
+
var GJ_CHAR_CHAPTER_TITLE = 16;
|
|
21313
|
+
var GJ_CHAR_COVER_TITLE = 17;
|
|
21314
|
+
var GJ_CHAR_COVER_SUB = 18;
|
|
21315
|
+
var GJ_CHAR_TOC_LABEL = 19;
|
|
21316
|
+
var GJ_CHAR_TOC_ROMAN = 20;
|
|
21317
|
+
var GJ_CHAR_TOC_ITEM = 21;
|
|
21318
|
+
var GJ_CHAR_TABLE = 22;
|
|
21319
|
+
var GJ_CHAR_TABLE_BOLD = 23;
|
|
21320
|
+
var GJ_CHAR_BAR = 24;
|
|
21321
|
+
var GJ_CHAR_BODY_TITLE = 25;
|
|
21322
|
+
var GJ_CHAR_COUNT = 15;
|
|
21323
|
+
var GJ_PARA_CHAM = 20;
|
|
21324
|
+
var GJ_PARA_COVER = 21;
|
|
21325
|
+
var GJ_PARA_TOC_ITEM = 22;
|
|
21326
|
+
var GJ_PARA_CHAPTER = 23;
|
|
21327
|
+
var GJ_PARA_BAR = 24;
|
|
21328
|
+
var GJ_BF_CHAPTER_NUM = 3;
|
|
21329
|
+
var GJ_BF_CHAPTER_GAP = 4;
|
|
21330
|
+
var GJ_BF_CHAPTER_TITLE = 5;
|
|
21331
|
+
var GJ_BF_BAR_DARK = 6;
|
|
21332
|
+
var GJ_BF_BAR_LIGHT = 7;
|
|
21333
|
+
var GJ_BF_TOC_BOX = 8;
|
|
21334
|
+
var GJ_BF_TOC_STRIPE = 9;
|
|
21335
|
+
function gongmunTableHeaderBf(gaejosik) {
|
|
21336
|
+
return gaejosik ? 10 : 3;
|
|
21337
|
+
}
|
|
21338
|
+
function borderFillEntry(id, b, fill) {
|
|
21339
|
+
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"/>`;
|
|
21340
|
+
let brush = "";
|
|
21341
|
+
if (typeof fill === "string") {
|
|
21342
|
+
brush = `
|
|
21343
|
+
<hc:fillBrush><hc:winBrush faceColor="${fill}" hatchColor="#000000" alpha="0"/></hc:fillBrush>`;
|
|
21344
|
+
} else if (fill) {
|
|
21345
|
+
brush = `
|
|
21346
|
+
<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>`;
|
|
21347
|
+
}
|
|
21348
|
+
return ` <hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
21349
|
+
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
21350
|
+
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
21351
|
+
${side("leftBorder", b.l)}
|
|
21352
|
+
${side("rightBorder", b.r)}
|
|
21353
|
+
${side("topBorder", b.t)}
|
|
21354
|
+
${side("bottomBorder", b.b)}${brush}
|
|
21355
|
+
</hh:borderFill>`;
|
|
21356
|
+
}
|
|
21357
|
+
function pageNumCtrl() {
|
|
21358
|
+
return `<hp:ctrl><hp:pageNum pos="BOTTOM_CENTER" formatType="DIGIT" sideChar="-"/></hp:ctrl>`;
|
|
21359
|
+
}
|
|
21360
|
+
function newPageNumCtrl(num4 = 1) {
|
|
21361
|
+
return `<hp:ctrl><hp:newNum num="${num4}" numType="PAGE"/></hp:ctrl>`;
|
|
21362
|
+
}
|
|
21363
|
+
function pageHidingCtrl(hideHeader = false) {
|
|
21364
|
+
return `<hp:ctrl><hp:pageHiding hideHeader="${hideHeader ? 1 : 0}" hideFooter="0" hideMasterPage="0" hideBorder="0" hideFill="0" hidePageNum="1"/></hp:ctrl>`;
|
|
21365
|
+
}
|
|
21159
21366
|
var CHAR_VARIANT_BASE = 11;
|
|
21367
|
+
function charVariantBase(gaejosik) {
|
|
21368
|
+
return gaejosik ? CHAR_VARIANT_BASE + GJ_CHAR_COUNT : CHAR_VARIANT_BASE;
|
|
21369
|
+
}
|
|
21160
21370
|
var GONGMUN_BODY_RATIO = 95;
|
|
21161
21371
|
|
|
21162
21372
|
// src/hwpx/md-runs.ts
|
|
@@ -21370,12 +21580,12 @@ function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
|
|
|
21370
21580
|
return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
|
|
21371
21581
|
}).join("");
|
|
21372
21582
|
}
|
|
21373
|
-
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId) {
|
|
21583
|
+
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId, styleId = 0) {
|
|
21374
21584
|
if (paraPrId === PARA_CODE) {
|
|
21375
21585
|
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
|
|
21376
21586
|
}
|
|
21377
21587
|
const runs = generateRuns(text, charPrId, mapCharId);
|
|
21378
|
-
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="
|
|
21588
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="${styleId}">${runs}</hp:p>`;
|
|
21379
21589
|
}
|
|
21380
21590
|
|
|
21381
21591
|
// src/hwpx/gen-header.ts
|
|
@@ -21403,6 +21613,7 @@ function generateManifest(chartParts = []) {
|
|
|
21403
21613
|
</opf:package>`;
|
|
21404
21614
|
}
|
|
21405
21615
|
function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls = []) {
|
|
21616
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
21406
21617
|
let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
|
|
21407
21618
|
if (gongmun) {
|
|
21408
21619
|
body = gongmun.bodyHeight;
|
|
@@ -21412,26 +21623,62 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
|
|
|
21412
21623
|
h3 = body;
|
|
21413
21624
|
h4 = Math.max(body - 100, 1300);
|
|
21414
21625
|
}
|
|
21626
|
+
const bodyFont = gaejosik ? 4 : 0;
|
|
21415
21627
|
const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
|
|
21416
21628
|
const rows = [
|
|
21417
|
-
charPr(0, body, false, false,
|
|
21418
|
-
charPr(1, body, true, false,
|
|
21419
|
-
charPr(2, body, false, true,
|
|
21420
|
-
charPr(3, body, true, true,
|
|
21629
|
+
charPr(0, body, false, false, bodyFont, theme.body, bodyRatio),
|
|
21630
|
+
charPr(1, body, true, false, bodyFont, theme.body, bodyRatio),
|
|
21631
|
+
charPr(2, body, false, true, bodyFont, theme.body, bodyRatio),
|
|
21632
|
+
charPr(3, body, true, true, bodyFont, theme.body, bodyRatio),
|
|
21421
21633
|
charPr(4, code, false, false, 1),
|
|
21422
21634
|
charPr(5, h1, true, false, 1, theme.h1),
|
|
21423
21635
|
charPr(6, h2, true, false, 1, theme.h2),
|
|
21424
21636
|
charPr(7, h3, true, false, 1, theme.h3),
|
|
21425
21637
|
charPr(8, h4, true, false, 1, theme.h4),
|
|
21426
|
-
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false,
|
|
21427
|
-
charPr(CHAR_QUOTE, body, false, true,
|
|
21638
|
+
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, bodyFont, theme.tableHeader),
|
|
21639
|
+
charPr(CHAR_QUOTE, body, false, true, bodyFont, theme.quote)
|
|
21428
21640
|
];
|
|
21641
|
+
if (gaejosik) {
|
|
21642
|
+
const sz = gaejosikSizes(body, gongmun.sizes);
|
|
21643
|
+
rows.push(
|
|
21644
|
+
charPr(11, sz.dae, false, false, 3),
|
|
21645
|
+
// □ HY헤드라인M
|
|
21646
|
+
charPr(12, sz.dae, true, false, 3, "#000000", 100, true),
|
|
21647
|
+
// □ bold
|
|
21648
|
+
charPr(13, sz.cham, false, false, 5),
|
|
21649
|
+
// ※ 한양중고딕
|
|
21650
|
+
charPr(14, sz.cham, true, false, 5, "#000000", 100, true),
|
|
21651
|
+
// ※ bold
|
|
21652
|
+
charPr(15, sz.chapter, true, false, 4, "#FFFFFF", 100, true),
|
|
21653
|
+
// 장 로마숫자(흰)
|
|
21654
|
+
charPr(16, sz.chapter, false, false, 3),
|
|
21655
|
+
// 장 제목
|
|
21656
|
+
charPr(17, sz.coverTitle, false, false, 3),
|
|
21657
|
+
// 표지 제목
|
|
21658
|
+
charPr(18, sz.coverSub, false, false, 3),
|
|
21659
|
+
// 표지 날짜·기관명
|
|
21660
|
+
charPr(19, sz.tocLabel, true, false, 3, "#000000", 100, true),
|
|
21661
|
+
// 목 차
|
|
21662
|
+
charPr(20, sz.tocRoman, true, false, 6, "#000000", 100, true),
|
|
21663
|
+
// 목차 로마숫자(한양신명조)
|
|
21664
|
+
charPr(21, sz.tocItem, false, false, 3),
|
|
21665
|
+
// 목차 항목
|
|
21666
|
+
charPr(22, sz.table, false, false, 7),
|
|
21667
|
+
// 표 셀(맑은 고딕 12pt)
|
|
21668
|
+
charPr(23, sz.table, true, false, 7, "#000000", 100, true),
|
|
21669
|
+
// 표 셀 bold
|
|
21670
|
+
charPr(24, sz.bar, false, false, 4),
|
|
21671
|
+
// 표지 바 셀 빈 문단(6pt)
|
|
21672
|
+
charPr(25, sz.bodyTitle, false, false, 3)
|
|
21673
|
+
// 본문 제목박스(HY헤드라인M 22pt, 실측 GT3 표④)
|
|
21674
|
+
);
|
|
21675
|
+
}
|
|
21429
21676
|
for (const r of ratioVariants) {
|
|
21430
21677
|
rows.push(
|
|
21431
|
-
charPr(rows.length, body, false, false,
|
|
21432
|
-
charPr(rows.length + 1, body, true, false,
|
|
21433
|
-
charPr(rows.length + 2, body, false, true,
|
|
21434
|
-
charPr(rows.length + 3, body, true, true,
|
|
21678
|
+
charPr(rows.length, body, false, false, bodyFont, theme.body, r),
|
|
21679
|
+
charPr(rows.length + 1, body, true, false, bodyFont, theme.body, r),
|
|
21680
|
+
charPr(rows.length + 2, body, false, true, bodyFont, theme.body, r),
|
|
21681
|
+
charPr(rows.length + 3, body, true, true, bodyFont, theme.body, r)
|
|
21435
21682
|
);
|
|
21436
21683
|
}
|
|
21437
21684
|
rows.push(...extraCharPrXmls);
|
|
@@ -21442,14 +21689,14 @@ ${rows.join("\n")}
|
|
|
21442
21689
|
function buildParaProperties(gongmun) {
|
|
21443
21690
|
if (!gongmun) {
|
|
21444
21691
|
const base2 = [
|
|
21445
|
-
paraPr(0),
|
|
21446
|
-
paraPr(1, { align: "LEFT", spaceBefore: 800, spaceAfter: 200, lineSpacing: 180, outlineLevel: 0 }),
|
|
21447
|
-
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: 170, outlineLevel: 1 }),
|
|
21448
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: 160, outlineLevel: 2 }),
|
|
21449
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160, outlineLevel: 3 }),
|
|
21450
|
-
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400 }),
|
|
21451
|
-
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600 }),
|
|
21452
|
-
paraPr(7, { align: "LEFT", lineSpacing: 160, indent: 600 })
|
|
21692
|
+
paraPr(0, { keepWord: true }),
|
|
21693
|
+
paraPr(1, { align: "LEFT", spaceBefore: 800, spaceAfter: 200, lineSpacing: 180, outlineLevel: 0, keepWord: true }),
|
|
21694
|
+
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: 170, outlineLevel: 1, keepWord: true }),
|
|
21695
|
+
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: 160, outlineLevel: 2, keepWord: true }),
|
|
21696
|
+
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160, outlineLevel: 3, keepWord: true }),
|
|
21697
|
+
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
21698
|
+
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600, keepWord: true }),
|
|
21699
|
+
paraPr(7, { align: "LEFT", lineSpacing: 160, indent: 600, keepWord: true })
|
|
21453
21700
|
];
|
|
21454
21701
|
return `<hh:paraProperties itemCnt="${base2.length}">
|
|
21455
21702
|
${base2.join("\n")}
|
|
@@ -21459,20 +21706,37 @@ ${base2.join("\n")}
|
|
|
21459
21706
|
const titleAlign = gongmun.centerTitle ? "CENTER" : "LEFT";
|
|
21460
21707
|
const base = [
|
|
21461
21708
|
paraPr(0, { lineSpacing: ls, keepWord: true }),
|
|
21462
|
-
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true
|
|
21463
|
-
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: ls, keepWord: true
|
|
21464
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true
|
|
21465
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true
|
|
21709
|
+
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true }),
|
|
21710
|
+
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: ls, keepWord: true }),
|
|
21711
|
+
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
21712
|
+
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
21466
21713
|
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
21467
21714
|
paraPr(6, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true }),
|
|
21468
21715
|
paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
|
|
21469
21716
|
];
|
|
21470
21717
|
for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
|
|
21471
|
-
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering);
|
|
21472
|
-
const sectionGap = gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
21473
|
-
|
|
21718
|
+
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes);
|
|
21719
|
+
const sectionGap = gongmun.numbering === "gaejosik" ? gaejosikSpaceBefore(d, gongmun.bodyHeight) : gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
21720
|
+
const keepNext = gongmun.numbering === "gaejosik" && d === 0;
|
|
21721
|
+
base.push(paraPr(GONGMUN_LIST_BASE + d, { align: "JUSTIFY", lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext }));
|
|
21474
21722
|
}
|
|
21475
21723
|
base.push(paraPr(GONGMUN_CENTER, { align: "CENTER", lineSpacing: ls, keepWord: true }));
|
|
21724
|
+
base.push(paraPr(GONGMUN_RIGHT, { align: "RIGHT", lineSpacing: ls, keepWord: true }));
|
|
21725
|
+
base.push(paraPr(GONGMUN_TBL_CENTER, { align: "CENTER", lineSpacing: 130, keepWord: true }));
|
|
21726
|
+
base.push(paraPr(GONGMUN_TBL_LEFT, { align: "LEFT", lineSpacing: 130, keepWord: true }));
|
|
21727
|
+
if (gongmun.preset === "gaejosik") {
|
|
21728
|
+
const cham = gaejosikChamIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
21729
|
+
const toc = gaejosikTocItemIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
21730
|
+
base.push(
|
|
21731
|
+
paraPr(GJ_PARA_CHAM, { align: "JUSTIFY", lineSpacing: ls, left: cham.left, indent: cham.indent, spaceBefore: gaejosikSpaceBefore(3, gongmun.bodyHeight), keepWord: true }),
|
|
21732
|
+
paraPr(GJ_PARA_COVER, { align: "CENTER", lineSpacing: 130, keepWord: true }),
|
|
21733
|
+
paraPr(GJ_PARA_TOC_ITEM, { align: "LEFT", lineSpacing: 160, left: toc.left, indent: toc.indent, spaceBefore: 1800, keepWord: true }),
|
|
21734
|
+
// 장 헤더는 다음 문단과 같은 쪽에 — 쪽 하단 고아 헤더 방지 (실렌더 확인 이슈)
|
|
21735
|
+
paraPr(GJ_PARA_CHAPTER, { align: "LEFT", lineSpacing: ls, spaceBefore: 2400, spaceAfter: 600, keepWord: true, keepWithNext: true }),
|
|
21736
|
+
// 표지 장식 바 셀 빈 문단 — 저줄간격(실측 71%)으로 바 높이 818 안에 수납
|
|
21737
|
+
paraPr(GJ_PARA_BAR, { align: "CENTER", lineSpacing: 70, keepWord: true })
|
|
21738
|
+
);
|
|
21739
|
+
}
|
|
21476
21740
|
return `<hh:paraProperties itemCnt="${base.length}">
|
|
21477
21741
|
${base.join("\n")}
|
|
21478
21742
|
</hh:paraProperties>`;
|
|
@@ -21488,25 +21752,37 @@ ${heads}
|
|
|
21488
21752
|
</hh:numbering>
|
|
21489
21753
|
</hh:numberings>`;
|
|
21490
21754
|
}
|
|
21491
|
-
function
|
|
21492
|
-
|
|
21493
|
-
|
|
21494
|
-
|
|
21495
|
-
|
|
21496
|
-
|
|
21497
|
-
|
|
21498
|
-
|
|
21499
|
-
|
|
21755
|
+
function fontEntry(id, face, weight = 6) {
|
|
21756
|
+
return ` <hh:font id="${id}" face="${face}" type="TTF" isEmbedded="0">
|
|
21757
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="${weight}" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21758
|
+
</hh:font>`;
|
|
21759
|
+
}
|
|
21760
|
+
function buildFontFaces(gongmun, bodyFace) {
|
|
21761
|
+
if (gongmun?.preset === "gaejosik") {
|
|
21762
|
+
const ov = gongmun.fonts;
|
|
21763
|
+
const faces = [
|
|
21764
|
+
"\uD568\uCD08\uB86C\uBC14\uD0D5",
|
|
21765
|
+
"\uD568\uCD08\uB86C\uB3CB\uC6C0",
|
|
21766
|
+
"HY\uACAC\uACE0\uB515",
|
|
21767
|
+
ov.heading ?? "HY\uD5E4\uB4DC\uB77C\uC778M",
|
|
21768
|
+
ov.body ?? "\uD734\uBA3C\uBA85\uC870",
|
|
21769
|
+
ov.ref ?? "\uD55C\uC591\uC911\uACE0\uB515",
|
|
21770
|
+
"\uD55C\uC591\uC2E0\uBA85\uC870",
|
|
21771
|
+
ov.table ?? "\uB9D1\uC740 \uACE0\uB515"
|
|
21772
|
+
];
|
|
21773
|
+
const list = faces.map((f, i) => fontEntry(i, f, i === 2 || i === 3 ? 9 : 6)).join("\n");
|
|
21774
|
+
const langs = ["HANGUL", "LATIN", "HANJA", "JAPANESE", "OTHER", "SYMBOL", "USER"];
|
|
21775
|
+
return `<hh:fontfaces itemCnt="${langs.length}">
|
|
21776
|
+
` + langs.map((l) => ` <hh:fontface lang="${l}" fontCnt="${faces.length}">
|
|
21777
|
+
${list}
|
|
21778
|
+
</hh:fontface>`).join("\n") + `
|
|
21779
|
+
</hh:fontfaces>`;
|
|
21780
|
+
}
|
|
21781
|
+
return `<hh:fontfaces itemCnt="7">
|
|
21500
21782
|
<hh:fontface lang="HANGUL" fontCnt="3">
|
|
21501
|
-
|
|
21502
|
-
|
|
21503
|
-
|
|
21504
|
-
<hh:font id="1" face="\uD568\uCD08\uB86C\uB3CB\uC6C0" type="TTF" isEmbedded="0">
|
|
21505
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21506
|
-
</hh:font>
|
|
21507
|
-
<hh:font id="2" face="HY\uACAC\uACE0\uB515" type="TTF" isEmbedded="0">
|
|
21508
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="9" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21509
|
-
</hh:font>
|
|
21783
|
+
${fontEntry(0, bodyFace)}
|
|
21784
|
+
${fontEntry(1, "\uD568\uCD08\uB86C\uB3CB\uC6C0")}
|
|
21785
|
+
${fontEntry(2, "HY\uACAC\uACE0\uB515", 9)}
|
|
21510
21786
|
</hh:fontface>
|
|
21511
21787
|
<hh:fontface lang="LATIN" fontCnt="3">
|
|
21512
21788
|
<hh:font id="0" face="Times New Roman" type="TTF" isEmbedded="0">
|
|
@@ -21520,57 +21796,87 @@ function generateHeaderXml(theme, gongmun, ratioVariants = [], remap = null) {
|
|
|
21520
21796
|
</hh:font>
|
|
21521
21797
|
</hh:fontface>
|
|
21522
21798
|
<hh:fontface lang="HANJA" fontCnt="1">
|
|
21523
|
-
|
|
21524
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21525
|
-
</hh:font>
|
|
21799
|
+
${fontEntry(0, "\uD568\uCD08\uB86C\uBC14\uD0D5")}
|
|
21526
21800
|
</hh:fontface>
|
|
21527
21801
|
<hh:fontface lang="JAPANESE" fontCnt="1">
|
|
21528
|
-
|
|
21529
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21530
|
-
</hh:font>
|
|
21802
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
21531
21803
|
</hh:fontface>
|
|
21532
21804
|
<hh:fontface lang="OTHER" fontCnt="1">
|
|
21533
|
-
|
|
21534
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21535
|
-
</hh:font>
|
|
21805
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
21536
21806
|
</hh:fontface>
|
|
21537
21807
|
<hh:fontface lang="SYMBOL" fontCnt="1">
|
|
21538
|
-
|
|
21539
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21540
|
-
</hh:font>
|
|
21808
|
+
${fontEntry(0, "Symbol")}
|
|
21541
21809
|
</hh:fontface>
|
|
21542
21810
|
<hh:fontface lang="USER" fontCnt="1">
|
|
21543
|
-
|
|
21544
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21545
|
-
</hh:font>
|
|
21811
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
21546
21812
|
</hh:fontface>
|
|
21547
|
-
</hh:fontfaces
|
|
21548
|
-
|
|
21549
|
-
|
|
21550
|
-
|
|
21551
|
-
|
|
21552
|
-
|
|
21553
|
-
|
|
21554
|
-
|
|
21555
|
-
|
|
21556
|
-
|
|
21557
|
-
|
|
21558
|
-
|
|
21559
|
-
|
|
21560
|
-
|
|
21561
|
-
|
|
21562
|
-
|
|
21563
|
-
|
|
21564
|
-
|
|
21565
|
-
|
|
21813
|
+
</hh:fontfaces>`;
|
|
21814
|
+
}
|
|
21815
|
+
function buildBorderFills(gongmun, extra = []) {
|
|
21816
|
+
const thin = ["0.12 mm", "#000000"];
|
|
21817
|
+
const items = [
|
|
21818
|
+
borderFillEntry(1, {}),
|
|
21819
|
+
borderFillEntry(2, { l: thin, r: thin, t: thin, b: thin })
|
|
21820
|
+
];
|
|
21821
|
+
if (gongmun?.preset === "gaejosik") {
|
|
21822
|
+
const c = GAEJOSIK_COLORS;
|
|
21823
|
+
const edge = ["0.12 mm", c.border];
|
|
21824
|
+
const grayLine = ["0.1 mm", c.titleLine];
|
|
21825
|
+
const tocEdge = ["0.4 mm", c.tocBorder];
|
|
21826
|
+
items.push(
|
|
21827
|
+
borderFillEntry(3, { l: edge, r: edge, t: edge, b: edge }, c.primary),
|
|
21828
|
+
// 장 로마숫자 셀
|
|
21829
|
+
borderFillEntry(4, { l: edge }),
|
|
21830
|
+
// 장 간격 셀(좌선)
|
|
21831
|
+
borderFillEntry(5, { t: grayLine, b: grayLine }, c.titleFill),
|
|
21832
|
+
// 장 제목 셀
|
|
21833
|
+
borderFillEntry(6, {}, c.primary),
|
|
21834
|
+
// 표지 진한 바
|
|
21835
|
+
borderFillEntry(7, {}, c.accent),
|
|
21836
|
+
// 표지 연한 바
|
|
21837
|
+
borderFillEntry(8, { l: tocEdge, r: tocEdge, t: tocEdge, b: tocEdge }),
|
|
21838
|
+
// 목차 박스
|
|
21839
|
+
borderFillEntry(9, {}, c.tocStripe)
|
|
21840
|
+
// 목차 배너 라벤더 스트라이프
|
|
21841
|
+
);
|
|
21842
|
+
}
|
|
21843
|
+
if (gongmun) {
|
|
21844
|
+
items.push(borderFillEntry(items.length + 1, { l: thin, r: thin, t: thin, b: thin }, "#E6E6E6"));
|
|
21845
|
+
}
|
|
21846
|
+
items.push(...extra);
|
|
21847
|
+
return `<hh:borderFills itemCnt="${items.length}">
|
|
21848
|
+
${items.join("\n")}
|
|
21849
|
+
</hh:borderFills>`;
|
|
21850
|
+
}
|
|
21851
|
+
function buildStyles(gongmun) {
|
|
21852
|
+
const items = [
|
|
21853
|
+
`<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>`
|
|
21854
|
+
];
|
|
21855
|
+
if (gongmun) {
|
|
21856
|
+
for (let lvl = 1; lvl <= 4; lvl++) {
|
|
21857
|
+
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"/>`);
|
|
21858
|
+
}
|
|
21859
|
+
}
|
|
21860
|
+
return `<hh:styles itemCnt="${items.length}">
|
|
21861
|
+
${items.join("\n ")}
|
|
21862
|
+
</hh:styles>`;
|
|
21863
|
+
}
|
|
21864
|
+
function generateHeaderXml(theme, gongmun, ratioVariants = [], extraBorderFills = [], extraCharPrXmls = []) {
|
|
21865
|
+
const bodyFace = gongmun?.fonts.body ?? (gongmun?.bodyFont === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5");
|
|
21866
|
+
const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants, extraCharPrXmls);
|
|
21867
|
+
const paraPropsXml = buildParaProperties(gongmun);
|
|
21868
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
|
21869
|
+
<hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" xmlns:hc="${NS_CORE}" version="1.4" secCnt="1">
|
|
21870
|
+
<hh:beginNum page="1" footnote="1" endnote="1" pic="1" tbl="1" equation="1"/>
|
|
21871
|
+
<hh:refList>
|
|
21872
|
+
${buildFontFaces(gongmun, bodyFace)}
|
|
21873
|
+
${buildBorderFills(gongmun, extraBorderFills)}
|
|
21566
21874
|
${charPropsXml}
|
|
21567
21875
|
<hh:tabProperties itemCnt="0"/>
|
|
21568
21876
|
${buildNumberings()}
|
|
21569
21877
|
<hh:bullets itemCnt="0"/>
|
|
21570
21878
|
${paraPropsXml}
|
|
21571
|
-
|
|
21572
|
-
<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>
|
|
21573
|
-
</hh:styles>
|
|
21879
|
+
${buildStyles(gongmun)}
|
|
21574
21880
|
</hh:refList>
|
|
21575
21881
|
<hh:compatibleDocument targetProgram="HWP2018"><hh:layoutCompatibility/></hh:compatibleDocument>
|
|
21576
21882
|
</hh:head>`;
|
|
@@ -21806,6 +22112,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
21806
22112
|
let contW;
|
|
21807
22113
|
if (block.type === "list_item" && gongmunList.has(i)) {
|
|
21808
22114
|
const { marker, depth } = gongmunList.get(i);
|
|
22115
|
+
if (gongmun.numbering === "gaejosik" && (depth === 0 || (block.text || "").trimStart().startsWith("\u203B"))) continue;
|
|
21809
22116
|
const content = plainRenderText(block.text || "");
|
|
21810
22117
|
text = marker ? `${marker} ${content}` : content;
|
|
21811
22118
|
const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
|
|
@@ -21814,6 +22121,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
21814
22121
|
} else if (block.type === "paragraph") {
|
|
21815
22122
|
const raw = (block.text || "").trim();
|
|
21816
22123
|
if (/^<center>[\s\S]*<\/center>$/i.test(raw)) continue;
|
|
22124
|
+
if (gongmun.numbering === "gaejosik" && raw.startsWith("\u203B")) continue;
|
|
21817
22125
|
text = plainRenderText(raw);
|
|
21818
22126
|
firstW = contW = pageW;
|
|
21819
22127
|
} else {
|
|
@@ -21827,14 +22135,15 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
21827
22135
|
}
|
|
21828
22136
|
return ratioByBlock.size > 0 ? { ratioByBlock, variants } : null;
|
|
21829
22137
|
}
|
|
21830
|
-
function variantMapper(fit, blockIdx) {
|
|
22138
|
+
function variantMapper(fit, blockIdx, base = CHAR_VARIANT_BASE) {
|
|
21831
22139
|
const r = fit.ratioByBlock.get(blockIdx);
|
|
21832
22140
|
if (r === void 0) return void 0;
|
|
21833
22141
|
const vi = fit.variants.indexOf(r);
|
|
21834
|
-
return (id) => id >= 0 && id <= 3 ?
|
|
22142
|
+
return (id) => id >= 0 && id <= 3 ? base + vi * 4 + id : id;
|
|
21835
22143
|
}
|
|
21836
22144
|
function precomputeGongmunList(blocks, gongmun) {
|
|
21837
22145
|
const result = /* @__PURE__ */ new Map();
|
|
22146
|
+
const depthOffset = gongmun.numbering === "gaejosik" && blocks.some((b) => b.type === "heading" && b.level === 3) ? 1 : 0;
|
|
21838
22147
|
let i = 0;
|
|
21839
22148
|
while (i < blocks.length) {
|
|
21840
22149
|
if (blocks[i].type !== "list_item") {
|
|
@@ -21860,7 +22169,7 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
21860
22169
|
}
|
|
21861
22170
|
break;
|
|
21862
22171
|
}
|
|
21863
|
-
const depths = run.map((bi) => Math.min(Math.max(blocks[bi].indent || 0, 0), GONGMUN_LIST_LEVELS - 1));
|
|
22172
|
+
const depths = run.map((bi) => Math.min(Math.max((blocks[bi].indent || 0) + depthOffset, 0), GONGMUN_LIST_LEVELS - 1));
|
|
21864
22173
|
const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
|
|
21865
22174
|
const numberer = new GongmunNumberer(gongmun.numbering);
|
|
21866
22175
|
run.forEach((bi, k) => {
|
|
@@ -21871,6 +22180,98 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
21871
22180
|
return result;
|
|
21872
22181
|
}
|
|
21873
22182
|
|
|
22183
|
+
// src/hwpx/gen-gaejosik.ts
|
|
22184
|
+
function chapterRoman(n) {
|
|
22185
|
+
if (n >= 1 && n <= 12) return String.fromCodePoint(8543 + n);
|
|
22186
|
+
const t = [[10, "\u2169"], [9, "\u2168"], [5, "\u2164"], [4, "\u2163"], [1, "\u2160"]];
|
|
22187
|
+
let s = "";
|
|
22188
|
+
for (const [v, r] of t) while (n >= v) {
|
|
22189
|
+
s += r;
|
|
22190
|
+
n -= v;
|
|
22191
|
+
}
|
|
22192
|
+
return s;
|
|
22193
|
+
}
|
|
22194
|
+
function emptyPara(paraPrId = PARA_NORMAL, pageBreak = false, charPrId = CHAR_NORMAL) {
|
|
22195
|
+
const brk = pageBreak ? ` pageBreak="1"` : "";
|
|
22196
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"${brk}><hp:run charPrIDRef="${charPrId}"><hp:t></hp:t></hp:run></hp:p>`;
|
|
22197
|
+
}
|
|
22198
|
+
var gjTableId = 92e5;
|
|
22199
|
+
function cell(opts) {
|
|
22200
|
+
const paras = opts.paras ?? emptyPara();
|
|
22201
|
+
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>`;
|
|
22202
|
+
}
|
|
22203
|
+
function table(rows, w, h, cols, tblBf = 1) {
|
|
22204
|
+
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>`;
|
|
22205
|
+
}
|
|
22206
|
+
function buildGaejosikCover(title, gongmun) {
|
|
22207
|
+
const g = coverGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
22208
|
+
const sz = gaejosikSizes(gongmun.bodyHeight, gongmun.sizes);
|
|
22209
|
+
const innerW = g.totalW - 282;
|
|
22210
|
+
const titleCharPr = simulateWrap(title, innerW, innerW, sz.coverTitle, 100, "keep").lines > 2 ? GJ_CHAR_COVER_SUB : GJ_CHAR_COVER_TITLE;
|
|
22211
|
+
const titlePara = `<hp:p paraPrIDRef="${GJ_PARA_COVER}" styleIDRef="0"><hp:run charPrIDRef="${titleCharPr}"><hp:t>${escapeXml(title)}</hp:t></hp:run></hp:p>`;
|
|
22212
|
+
const barEmpty = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
22213
|
+
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 });
|
|
22214
|
+
const titleRow = cell({ bf: 1, col: 0, colSpan: 3, row: 1, w: g.totalW, h: g.titleH, paras: titlePara });
|
|
22215
|
+
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 });
|
|
22216
|
+
const tbl2 = table([topRow, titleRow, botRow], g.totalW, g.barH + g.titleH + g.botBarH, 3);
|
|
22217
|
+
const host = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${tbl2}</hp:run></hp:p>`;
|
|
22218
|
+
const date = gongmun.cover?.date ?? formatGaejosikDate(/* @__PURE__ */ new Date());
|
|
22219
|
+
const org = gongmun.cover?.org ?? "";
|
|
22220
|
+
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>`;
|
|
22221
|
+
const subEmpty = emptyPara(GJ_PARA_COVER, false, GJ_CHAR_COVER_SUB);
|
|
22222
|
+
return [
|
|
22223
|
+
...Array(5).fill(emptyPara()),
|
|
22224
|
+
host,
|
|
22225
|
+
...Array(5).fill(emptyPara()),
|
|
22226
|
+
sub(date),
|
|
22227
|
+
...org ? [...Array(4).fill(subEmpty), sub(org)] : []
|
|
22228
|
+
];
|
|
22229
|
+
}
|
|
22230
|
+
function buildTocBanner(gongmun) {
|
|
22231
|
+
const g = tocBannerGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
22232
|
+
const bfs = [GJ_BF_BAR_DARK, 1, GJ_BF_TOC_STRIPE, 1, GJ_BF_TOC_STRIPE, 1, GJ_BF_BAR_DARK];
|
|
22233
|
+
const filler = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
22234
|
+
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>`;
|
|
22235
|
+
const row = g.colWs.map(
|
|
22236
|
+
(w, c) => cell({ bf: bfs[c], col: c, w, h: g.h, paras: c === 3 ? label : filler })
|
|
22237
|
+
).join("");
|
|
22238
|
+
const banner = table([row], g.colWs.reduce((a, b) => a + b, 0), g.h, 7, 2);
|
|
22239
|
+
return `<hp:p paraPrIDRef="${GJ_PARA_BAR}" styleIDRef="0" pageBreak="1"><hp:run charPrIDRef="${CHAR_NORMAL}">${banner}</hp:run></hp:p>`;
|
|
22240
|
+
}
|
|
22241
|
+
function buildGaejosikToc(chapters, gongmun) {
|
|
22242
|
+
const label = buildTocBanner(gongmun);
|
|
22243
|
+
const items = chapters.map(
|
|
22244
|
+
(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>`
|
|
22245
|
+
).join("");
|
|
22246
|
+
const box = table(
|
|
22247
|
+
[cell({ bf: GJ_BF_TOC_BOX, col: 0, w: TOC_GEOM.boxW, h: TOC_GEOM.boxH, paras: items })],
|
|
22248
|
+
TOC_GEOM.boxW,
|
|
22249
|
+
TOC_GEOM.boxH,
|
|
22250
|
+
1
|
|
22251
|
+
);
|
|
22252
|
+
const host = `<hp:p paraPrIDRef="${GJ_PARA_BAR}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${box}</hp:run></hp:p>`;
|
|
22253
|
+
return [label, emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR), host];
|
|
22254
|
+
}
|
|
22255
|
+
function buildGaejosikBodyTitle(title, gongmun) {
|
|
22256
|
+
const g = COVER_GEOM;
|
|
22257
|
+
const bt = bodyTitleGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
22258
|
+
const barEmpty = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
22259
|
+
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>`;
|
|
22260
|
+
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 });
|
|
22261
|
+
const titleRow = cell({ bf: 1, col: 0, colSpan: 3, row: 1, w: g.totalW, h: bt.titleH, paras: titlePara });
|
|
22262
|
+
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 });
|
|
22263
|
+
const box = table([topRow, titleRow, botRow], g.totalW, bt.barH * 2 + bt.titleH, 3);
|
|
22264
|
+
return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${box}</hp:run></hp:p>`;
|
|
22265
|
+
}
|
|
22266
|
+
function buildGaejosikChapter(n, title, gongmun) {
|
|
22267
|
+
const g = gongmun ? chapterGeom(gongmun.bodyHeight, gongmun.sizes) : chapterGeom(1500);
|
|
22268
|
+
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>`;
|
|
22269
|
+
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>`;
|
|
22270
|
+
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 });
|
|
22271
|
+
const tbl2 = table([row], g.numW + g.gapW + g.titleW, g.rowH, 3);
|
|
22272
|
+
return `<hp:p paraPrIDRef="${GJ_PARA_CHAPTER}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${tbl2}</hp:run></hp:p>`;
|
|
22273
|
+
}
|
|
22274
|
+
|
|
21874
22275
|
// src/diff/text-diff.ts
|
|
21875
22276
|
function similarity(a, b) {
|
|
21876
22277
|
if (a === b) return 1;
|
|
@@ -22068,8 +22469,8 @@ function summarize(text) {
|
|
|
22068
22469
|
const t = text.replace(/\s+/g, " ").trim();
|
|
22069
22470
|
return t.length > 80 ? t.slice(0, 77) + "..." : t;
|
|
22070
22471
|
}
|
|
22071
|
-
function replicateGfmTable(
|
|
22072
|
-
const { cells, rows: numRows, cols: numCols } =
|
|
22472
|
+
function replicateGfmTable(table2) {
|
|
22473
|
+
const { cells, rows: numRows, cols: numCols } = table2;
|
|
22073
22474
|
if (numRows === 0 || numCols === 0) return null;
|
|
22074
22475
|
if (numRows === 1 && numCols === 1) return null;
|
|
22075
22476
|
if (numCols === 1) return null;
|
|
@@ -22078,28 +22479,28 @@ function replicateGfmTable(table) {
|
|
|
22078
22479
|
for (let r = 0; r < numRows; r++) {
|
|
22079
22480
|
for (let c = 0; c < numCols; c++) {
|
|
22080
22481
|
if (skip.has(`${r},${c}`)) continue;
|
|
22081
|
-
const
|
|
22082
|
-
if (!
|
|
22482
|
+
const cell2 = cells[r]?.[c];
|
|
22483
|
+
if (!cell2) continue;
|
|
22083
22484
|
display[r][c] = {
|
|
22084
|
-
text: escapeGfm(sanitizeText(
|
|
22485
|
+
text: escapeGfm(sanitizeText(cell2.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
|
|
22085
22486
|
gridR: r,
|
|
22086
22487
|
gridC: c
|
|
22087
22488
|
};
|
|
22088
|
-
for (let dr = 0; dr <
|
|
22089
|
-
for (let dc = 0; dc <
|
|
22489
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
22490
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
22090
22491
|
if (dr === 0 && dc === 0) continue;
|
|
22091
22492
|
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
22092
22493
|
}
|
|
22093
22494
|
}
|
|
22094
|
-
c +=
|
|
22495
|
+
c += cell2.colSpan - 1;
|
|
22095
22496
|
}
|
|
22096
22497
|
}
|
|
22097
22498
|
const uniqueRows = [];
|
|
22098
22499
|
let pendingLabelRow = null;
|
|
22099
22500
|
for (let r = 0; r < display.length; r++) {
|
|
22100
22501
|
const row = display[r];
|
|
22101
|
-
if (row.every((
|
|
22102
|
-
const nonEmptyCols = row.filter((
|
|
22502
|
+
if (row.every((cell2) => cell2.text === "")) continue;
|
|
22503
|
+
const nonEmptyCols = row.filter((cell2) => cell2.text !== "");
|
|
22103
22504
|
const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
|
|
22104
22505
|
if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
|
|
22105
22506
|
if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
|
|
@@ -22131,9 +22532,9 @@ function parseGfmTable(lines) {
|
|
|
22131
22532
|
function unescapeGfmCell(text) {
|
|
22132
22533
|
return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\([~*])/g, "$1");
|
|
22133
22534
|
}
|
|
22134
|
-
function replicateCellInnerHtml(
|
|
22135
|
-
if (
|
|
22136
|
-
return
|
|
22535
|
+
function replicateCellInnerHtml(cell2) {
|
|
22536
|
+
if (cell2.blocks?.length) {
|
|
22537
|
+
return cell2.blocks.map((b) => {
|
|
22137
22538
|
if (b.type === "table" && b.table) {
|
|
22138
22539
|
const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
|
|
22139
22540
|
return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
|
|
@@ -22143,27 +22544,27 @@ function replicateCellInnerHtml(cell) {
|
|
|
22143
22544
|
return t ? t.replace(/\n/g, "<br>") : "";
|
|
22144
22545
|
}).filter(Boolean).join("<br>");
|
|
22145
22546
|
}
|
|
22146
|
-
return sanitizeText(
|
|
22547
|
+
return sanitizeText(cell2.text).replace(/\n/g, "<br>");
|
|
22147
22548
|
}
|
|
22148
|
-
function replicateTableToHtml(
|
|
22149
|
-
const rows = replicateHtmlTable(
|
|
22549
|
+
function replicateTableToHtml(table2) {
|
|
22550
|
+
const rows = replicateHtmlTable(table2);
|
|
22150
22551
|
const lines = ["<table>"];
|
|
22151
22552
|
for (let r = 0; r < rows.length; r++) {
|
|
22152
22553
|
const tag = rows[r].tag;
|
|
22153
|
-
const rowHtml = rows[r].cells.map((
|
|
22554
|
+
const rowHtml = rows[r].cells.map((cell2) => {
|
|
22154
22555
|
const attrs = [];
|
|
22155
|
-
if (
|
|
22156
|
-
if (
|
|
22556
|
+
if (cell2.colSpan > 1) attrs.push(`colspan="${cell2.colSpan}"`);
|
|
22557
|
+
if (cell2.rowSpan > 1) attrs.push(`rowspan="${cell2.rowSpan}"`);
|
|
22157
22558
|
const attrStr = attrs.length ? " " + attrs.join(" ") : "";
|
|
22158
|
-
return `<${tag}${attrStr}>${
|
|
22559
|
+
return `<${tag}${attrStr}>${cell2.inner}</${tag}>`;
|
|
22159
22560
|
});
|
|
22160
22561
|
if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
|
|
22161
22562
|
}
|
|
22162
22563
|
lines.push("</table>");
|
|
22163
22564
|
return lines.join("\n");
|
|
22164
22565
|
}
|
|
22165
|
-
function replicateHtmlTable(
|
|
22166
|
-
const { cells, rows: numRows, cols: numCols } =
|
|
22566
|
+
function replicateHtmlTable(table2) {
|
|
22567
|
+
const { cells, rows: numRows, cols: numCols } = table2;
|
|
22167
22568
|
const skip = /* @__PURE__ */ new Set();
|
|
22168
22569
|
const result = [];
|
|
22169
22570
|
for (let r = 0; r < numRows; r++) {
|
|
@@ -22171,18 +22572,18 @@ function replicateHtmlTable(table) {
|
|
|
22171
22572
|
const rowCells = [];
|
|
22172
22573
|
for (let c = 0; c < numCols; c++) {
|
|
22173
22574
|
if (skip.has(`${r},${c}`)) continue;
|
|
22174
|
-
const
|
|
22175
|
-
if (!
|
|
22176
|
-
for (let dr = 0; dr <
|
|
22177
|
-
for (let dc = 0; dc <
|
|
22575
|
+
const cell2 = cells[r]?.[c];
|
|
22576
|
+
if (!cell2) continue;
|
|
22577
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
22578
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
22178
22579
|
if (dr === 0 && dc === 0) continue;
|
|
22179
22580
|
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
22180
22581
|
}
|
|
22181
22582
|
}
|
|
22182
22583
|
rowCells.push({
|
|
22183
|
-
inner: replicateCellInnerHtml(
|
|
22184
|
-
colSpan:
|
|
22185
|
-
rowSpan:
|
|
22584
|
+
inner: replicateCellInnerHtml(cell2),
|
|
22585
|
+
colSpan: cell2.colSpan,
|
|
22586
|
+
rowSpan: cell2.rowSpan,
|
|
22186
22587
|
gridR: r,
|
|
22187
22588
|
gridC: c
|
|
22188
22589
|
});
|
|
@@ -22287,59 +22688,302 @@ function removeNestedTables(html) {
|
|
|
22287
22688
|
return result;
|
|
22288
22689
|
}
|
|
22289
22690
|
|
|
22691
|
+
// src/hwpx/gen-table-bf.ts
|
|
22692
|
+
var THIN = ["0.12 mm", "#000000"];
|
|
22693
|
+
var THICK = ["0.4 mm", "#000000"];
|
|
22694
|
+
var DOUBLE = ["0.5 mm", "#000000", "DOUBLE_SLIM"];
|
|
22695
|
+
var EDGE = { thin: THIN, thick: THICK, double: DOUBLE };
|
|
22696
|
+
function sideOf(kind) {
|
|
22697
|
+
return kind === "none" ? void 0 : EDGE[kind];
|
|
22698
|
+
}
|
|
22699
|
+
var TableBfRegistry = class {
|
|
22700
|
+
constructor(nextId) {
|
|
22701
|
+
this.nextId = nextId;
|
|
22702
|
+
}
|
|
22703
|
+
map = /* @__PURE__ */ new Map();
|
|
22704
|
+
xmls = [];
|
|
22705
|
+
get(spec) {
|
|
22706
|
+
const key = `${spec.t}|${spec.b}|${spec.l}|${spec.r}|${typeof spec.fill === "string" ? spec.fill : spec.fill ? spec.fill.gradient.join("-") : ""}`;
|
|
22707
|
+
const hit = this.map.get(key);
|
|
22708
|
+
if (hit !== void 0) return hit;
|
|
22709
|
+
const id = this.nextId++;
|
|
22710
|
+
this.map.set(key, id);
|
|
22711
|
+
this.xmls.push(
|
|
22712
|
+
borderFillEntry(id, { t: sideOf(spec.t), b: sideOf(spec.b), l: sideOf(spec.l), r: sideOf(spec.r) }, spec.fill)
|
|
22713
|
+
);
|
|
22714
|
+
return id;
|
|
22715
|
+
}
|
|
22716
|
+
/** 등록된 borderFill XML 목록 (등록 순서 = id 순서) */
|
|
22717
|
+
emit() {
|
|
22718
|
+
return this.xmls;
|
|
22719
|
+
}
|
|
22720
|
+
get count() {
|
|
22721
|
+
return this.xmls.length;
|
|
22722
|
+
}
|
|
22723
|
+
};
|
|
22724
|
+
function dataCellSpec(opts) {
|
|
22725
|
+
const { row, rowEnd, col, colEnd, rowCnt, colCnt, headerRows, fill } = opts;
|
|
22726
|
+
const isTop = row === 0;
|
|
22727
|
+
const isBottom = rowEnd === rowCnt - 1;
|
|
22728
|
+
const isHeaderBottom = headerRows > 0 && rowEnd === headerRows - 1;
|
|
22729
|
+
const isBelowHeader = headerRows > 0 && row === headerRows;
|
|
22730
|
+
return {
|
|
22731
|
+
t: isTop ? "thick" : isBelowHeader ? "double" : "thin",
|
|
22732
|
+
b: isBottom ? "thick" : isHeaderBottom ? "double" : "thin",
|
|
22733
|
+
l: col === 0 ? "thick" : "thin",
|
|
22734
|
+
r: colEnd === colCnt - 1 ? "thick" : "thin",
|
|
22735
|
+
fill
|
|
22736
|
+
};
|
|
22737
|
+
}
|
|
22738
|
+
|
|
22739
|
+
// src/hwpx/gen-profile.ts
|
|
22740
|
+
function normalizeAnchor(s) {
|
|
22741
|
+
return s.toLowerCase().replace(/[^\p{L}\p{N}]/gu, "").slice(0, 24);
|
|
22742
|
+
}
|
|
22743
|
+
function takeProfile(remap, rows, cols, anchor, seq) {
|
|
22744
|
+
if (!remap) return null;
|
|
22745
|
+
for (const t of remap.tables) {
|
|
22746
|
+
if (t.used) continue;
|
|
22747
|
+
if (t.rows !== rows || t.cols !== cols) continue;
|
|
22748
|
+
if (t.anchor && anchor) {
|
|
22749
|
+
if (t.anchor !== anchor) continue;
|
|
22750
|
+
} else if (t.index !== seq) {
|
|
22751
|
+
continue;
|
|
22752
|
+
}
|
|
22753
|
+
t.used = true;
|
|
22754
|
+
return t;
|
|
22755
|
+
}
|
|
22756
|
+
return null;
|
|
22757
|
+
}
|
|
22758
|
+
function parseHu(s) {
|
|
22759
|
+
if (s == null) return void 0;
|
|
22760
|
+
const n = parseInt(String(s).trim(), 10);
|
|
22761
|
+
return Number.isFinite(n) ? n : void 0;
|
|
22762
|
+
}
|
|
22763
|
+
function edgeXml(tag, d) {
|
|
22764
|
+
return d ? `<hh:${tag} type="${d.type}" width="${d.width}" color="${d.color}"/>` : `<hh:${tag} type="NONE" width="0.1 mm" color="#000000"/>`;
|
|
22765
|
+
}
|
|
22766
|
+
function borderFillDefToXml(id, def) {
|
|
22767
|
+
const fill = def.fill?.faceColor ? `<hh:fillBrush><hh:winBrush faceColor="${def.fill.faceColor}" hatchColor="#000000" alpha="0"/></hh:fillBrush>` : "";
|
|
22768
|
+
return ` <hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
22769
|
+
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
22770
|
+
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
22771
|
+
${edgeXml("leftBorder", def.leftBorder)}
|
|
22772
|
+
${edgeXml("rightBorder", def.rightBorder)}
|
|
22773
|
+
${edgeXml("topBorder", def.topBorder)}
|
|
22774
|
+
${edgeXml("bottomBorder", def.bottomBorder)}${fill ? `
|
|
22775
|
+
${fill}` : ""}
|
|
22776
|
+
</hh:borderFill>`;
|
|
22777
|
+
}
|
|
22778
|
+
var PROFILE_FONT_MAX = 2;
|
|
22779
|
+
function profileCharPrXml(id, def) {
|
|
22780
|
+
const height = parseHu(def.height_hwpunit) ?? 1e3;
|
|
22781
|
+
const color = def.textColor ?? "#000000";
|
|
22782
|
+
const rawFont = def.fontRef_hangul != null ? parseInt(def.fontRef_hangul, 10) || 0 : 0;
|
|
22783
|
+
const font = rawFont >= 0 && rawFont <= PROFILE_FONT_MAX ? rawFont : 0;
|
|
22784
|
+
const boldAttr = def.bold ? ` bold="1"` : "";
|
|
22785
|
+
const italicAttr = def.italic ? ` italic="1"` : "";
|
|
22786
|
+
const underline = def.underline ? `
|
|
22787
|
+
<hh:underline type="BOTTOM" shape="SOLID" color="${color}"/>` : "";
|
|
22788
|
+
return ` <hh:charPr id="${id}" height="${height}" textColor="${color}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
22789
|
+
<hh:fontRef hangul="${font}" latin="${font}" hanja="${font}" japanese="${font}" other="${font}" symbol="${font}" user="${font}"/>
|
|
22790
|
+
<hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
22791
|
+
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
22792
|
+
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
22793
|
+
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>${underline}
|
|
22794
|
+
</hh:charPr>`;
|
|
22795
|
+
}
|
|
22796
|
+
function buildProfileRemap(profile, charPrBase, borderFillBase = 3) {
|
|
22797
|
+
const remap = { borderFillXmls: [], charPrXmls: [], tables: [] };
|
|
22798
|
+
let bfNext = borderFillBase;
|
|
22799
|
+
let charNext = charPrBase;
|
|
22800
|
+
for (const t of profile.tables) {
|
|
22801
|
+
const localBf = {};
|
|
22802
|
+
for (const [key, def] of Object.entries(t.used_border_fills ?? {})) {
|
|
22803
|
+
const gid = bfNext++;
|
|
22804
|
+
remap.borderFillXmls.push(borderFillDefToXml(gid, def));
|
|
22805
|
+
localBf[key] = gid;
|
|
22806
|
+
}
|
|
22807
|
+
const localChar = {};
|
|
22808
|
+
for (const [key, def] of Object.entries(t.used_char_prs ?? {})) {
|
|
22809
|
+
const gid = charNext++;
|
|
22810
|
+
remap.charPrXmls.push(profileCharPrXml(gid, def));
|
|
22811
|
+
localChar[key] = gid;
|
|
22812
|
+
}
|
|
22813
|
+
let colWidths;
|
|
22814
|
+
if (t.col_widths_hwpunit && t.col_widths_hwpunit.length === t.cols) {
|
|
22815
|
+
const parsed = t.col_widths_hwpunit.map(parseHu);
|
|
22816
|
+
if (parsed.every((n) => n != null)) colWidths = parsed;
|
|
22817
|
+
}
|
|
22818
|
+
const tr = {
|
|
22819
|
+
index: t.table_index,
|
|
22820
|
+
rows: t.rows,
|
|
22821
|
+
cols: t.cols,
|
|
22822
|
+
// 재정규화 — 추출기는 정규화해 담지만 손편집된 프로필 JSON도 같은 키 공간으로
|
|
22823
|
+
anchor: t.anchor_text ? normalizeAnchor(t.anchor_text) : void 0,
|
|
22824
|
+
width: parseHu(t.width_hwpunit),
|
|
22825
|
+
colWidths,
|
|
22826
|
+
cellBf: /* @__PURE__ */ new Map(),
|
|
22827
|
+
cellChar: /* @__PURE__ */ new Map(),
|
|
22828
|
+
cellH: /* @__PURE__ */ new Map()
|
|
22829
|
+
};
|
|
22830
|
+
for (const cell2 of t.cells) {
|
|
22831
|
+
const k = `${cell2.row},${cell2.col}`;
|
|
22832
|
+
if (cell2.borderFillIDRef != null && cell2.borderFillIDRef in localBf) {
|
|
22833
|
+
tr.cellBf.set(k, localBf[cell2.borderFillIDRef]);
|
|
22834
|
+
}
|
|
22835
|
+
if (cell2.charPrIDRef != null && cell2.charPrIDRef in localChar) {
|
|
22836
|
+
tr.cellChar.set(k, localChar[cell2.charPrIDRef]);
|
|
22837
|
+
}
|
|
22838
|
+
const h = parseHu(cell2.height_hwpunit);
|
|
22839
|
+
if (h != null) tr.cellH.set(k, h);
|
|
22840
|
+
}
|
|
22841
|
+
remap.tables.push(tr);
|
|
22842
|
+
}
|
|
22843
|
+
return remap;
|
|
22844
|
+
}
|
|
22845
|
+
|
|
22290
22846
|
// src/hwpx/gen-table.ts
|
|
22291
22847
|
var TABLE_ID_BASE = 1e3;
|
|
22292
22848
|
var tableIdCounter = TABLE_ID_BASE;
|
|
22293
22849
|
function nextTableId() {
|
|
22294
22850
|
return ++tableIdCounter;
|
|
22295
22851
|
}
|
|
22296
|
-
var
|
|
22297
|
-
function
|
|
22298
|
-
|
|
22299
|
-
|
|
22300
|
-
|
|
22852
|
+
var DATA_TABLE_INSET = 1800;
|
|
22853
|
+
function anchorOfMarkdownCell(cell2) {
|
|
22854
|
+
return normalizeAnchor(cell2.replace(/!\[[^\]]*\]\([^)]*\)/g, ""));
|
|
22855
|
+
}
|
|
22856
|
+
function anchorOfHtmlCell(inner) {
|
|
22857
|
+
const noNested = inner.replace(/<table[\s\S]*?<\/table>/gi, "");
|
|
22858
|
+
const { lines } = htmlCellInnerToLines(noNested);
|
|
22859
|
+
return normalizeAnchor(lines.join(""));
|
|
22301
22860
|
}
|
|
22302
|
-
function
|
|
22861
|
+
function profileColWidths(tp, colCnt) {
|
|
22303
22862
|
if (!tp) return null;
|
|
22304
|
-
if (tp.
|
|
22305
|
-
|
|
22306
|
-
|
|
22863
|
+
if (tp.colWidths && tp.colWidths.length === colCnt) return tp.colWidths;
|
|
22864
|
+
if (tp.width) return Array(colCnt).fill(Math.floor(tp.width / colCnt));
|
|
22865
|
+
return null;
|
|
22866
|
+
}
|
|
22867
|
+
var CELL_PAD = 582;
|
|
22868
|
+
function cellContentWidth(text, charHeight) {
|
|
22869
|
+
let max = 0;
|
|
22870
|
+
for (const seg of text.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
|
|
22871
|
+
const w = measureTextWidth(seg.trim(), charHeight, 100);
|
|
22872
|
+
if (w > max) max = w;
|
|
22307
22873
|
}
|
|
22308
|
-
return
|
|
22874
|
+
return max;
|
|
22309
22875
|
}
|
|
22310
|
-
function
|
|
22311
|
-
|
|
22312
|
-
const
|
|
22313
|
-
|
|
22876
|
+
function computeColWidths(colMax, totalWidth) {
|
|
22877
|
+
const colCnt = colMax.length;
|
|
22878
|
+
const minW = Math.min(Math.max(2e3, Math.round(totalWidth * 0.06)), Math.floor(totalWidth / colCnt));
|
|
22879
|
+
const cap = Math.round(totalWidth * 0.8);
|
|
22880
|
+
const raw = colMax.map((w) => Math.min(Math.max(w + CELL_PAD, minW), cap));
|
|
22881
|
+
const widths = Array(colCnt).fill(0);
|
|
22882
|
+
const free = new Set(raw.map((_, i) => i));
|
|
22883
|
+
let budget = totalWidth;
|
|
22884
|
+
const evenShare = Math.floor(totalWidth / colCnt);
|
|
22885
|
+
for (let i = 0; i < colCnt; i++) {
|
|
22886
|
+
const fixed = Math.min(Math.round(raw[i] * 1.12), evenShare);
|
|
22887
|
+
if (raw[i] <= evenShare && free.size > 1) {
|
|
22888
|
+
widths[i] = fixed;
|
|
22889
|
+
free.delete(i);
|
|
22890
|
+
budget -= fixed;
|
|
22891
|
+
}
|
|
22892
|
+
}
|
|
22893
|
+
if (free.size === 0) {
|
|
22894
|
+
const sumRaw = raw.reduce((a, b) => a + b, 0);
|
|
22895
|
+
for (let i = 0; i < colCnt; i++) widths[i] += Math.floor(raw[i] / sumRaw * (totalWidth - sumRaw));
|
|
22896
|
+
} else {
|
|
22897
|
+
for (; ; ) {
|
|
22898
|
+
const sum2 = [...free].reduce((a, i) => a + raw[i], 0);
|
|
22899
|
+
const short = [...free].filter((i) => raw[i] / sum2 * budget < minW);
|
|
22900
|
+
if (short.length === 0) break;
|
|
22901
|
+
for (const i of short) {
|
|
22902
|
+
widths[i] = minW;
|
|
22903
|
+
free.delete(i);
|
|
22904
|
+
budget -= minW;
|
|
22905
|
+
}
|
|
22906
|
+
if (free.size === 0) break;
|
|
22907
|
+
}
|
|
22908
|
+
const sum = [...free].reduce((a, i) => a + raw[i], 0);
|
|
22909
|
+
for (const i of free) widths[i] = Math.floor(raw[i] / sum * budget);
|
|
22910
|
+
}
|
|
22911
|
+
let rem = totalWidth - widths.reduce((a, b) => a + b, 0);
|
|
22912
|
+
const order = [...raw.keys()].sort((a, b) => raw[b] - raw[a]);
|
|
22913
|
+
for (let k = 0; rem > 0; k = (k + 1) % colCnt, rem--) widths[order[k]]++;
|
|
22914
|
+
return widths;
|
|
22915
|
+
}
|
|
22916
|
+
function estimateRowHeight(cells, widths, charHeight) {
|
|
22917
|
+
let maxLines = 1;
|
|
22918
|
+
cells.forEach((cell2, c) => {
|
|
22919
|
+
const usable = Math.max((widths[c] ?? widths[widths.length - 1]) - CELL_PAD, 1e3);
|
|
22920
|
+
let lines = 0;
|
|
22921
|
+
for (const seg of cell2.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
|
|
22922
|
+
lines += Math.max(1, Math.ceil(measureTextWidth(seg.trim(), charHeight, 100) / usable));
|
|
22923
|
+
}
|
|
22924
|
+
if (lines > maxLines) maxLines = lines;
|
|
22925
|
+
});
|
|
22926
|
+
return maxLines * Math.round(charHeight * 1.6) + 282;
|
|
22314
22927
|
}
|
|
22315
|
-
function generateTable(rows, theme,
|
|
22928
|
+
function generateTable(rows, theme, style = null, remap = null, seq = 0) {
|
|
22316
22929
|
const rowCnt = rows.length;
|
|
22317
22930
|
const colCnt = Math.max(...rows.map((r) => r.length), 1);
|
|
22318
|
-
const
|
|
22931
|
+
const reg = style?.bfRegistry ?? null;
|
|
22932
|
+
const totalW = style ? reg ? style.totalWidth - DATA_TABLE_INSET : style.totalWidth : 44e3;
|
|
22933
|
+
const measureH = style?.charHeight ?? 1e3;
|
|
22934
|
+
const prof = takeProfile(remap, rowCnt, colCnt, anchorOfMarkdownCell(rows[0]?.[0] ?? ""), seq);
|
|
22935
|
+
const colMax = Array(colCnt).fill(0);
|
|
22936
|
+
const colMaxBody = Array(colCnt).fill(0);
|
|
22937
|
+
rows.forEach((row, r) => row.forEach((cell2, c) => {
|
|
22938
|
+
const w = cellContentWidth(cell2, measureH);
|
|
22939
|
+
if (w > colMax[c]) colMax[c] = w;
|
|
22940
|
+
if (r > 0 && w > colMaxBody[c]) colMaxBody[c] = w;
|
|
22941
|
+
}));
|
|
22942
|
+
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW);
|
|
22943
|
+
const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
|
|
22944
|
+
const labelCol0 = !!reg && colCnt === 2 && colCentered[0] && rows.every((r) => (r[0] ?? "").replace(/\*\*|__|`/g, "").length <= 12);
|
|
22319
22945
|
const tblId = nextTableId();
|
|
22320
|
-
const
|
|
22321
|
-
const
|
|
22322
|
-
const
|
|
22323
|
-
const tblH = cellH * rowCnt;
|
|
22324
|
-
const useHeaderStyle = theme.tableHeader !== theme.body || theme.tableHeaderBold;
|
|
22946
|
+
const useHeaderStyle = !style && (theme.tableHeader !== theme.body || theme.tableHeaderBold);
|
|
22947
|
+
const mapId = style ? (id) => id === CHAR_NORMAL ? style.charPr : id === CHAR_BOLD ? style.boldCharPr : id : void 0;
|
|
22948
|
+
const rowHeights = rows.map((row) => style ? estimateRowHeight(row, colWidths, measureH) : 1500);
|
|
22325
22949
|
const trElements = rows.map((row, rowIdx) => {
|
|
22326
22950
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
22327
22951
|
const isHeaderRow = rowIdx === 0;
|
|
22328
|
-
const
|
|
22329
|
-
const
|
|
22952
|
+
const cellH = rowHeights[rowIdx];
|
|
22953
|
+
const baseCharPr = style ? style.charPr : CHAR_NORMAL;
|
|
22954
|
+
const headerCharPr = isHeaderRow && useHeaderStyle ? CHAR_TABLE_HEADER : baseCharPr;
|
|
22955
|
+
const tdElements = cells.map((cell2, colIdx) => {
|
|
22330
22956
|
const k = `${rowIdx},${colIdx}`;
|
|
22331
|
-
const
|
|
22332
|
-
const
|
|
22957
|
+
const isLabelCell2 = labelCol0 && colIdx === 0;
|
|
22958
|
+
const defaultCharPr = style ? reg && (isHeaderRow || isLabelCell2) ? style.boldCharPr : style.charPr : isHeaderRow ? headerCharPr : baseCharPr;
|
|
22959
|
+
const cellCharPr = prof?.cellChar.get(k) ?? defaultCharPr;
|
|
22960
|
+
const centered = isHeaderRow || colCentered[colIdx];
|
|
22961
|
+
const paraPrId = style ? centered ? style.tblCenterParaPr ?? style.centerParaPr : reg ? style.tblLeftParaPr ?? PARA_NORMAL : PARA_NORMAL : PARA_NORMAL;
|
|
22962
|
+
const p = cell2.split(/<br\s*\/?>/i).map((seg) => {
|
|
22963
|
+
const runs = generateRuns(seg, cellCharPr, prof?.cellChar.has(k) ? void 0 : mapId);
|
|
22964
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0">${runs || `<hp:run charPrIDRef="${cellCharPr}"><hp:t></hp:t></hp:run>`}</hp:p>`;
|
|
22965
|
+
}).join("");
|
|
22966
|
+
const bf = prof?.cellBf.get(k) ?? (reg ? reg.get(dataCellSpec({
|
|
22967
|
+
row: rowIdx,
|
|
22968
|
+
rowEnd: rowIdx,
|
|
22969
|
+
col: colIdx,
|
|
22970
|
+
colEnd: colIdx,
|
|
22971
|
+
rowCnt,
|
|
22972
|
+
colCnt,
|
|
22973
|
+
headerRows: 1,
|
|
22974
|
+
fill: isHeaderRow ? style.headerFill ?? "#E6E6E6" : isLabelCell2 ? style.labelFill ?? "#E7E7E7" : void 0
|
|
22975
|
+
})) : style && isHeaderRow ? style.headerBf : 2);
|
|
22333
22976
|
const h = prof?.cellH.get(k) ?? cellH;
|
|
22334
|
-
|
|
22335
|
-
const p = `<hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p>`;
|
|
22336
|
-
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>`;
|
|
22977
|
+
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>`;
|
|
22337
22978
|
}).join("");
|
|
22338
22979
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
22339
22980
|
}).join("");
|
|
22981
|
+
const tblW = colWidths.reduce((a, b) => a + b, 0);
|
|
22982
|
+
const tblH = rowHeights.reduce((a, b) => a + b, 0);
|
|
22340
22983
|
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;
|
|
22341
|
-
const
|
|
22342
|
-
|
|
22984
|
+
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>`;
|
|
22985
|
+
const hostPr = reg && style?.rightParaPr !== void 0 ? style.rightParaPr : 0;
|
|
22986
|
+
return `<hp:p paraPrIDRef="${hostPr}" styleIDRef="0"><hp:run charPrIDRef="0">${tbl2}</hp:run></hp:p>`;
|
|
22343
22987
|
}
|
|
22344
22988
|
function layoutHtmlRows(rows) {
|
|
22345
22989
|
const occupied = /* @__PURE__ */ new Set();
|
|
@@ -22347,11 +22991,11 @@ function layoutHtmlRows(rows) {
|
|
|
22347
22991
|
let colCnt = 0;
|
|
22348
22992
|
for (let r = 0; r < rows.length; r++) {
|
|
22349
22993
|
let c = 0;
|
|
22350
|
-
for (const
|
|
22994
|
+
for (const cell2 of rows[r].cells) {
|
|
22351
22995
|
while (occupied.has(`${r},${c}`)) c++;
|
|
22352
|
-
const colSpan = Math.max(1,
|
|
22353
|
-
const rowSpan = Math.max(1,
|
|
22354
|
-
placed.push({ r, c, colSpan, rowSpan, inner:
|
|
22996
|
+
const colSpan = Math.max(1, cell2.colSpan);
|
|
22997
|
+
const rowSpan = Math.max(1, cell2.rowSpan);
|
|
22998
|
+
placed.push({ r, c, colSpan, rowSpan, inner: cell2.inner, isHeader: rows[r].tag === "th" });
|
|
22355
22999
|
for (let dr = 0; dr < rowSpan; dr++) {
|
|
22356
23000
|
for (let dc = 0; dc < colSpan; dc++) occupied.add(`${r + dr},${c + dc}`);
|
|
22357
23001
|
}
|
|
@@ -22364,49 +23008,135 @@ function layoutHtmlRows(rows) {
|
|
|
22364
23008
|
function unescapeHtml(s) {
|
|
22365
23009
|
return s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
22366
23010
|
}
|
|
22367
|
-
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3,
|
|
23011
|
+
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, remap = null, seq = 0) {
|
|
22368
23012
|
const rows = parseHtmlTable(rawHtml);
|
|
22369
23013
|
if (!rows || rows.length === 0) return null;
|
|
22370
23014
|
const { placed, rowCnt, colCnt } = layoutHtmlRows(rows);
|
|
22371
23015
|
if (rowCnt === 0 || colCnt === 0) return null;
|
|
22372
|
-
const
|
|
23016
|
+
const measureH = style?.charHeight ?? 1e3;
|
|
23017
|
+
const first = placed.find((p) => p.r === 0 && p.c === 0) ?? placed[0];
|
|
23018
|
+
const prof = takeProfile(remap, rowCnt, colCnt, first ? anchorOfHtmlCell(first.inner) : "", seq);
|
|
23019
|
+
const colMax = Array(colCnt).fill(0);
|
|
23020
|
+
const colMaxBody = Array(colCnt).fill(0);
|
|
23021
|
+
const cellLines = placed.map((cell2) => htmlCellInnerToLines(cell2.inner).lines);
|
|
23022
|
+
placed.forEach((cell2, i) => {
|
|
23023
|
+
const w = Math.max(...cellLines[i].map((l) => measureTextWidth(unescapeHtml(l).trim(), measureH, 100)), 0) / cell2.colSpan;
|
|
23024
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
23025
|
+
const c = cell2.c + dc;
|
|
23026
|
+
if (w > colMax[c]) colMax[c] = w;
|
|
23027
|
+
if (!cell2.isHeader && w > colMaxBody[c]) colMaxBody[c] = w;
|
|
23028
|
+
}
|
|
23029
|
+
});
|
|
23030
|
+
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth);
|
|
23031
|
+
const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
|
|
23032
|
+
const cellH = style ? Math.round(measureH * 1.6) + 282 : 1500;
|
|
23033
|
+
const tblW = colWidths.reduce((a, b) => a + b, 0);
|
|
22373
23034
|
const tblId = nextTableId();
|
|
22374
|
-
const
|
|
22375
|
-
const
|
|
22376
|
-
const
|
|
22377
|
-
|
|
22378
|
-
|
|
22379
|
-
const tcXmls = placed.map((
|
|
22380
|
-
const k = `${
|
|
22381
|
-
const
|
|
22382
|
-
const
|
|
22383
|
-
const
|
|
22384
|
-
const
|
|
23035
|
+
const useHeaderStyle = !style && (theme.tableHeader !== theme.body || theme.tableHeaderBold);
|
|
23036
|
+
const spanW = (cell2) => colWidths.slice(cell2.c, cell2.c + cell2.colSpan).reduce((a, b) => a + b, 0);
|
|
23037
|
+
const reg = style?.bfRegistry ?? null;
|
|
23038
|
+
let htmlHeaderRows = 0;
|
|
23039
|
+
while (htmlHeaderRows < rows.length && rows[htmlHeaderRows].tag === "th") htmlHeaderRows++;
|
|
23040
|
+
const tcXmls = placed.map((cell2, i) => {
|
|
23041
|
+
const k = `${cell2.r},${cell2.c}`;
|
|
23042
|
+
const isHeader = cell2.isHeader;
|
|
23043
|
+
const baseCharPr = style ? style.charPr : CHAR_NORMAL;
|
|
23044
|
+
const headerCharPr = isHeader && useHeaderStyle ? CHAR_TABLE_HEADER : baseCharPr;
|
|
23045
|
+
const defaultCharPr = style && reg && isHeader ? style.boldCharPr : isHeader ? headerCharPr : baseCharPr;
|
|
23046
|
+
const charPrId = prof?.cellChar.get(k) ?? defaultCharPr;
|
|
23047
|
+
const centered = isHeader || colCentered[cell2.c];
|
|
23048
|
+
const paraPrId = style ? centered ? reg ? style.tblCenterParaPr ?? style.centerParaPr : style.centerParaPr : reg ? style.tblLeftParaPr ?? PARA_NORMAL : PARA_NORMAL : PARA_NORMAL;
|
|
23049
|
+
const lines = cellLines[i];
|
|
22385
23050
|
const paras = lines.map(
|
|
22386
|
-
(line) => `<hp:p paraPrIDRef="
|
|
23051
|
+
(line) => `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(unescapeHtml(line))}</hp:t></hp:run></hp:p>`
|
|
22387
23052
|
);
|
|
22388
|
-
const cellW = spanW(cell.c, cell.colSpan);
|
|
22389
23053
|
let nestedH = 0;
|
|
22390
|
-
for (const nested of extractTopLevelTables(
|
|
22391
|
-
const
|
|
23054
|
+
for (const nested of extractTopLevelTables(cell2.inner)) {
|
|
23055
|
+
const nestedW = Math.max(spanW(cell2) - 1020, 4e3);
|
|
23056
|
+
const nestedXml = generateHtmlTableXml(nested, theme, nestedW, style ? { ...style, totalWidth: nestedW } : null);
|
|
22392
23057
|
if (nestedXml) {
|
|
22393
23058
|
paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${nestedXml}</hp:run></hp:p>`);
|
|
22394
23059
|
nestedH += (nested.match(/<tr[\s>]/gi) ?? []).length * cellH + 300;
|
|
22395
23060
|
}
|
|
22396
23061
|
}
|
|
22397
23062
|
if (paras.length === 0) {
|
|
22398
|
-
paras.push(`<hp:p paraPrIDRef="
|
|
23063
|
+
paras.push(`<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t></hp:t></hp:run></hp:p>`);
|
|
22399
23064
|
}
|
|
22400
|
-
const contentH = Math.max(cellH *
|
|
23065
|
+
const contentH = Math.max(cellH * cell2.rowSpan, Math.max(lines.length, 1) * (style ? Math.round(measureH * 1.6) : 800) + nestedH);
|
|
22401
23066
|
const cellHeight = Math.max(prof?.cellH.get(k) ?? 0, contentH);
|
|
22402
|
-
|
|
23067
|
+
const bf = prof?.cellBf.get(k) ?? (reg ? reg.get(dataCellSpec({
|
|
23068
|
+
row: cell2.r,
|
|
23069
|
+
rowEnd: cell2.r + cell2.rowSpan - 1,
|
|
23070
|
+
col: cell2.c,
|
|
23071
|
+
colEnd: cell2.c + cell2.colSpan - 1,
|
|
23072
|
+
rowCnt,
|
|
23073
|
+
colCnt,
|
|
23074
|
+
headerRows: htmlHeaderRows,
|
|
23075
|
+
fill: isHeader ? style.headerFill ?? "#E6E6E6" : void 0
|
|
23076
|
+
})) : style && isHeader ? style.headerBf : 2);
|
|
23077
|
+
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>`;
|
|
22403
23078
|
});
|
|
22404
23079
|
const trXmls = [];
|
|
22405
23080
|
for (let r = 0; r < rowCnt; r++) {
|
|
22406
23081
|
const rowTcs = tcXmls.filter((_, i) => placed[i].r === r);
|
|
22407
23082
|
trXmls.push(`<hp:tr>${rowTcs.join("")}</hp:tr>`);
|
|
22408
23083
|
}
|
|
22409
|
-
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>`;
|
|
23084
|
+
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>`;
|
|
23085
|
+
}
|
|
23086
|
+
|
|
23087
|
+
// src/hwpx/gen-gongmun-extra.ts
|
|
23088
|
+
var extraTableId = 93e5;
|
|
23089
|
+
function tbl(rows, w, h, cols) {
|
|
23090
|
+
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>`;
|
|
23091
|
+
}
|
|
23092
|
+
function tc(opts) {
|
|
23093
|
+
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>`;
|
|
23094
|
+
}
|
|
23095
|
+
function para(text, paraPrId, charPrId) {
|
|
23096
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
|
|
23097
|
+
}
|
|
23098
|
+
var APPROVAL_COL_W = 7085;
|
|
23099
|
+
var APPROVAL_LABEL_H = 1100;
|
|
23100
|
+
var APPROVAL_SIGN_H = 4200;
|
|
23101
|
+
function buildApprovalTable(labels, gongmun, reg) {
|
|
23102
|
+
const n = labels.length;
|
|
23103
|
+
const w = APPROVAL_COL_W * n;
|
|
23104
|
+
const bfAt = (row, col) => reg.get({
|
|
23105
|
+
t: row === 0 ? "thick" : "thin",
|
|
23106
|
+
b: row === 1 ? "thick" : "thin",
|
|
23107
|
+
l: col === 0 ? "thick" : "thin",
|
|
23108
|
+
r: col === n - 1 ? "thick" : "thin"
|
|
23109
|
+
});
|
|
23110
|
+
const labelRow = labels.map(
|
|
23111
|
+
(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) })
|
|
23112
|
+
).join("");
|
|
23113
|
+
const signRow = labels.map(
|
|
23114
|
+
(_, 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) })
|
|
23115
|
+
).join("");
|
|
23116
|
+
const table2 = tbl([labelRow, signRow], w, APPROVAL_LABEL_H + APPROVAL_SIGN_H, n);
|
|
23117
|
+
return `<hp:p paraPrIDRef="${GONGMUN_RIGHT}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`;
|
|
23118
|
+
}
|
|
23119
|
+
function hasEndMark(lastText) {
|
|
23120
|
+
return /끝\s*\.?\s*$/.test(lastText.trim());
|
|
23121
|
+
}
|
|
23122
|
+
function buildEndMark() {
|
|
23123
|
+
return para(" \uB05D.", PARA_NORMAL, CHAR_NORMAL);
|
|
23124
|
+
}
|
|
23125
|
+
var TITLE_BOX = { barH: 382, titleH: 2850, color: "#0080C0", gradient: ["#0080C0", "#3CBFFF"] };
|
|
23126
|
+
function buildTitleBox(title, titleCharPr, bodyWidth, reg) {
|
|
23127
|
+
const w = bodyWidth - 280;
|
|
23128
|
+
const outer = { t: "thin", b: "thin", l: "thin", r: "thin" };
|
|
23129
|
+
const barTop = reg.get({ ...outer, fill: TITLE_BOX.color });
|
|
23130
|
+
const barBottom = reg.get({ ...outer, fill: { gradient: TITLE_BOX.gradient } });
|
|
23131
|
+
const mid = reg.get(outer);
|
|
23132
|
+
const barPara = `<hp:p paraPrIDRef="${GONGMUN_TBL_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t></hp:t></hp:run></hp:p>`;
|
|
23133
|
+
const rows = [
|
|
23134
|
+
tc({ bf: barTop, row: 0, col: 0, w, h: TITLE_BOX.barH, paras: barPara }),
|
|
23135
|
+
tc({ bf: mid, row: 1, col: 0, w, h: TITLE_BOX.titleH, paras: para(title, GONGMUN_TBL_CENTER, titleCharPr) }),
|
|
23136
|
+
tc({ bf: barBottom, row: 2, col: 0, w, h: TITLE_BOX.barH, paras: barPara })
|
|
23137
|
+
];
|
|
23138
|
+
const table2 = tbl(rows, w, TITLE_BOX.barH * 2 + TITLE_BOX.titleH, 1);
|
|
23139
|
+
return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`;
|
|
22410
23140
|
}
|
|
22411
23141
|
|
|
22412
23142
|
// src/hwpx/equation-generate.ts
|
|
@@ -22696,14 +23426,76 @@ function generateSecPr(gongmun) {
|
|
|
22696
23426
|
header: 0,
|
|
22697
23427
|
footer: 0
|
|
22698
23428
|
} : { top: 8504, bottom: 4252, left: 5670, right: 4252, header: 2835, footer: 2835 };
|
|
22699
|
-
|
|
23429
|
+
if (gongmun) {
|
|
23430
|
+
m.header = gongmun.headerFooter;
|
|
23431
|
+
m.footer = gongmun.headerFooter;
|
|
23432
|
+
}
|
|
23433
|
+
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>`;
|
|
23434
|
+
return gongmun?.pageNumbers ? secPr + pageNumCtrl() : secPr;
|
|
22700
23435
|
}
|
|
22701
|
-
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, remap = null) {
|
|
23436
|
+
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null) {
|
|
22702
23437
|
const paraXmls = [];
|
|
22703
23438
|
let isFirst = true;
|
|
22704
23439
|
let tableSeq = 0;
|
|
22705
23440
|
const orderedCounters = {};
|
|
22706
23441
|
let prevWasOrdered = false;
|
|
23442
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
23443
|
+
const vBase = charVariantBase(gaejosik);
|
|
23444
|
+
const tableStyle = gongmun ? {
|
|
23445
|
+
totalWidth: mmToHwpunit(210 - gongmun.margins.left - gongmun.margins.right),
|
|
23446
|
+
charPr: gaejosik ? GJ_CHAR_TABLE : CHAR_NORMAL,
|
|
23447
|
+
boldCharPr: gaejosik ? GJ_CHAR_TABLE_BOLD : CHAR_BOLD,
|
|
23448
|
+
charHeight: gaejosik ? gaejosikSizes(gongmun.bodyHeight, gongmun.sizes).table : gongmun.bodyHeight,
|
|
23449
|
+
headerBf: gongmunTableHeaderBf(gaejosik),
|
|
23450
|
+
centerParaPr: GONGMUN_CENTER,
|
|
23451
|
+
tblCenterParaPr: GONGMUN_TBL_CENTER,
|
|
23452
|
+
tblLeftParaPr: GONGMUN_TBL_LEFT,
|
|
23453
|
+
bfRegistry: bfReg ?? void 0,
|
|
23454
|
+
rightParaPr: GONGMUN_RIGHT
|
|
23455
|
+
} : null;
|
|
23456
|
+
const chamMap = (id) => id === CHAR_BOLD ? GJ_CHAR_CHAM_BOLD : id;
|
|
23457
|
+
let chapterNo = 0;
|
|
23458
|
+
let coverH1Idx = -1;
|
|
23459
|
+
let pendingPageBreak = false;
|
|
23460
|
+
let pendingNewNum = false;
|
|
23461
|
+
let titleBoxH1Idx = -1;
|
|
23462
|
+
let hasFrontPages = false;
|
|
23463
|
+
const preamble = [];
|
|
23464
|
+
if (gongmun?.approval && bfReg) {
|
|
23465
|
+
preamble.push(buildApprovalTable(gongmun.approval, gongmun, bfReg));
|
|
23466
|
+
}
|
|
23467
|
+
if (gaejosik && gongmun) {
|
|
23468
|
+
const h1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
|
|
23469
|
+
const chapters = blocks.filter((b) => b.type === "heading" && b.level === 2).map((b) => stripChapterNumber(b.text || ""));
|
|
23470
|
+
let coverTitle = "";
|
|
23471
|
+
const hide = (xml, hideHeader) => gongmun.pageNumbers ? xml.replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${pageHidingCtrl(hideHeader)}`) : xml;
|
|
23472
|
+
if (gongmun.cover && h1Idx >= 0) {
|
|
23473
|
+
coverTitle = (blocks[h1Idx].text || "").trim();
|
|
23474
|
+
const coverPart = buildGaejosikCover(coverTitle, gongmun);
|
|
23475
|
+
coverPart[0] = hide(coverPart[0], true);
|
|
23476
|
+
preamble.push(...coverPart);
|
|
23477
|
+
coverH1Idx = h1Idx;
|
|
23478
|
+
hasFrontPages = true;
|
|
23479
|
+
}
|
|
23480
|
+
if (gongmun.toc && chapters.length > 0) {
|
|
23481
|
+
const tocPart = buildGaejosikToc(chapters, gongmun);
|
|
23482
|
+
tocPart[0] = hide(tocPart[0], false);
|
|
23483
|
+
preamble.push(...tocPart);
|
|
23484
|
+
hasFrontPages = true;
|
|
23485
|
+
}
|
|
23486
|
+
if (gongmun.bodyTitleBox && coverTitle && hasFrontPages) {
|
|
23487
|
+
preamble.push(buildGaejosikBodyTitle(coverTitle, gongmun).replace(/^<hp:p /, `<hp:p pageBreak="1" `));
|
|
23488
|
+
}
|
|
23489
|
+
} else if (gongmun && !gaejosik && bfReg && (gongmun.preset === "report" || gongmun.preset === "plan" || gongmun.preset === "notice")) {
|
|
23490
|
+
titleBoxH1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
|
|
23491
|
+
}
|
|
23492
|
+
if (preamble.length > 0) {
|
|
23493
|
+
preamble[0] = preamble[0].replace(` pageBreak="1"`, "").replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${generateSecPr(gongmun)}`);
|
|
23494
|
+
isFirst = false;
|
|
23495
|
+
pendingPageBreak = hasFrontPages && !preamble[preamble.length - 1].includes(`pageBreak="1"`);
|
|
23496
|
+
pendingNewNum = !!gongmun.pageNumbers && hasFrontPages;
|
|
23497
|
+
paraXmls.push(...preamble);
|
|
23498
|
+
}
|
|
22707
23499
|
for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
|
|
22708
23500
|
const block = blocks[blockIdx];
|
|
22709
23501
|
let xml = "";
|
|
@@ -22715,17 +23507,47 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22715
23507
|
}
|
|
22716
23508
|
switch (block.type) {
|
|
22717
23509
|
case "heading": {
|
|
23510
|
+
if (gongmun && blockIdx === titleBoxH1Idx && tableStyle && bfReg) {
|
|
23511
|
+
xml = buildTitleBox((block.text || "").trim(), CHAR_H1, tableStyle.totalWidth, bfReg);
|
|
23512
|
+
break;
|
|
23513
|
+
}
|
|
23514
|
+
if (gaejosik) {
|
|
23515
|
+
const lvl = block.level || 1;
|
|
23516
|
+
if (blockIdx === coverH1Idx) break;
|
|
23517
|
+
if (lvl <= 2) {
|
|
23518
|
+
chapterNo++;
|
|
23519
|
+
xml = buildGaejosikChapter(chapterNo, stripChapterNumber(block.text || ""), gongmun);
|
|
23520
|
+
} else if (lvl === 3) {
|
|
23521
|
+
xml = generateParagraph(
|
|
23522
|
+
`\u25A1 ${block.text || ""}`,
|
|
23523
|
+
GONGMUN_LIST_BASE,
|
|
23524
|
+
GJ_CHAR_DAE,
|
|
23525
|
+
(id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id
|
|
23526
|
+
);
|
|
23527
|
+
} else {
|
|
23528
|
+
xml = generateParagraph(`\u25CB ${block.text || ""}`, GONGMUN_LIST_BASE + 1, CHAR_NORMAL);
|
|
23529
|
+
}
|
|
23530
|
+
break;
|
|
23531
|
+
}
|
|
22718
23532
|
const pId = headingParaPrId(block.level || 1);
|
|
22719
23533
|
const cId = headingCharPrId(block.level || 1);
|
|
22720
|
-
|
|
23534
|
+
const styleId = gongmun ? Math.min(block.level || 1, 4) : 0;
|
|
23535
|
+
xml = generateParagraph(block.text || "", pId, cId, void 0, styleId);
|
|
22721
23536
|
break;
|
|
22722
23537
|
}
|
|
22723
23538
|
case "paragraph": {
|
|
23539
|
+
if (gaejosik && (block.text || "").trimStart().startsWith("\u203B")) {
|
|
23540
|
+
xml = generateParagraph((block.text || "").trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23541
|
+
break;
|
|
23542
|
+
}
|
|
22724
23543
|
const ctr = gongmun && /^<center>([\s\S]*)<\/center>$/i.exec((block.text || "").trim());
|
|
23544
|
+
const rgt = gongmun && /^<right>([\s\S]*)<\/right>$/i.exec((block.text || "").trim());
|
|
22725
23545
|
if (ctr) {
|
|
22726
23546
|
xml = generateParagraph(ctr[1].trim(), GONGMUN_CENTER);
|
|
23547
|
+
} else if (rgt) {
|
|
23548
|
+
xml = generateParagraph(rgt[1].trim(), GONGMUN_RIGHT);
|
|
22727
23549
|
} else {
|
|
22728
|
-
xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx) : void 0);
|
|
23550
|
+
xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx, vBase) : void 0);
|
|
22729
23551
|
}
|
|
22730
23552
|
break;
|
|
22731
23553
|
}
|
|
@@ -22758,22 +23580,37 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22758
23580
|
xml = generateEquationParagraph(block.text || "", blockIdx);
|
|
22759
23581
|
break;
|
|
22760
23582
|
}
|
|
22761
|
-
case "blockquote":
|
|
23583
|
+
case "blockquote": {
|
|
23584
|
+
if (gaejosik) {
|
|
23585
|
+
const t = (block.text || "").trim();
|
|
23586
|
+
if (t) xml = generateParagraph(t.startsWith("\u203B") ? t : `\u203B ${t}`, GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23587
|
+
break;
|
|
23588
|
+
}
|
|
22762
23589
|
xml = generateParagraph(
|
|
22763
23590
|
block.text || "",
|
|
22764
23591
|
PARA_QUOTE,
|
|
22765
23592
|
theme.hasQuoteOption ? CHAR_QUOTE : CHAR_NORMAL
|
|
22766
23593
|
);
|
|
22767
23594
|
break;
|
|
23595
|
+
}
|
|
22768
23596
|
case "list_item": {
|
|
22769
23597
|
if (gongmun && gongmunList) {
|
|
22770
23598
|
const info = gongmunList.get(blockIdx);
|
|
22771
23599
|
const depth = info?.depth ?? 0;
|
|
22772
23600
|
const marker2 = info?.marker ?? "";
|
|
22773
23601
|
const content = block.text || "";
|
|
23602
|
+
if (gaejosik && content.trimStart().startsWith("\u203B")) {
|
|
23603
|
+
xml = generateParagraph(content.trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23604
|
+
break;
|
|
23605
|
+
}
|
|
22774
23606
|
const text = marker2 ? `${marker2} ${content}` : content;
|
|
22775
|
-
|
|
22776
|
-
|
|
23607
|
+
let listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
|
|
23608
|
+
let mapId = fit ? variantMapper(fit, blockIdx, vBase) : void 0;
|
|
23609
|
+
if (gaejosik && depth === 0) {
|
|
23610
|
+
listCharPr = GJ_CHAR_DAE;
|
|
23611
|
+
mapId = (id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id;
|
|
23612
|
+
}
|
|
23613
|
+
xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr, mapId);
|
|
22777
23614
|
break;
|
|
22778
23615
|
}
|
|
22779
23616
|
const indent = block.indent || 0;
|
|
@@ -22800,7 +23637,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22800
23637
|
break;
|
|
22801
23638
|
}
|
|
22802
23639
|
case "hr":
|
|
22803
|
-
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>`;
|
|
23640
|
+
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>`;
|
|
22804
23641
|
break;
|
|
22805
23642
|
case "table":
|
|
22806
23643
|
if (block.rows) {
|
|
@@ -22809,20 +23646,19 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22809
23646
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
22810
23647
|
isFirst = false;
|
|
22811
23648
|
}
|
|
22812
|
-
xml = generateTable(block.rows, theme, remap
|
|
22813
|
-
tableSeq++;
|
|
23649
|
+
xml = generateTable(block.rows, theme, tableStyle, remap, tableSeq++);
|
|
22814
23650
|
}
|
|
22815
23651
|
break;
|
|
22816
23652
|
case "html_table": {
|
|
22817
|
-
const
|
|
22818
|
-
|
|
23653
|
+
const htmlW = tableStyle ? bfReg ? tableStyle.totalWidth - DATA_TABLE_INSET : tableStyle.totalWidth : 44e3;
|
|
23654
|
+
const tbl2 = generateHtmlTableXml(block.text || "", theme, htmlW, tableStyle, remap, tableSeq++);
|
|
23655
|
+
if (tbl2) {
|
|
22819
23656
|
if (isFirst) {
|
|
22820
23657
|
const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
|
|
22821
23658
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
22822
23659
|
isFirst = false;
|
|
22823
23660
|
}
|
|
22824
|
-
xml = `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${
|
|
22825
|
-
tableSeq++;
|
|
23661
|
+
xml = `<hp:p paraPrIDRef="${tableStyle && bfReg ? GONGMUN_RIGHT : 0}" styleIDRef="0"><hp:run charPrIDRef="0">${tbl2}</hp:run></hp:p>`;
|
|
22826
23662
|
} else {
|
|
22827
23663
|
const plain = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
22828
23664
|
xml = plain ? generateParagraph(plain) : "";
|
|
@@ -22838,8 +23674,20 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22838
23674
|
);
|
|
22839
23675
|
isFirst = false;
|
|
22840
23676
|
}
|
|
23677
|
+
if (pendingPageBreak) {
|
|
23678
|
+
xml = xml.replace(/^<hp:p /, `<hp:p pageBreak="1" `);
|
|
23679
|
+
pendingPageBreak = false;
|
|
23680
|
+
}
|
|
23681
|
+
if (pendingNewNum) {
|
|
23682
|
+
xml = xml.replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${newPageNumCtrl(1)}`);
|
|
23683
|
+
pendingNewNum = false;
|
|
23684
|
+
}
|
|
22841
23685
|
paraXmls.push(xml);
|
|
22842
23686
|
}
|
|
23687
|
+
if (gongmun?.endMark && paraXmls.length > 0) {
|
|
23688
|
+
const lastText = [...blocks].reverse().find((b) => (b.type === "paragraph" || b.type === "list_item") && (b.text || "").trim())?.text ?? "";
|
|
23689
|
+
if (!hasEndMark(lastText)) paraXmls.push(buildEndMark());
|
|
23690
|
+
}
|
|
22843
23691
|
if (paraXmls.length === 0) {
|
|
22844
23692
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run></hp:p>`);
|
|
22845
23693
|
}
|
|
@@ -22849,108 +23697,31 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22849
23697
|
</hs:sec>`;
|
|
22850
23698
|
}
|
|
22851
23699
|
|
|
22852
|
-
// src/hwpx/gen-profile.ts
|
|
22853
|
-
function parseHu(s) {
|
|
22854
|
-
if (s == null) return void 0;
|
|
22855
|
-
const n = parseInt(String(s).trim(), 10);
|
|
22856
|
-
return Number.isFinite(n) ? n : void 0;
|
|
22857
|
-
}
|
|
22858
|
-
function edgeXml(tag, d) {
|
|
22859
|
-
return d ? `<hh:${tag} type="${d.type}" width="${d.width}" color="${d.color}"/>` : `<hh:${tag} type="NONE" width="0.1 mm" color="#000000"/>`;
|
|
22860
|
-
}
|
|
22861
|
-
function borderFillDefToXml(id, def) {
|
|
22862
|
-
const fill = def.fill?.faceColor ? `<hh:fillBrush><hh:winBrush faceColor="${def.fill.faceColor}" hatchColor="#000000" alpha="0"/></hh:fillBrush>` : "";
|
|
22863
|
-
return ` <hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
22864
|
-
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
22865
|
-
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
22866
|
-
${edgeXml("leftBorder", def.leftBorder)}
|
|
22867
|
-
${edgeXml("rightBorder", def.rightBorder)}
|
|
22868
|
-
${edgeXml("topBorder", def.topBorder)}
|
|
22869
|
-
${edgeXml("bottomBorder", def.bottomBorder)}${fill ? `
|
|
22870
|
-
${fill}` : ""}
|
|
22871
|
-
</hh:borderFill>`;
|
|
22872
|
-
}
|
|
22873
|
-
function profileCharPrXml(id, def) {
|
|
22874
|
-
const height = parseHu(def.height_hwpunit) ?? 1e3;
|
|
22875
|
-
const color = def.textColor ?? "#000000";
|
|
22876
|
-
const font = def.fontRef_hangul != null ? parseInt(def.fontRef_hangul, 10) || 0 : 0;
|
|
22877
|
-
const boldAttr = def.bold ? ` bold="1"` : "";
|
|
22878
|
-
const italicAttr = def.italic ? ` italic="1"` : "";
|
|
22879
|
-
const underline = def.underline ? `
|
|
22880
|
-
<hh:underline type="BOTTOM" shape="SOLID" color="${color}"/>` : "";
|
|
22881
|
-
return ` <hh:charPr id="${id}" height="${height}" textColor="${color}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
22882
|
-
<hh:fontRef hangul="${font}" latin="${font}" hanja="${font}" japanese="${font}" other="${font}" symbol="${font}" user="${font}"/>
|
|
22883
|
-
<hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
22884
|
-
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
22885
|
-
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
22886
|
-
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>${underline}
|
|
22887
|
-
</hh:charPr>`;
|
|
22888
|
-
}
|
|
22889
|
-
function buildProfileRemap(profile, charPrBase, borderFillBase = 3) {
|
|
22890
|
-
const remap = { borderFillXmls: [], charPrXmls: [], tables: /* @__PURE__ */ new Map() };
|
|
22891
|
-
let bfNext = borderFillBase;
|
|
22892
|
-
let charNext = charPrBase;
|
|
22893
|
-
for (const t of profile.tables) {
|
|
22894
|
-
const localBf = {};
|
|
22895
|
-
for (const [key, def] of Object.entries(t.used_border_fills ?? {})) {
|
|
22896
|
-
const gid = bfNext++;
|
|
22897
|
-
remap.borderFillXmls.push(borderFillDefToXml(gid, def));
|
|
22898
|
-
localBf[key] = gid;
|
|
22899
|
-
}
|
|
22900
|
-
const localChar = {};
|
|
22901
|
-
for (const [key, def] of Object.entries(t.used_char_prs ?? {})) {
|
|
22902
|
-
const gid = charNext++;
|
|
22903
|
-
remap.charPrXmls.push(profileCharPrXml(gid, def));
|
|
22904
|
-
localChar[key] = gid;
|
|
22905
|
-
}
|
|
22906
|
-
let colWidths;
|
|
22907
|
-
if (t.col_widths_hwpunit && t.col_widths_hwpunit.length === t.cols) {
|
|
22908
|
-
const parsed = t.col_widths_hwpunit.map(parseHu);
|
|
22909
|
-
if (parsed.every((n) => n != null)) colWidths = parsed;
|
|
22910
|
-
}
|
|
22911
|
-
const tr = {
|
|
22912
|
-
rows: t.rows,
|
|
22913
|
-
cols: t.cols,
|
|
22914
|
-
width: parseHu(t.width_hwpunit),
|
|
22915
|
-
colWidths,
|
|
22916
|
-
cellBf: /* @__PURE__ */ new Map(),
|
|
22917
|
-
cellChar: /* @__PURE__ */ new Map(),
|
|
22918
|
-
cellH: /* @__PURE__ */ new Map()
|
|
22919
|
-
};
|
|
22920
|
-
for (const cell of t.cells) {
|
|
22921
|
-
const k = `${cell.row},${cell.col}`;
|
|
22922
|
-
if (cell.borderFillIDRef != null && cell.borderFillIDRef in localBf) {
|
|
22923
|
-
tr.cellBf.set(k, localBf[cell.borderFillIDRef]);
|
|
22924
|
-
}
|
|
22925
|
-
if (cell.charPrIDRef != null && cell.charPrIDRef in localChar) {
|
|
22926
|
-
tr.cellChar.set(k, localChar[cell.charPrIDRef]);
|
|
22927
|
-
}
|
|
22928
|
-
const h = parseHu(cell.height_hwpunit);
|
|
22929
|
-
if (h != null) tr.cellH.set(k, h);
|
|
22930
|
-
}
|
|
22931
|
-
remap.tables.set(t.table_index, tr);
|
|
22932
|
-
}
|
|
22933
|
-
return remap;
|
|
22934
|
-
}
|
|
22935
|
-
function profileCharPrBase(ratioVariantCount) {
|
|
22936
|
-
return CHAR_VARIANT_BASE + ratioVariantCount * 4;
|
|
22937
|
-
}
|
|
22938
|
-
|
|
22939
23700
|
// src/hwpx/generator.ts
|
|
22940
23701
|
async function markdownToHwpx(markdown, options) {
|
|
22941
23702
|
const theme = resolveTheme(options?.theme);
|
|
22942
23703
|
const gongmun = options?.gongmun ? resolveGongmun(options.gongmun) : null;
|
|
23704
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
22943
23705
|
const blocks = parseMarkdownToBlocks(markdown);
|
|
22944
23706
|
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
22945
23707
|
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
22946
|
-
const
|
|
23708
|
+
const staticBfEnd = gongmun ? gaejosik ? 11 : 4 : 3;
|
|
23709
|
+
const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(gaejosik) + (fit?.variants?.length ?? 0) * 4, staticBfEnd) : null;
|
|
23710
|
+
const bfReg = gongmun ? new TableBfRegistry(staticBfEnd + (remap?.borderFillXmls.length ?? 0)) : null;
|
|
22947
23711
|
const chartParts = [];
|
|
22948
|
-
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, remap);
|
|
23712
|
+
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap);
|
|
23713
|
+
if (remap && remap.tables.length > 0) {
|
|
23714
|
+
const unused = remap.tables.filter((t) => !t.used).length;
|
|
23715
|
+
if (unused === remap.tables.length) {
|
|
23716
|
+
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)`);
|
|
23717
|
+
}
|
|
23718
|
+
}
|
|
23719
|
+
const extraBorderFills = [...remap?.borderFillXmls ?? [], ...bfReg?.emit() ?? []];
|
|
22949
23720
|
const zip = new JSZip7();
|
|
22950
23721
|
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
22951
23722
|
zip.file("META-INF/container.xml", generateContainerXml());
|
|
22952
23723
|
zip.file("Contents/content.hpf", generateManifest(chartParts));
|
|
22953
|
-
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? [], remap));
|
|
23724
|
+
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? [], extraBorderFills, remap?.charPrXmls ?? []));
|
|
22954
23725
|
zip.file("Contents/section0.xml", sectionXml);
|
|
22955
23726
|
for (const part of chartParts) zip.file(part.name, part.xml);
|
|
22956
23727
|
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
@@ -23220,6 +23991,12 @@ function parseParaGeom(el) {
|
|
|
23220
23991
|
g.spaceBefore = v("prev");
|
|
23221
23992
|
g.spaceAfter = v("next");
|
|
23222
23993
|
}
|
|
23994
|
+
const bs = findDeep(el, "breakSetting");
|
|
23995
|
+
if (bs) {
|
|
23996
|
+
const nl = bs.getAttribute("breakNonLatinWord");
|
|
23997
|
+
if (nl === "BREAK_WORD") g.wrapMode = "keep";
|
|
23998
|
+
else if (nl === "KEEP_WORD") g.wrapMode = "charAll";
|
|
23999
|
+
}
|
|
23223
24000
|
return g;
|
|
23224
24001
|
}
|
|
23225
24002
|
function parseRenderStyles(headXml) {
|
|
@@ -23327,9 +24104,9 @@ function collectSites(scan) {
|
|
|
23327
24104
|
if (depth > 16) return;
|
|
23328
24105
|
for (const t of tables) {
|
|
23329
24106
|
for (const row of t.rows) {
|
|
23330
|
-
for (const
|
|
23331
|
-
for (const p of
|
|
23332
|
-
walkTables(
|
|
24107
|
+
for (const cell2 of row) {
|
|
24108
|
+
for (const p of cell2.paragraphs) sites.push({ para: p, cell: cell2, table: t, nested: depth > 0, outer: outer.length ? outer : void 0 });
|
|
24109
|
+
walkTables(cell2.tables, depth + 1, [...outer, { cell: cell2, table: t }]);
|
|
23333
24110
|
}
|
|
23334
24111
|
}
|
|
23335
24112
|
}
|
|
@@ -23343,18 +24120,18 @@ function attrOf(openTag, name) {
|
|
|
23343
24120
|
const m = openTag.match(new RegExp(`\\b${name}="([^"]*)"`));
|
|
23344
24121
|
return m?.[1];
|
|
23345
24122
|
}
|
|
23346
|
-
function paraOpenTag(xml,
|
|
23347
|
-
const end = xml.indexOf(">",
|
|
23348
|
-
return end === -1 ? "" : xml.slice(
|
|
24123
|
+
function paraOpenTag(xml, para2) {
|
|
24124
|
+
const end = xml.indexOf(">", para2.start);
|
|
24125
|
+
return end === -1 ? "" : xml.slice(para2.start, end + 1);
|
|
23349
24126
|
}
|
|
23350
|
-
function anchorRunInfo(xml,
|
|
23351
|
-
let tr =
|
|
24127
|
+
function anchorRunInfo(xml, para2, anchor) {
|
|
24128
|
+
let tr = para2.tRanges.find((r) => !r.selfClosing && xml.slice(r.contentStart, r.contentEnd).includes(anchor));
|
|
23352
24129
|
if (!tr) {
|
|
23353
24130
|
const head = anchor[0];
|
|
23354
|
-
tr =
|
|
24131
|
+
tr = para2.tRanges.find((r) => !r.selfClosing && xml.slice(r.contentStart, r.contentEnd).includes(head)) ?? para2.tRanges[para2.tRanges.length - 1];
|
|
23355
24132
|
}
|
|
23356
24133
|
if (!tr) return null;
|
|
23357
|
-
const before = xml.slice(Math.max(0,
|
|
24134
|
+
const before = xml.slice(Math.max(0, para2.start), tr.contentStart);
|
|
23358
24135
|
const runOpen = [...before.matchAll(/<([A-Za-z0-9]+):run\b[^>]*>/g)].pop();
|
|
23359
24136
|
const prefix = runOpen?.[1] ?? tr.prefix ?? "hp";
|
|
23360
24137
|
const charPr2 = runOpen && attrOf(runOpen[0], "charPrIDRef") || "0";
|
|
@@ -23362,37 +24139,37 @@ function anchorRunInfo(xml, para, anchor) {
|
|
|
23362
24139
|
if (close === -1) return null;
|
|
23363
24140
|
return { charPr: charPr2, prefix, insertAt: close + `</${prefix}:run>`.length };
|
|
23364
24141
|
}
|
|
23365
|
-
function cellAddrWindow(xml,
|
|
23366
|
-
if (!
|
|
23367
|
-
return xml.slice(
|
|
24142
|
+
function cellAddrWindow(xml, cell2) {
|
|
24143
|
+
if (!cell2.addrTagRange) return null;
|
|
24144
|
+
return xml.slice(cell2.addrTagRange.end, cell2.addrTagRange.end + 400);
|
|
23368
24145
|
}
|
|
23369
|
-
function cellSzWidthHu(xml,
|
|
23370
|
-
const win = cellAddrWindow(xml,
|
|
24146
|
+
function cellSzWidthHu(xml, cell2) {
|
|
24147
|
+
const win = cellAddrWindow(xml, cell2);
|
|
23371
24148
|
if (win) {
|
|
23372
24149
|
const m = win.match(/<[A-Za-z0-9]+:cellSz\b[^>]*\bwidth="(\d+)"/);
|
|
23373
24150
|
if (m) return Number(m[1]);
|
|
23374
24151
|
}
|
|
23375
|
-
const firstPara =
|
|
24152
|
+
const firstPara = cell2.paragraphs[0];
|
|
23376
24153
|
if (!firstPara) return null;
|
|
23377
24154
|
const upto = xml.slice(0, firstPara.start);
|
|
23378
24155
|
const szMatch = [...upto.matchAll(/<[A-Za-z0-9]+:cellSz\b[^>]*\bwidth="(\d+)"[^>]*>/g)].pop();
|
|
23379
24156
|
return szMatch ? Number(szMatch[1]) : null;
|
|
23380
24157
|
}
|
|
23381
|
-
function cellContentWidthMm(xml,
|
|
23382
|
-
const width = cellSzWidthHu(xml,
|
|
24158
|
+
function cellContentWidthMm(xml, cell2) {
|
|
24159
|
+
const width = cellSzWidthHu(xml, cell2);
|
|
23383
24160
|
if (width === null) return null;
|
|
23384
24161
|
let content = width;
|
|
23385
|
-
const win = cellAddrWindow(xml,
|
|
24162
|
+
const win = cellAddrWindow(xml, cell2);
|
|
23386
24163
|
const mg = win?.match(/<[A-Za-z0-9]+:cellMargin\b[^>]*>/);
|
|
23387
24164
|
if (mg) {
|
|
23388
24165
|
content -= Number(attrOf(mg[0], "left") ?? 0) + Number(attrOf(mg[0], "right") ?? 0);
|
|
23389
24166
|
}
|
|
23390
24167
|
return content > 0 ? content / HU_PER_MM2 : null;
|
|
23391
24168
|
}
|
|
23392
|
-
function cellLeftOffsetMm(xml,
|
|
23393
|
-
if (
|
|
24169
|
+
function cellLeftOffsetMm(xml, table2, cell2) {
|
|
24170
|
+
if (cell2.colAddr === void 0) return 0;
|
|
23394
24171
|
const colW = /* @__PURE__ */ new Map();
|
|
23395
|
-
for (const row of
|
|
24172
|
+
for (const row of table2.rows) {
|
|
23396
24173
|
for (const c of row) {
|
|
23397
24174
|
if (c.colAddr === void 0 || colW.has(c.colAddr)) continue;
|
|
23398
24175
|
if (c.colSpan > 1) continue;
|
|
@@ -23401,7 +24178,7 @@ function cellLeftOffsetMm(xml, table, cell) {
|
|
|
23401
24178
|
}
|
|
23402
24179
|
}
|
|
23403
24180
|
let sum = 0;
|
|
23404
|
-
for (let col = 0; col <
|
|
24181
|
+
for (let col = 0; col < cell2.colAddr; col++) sum += colW.get(col) ?? 0;
|
|
23405
24182
|
return sum / HU_PER_MM2;
|
|
23406
24183
|
}
|
|
23407
24184
|
function bodyColumnWidthMm(xml) {
|
|
@@ -23640,8 +24417,8 @@ function parseCharPrs(headerDoc) {
|
|
|
23640
24417
|
}
|
|
23641
24418
|
return map;
|
|
23642
24419
|
}
|
|
23643
|
-
function isTopLevelTable(
|
|
23644
|
-
let p =
|
|
24420
|
+
function isTopLevelTable(tbl2) {
|
|
24421
|
+
let p = tbl2.parentNode;
|
|
23645
24422
|
while (p) {
|
|
23646
24423
|
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
23647
24424
|
if (tag === "tbl") return false;
|
|
@@ -23654,57 +24431,61 @@ function num(s) {
|
|
|
23654
24431
|
const n = parseInt(s, 10);
|
|
23655
24432
|
return Number.isFinite(n) ? n : void 0;
|
|
23656
24433
|
}
|
|
23657
|
-
function parseTable3(
|
|
23658
|
-
const rows = num(
|
|
23659
|
-
const cols = num(
|
|
23660
|
-
const sz = findChildByLocalName(
|
|
24434
|
+
function parseTable3(tbl2, tableIndex, borderFills, charPrs) {
|
|
24435
|
+
const rows = num(tbl2.getAttribute("rowCnt")) ?? 0;
|
|
24436
|
+
const cols = num(tbl2.getAttribute("colCnt")) ?? 0;
|
|
24437
|
+
const sz = findChildByLocalName(tbl2, "sz");
|
|
23661
24438
|
const width = sz?.getAttribute("width") || void 0;
|
|
23662
24439
|
const cells = [];
|
|
23663
24440
|
const usedBf = /* @__PURE__ */ new Set();
|
|
23664
24441
|
const usedCp = /* @__PURE__ */ new Set();
|
|
23665
24442
|
const colWidths = new Array(cols).fill(void 0);
|
|
23666
|
-
|
|
23667
|
-
|
|
23668
|
-
|
|
23669
|
-
const
|
|
23670
|
-
const
|
|
24443
|
+
let anchorText = "";
|
|
24444
|
+
for (const tc2 of elemsByLocal(tbl2, "tc")) {
|
|
24445
|
+
if (nearestTable(tc2) !== tbl2) continue;
|
|
24446
|
+
const addr = findChildByLocalName(tc2, "cellAddr");
|
|
24447
|
+
const span = findChildByLocalName(tc2, "cellSpan");
|
|
24448
|
+
const csz = findChildByLocalName(tc2, "cellSz");
|
|
23671
24449
|
const row = num(addr?.getAttribute("rowAddr")) ?? 0;
|
|
23672
24450
|
const col = num(addr?.getAttribute("colAddr")) ?? 0;
|
|
24451
|
+
if (row === 0 && col === 0 && !anchorText) anchorText = directCellText(tc2);
|
|
23673
24452
|
const colSpan = num(span?.getAttribute("colSpan")) ?? 1;
|
|
23674
24453
|
const rowSpan = num(span?.getAttribute("rowSpan")) ?? 1;
|
|
23675
|
-
const bfId =
|
|
23676
|
-
const cpId = firstRunCharPr(
|
|
23677
|
-
const
|
|
24454
|
+
const bfId = tc2.getAttribute("borderFillIDRef") || void 0;
|
|
24455
|
+
const cpId = firstRunCharPr(tc2);
|
|
24456
|
+
const cell2 = { row, col, rowSpan, colSpan };
|
|
23678
24457
|
const w = csz?.getAttribute("width");
|
|
23679
24458
|
const hh = csz?.getAttribute("height");
|
|
23680
|
-
if (w)
|
|
23681
|
-
if (hh)
|
|
24459
|
+
if (w) cell2.width_hwpunit = w;
|
|
24460
|
+
if (hh) cell2.height_hwpunit = hh;
|
|
23682
24461
|
if (bfId) {
|
|
23683
|
-
|
|
24462
|
+
cell2.borderFillIDRef = bfId;
|
|
23684
24463
|
usedBf.add(bfId);
|
|
23685
24464
|
}
|
|
23686
24465
|
if (cpId) {
|
|
23687
|
-
|
|
24466
|
+
cell2.charPrIDRef = cpId;
|
|
23688
24467
|
usedCp.add(cpId);
|
|
23689
24468
|
}
|
|
23690
|
-
cells.push(
|
|
24469
|
+
cells.push(cell2);
|
|
23691
24470
|
if (row === 0 && colSpan === 1 && col < cols && w) colWidths[col] = w;
|
|
23692
24471
|
}
|
|
23693
|
-
const
|
|
24472
|
+
const table2 = {
|
|
23694
24473
|
table_index: tableIndex,
|
|
23695
24474
|
rows,
|
|
23696
24475
|
cols,
|
|
23697
24476
|
cells,
|
|
23698
24477
|
used_border_fills: pick(borderFills, usedBf)
|
|
23699
24478
|
};
|
|
23700
|
-
|
|
23701
|
-
if (
|
|
24479
|
+
const anchor = normalizeAnchor(anchorText);
|
|
24480
|
+
if (anchor) table2.anchor_text = anchor;
|
|
24481
|
+
if (width) table2.width_hwpunit = width;
|
|
24482
|
+
if (colWidths.every((w) => w != null)) table2.col_widths_hwpunit = colWidths;
|
|
23702
24483
|
const cp = pick(charPrs, usedCp);
|
|
23703
|
-
if (Object.keys(cp).length)
|
|
23704
|
-
return
|
|
24484
|
+
if (Object.keys(cp).length) table2.used_char_prs = cp;
|
|
24485
|
+
return table2;
|
|
23705
24486
|
}
|
|
23706
|
-
function nearestTable(
|
|
23707
|
-
let p =
|
|
24487
|
+
function nearestTable(tc2) {
|
|
24488
|
+
let p = tc2.parentNode;
|
|
23708
24489
|
while (p) {
|
|
23709
24490
|
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
23710
24491
|
if (tag === "tbl") return p;
|
|
@@ -23712,9 +24493,9 @@ function nearestTable(tc) {
|
|
|
23712
24493
|
}
|
|
23713
24494
|
return null;
|
|
23714
24495
|
}
|
|
23715
|
-
function firstRunCharPr(
|
|
23716
|
-
for (const run of elemsByLocal(
|
|
23717
|
-
if (nearestCell(run) !==
|
|
24496
|
+
function firstRunCharPr(tc2) {
|
|
24497
|
+
for (const run of elemsByLocal(tc2, "run")) {
|
|
24498
|
+
if (nearestCell(run) !== tc2) continue;
|
|
23718
24499
|
const id = run.getAttribute("charPrIDRef");
|
|
23719
24500
|
if (id) return id;
|
|
23720
24501
|
}
|
|
@@ -23729,6 +24510,15 @@ function nearestCell(el) {
|
|
|
23729
24510
|
}
|
|
23730
24511
|
return null;
|
|
23731
24512
|
}
|
|
24513
|
+
function directCellText(tc2) {
|
|
24514
|
+
let out = "";
|
|
24515
|
+
for (const t of elemsByLocal(tc2, "t")) {
|
|
24516
|
+
if (nearestCell(t) !== tc2) continue;
|
|
24517
|
+
out += t.textContent ?? "";
|
|
24518
|
+
if (out.length >= 64) break;
|
|
24519
|
+
}
|
|
24520
|
+
return out;
|
|
24521
|
+
}
|
|
23732
24522
|
function pick(map, keys) {
|
|
23733
24523
|
const out = {};
|
|
23734
24524
|
for (const k of keys) {
|
|
@@ -23752,12 +24542,166 @@ async function hwpxToProfile(input) {
|
|
|
23752
24542
|
let tableIndex = 0;
|
|
23753
24543
|
for (const f of sectionFiles) {
|
|
23754
24544
|
const doc = parser.parseFromString(await f.async("text"), "text/xml");
|
|
23755
|
-
for (const
|
|
23756
|
-
if (!isTopLevelTable(
|
|
23757
|
-
tables.push(parseTable3(
|
|
24545
|
+
for (const tbl2 of elemsByLocal(doc, "tbl")) {
|
|
24546
|
+
if (!isTopLevelTable(tbl2)) continue;
|
|
24547
|
+
tables.push(parseTable3(tbl2, tableIndex++, borderFills, charPrs));
|
|
23758
24548
|
}
|
|
23759
24549
|
}
|
|
23760
|
-
return { schema_version: "0.
|
|
24550
|
+
return { schema_version: "0.2.0", tables };
|
|
24551
|
+
}
|
|
24552
|
+
|
|
24553
|
+
// src/hwpx/font-catalog.ts
|
|
24554
|
+
var HANCOM_BUNDLED = [
|
|
24555
|
+
"\uD568\uCD08\uB86C\uBC14\uD0D5",
|
|
24556
|
+
"\uD568\uCD08\uB86C\uB3CB\uC6C0",
|
|
24557
|
+
"\uD55C\uCEF4\uBC14\uD0D5",
|
|
24558
|
+
"\uD55C\uCEF4\uB3CB\uC6C0",
|
|
24559
|
+
"\uD55C\uCEF4 \uACE0\uB515",
|
|
24560
|
+
"\uD55C\uCEF4\uACE0\uB515",
|
|
24561
|
+
"\uD55C\uCEF4 \uB9D0\uB791\uB9D0\uB791",
|
|
24562
|
+
"\uD55C\uCEF4\uC0B0\uB73B\uB3CB\uC6C0",
|
|
24563
|
+
"\uD55C\uCEF4\uC194\uC78E",
|
|
24564
|
+
"HY\uD5E4\uB4DC\uB77C\uC778M",
|
|
24565
|
+
"HY\uACAC\uACE0\uB515",
|
|
24566
|
+
"HY\uACAC\uBA85\uC870",
|
|
24567
|
+
"HY\uC911\uACE0\uB515",
|
|
24568
|
+
"HY\uC2E0\uBA85\uC870",
|
|
24569
|
+
"HY\uBA85\uC870",
|
|
24570
|
+
"HY\uADF8\uB798\uD53DM",
|
|
24571
|
+
"HY\uAD81\uC11C",
|
|
24572
|
+
"HY\uAC15M",
|
|
24573
|
+
"HY\uAC15B",
|
|
24574
|
+
"HY\uC6B8\uB989\uB3C4M",
|
|
24575
|
+
"HY\uC6B8\uB989\uB3C4B",
|
|
24576
|
+
"HY\uD0DC\uBC31B",
|
|
24577
|
+
"HY\uC218\uD3C9\uC120M",
|
|
24578
|
+
"HY\uC218\uD3C9\uC120B",
|
|
24579
|
+
"HY\uC13C\uC2A4L",
|
|
24580
|
+
"HY\uC595\uC740\uC0D8\uBB3CM",
|
|
24581
|
+
"HY\uBAA9\uD310L",
|
|
24582
|
+
"HY\uC5FD\uC11CM",
|
|
24583
|
+
"HY\uC5FD\uC11CL",
|
|
24584
|
+
"HY\uB3D9\uB158M",
|
|
24585
|
+
"HY\uB3D9\uB158B",
|
|
24586
|
+
"\uD55C\uC591\uC2E0\uBA85\uC870",
|
|
24587
|
+
"\uD55C\uC591\uC911\uACE0\uB515",
|
|
24588
|
+
"\uD55C\uC591\uACAC\uBA85\uC870",
|
|
24589
|
+
"\uD55C\uC591\uACAC\uACE0\uB515",
|
|
24590
|
+
"\uD55C\uC591\uAD81\uC11C",
|
|
24591
|
+
"\uD55C\uC591\uADF8\uB798\uD53D",
|
|
24592
|
+
"\uD734\uBA3C\uBA85\uC870",
|
|
24593
|
+
"\uD734\uBA3C\uACE0\uB515",
|
|
24594
|
+
"\uD734\uBA3C\uAD75\uC740\uD338\uCCB4",
|
|
24595
|
+
"\uD734\uBA3C\uAC00\uB294\uD338\uCCB4",
|
|
24596
|
+
"\uD734\uBA3C\uAD75\uC740\uC0D8\uCCB4",
|
|
24597
|
+
"\uD734\uBA3C\uAC00\uB294\uC0D8\uCCB4",
|
|
24598
|
+
"\uD734\uBA3C\uC61B\uCCB4",
|
|
24599
|
+
"\uD734\uBA3C\uC544\uBBF8\uCCB4",
|
|
24600
|
+
"\uD734\uBA3C\uD3B8\uC9C0\uCCB4",
|
|
24601
|
+
"\uD734\uBA3C\uB465\uADFC\uD5E4\uB4DC\uB77C\uC778",
|
|
24602
|
+
"\uD734\uBA3C\uBAA8\uC74CT",
|
|
24603
|
+
"\uD0DC \uB098\uBB34",
|
|
24604
|
+
"\uD0DC \uADF8\uB298",
|
|
24605
|
+
"\uC591\uC7AC\uAE68\uBE44\uCCB4B",
|
|
24606
|
+
"\uC591\uC7AC\uB09C\uCD08\uCCB4M",
|
|
24607
|
+
"\uC591\uC7AC\uB458\uAE30\uCCB4M",
|
|
24608
|
+
"\uC591\uC7AC\uBE14\uB7ED\uCCB4",
|
|
24609
|
+
"\uBB38\uCCB4\uBD80 \uAD81\uCCB4 \uC815\uC790\uCCB4",
|
|
24610
|
+
"\uBB38\uCCB4\uBD80 \uAD81\uCCB4 \uD758\uB9BC\uCCB4",
|
|
24611
|
+
"\uBB38\uCCB4\uBD80 \uB3CB\uC6C0\uCCB4",
|
|
24612
|
+
"\uBB38\uCCB4\uBD80 \uBC14\uD0D5\uCCB4",
|
|
24613
|
+
"\uBB38\uCCB4\uBD80 \uC4F0\uAE30 \uC815\uCCB4",
|
|
24614
|
+
"\uBB38\uCCB4\uBD80 \uC81C\uBAA9 \uB3CB\uC6C0\uCCB4",
|
|
24615
|
+
"\uBB38\uCCB4\uBD80 \uC81C\uBAA9 \uBC14\uD0D5\uCCB4",
|
|
24616
|
+
"\uC2E0\uBA85 \uC2E0\uBA85\uC870",
|
|
24617
|
+
"\uC2E0\uBA85 \uC2E0\uC2E0\uBA85\uC870",
|
|
24618
|
+
"\uC2E0\uBA85 \uACAC\uBA85\uC870",
|
|
24619
|
+
"\uC2E0\uBA85 \uC911\uACE0\uB515",
|
|
24620
|
+
"\uC2E0\uBA85 \uD0DC\uACE0\uB515",
|
|
24621
|
+
"\uC2E0\uBA85 \uACAC\uACE0\uB515",
|
|
24622
|
+
"\uC2E0\uBA85 \uC2E0\uBB38\uBA85\uC870",
|
|
24623
|
+
"MD\uAC1C\uC131\uCCB4",
|
|
24624
|
+
"MD\uC544\uB871\uCCB4",
|
|
24625
|
+
"MD\uC194\uCCB4",
|
|
24626
|
+
"MD\uC774\uC19D\uCCB4",
|
|
24627
|
+
"MD\uC544\uD2B8\uCCB4",
|
|
24628
|
+
"\uAC00\uB294\uC548\uC0C1\uC218\uCCB4",
|
|
24629
|
+
"\uC911\uAC04\uC548\uC0C1\uC218\uCCB4",
|
|
24630
|
+
"\uAD75\uC740\uC548\uC0C1\uC218\uCCB4",
|
|
24631
|
+
"HCI Poppy",
|
|
24632
|
+
"HCI Tulip",
|
|
24633
|
+
"-\uC544\uC774\uB9AC\uC2A4M"
|
|
24634
|
+
];
|
|
24635
|
+
var WINDOWS_DEFAULT = [
|
|
24636
|
+
"\uB9D1\uC740 \uACE0\uB515",
|
|
24637
|
+
"\uB9D1\uC740\uACE0\uB515",
|
|
24638
|
+
"Malgun Gothic",
|
|
24639
|
+
"\uAD74\uB9BC",
|
|
24640
|
+
"\uAD74\uB9BC\uCCB4",
|
|
24641
|
+
"\uB3CB\uC6C0",
|
|
24642
|
+
"\uB3CB\uC6C0\uCCB4",
|
|
24643
|
+
"\uBC14\uD0D5",
|
|
24644
|
+
"\uBC14\uD0D5\uCCB4",
|
|
24645
|
+
"\uAD81\uC11C",
|
|
24646
|
+
"\uAD81\uC11C\uCCB4",
|
|
24647
|
+
"Arial",
|
|
24648
|
+
"Arial Black",
|
|
24649
|
+
"Times New Roman",
|
|
24650
|
+
"Courier New",
|
|
24651
|
+
"Consolas",
|
|
24652
|
+
"Calibri",
|
|
24653
|
+
"Cambria",
|
|
24654
|
+
"Segoe UI",
|
|
24655
|
+
"Tahoma",
|
|
24656
|
+
"Verdana",
|
|
24657
|
+
"Georgia",
|
|
24658
|
+
"Symbol"
|
|
24659
|
+
];
|
|
24660
|
+
var COMMON_FREE = [
|
|
24661
|
+
"\uB098\uB214\uACE0\uB515",
|
|
24662
|
+
"\uB098\uB214\uBA85\uC870",
|
|
24663
|
+
"\uB098\uB214\uBC14\uB978\uACE0\uB515",
|
|
24664
|
+
"\uB098\uB214\uC2A4\uD018\uC5B4",
|
|
24665
|
+
"\uB098\uB214\uC190\uAE00\uC528 \uBD93",
|
|
24666
|
+
"\uB098\uB214\uC190\uAE00\uC528 \uD39C",
|
|
24667
|
+
"NanumGothic",
|
|
24668
|
+
"NanumMyeongjo",
|
|
24669
|
+
"Noto Sans KR",
|
|
24670
|
+
"Noto Serif KR",
|
|
24671
|
+
"\uBCF8\uACE0\uB515",
|
|
24672
|
+
"\uBCF8\uBA85\uC870",
|
|
24673
|
+
"Pretendard",
|
|
24674
|
+
"\uD504\uB9AC\uD150\uB2E4\uB4DC",
|
|
24675
|
+
"KoPub\uB3CB\uC6C0",
|
|
24676
|
+
"KoPub\uBC14\uD0D5",
|
|
24677
|
+
"KoPubWorld\uB3CB\uC6C0",
|
|
24678
|
+
"KoPubWorld\uBC14\uD0D5",
|
|
24679
|
+
"\uC5D0\uC2A4\uCF54\uC5B4 \uB4DC\uB9BC",
|
|
24680
|
+
"S-Core Dream",
|
|
24681
|
+
"G\uB9C8\uCF13 \uC0B0\uC2A4",
|
|
24682
|
+
"Gmarket Sans",
|
|
24683
|
+
"\uC724\uACE0\uB515",
|
|
24684
|
+
"\uC724\uACE0\uB515320",
|
|
24685
|
+
"\uC724\uACE0\uB515330",
|
|
24686
|
+
"\uC724\uACE0\uB515340",
|
|
24687
|
+
"\uC724\uBA85\uC870"
|
|
24688
|
+
];
|
|
24689
|
+
function norm(name) {
|
|
24690
|
+
return name.replace(/\s+/g, "").toLowerCase();
|
|
24691
|
+
}
|
|
24692
|
+
var KNOWN = new Set([...HANCOM_BUNDLED, ...WINDOWS_DEFAULT, ...COMMON_FREE].map(norm));
|
|
24693
|
+
function isKnownFont(name) {
|
|
24694
|
+
return KNOWN.has(norm(name));
|
|
24695
|
+
}
|
|
24696
|
+
function unknownFontWarnings(fonts) {
|
|
24697
|
+
const warnings = [];
|
|
24698
|
+
for (const [role, name] of Object.entries(fonts)) {
|
|
24699
|
+
if (!name || isKnownFont(name)) continue;
|
|
24700
|
+
warnings.push(
|
|
24701
|
+
`\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)`
|
|
24702
|
+
);
|
|
24703
|
+
}
|
|
24704
|
+
return warnings;
|
|
23761
24705
|
}
|
|
23762
24706
|
|
|
23763
24707
|
// src/roundtrip/patcher.ts
|
|
@@ -23767,10 +24711,10 @@ import JSZip10 from "jszip";
|
|
|
23767
24711
|
var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
|
|
23768
24712
|
var TAG_AT_RE = /<[A-Za-z0-9_:]+(?:"[^"]*"|'[^']*'|[^>"'])*>/y;
|
|
23769
24713
|
function patchTableRows(input) {
|
|
23770
|
-
const { table, scanTable, ctx, skip, origKeys, editedKeys } = input;
|
|
24714
|
+
const { table: table2, scanTable, ctx, skip, origKeys, editedKeys } = input;
|
|
23771
24715
|
const xml = ctx.scans[scanTable.sectionIndex]?.xml;
|
|
23772
24716
|
if (!xml) return skip("\uC139\uC158 XML \uB9E4\uD551 \uC2E4\uD328");
|
|
23773
|
-
const numRows =
|
|
24717
|
+
const numRows = table2.rows;
|
|
23774
24718
|
if (origKeys.length !== numRows) return skip("\uD45C \uD589 \uC88C\uD45C \uBD88\uC77C\uCE58 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
23775
24719
|
if (scanTable.rows.length !== numRows || scanTable.rowRanges.length !== numRows) {
|
|
23776
24720
|
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");
|
|
@@ -23841,8 +24785,8 @@ function patchTableRows(input) {
|
|
|
23841
24785
|
if (template < 0) template = kept[0];
|
|
23842
24786
|
const cells = input.editedCells(ins.ei);
|
|
23843
24787
|
if (!cells) return skip("\uC0BD\uC785 \uD589\uC5D0 \uC774\uBBF8\uC9C0/\uC911\uCCA9\uD45C \uD3EC\uD568 \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
|
|
23844
|
-
for (const
|
|
23845
|
-
const unstable =
|
|
24788
|
+
for (const cell2 of cells) {
|
|
24789
|
+
const unstable = cell2.lines.find((l) => sanitizeText(l) !== l);
|
|
23846
24790
|
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");
|
|
23847
24791
|
}
|
|
23848
24792
|
const tmplCells = scanTable.rows[template];
|
|
@@ -23852,7 +24796,7 @@ function patchTableRows(input) {
|
|
|
23852
24796
|
}
|
|
23853
24797
|
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");
|
|
23854
24798
|
const tmplWidth = tmplCells.reduce((s, c) => s + c.colSpan, 0);
|
|
23855
|
-
if (tmplWidth !==
|
|
24799
|
+
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");
|
|
23856
24800
|
if (cells.length !== tmplCells.length) {
|
|
23857
24801
|
return skip(`\uC0BD\uC785 \uD589 \uC140 \uC218(${cells.length}) \u2260 \uAE30\uC900 \uD589 \uC140 \uC218(${tmplCells.length}) \u2014 \uBBF8\uC9C0\uC6D0`);
|
|
23858
24802
|
}
|
|
@@ -23909,8 +24853,8 @@ function patchTableRows(input) {
|
|
|
23909
24853
|
for (const k of keeps) {
|
|
23910
24854
|
const fi = finalIndex.get(k);
|
|
23911
24855
|
if (fi === k.oi) continue;
|
|
23912
|
-
for (const
|
|
23913
|
-
const sp = rowAddrRewrite(xml,
|
|
24856
|
+
for (const cell2 of scanTable.rows[k.oi]) {
|
|
24857
|
+
const sp = rowAddrRewrite(xml, cell2, fi);
|
|
23914
24858
|
if (sp) splices.push(sp);
|
|
23915
24859
|
}
|
|
23916
24860
|
}
|
|
@@ -23959,13 +24903,13 @@ function buildRowFragment(xml, scanTable, template, cells, finalRow, hasExplicit
|
|
|
23959
24903
|
const patched = applySplices(wrapped, splices);
|
|
23960
24904
|
return patched.slice(FRAG_OPEN.length, patched.length - FRAG_CLOSE.length);
|
|
23961
24905
|
}
|
|
23962
|
-
function rowAddrRewrite(xml,
|
|
23963
|
-
if (!
|
|
23964
|
-
const tag = xml.slice(
|
|
24906
|
+
function rowAddrRewrite(xml, cell2, newRow) {
|
|
24907
|
+
if (!cell2.addrTagRange) return null;
|
|
24908
|
+
const tag = xml.slice(cell2.addrTagRange.start, cell2.addrTagRange.end);
|
|
23965
24909
|
const m = tag.match(/\browAddr\s*=\s*"(\d+)"/);
|
|
23966
24910
|
if (!m || m.index === void 0) return null;
|
|
23967
24911
|
if (parseInt(m[1], 10) === newRow) return null;
|
|
23968
|
-
const valStart =
|
|
24912
|
+
const valStart = cell2.addrTagRange.start + m.index + m[0].indexOf('"') + 1;
|
|
23969
24913
|
return { start: valStart, end: valStart + m[1].length, replacement: String(newRow) };
|
|
23970
24914
|
}
|
|
23971
24915
|
function rowHeightOf(fragment) {
|
|
@@ -23991,8 +24935,8 @@ function tableSzHeightSplice(xml, scanTable, tblOpenLen, delta) {
|
|
|
23991
24935
|
}
|
|
23992
24936
|
|
|
23993
24937
|
// src/roundtrip/table-patch.ts
|
|
23994
|
-
function patchGfmTable(
|
|
23995
|
-
const replica = replicateGfmTable(
|
|
24938
|
+
function patchGfmTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
24939
|
+
const replica = replicateGfmTable(table2);
|
|
23996
24940
|
if (!replica) return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
23997
24941
|
const origRows = parseGfmTable(orig.lines);
|
|
23998
24942
|
const editedRows = parseGfmTable(edited.lines);
|
|
@@ -24000,15 +24944,15 @@ function patchGfmTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
24000
24944
|
return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
24001
24945
|
}
|
|
24002
24946
|
if (editedRows.length !== origRows.length) {
|
|
24003
|
-
return patchGfmTableRows(
|
|
24947
|
+
return patchGfmTableRows(table2, scanTable, origRows, editedRows, replica, ctx, skip);
|
|
24004
24948
|
}
|
|
24005
24949
|
let applied = 0;
|
|
24006
24950
|
for (let r = 0; r < origRows.length; r++) {
|
|
24007
|
-
applied += patchGfmRowPair(
|
|
24951
|
+
applied += patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, r, r, ctx, skip);
|
|
24008
24952
|
}
|
|
24009
24953
|
return applied;
|
|
24010
24954
|
}
|
|
24011
|
-
function patchGfmRowPair(
|
|
24955
|
+
function patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, r, er, ctx, skip) {
|
|
24012
24956
|
if (editedRows[er].length !== origRows[r].length) {
|
|
24013
24957
|
skip(`\uD45C ${r + 1}\uD589 \uC5F4 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
|
|
24014
24958
|
return 0;
|
|
@@ -24025,7 +24969,7 @@ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er,
|
|
|
24025
24969
|
}
|
|
24026
24970
|
const newLines = unescapeGfmCell(stripCellTokens(editedRows[er][c])).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
24027
24971
|
const origLines = unescapeGfmCell(stripCellTokens(origRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
24028
|
-
const n = applyCellEdit(
|
|
24972
|
+
const n = applyCellEdit(table2, scanTable, gridR, gridC, newLines, ctx, origRows[r][c], editedRows[er][c], origLines.length);
|
|
24029
24973
|
if (n > 0 && origTokens) {
|
|
24030
24974
|
ctx.skipped.push({
|
|
24031
24975
|
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)",
|
|
@@ -24038,19 +24982,19 @@ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er,
|
|
|
24038
24982
|
}
|
|
24039
24983
|
return applied;
|
|
24040
24984
|
}
|
|
24041
|
-
function patchGfmTableRows(
|
|
24042
|
-
if (replica.length !==
|
|
24985
|
+
function patchGfmTableRows(table2, scanTable, origRows, editedRows, replica, ctx, skip) {
|
|
24986
|
+
if (replica.length !== table2.rows || replica.some((row, r) => row.some((c) => c.gridR !== r))) {
|
|
24043
24987
|
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");
|
|
24044
24988
|
}
|
|
24045
|
-
if (
|
|
24989
|
+
if (table2.cells.some((row) => row.some((c) => c && (c.colSpan > 1 || c.rowSpan > 1)))) {
|
|
24046
24990
|
return skip("\uBCD1\uD569 \uC140 \uD45C \u2014 GFM \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
24047
24991
|
}
|
|
24048
|
-
if (!gfmRenderStable(editedRows,
|
|
24992
|
+
if (!gfmRenderStable(editedRows, table2.cols)) {
|
|
24049
24993
|
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");
|
|
24050
24994
|
}
|
|
24051
24995
|
const key = (row) => row.join("\0");
|
|
24052
24996
|
return patchTableRows({
|
|
24053
|
-
table,
|
|
24997
|
+
table: table2,
|
|
24054
24998
|
scanTable,
|
|
24055
24999
|
ctx,
|
|
24056
25000
|
skip,
|
|
@@ -24065,7 +25009,7 @@ function patchGfmTableRows(table, scanTable, origRows, editedRows, replica, ctx,
|
|
|
24065
25009
|
}
|
|
24066
25010
|
return cells;
|
|
24067
25011
|
},
|
|
24068
|
-
patchMatched: (oi, ei) => patchGfmRowPair(
|
|
25012
|
+
patchMatched: (oi, ei) => patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, oi, ei, ctx, skip)
|
|
24069
25013
|
});
|
|
24070
25014
|
}
|
|
24071
25015
|
function gfmRenderStable(editedRows, cols) {
|
|
@@ -24082,13 +25026,13 @@ function gfmRenderStable(editedRows, cols) {
|
|
|
24082
25026
|
if (!replica || replica.length !== editedRows.length) return false;
|
|
24083
25027
|
return replica.every((row, r) => row.length === editedRows[r].length && row.every((c, j) => c.text === editedRows[r][j]));
|
|
24084
25028
|
}
|
|
24085
|
-
function patchHtmlTable(
|
|
24086
|
-
return patchHtmlTableRaw(
|
|
25029
|
+
function patchHtmlTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
25030
|
+
return patchHtmlTableRaw(table2, scanTable, orig.raw, edited.raw, ctx, skip, 0);
|
|
24087
25031
|
}
|
|
24088
|
-
function patchHtmlTableRaw(
|
|
25032
|
+
function patchHtmlTableRaw(table2, scanTable, origRaw, editedRaw, ctx, skip, depth) {
|
|
24089
25033
|
if (depth > 8) return skip("\uC911\uCCA9\uD45C \uAE4A\uC774 \uCD08\uACFC");
|
|
24090
|
-
if (replicateTableToHtml(
|
|
24091
|
-
const replica = replicateHtmlTable(
|
|
25034
|
+
if (replicateTableToHtml(table2) !== origRaw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
25035
|
+
const replica = replicateHtmlTable(table2);
|
|
24092
25036
|
const origRows = parseHtmlTable(origRaw);
|
|
24093
25037
|
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))) {
|
|
24094
25038
|
return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -24096,15 +25040,15 @@ function patchHtmlTableRaw(table, scanTable, origRaw, editedRaw, ctx, skip, dept
|
|
|
24096
25040
|
const editedRows = parseHtmlTable(editedRaw);
|
|
24097
25041
|
if (!editedRows) return skip("\uD3B8\uC9D1\uB41C HTML \uD45C \uD30C\uC2F1 \uC2E4\uD328");
|
|
24098
25042
|
if (editedRows.length !== replica.length) {
|
|
24099
|
-
return patchHtmlTableRows(
|
|
25043
|
+
return patchHtmlTableRows(table2, scanTable, replica, editedRows, ctx, skip, depth);
|
|
24100
25044
|
}
|
|
24101
25045
|
let applied = 0;
|
|
24102
25046
|
for (let r = 0; r < replica.length; r++) {
|
|
24103
|
-
applied += patchHtmlRowPair(
|
|
25047
|
+
applied += patchHtmlRowPair(table2, scanTable, replica, editedRows, r, r, ctx, skip, depth);
|
|
24104
25048
|
}
|
|
24105
25049
|
return applied;
|
|
24106
25050
|
}
|
|
24107
|
-
function patchHtmlRowPair(
|
|
25051
|
+
function patchHtmlRowPair(table2, scanTable, replica, editedRows, r, er, ctx, skip, depth) {
|
|
24108
25052
|
if (editedRows[er].cells.length !== replica[r].cells.length) {
|
|
24109
25053
|
skip(`\uD45C ${r + 1}\uD589 \uC140 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
|
|
24110
25054
|
return 0;
|
|
@@ -24132,23 +25076,23 @@ function patchHtmlRowPair(table, scanTable, replica, editedRows, r, er, ctx, ski
|
|
|
24132
25076
|
continue;
|
|
24133
25077
|
}
|
|
24134
25078
|
if (origTables.join("\n") !== editedTables.join("\n")) {
|
|
24135
|
-
applied += patchNestedTables(
|
|
25079
|
+
applied += patchNestedTables(table2, scanTable, oc, origTables, editedTables, ctx, skip, depth);
|
|
24136
25080
|
}
|
|
24137
25081
|
}
|
|
24138
25082
|
if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
|
|
24139
25083
|
const newLines = editedContent.lines.map((l) => unescapeGfm(l));
|
|
24140
|
-
applied += applyCellEdit(
|
|
25084
|
+
applied += applyCellEdit(table2, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
|
|
24141
25085
|
}
|
|
24142
25086
|
}
|
|
24143
25087
|
return applied;
|
|
24144
25088
|
}
|
|
24145
|
-
function patchHtmlTableRows(
|
|
24146
|
-
if (replica.length !==
|
|
25089
|
+
function patchHtmlTableRows(table2, scanTable, replica, editedRows, ctx, skip, depth) {
|
|
25090
|
+
if (replica.length !== table2.rows || replica.some((row, r) => row.cells.some((c) => c.gridR !== r))) {
|
|
24147
25091
|
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");
|
|
24148
25092
|
}
|
|
24149
25093
|
const key = (row) => row.cells.map((c) => `${c.colSpan}x${c.rowSpan}:${c.inner}`).join("\0");
|
|
24150
25094
|
return patchTableRows({
|
|
24151
|
-
table,
|
|
25095
|
+
table: table2,
|
|
24152
25096
|
scanTable,
|
|
24153
25097
|
ctx,
|
|
24154
25098
|
skip,
|
|
@@ -24156,18 +25100,18 @@ function patchHtmlTableRows(table, scanTable, replica, editedRows, ctx, skip, de
|
|
|
24156
25100
|
editedKeys: editedRows.map(key),
|
|
24157
25101
|
editedCells: (ei) => {
|
|
24158
25102
|
const cells = [];
|
|
24159
|
-
for (const
|
|
24160
|
-
const content = htmlCellInnerToLines(
|
|
25103
|
+
for (const cell2 of editedRows[ei].cells) {
|
|
25104
|
+
const content = htmlCellInnerToLines(cell2.inner);
|
|
24161
25105
|
if (content.hadNonText) return null;
|
|
24162
|
-
cells.push({ lines: content.lines.map((l) => unescapeGfm(l)), colSpan:
|
|
25106
|
+
cells.push({ lines: content.lines.map((l) => unescapeGfm(l)), colSpan: cell2.colSpan, rowSpan: cell2.rowSpan });
|
|
24163
25107
|
}
|
|
24164
25108
|
return cells;
|
|
24165
25109
|
},
|
|
24166
|
-
patchMatched: (oi, ei) => patchHtmlRowPair(
|
|
25110
|
+
patchMatched: (oi, ei) => patchHtmlRowPair(table2, scanTable, replica, editedRows, oi, ei, ctx, skip, depth)
|
|
24167
25111
|
});
|
|
24168
25112
|
}
|
|
24169
|
-
function patchNestedTables(
|
|
24170
|
-
const irCell =
|
|
25113
|
+
function patchNestedTables(table2, scanTable, oc, origTables, editedTables, ctx, skip, depth) {
|
|
25114
|
+
const irCell = table2.cells[oc.gridR]?.[oc.gridC];
|
|
24171
25115
|
const scanCell = scanTable.cellByAnchor.get(`${oc.gridR},${oc.gridC}`);
|
|
24172
25116
|
const nestedIRs = (irCell?.blocks ?? []).filter((b) => b.type === "table" && b.table).map((b) => b.table);
|
|
24173
25117
|
if (!scanCell || nestedIRs.length !== origTables.length || scanCell.tables.length !== origTables.length) {
|
|
@@ -24190,9 +25134,9 @@ function extractCellTokens(text) {
|
|
|
24190
25134
|
function stripCellTokens(text) {
|
|
24191
25135
|
return text.replace(CELL_TOKEN_RE, "");
|
|
24192
25136
|
}
|
|
24193
|
-
function patchTextChunkTable(
|
|
24194
|
-
if (
|
|
24195
|
-
const content = sanitizeText(
|
|
25137
|
+
function patchTextChunkTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
25138
|
+
if (table2.rows === 1 && table2.cols === 1) {
|
|
25139
|
+
const content = sanitizeText(table2.cells[0][0].text);
|
|
24196
25140
|
const replicaLines = content.split(/\n/).map((line) => {
|
|
24197
25141
|
const t = line.trim();
|
|
24198
25142
|
if (!t) return "";
|
|
@@ -24206,12 +25150,12 @@ function patchTextChunkTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
24206
25150
|
const unwrap = m && /^\d+\.\s/.test(unescapeGfm(m[1]));
|
|
24207
25151
|
return stripCellTokens(unescapeGfm(unwrap ? m[1] : l)).trim();
|
|
24208
25152
|
}).filter(Boolean);
|
|
24209
|
-
return applyCellEdit(
|
|
25153
|
+
return applyCellEdit(table2, scanTable, 0, 0, newLines, ctx, orig.raw, edited.raw, orig.lines.length);
|
|
24210
25154
|
}
|
|
24211
|
-
if (
|
|
25155
|
+
if (table2.cols === 1 && table2.rows >= 2) {
|
|
24212
25156
|
const replica = [];
|
|
24213
|
-
for (let r = 0; r <
|
|
24214
|
-
const line = escapeGfm(sanitizeText(
|
|
25157
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
25158
|
+
const line = escapeGfm(sanitizeText(table2.cells[r][0].text)).replace(/\n/g, " ");
|
|
24215
25159
|
if (line) replica.push({ line, gridR: r });
|
|
24216
25160
|
}
|
|
24217
25161
|
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");
|
|
@@ -24224,21 +25168,21 @@ function patchTextChunkTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
24224
25168
|
continue;
|
|
24225
25169
|
}
|
|
24226
25170
|
const newLines = [stripCellTokens(unescapeGfm(edited.lines[i])).trim()].filter(Boolean);
|
|
24227
|
-
applied += applyCellEdit(
|
|
25171
|
+
applied += applyCellEdit(table2, scanTable, replica[i].gridR, 0, newLines, ctx, replica[i].line, edited.lines[i], 1);
|
|
24228
25172
|
}
|
|
24229
25173
|
return applied;
|
|
24230
25174
|
}
|
|
24231
25175
|
return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
24232
25176
|
}
|
|
24233
|
-
function applyCellEdit(
|
|
25177
|
+
function applyCellEdit(table2, scanTable, gridR, gridC, newLines, ctx, before, after, origLineCount) {
|
|
24234
25178
|
const skip = (reason) => {
|
|
24235
25179
|
ctx.skipped.push({ reason, before: summarize(before), after: summarize(after) });
|
|
24236
25180
|
return 0;
|
|
24237
25181
|
};
|
|
24238
|
-
const
|
|
24239
|
-
if (!
|
|
24240
|
-
const irCell =
|
|
24241
|
-
const scanJoined =
|
|
25182
|
+
const cell2 = scanTable.cellByAnchor.get(`${gridR},${gridC}`);
|
|
25183
|
+
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)");
|
|
25184
|
+
const irCell = table2.cells[gridR]?.[gridC];
|
|
25185
|
+
const scanJoined = cell2.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
|
|
24242
25186
|
if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
24243
25187
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
24244
25188
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -24248,7 +25192,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
|
|
|
24248
25192
|
}
|
|
24249
25193
|
}
|
|
24250
25194
|
}
|
|
24251
|
-
const nonEmpty =
|
|
25195
|
+
const nonEmpty = cell2.paragraphs.filter((p) => normForMatch(p.text) !== "");
|
|
24252
25196
|
if (origLineCount !== void 0 && nonEmpty.length > 0 && origLineCount !== nonEmpty.length) {
|
|
24253
25197
|
return skip("\uC140 \uC904 \uACBD\uACC4 \uB9E4\uD551 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 <br>/\uBB38\uB2E8 \uB0B4 \uC904\uBC14\uAFC8) \u2014 \uBBF8\uC9C0\uC6D0");
|
|
24254
25198
|
}
|
|
@@ -24258,7 +25202,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
|
|
|
24258
25202
|
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");
|
|
24259
25203
|
if (nonEmpty.length === 0) {
|
|
24260
25204
|
if (newLines.length === 0) return 0;
|
|
24261
|
-
const target =
|
|
25205
|
+
const target = cell2.paragraphs[0];
|
|
24262
25206
|
if (!target) return skip("\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00");
|
|
24263
25207
|
const sp = buildParagraphSplices(target, newLines.join(" "), ctx.scans[target.sectionIndex]?.xml);
|
|
24264
25208
|
if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
|
|
@@ -24343,16 +25287,16 @@ function buildTableParagraphXml(rows, opts) {
|
|
|
24343
25287
|
const trElements = rows.map((row, rowIdx) => {
|
|
24344
25288
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
24345
25289
|
const isHeaderRow = rowIdx === 0;
|
|
24346
|
-
const tdElements = cells.map((
|
|
24347
|
-
const text = escapeXmlText(cellPlainText(
|
|
25290
|
+
const tdElements = cells.map((cell2, colIdx) => {
|
|
25291
|
+
const text = escapeXmlText(cellPlainText(cell2));
|
|
24348
25292
|
const cellP = `<hp:p paraPrIDRef="${cellParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}"><hp:t>${text}</hp:t></hp:run></hp:p>`;
|
|
24349
25293
|
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>`;
|
|
24350
25294
|
}).join("");
|
|
24351
25295
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
24352
25296
|
}).join("");
|
|
24353
25297
|
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;
|
|
24354
|
-
const
|
|
24355
|
-
return `<hp:p paraPrIDRef="${outerParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}">${
|
|
25298
|
+
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>`;
|
|
25299
|
+
return `<hp:p paraPrIDRef="${outerParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}">${tbl2}</hp:run></hp:p>`;
|
|
24356
25300
|
}
|
|
24357
25301
|
|
|
24358
25302
|
// src/roundtrip/hwpx-entries.ts
|
|
@@ -24524,12 +25468,12 @@ function buildTableOrdinals(blocks) {
|
|
|
24524
25468
|
function resolveParagraphMappings(blocks, scans) {
|
|
24525
25469
|
const buckets = /* @__PURE__ */ new Map();
|
|
24526
25470
|
for (const scan of scans) {
|
|
24527
|
-
for (const
|
|
24528
|
-
const key = normForMatch(
|
|
25471
|
+
for (const para2 of scan.bodyParagraphs) {
|
|
25472
|
+
const key = normForMatch(para2.text);
|
|
24529
25473
|
if (!key) continue;
|
|
24530
25474
|
let list = buckets.get(key);
|
|
24531
25475
|
if (!list) buckets.set(key, list = []);
|
|
24532
|
-
list.push(
|
|
25476
|
+
list.push(para2);
|
|
24533
25477
|
}
|
|
24534
25478
|
}
|
|
24535
25479
|
const headerNorms = new Set(scans.flatMap((s) => s.headerTexts.map(normForMatch)).filter(Boolean));
|
|
@@ -24615,11 +25559,11 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
24615
25559
|
if (!ti) return skip("\uBB38\uB2E8\u2192\uD45C \uBCC0\uD658 \uBD88\uAC00 \u2014 header \uC5D4\uD2B8\uB9AC(borderFills) \uD574\uC11D \uC2E4\uD328");
|
|
24616
25560
|
const mapping = ctx.paraMap.get(orig.blockIdx);
|
|
24617
25561
|
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");
|
|
24618
|
-
const
|
|
24619
|
-
if (
|
|
24620
|
-
const scan = ctx.scans[
|
|
25562
|
+
const para2 = mapping.para;
|
|
25563
|
+
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");
|
|
25564
|
+
const scan = ctx.scans[para2.sectionIndex];
|
|
24621
25565
|
if (!scan) return skip("\uC139\uC158 \uB9E4\uD551 \uC2E4\uD328");
|
|
24622
|
-
const pEnd = findElementEnd(scan.xml,
|
|
25566
|
+
const pEnd = findElementEnd(scan.xml, para2.start);
|
|
24623
25567
|
if (pEnd < 0) return skip("\uBB38\uB2E8 \uB05D \uC704\uCE58 \uD0D0\uC0C9 \uC2E4\uD328");
|
|
24624
25568
|
const rows = parseGfmTable(edited.lines);
|
|
24625
25569
|
if (rows.length === 0 || rows.every((r) => r.length === 0)) return skip("\uD45C \uB0B4\uC6A9\uC774 \uBE44\uC5B4 \uC788\uC74C");
|
|
@@ -24629,7 +25573,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
24629
25573
|
ti.borderFillId = inj.borderFillId;
|
|
24630
25574
|
ti.headerSplices.push(...inj.headerSplices);
|
|
24631
25575
|
}
|
|
24632
|
-
const outerParaPrId = extractParaPrIdRef(scan.xml,
|
|
25576
|
+
const outerParaPrId = extractParaPrIdRef(scan.xml, para2.start) ?? 0;
|
|
24633
25577
|
const tableXml = buildTableParagraphXml(rows, {
|
|
24634
25578
|
borderFillId: ti.borderFillId,
|
|
24635
25579
|
outerParaPrId,
|
|
@@ -24637,7 +25581,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
24637
25581
|
cellCharPrId: 0,
|
|
24638
25582
|
tableId: ti.nextId++
|
|
24639
25583
|
});
|
|
24640
|
-
ctx.sectionSplices[
|
|
25584
|
+
ctx.sectionSplices[para2.sectionIndex].push({ start: para2.start, end: pEnd, replacement: tableXml });
|
|
24641
25585
|
return 1;
|
|
24642
25586
|
}
|
|
24643
25587
|
function patchParagraphUnit(block, orig, edited, ctx, skip) {
|
|
@@ -25118,7 +26062,7 @@ function scanSection(stream, sectionIndex, compressed) {
|
|
|
25118
26062
|
}
|
|
25119
26063
|
}
|
|
25120
26064
|
const kind = !ctrlSeen || !nonGso ? "body" : "other";
|
|
25121
|
-
const
|
|
26065
|
+
const para2 = {
|
|
25122
26066
|
sectionIndex,
|
|
25123
26067
|
headerIdx: i,
|
|
25124
26068
|
kind,
|
|
@@ -25130,8 +26074,8 @@ function scanSection(stream, sectionIndex, compressed) {
|
|
|
25130
26074
|
nCharsRaw: rec.data.readUInt32LE(0),
|
|
25131
26075
|
rawText: state.text
|
|
25132
26076
|
};
|
|
25133
|
-
paras.push(
|
|
25134
|
-
parasByHeader.set(i,
|
|
26077
|
+
paras.push(para2);
|
|
26078
|
+
parasByHeader.set(i, para2);
|
|
25135
26079
|
}
|
|
25136
26080
|
const tables = [];
|
|
25137
26081
|
for (let i = 0; i < records.length; i++) {
|
|
@@ -25284,13 +26228,13 @@ function msg(err) {
|
|
|
25284
26228
|
function resolveParaMappings(blocks, scans) {
|
|
25285
26229
|
const buckets = /* @__PURE__ */ new Map();
|
|
25286
26230
|
for (const scan of scans) {
|
|
25287
|
-
for (const
|
|
25288
|
-
if (
|
|
25289
|
-
const key = normForMatch(
|
|
26231
|
+
for (const para2 of scan.paras) {
|
|
26232
|
+
if (para2.kind === "other") continue;
|
|
26233
|
+
const key = normForMatch(para2.rawText);
|
|
25290
26234
|
if (!key) continue;
|
|
25291
26235
|
let list = buckets.get(key);
|
|
25292
26236
|
if (!list) buckets.set(key, list = []);
|
|
25293
|
-
list.push(
|
|
26237
|
+
list.push(para2);
|
|
25294
26238
|
}
|
|
25295
26239
|
}
|
|
25296
26240
|
const usable = (list) => list.length === 1 || list.every((p) => p.kind === "body");
|
|
@@ -25326,18 +26270,18 @@ function resolveTableMappings(blocks, scanTables) {
|
|
|
25326
26270
|
const result = /* @__PURE__ */ new Map();
|
|
25327
26271
|
let si = 0;
|
|
25328
26272
|
for (let i = 0; i < blocks.length; i++) {
|
|
25329
|
-
const
|
|
25330
|
-
if (blocks[i].type !== "table" || !
|
|
26273
|
+
const table2 = blocks[i].table;
|
|
26274
|
+
if (blocks[i].type !== "table" || !table2) continue;
|
|
25331
26275
|
const cands = [];
|
|
25332
26276
|
for (let k = si; k < scanTables.length; k++) {
|
|
25333
|
-
if (scanTables[k].rows ===
|
|
26277
|
+
if (scanTables[k].rows === table2.rows && scanTables[k].cols === table2.cols) cands.push(k);
|
|
25334
26278
|
}
|
|
25335
26279
|
if (cands.length === 0) continue;
|
|
25336
26280
|
let pick2 = cands[0];
|
|
25337
26281
|
if (cands.length > 1) {
|
|
25338
|
-
let best = tableContentScore(
|
|
26282
|
+
let best = tableContentScore(table2, scanTables[cands[0]]);
|
|
25339
26283
|
for (let ci = 1; ci < cands.length; ci++) {
|
|
25340
|
-
const sc = tableContentScore(
|
|
26284
|
+
const sc = tableContentScore(table2, scanTables[cands[ci]]);
|
|
25341
26285
|
if (sc > best) {
|
|
25342
26286
|
best = sc;
|
|
25343
26287
|
pick2 = cands[ci];
|
|
@@ -25438,14 +26382,14 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25438
26382
|
ctx.skipped.push({ reason, before: summarize(origRows[r][c]), after: summarize(editedRows[r][c]) });
|
|
25439
26383
|
return 0;
|
|
25440
26384
|
};
|
|
25441
|
-
const
|
|
25442
|
-
if (!
|
|
26385
|
+
const cell2 = scanTable.cells.get(`${r},${c}`);
|
|
26386
|
+
if (!cell2) {
|
|
25443
26387
|
cellSkip("\uBCD1\uD569 \uC601\uC5ED \uC140 \u2014 \uC575\uCEE4 \uC140\uC774 \uC544\uB2C8\uBBC0\uB85C \uBBF8\uC9C0\uC6D0");
|
|
25444
26388
|
continue;
|
|
25445
26389
|
}
|
|
25446
26390
|
const beforeParts = origRows[r][c].split(/<br\s*\/?>/i);
|
|
25447
26391
|
const afterParts = editedRows[r][c].split(/<br\s*\/?>/i);
|
|
25448
|
-
if (
|
|
26392
|
+
if (cell2.paras.length === 1) {
|
|
25449
26393
|
const beforeEach = beforeParts.map(gfmCellToPlain);
|
|
25450
26394
|
const afterEach = afterParts.map(gfmCellToPlain);
|
|
25451
26395
|
if (beforeEach.some((p) => p === null) || afterEach.some((p) => p === null)) {
|
|
@@ -25455,8 +26399,8 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25455
26399
|
const before = beforeEach.join("\n");
|
|
25456
26400
|
const after = afterEach.join("\n");
|
|
25457
26401
|
if (before === after) continue;
|
|
25458
|
-
const
|
|
25459
|
-
if (normForMatch(
|
|
26402
|
+
const para2 = cell2.paras[0];
|
|
26403
|
+
if (normForMatch(para2.rawText) !== normForMatch(before)) {
|
|
25460
26404
|
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
25461
26405
|
continue;
|
|
25462
26406
|
}
|
|
@@ -25464,14 +26408,14 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25464
26408
|
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25465
26409
|
continue;
|
|
25466
26410
|
}
|
|
25467
|
-
applied += stageParaPatch(ctx.scans[
|
|
26411
|
+
applied += stageParaPatch(ctx.scans[para2.sectionIndex], para2, after, cellSkip);
|
|
25468
26412
|
continue;
|
|
25469
26413
|
}
|
|
25470
|
-
if (beforeParts.length !==
|
|
26414
|
+
if (beforeParts.length !== cell2.paras.length || afterParts.length !== cell2.paras.length) {
|
|
25471
26415
|
cellSkip("\uC140 \uBB38\uB2E8 \uC218 \uBCC0\uACBD \u2014 \uBBF8\uC9C0\uC6D0 (\uBB38\uB2E8 \uCD94\uAC00/\uC0AD\uC81C)");
|
|
25472
26416
|
continue;
|
|
25473
26417
|
}
|
|
25474
|
-
for (let k = 0; k <
|
|
26418
|
+
for (let k = 0; k < cell2.paras.length; k++) {
|
|
25475
26419
|
const before = gfmCellToPlain(beforeParts[k]);
|
|
25476
26420
|
const after = gfmCellToPlain(afterParts[k]);
|
|
25477
26421
|
if (before === null || after === null) {
|
|
@@ -25483,8 +26427,8 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25483
26427
|
cellSkip("\uC140 \uB0B4 \uC904\uBC14\uAFC8 \uCD94\uAC00\uB294 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
25484
26428
|
break;
|
|
25485
26429
|
}
|
|
25486
|
-
const
|
|
25487
|
-
if (normForMatch(
|
|
26430
|
+
const para2 = cell2.paras[k];
|
|
26431
|
+
if (normForMatch(para2.rawText) !== normForMatch(before)) {
|
|
25488
26432
|
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
25489
26433
|
break;
|
|
25490
26434
|
}
|
|
@@ -25492,15 +26436,15 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25492
26436
|
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25493
26437
|
break;
|
|
25494
26438
|
}
|
|
25495
|
-
applied += stageParaPatch(ctx.scans[
|
|
26439
|
+
applied += stageParaPatch(ctx.scans[para2.sectionIndex], para2, after, cellSkip);
|
|
25496
26440
|
}
|
|
25497
26441
|
}
|
|
25498
26442
|
}
|
|
25499
26443
|
return applied;
|
|
25500
26444
|
}
|
|
25501
|
-
function patchHtmlCells5(
|
|
25502
|
-
if (replicateTableToHtml(
|
|
25503
|
-
const replica = replicateHtmlTable(
|
|
26445
|
+
function patchHtmlCells5(table2, scanTable, orig, edited, ctx, skip) {
|
|
26446
|
+
if (replicateTableToHtml(table2) !== orig.raw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
26447
|
+
const replica = replicateHtmlTable(table2);
|
|
25504
26448
|
const origRows = parseHtmlTable(orig.raw);
|
|
25505
26449
|
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))) {
|
|
25506
26450
|
return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -25536,15 +26480,15 @@ function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
25536
26480
|
}
|
|
25537
26481
|
if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
|
|
25538
26482
|
const newLines = editedContent.lines.map((l) => unescapeGfm(l));
|
|
25539
|
-
applied += applyCellEdit5(
|
|
26483
|
+
applied += applyCellEdit5(table2, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
|
|
25540
26484
|
}
|
|
25541
26485
|
}
|
|
25542
26486
|
}
|
|
25543
26487
|
return applied;
|
|
25544
26488
|
}
|
|
25545
|
-
function patchTextChunk5(
|
|
25546
|
-
if (
|
|
25547
|
-
const content = sanitizeText(
|
|
26489
|
+
function patchTextChunk5(table2, scanTable, orig, edited, ctx, skip) {
|
|
26490
|
+
if (table2.rows === 1 && table2.cols === 1) {
|
|
26491
|
+
const content = sanitizeText(table2.cells[0][0].text);
|
|
25548
26492
|
const replicaLines = content.split(/\n/).map((line) => {
|
|
25549
26493
|
const t = line.trim();
|
|
25550
26494
|
if (!t) return "";
|
|
@@ -25558,12 +26502,12 @@ function patchTextChunk5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
25558
26502
|
const unwrap = m && /^\d+\.\s/.test(unescapeGfm(m[1]));
|
|
25559
26503
|
return stripCellTokens(unescapeGfm(unwrap ? m[1] : l)).trim();
|
|
25560
26504
|
}).filter(Boolean);
|
|
25561
|
-
return applyCellEdit5(
|
|
26505
|
+
return applyCellEdit5(table2, scanTable, 0, 0, newLines, ctx, orig.raw, edited.raw, orig.lines.length);
|
|
25562
26506
|
}
|
|
25563
|
-
if (
|
|
26507
|
+
if (table2.cols === 1 && table2.rows >= 2) {
|
|
25564
26508
|
const replica = [];
|
|
25565
|
-
for (let r = 0; r <
|
|
25566
|
-
const line = escapeGfm(sanitizeText(
|
|
26509
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
26510
|
+
const line = escapeGfm(sanitizeText(table2.cells[r][0].text)).replace(/\n/g, " ");
|
|
25567
26511
|
if (line) replica.push({ line, gridR: r });
|
|
25568
26512
|
}
|
|
25569
26513
|
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");
|
|
@@ -25576,21 +26520,21 @@ function patchTextChunk5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
25576
26520
|
continue;
|
|
25577
26521
|
}
|
|
25578
26522
|
const newLines = [stripCellTokens(unescapeGfm(edited.lines[i])).trim()].filter(Boolean);
|
|
25579
|
-
applied += applyCellEdit5(
|
|
26523
|
+
applied += applyCellEdit5(table2, scanTable, replica[i].gridR, 0, newLines, ctx, replica[i].line, edited.lines[i], 1);
|
|
25580
26524
|
}
|
|
25581
26525
|
return applied;
|
|
25582
26526
|
}
|
|
25583
26527
|
return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
25584
26528
|
}
|
|
25585
|
-
function applyCellEdit5(
|
|
26529
|
+
function applyCellEdit5(table2, scanTable, gridR, gridC, newLines, ctx, before, after, origLineCount) {
|
|
25586
26530
|
const skip = (reason) => {
|
|
25587
26531
|
ctx.skipped.push({ reason, before: summarize(before), after: summarize(after) });
|
|
25588
26532
|
return 0;
|
|
25589
26533
|
};
|
|
25590
|
-
const
|
|
25591
|
-
if (!
|
|
25592
|
-
const irCell =
|
|
25593
|
-
const scanJoined =
|
|
26534
|
+
const cell2 = scanTable.cells.get(`${gridR},${gridC}`);
|
|
26535
|
+
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)");
|
|
26536
|
+
const irCell = table2.cells[gridR]?.[gridC];
|
|
26537
|
+
const scanJoined = cell2.paras.map((p) => p.rawText).filter((t) => normForMatch(t)).join("\n");
|
|
25594
26538
|
if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
25595
26539
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
25596
26540
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -25600,13 +26544,13 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
|
|
|
25600
26544
|
}
|
|
25601
26545
|
}
|
|
25602
26546
|
}
|
|
25603
|
-
const nonEmpty =
|
|
26547
|
+
const nonEmpty = cell2.paras.filter((p) => normForMatch(p.rawText) !== "");
|
|
25604
26548
|
if (origLineCount !== void 0 && nonEmpty.length > 0 && origLineCount !== nonEmpty.length) {
|
|
25605
26549
|
return skip("\uC140 \uC904 \uACBD\uACC4 \uB9E4\uD551 \uBAA8\uD638 (\uBB38\uB2E8 \uB0B4 \uC904\uBC14\uAFC8) \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25606
26550
|
}
|
|
25607
26551
|
const unstable = newLines.find((l) => sanitizeText(l) !== l);
|
|
25608
26552
|
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");
|
|
25609
|
-
const targets = nonEmpty.length > 0 ? nonEmpty :
|
|
26553
|
+
const targets = nonEmpty.length > 0 ? nonEmpty : cell2.paras;
|
|
25610
26554
|
if (targets.length === 0) return skip("\uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC74C \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25611
26555
|
const assigned = [];
|
|
25612
26556
|
for (let i = 0; i < targets.length; i++) {
|
|
@@ -25756,67 +26700,67 @@ function synthesizeLineSegs(lineSegData, newRaw, startUnits) {
|
|
|
25756
26700
|
}
|
|
25757
26701
|
return { buf: Buffer.concat(segs), count: lines.length };
|
|
25758
26702
|
}
|
|
25759
|
-
function stageParaPatch(scan,
|
|
26703
|
+
function stageParaPatch(scan, para2, newPlain, skip) {
|
|
25760
26704
|
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");
|
|
25761
|
-
if (
|
|
25762
|
-
if (
|
|
25763
|
-
if (
|
|
25764
|
-
if (scan.repl.has(
|
|
26705
|
+
if (para2.textIdx === -2) return skip("\uBCF5\uC218 PARA_TEXT \uB808\uCF54\uB4DC \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
26706
|
+
if (para2.rangeTagCount > 0) return skip("\uBC94\uC704 \uD0DC\uADF8(\uD615\uAD11\uD39C/\uAD50\uC815\uBD80\uD638) \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
26707
|
+
if (para2.charShapeIdx < 0 || para2.lineSegIdx < 0) return skip("\uBB38\uB2E8 \uB808\uCF54\uB4DC \uAD6C\uC131 \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
26708
|
+
if (scan.repl.has(para2.headerIdx)) return skip("\uB3D9\uC77C \uBB38\uB2E8 \uC911\uBCF5 \uC218\uC815 \u2014 \uCCAB \uC218\uC815\uB9CC \uC801\uC6A9");
|
|
25765
26709
|
if (/[\u0000-\u0009\u000b-\u001f]/.test(newPlain)) return skip("\uC0C8 \uD14D\uC2A4\uD2B8\uC5D0 \uC81C\uC5B4\uBB38\uC790 \uD3EC\uD568 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25766
26710
|
const records = scan.records;
|
|
25767
|
-
const headerRec = records[
|
|
25768
|
-
const charShapeRec = records[
|
|
26711
|
+
const headerRec = records[para2.headerIdx];
|
|
26712
|
+
const charShapeRec = records[para2.charShapeIdx];
|
|
25769
26713
|
if (charShapeRec.data.length < 8) {
|
|
25770
26714
|
return skip("CHAR_SHAPE \uB808\uCF54\uB4DC \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25771
26715
|
}
|
|
25772
|
-
if (
|
|
25773
|
-
const nCharsLow =
|
|
26716
|
+
if (para2.textIdx === -1) {
|
|
26717
|
+
const nCharsLow = para2.nCharsRaw & 2147483647;
|
|
25774
26718
|
if (nCharsLow > 1) return skip("PARA_TEXT \uC5C6\uB294 \uBB38\uB2E8\uC758 nChars \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25775
26719
|
const paraEnd = nCharsLow === 1 ? Buffer.from([13, 0]) : Buffer.alloc(0);
|
|
25776
|
-
const at =
|
|
26720
|
+
const at = para2.headerIdx + 1;
|
|
25777
26721
|
const list = scan.inserts.get(at) ?? [];
|
|
25778
26722
|
list.push({ tagId: TAG_PARA_TEXT, level: headerRec.level + 1, data: Buffer.concat([Buffer.from(newPlain, "utf16le"), paraEnd]) });
|
|
25779
26723
|
scan.inserts.set(at, list);
|
|
25780
26724
|
const newHeader2 = Buffer.from(headerRec.data);
|
|
25781
|
-
newHeader2.writeUInt32LE((
|
|
26725
|
+
newHeader2.writeUInt32LE((para2.nCharsRaw & 2147483648 | newPlain.length + nCharsLow) >>> 0, 0);
|
|
25782
26726
|
const cs2 = rebuildCharShape(charShapeRec.data, 0);
|
|
25783
|
-
scan.repl.set(
|
|
26727
|
+
scan.repl.set(para2.charShapeIdx, cs2.buf);
|
|
25784
26728
|
newHeader2.writeUInt16LE(cs2.count, 12);
|
|
25785
26729
|
if (newPlain.includes("\n")) {
|
|
25786
|
-
const synth = synthesizeLineSegs(records[
|
|
26730
|
+
const synth = synthesizeLineSegs(records[para2.lineSegIdx].data, newPlain, 0);
|
|
25787
26731
|
if (synth) {
|
|
25788
|
-
scan.repl.set(
|
|
26732
|
+
scan.repl.set(para2.lineSegIdx, synth.buf);
|
|
25789
26733
|
newHeader2.writeUInt16LE(synth.count, 16);
|
|
25790
26734
|
}
|
|
25791
26735
|
}
|
|
25792
|
-
scan.repl.set(
|
|
26736
|
+
scan.repl.set(para2.headerIdx, newHeader2);
|
|
25793
26737
|
return 1;
|
|
25794
26738
|
}
|
|
25795
|
-
const textRec = records[
|
|
26739
|
+
const textRec = records[para2.textIdx];
|
|
25796
26740
|
const seg = splitParaText(textRec.data);
|
|
25797
26741
|
if (!seg) {
|
|
25798
|
-
return skip(
|
|
26742
|
+
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");
|
|
25799
26743
|
}
|
|
25800
|
-
if (seg.core !==
|
|
25801
|
-
const lead =
|
|
25802
|
-
const trail =
|
|
25803
|
-
const newRaw =
|
|
26744
|
+
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");
|
|
26745
|
+
const lead = para2.rawText.match(/^\s*/)[0];
|
|
26746
|
+
const trail = para2.rawText.match(/\s*$/)[0];
|
|
26747
|
+
const newRaw = para2.rawText.trim() === para2.rawText ? newPlain : lead + newPlain + trail;
|
|
25804
26748
|
const newText = Buffer.concat([seg.prefix, Buffer.from(newRaw, "utf16le"), seg.suffix]);
|
|
25805
|
-
scan.repl.set(
|
|
26749
|
+
scan.repl.set(para2.textIdx, newText);
|
|
25806
26750
|
const newHeader = Buffer.from(headerRec.data);
|
|
25807
26751
|
const nChars = seg.prefixUnits + newRaw.length + seg.suffixUnits;
|
|
25808
|
-
newHeader.writeUInt32LE((
|
|
26752
|
+
newHeader.writeUInt32LE((para2.nCharsRaw & 2147483648 | nChars) >>> 0, 0);
|
|
25809
26753
|
const cs = rebuildCharShape(charShapeRec.data, seg.prefixUnits);
|
|
25810
|
-
scan.repl.set(
|
|
26754
|
+
scan.repl.set(para2.charShapeIdx, cs.buf);
|
|
25811
26755
|
newHeader.writeUInt16LE(cs.count, 12);
|
|
25812
26756
|
if (newRaw.includes("\n")) {
|
|
25813
|
-
const synth = synthesizeLineSegs(records[
|
|
26757
|
+
const synth = synthesizeLineSegs(records[para2.lineSegIdx].data, newRaw, seg.prefixUnits);
|
|
25814
26758
|
if (synth) {
|
|
25815
|
-
scan.repl.set(
|
|
26759
|
+
scan.repl.set(para2.lineSegIdx, synth.buf);
|
|
25816
26760
|
newHeader.writeUInt16LE(synth.count, 16);
|
|
25817
26761
|
}
|
|
25818
26762
|
}
|
|
25819
|
-
scan.repl.set(
|
|
26763
|
+
scan.repl.set(para2.headerIdx, newHeader);
|
|
25820
26764
|
return 1;
|
|
25821
26765
|
}
|
|
25822
26766
|
|
|
@@ -25981,9 +26925,9 @@ var HwpxSession = class _HwpxSession {
|
|
|
25981
26925
|
const block = st.blocks[blockIndex];
|
|
25982
26926
|
if (!block) return void 0;
|
|
25983
26927
|
if (block.type === "paragraph" || block.type === "heading") {
|
|
25984
|
-
const
|
|
25985
|
-
if (!
|
|
25986
|
-
return { kind: "paragraph", sectionIndex:
|
|
26928
|
+
const para2 = st.paraMap.get(blockIndex)?.para;
|
|
26929
|
+
if (!para2) return void 0;
|
|
26930
|
+
return { kind: "paragraph", sectionIndex: para2.sectionIndex, xmlStart: para2.start };
|
|
25987
26931
|
}
|
|
25988
26932
|
if (block.type === "table" && block.table) {
|
|
25989
26933
|
if (st.tableOrdinals.size !== st.scanTables.length) return void 0;
|
|
@@ -26020,13 +26964,13 @@ var HwpxSession = class _HwpxSession {
|
|
|
26020
26964
|
if (!scanTable) {
|
|
26021
26965
|
return { capability: "locked", reason: "\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328" };
|
|
26022
26966
|
}
|
|
26023
|
-
const
|
|
26967
|
+
const table2 = block.table;
|
|
26024
26968
|
const cells = [];
|
|
26025
26969
|
let anyEditable = false;
|
|
26026
|
-
for (let r = 0; r <
|
|
26970
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
26027
26971
|
const row = [];
|
|
26028
|
-
for (let c = 0; c <
|
|
26029
|
-
const info = cellStaticCheck(
|
|
26972
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
26973
|
+
const info = cellStaticCheck(table2, scanTable, r, c);
|
|
26030
26974
|
if (info.editable) anyEditable = true;
|
|
26031
26975
|
row.push(info);
|
|
26032
26976
|
}
|
|
@@ -26215,12 +27159,12 @@ var HwpxSession = class _HwpxSession {
|
|
|
26215
27159
|
return 1;
|
|
26216
27160
|
}
|
|
26217
27161
|
};
|
|
26218
|
-
function cellStaticCheck(
|
|
26219
|
-
const irCell =
|
|
27162
|
+
function cellStaticCheck(table2, scanTable, r, c) {
|
|
27163
|
+
const irCell = table2.cells[r]?.[c];
|
|
26220
27164
|
if (!irCell) return { editable: false, reason: "\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16" };
|
|
26221
|
-
const
|
|
26222
|
-
if (!
|
|
26223
|
-
const scanJoined =
|
|
27165
|
+
const cell2 = scanTable.cellByAnchor.get(`${r},${c}`);
|
|
27166
|
+
if (!cell2) return { editable: false, reason: "\uBCD1\uD569 \uC601\uC5ED\uC758 \uBE48 \uCE78\uC774\uAC70\uB098 \uC88C\uD45C \uBD88\uC77C\uCE58" };
|
|
27167
|
+
const scanJoined = cell2.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
|
|
26224
27168
|
if (normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
26225
27169
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
26226
27170
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -26230,9 +27174,9 @@ function cellStaticCheck(table, scanTable, r, c) {
|
|
|
26230
27174
|
}
|
|
26231
27175
|
}
|
|
26232
27176
|
}
|
|
26233
|
-
const nonEmpty =
|
|
27177
|
+
const nonEmpty = cell2.paragraphs.filter((p) => normForMatch(p.text) !== "");
|
|
26234
27178
|
if (nonEmpty.length === 0) {
|
|
26235
|
-
if (
|
|
27179
|
+
if (cell2.paragraphs.length === 0) {
|
|
26236
27180
|
return { editable: false, reason: "\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00" };
|
|
26237
27181
|
}
|
|
26238
27182
|
return { editable: true };
|
|
@@ -26550,7 +27494,8 @@ function reflowPara(p, doc, styles, areaW, startV, mode) {
|
|
|
26550
27494
|
const firstWidth = avail;
|
|
26551
27495
|
const contWidth = Math.max(500, avail + Math.min(0, geom.marginIntent));
|
|
26552
27496
|
const contHorz = marginL - Math.min(0, geom.marginIntent);
|
|
26553
|
-
const
|
|
27497
|
+
const paraMode = geom.wrapMode ?? mode;
|
|
27498
|
+
const wrap = text.length === 0 ? { lines: 1, starts: [0], lastLineWidth: 0 } : simulateWrap(text, firstWidth, contWidth, height, ratio, paraMode, { spacingPct });
|
|
26554
27499
|
const pitch = pitchFor(height, geom);
|
|
26555
27500
|
const baseline = Math.round(height * BASELINE_RATIO);
|
|
26556
27501
|
const spacing = Math.max(0, pitch - height);
|
|
@@ -26588,15 +27533,15 @@ function reflowTablesIn(p, doc, styles, mode, counter) {
|
|
|
26588
27533
|
if (ln(obj) !== "tbl") continue;
|
|
26589
27534
|
for (const tr of elements(obj)) {
|
|
26590
27535
|
if (ln(tr) !== "tr") continue;
|
|
26591
|
-
for (const
|
|
26592
|
-
if (ln(
|
|
26593
|
-
const csz = findChildByLocalName(
|
|
26594
|
-
const cm = findChildByLocalName(
|
|
27536
|
+
for (const tc2 of elements(tr)) {
|
|
27537
|
+
if (ln(tc2) !== "tc") continue;
|
|
27538
|
+
const csz = findChildByLocalName(tc2, "cellSz");
|
|
27539
|
+
const cm = findChildByLocalName(tc2, "cellMargin");
|
|
26595
27540
|
const cellW = num2(csz, "width");
|
|
26596
27541
|
const mL = cm ? num2(cm, "left", 141) : 141;
|
|
26597
27542
|
const mR = cm ? num2(cm, "right", 141) : 141;
|
|
26598
27543
|
const areaW = Math.max(500, cellW - mL - mR);
|
|
26599
|
-
const sub = findChildByLocalName(
|
|
27544
|
+
const sub = findChildByLocalName(tc2, "subList");
|
|
26600
27545
|
if (sub) reflowBlockFlow(sub, doc, styles, areaW, mode, counter, 0);
|
|
26601
27546
|
}
|
|
26602
27547
|
}
|
|
@@ -27004,10 +27949,10 @@ function drawShape(o, x, y, ctx, depth) {
|
|
|
27004
27949
|
for (const p of elements2(sub)) if (ln2(p) === "p") drawPara(p, x, y, w, ctx, depth + 1);
|
|
27005
27950
|
}
|
|
27006
27951
|
}
|
|
27007
|
-
function cellContentExtent(
|
|
27008
|
-
if (!
|
|
27952
|
+
function cellContentExtent(cell2) {
|
|
27953
|
+
if (!cell2.sub) return 0;
|
|
27009
27954
|
let ext = 0;
|
|
27010
|
-
for (const p of elements2(
|
|
27955
|
+
for (const p of elements2(cell2.sub)) {
|
|
27011
27956
|
if (ln2(p) !== "p") continue;
|
|
27012
27957
|
const m = buildPara(p);
|
|
27013
27958
|
for (const s of m.segs) ext = Math.max(ext, s.vertpos + s.textheight);
|
|
@@ -27032,30 +27977,30 @@ function edgeLine(x1, y1, x2, y2, e) {
|
|
|
27032
27977
|
const dash = /DASH|DOT/.test(e.type) ? ` stroke-dasharray="${e.type.includes("DOT") ? "1,1.5" : "3,1.5"}"` : "";
|
|
27033
27978
|
return `<line x1="${pt(x1)}" y1="${pt(y1)}" x2="${pt(x2)}" y2="${pt(y2)}" stroke="${escapeXml3(e.color)}" stroke-width="${e.widthPt.toFixed(2)}"${dash}/>`;
|
|
27034
27979
|
}
|
|
27035
|
-
function collectCells(
|
|
27036
|
-
const inMargin = findChildByLocalName(
|
|
27980
|
+
function collectCells(tbl2) {
|
|
27981
|
+
const inMargin = findChildByLocalName(tbl2, "inMargin");
|
|
27037
27982
|
const defL = num3(inMargin, "left", 141), defR = num3(inMargin, "right", 141);
|
|
27038
27983
|
const defT = num3(inMargin, "top", 141), defB = num3(inMargin, "bottom", 141);
|
|
27039
27984
|
const cells = [];
|
|
27040
|
-
for (const tr of elements2(
|
|
27985
|
+
for (const tr of elements2(tbl2)) {
|
|
27041
27986
|
if (ln2(tr) !== "tr") continue;
|
|
27042
|
-
for (const
|
|
27043
|
-
if (ln2(
|
|
27044
|
-
const addr = findChildByLocalName(
|
|
27045
|
-
const span = findChildByLocalName(
|
|
27046
|
-
const csz = findChildByLocalName(
|
|
27047
|
-
const cm = findChildByLocalName(
|
|
27987
|
+
for (const tc2 of elements2(tr)) {
|
|
27988
|
+
if (ln2(tc2) !== "tc") continue;
|
|
27989
|
+
const addr = findChildByLocalName(tc2, "cellAddr");
|
|
27990
|
+
const span = findChildByLocalName(tc2, "cellSpan");
|
|
27991
|
+
const csz = findChildByLocalName(tc2, "cellSz");
|
|
27992
|
+
const cm = findChildByLocalName(tc2, "cellMargin");
|
|
27048
27993
|
if (!addr || !csz) continue;
|
|
27049
27994
|
cells.push({
|
|
27050
|
-
el:
|
|
27995
|
+
el: tc2,
|
|
27051
27996
|
ca: num3(addr, "colAddr"),
|
|
27052
27997
|
ra: num3(addr, "rowAddr"),
|
|
27053
27998
|
cs: Math.max(1, num3(span, "colSpan", 1)),
|
|
27054
27999
|
rs: Math.max(1, num3(span, "rowSpan", 1)),
|
|
27055
28000
|
w: num3(csz, "width"),
|
|
27056
28001
|
h: num3(csz, "height"),
|
|
27057
|
-
bfId:
|
|
27058
|
-
sub: findChildByLocalName(
|
|
28002
|
+
bfId: tc2.getAttribute("borderFillIDRef"),
|
|
28003
|
+
sub: findChildByLocalName(tc2, "subList"),
|
|
27059
28004
|
marginL: cm ? num3(cm, "left", defL) : defL,
|
|
27060
28005
|
marginR: cm ? num3(cm, "right", defR) : defR,
|
|
27061
28006
|
marginT: cm ? num3(cm, "top", defT) : defT,
|
|
@@ -27065,8 +28010,8 @@ function collectCells(tbl) {
|
|
|
27065
28010
|
}
|
|
27066
28011
|
return cells;
|
|
27067
28012
|
}
|
|
27068
|
-
function measureTableHeight(
|
|
27069
|
-
const cells = collectCells(
|
|
28013
|
+
function measureTableHeight(tbl2) {
|
|
28014
|
+
const cells = collectCells(tbl2);
|
|
27070
28015
|
if (cells.length === 0 || cells.length > 4096) return 0;
|
|
27071
28016
|
const nRows = Math.max(...cells.map((c) => c.ra + c.rs));
|
|
27072
28017
|
const rowH = solveRowHeights(
|
|
@@ -27077,14 +28022,14 @@ function measureTableHeight(tbl) {
|
|
|
27077
28022
|
for (const h of rowH) sum += h;
|
|
27078
28023
|
return sum;
|
|
27079
28024
|
}
|
|
27080
|
-
function drawTable(
|
|
28025
|
+
function drawTable(tbl2, tx, ty, ctx, depth) {
|
|
27081
28026
|
if (depth > 16) {
|
|
27082
28027
|
warnOnce(ctx, "depth", "\uC911\uCCA9 \uAE4A\uC774 16 \uCD08\uACFC \u2014 \uC774\uD558 \uC0DD\uB7B5");
|
|
27083
28028
|
return;
|
|
27084
28029
|
}
|
|
27085
28030
|
ctx.stats.tables++;
|
|
27086
|
-
const tblSz = findChildByLocalName(
|
|
27087
|
-
const cells = collectCells(
|
|
28031
|
+
const tblSz = findChildByLocalName(tbl2, "sz");
|
|
28032
|
+
const cells = collectCells(tbl2);
|
|
27088
28033
|
if (cells.length === 0 || cells.length > 4096) return;
|
|
27089
28034
|
const nCols = Math.max(...cells.map((c) => c.ca + c.cs));
|
|
27090
28035
|
const nRows = Math.max(...cells.map((c) => c.ra + c.rs));
|
|
@@ -27448,7 +28393,7 @@ async function parseHwp(buffer, options) {
|
|
|
27448
28393
|
async function parsePdf(buffer, options) {
|
|
27449
28394
|
let parsePdfDocument;
|
|
27450
28395
|
try {
|
|
27451
|
-
const mod = await import("./parser-
|
|
28396
|
+
const mod = await import("./parser-NXHY37WH.js");
|
|
27452
28397
|
parsePdfDocument = mod.parsePdfDocument;
|
|
27453
28398
|
} catch {
|
|
27454
28399
|
return {
|
|
@@ -27566,6 +28511,7 @@ export {
|
|
|
27566
28511
|
hwpxToProfile,
|
|
27567
28512
|
inferFieldType,
|
|
27568
28513
|
isHwpxFile,
|
|
28514
|
+
isKnownFont,
|
|
27569
28515
|
isLabelCell,
|
|
27570
28516
|
isOldHwpFile,
|
|
27571
28517
|
isPdfFile,
|
|
@@ -27593,6 +28539,7 @@ export {
|
|
|
27593
28539
|
scanSectionXml,
|
|
27594
28540
|
simulateWrap,
|
|
27595
28541
|
simulateWrapKeepWord,
|
|
28542
|
+
unknownFontWarnings,
|
|
27596
28543
|
validateHwpx
|
|
27597
28544
|
};
|
|
27598
28545
|
//# sourceMappingURL=index.js.map
|