kordoc 3.18.1 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +768 -752
- package/dist/{-V66QW3WA.js → -O3AWNVPH.js} +16 -8
- package/dist/{chunk-2IBFK5ZO.js → chunk-33OUI7HC.js} +2 -2
- package/dist/chunk-33OUI7HC.js.map +1 -0
- package/dist/{chunk-UHYPUIRH.js → chunk-3H3CVOZ3.js} +2 -2
- package/dist/chunk-3H3CVOZ3.js.map +1 -0
- package/dist/{chunk-MEPHGCPQ.js → chunk-5CJGKKMZ.js} +1 -1
- package/dist/chunk-5CJGKKMZ.js.map +1 -0
- package/dist/{chunk-QMJJI6TD.js → chunk-C5ABJ7PB.js} +6 -4
- package/dist/chunk-C5ABJ7PB.js.map +1 -0
- package/dist/chunk-DCZVOIEO.cjs.map +1 -1
- package/dist/{chunk-UNV7F3FK.js → chunk-EH2KYFFO.js} +2 -2
- package/dist/chunk-EH2KYFFO.js.map +1 -0
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-NZJAXMN7.js → chunk-JMLK6NTW.js} +3 -3
- package/dist/chunk-JMLK6NTW.js.map +1 -0
- package/dist/chunk-MOL7MDBG.js +0 -0
- package/dist/{chunk-R2H34FY5.cjs → chunk-NIZXIVEI.cjs} +2 -2
- package/dist/chunk-NIZXIVEI.cjs.map +1 -0
- package/dist/{chunk-7K5P4RNT.js → chunk-SHVV3BD6.js} +1652 -588
- package/dist/chunk-SHVV3BD6.js.map +1 -0
- package/dist/{chunk-4RGDFDQ2.js → chunk-YEC7VG6O.js} +8 -2
- package/dist/chunk-YEC7VG6O.js.map +1 -0
- package/dist/cli.js +76 -16
- package/dist/cli.js.map +1 -1
- package/dist/{detect-RI2MQ33K.js → detect-PJZMUL2Z.js} +2 -2
- package/dist/formula-5NKVS2LR.cjs.map +1 -1
- package/dist/formula-JCNF43NE.js +0 -0
- package/dist/index.cjs +2036 -966
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -9
- package/dist/index.d.ts +110 -9
- package/dist/index.js +1811 -741
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +60 -17
- package/dist/mcp.js.map +1 -1
- package/dist/page-range-737B4EZW.js +0 -0
- package/dist/page-range-P7SDW6LR.cjs.map +1 -1
- package/dist/{parser-XEY5MRGV.cjs → parser-44OPXZMP.cjs} +15 -15
- package/dist/parser-44OPXZMP.cjs.map +1 -0
- package/dist/{parser-JBBA5A5E.js → parser-G433UZMX.js} +3 -3
- package/dist/parser-G433UZMX.js.map +1 -0
- package/dist/{parser-DOBK652H.js → parser-ZOMDHCA7.js} +4 -4
- package/dist/parser-ZOMDHCA7.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-SQVQBORJ.js +10 -0
- package/dist/seal-6E26L45Z.js +10 -0
- package/dist/setup-57FB3LSP.js +0 -0
- package/dist/{watch-2MNRQWGV.js → watch-UYT3ZCBM.js} +8 -8
- package/dist/watch-UYT3ZCBM.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2IBFK5ZO.js.map +0 -1
- package/dist/chunk-4RGDFDQ2.js.map +0 -1
- package/dist/chunk-7K5P4RNT.js.map +0 -1
- package/dist/chunk-MEPHGCPQ.js.map +0 -1
- package/dist/chunk-NZJAXMN7.js.map +0 -1
- package/dist/chunk-QMJJI6TD.js.map +0 -1
- package/dist/chunk-R2H34FY5.cjs.map +0 -1
- package/dist/chunk-UHYPUIRH.js.map +0 -1
- package/dist/chunk-UNV7F3FK.js.map +0 -1
- package/dist/parser-DOBK652H.js.map +0 -1
- package/dist/parser-JBBA5A5E.js.map +0 -1
- package/dist/parser-XEY5MRGV.cjs.map +0 -1
- package/dist/provider-4ZJKV3DC.js.map +0 -1
- package/dist/provider-AKROB7WQ.js.map +0 -1
- package/dist/provider-G4C2V2PD.cjs.map +0 -1
- package/dist/render-VX4H2S4F.js +0 -10
- package/dist/seal-6Z6H4YXN.js +0 -10
- package/dist/watch-2MNRQWGV.js.map +0 -1
- /package/dist/{-V66QW3WA.js.map → -O3AWNVPH.js.map} +0 -0
- /package/dist/{detect-RI2MQ33K.js.map → detect-PJZMUL2Z.js.map} +0 -0
- /package/dist/{render-VX4H2S4F.js.map → render-SQVQBORJ.js.map} +0 -0
- /package/dist/{seal-6Z6H4YXN.js.map → seal-6E26L45Z.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-3H3CVOZ3.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;
|
|
@@ -4297,8 +4304,8 @@ function parseParagraph(records, start, end, ctx) {
|
|
|
4297
4304
|
function applyCtrlEffect(ctrl, records, ctx) {
|
|
4298
4305
|
switch (ctrl.id) {
|
|
4299
4306
|
case CTRL_TBL: {
|
|
4300
|
-
const
|
|
4301
|
-
if (
|
|
4307
|
+
const table2 = parseTableControl(ctrl, records, ctx);
|
|
4308
|
+
if (table2) ctrl.afterBlocks = [{ type: "table", table: table2, pageNumber: ctx.sectionNum }];
|
|
4302
4309
|
return;
|
|
4303
4310
|
}
|
|
4304
4311
|
case CTRL_GSO: {
|
|
@@ -4517,14 +4524,14 @@ function parseTableControl(ctrl, records, ctx) {
|
|
|
4517
4524
|
if (c.isHeader) ir.isHeader = true;
|
|
4518
4525
|
return ir;
|
|
4519
4526
|
}));
|
|
4520
|
-
const
|
|
4521
|
-
if (caption)
|
|
4522
|
-
return
|
|
4527
|
+
const table3 = { rows, cols, cells: irCells, hasHeader: rows > 1 };
|
|
4528
|
+
if (caption) table3.caption = caption;
|
|
4529
|
+
return table3;
|
|
4523
4530
|
}
|
|
4524
4531
|
const cellRows = arrangeCells(rows, cols, cells);
|
|
4525
|
-
const
|
|
4526
|
-
if (caption &&
|
|
4527
|
-
return
|
|
4532
|
+
const table2 = buildTable(cellRows);
|
|
4533
|
+
if (caption && table2.rows > 0) table2.caption = caption;
|
|
4534
|
+
return table2.rows > 0 ? table2 : null;
|
|
4528
4535
|
}
|
|
4529
4536
|
function parseCell(records, lhIdx, end, ctx) {
|
|
4530
4537
|
const rec = records[lhIdx];
|
|
@@ -4562,22 +4569,22 @@ function parseCell(records, lhIdx, end, ctx) {
|
|
|
4562
4569
|
parts.push(t);
|
|
4563
4570
|
}
|
|
4564
4571
|
}
|
|
4565
|
-
const
|
|
4566
|
-
if (hasStructure && blocks.length > 0)
|
|
4567
|
-
if (isHeader)
|
|
4568
|
-
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;
|
|
4569
4576
|
}
|
|
4570
4577
|
function arrangeCells(rows, cols, cells) {
|
|
4571
4578
|
const grid = Array.from({ length: rows }, () => Array(cols).fill(null));
|
|
4572
4579
|
const hasAddr = cells.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0);
|
|
4573
4580
|
if (hasAddr) {
|
|
4574
|
-
for (const
|
|
4575
|
-
const r =
|
|
4576
|
-
const c =
|
|
4581
|
+
for (const cell2 of cells) {
|
|
4582
|
+
const r = cell2.rowAddr ?? 0;
|
|
4583
|
+
const c = cell2.colAddr ?? 0;
|
|
4577
4584
|
if (r >= rows || c >= cols) continue;
|
|
4578
|
-
grid[r][c] =
|
|
4579
|
-
for (let dr = 0; dr <
|
|
4580
|
-
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++) {
|
|
4581
4588
|
if (dr === 0 && dc === 0) continue;
|
|
4582
4589
|
if (r + dr < rows && c + dc < cols)
|
|
4583
4590
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -4589,10 +4596,10 @@ function arrangeCells(rows, cols, cells) {
|
|
|
4589
4596
|
for (let r = 0; r < rows && cellIdx < cells.length; r++) {
|
|
4590
4597
|
for (let c = 0; c < cols && cellIdx < cells.length; c++) {
|
|
4591
4598
|
if (grid[r][c] !== null) continue;
|
|
4592
|
-
const
|
|
4593
|
-
grid[r][c] =
|
|
4594
|
-
for (let dr = 0; dr <
|
|
4595
|
-
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++) {
|
|
4596
4603
|
if (dr === 0 && dc === 0) continue;
|
|
4597
4604
|
if (r + dr < rows && c + dc < cols)
|
|
4598
4605
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -17108,7 +17115,7 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
17108
17115
|
let lastRow = -1;
|
|
17109
17116
|
for (let r = 0; r <= maxRow; r++) {
|
|
17110
17117
|
const row = grid[r];
|
|
17111
|
-
if (row && row.some((
|
|
17118
|
+
if (row && row.some((cell2) => cell2 !== "")) {
|
|
17112
17119
|
if (firstRow === -1) firstRow = r;
|
|
17113
17120
|
lastRow = r;
|
|
17114
17121
|
}
|
|
@@ -17131,9 +17138,9 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
|
|
|
17131
17138
|
cellRows.push(row);
|
|
17132
17139
|
}
|
|
17133
17140
|
if (cellRows.length > 0) {
|
|
17134
|
-
const
|
|
17135
|
-
if (
|
|
17136
|
-
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 });
|
|
17137
17144
|
}
|
|
17138
17145
|
}
|
|
17139
17146
|
return blocks;
|
|
@@ -17751,9 +17758,9 @@ function sheetToBlocks2(sheetName, sheet, sheetIndex) {
|
|
|
17751
17758
|
cellRows.push(row);
|
|
17752
17759
|
}
|
|
17753
17760
|
if (cellRows.length > 0) {
|
|
17754
|
-
const
|
|
17755
|
-
if (
|
|
17756
|
-
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 });
|
|
17757
17764
|
}
|
|
17758
17765
|
}
|
|
17759
17766
|
return blocks;
|
|
@@ -18499,8 +18506,8 @@ function collectTextboxParagraphs(node, inTxbx = false, out = [], depth = 0) {
|
|
|
18499
18506
|
}
|
|
18500
18507
|
return out;
|
|
18501
18508
|
}
|
|
18502
|
-
function parseTable(
|
|
18503
|
-
const trElements = getChildElements(
|
|
18509
|
+
function parseTable(tbl2, styles, numbering, footnotes, rels) {
|
|
18510
|
+
const trElements = getChildElements(tbl2, "tr");
|
|
18504
18511
|
if (trElements.length === 0) return null;
|
|
18505
18512
|
const rawRows = [];
|
|
18506
18513
|
for (const tr of trElements) {
|
|
@@ -18513,10 +18520,10 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18513
18520
|
col = Math.max(0, parseInt(getAttr(gridBeforeEls[0], "val") ?? "0", 10) || 0);
|
|
18514
18521
|
}
|
|
18515
18522
|
}
|
|
18516
|
-
for (const
|
|
18523
|
+
for (const tc2 of getChildElements(tr, "tc")) {
|
|
18517
18524
|
let colSpan = 1;
|
|
18518
18525
|
let vMerge = null;
|
|
18519
|
-
const tcPrEls = getChildElements(
|
|
18526
|
+
const tcPrEls = getChildElements(tc2, "tcPr");
|
|
18520
18527
|
if (tcPrEls.length > 0) {
|
|
18521
18528
|
const gridSpanEls = getChildElements(tcPrEls[0], "gridSpan");
|
|
18522
18529
|
if (gridSpanEls.length > 0) {
|
|
@@ -18527,48 +18534,48 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
|
|
|
18527
18534
|
vMerge = getAttr(vMergeEls[0], "val") === "restart" ? "restart" : "continue";
|
|
18528
18535
|
}
|
|
18529
18536
|
}
|
|
18530
|
-
const text = collectCellText(
|
|
18537
|
+
const text = collectCellText(tc2, styles, numbering, footnotes, rels, 0).join("\n");
|
|
18531
18538
|
row.push({ col, colSpan, vMerge, text });
|
|
18532
18539
|
col += colSpan;
|
|
18533
18540
|
}
|
|
18534
18541
|
rawRows.push(row);
|
|
18535
18542
|
}
|
|
18536
18543
|
for (let r = 0; r < rawRows.length; r++) {
|
|
18537
|
-
for (const
|
|
18538
|
-
if (
|
|
18544
|
+
for (const cell2 of rawRows[r]) {
|
|
18545
|
+
if (cell2.vMerge !== "continue" || !cell2.text) continue;
|
|
18539
18546
|
let start;
|
|
18540
18547
|
for (let pr = r - 1; pr >= 0 && !start; pr--) {
|
|
18541
|
-
start = rawRows[pr].find((pc) => pc.col ===
|
|
18548
|
+
start = rawRows[pr].find((pc) => pc.col === cell2.col && pc.vMerge !== "continue");
|
|
18542
18549
|
}
|
|
18543
18550
|
if (start) {
|
|
18544
18551
|
start.text = start.text ? `${start.text}
|
|
18545
|
-
${
|
|
18546
|
-
|
|
18552
|
+
${cell2.text}` : cell2.text;
|
|
18553
|
+
cell2.text = "";
|
|
18547
18554
|
} else {
|
|
18548
|
-
|
|
18555
|
+
cell2.vMerge = null;
|
|
18549
18556
|
}
|
|
18550
18557
|
}
|
|
18551
18558
|
}
|
|
18552
18559
|
const cellRows = rawRows.map(
|
|
18553
|
-
(row, r) => row.filter((
|
|
18560
|
+
(row, r) => row.filter((cell2) => cell2.vMerge !== "continue").map((cell2) => {
|
|
18554
18561
|
let rowSpan = 1;
|
|
18555
|
-
if (
|
|
18562
|
+
if (cell2.vMerge === "restart") {
|
|
18556
18563
|
for (let nr = r + 1; nr < rawRows.length; nr++) {
|
|
18557
|
-
if (!rawRows[nr].some((nc) => nc.col ===
|
|
18564
|
+
if (!rawRows[nr].some((nc) => nc.col === cell2.col && nc.vMerge === "continue")) break;
|
|
18558
18565
|
rowSpan++;
|
|
18559
18566
|
}
|
|
18560
18567
|
}
|
|
18561
|
-
return { text:
|
|
18568
|
+
return { text: cell2.text, colSpan: cell2.colSpan, rowSpan, colAddr: cell2.col, rowAddr: r };
|
|
18562
18569
|
})
|
|
18563
18570
|
);
|
|
18564
|
-
const
|
|
18565
|
-
if (
|
|
18566
|
-
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 };
|
|
18567
18574
|
}
|
|
18568
|
-
function collectCellText(
|
|
18575
|
+
function collectCellText(tc2, styles, numbering, footnotes, rels, depth) {
|
|
18569
18576
|
const parts = [];
|
|
18570
18577
|
if (depth > 20) return parts;
|
|
18571
|
-
for (const el of effectiveChildElements(
|
|
18578
|
+
for (const el of effectiveChildElements(tc2)) {
|
|
18572
18579
|
if (matchesLocal(el, "p")) {
|
|
18573
18580
|
const block = parseParagraph2(el, styles, numbering, footnotes, rels);
|
|
18574
18581
|
if (block?.text) parts.push(block.text);
|
|
@@ -18929,13 +18936,13 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18929
18936
|
}
|
|
18930
18937
|
if (cells.length === 0) return;
|
|
18931
18938
|
const grid = Array.from({ length: rowCount }, () => Array(colCount).fill(null));
|
|
18932
|
-
for (const
|
|
18933
|
-
const r =
|
|
18934
|
-
const c =
|
|
18939
|
+
for (const cell2 of cells) {
|
|
18940
|
+
const r = cell2.rowAddr ?? 0;
|
|
18941
|
+
const c = cell2.colAddr ?? 0;
|
|
18935
18942
|
if (isNaN(r) || isNaN(c) || r >= rowCount || c >= colCount) continue;
|
|
18936
|
-
grid[r][c] =
|
|
18937
|
-
for (let dr = 0; dr <
|
|
18938
|
-
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++) {
|
|
18939
18946
|
if (dr === 0 && dc === 0) continue;
|
|
18940
18947
|
if (r + dr < rowCount && c + dc < colCount) {
|
|
18941
18948
|
grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
|
|
@@ -18944,14 +18951,14 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
|
|
|
18944
18951
|
}
|
|
18945
18952
|
}
|
|
18946
18953
|
const cellRows = grid.map(
|
|
18947
|
-
(row) => row.map((
|
|
18954
|
+
(row) => row.map((cell2) => cell2 ?? { text: "", colSpan: 1, rowSpan: 1 })
|
|
18948
18955
|
);
|
|
18949
|
-
const
|
|
18956
|
+
const table2 = buildTable(cellRows);
|
|
18950
18957
|
const caption = extractShapeCaption(el);
|
|
18951
18958
|
if (caption.text && caption.before) {
|
|
18952
18959
|
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18953
18960
|
}
|
|
18954
|
-
blocks.push({ type: "table", table, pageNumber: sectionNum });
|
|
18961
|
+
blocks.push({ type: "table", table: table2, pageNumber: sectionNum });
|
|
18955
18962
|
if (caption.text && !caption.before) {
|
|
18956
18963
|
blocks.push({ type: "paragraph", text: caption.text, pageNumber: sectionNum });
|
|
18957
18964
|
}
|
|
@@ -19451,13 +19458,13 @@ function extractFormFields(blocks) {
|
|
|
19451
19458
|
const confidence = totalTables > 0 ? formTables / totalTables : fields.length > 0 ? 0.3 : 0;
|
|
19452
19459
|
return { fields, confidence: Math.min(confidence, 1) };
|
|
19453
19460
|
}
|
|
19454
|
-
function extractFromTable(
|
|
19461
|
+
function extractFromTable(table2) {
|
|
19455
19462
|
const fields = [];
|
|
19456
|
-
if (
|
|
19457
|
-
for (let r = 0; r <
|
|
19458
|
-
for (let c = 0; c <
|
|
19459
|
-
const labelCell =
|
|
19460
|
-
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];
|
|
19461
19468
|
if (!labelCell || !valueCell) continue;
|
|
19462
19469
|
if (isLabelCell(labelCell.text)) {
|
|
19463
19470
|
fields.push({
|
|
@@ -19470,17 +19477,17 @@ function extractFromTable(table) {
|
|
|
19470
19477
|
}
|
|
19471
19478
|
}
|
|
19472
19479
|
}
|
|
19473
|
-
if (fields.length === 0 &&
|
|
19474
|
-
const headerRow =
|
|
19475
|
-
const allLabels = headerRow.every((
|
|
19476
|
-
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();
|
|
19477
19484
|
return t.length > 0 && t.length <= 20;
|
|
19478
19485
|
});
|
|
19479
19486
|
if (allLabels) {
|
|
19480
|
-
for (let r = 1; r <
|
|
19481
|
-
for (let c = 0; c <
|
|
19487
|
+
for (let r = 1; r < table2.rows; r++) {
|
|
19488
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19482
19489
|
const label = headerRow[c]?.text.trim() ?? "";
|
|
19483
|
-
const value =
|
|
19490
|
+
const value = table2.cells[r]?.[c]?.text.trim() ?? "";
|
|
19484
19491
|
if (label && value) {
|
|
19485
19492
|
fields.push({ label, value, row: r, col: c });
|
|
19486
19493
|
}
|
|
@@ -19517,9 +19524,9 @@ function inferFieldType(label, value) {
|
|
|
19517
19524
|
if (/^[\d,.\s]+(?:원|명|건|개|회|부|매|%)$/.test(v) && /\d/.test(v)) return "amount";
|
|
19518
19525
|
if (/^\d{1,3}(?:,\d{3})+$/.test(v)) return "amount";
|
|
19519
19526
|
}
|
|
19520
|
-
const
|
|
19527
|
+
const norm2 = label.replace(/\s/g, "");
|
|
19521
19528
|
for (const [re, type] of LABEL_TYPE_RULES) {
|
|
19522
|
-
if (re.test(
|
|
19529
|
+
if (re.test(norm2)) return type;
|
|
19523
19530
|
}
|
|
19524
19531
|
return "text";
|
|
19525
19532
|
}
|
|
@@ -19570,15 +19577,15 @@ function fillFormFields(blocks, values, blockedLabels) {
|
|
|
19570
19577
|
const cursor = new ValueCursor(normalizedValues);
|
|
19571
19578
|
const allTables = collectIRTables(cloned, 0);
|
|
19572
19579
|
const patternFilledCells = /* @__PURE__ */ new Set();
|
|
19573
|
-
for (const
|
|
19574
|
-
for (let r = 0; r <
|
|
19575
|
-
for (let c = 0; c <
|
|
19576
|
-
const
|
|
19577
|
-
if (!
|
|
19578
|
-
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);
|
|
19579
19586
|
if (result) {
|
|
19580
|
-
|
|
19581
|
-
patternFilledCells.add(
|
|
19587
|
+
cell2.text = result.text;
|
|
19588
|
+
patternFilledCells.add(cell2);
|
|
19582
19589
|
for (const m of result.matches) {
|
|
19583
19590
|
filled.push({ label: m.label, value: m.value, row: r, col: c, key: m.key });
|
|
19584
19591
|
}
|
|
@@ -19586,8 +19593,8 @@ function fillFormFields(blocks, values, blockedLabels) {
|
|
|
19586
19593
|
}
|
|
19587
19594
|
}
|
|
19588
19595
|
}
|
|
19589
|
-
for (const
|
|
19590
|
-
fillTable(
|
|
19596
|
+
for (const table2 of allTables) {
|
|
19597
|
+
fillTable(table2, cursor, filled, matchedLabels, patternFilledCells, blockedLabels);
|
|
19591
19598
|
}
|
|
19592
19599
|
for (const block of cloned) {
|
|
19593
19600
|
if (block.type !== "paragraph" || !block.text) continue;
|
|
@@ -19604,44 +19611,44 @@ function collectIRTables(blocks, depth) {
|
|
|
19604
19611
|
if (block.type !== "table" || !block.table) continue;
|
|
19605
19612
|
out.push(block.table);
|
|
19606
19613
|
for (const row of block.table.cells) {
|
|
19607
|
-
for (const
|
|
19608
|
-
if (
|
|
19614
|
+
for (const cell2 of row) {
|
|
19615
|
+
if (cell2?.blocks?.length) out.push(...collectIRTables(cell2.blocks, depth + 1));
|
|
19609
19616
|
}
|
|
19610
19617
|
}
|
|
19611
19618
|
}
|
|
19612
19619
|
return out;
|
|
19613
19620
|
}
|
|
19614
|
-
function coveredPositions(
|
|
19621
|
+
function coveredPositions(table2) {
|
|
19615
19622
|
const covered = /* @__PURE__ */ new Set();
|
|
19616
|
-
for (let r = 0; r <
|
|
19617
|
-
for (let c = 0; c <
|
|
19623
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
19624
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19618
19625
|
if (covered.has(`${r},${c}`)) continue;
|
|
19619
|
-
const
|
|
19620
|
-
if (!
|
|
19621
|
-
for (let dr = 0; dr <
|
|
19622
|
-
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++) {
|
|
19623
19630
|
if (dr === 0 && dc === 0) continue;
|
|
19624
|
-
if (r + dr <
|
|
19631
|
+
if (r + dr < table2.rows && c + dc < table2.cols) covered.add(`${r + dr},${c + dc}`);
|
|
19625
19632
|
}
|
|
19626
19633
|
}
|
|
19627
|
-
c +=
|
|
19634
|
+
c += cell2.colSpan - 1;
|
|
19628
19635
|
}
|
|
19629
19636
|
}
|
|
19630
19637
|
return covered;
|
|
19631
19638
|
}
|
|
19632
|
-
function fillTable(
|
|
19633
|
-
if (
|
|
19634
|
-
const covered = coveredPositions(
|
|
19635
|
-
for (let r = 0; r <
|
|
19636
|
-
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++) {
|
|
19637
19644
|
if (covered.has(`${r},${c}`)) continue;
|
|
19638
|
-
const labelCell =
|
|
19645
|
+
const labelCell = table2.cells[r][c];
|
|
19639
19646
|
if (!labelCell) continue;
|
|
19640
19647
|
if (!isLabelCell(labelCell.text)) continue;
|
|
19641
19648
|
let vc = c + labelCell.colSpan;
|
|
19642
|
-
while (vc <
|
|
19643
|
-
if (vc >=
|
|
19644
|
-
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];
|
|
19645
19652
|
if (!valueCell) continue;
|
|
19646
19653
|
if (isKeywordLabel(valueCell.text)) continue;
|
|
19647
19654
|
const normalizedCellLabel = normalizeLabel(labelCell.text);
|
|
@@ -19666,18 +19673,18 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells, blo
|
|
|
19666
19673
|
});
|
|
19667
19674
|
}
|
|
19668
19675
|
}
|
|
19669
|
-
if (
|
|
19670
|
-
const headerRow =
|
|
19671
|
-
const allLabels = headerRow.every((
|
|
19672
|
-
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();
|
|
19673
19680
|
return t.length > 0 && t.length <= 20 && isLabelCell(t);
|
|
19674
19681
|
});
|
|
19675
19682
|
if (!allLabels) return;
|
|
19676
|
-
for (let r = 1; r <
|
|
19677
|
-
for (let c = 0; c <
|
|
19683
|
+
for (let r = 1; r < table2.rows; r++) {
|
|
19684
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
19678
19685
|
if (covered.has(`${r},${c}`)) continue;
|
|
19679
19686
|
const headerCell = headerRow[c];
|
|
19680
|
-
const valueCell =
|
|
19687
|
+
const valueCell = table2.cells[r]?.[c];
|
|
19681
19688
|
if (!headerCell || !valueCell) continue;
|
|
19682
19689
|
const headerLabel = normalizeLabel(headerCell.text);
|
|
19683
19690
|
if (blockedLabels?.has(headerLabel)) continue;
|
|
@@ -19858,9 +19865,9 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19858
19865
|
if (closeName !== void 0) {
|
|
19859
19866
|
const local2 = localOf(closeName);
|
|
19860
19867
|
if (local2 === "t" && pendingT) {
|
|
19861
|
-
const { para, contentStart: contentStart2 } = pendingT;
|
|
19862
|
-
|
|
19863
|
-
|
|
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));
|
|
19864
19871
|
pendingT = null;
|
|
19865
19872
|
}
|
|
19866
19873
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
@@ -19870,35 +19877,35 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19870
19877
|
}
|
|
19871
19878
|
}
|
|
19872
19879
|
if (local2 === "p") {
|
|
19873
|
-
const
|
|
19874
|
-
if (
|
|
19880
|
+
const para2 = paraStack.pop();
|
|
19881
|
+
if (para2 && para2.kind === "excluded") {
|
|
19875
19882
|
const sub = currentCtrlSub();
|
|
19876
|
-
if (sub &&
|
|
19883
|
+
if (sub && para2.text.trim()) sub.texts.push(para2.text);
|
|
19877
19884
|
}
|
|
19878
19885
|
} else if (local2 === "tc") {
|
|
19879
|
-
const
|
|
19886
|
+
const cell2 = cellStack.pop();
|
|
19880
19887
|
const row = rowStack[rowStack.length - 1];
|
|
19881
|
-
if (
|
|
19888
|
+
if (cell2 && row) row.push(cell2);
|
|
19882
19889
|
} else if (local2 === "tr") {
|
|
19883
19890
|
const row = rowStack[rowStack.length - 1];
|
|
19884
|
-
const
|
|
19885
|
-
if (row &&
|
|
19886
|
-
|
|
19891
|
+
const table2 = tableStack[tableStack.length - 1];
|
|
19892
|
+
if (row && table2 && row.length > 0) {
|
|
19893
|
+
table2.rows.push(row);
|
|
19887
19894
|
const trStart = trStartStack[trStartStack.length - 1];
|
|
19888
|
-
if (trStart >= 0)
|
|
19895
|
+
if (trStart >= 0) table2.rowRanges.push({ start: trStart, end: m.index + full.length });
|
|
19889
19896
|
}
|
|
19890
19897
|
if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
|
|
19891
19898
|
if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = -1;
|
|
19892
19899
|
} else if (local2 === "tbl") {
|
|
19893
|
-
const
|
|
19900
|
+
const table2 = tableStack.pop();
|
|
19894
19901
|
rowStack.pop();
|
|
19895
19902
|
trStartStack.pop();
|
|
19896
|
-
if (
|
|
19897
|
-
finalizeTable(
|
|
19898
|
-
if (!
|
|
19899
|
-
const
|
|
19900
|
-
if (
|
|
19901
|
-
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);
|
|
19902
19909
|
}
|
|
19903
19910
|
}
|
|
19904
19911
|
} else if (local2 === "header" || local2 === "footer") {
|
|
@@ -19918,45 +19925,45 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19918
19925
|
const contentStart = m.index + full.length;
|
|
19919
19926
|
if (isSelfClose) {
|
|
19920
19927
|
if (local === "t") {
|
|
19921
|
-
const
|
|
19922
|
-
if (
|
|
19928
|
+
const para2 = owningPara();
|
|
19929
|
+
if (para2) para2.tRanges.push({ contentStart: m.index, contentEnd: m.index + full.length, selfClosing: true, prefix: prefixOf(qname) });
|
|
19923
19930
|
} else if (local === "tab" || local === "fwSpace" || local === "hwSpace" || local === "br" || local === "lineBreak") {
|
|
19924
19931
|
if (!pendingT) {
|
|
19925
|
-
const
|
|
19926
|
-
if (
|
|
19932
|
+
const para2 = owningPara();
|
|
19933
|
+
if (para2) para2.text += " ";
|
|
19927
19934
|
}
|
|
19928
19935
|
} else if (local === "run" || local === "r") {
|
|
19929
|
-
const
|
|
19930
|
-
if (
|
|
19936
|
+
const para2 = owningPara();
|
|
19937
|
+
if (para2 && !para2.selfCloseRun) para2.selfCloseRun = { start: m.index, end: m.index + full.length };
|
|
19931
19938
|
} else if (local === "cellAddr") {
|
|
19932
|
-
const
|
|
19933
|
-
if (
|
|
19939
|
+
const cell2 = cellStack[cellStack.length - 1];
|
|
19940
|
+
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
19934
19941
|
const ca = parseInt(getAttr2(attrsRaw, "colAddr") || "", 10);
|
|
19935
19942
|
const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
|
|
19936
|
-
if (!isNaN(ca))
|
|
19937
|
-
if (!isNaN(ra))
|
|
19938
|
-
|
|
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 };
|
|
19939
19946
|
}
|
|
19940
19947
|
} else if (local === "cellSpan") {
|
|
19941
|
-
const
|
|
19942
|
-
if (
|
|
19948
|
+
const cell2 = cellStack[cellStack.length - 1];
|
|
19949
|
+
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
19943
19950
|
const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
|
|
19944
19951
|
const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
|
|
19945
|
-
|
|
19946
|
-
|
|
19952
|
+
cell2.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
|
|
19953
|
+
cell2.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
|
|
19947
19954
|
}
|
|
19948
19955
|
}
|
|
19949
19956
|
continue;
|
|
19950
19957
|
}
|
|
19951
19958
|
if (local === "t") {
|
|
19952
|
-
const
|
|
19953
|
-
if (
|
|
19959
|
+
const para2 = owningPara();
|
|
19960
|
+
if (para2) pendingT = { para: para2, contentStart };
|
|
19954
19961
|
stack.push({ local, qname, contentStart });
|
|
19955
19962
|
continue;
|
|
19956
19963
|
}
|
|
19957
19964
|
stack.push({ local, qname, contentStart });
|
|
19958
19965
|
if (local === "p") {
|
|
19959
|
-
const
|
|
19966
|
+
const para2 = {
|
|
19960
19967
|
sectionIndex,
|
|
19961
19968
|
kind: "excluded",
|
|
19962
19969
|
// 분류는 push 직후 스택 기준 (자기 자신 제외)
|
|
@@ -19966,22 +19973,22 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19966
19973
|
};
|
|
19967
19974
|
stack.pop();
|
|
19968
19975
|
const cls = classifyPara();
|
|
19969
|
-
|
|
19970
|
-
if (cls.inTextbox)
|
|
19976
|
+
para2.kind = cls.kind;
|
|
19977
|
+
if (cls.inTextbox) para2.inTextbox = true;
|
|
19971
19978
|
stack.push({ local, qname, contentStart });
|
|
19972
|
-
paraStack.push(
|
|
19973
|
-
if (
|
|
19974
|
-
else if (
|
|
19975
|
-
const
|
|
19976
|
-
if (
|
|
19977
|
-
} else if (
|
|
19978
|
-
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);
|
|
19979
19986
|
}
|
|
19980
19987
|
} else if (local === "run" || local === "r") {
|
|
19981
|
-
const
|
|
19982
|
-
if (
|
|
19988
|
+
const para2 = owningPara();
|
|
19989
|
+
if (para2 && para2.runPrefix === void 0) para2.runPrefix = prefixOf(qname);
|
|
19983
19990
|
} else if (local === "tbl") {
|
|
19984
|
-
const
|
|
19991
|
+
const table2 = {
|
|
19985
19992
|
sectionIndex,
|
|
19986
19993
|
start: m.index,
|
|
19987
19994
|
topLevel: false,
|
|
@@ -19990,31 +19997,31 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
19990
19997
|
cellByAnchor: /* @__PURE__ */ new Map()
|
|
19991
19998
|
};
|
|
19992
19999
|
stack.pop();
|
|
19993
|
-
|
|
20000
|
+
table2.topLevel = isTableTopLevel();
|
|
19994
20001
|
stack.push({ local, qname, contentStart });
|
|
19995
|
-
tableStack.push(
|
|
20002
|
+
tableStack.push(table2);
|
|
19996
20003
|
rowStack.push([]);
|
|
19997
20004
|
trStartStack.push(-1);
|
|
19998
|
-
if (
|
|
20005
|
+
if (table2.topLevel) tables.push(table2);
|
|
19999
20006
|
} else if (local === "tr") {
|
|
20000
20007
|
if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
|
|
20001
20008
|
if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = m.index;
|
|
20002
20009
|
} else if (local === "tc") {
|
|
20003
20010
|
cellStack.push({ colSpan: 1, rowSpan: 1, paragraphs: [], tables: [] });
|
|
20004
20011
|
} else if (local === "cellAddr" || local === "cellSpan") {
|
|
20005
|
-
const
|
|
20006
|
-
if (
|
|
20012
|
+
const cell2 = cellStack[cellStack.length - 1];
|
|
20013
|
+
if (cell2 && insideCurrentTable(stack, tableStack)) {
|
|
20007
20014
|
if (local === "cellAddr") {
|
|
20008
20015
|
const ca = parseInt(getAttr2(attrsRaw, "colAddr") || "", 10);
|
|
20009
20016
|
const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
|
|
20010
|
-
if (!isNaN(ca))
|
|
20011
|
-
if (!isNaN(ra))
|
|
20012
|
-
|
|
20017
|
+
if (!isNaN(ca)) cell2.colAddr = ca;
|
|
20018
|
+
if (!isNaN(ra)) cell2.rowAddr = ra;
|
|
20019
|
+
cell2.addrTagRange = { start: m.index, end: contentStart };
|
|
20013
20020
|
} else {
|
|
20014
20021
|
const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
|
|
20015
20022
|
const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
|
|
20016
|
-
|
|
20017
|
-
|
|
20023
|
+
cell2.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
|
|
20024
|
+
cell2.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
|
|
20018
20025
|
}
|
|
20019
20026
|
}
|
|
20020
20027
|
} else if (local === "header" || local === "footer") {
|
|
@@ -20022,23 +20029,23 @@ function scanSectionXml(xml, sectionIndex) {
|
|
|
20022
20029
|
ctrlSubStack.push({ kind: local, texts: [] });
|
|
20023
20030
|
}
|
|
20024
20031
|
} else if (local === "tab" || local === "fwSpace" || local === "hwSpace" || local === "br" || local === "lineBreak") {
|
|
20025
|
-
const
|
|
20026
|
-
if (
|
|
20032
|
+
const para2 = owningPara();
|
|
20033
|
+
if (para2) para2.text += " ";
|
|
20027
20034
|
}
|
|
20028
20035
|
}
|
|
20029
|
-
for (const
|
|
20030
|
-
for (const
|
|
20031
|
-
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) => {
|
|
20032
20039
|
if (depth > 16) return;
|
|
20033
|
-
for (const row of
|
|
20034
|
-
for (const
|
|
20035
|
-
for (const
|
|
20036
|
-
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);
|
|
20037
20044
|
}
|
|
20038
20045
|
}
|
|
20039
20046
|
};
|
|
20040
|
-
for (const
|
|
20041
|
-
for (const
|
|
20047
|
+
for (const table2 of tables) fillTableInsertPos(table2);
|
|
20048
|
+
for (const table2 of orphanTables) fillTableInsertPos(table2);
|
|
20042
20049
|
return { sectionIndex, xml, bodyParagraphs, tables, headerTexts, footerTexts, excludedParagraphs, orphanTables };
|
|
20043
20050
|
}
|
|
20044
20051
|
function getAttr2(attrsRaw, name) {
|
|
@@ -20055,19 +20062,19 @@ function insideCurrentTable(stack, tableStack) {
|
|
|
20055
20062
|
}
|
|
20056
20063
|
return false;
|
|
20057
20064
|
}
|
|
20058
|
-
function fillRunInsertPos(
|
|
20059
|
-
if (
|
|
20060
|
-
const pEnd = findElementEnd(xml,
|
|
20065
|
+
function fillRunInsertPos(para2, xml) {
|
|
20066
|
+
if (para2.tRanges.length > 0) return;
|
|
20067
|
+
const pEnd = findElementEnd(xml, para2.start);
|
|
20061
20068
|
if (pEnd < 0) return;
|
|
20062
|
-
const slice = xml.slice(
|
|
20069
|
+
const slice = xml.slice(para2.start, pEnd);
|
|
20063
20070
|
const runOpen = slice.match(/<((?:[A-Za-z0-9_]+:)?run)(?:\s(?:"[^"]*"|'[^']*'|[^>"'])*?)?(\/?)>/);
|
|
20064
20071
|
if (!runOpen || runOpen.index === void 0) return;
|
|
20065
20072
|
if (runOpen[2] === "/") return;
|
|
20066
20073
|
const qname = runOpen[1];
|
|
20067
20074
|
const closeIdx = slice.indexOf(`</${qname}>`, runOpen.index);
|
|
20068
20075
|
if (closeIdx < 0) return;
|
|
20069
|
-
|
|
20070
|
-
|
|
20076
|
+
para2.runInsertPos = para2.start + closeIdx;
|
|
20077
|
+
para2.runPrefix = prefixOf(qname);
|
|
20071
20078
|
}
|
|
20072
20079
|
function findElementEnd(xml, start) {
|
|
20073
20080
|
const open = xml.slice(start).match(/^<([^\s/>!?]+)/);
|
|
@@ -20087,39 +20094,39 @@ function findElementEnd(xml, start) {
|
|
|
20087
20094
|
}
|
|
20088
20095
|
return -1;
|
|
20089
20096
|
}
|
|
20090
|
-
function finalizeTable(
|
|
20091
|
-
const hasAddr =
|
|
20097
|
+
function finalizeTable(table2) {
|
|
20098
|
+
const hasAddr = table2.rows.some((row) => row.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0));
|
|
20092
20099
|
if (hasAddr) {
|
|
20093
|
-
for (const row of
|
|
20094
|
-
for (const
|
|
20095
|
-
if (
|
|
20096
|
-
|
|
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);
|
|
20097
20104
|
}
|
|
20098
20105
|
}
|
|
20099
20106
|
}
|
|
20100
20107
|
return;
|
|
20101
20108
|
}
|
|
20102
|
-
const numRows =
|
|
20109
|
+
const numRows = table2.rows.length;
|
|
20103
20110
|
const occupied = Array.from({ length: numRows }, () => []);
|
|
20104
20111
|
for (let rowIdx = 0; rowIdx < numRows; rowIdx++) {
|
|
20105
20112
|
let colIdx = 0;
|
|
20106
|
-
for (const
|
|
20113
|
+
for (const cell2 of table2.rows[rowIdx]) {
|
|
20107
20114
|
while (occupied[rowIdx][colIdx]) colIdx++;
|
|
20108
|
-
|
|
20109
|
-
|
|
20110
|
-
|
|
20111
|
-
for (let r = rowIdx; r < Math.min(rowIdx +
|
|
20112
|
-
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++) {
|
|
20113
20120
|
occupied[r][c] = true;
|
|
20114
20121
|
}
|
|
20115
20122
|
}
|
|
20116
|
-
colIdx +=
|
|
20123
|
+
colIdx += cell2.colSpan;
|
|
20117
20124
|
}
|
|
20118
20125
|
}
|
|
20119
20126
|
}
|
|
20120
|
-
function buildParagraphSplices(
|
|
20127
|
+
function buildParagraphSplices(para2, newText, xml) {
|
|
20121
20128
|
if (newText && xml) {
|
|
20122
|
-
const orig = paraTText(
|
|
20129
|
+
const orig = paraTText(para2, xml);
|
|
20123
20130
|
if (orig && orig.trim() !== "") {
|
|
20124
20131
|
const lead = orig.match(/^\s*/)[0];
|
|
20125
20132
|
const trail = orig.match(/\s*$/)[0];
|
|
@@ -20129,31 +20136,31 @@ function buildParagraphSplices(para, newText, xml) {
|
|
|
20129
20136
|
}
|
|
20130
20137
|
}
|
|
20131
20138
|
const escaped = escapeXmlText(newText);
|
|
20132
|
-
if (
|
|
20139
|
+
if (para2.tRanges.length > 0) {
|
|
20133
20140
|
const splices = [];
|
|
20134
|
-
const first =
|
|
20141
|
+
const first = para2.tRanges[0];
|
|
20135
20142
|
if (first.selfClosing) {
|
|
20136
20143
|
const prefix = first.prefix ? first.prefix + ":" : "";
|
|
20137
20144
|
splices.push({ start: first.contentStart, end: first.contentEnd, replacement: `<${prefix}t>${escaped}</${prefix}t>` });
|
|
20138
20145
|
} else {
|
|
20139
20146
|
splices.push({ start: first.contentStart, end: first.contentEnd, replacement: escaped });
|
|
20140
20147
|
}
|
|
20141
|
-
for (let i = 1; i <
|
|
20142
|
-
const r =
|
|
20148
|
+
for (let i = 1; i < para2.tRanges.length; i++) {
|
|
20149
|
+
const r = para2.tRanges[i];
|
|
20143
20150
|
if (!r.selfClosing && r.contentStart < r.contentEnd) {
|
|
20144
20151
|
splices.push({ start: r.contentStart, end: r.contentEnd, replacement: "" });
|
|
20145
20152
|
}
|
|
20146
20153
|
}
|
|
20147
20154
|
return splices;
|
|
20148
20155
|
}
|
|
20149
|
-
if (
|
|
20156
|
+
if (para2.runInsertPos !== void 0) {
|
|
20150
20157
|
if (!newText) return [];
|
|
20151
|
-
const prefix =
|
|
20152
|
-
return [{ start:
|
|
20158
|
+
const prefix = para2.runPrefix ? para2.runPrefix + ":" : "";
|
|
20159
|
+
return [{ start: para2.runInsertPos, end: para2.runInsertPos, replacement: `<${prefix}t>${escaped}</${prefix}t>` }];
|
|
20153
20160
|
}
|
|
20154
|
-
if (
|
|
20161
|
+
if (para2.selfCloseRun && xml) {
|
|
20155
20162
|
if (!newText) return [];
|
|
20156
|
-
const { start, end } =
|
|
20163
|
+
const { start, end } = para2.selfCloseRun;
|
|
20157
20164
|
const tag = xml.slice(start, end);
|
|
20158
20165
|
const qm = tag.match(/^<([^\s/>]+)/);
|
|
20159
20166
|
if (!qm || !tag.endsWith("/>")) return null;
|
|
@@ -20165,9 +20172,9 @@ function buildParagraphSplices(para, newText, xml) {
|
|
|
20165
20172
|
}
|
|
20166
20173
|
return newText ? null : [];
|
|
20167
20174
|
}
|
|
20168
|
-
function paraTText(
|
|
20175
|
+
function paraTText(para2, xml) {
|
|
20169
20176
|
let text = "";
|
|
20170
|
-
for (const t of
|
|
20177
|
+
for (const t of para2.tRanges) {
|
|
20171
20178
|
if (t.selfClosing) continue;
|
|
20172
20179
|
const raw = xml.slice(t.contentStart, t.contentEnd);
|
|
20173
20180
|
if (/[<&]/.test(raw)) return null;
|
|
@@ -20175,19 +20182,19 @@ function paraTText(para, xml) {
|
|
|
20175
20182
|
}
|
|
20176
20183
|
return text;
|
|
20177
20184
|
}
|
|
20178
|
-
function paraTextPureT(
|
|
20185
|
+
function paraTextPureT(para2, xml) {
|
|
20179
20186
|
let len = 0;
|
|
20180
|
-
for (const t of
|
|
20187
|
+
for (const t of para2.tRanges) {
|
|
20181
20188
|
if (t.selfClosing) continue;
|
|
20182
20189
|
len += tContentToText(xml.slice(t.contentStart, t.contentEnd)).length;
|
|
20183
20190
|
}
|
|
20184
|
-
return len ===
|
|
20191
|
+
return len === para2.text.length;
|
|
20185
20192
|
}
|
|
20186
|
-
function buildRangeSplices(
|
|
20193
|
+
function buildRangeSplices(para2, xml, start, end, replacement) {
|
|
20187
20194
|
if (start < 0 || end < start) return null;
|
|
20188
20195
|
const segs = [];
|
|
20189
20196
|
let offset = 0;
|
|
20190
|
-
for (const t of
|
|
20197
|
+
for (const t of para2.tRanges) {
|
|
20191
20198
|
if (t.selfClosing) continue;
|
|
20192
20199
|
const raw = xml.slice(t.contentStart, t.contentEnd);
|
|
20193
20200
|
if (/[<&]/.test(raw)) return null;
|
|
@@ -20307,13 +20314,13 @@ function parseCentralDirectory(buf) {
|
|
|
20307
20314
|
return { entries, cdOffset, cdSize, eocdOffset };
|
|
20308
20315
|
}
|
|
20309
20316
|
var CRC_TABLE2 = (() => {
|
|
20310
|
-
const
|
|
20317
|
+
const table2 = new Uint32Array(256);
|
|
20311
20318
|
for (let n = 0; n < 256; n++) {
|
|
20312
20319
|
let c = n;
|
|
20313
20320
|
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
20314
|
-
|
|
20321
|
+
table2[n] = c >>> 0;
|
|
20315
20322
|
}
|
|
20316
|
-
return
|
|
20323
|
+
return table2;
|
|
20317
20324
|
})();
|
|
20318
20325
|
function crc322(data) {
|
|
20319
20326
|
let crc = 4294967295;
|
|
@@ -20475,28 +20482,28 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20475
20482
|
return l;
|
|
20476
20483
|
};
|
|
20477
20484
|
const matchText = (p) => paraTText(p, xml) ?? p.text;
|
|
20478
|
-
const cellLabelText = (
|
|
20485
|
+
const cellLabelText = (cell2) => cell2.paragraphs.filter((p) => !p.inTextbox).map((p) => matchText(p)).join("");
|
|
20479
20486
|
const allTables = [];
|
|
20480
20487
|
const collectTables = (tables, depth) => {
|
|
20481
20488
|
if (depth > 16) return;
|
|
20482
20489
|
for (const t of tables) {
|
|
20483
20490
|
allTables.push(t);
|
|
20484
20491
|
for (const row of t.rows) {
|
|
20485
|
-
for (const
|
|
20492
|
+
for (const cell2 of row) collectTables(cell2.tables, depth + 1);
|
|
20486
20493
|
}
|
|
20487
20494
|
}
|
|
20488
20495
|
};
|
|
20489
20496
|
collectTables(scan.tables, 0);
|
|
20490
20497
|
collectTables(scan.orphanTables, 0);
|
|
20491
20498
|
const patternApplied = /* @__PURE__ */ new Set();
|
|
20492
|
-
for (const
|
|
20493
|
-
for (const row of
|
|
20494
|
-
for (const
|
|
20495
|
-
for (const
|
|
20496
|
-
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);
|
|
20497
20504
|
const result = fillInCellPatterns(text, cursor, matchedLabels, blockedLabels);
|
|
20498
20505
|
if (!result) continue;
|
|
20499
|
-
const l = led(
|
|
20506
|
+
const l = led(para2);
|
|
20500
20507
|
if (l.fullText !== void 0) continue;
|
|
20501
20508
|
const newT = result.text;
|
|
20502
20509
|
let s = 0;
|
|
@@ -20508,7 +20515,7 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20508
20515
|
en--;
|
|
20509
20516
|
}
|
|
20510
20517
|
l.ranges.push({ start: s, end: eo, replacement: newT.slice(s, en) });
|
|
20511
|
-
patternApplied.add(
|
|
20518
|
+
patternApplied.add(cell2);
|
|
20512
20519
|
for (const m of result.matches) {
|
|
20513
20520
|
l.filledIdx.push(filled.length);
|
|
20514
20521
|
l.matchKeys.push(m.key);
|
|
@@ -20518,9 +20525,9 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20518
20525
|
}
|
|
20519
20526
|
}
|
|
20520
20527
|
}
|
|
20521
|
-
for (const
|
|
20522
|
-
for (let rowIdx = 0; rowIdx <
|
|
20523
|
-
const cells =
|
|
20528
|
+
for (const table2 of allTables) {
|
|
20529
|
+
for (let rowIdx = 0; rowIdx < table2.rows.length; rowIdx++) {
|
|
20530
|
+
const cells = table2.rows[rowIdx];
|
|
20524
20531
|
for (let colIdx = 0; colIdx < cells.length - 1; colIdx++) {
|
|
20525
20532
|
const labelText = cellLabelText(cells[colIdx]);
|
|
20526
20533
|
if (!isLabelCell(labelText)) continue;
|
|
@@ -20575,15 +20582,15 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20575
20582
|
}
|
|
20576
20583
|
}
|
|
20577
20584
|
}
|
|
20578
|
-
if (
|
|
20579
|
-
const headerCells =
|
|
20580
|
-
const allLabels = headerCells.length > 0 && headerCells.every((
|
|
20581
|
-
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();
|
|
20582
20589
|
return t.length > 0 && t.length <= 20 && isLabelCell(t);
|
|
20583
20590
|
});
|
|
20584
20591
|
if (allLabels) {
|
|
20585
|
-
for (let rowIdx = 1; rowIdx <
|
|
20586
|
-
const dataCells =
|
|
20592
|
+
for (let rowIdx = 1; rowIdx < table2.rows.length; rowIdx++) {
|
|
20593
|
+
const dataCells = table2.rows[rowIdx];
|
|
20587
20594
|
for (let colIdx = 0; colIdx < Math.min(headerCells.length, dataCells.length); colIdx++) {
|
|
20588
20595
|
const headerLabel = normalizeLabel(cellLabelText(headerCells[colIdx]));
|
|
20589
20596
|
if (blockedLabels?.has(headerLabel)) continue;
|
|
@@ -20617,10 +20624,10 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20617
20624
|
}
|
|
20618
20625
|
}
|
|
20619
20626
|
}
|
|
20620
|
-
for (const
|
|
20621
|
-
const existing = ledger.get(
|
|
20627
|
+
for (const para2 of [...scan.bodyParagraphs, ...scan.excludedParagraphs]) {
|
|
20628
|
+
const existing = ledger.get(para2);
|
|
20622
20629
|
if (existing?.fullText !== void 0) continue;
|
|
20623
|
-
const text = matchText(
|
|
20630
|
+
const text = matchText(para2);
|
|
20624
20631
|
for (const seg of scanInlineSegments(text)) {
|
|
20625
20632
|
const nlabel = normalizeLabel(seg.label);
|
|
20626
20633
|
if (blockedLabels?.has(nlabel)) continue;
|
|
@@ -20629,7 +20636,7 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20629
20636
|
const newValue = cursor.consume(matchKey);
|
|
20630
20637
|
if (newValue === void 0) continue;
|
|
20631
20638
|
const replacement = seg.valueStart === seg.valueEnd ? padInsertion(text, seg.valueStart, newValue) : newValue;
|
|
20632
|
-
const l = led(
|
|
20639
|
+
const l = led(para2);
|
|
20633
20640
|
l.ranges.push({ start: seg.valueStart, end: seg.valueEnd, replacement });
|
|
20634
20641
|
matchedLabels.add(matchKey);
|
|
20635
20642
|
l.filledIdx.push(filled.length);
|
|
@@ -20638,10 +20645,10 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20638
20645
|
}
|
|
20639
20646
|
}
|
|
20640
20647
|
const splices = [];
|
|
20641
|
-
for (const [
|
|
20648
|
+
for (const [para2, l] of ledger) {
|
|
20642
20649
|
let paraSplices = null;
|
|
20643
20650
|
if (l.fullText !== void 0) {
|
|
20644
|
-
paraSplices = buildParagraphSplices(
|
|
20651
|
+
paraSplices = buildParagraphSplices(para2, l.fullText, xml);
|
|
20645
20652
|
} else if (l.ranges.length > 0) {
|
|
20646
20653
|
const sorted = [...l.ranges].sort((a, b) => a.start - b.start || a.end - b.end);
|
|
20647
20654
|
const merged = [];
|
|
@@ -20650,11 +20657,11 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20650
20657
|
if (prev && r.start < prev.end) continue;
|
|
20651
20658
|
merged.push(r);
|
|
20652
20659
|
}
|
|
20653
|
-
if (paraTText(
|
|
20660
|
+
if (paraTText(para2, xml) !== null) {
|
|
20654
20661
|
const precise = [];
|
|
20655
20662
|
let ok = true;
|
|
20656
20663
|
for (const r of merged) {
|
|
20657
|
-
const sp = buildRangeSplices(
|
|
20664
|
+
const sp = buildRangeSplices(para2, xml, r.start, r.end, r.replacement);
|
|
20658
20665
|
if (!sp) {
|
|
20659
20666
|
ok = false;
|
|
20660
20667
|
break;
|
|
@@ -20662,13 +20669,13 @@ async function fillHwpx(hwpxBuffer, values, blockedLabels) {
|
|
|
20662
20669
|
precise.push(...sp);
|
|
20663
20670
|
}
|
|
20664
20671
|
paraSplices = ok ? precise : null;
|
|
20665
|
-
} else if (paraTextPureT(
|
|
20666
|
-
let text =
|
|
20672
|
+
} else if (paraTextPureT(para2, xml)) {
|
|
20673
|
+
let text = para2.text;
|
|
20667
20674
|
for (let k = merged.length - 1; k >= 0; k--) {
|
|
20668
20675
|
const r = merged[k];
|
|
20669
20676
|
text = text.slice(0, r.start) + r.replacement + text.slice(r.end);
|
|
20670
20677
|
}
|
|
20671
|
-
paraSplices = buildParagraphSplices(
|
|
20678
|
+
paraSplices = buildParagraphSplices(para2, text, xml);
|
|
20672
20679
|
} else {
|
|
20673
20680
|
paraSplices = null;
|
|
20674
20681
|
}
|
|
@@ -20850,6 +20857,7 @@ function charWidthEm1000(cp) {
|
|
|
20850
20857
|
if (cp >= 19968 && cp <= 40959 || cp >= 63744 && cp <= 64255) return 1e3;
|
|
20851
20858
|
if (cp >= 12296 && cp <= 12305 || cp >= 12308 && cp <= 12315) return 500;
|
|
20852
20859
|
if (cp === 12288) return 970;
|
|
20860
|
+
if (cp >= 8544 && cp <= 8579) return 970;
|
|
20853
20861
|
if (cp >= 8592 && cp <= 8959) return 970;
|
|
20854
20862
|
if (cp >= 9312 && cp <= 9471) return 970;
|
|
20855
20863
|
if (cp >= 9632 && cp <= 9983) return 970;
|
|
@@ -20941,14 +20949,126 @@ function fitRatioForFewerLines(text, firstWidth, contWidth, height, baseRatio, m
|
|
|
20941
20949
|
return null;
|
|
20942
20950
|
}
|
|
20943
20951
|
|
|
20952
|
+
// src/hwpx/gaejosik.ts
|
|
20953
|
+
var GAEJOSIK_BULLETS = ["\u25A1", "\u25CB", "-", "\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
|
+
|
|
20944
21061
|
// src/hwpx/gongmun.ts
|
|
20945
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;
|
|
20946
21065
|
var PRESET_DEFAULTS = {
|
|
20947
21066
|
official: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
20948
21067
|
report: { bodyPt: 15, lineSpacing: 160, numbering: "report" },
|
|
20949
21068
|
plan: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
20950
21069
|
notice: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
|
|
20951
|
-
minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" }
|
|
21070
|
+
minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" },
|
|
21071
|
+
gaejosik: { bodyPt: 15, lineSpacing: 160, numbering: "gaejosik" }
|
|
20952
21072
|
};
|
|
20953
21073
|
var PRESET_ALIAS = {
|
|
20954
21074
|
official: "official",
|
|
@@ -20966,26 +21086,51 @@ var PRESET_ALIAS = {
|
|
|
20966
21086
|
\uC54C\uB9BC: "notice",
|
|
20967
21087
|
\uC548\uB0B4: "notice",
|
|
20968
21088
|
minutes: "minutes",
|
|
20969
|
-
\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"
|
|
20970
21095
|
};
|
|
20971
21096
|
function normalizeGongmunPreset(preset) {
|
|
20972
21097
|
if (!preset) return "official";
|
|
20973
21098
|
return PRESET_ALIAS[preset.trim()] ?? "official";
|
|
20974
21099
|
}
|
|
21100
|
+
function usesReportFonts(preset) {
|
|
21101
|
+
return preset === "gaejosik" || preset === "report" || preset === "plan";
|
|
21102
|
+
}
|
|
20975
21103
|
function resolveGongmun(opts) {
|
|
20976
21104
|
const preset = normalizeGongmunPreset(opts.preset);
|
|
20977
21105
|
const d = PRESET_DEFAULTS[preset];
|
|
20978
21106
|
const bodyPt = opts.bodyPt ?? d.bodyPt;
|
|
20979
21107
|
const autoFitMinRatio = opts.autoFit === false ? null : typeof opts.autoFit === "object" ? Math.min(Math.max(opts.autoFit.minRatio ?? 90, 50), 99) : 90;
|
|
21108
|
+
const coverOn = opts.cover !== void 0 ? opts.cover !== false : preset === "gaejosik";
|
|
21109
|
+
const coverOpts = typeof opts.cover === "object" ? opts.cover : {};
|
|
21110
|
+
const gaejosik = preset === "gaejosik";
|
|
20980
21111
|
return {
|
|
20981
21112
|
preset,
|
|
20982
21113
|
bodyFont: opts.bodyFont ?? "myeongjo",
|
|
20983
21114
|
bodyHeight: Math.round(bodyPt * 100),
|
|
20984
21115
|
lineSpacing: opts.lineSpacing ?? d.lineSpacing,
|
|
20985
21116
|
numbering: opts.numbering ?? d.numbering,
|
|
20986
|
-
margins: opts.margins ?? OFFICIAL_MARGINS,
|
|
21117
|
+
margins: opts.margins ?? (gaejosik ? GAEJOSIK_MARGINS : OFFICIAL_MARGINS),
|
|
20987
21118
|
centerTitle: opts.centerTitle ?? true,
|
|
20988
|
-
autoFitMinRatio
|
|
21119
|
+
autoFitMinRatio,
|
|
21120
|
+
cover: coverOn ? { date: coverOpts.date ?? null, org: coverOpts.org ?? "" } : null,
|
|
21121
|
+
toc: opts.toc ?? gaejosik,
|
|
21122
|
+
fonts: opts.fonts ?? {},
|
|
21123
|
+
sizes: opts.sizes ?? {},
|
|
21124
|
+
// 쪽번호 — 보고서 계열 관행(실측: 2_보고서 양식·추진계획·공고문 전부 하단 중앙)
|
|
21125
|
+
pageNumbers: opts.pageNumbers ?? (gaejosik || preset === "report" || preset === "plan"),
|
|
21126
|
+
headerFooter: gaejosik ? GAEJOSIK_HEADER_FOOTER : 0,
|
|
21127
|
+
// "끝." — 기안문 규정(본문 끝 2타+"끝."). 그 외는 opt-in
|
|
21128
|
+
endMark: opts.endMark ?? preset === "official",
|
|
21129
|
+
approval: opts.approval && opts.approval.length > 0 ? opts.approval : null,
|
|
21130
|
+
// 본문 제목박스 — 실측(GT3·GT12): 목차 뒤 본문 시작에 제목 반복. 표지 켜진 개조식 기본
|
|
21131
|
+
bodyTitleBox: opts.bodyTitleBox ?? (gaejosik && coverOn),
|
|
21132
|
+
// h2 말머리 — 실측 보고서 양식(부처별 3종)의 섹션 제목이 곧 □ 대항목 (QA-2)
|
|
21133
|
+
h2Marker: opts.h2Marker ?? (preset === "report" || preset === "plan" ? "box" : "none")
|
|
20989
21134
|
};
|
|
20990
21135
|
}
|
|
20991
21136
|
var HANGUL_INITIALS = [0, 2, 3, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18];
|
|
@@ -21033,7 +21178,8 @@ function markerWidth(marker, bodyHeight) {
|
|
|
21033
21178
|
for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
|
|
21034
21179
|
return Math.round(em / 1e3 * bodyHeight);
|
|
21035
21180
|
}
|
|
21036
|
-
function levelIndent(depth, bodyHeight, numbering) {
|
|
21181
|
+
function levelIndent(depth, bodyHeight, numbering, sizes = {}) {
|
|
21182
|
+
if (numbering === "gaejosik") return gaejosikLevelIndent(depth, bodyHeight, sizes);
|
|
21037
21183
|
const marker = numbering === "report" ? reportMarker(depth) : standardMarker(depth, 0);
|
|
21038
21184
|
return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, bodyHeight) };
|
|
21039
21185
|
}
|
|
@@ -21061,6 +21207,7 @@ var GongmunNumberer = class {
|
|
|
21061
21207
|
const n = this.counts[depth] ?? 0;
|
|
21062
21208
|
this.counts[depth] = n + 1;
|
|
21063
21209
|
if (suppress) return "";
|
|
21210
|
+
if (this.numbering === "gaejosik") return gaejosikMarker(depth);
|
|
21064
21211
|
return this.numbering === "report" ? reportMarker(depth) : standardMarker(depth, n);
|
|
21065
21212
|
}
|
|
21066
21213
|
reset() {
|
|
@@ -21131,24 +21278,25 @@ function headingCharPrId(level) {
|
|
|
21131
21278
|
function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100) {
|
|
21132
21279
|
const boldAttr = bold ? ` bold="1"` : "";
|
|
21133
21280
|
const italicAttr = italic ? ` italic="1"` : "";
|
|
21134
|
-
const effFont =
|
|
21281
|
+
const effFont = fontId;
|
|
21282
|
+
const boldEl = bold ? `<hh:bold/>` : "";
|
|
21135
21283
|
return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
21136
21284
|
<hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
|
|
21137
21285
|
<hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
|
|
21138
21286
|
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
21139
21287
|
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
21140
|
-
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"
|
|
21288
|
+
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>${boldEl}
|
|
21141
21289
|
</hh:charPr>`;
|
|
21142
21290
|
}
|
|
21143
21291
|
function paraPr(id, opts = {}) {
|
|
21144
|
-
const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, keepWord = false, outlineLevel } = opts;
|
|
21145
|
-
const breakNonLatin = keepWord ? "
|
|
21292
|
+
const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, keepWord = false, keepWithNext = false, outlineLevel } = opts;
|
|
21293
|
+
const breakNonLatin = keepWord ? "BREAK_WORD" : "KEEP_WORD";
|
|
21146
21294
|
const snapGrid = keepWord ? "0" : "1";
|
|
21147
21295
|
const heading = outlineLevel !== void 0 ? `<hh:heading type="OUTLINE" idRef="0" level="${outlineLevel}"/>` : `<hh:heading type="NONE" idRef="0" level="0"/>`;
|
|
21148
21296
|
return ` <hh:paraPr id="${id}" tabPrIDRef="0" condense="0" fontLineHeight="0" snapToGrid="${snapGrid}" suppressLineNumbers="0" checked="0" textDir="AUTO">
|
|
21149
21297
|
<hh:align horizontal="${align}" vertical="BASELINE"/>
|
|
21150
21298
|
${heading}
|
|
21151
|
-
<hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="0" keepWithNext="0" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
|
|
21299
|
+
<hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="0" keepWithNext="${keepWithNext ? 1 : 0}" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
|
|
21152
21300
|
<hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
|
|
21153
21301
|
<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>
|
|
21154
21302
|
<hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
|
|
@@ -21158,7 +21306,72 @@ function paraPr(id, opts = {}) {
|
|
|
21158
21306
|
var GONGMUN_LIST_BASE = 8;
|
|
21159
21307
|
var GONGMUN_LIST_LEVELS = 8;
|
|
21160
21308
|
var GONGMUN_CENTER = GONGMUN_LIST_BASE + GONGMUN_LIST_LEVELS;
|
|
21309
|
+
var GONGMUN_RIGHT = GONGMUN_CENTER + 1;
|
|
21310
|
+
var GONGMUN_TBL_CENTER = GONGMUN_RIGHT + 1;
|
|
21311
|
+
var GONGMUN_TBL_LEFT = GONGMUN_TBL_CENTER + 1;
|
|
21312
|
+
var GJ_CHAR_DAE = 11;
|
|
21313
|
+
var GJ_CHAR_DAE_BOLD = 12;
|
|
21314
|
+
var GJ_CHAR_CHAM = 13;
|
|
21315
|
+
var GJ_CHAR_CHAM_BOLD = 14;
|
|
21316
|
+
var GJ_CHAR_CHAPTER_NUM = 15;
|
|
21317
|
+
var GJ_CHAR_CHAPTER_TITLE = 16;
|
|
21318
|
+
var GJ_CHAR_COVER_TITLE = 17;
|
|
21319
|
+
var GJ_CHAR_COVER_SUB = 18;
|
|
21320
|
+
var GJ_CHAR_TOC_LABEL = 19;
|
|
21321
|
+
var GJ_CHAR_TOC_ROMAN = 20;
|
|
21322
|
+
var GJ_CHAR_TOC_ITEM = 21;
|
|
21323
|
+
var GJ_CHAR_TABLE = 22;
|
|
21324
|
+
var GJ_CHAR_TABLE_BOLD = 23;
|
|
21325
|
+
var GJ_CHAR_BAR = 24;
|
|
21326
|
+
var GJ_CHAR_BODY_TITLE = 25;
|
|
21327
|
+
var GJ_CHAR_COUNT = 15;
|
|
21328
|
+
var GJ_PARA_CHAM = 20;
|
|
21329
|
+
var GJ_PARA_COVER = 21;
|
|
21330
|
+
var GJ_PARA_TOC_ITEM = 22;
|
|
21331
|
+
var GJ_PARA_CHAPTER = 23;
|
|
21332
|
+
var GJ_PARA_BAR = 24;
|
|
21333
|
+
var GJ_BF_CHAPTER_NUM = 3;
|
|
21334
|
+
var GJ_BF_CHAPTER_GAP = 4;
|
|
21335
|
+
var GJ_BF_CHAPTER_TITLE = 5;
|
|
21336
|
+
var GJ_BF_BAR_DARK = 6;
|
|
21337
|
+
var GJ_BF_BAR_LIGHT = 7;
|
|
21338
|
+
var GJ_BF_TOC_BOX = 8;
|
|
21339
|
+
var GJ_BF_TOC_STRIPE = 9;
|
|
21340
|
+
function gongmunTableHeaderBf(gaejosik) {
|
|
21341
|
+
return gaejosik ? 10 : 3;
|
|
21342
|
+
}
|
|
21343
|
+
function borderFillEntry(id, b, fill) {
|
|
21344
|
+
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"/>`;
|
|
21345
|
+
let brush = "";
|
|
21346
|
+
if (typeof fill === "string") {
|
|
21347
|
+
brush = `
|
|
21348
|
+
<hc:fillBrush><hc:winBrush faceColor="${fill}" hatchColor="#000000" alpha="0"/></hc:fillBrush>`;
|
|
21349
|
+
} else if (fill) {
|
|
21350
|
+
brush = `
|
|
21351
|
+
<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>`;
|
|
21352
|
+
}
|
|
21353
|
+
return ` <hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
21354
|
+
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
21355
|
+
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
21356
|
+
${side("leftBorder", b.l)}
|
|
21357
|
+
${side("rightBorder", b.r)}
|
|
21358
|
+
${side("topBorder", b.t)}
|
|
21359
|
+
${side("bottomBorder", b.b)}${brush}
|
|
21360
|
+
</hh:borderFill>`;
|
|
21361
|
+
}
|
|
21362
|
+
function pageNumCtrl() {
|
|
21363
|
+
return `<hp:ctrl><hp:pageNum pos="BOTTOM_CENTER" formatType="DIGIT" sideChar="-"/></hp:ctrl>`;
|
|
21364
|
+
}
|
|
21365
|
+
function newPageNumCtrl(num4 = 1) {
|
|
21366
|
+
return `<hp:ctrl><hp:newNum num="${num4}" numType="PAGE"/></hp:ctrl>`;
|
|
21367
|
+
}
|
|
21368
|
+
function pageHidingCtrl(hideHeader = false) {
|
|
21369
|
+
return `<hp:ctrl><hp:pageHiding hideHeader="${hideHeader ? 1 : 0}" hideFooter="0" hideMasterPage="0" hideBorder="0" hideFill="0" hidePageNum="1"/></hp:ctrl>`;
|
|
21370
|
+
}
|
|
21161
21371
|
var CHAR_VARIANT_BASE = 11;
|
|
21372
|
+
function charVariantBase(measured) {
|
|
21373
|
+
return measured ? CHAR_VARIANT_BASE + GJ_CHAR_COUNT : CHAR_VARIANT_BASE;
|
|
21374
|
+
}
|
|
21162
21375
|
var GONGMUN_BODY_RATIO = 95;
|
|
21163
21376
|
|
|
21164
21377
|
// src/hwpx/md-runs.ts
|
|
@@ -21372,12 +21585,12 @@ function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
|
|
|
21372
21585
|
return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
|
|
21373
21586
|
}).join("");
|
|
21374
21587
|
}
|
|
21375
|
-
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId) {
|
|
21588
|
+
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId, styleId = 0) {
|
|
21376
21589
|
if (paraPrId === PARA_CODE) {
|
|
21377
21590
|
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
|
|
21378
21591
|
}
|
|
21379
21592
|
const runs = generateRuns(text, charPrId, mapCharId);
|
|
21380
|
-
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="
|
|
21593
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="${styleId}">${runs}</hp:p>`;
|
|
21381
21594
|
}
|
|
21382
21595
|
|
|
21383
21596
|
// src/hwpx/gen-header.ts
|
|
@@ -21405,6 +21618,7 @@ function generateManifest(chartParts = []) {
|
|
|
21405
21618
|
</opf:package>`;
|
|
21406
21619
|
}
|
|
21407
21620
|
function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls = []) {
|
|
21621
|
+
const measured = !!gongmun && usesReportFonts(gongmun.preset);
|
|
21408
21622
|
let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
|
|
21409
21623
|
if (gongmun) {
|
|
21410
21624
|
body = gongmun.bodyHeight;
|
|
@@ -21414,26 +21628,64 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
|
|
|
21414
21628
|
h3 = body;
|
|
21415
21629
|
h4 = Math.max(body - 100, 1300);
|
|
21416
21630
|
}
|
|
21631
|
+
const bodyFont = measured ? 4 : 0;
|
|
21632
|
+
const hFont = measured ? 3 : 1;
|
|
21633
|
+
const hBold = !measured;
|
|
21417
21634
|
const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
|
|
21418
21635
|
const rows = [
|
|
21419
|
-
charPr(0, body, false, false,
|
|
21420
|
-
charPr(1, body, true, false,
|
|
21421
|
-
charPr(2, body, false, true,
|
|
21422
|
-
charPr(3, body, true, true,
|
|
21636
|
+
charPr(0, body, false, false, bodyFont, theme.body, bodyRatio),
|
|
21637
|
+
charPr(1, body, true, false, bodyFont, theme.body, bodyRatio),
|
|
21638
|
+
charPr(2, body, false, true, bodyFont, theme.body, bodyRatio),
|
|
21639
|
+
charPr(3, body, true, true, bodyFont, theme.body, bodyRatio),
|
|
21423
21640
|
charPr(4, code, false, false, 1),
|
|
21424
|
-
charPr(5, h1,
|
|
21425
|
-
charPr(6, h2,
|
|
21426
|
-
charPr(7, h3,
|
|
21427
|
-
charPr(8, h4,
|
|
21428
|
-
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false,
|
|
21429
|
-
charPr(CHAR_QUOTE, body, false, true,
|
|
21641
|
+
charPr(5, h1, hBold, false, hFont, theme.h1),
|
|
21642
|
+
charPr(6, h2, hBold, false, hFont, theme.h2),
|
|
21643
|
+
charPr(7, h3, hBold, false, hFont, theme.h3),
|
|
21644
|
+
charPr(8, h4, hBold, false, hFont, theme.h4),
|
|
21645
|
+
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, bodyFont, theme.tableHeader),
|
|
21646
|
+
charPr(CHAR_QUOTE, body, false, true, bodyFont, theme.quote)
|
|
21430
21647
|
];
|
|
21648
|
+
if (measured) {
|
|
21649
|
+
const sz = gaejosikSizes(body, gongmun.sizes);
|
|
21650
|
+
rows.push(
|
|
21651
|
+
charPr(11, sz.dae, false, false, 3),
|
|
21652
|
+
// □ HY헤드라인M
|
|
21653
|
+
charPr(12, sz.dae, true, false, 3),
|
|
21654
|
+
// □ bold
|
|
21655
|
+
charPr(13, sz.cham, false, false, 5),
|
|
21656
|
+
// ※ 한양중고딕
|
|
21657
|
+
charPr(14, sz.cham, true, false, 5),
|
|
21658
|
+
// ※ bold
|
|
21659
|
+
charPr(15, sz.chapter, true, false, 4, "#FFFFFF"),
|
|
21660
|
+
// 장 로마숫자(흰)
|
|
21661
|
+
charPr(16, sz.chapter, false, false, 3),
|
|
21662
|
+
// 장 제목
|
|
21663
|
+
charPr(17, sz.coverTitle, false, false, 3),
|
|
21664
|
+
// 표지 제목
|
|
21665
|
+
charPr(18, sz.coverSub, false, false, 3),
|
|
21666
|
+
// 표지 날짜·기관명
|
|
21667
|
+
charPr(19, sz.tocLabel, true, false, 3),
|
|
21668
|
+
// 목 차
|
|
21669
|
+
charPr(20, sz.tocRoman, true, false, 6),
|
|
21670
|
+
// 목차 로마숫자(한양신명조)
|
|
21671
|
+
charPr(21, sz.tocItem, false, false, 3),
|
|
21672
|
+
// 목차 항목
|
|
21673
|
+
charPr(22, sz.table, false, false, 7),
|
|
21674
|
+
// 표 셀(맑은 고딕 12pt)
|
|
21675
|
+
charPr(23, sz.table, true, false, 7),
|
|
21676
|
+
// 표 셀 bold
|
|
21677
|
+
charPr(24, sz.bar, false, false, 4),
|
|
21678
|
+
// 표지 바 셀 빈 문단(6pt)
|
|
21679
|
+
charPr(25, sz.bodyTitle, false, false, 3)
|
|
21680
|
+
// 본문 제목박스(HY헤드라인M 22pt, 실측 GT3 표④)
|
|
21681
|
+
);
|
|
21682
|
+
}
|
|
21431
21683
|
for (const r of ratioVariants) {
|
|
21432
21684
|
rows.push(
|
|
21433
|
-
charPr(rows.length, body, false, false,
|
|
21434
|
-
charPr(rows.length + 1, body, true, false,
|
|
21435
|
-
charPr(rows.length + 2, body, false, true,
|
|
21436
|
-
charPr(rows.length + 3, body, true, true,
|
|
21685
|
+
charPr(rows.length, body, false, false, bodyFont, theme.body, r),
|
|
21686
|
+
charPr(rows.length + 1, body, true, false, bodyFont, theme.body, r),
|
|
21687
|
+
charPr(rows.length + 2, body, false, true, bodyFont, theme.body, r),
|
|
21688
|
+
charPr(rows.length + 3, body, true, true, bodyFont, theme.body, r)
|
|
21437
21689
|
);
|
|
21438
21690
|
}
|
|
21439
21691
|
rows.push(...extraCharPrXmls);
|
|
@@ -21444,14 +21696,14 @@ ${rows.join("\n")}
|
|
|
21444
21696
|
function buildParaProperties(gongmun) {
|
|
21445
21697
|
if (!gongmun) {
|
|
21446
21698
|
const base2 = [
|
|
21447
|
-
paraPr(0),
|
|
21448
|
-
paraPr(1, { align: "LEFT", spaceBefore: 800, spaceAfter: 200, lineSpacing: 180, outlineLevel: 0 }),
|
|
21449
|
-
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: 170, outlineLevel: 1 }),
|
|
21450
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: 160, outlineLevel: 2 }),
|
|
21451
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160, outlineLevel: 3 }),
|
|
21452
|
-
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400 }),
|
|
21453
|
-
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600 }),
|
|
21454
|
-
paraPr(7, { align: "LEFT", lineSpacing: 160, indent: 600 })
|
|
21699
|
+
paraPr(0, { keepWord: true }),
|
|
21700
|
+
paraPr(1, { align: "LEFT", spaceBefore: 800, spaceAfter: 200, lineSpacing: 180, outlineLevel: 0, keepWord: true }),
|
|
21701
|
+
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: 170, outlineLevel: 1, keepWord: true }),
|
|
21702
|
+
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: 160, outlineLevel: 2, keepWord: true }),
|
|
21703
|
+
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160, outlineLevel: 3, keepWord: true }),
|
|
21704
|
+
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
21705
|
+
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600, keepWord: true }),
|
|
21706
|
+
paraPr(7, { align: "LEFT", lineSpacing: 160, indent: 600, keepWord: true })
|
|
21455
21707
|
];
|
|
21456
21708
|
return `<hh:paraProperties itemCnt="${base2.length}">
|
|
21457
21709
|
${base2.join("\n")}
|
|
@@ -21459,22 +21711,45 @@ ${base2.join("\n")}
|
|
|
21459
21711
|
}
|
|
21460
21712
|
const ls = gongmun.lineSpacing;
|
|
21461
21713
|
const titleAlign = gongmun.centerTitle ? "CENTER" : "LEFT";
|
|
21714
|
+
const h2Geom = gongmun.h2Marker !== "none" ? { spaceBefore: Math.round(gongmun.bodyHeight * 2), spaceAfter: 0, indent: -markerWidth(gongmun.h2Marker === "box" ? "\u25A1" : "1.", 1600) } : { spaceBefore: 600, spaceAfter: 150 };
|
|
21462
21715
|
const base = [
|
|
21463
21716
|
paraPr(0, { lineSpacing: ls, keepWord: true }),
|
|
21464
|
-
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true
|
|
21465
|
-
paraPr(2, { align: "LEFT",
|
|
21466
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true
|
|
21467
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true
|
|
21717
|
+
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true }),
|
|
21718
|
+
paraPr(2, { align: "LEFT", ...h2Geom, lineSpacing: ls, keepWord: true }),
|
|
21719
|
+
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
21720
|
+
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
21468
21721
|
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
21469
21722
|
paraPr(6, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true }),
|
|
21470
21723
|
paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
|
|
21471
21724
|
];
|
|
21472
21725
|
for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
|
|
21473
|
-
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering);
|
|
21474
|
-
const sectionGap = gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
21475
|
-
|
|
21726
|
+
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes);
|
|
21727
|
+
const sectionGap = gongmun.numbering === "gaejosik" ? gaejosikSpaceBefore(d, gongmun.bodyHeight) : gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
21728
|
+
const keepNext = gongmun.numbering === "gaejosik" && d === 0;
|
|
21729
|
+
base.push(paraPr(GONGMUN_LIST_BASE + d, { align: "JUSTIFY", lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext }));
|
|
21476
21730
|
}
|
|
21477
21731
|
base.push(paraPr(GONGMUN_CENTER, { align: "CENTER", lineSpacing: ls, keepWord: true }));
|
|
21732
|
+
base.push(paraPr(GONGMUN_RIGHT, { align: "RIGHT", lineSpacing: ls, keepWord: true }));
|
|
21733
|
+
base.push(paraPr(GONGMUN_TBL_CENTER, { align: "CENTER", lineSpacing: 130, keepWord: true }));
|
|
21734
|
+
base.push(paraPr(GONGMUN_TBL_LEFT, { align: "LEFT", lineSpacing: 130, keepWord: true }));
|
|
21735
|
+
if (gongmun.preset === "gaejosik") {
|
|
21736
|
+
const cham = gaejosikChamIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
21737
|
+
const toc = gaejosikTocItemIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
21738
|
+
base.push(
|
|
21739
|
+
paraPr(GJ_PARA_CHAM, { align: "JUSTIFY", lineSpacing: ls, left: cham.left, indent: cham.indent, spaceBefore: gaejosikSpaceBefore(3, gongmun.bodyHeight), keepWord: true }),
|
|
21740
|
+
paraPr(GJ_PARA_COVER, { align: "CENTER", lineSpacing: 130, keepWord: true }),
|
|
21741
|
+
paraPr(GJ_PARA_TOC_ITEM, { align: "LEFT", lineSpacing: 160, left: toc.left, indent: toc.indent, spaceBefore: 1800, keepWord: true }),
|
|
21742
|
+
// 장 헤더는 다음 문단과 같은 쪽에 — 쪽 하단 고아 헤더 방지 (실렌더 확인 이슈)
|
|
21743
|
+
paraPr(GJ_PARA_CHAPTER, { align: "LEFT", lineSpacing: ls, spaceBefore: 2400, spaceAfter: 600, keepWord: true, keepWithNext: true }),
|
|
21744
|
+
// 표지 장식 바 셀 빈 문단 — 저줄간격(실측 71%)으로 바 높이 818 안에 수납
|
|
21745
|
+
paraPr(GJ_PARA_BAR, { align: "CENTER", lineSpacing: 70, keepWord: true })
|
|
21746
|
+
);
|
|
21747
|
+
} else if (usesReportFonts(gongmun.preset)) {
|
|
21748
|
+
const cham = gaejosikChamIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
21749
|
+
base.push(
|
|
21750
|
+
paraPr(GJ_PARA_CHAM, { align: "JUSTIFY", lineSpacing: ls, left: cham.left, indent: cham.indent, spaceBefore: gaejosikSpaceBefore(3, gongmun.bodyHeight), keepWord: true })
|
|
21751
|
+
);
|
|
21752
|
+
}
|
|
21478
21753
|
return `<hh:paraProperties itemCnt="${base.length}">
|
|
21479
21754
|
${base.join("\n")}
|
|
21480
21755
|
</hh:paraProperties>`;
|
|
@@ -21490,25 +21765,38 @@ ${heads}
|
|
|
21490
21765
|
</hh:numbering>
|
|
21491
21766
|
</hh:numberings>`;
|
|
21492
21767
|
}
|
|
21493
|
-
function
|
|
21494
|
-
|
|
21495
|
-
|
|
21496
|
-
|
|
21497
|
-
|
|
21498
|
-
|
|
21499
|
-
|
|
21500
|
-
|
|
21501
|
-
|
|
21768
|
+
function fontEntry(id, face, weight = 6) {
|
|
21769
|
+
return ` <hh:font id="${id}" face="${face}" type="TTF" isEmbedded="0">
|
|
21770
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="${weight}" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21771
|
+
</hh:font>`;
|
|
21772
|
+
}
|
|
21773
|
+
function buildFontFaces(gongmun, bodyFace) {
|
|
21774
|
+
if (gongmun && usesReportFonts(gongmun.preset)) {
|
|
21775
|
+
const ov = gongmun.fonts;
|
|
21776
|
+
const bodyDefault = gongmun.preset !== "gaejosik" && gongmun.bodyFont === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD734\uBA3C\uBA85\uC870";
|
|
21777
|
+
const faces = [
|
|
21778
|
+
"\uD568\uCD08\uB86C\uBC14\uD0D5",
|
|
21779
|
+
"\uD568\uCD08\uB86C\uB3CB\uC6C0",
|
|
21780
|
+
"HY\uACAC\uACE0\uB515",
|
|
21781
|
+
ov.heading ?? "HY\uD5E4\uB4DC\uB77C\uC778M",
|
|
21782
|
+
ov.body ?? bodyDefault,
|
|
21783
|
+
ov.ref ?? "\uD55C\uC591\uC911\uACE0\uB515",
|
|
21784
|
+
"\uD55C\uC591\uC2E0\uBA85\uC870",
|
|
21785
|
+
ov.table ?? "\uB9D1\uC740 \uACE0\uB515"
|
|
21786
|
+
];
|
|
21787
|
+
const list = faces.map((f, i) => fontEntry(i, f, i === 2 || i === 3 ? 9 : 6)).join("\n");
|
|
21788
|
+
const langs = ["HANGUL", "LATIN", "HANJA", "JAPANESE", "OTHER", "SYMBOL", "USER"];
|
|
21789
|
+
return `<hh:fontfaces itemCnt="${langs.length}">
|
|
21790
|
+
` + langs.map((l) => ` <hh:fontface lang="${l}" fontCnt="${faces.length}">
|
|
21791
|
+
${list}
|
|
21792
|
+
</hh:fontface>`).join("\n") + `
|
|
21793
|
+
</hh:fontfaces>`;
|
|
21794
|
+
}
|
|
21795
|
+
return `<hh:fontfaces itemCnt="7">
|
|
21502
21796
|
<hh:fontface lang="HANGUL" fontCnt="3">
|
|
21503
|
-
|
|
21504
|
-
|
|
21505
|
-
|
|
21506
|
-
<hh:font id="1" face="\uD568\uCD08\uB86C\uB3CB\uC6C0" type="TTF" isEmbedded="0">
|
|
21507
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21508
|
-
</hh:font>
|
|
21509
|
-
<hh:font id="2" face="HY\uACAC\uACE0\uB515" type="TTF" isEmbedded="0">
|
|
21510
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="9" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21511
|
-
</hh:font>
|
|
21797
|
+
${fontEntry(0, bodyFace)}
|
|
21798
|
+
${fontEntry(1, "\uD568\uCD08\uB86C\uB3CB\uC6C0")}
|
|
21799
|
+
${fontEntry(2, "HY\uACAC\uACE0\uB515", 9)}
|
|
21512
21800
|
</hh:fontface>
|
|
21513
21801
|
<hh:fontface lang="LATIN" fontCnt="3">
|
|
21514
21802
|
<hh:font id="0" face="Times New Roman" type="TTF" isEmbedded="0">
|
|
@@ -21522,57 +21810,87 @@ function generateHeaderXml(theme, gongmun, ratioVariants = [], remap = null) {
|
|
|
21522
21810
|
</hh:font>
|
|
21523
21811
|
</hh:fontface>
|
|
21524
21812
|
<hh:fontface lang="HANJA" fontCnt="1">
|
|
21525
|
-
|
|
21526
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21527
|
-
</hh:font>
|
|
21813
|
+
${fontEntry(0, "\uD568\uCD08\uB86C\uBC14\uD0D5")}
|
|
21528
21814
|
</hh:fontface>
|
|
21529
21815
|
<hh:fontface lang="JAPANESE" fontCnt="1">
|
|
21530
|
-
|
|
21531
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21532
|
-
</hh:font>
|
|
21816
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
21533
21817
|
</hh:fontface>
|
|
21534
21818
|
<hh:fontface lang="OTHER" fontCnt="1">
|
|
21535
|
-
|
|
21536
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21537
|
-
</hh:font>
|
|
21819
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
21538
21820
|
</hh:fontface>
|
|
21539
21821
|
<hh:fontface lang="SYMBOL" fontCnt="1">
|
|
21540
|
-
|
|
21541
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21542
|
-
</hh:font>
|
|
21822
|
+
${fontEntry(0, "Symbol")}
|
|
21543
21823
|
</hh:fontface>
|
|
21544
21824
|
<hh:fontface lang="USER" fontCnt="1">
|
|
21545
|
-
|
|
21546
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21547
|
-
</hh:font>
|
|
21825
|
+
${fontEntry(0, "\uAD74\uB9BC")}
|
|
21548
21826
|
</hh:fontface>
|
|
21549
|
-
</hh:fontfaces
|
|
21550
|
-
|
|
21551
|
-
|
|
21552
|
-
|
|
21553
|
-
|
|
21554
|
-
|
|
21555
|
-
|
|
21556
|
-
|
|
21557
|
-
|
|
21558
|
-
|
|
21559
|
-
|
|
21560
|
-
|
|
21561
|
-
|
|
21562
|
-
|
|
21563
|
-
|
|
21564
|
-
|
|
21565
|
-
|
|
21566
|
-
|
|
21567
|
-
|
|
21827
|
+
</hh:fontfaces>`;
|
|
21828
|
+
}
|
|
21829
|
+
function buildBorderFills(gongmun, extra = []) {
|
|
21830
|
+
const thin = ["0.12 mm", "#000000"];
|
|
21831
|
+
const items = [
|
|
21832
|
+
borderFillEntry(1, {}),
|
|
21833
|
+
borderFillEntry(2, { l: thin, r: thin, t: thin, b: thin })
|
|
21834
|
+
];
|
|
21835
|
+
if (gongmun?.preset === "gaejosik") {
|
|
21836
|
+
const c = GAEJOSIK_COLORS;
|
|
21837
|
+
const edge = ["0.12 mm", c.border];
|
|
21838
|
+
const grayLine = ["0.1 mm", c.titleLine];
|
|
21839
|
+
const tocEdge = ["0.4 mm", c.tocBorder];
|
|
21840
|
+
items.push(
|
|
21841
|
+
borderFillEntry(3, { l: edge, r: edge, t: edge, b: edge }, c.primary),
|
|
21842
|
+
// 장 로마숫자 셀
|
|
21843
|
+
borderFillEntry(4, { l: edge }),
|
|
21844
|
+
// 장 간격 셀(좌선)
|
|
21845
|
+
borderFillEntry(5, { t: grayLine, b: grayLine }, c.titleFill),
|
|
21846
|
+
// 장 제목 셀
|
|
21847
|
+
borderFillEntry(6, {}, c.primary),
|
|
21848
|
+
// 표지 진한 바
|
|
21849
|
+
borderFillEntry(7, {}, c.accent),
|
|
21850
|
+
// 표지 연한 바
|
|
21851
|
+
borderFillEntry(8, { l: tocEdge, r: tocEdge, t: tocEdge, b: tocEdge }),
|
|
21852
|
+
// 목차 박스
|
|
21853
|
+
borderFillEntry(9, {}, c.tocStripe)
|
|
21854
|
+
// 목차 배너 라벤더 스트라이프
|
|
21855
|
+
);
|
|
21856
|
+
}
|
|
21857
|
+
if (gongmun) {
|
|
21858
|
+
items.push(borderFillEntry(items.length + 1, { l: thin, r: thin, t: thin, b: thin }, "#E6E6E6"));
|
|
21859
|
+
}
|
|
21860
|
+
items.push(...extra);
|
|
21861
|
+
return `<hh:borderFills itemCnt="${items.length}">
|
|
21862
|
+
${items.join("\n")}
|
|
21863
|
+
</hh:borderFills>`;
|
|
21864
|
+
}
|
|
21865
|
+
function buildStyles(gongmun) {
|
|
21866
|
+
const items = [
|
|
21867
|
+
`<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>`
|
|
21868
|
+
];
|
|
21869
|
+
if (gongmun) {
|
|
21870
|
+
for (let lvl = 1; lvl <= 4; lvl++) {
|
|
21871
|
+
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"/>`);
|
|
21872
|
+
}
|
|
21873
|
+
}
|
|
21874
|
+
return `<hh:styles itemCnt="${items.length}">
|
|
21875
|
+
${items.join("\n ")}
|
|
21876
|
+
</hh:styles>`;
|
|
21877
|
+
}
|
|
21878
|
+
function generateHeaderXml(theme, gongmun, ratioVariants = [], extraBorderFills = [], extraCharPrXmls = []) {
|
|
21879
|
+
const bodyFace = gongmun?.fonts.body ?? (gongmun?.bodyFont === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5");
|
|
21880
|
+
const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants, extraCharPrXmls);
|
|
21881
|
+
const paraPropsXml = buildParaProperties(gongmun);
|
|
21882
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
|
21883
|
+
<hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" xmlns:hc="${NS_CORE}" version="1.4" secCnt="1">
|
|
21884
|
+
<hh:beginNum page="1" footnote="1" endnote="1" pic="1" tbl="1" equation="1"/>
|
|
21885
|
+
<hh:refList>
|
|
21886
|
+
${buildFontFaces(gongmun, bodyFace)}
|
|
21887
|
+
${buildBorderFills(gongmun, extraBorderFills)}
|
|
21568
21888
|
${charPropsXml}
|
|
21569
21889
|
<hh:tabProperties itemCnt="0"/>
|
|
21570
21890
|
${buildNumberings()}
|
|
21571
21891
|
<hh:bullets itemCnt="0"/>
|
|
21572
21892
|
${paraPropsXml}
|
|
21573
|
-
|
|
21574
|
-
<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>
|
|
21575
|
-
</hh:styles>
|
|
21893
|
+
${buildStyles(gongmun)}
|
|
21576
21894
|
</hh:refList>
|
|
21577
21895
|
<hh:compatibleDocument targetProgram="HWP2018"><hh:layoutCompatibility/></hh:compatibleDocument>
|
|
21578
21896
|
</hh:head>`;
|
|
@@ -21808,6 +22126,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
21808
22126
|
let contW;
|
|
21809
22127
|
if (block.type === "list_item" && gongmunList.has(i)) {
|
|
21810
22128
|
const { marker, depth } = gongmunList.get(i);
|
|
22129
|
+
if (gongmun.numbering === "gaejosik" && (depth === 0 || (block.text || "").trimStart().startsWith("\u203B"))) continue;
|
|
21811
22130
|
const content = plainRenderText(block.text || "");
|
|
21812
22131
|
text = marker ? `${marker} ${content}` : content;
|
|
21813
22132
|
const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
|
|
@@ -21816,6 +22135,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
21816
22135
|
} else if (block.type === "paragraph") {
|
|
21817
22136
|
const raw = (block.text || "").trim();
|
|
21818
22137
|
if (/^<center>[\s\S]*<\/center>$/i.test(raw)) continue;
|
|
22138
|
+
if (gongmun.numbering === "gaejosik" && raw.startsWith("\u203B")) continue;
|
|
21819
22139
|
text = plainRenderText(raw);
|
|
21820
22140
|
firstW = contW = pageW;
|
|
21821
22141
|
} else {
|
|
@@ -21829,14 +22149,15 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
21829
22149
|
}
|
|
21830
22150
|
return ratioByBlock.size > 0 ? { ratioByBlock, variants } : null;
|
|
21831
22151
|
}
|
|
21832
|
-
function variantMapper(fit, blockIdx) {
|
|
22152
|
+
function variantMapper(fit, blockIdx, base = CHAR_VARIANT_BASE) {
|
|
21833
22153
|
const r = fit.ratioByBlock.get(blockIdx);
|
|
21834
22154
|
if (r === void 0) return void 0;
|
|
21835
22155
|
const vi = fit.variants.indexOf(r);
|
|
21836
|
-
return (id) => id >= 0 && id <= 3 ?
|
|
22156
|
+
return (id) => id >= 0 && id <= 3 ? base + vi * 4 + id : id;
|
|
21837
22157
|
}
|
|
21838
22158
|
function precomputeGongmunList(blocks, gongmun) {
|
|
21839
22159
|
const result = /* @__PURE__ */ new Map();
|
|
22160
|
+
const depthOffset = gongmun.numbering === "gaejosik" && blocks.some((b) => b.type === "heading" && b.level === 3) ? 1 : 0;
|
|
21840
22161
|
let i = 0;
|
|
21841
22162
|
while (i < blocks.length) {
|
|
21842
22163
|
if (blocks[i].type !== "list_item") {
|
|
@@ -21862,7 +22183,7 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
21862
22183
|
}
|
|
21863
22184
|
break;
|
|
21864
22185
|
}
|
|
21865
|
-
const depths = run.map((bi) => Math.min(Math.max(blocks[bi].indent || 0, 0), GONGMUN_LIST_LEVELS - 1));
|
|
22186
|
+
const depths = run.map((bi) => Math.min(Math.max((blocks[bi].indent || 0) + depthOffset, 0), GONGMUN_LIST_LEVELS - 1));
|
|
21866
22187
|
const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
|
|
21867
22188
|
const numberer = new GongmunNumberer(gongmun.numbering);
|
|
21868
22189
|
run.forEach((bi, k) => {
|
|
@@ -21873,6 +22194,98 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
21873
22194
|
return result;
|
|
21874
22195
|
}
|
|
21875
22196
|
|
|
22197
|
+
// src/hwpx/gen-gaejosik.ts
|
|
22198
|
+
function chapterRoman(n) {
|
|
22199
|
+
if (n >= 1 && n <= 12) return String.fromCodePoint(8543 + n);
|
|
22200
|
+
const t = [[10, "\u2169"], [9, "\u2168"], [5, "\u2164"], [4, "\u2163"], [1, "\u2160"]];
|
|
22201
|
+
let s = "";
|
|
22202
|
+
for (const [v, r] of t) while (n >= v) {
|
|
22203
|
+
s += r;
|
|
22204
|
+
n -= v;
|
|
22205
|
+
}
|
|
22206
|
+
return s;
|
|
22207
|
+
}
|
|
22208
|
+
function emptyPara(paraPrId = PARA_NORMAL, pageBreak = false, charPrId = CHAR_NORMAL) {
|
|
22209
|
+
const brk = pageBreak ? ` pageBreak="1"` : "";
|
|
22210
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"${brk}><hp:run charPrIDRef="${charPrId}"><hp:t></hp:t></hp:run></hp:p>`;
|
|
22211
|
+
}
|
|
22212
|
+
var gjTableId = 92e5;
|
|
22213
|
+
function cell(opts) {
|
|
22214
|
+
const paras = opts.paras ?? emptyPara();
|
|
22215
|
+
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>`;
|
|
22216
|
+
}
|
|
22217
|
+
function table(rows, w, h, cols, tblBf = 1) {
|
|
22218
|
+
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>`;
|
|
22219
|
+
}
|
|
22220
|
+
function buildGaejosikCover(title, gongmun) {
|
|
22221
|
+
const g = coverGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
22222
|
+
const sz = gaejosikSizes(gongmun.bodyHeight, gongmun.sizes);
|
|
22223
|
+
const innerW = g.totalW - 282;
|
|
22224
|
+
const titleCharPr = simulateWrap(title, innerW, innerW, sz.coverTitle, 100, "keep").lines > 2 ? GJ_CHAR_COVER_SUB : GJ_CHAR_COVER_TITLE;
|
|
22225
|
+
const titlePara = `<hp:p paraPrIDRef="${GJ_PARA_COVER}" styleIDRef="0"><hp:run charPrIDRef="${titleCharPr}"><hp:t>${escapeXml(title)}</hp:t></hp:run></hp:p>`;
|
|
22226
|
+
const barEmpty = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
22227
|
+
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 });
|
|
22228
|
+
const titleRow = cell({ bf: 1, col: 0, colSpan: 3, row: 1, w: g.totalW, h: g.titleH, paras: titlePara });
|
|
22229
|
+
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 });
|
|
22230
|
+
const tbl2 = table([topRow, titleRow, botRow], g.totalW, g.barH + g.titleH + g.botBarH, 3);
|
|
22231
|
+
const host = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${tbl2}</hp:run></hp:p>`;
|
|
22232
|
+
const date = gongmun.cover?.date ?? formatGaejosikDate(/* @__PURE__ */ new Date());
|
|
22233
|
+
const org = gongmun.cover?.org ?? "";
|
|
22234
|
+
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>`;
|
|
22235
|
+
const subEmpty = emptyPara(GJ_PARA_COVER, false, GJ_CHAR_COVER_SUB);
|
|
22236
|
+
return [
|
|
22237
|
+
...Array(5).fill(emptyPara()),
|
|
22238
|
+
host,
|
|
22239
|
+
...Array(5).fill(emptyPara()),
|
|
22240
|
+
sub(date),
|
|
22241
|
+
...org ? [...Array(4).fill(subEmpty), sub(org)] : []
|
|
22242
|
+
];
|
|
22243
|
+
}
|
|
22244
|
+
function buildTocBanner(gongmun) {
|
|
22245
|
+
const g = tocBannerGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
22246
|
+
const bfs = [GJ_BF_BAR_DARK, 1, GJ_BF_TOC_STRIPE, 1, GJ_BF_TOC_STRIPE, 1, GJ_BF_BAR_DARK];
|
|
22247
|
+
const filler = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
22248
|
+
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>`;
|
|
22249
|
+
const row = g.colWs.map(
|
|
22250
|
+
(w, c) => cell({ bf: bfs[c], col: c, w, h: g.h, paras: c === 3 ? label : filler })
|
|
22251
|
+
).join("");
|
|
22252
|
+
const banner = table([row], g.colWs.reduce((a, b) => a + b, 0), g.h, 7, 2);
|
|
22253
|
+
return `<hp:p paraPrIDRef="${GJ_PARA_BAR}" styleIDRef="0" pageBreak="1"><hp:run charPrIDRef="${CHAR_NORMAL}">${banner}</hp:run></hp:p>`;
|
|
22254
|
+
}
|
|
22255
|
+
function buildGaejosikToc(chapters, gongmun) {
|
|
22256
|
+
const label = buildTocBanner(gongmun);
|
|
22257
|
+
const items = chapters.map(
|
|
22258
|
+
(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>`
|
|
22259
|
+
).join("");
|
|
22260
|
+
const box = table(
|
|
22261
|
+
[cell({ bf: GJ_BF_TOC_BOX, col: 0, w: TOC_GEOM.boxW, h: TOC_GEOM.boxH, paras: items })],
|
|
22262
|
+
TOC_GEOM.boxW,
|
|
22263
|
+
TOC_GEOM.boxH,
|
|
22264
|
+
1
|
|
22265
|
+
);
|
|
22266
|
+
const host = `<hp:p paraPrIDRef="${GJ_PARA_BAR}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${box}</hp:run></hp:p>`;
|
|
22267
|
+
return [label, emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR), host];
|
|
22268
|
+
}
|
|
22269
|
+
function buildGaejosikBodyTitle(title, gongmun) {
|
|
22270
|
+
const g = COVER_GEOM;
|
|
22271
|
+
const bt = bodyTitleGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
22272
|
+
const barEmpty = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
|
|
22273
|
+
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>`;
|
|
22274
|
+
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 });
|
|
22275
|
+
const titleRow = cell({ bf: 1, col: 0, colSpan: 3, row: 1, w: g.totalW, h: bt.titleH, paras: titlePara });
|
|
22276
|
+
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 });
|
|
22277
|
+
const box = table([topRow, titleRow, botRow], g.totalW, bt.barH * 2 + bt.titleH, 3);
|
|
22278
|
+
return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${box}</hp:run></hp:p>`;
|
|
22279
|
+
}
|
|
22280
|
+
function buildGaejosikChapter(n, title, gongmun) {
|
|
22281
|
+
const g = gongmun ? chapterGeom(gongmun.bodyHeight, gongmun.sizes) : chapterGeom(1500);
|
|
22282
|
+
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>`;
|
|
22283
|
+
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>`;
|
|
22284
|
+
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 });
|
|
22285
|
+
const tbl2 = table([row], g.numW + g.gapW + g.titleW, g.rowH, 3);
|
|
22286
|
+
return `<hp:p paraPrIDRef="${GJ_PARA_CHAPTER}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${tbl2}</hp:run></hp:p>`;
|
|
22287
|
+
}
|
|
22288
|
+
|
|
21876
22289
|
// src/diff/text-diff.ts
|
|
21877
22290
|
function similarity(a, b) {
|
|
21878
22291
|
if (a === b) return 1;
|
|
@@ -22070,8 +22483,8 @@ function summarize(text) {
|
|
|
22070
22483
|
const t = text.replace(/\s+/g, " ").trim();
|
|
22071
22484
|
return t.length > 80 ? t.slice(0, 77) + "..." : t;
|
|
22072
22485
|
}
|
|
22073
|
-
function replicateGfmTable(
|
|
22074
|
-
const { cells, rows: numRows, cols: numCols } =
|
|
22486
|
+
function replicateGfmTable(table2) {
|
|
22487
|
+
const { cells, rows: numRows, cols: numCols } = table2;
|
|
22075
22488
|
if (numRows === 0 || numCols === 0) return null;
|
|
22076
22489
|
if (numRows === 1 && numCols === 1) return null;
|
|
22077
22490
|
if (numCols === 1) return null;
|
|
@@ -22080,28 +22493,28 @@ function replicateGfmTable(table) {
|
|
|
22080
22493
|
for (let r = 0; r < numRows; r++) {
|
|
22081
22494
|
for (let c = 0; c < numCols; c++) {
|
|
22082
22495
|
if (skip.has(`${r},${c}`)) continue;
|
|
22083
|
-
const
|
|
22084
|
-
if (!
|
|
22496
|
+
const cell2 = cells[r]?.[c];
|
|
22497
|
+
if (!cell2) continue;
|
|
22085
22498
|
display[r][c] = {
|
|
22086
|
-
text: escapeGfm(sanitizeText(
|
|
22499
|
+
text: escapeGfm(sanitizeText(cell2.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
|
|
22087
22500
|
gridR: r,
|
|
22088
22501
|
gridC: c
|
|
22089
22502
|
};
|
|
22090
|
-
for (let dr = 0; dr <
|
|
22091
|
-
for (let dc = 0; dc <
|
|
22503
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
22504
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
22092
22505
|
if (dr === 0 && dc === 0) continue;
|
|
22093
22506
|
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
22094
22507
|
}
|
|
22095
22508
|
}
|
|
22096
|
-
c +=
|
|
22509
|
+
c += cell2.colSpan - 1;
|
|
22097
22510
|
}
|
|
22098
22511
|
}
|
|
22099
22512
|
const uniqueRows = [];
|
|
22100
22513
|
let pendingLabelRow = null;
|
|
22101
22514
|
for (let r = 0; r < display.length; r++) {
|
|
22102
22515
|
const row = display[r];
|
|
22103
|
-
if (row.every((
|
|
22104
|
-
const nonEmptyCols = row.filter((
|
|
22516
|
+
if (row.every((cell2) => cell2.text === "")) continue;
|
|
22517
|
+
const nonEmptyCols = row.filter((cell2) => cell2.text !== "");
|
|
22105
22518
|
const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
|
|
22106
22519
|
if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
|
|
22107
22520
|
if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
|
|
@@ -22133,9 +22546,9 @@ function parseGfmTable(lines) {
|
|
|
22133
22546
|
function unescapeGfmCell(text) {
|
|
22134
22547
|
return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\([~*])/g, "$1");
|
|
22135
22548
|
}
|
|
22136
|
-
function replicateCellInnerHtml(
|
|
22137
|
-
if (
|
|
22138
|
-
return
|
|
22549
|
+
function replicateCellInnerHtml(cell2) {
|
|
22550
|
+
if (cell2.blocks?.length) {
|
|
22551
|
+
return cell2.blocks.map((b) => {
|
|
22139
22552
|
if (b.type === "table" && b.table) {
|
|
22140
22553
|
const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
|
|
22141
22554
|
return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
|
|
@@ -22145,27 +22558,27 @@ function replicateCellInnerHtml(cell) {
|
|
|
22145
22558
|
return t ? t.replace(/\n/g, "<br>") : "";
|
|
22146
22559
|
}).filter(Boolean).join("<br>");
|
|
22147
22560
|
}
|
|
22148
|
-
return sanitizeText(
|
|
22561
|
+
return sanitizeText(cell2.text).replace(/\n/g, "<br>");
|
|
22149
22562
|
}
|
|
22150
|
-
function replicateTableToHtml(
|
|
22151
|
-
const rows = replicateHtmlTable(
|
|
22563
|
+
function replicateTableToHtml(table2) {
|
|
22564
|
+
const rows = replicateHtmlTable(table2);
|
|
22152
22565
|
const lines = ["<table>"];
|
|
22153
22566
|
for (let r = 0; r < rows.length; r++) {
|
|
22154
22567
|
const tag = rows[r].tag;
|
|
22155
|
-
const rowHtml = rows[r].cells.map((
|
|
22568
|
+
const rowHtml = rows[r].cells.map((cell2) => {
|
|
22156
22569
|
const attrs = [];
|
|
22157
|
-
if (
|
|
22158
|
-
if (
|
|
22570
|
+
if (cell2.colSpan > 1) attrs.push(`colspan="${cell2.colSpan}"`);
|
|
22571
|
+
if (cell2.rowSpan > 1) attrs.push(`rowspan="${cell2.rowSpan}"`);
|
|
22159
22572
|
const attrStr = attrs.length ? " " + attrs.join(" ") : "";
|
|
22160
|
-
return `<${tag}${attrStr}>${
|
|
22573
|
+
return `<${tag}${attrStr}>${cell2.inner}</${tag}>`;
|
|
22161
22574
|
});
|
|
22162
22575
|
if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
|
|
22163
22576
|
}
|
|
22164
22577
|
lines.push("</table>");
|
|
22165
22578
|
return lines.join("\n");
|
|
22166
22579
|
}
|
|
22167
|
-
function replicateHtmlTable(
|
|
22168
|
-
const { cells, rows: numRows, cols: numCols } =
|
|
22580
|
+
function replicateHtmlTable(table2) {
|
|
22581
|
+
const { cells, rows: numRows, cols: numCols } = table2;
|
|
22169
22582
|
const skip = /* @__PURE__ */ new Set();
|
|
22170
22583
|
const result = [];
|
|
22171
22584
|
for (let r = 0; r < numRows; r++) {
|
|
@@ -22173,18 +22586,18 @@ function replicateHtmlTable(table) {
|
|
|
22173
22586
|
const rowCells = [];
|
|
22174
22587
|
for (let c = 0; c < numCols; c++) {
|
|
22175
22588
|
if (skip.has(`${r},${c}`)) continue;
|
|
22176
|
-
const
|
|
22177
|
-
if (!
|
|
22178
|
-
for (let dr = 0; dr <
|
|
22179
|
-
for (let dc = 0; dc <
|
|
22589
|
+
const cell2 = cells[r]?.[c];
|
|
22590
|
+
if (!cell2) continue;
|
|
22591
|
+
for (let dr = 0; dr < cell2.rowSpan; dr++) {
|
|
22592
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
22180
22593
|
if (dr === 0 && dc === 0) continue;
|
|
22181
22594
|
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
22182
22595
|
}
|
|
22183
22596
|
}
|
|
22184
22597
|
rowCells.push({
|
|
22185
|
-
inner: replicateCellInnerHtml(
|
|
22186
|
-
colSpan:
|
|
22187
|
-
rowSpan:
|
|
22598
|
+
inner: replicateCellInnerHtml(cell2),
|
|
22599
|
+
colSpan: cell2.colSpan,
|
|
22600
|
+
rowSpan: cell2.rowSpan,
|
|
22188
22601
|
gridR: r,
|
|
22189
22602
|
gridC: c
|
|
22190
22603
|
});
|
|
@@ -22289,6 +22702,54 @@ function removeNestedTables(html) {
|
|
|
22289
22702
|
return result;
|
|
22290
22703
|
}
|
|
22291
22704
|
|
|
22705
|
+
// src/hwpx/gen-table-bf.ts
|
|
22706
|
+
var THIN = ["0.12 mm", "#000000"];
|
|
22707
|
+
var THICK = ["0.4 mm", "#000000"];
|
|
22708
|
+
var DOUBLE = ["0.5 mm", "#000000", "DOUBLE_SLIM"];
|
|
22709
|
+
var EDGE = { thin: THIN, thick: THICK, double: DOUBLE };
|
|
22710
|
+
function sideOf(kind) {
|
|
22711
|
+
return kind === "none" ? void 0 : EDGE[kind];
|
|
22712
|
+
}
|
|
22713
|
+
var TableBfRegistry = class {
|
|
22714
|
+
constructor(nextId) {
|
|
22715
|
+
this.nextId = nextId;
|
|
22716
|
+
}
|
|
22717
|
+
map = /* @__PURE__ */ new Map();
|
|
22718
|
+
xmls = [];
|
|
22719
|
+
get(spec) {
|
|
22720
|
+
const key = `${spec.t}|${spec.b}|${spec.l}|${spec.r}|${typeof spec.fill === "string" ? spec.fill : spec.fill ? spec.fill.gradient.join("-") : ""}`;
|
|
22721
|
+
const hit = this.map.get(key);
|
|
22722
|
+
if (hit !== void 0) return hit;
|
|
22723
|
+
const id = this.nextId++;
|
|
22724
|
+
this.map.set(key, id);
|
|
22725
|
+
this.xmls.push(
|
|
22726
|
+
borderFillEntry(id, { t: sideOf(spec.t), b: sideOf(spec.b), l: sideOf(spec.l), r: sideOf(spec.r) }, spec.fill)
|
|
22727
|
+
);
|
|
22728
|
+
return id;
|
|
22729
|
+
}
|
|
22730
|
+
/** 등록된 borderFill XML 목록 (등록 순서 = id 순서) */
|
|
22731
|
+
emit() {
|
|
22732
|
+
return this.xmls;
|
|
22733
|
+
}
|
|
22734
|
+
get count() {
|
|
22735
|
+
return this.xmls.length;
|
|
22736
|
+
}
|
|
22737
|
+
};
|
|
22738
|
+
function dataCellSpec(opts) {
|
|
22739
|
+
const { row, rowEnd, col, colEnd, rowCnt, colCnt, headerRows, fill } = opts;
|
|
22740
|
+
const isTop = row === 0;
|
|
22741
|
+
const isBottom = rowEnd === rowCnt - 1;
|
|
22742
|
+
const isHeaderBottom = headerRows > 0 && rowEnd === headerRows - 1;
|
|
22743
|
+
const isBelowHeader = headerRows > 0 && row === headerRows;
|
|
22744
|
+
return {
|
|
22745
|
+
t: isTop ? "thick" : isBelowHeader ? "double" : "thin",
|
|
22746
|
+
b: isBottom ? "thick" : isHeaderBottom ? "double" : "thin",
|
|
22747
|
+
l: col === 0 ? "thick" : "thin",
|
|
22748
|
+
r: colEnd === colCnt - 1 ? "thick" : "thin",
|
|
22749
|
+
fill
|
|
22750
|
+
};
|
|
22751
|
+
}
|
|
22752
|
+
|
|
22292
22753
|
// src/hwpx/gen-profile.ts
|
|
22293
22754
|
function normalizeAnchor(s) {
|
|
22294
22755
|
return s.toLowerCase().replace(/[^\p{L}\p{N}]/gu, "").slice(0, 24);
|
|
@@ -22380,24 +22841,21 @@ function buildProfileRemap(profile, charPrBase, borderFillBase = 3) {
|
|
|
22380
22841
|
cellChar: /* @__PURE__ */ new Map(),
|
|
22381
22842
|
cellH: /* @__PURE__ */ new Map()
|
|
22382
22843
|
};
|
|
22383
|
-
for (const
|
|
22384
|
-
const k = `${
|
|
22385
|
-
if (
|
|
22386
|
-
tr.cellBf.set(k, localBf[
|
|
22844
|
+
for (const cell2 of t.cells) {
|
|
22845
|
+
const k = `${cell2.row},${cell2.col}`;
|
|
22846
|
+
if (cell2.borderFillIDRef != null && cell2.borderFillIDRef in localBf) {
|
|
22847
|
+
tr.cellBf.set(k, localBf[cell2.borderFillIDRef]);
|
|
22387
22848
|
}
|
|
22388
|
-
if (
|
|
22389
|
-
tr.cellChar.set(k, localChar[
|
|
22849
|
+
if (cell2.charPrIDRef != null && cell2.charPrIDRef in localChar) {
|
|
22850
|
+
tr.cellChar.set(k, localChar[cell2.charPrIDRef]);
|
|
22390
22851
|
}
|
|
22391
|
-
const h = parseHu(
|
|
22852
|
+
const h = parseHu(cell2.height_hwpunit);
|
|
22392
22853
|
if (h != null) tr.cellH.set(k, h);
|
|
22393
22854
|
}
|
|
22394
22855
|
remap.tables.push(tr);
|
|
22395
22856
|
}
|
|
22396
22857
|
return remap;
|
|
22397
22858
|
}
|
|
22398
|
-
function profileCharPrBase(ratioVariantCount) {
|
|
22399
|
-
return CHAR_VARIANT_BASE + ratioVariantCount * 4;
|
|
22400
|
-
}
|
|
22401
22859
|
|
|
22402
22860
|
// src/hwpx/gen-table.ts
|
|
22403
22861
|
var TABLE_ID_BASE = 1e3;
|
|
@@ -22405,47 +22863,141 @@ var tableIdCounter = TABLE_ID_BASE;
|
|
|
22405
22863
|
function nextTableId() {
|
|
22406
22864
|
return ++tableIdCounter;
|
|
22407
22865
|
}
|
|
22408
|
-
|
|
22409
|
-
|
|
22866
|
+
var DATA_TABLE_INSET = 1800;
|
|
22867
|
+
function anchorOfMarkdownCell(cell2) {
|
|
22868
|
+
return normalizeAnchor(cell2.replace(/!\[[^\]]*\]\([^)]*\)/g, ""));
|
|
22410
22869
|
}
|
|
22411
22870
|
function anchorOfHtmlCell(inner) {
|
|
22412
22871
|
const noNested = inner.replace(/<table[\s\S]*?<\/table>/gi, "");
|
|
22413
22872
|
const { lines } = htmlCellInnerToLines(noNested);
|
|
22414
22873
|
return normalizeAnchor(lines.join(""));
|
|
22415
22874
|
}
|
|
22416
|
-
function
|
|
22417
|
-
if (tp
|
|
22418
|
-
|
|
22419
|
-
return Array(colCnt).fill(
|
|
22875
|
+
function profileColWidths(tp, colCnt) {
|
|
22876
|
+
if (!tp) return null;
|
|
22877
|
+
if (tp.colWidths && tp.colWidths.length === colCnt) return tp.colWidths;
|
|
22878
|
+
if (tp.width) return Array(colCnt).fill(Math.floor(tp.width / colCnt));
|
|
22879
|
+
return null;
|
|
22880
|
+
}
|
|
22881
|
+
var CELL_PAD = 582;
|
|
22882
|
+
function cellContentWidth(text, charHeight) {
|
|
22883
|
+
let max = 0;
|
|
22884
|
+
for (const seg of text.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
|
|
22885
|
+
const w = measureTextWidth(seg.trim(), charHeight, 100);
|
|
22886
|
+
if (w > max) max = w;
|
|
22887
|
+
}
|
|
22888
|
+
return max;
|
|
22889
|
+
}
|
|
22890
|
+
function computeColWidths(colMax, totalWidth) {
|
|
22891
|
+
const colCnt = colMax.length;
|
|
22892
|
+
const minW = Math.min(Math.max(2e3, Math.round(totalWidth * 0.06)), Math.floor(totalWidth / colCnt));
|
|
22893
|
+
const cap = Math.round(totalWidth * 0.8);
|
|
22894
|
+
const raw = colMax.map((w) => Math.min(Math.max(w + CELL_PAD, minW), cap));
|
|
22895
|
+
const widths = Array(colCnt).fill(0);
|
|
22896
|
+
const free = new Set(raw.map((_, i) => i));
|
|
22897
|
+
let budget = totalWidth;
|
|
22898
|
+
const evenShare = Math.floor(totalWidth / colCnt);
|
|
22899
|
+
for (let i = 0; i < colCnt; i++) {
|
|
22900
|
+
const fixed = Math.min(Math.round(raw[i] * 1.12), evenShare);
|
|
22901
|
+
if (raw[i] <= evenShare && free.size > 1) {
|
|
22902
|
+
widths[i] = fixed;
|
|
22903
|
+
free.delete(i);
|
|
22904
|
+
budget -= fixed;
|
|
22905
|
+
}
|
|
22906
|
+
}
|
|
22907
|
+
if (free.size === 0) {
|
|
22908
|
+
const sumRaw = raw.reduce((a, b) => a + b, 0);
|
|
22909
|
+
for (let i = 0; i < colCnt; i++) widths[i] += Math.floor(raw[i] / sumRaw * (totalWidth - sumRaw));
|
|
22910
|
+
} else {
|
|
22911
|
+
for (; ; ) {
|
|
22912
|
+
const sum2 = [...free].reduce((a, i) => a + raw[i], 0);
|
|
22913
|
+
const short = [...free].filter((i) => raw[i] / sum2 * budget < minW);
|
|
22914
|
+
if (short.length === 0) break;
|
|
22915
|
+
for (const i of short) {
|
|
22916
|
+
widths[i] = minW;
|
|
22917
|
+
free.delete(i);
|
|
22918
|
+
budget -= minW;
|
|
22919
|
+
}
|
|
22920
|
+
if (free.size === 0) break;
|
|
22921
|
+
}
|
|
22922
|
+
const sum = [...free].reduce((a, i) => a + raw[i], 0);
|
|
22923
|
+
for (const i of free) widths[i] = Math.floor(raw[i] / sum * budget);
|
|
22924
|
+
}
|
|
22925
|
+
let rem = totalWidth - widths.reduce((a, b) => a + b, 0);
|
|
22926
|
+
const order = [...raw.keys()].sort((a, b) => raw[b] - raw[a]);
|
|
22927
|
+
for (let k = 0; rem > 0; k = (k + 1) % colCnt, rem--) widths[order[k]]++;
|
|
22928
|
+
return widths;
|
|
22929
|
+
}
|
|
22930
|
+
function estimateRowHeight(cells, widths, charHeight) {
|
|
22931
|
+
let maxLines = 1;
|
|
22932
|
+
cells.forEach((cell2, c) => {
|
|
22933
|
+
const usable = Math.max((widths[c] ?? widths[widths.length - 1]) - CELL_PAD, 1e3);
|
|
22934
|
+
let lines = 0;
|
|
22935
|
+
for (const seg of cell2.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
|
|
22936
|
+
lines += Math.max(1, Math.ceil(measureTextWidth(seg.trim(), charHeight, 100) / usable));
|
|
22937
|
+
}
|
|
22938
|
+
if (lines > maxLines) maxLines = lines;
|
|
22939
|
+
});
|
|
22940
|
+
return maxLines * Math.round(charHeight * 1.6) + 282;
|
|
22420
22941
|
}
|
|
22421
|
-
function generateTable(rows, theme, remap = null, seq = 0) {
|
|
22942
|
+
function generateTable(rows, theme, style = null, remap = null, seq = 0) {
|
|
22422
22943
|
const rowCnt = rows.length;
|
|
22423
22944
|
const colCnt = Math.max(...rows.map((r) => r.length), 1);
|
|
22424
|
-
const
|
|
22425
|
-
const
|
|
22945
|
+
const reg = style?.bfRegistry ?? null;
|
|
22946
|
+
const totalW = style ? reg ? style.totalWidth - DATA_TABLE_INSET : style.totalWidth : 44e3;
|
|
22947
|
+
const measureH = style?.charHeight ?? 1e3;
|
|
22426
22948
|
const prof = takeProfile(remap, rowCnt, colCnt, anchorOfMarkdownCell(rows[0]?.[0] ?? ""), seq);
|
|
22427
|
-
const
|
|
22428
|
-
const
|
|
22429
|
-
|
|
22430
|
-
|
|
22949
|
+
const colMax = Array(colCnt).fill(0);
|
|
22950
|
+
const colMaxBody = Array(colCnt).fill(0);
|
|
22951
|
+
rows.forEach((row, r) => row.forEach((cell2, c) => {
|
|
22952
|
+
const w = cellContentWidth(cell2, measureH);
|
|
22953
|
+
if (w > colMax[c]) colMax[c] = w;
|
|
22954
|
+
if (r > 0 && w > colMaxBody[c]) colMaxBody[c] = w;
|
|
22955
|
+
}));
|
|
22956
|
+
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW);
|
|
22957
|
+
const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
|
|
22958
|
+
const labelCol0 = !!reg && colCnt === 2 && colCentered[0] && rows.every((r) => (r[0] ?? "").replace(/\*\*|__|`/g, "").length <= 12);
|
|
22959
|
+
const tblId = nextTableId();
|
|
22960
|
+
const useHeaderStyle = !style && (theme.tableHeader !== theme.body || theme.tableHeaderBold);
|
|
22961
|
+
const mapId = style ? (id) => id === CHAR_NORMAL ? style.charPr : id === CHAR_BOLD ? style.boldCharPr : id : void 0;
|
|
22962
|
+
const rowHeights = rows.map((row) => style ? estimateRowHeight(row, colWidths, measureH) : 1500);
|
|
22431
22963
|
const trElements = rows.map((row, rowIdx) => {
|
|
22432
22964
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
22433
22965
|
const isHeaderRow = rowIdx === 0;
|
|
22434
|
-
const
|
|
22435
|
-
const
|
|
22966
|
+
const cellH = rowHeights[rowIdx];
|
|
22967
|
+
const baseCharPr = style ? style.charPr : CHAR_NORMAL;
|
|
22968
|
+
const headerCharPr = isHeaderRow && useHeaderStyle ? CHAR_TABLE_HEADER : baseCharPr;
|
|
22969
|
+
const tdElements = cells.map((cell2, colIdx) => {
|
|
22436
22970
|
const k = `${rowIdx},${colIdx}`;
|
|
22437
|
-
const
|
|
22438
|
-
const
|
|
22971
|
+
const isLabelCell2 = labelCol0 && colIdx === 0;
|
|
22972
|
+
const defaultCharPr = style ? reg && (isHeaderRow || isLabelCell2) ? style.boldCharPr : style.charPr : isHeaderRow ? headerCharPr : baseCharPr;
|
|
22973
|
+
const cellCharPr = prof?.cellChar.get(k) ?? defaultCharPr;
|
|
22974
|
+
const centered = isHeaderRow || colCentered[colIdx];
|
|
22975
|
+
const paraPrId = style ? centered ? style.tblCenterParaPr ?? style.centerParaPr : reg ? style.tblLeftParaPr ?? PARA_NORMAL : PARA_NORMAL : PARA_NORMAL;
|
|
22976
|
+
const p = cell2.split(/<br\s*\/?>/i).map((seg) => {
|
|
22977
|
+
const runs = generateRuns(seg, cellCharPr, prof?.cellChar.has(k) ? void 0 : mapId);
|
|
22978
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0">${runs || `<hp:run charPrIDRef="${cellCharPr}"><hp:t></hp:t></hp:run>`}</hp:p>`;
|
|
22979
|
+
}).join("");
|
|
22980
|
+
const bf = prof?.cellBf.get(k) ?? (reg ? reg.get(dataCellSpec({
|
|
22981
|
+
row: rowIdx,
|
|
22982
|
+
rowEnd: rowIdx,
|
|
22983
|
+
col: colIdx,
|
|
22984
|
+
colEnd: colIdx,
|
|
22985
|
+
rowCnt,
|
|
22986
|
+
colCnt,
|
|
22987
|
+
headerRows: 1,
|
|
22988
|
+
fill: isHeaderRow ? style.headerFill ?? "#E6E6E6" : isLabelCell2 ? style.labelFill ?? "#E7E7E7" : void 0
|
|
22989
|
+
})) : style && isHeaderRow ? style.headerBf : 2);
|
|
22439
22990
|
const h = prof?.cellH.get(k) ?? cellH;
|
|
22440
|
-
|
|
22441
|
-
const p = `<hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p>`;
|
|
22442
|
-
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>`;
|
|
22991
|
+
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>`;
|
|
22443
22992
|
}).join("");
|
|
22444
22993
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
22445
22994
|
}).join("");
|
|
22995
|
+
const tblW = colWidths.reduce((a, b) => a + b, 0);
|
|
22996
|
+
const tblH = rowHeights.reduce((a, b) => a + b, 0);
|
|
22446
22997
|
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;
|
|
22447
|
-
const
|
|
22448
|
-
|
|
22998
|
+
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>`;
|
|
22999
|
+
const hostPr = reg && style?.rightParaPr !== void 0 ? style.rightParaPr : 0;
|
|
23000
|
+
return `<hp:p paraPrIDRef="${hostPr}" styleIDRef="0"><hp:run charPrIDRef="0">${tbl2}</hp:run></hp:p>`;
|
|
22449
23001
|
}
|
|
22450
23002
|
function layoutHtmlRows(rows) {
|
|
22451
23003
|
const occupied = /* @__PURE__ */ new Set();
|
|
@@ -22453,11 +23005,11 @@ function layoutHtmlRows(rows) {
|
|
|
22453
23005
|
let colCnt = 0;
|
|
22454
23006
|
for (let r = 0; r < rows.length; r++) {
|
|
22455
23007
|
let c = 0;
|
|
22456
|
-
for (const
|
|
23008
|
+
for (const cell2 of rows[r].cells) {
|
|
22457
23009
|
while (occupied.has(`${r},${c}`)) c++;
|
|
22458
|
-
const colSpan = Math.max(1,
|
|
22459
|
-
const rowSpan = Math.max(1,
|
|
22460
|
-
placed.push({ r, c, colSpan, rowSpan, inner:
|
|
23010
|
+
const colSpan = Math.max(1, cell2.colSpan);
|
|
23011
|
+
const rowSpan = Math.max(1, cell2.rowSpan);
|
|
23012
|
+
placed.push({ r, c, colSpan, rowSpan, inner: cell2.inner, isHeader: rows[r].tag === "th" });
|
|
22461
23013
|
for (let dr = 0; dr < rowSpan; dr++) {
|
|
22462
23014
|
for (let dc = 0; dc < colSpan; dc++) occupied.add(`${r + dr},${c + dc}`);
|
|
22463
23015
|
}
|
|
@@ -22470,50 +23022,135 @@ function layoutHtmlRows(rows) {
|
|
|
22470
23022
|
function unescapeHtml(s) {
|
|
22471
23023
|
return s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
22472
23024
|
}
|
|
22473
|
-
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, remap = null, seq = 0) {
|
|
23025
|
+
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, remap = null, seq = 0) {
|
|
22474
23026
|
const rows = parseHtmlTable(rawHtml);
|
|
22475
23027
|
if (!rows || rows.length === 0) return null;
|
|
22476
23028
|
const { placed, rowCnt, colCnt } = layoutHtmlRows(rows);
|
|
22477
23029
|
if (rowCnt === 0 || colCnt === 0) return null;
|
|
22478
|
-
const
|
|
22479
|
-
const tblId = nextTableId();
|
|
23030
|
+
const measureH = style?.charHeight ?? 1e3;
|
|
22480
23031
|
const first = placed.find((p) => p.r === 0 && p.c === 0) ?? placed[0];
|
|
22481
23032
|
const prof = takeProfile(remap, rowCnt, colCnt, first ? anchorOfHtmlCell(first.inner) : "", seq);
|
|
22482
|
-
const
|
|
22483
|
-
const
|
|
22484
|
-
const
|
|
22485
|
-
|
|
22486
|
-
|
|
22487
|
-
|
|
22488
|
-
|
|
22489
|
-
|
|
22490
|
-
|
|
22491
|
-
|
|
23033
|
+
const colMax = Array(colCnt).fill(0);
|
|
23034
|
+
const colMaxBody = Array(colCnt).fill(0);
|
|
23035
|
+
const cellLines = placed.map((cell2) => htmlCellInnerToLines(cell2.inner).lines);
|
|
23036
|
+
placed.forEach((cell2, i) => {
|
|
23037
|
+
const w = Math.max(...cellLines[i].map((l) => measureTextWidth(unescapeHtml(l).trim(), measureH, 100)), 0) / cell2.colSpan;
|
|
23038
|
+
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
23039
|
+
const c = cell2.c + dc;
|
|
23040
|
+
if (w > colMax[c]) colMax[c] = w;
|
|
23041
|
+
if (!cell2.isHeader && w > colMaxBody[c]) colMaxBody[c] = w;
|
|
23042
|
+
}
|
|
23043
|
+
});
|
|
23044
|
+
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth);
|
|
23045
|
+
const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
|
|
23046
|
+
const cellH = style ? Math.round(measureH * 1.6) + 282 : 1500;
|
|
23047
|
+
const tblW = colWidths.reduce((a, b) => a + b, 0);
|
|
23048
|
+
const tblId = nextTableId();
|
|
23049
|
+
const useHeaderStyle = !style && (theme.tableHeader !== theme.body || theme.tableHeaderBold);
|
|
23050
|
+
const spanW = (cell2) => colWidths.slice(cell2.c, cell2.c + cell2.colSpan).reduce((a, b) => a + b, 0);
|
|
23051
|
+
const reg = style?.bfRegistry ?? null;
|
|
23052
|
+
let htmlHeaderRows = 0;
|
|
23053
|
+
while (htmlHeaderRows < rows.length && rows[htmlHeaderRows].tag === "th") htmlHeaderRows++;
|
|
23054
|
+
const tcXmls = placed.map((cell2, i) => {
|
|
23055
|
+
const k = `${cell2.r},${cell2.c}`;
|
|
23056
|
+
const isHeader = cell2.isHeader;
|
|
23057
|
+
const baseCharPr = style ? style.charPr : CHAR_NORMAL;
|
|
23058
|
+
const headerCharPr = isHeader && useHeaderStyle ? CHAR_TABLE_HEADER : baseCharPr;
|
|
23059
|
+
const defaultCharPr = style && reg && isHeader ? style.boldCharPr : isHeader ? headerCharPr : baseCharPr;
|
|
23060
|
+
const charPrId = prof?.cellChar.get(k) ?? defaultCharPr;
|
|
23061
|
+
const centered = isHeader || colCentered[cell2.c];
|
|
23062
|
+
const paraPrId = style ? centered ? reg ? style.tblCenterParaPr ?? style.centerParaPr : style.centerParaPr : reg ? style.tblLeftParaPr ?? PARA_NORMAL : PARA_NORMAL : PARA_NORMAL;
|
|
23063
|
+
const lines = cellLines[i];
|
|
22492
23064
|
const paras = lines.map(
|
|
22493
|
-
(line) => `<hp:p paraPrIDRef="
|
|
23065
|
+
(line) => `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(unescapeHtml(line))}</hp:t></hp:run></hp:p>`
|
|
22494
23066
|
);
|
|
22495
|
-
const cellW = spanW(cell.c, cell.colSpan);
|
|
22496
23067
|
let nestedH = 0;
|
|
22497
|
-
for (const nested of extractTopLevelTables(
|
|
22498
|
-
const
|
|
23068
|
+
for (const nested of extractTopLevelTables(cell2.inner)) {
|
|
23069
|
+
const nestedW = Math.max(spanW(cell2) - 1020, 4e3);
|
|
23070
|
+
const nestedXml = generateHtmlTableXml(nested, theme, nestedW, style ? { ...style, totalWidth: nestedW } : null);
|
|
22499
23071
|
if (nestedXml) {
|
|
22500
23072
|
paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${nestedXml}</hp:run></hp:p>`);
|
|
22501
23073
|
nestedH += (nested.match(/<tr[\s>]/gi) ?? []).length * cellH + 300;
|
|
22502
23074
|
}
|
|
22503
23075
|
}
|
|
22504
23076
|
if (paras.length === 0) {
|
|
22505
|
-
paras.push(`<hp:p paraPrIDRef="
|
|
23077
|
+
paras.push(`<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t></hp:t></hp:run></hp:p>`);
|
|
22506
23078
|
}
|
|
22507
|
-
const contentH = Math.max(cellH *
|
|
23079
|
+
const contentH = Math.max(cellH * cell2.rowSpan, Math.max(lines.length, 1) * (style ? Math.round(measureH * 1.6) : 800) + nestedH);
|
|
22508
23080
|
const cellHeight = Math.max(prof?.cellH.get(k) ?? 0, contentH);
|
|
22509
|
-
|
|
23081
|
+
const bf = prof?.cellBf.get(k) ?? (reg ? reg.get(dataCellSpec({
|
|
23082
|
+
row: cell2.r,
|
|
23083
|
+
rowEnd: cell2.r + cell2.rowSpan - 1,
|
|
23084
|
+
col: cell2.c,
|
|
23085
|
+
colEnd: cell2.c + cell2.colSpan - 1,
|
|
23086
|
+
rowCnt,
|
|
23087
|
+
colCnt,
|
|
23088
|
+
headerRows: htmlHeaderRows,
|
|
23089
|
+
fill: isHeader ? style.headerFill ?? "#E6E6E6" : void 0
|
|
23090
|
+
})) : style && isHeader ? style.headerBf : 2);
|
|
23091
|
+
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>`;
|
|
22510
23092
|
});
|
|
22511
23093
|
const trXmls = [];
|
|
22512
23094
|
for (let r = 0; r < rowCnt; r++) {
|
|
22513
23095
|
const rowTcs = tcXmls.filter((_, i) => placed[i].r === r);
|
|
22514
23096
|
trXmls.push(`<hp:tr>${rowTcs.join("")}</hp:tr>`);
|
|
22515
23097
|
}
|
|
22516
|
-
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>`;
|
|
23098
|
+
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>`;
|
|
23099
|
+
}
|
|
23100
|
+
|
|
23101
|
+
// src/hwpx/gen-gongmun-extra.ts
|
|
23102
|
+
var extraTableId = 93e5;
|
|
23103
|
+
function tbl(rows, w, h, cols) {
|
|
23104
|
+
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>`;
|
|
23105
|
+
}
|
|
23106
|
+
function tc(opts) {
|
|
23107
|
+
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>`;
|
|
23108
|
+
}
|
|
23109
|
+
function para(text, paraPrId, charPrId) {
|
|
23110
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
|
|
23111
|
+
}
|
|
23112
|
+
var APPROVAL_COL_W = 7085;
|
|
23113
|
+
var APPROVAL_LABEL_H = 1100;
|
|
23114
|
+
var APPROVAL_SIGN_H = 4200;
|
|
23115
|
+
function buildApprovalTable(labels, gongmun, reg) {
|
|
23116
|
+
const n = labels.length;
|
|
23117
|
+
const w = APPROVAL_COL_W * n;
|
|
23118
|
+
const bfAt = (row, col) => reg.get({
|
|
23119
|
+
t: row === 0 ? "thick" : "thin",
|
|
23120
|
+
b: row === 1 ? "thick" : "thin",
|
|
23121
|
+
l: col === 0 ? "thick" : "thin",
|
|
23122
|
+
r: col === n - 1 ? "thick" : "thin"
|
|
23123
|
+
});
|
|
23124
|
+
const labelRow = labels.map(
|
|
23125
|
+
(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) })
|
|
23126
|
+
).join("");
|
|
23127
|
+
const signRow = labels.map(
|
|
23128
|
+
(_, 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) })
|
|
23129
|
+
).join("");
|
|
23130
|
+
const table2 = tbl([labelRow, signRow], w, APPROVAL_LABEL_H + APPROVAL_SIGN_H, n);
|
|
23131
|
+
return `<hp:p paraPrIDRef="${GONGMUN_RIGHT}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`;
|
|
23132
|
+
}
|
|
23133
|
+
function hasEndMark(lastText) {
|
|
23134
|
+
return /끝\s*\.?\s*$/.test(lastText.trim());
|
|
23135
|
+
}
|
|
23136
|
+
function buildEndMark() {
|
|
23137
|
+
return para(" \uB05D.", PARA_NORMAL, CHAR_NORMAL);
|
|
23138
|
+
}
|
|
23139
|
+
var TITLE_BOX = { barH: 382, titleH: 2850, color: "#0080C0", gradient: ["#0080C0", "#3CBFFF"] };
|
|
23140
|
+
function buildTitleBox(title, titleCharPr, bodyWidth, reg) {
|
|
23141
|
+
const w = bodyWidth - 280;
|
|
23142
|
+
const outer = { t: "thin", b: "thin", l: "thin", r: "thin" };
|
|
23143
|
+
const barTop = reg.get({ ...outer, fill: TITLE_BOX.color });
|
|
23144
|
+
const barBottom = reg.get({ ...outer, fill: { gradient: TITLE_BOX.gradient } });
|
|
23145
|
+
const mid = reg.get(outer);
|
|
23146
|
+
const barPara = `<hp:p paraPrIDRef="${GONGMUN_TBL_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t></hp:t></hp:run></hp:p>`;
|
|
23147
|
+
const rows = [
|
|
23148
|
+
tc({ bf: barTop, row: 0, col: 0, w, h: TITLE_BOX.barH, paras: barPara }),
|
|
23149
|
+
tc({ bf: mid, row: 1, col: 0, w, h: TITLE_BOX.titleH, paras: para(title, GONGMUN_TBL_CENTER, titleCharPr) }),
|
|
23150
|
+
tc({ bf: barBottom, row: 2, col: 0, w, h: TITLE_BOX.barH, paras: barPara })
|
|
23151
|
+
];
|
|
23152
|
+
const table2 = tbl(rows, w, TITLE_BOX.barH * 2 + TITLE_BOX.titleH, 1);
|
|
23153
|
+
return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`;
|
|
22517
23154
|
}
|
|
22518
23155
|
|
|
22519
23156
|
// src/hwpx/equation-generate.ts
|
|
@@ -22803,14 +23440,78 @@ function generateSecPr(gongmun) {
|
|
|
22803
23440
|
header: 0,
|
|
22804
23441
|
footer: 0
|
|
22805
23442
|
} : { top: 8504, bottom: 4252, left: 5670, right: 4252, header: 2835, footer: 2835 };
|
|
22806
|
-
|
|
23443
|
+
if (gongmun) {
|
|
23444
|
+
m.header = gongmun.headerFooter;
|
|
23445
|
+
m.footer = gongmun.headerFooter;
|
|
23446
|
+
}
|
|
23447
|
+
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>`;
|
|
23448
|
+
return gongmun?.pageNumbers ? secPr + pageNumCtrl() : secPr;
|
|
22807
23449
|
}
|
|
22808
|
-
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, remap = null) {
|
|
23450
|
+
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null) {
|
|
22809
23451
|
const paraXmls = [];
|
|
22810
23452
|
let isFirst = true;
|
|
22811
23453
|
let tableSeq = 0;
|
|
22812
23454
|
const orderedCounters = {};
|
|
22813
23455
|
let prevWasOrdered = false;
|
|
23456
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
23457
|
+
const measured = !!gongmun && usesReportFonts(gongmun.preset);
|
|
23458
|
+
const vBase = charVariantBase(measured);
|
|
23459
|
+
const tableStyle = gongmun ? {
|
|
23460
|
+
totalWidth: mmToHwpunit(210 - gongmun.margins.left - gongmun.margins.right),
|
|
23461
|
+
charPr: measured ? GJ_CHAR_TABLE : CHAR_NORMAL,
|
|
23462
|
+
boldCharPr: measured ? GJ_CHAR_TABLE_BOLD : CHAR_BOLD,
|
|
23463
|
+
charHeight: measured ? gaejosikSizes(gongmun.bodyHeight, gongmun.sizes).table : gongmun.bodyHeight,
|
|
23464
|
+
headerBf: gongmunTableHeaderBf(gaejosik),
|
|
23465
|
+
centerParaPr: GONGMUN_CENTER,
|
|
23466
|
+
tblCenterParaPr: GONGMUN_TBL_CENTER,
|
|
23467
|
+
tblLeftParaPr: GONGMUN_TBL_LEFT,
|
|
23468
|
+
bfRegistry: bfReg ?? void 0,
|
|
23469
|
+
rightParaPr: GONGMUN_RIGHT
|
|
23470
|
+
} : null;
|
|
23471
|
+
const chamMap = (id) => id === CHAR_BOLD ? GJ_CHAR_CHAM_BOLD : id;
|
|
23472
|
+
let chapterNo = 0;
|
|
23473
|
+
let h2Seq = 0;
|
|
23474
|
+
let coverH1Idx = -1;
|
|
23475
|
+
let pendingPageBreak = false;
|
|
23476
|
+
let pendingNewNum = false;
|
|
23477
|
+
let titleBoxH1Idx = -1;
|
|
23478
|
+
let hasFrontPages = false;
|
|
23479
|
+
const preamble = [];
|
|
23480
|
+
if (gongmun?.approval && bfReg) {
|
|
23481
|
+
preamble.push(buildApprovalTable(gongmun.approval, gongmun, bfReg));
|
|
23482
|
+
}
|
|
23483
|
+
if (gaejosik && gongmun) {
|
|
23484
|
+
const h1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
|
|
23485
|
+
const chapters = blocks.filter((b) => b.type === "heading" && b.level === 2).map((b) => stripChapterNumber(b.text || ""));
|
|
23486
|
+
let coverTitle = "";
|
|
23487
|
+
const hide = (xml, hideHeader) => gongmun.pageNumbers ? xml.replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${pageHidingCtrl(hideHeader)}`) : xml;
|
|
23488
|
+
if (gongmun.cover && h1Idx >= 0) {
|
|
23489
|
+
coverTitle = (blocks[h1Idx].text || "").trim();
|
|
23490
|
+
const coverPart = buildGaejosikCover(coverTitle, gongmun);
|
|
23491
|
+
coverPart[0] = hide(coverPart[0], true);
|
|
23492
|
+
preamble.push(...coverPart);
|
|
23493
|
+
coverH1Idx = h1Idx;
|
|
23494
|
+
hasFrontPages = true;
|
|
23495
|
+
}
|
|
23496
|
+
if (gongmun.toc && chapters.length > 0) {
|
|
23497
|
+
const tocPart = buildGaejosikToc(chapters, gongmun);
|
|
23498
|
+
tocPart[0] = hide(tocPart[0], false);
|
|
23499
|
+
preamble.push(...tocPart);
|
|
23500
|
+
hasFrontPages = true;
|
|
23501
|
+
}
|
|
23502
|
+
if (gongmun.bodyTitleBox && coverTitle && hasFrontPages) {
|
|
23503
|
+
preamble.push(buildGaejosikBodyTitle(coverTitle, gongmun).replace(/^<hp:p /, `<hp:p pageBreak="1" `));
|
|
23504
|
+
}
|
|
23505
|
+
} else if (gongmun && !gaejosik && bfReg && (gongmun.preset === "report" || gongmun.preset === "plan" || gongmun.preset === "notice")) {
|
|
23506
|
+
titleBoxH1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
|
|
23507
|
+
}
|
|
23508
|
+
if (preamble.length > 0) {
|
|
23509
|
+
preamble[0] = preamble[0].replace(` pageBreak="1"`, "").replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${generateSecPr(gongmun)}`);
|
|
23510
|
+
isFirst = false;
|
|
23511
|
+
pendingPageBreak = hasFrontPages && !preamble[preamble.length - 1].includes(`pageBreak="1"`);
|
|
23512
|
+
pendingNewNum = !!gongmun.pageNumbers && hasFrontPages;
|
|
23513
|
+
paraXmls.push(...preamble);
|
|
23514
|
+
}
|
|
22814
23515
|
for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
|
|
22815
23516
|
const block = blocks[blockIdx];
|
|
22816
23517
|
let xml = "";
|
|
@@ -22822,17 +23523,52 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22822
23523
|
}
|
|
22823
23524
|
switch (block.type) {
|
|
22824
23525
|
case "heading": {
|
|
23526
|
+
if (gongmun && blockIdx === titleBoxH1Idx && tableStyle && bfReg) {
|
|
23527
|
+
xml = buildTitleBox((block.text || "").trim(), measured ? GJ_CHAR_BODY_TITLE : CHAR_H1, tableStyle.totalWidth, bfReg);
|
|
23528
|
+
break;
|
|
23529
|
+
}
|
|
23530
|
+
if (gaejosik) {
|
|
23531
|
+
const lvl = block.level || 1;
|
|
23532
|
+
if (blockIdx === coverH1Idx) break;
|
|
23533
|
+
if (lvl <= 2) {
|
|
23534
|
+
chapterNo++;
|
|
23535
|
+
xml = buildGaejosikChapter(chapterNo, stripChapterNumber(block.text || ""), gongmun);
|
|
23536
|
+
} else if (lvl === 3) {
|
|
23537
|
+
xml = generateParagraph(
|
|
23538
|
+
`\u25A1 ${block.text || ""}`,
|
|
23539
|
+
GONGMUN_LIST_BASE,
|
|
23540
|
+
GJ_CHAR_DAE,
|
|
23541
|
+
(id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id
|
|
23542
|
+
);
|
|
23543
|
+
} else {
|
|
23544
|
+
xml = generateParagraph(`\u25CB ${block.text || ""}`, GONGMUN_LIST_BASE + 1, CHAR_NORMAL);
|
|
23545
|
+
}
|
|
23546
|
+
break;
|
|
23547
|
+
}
|
|
22825
23548
|
const pId = headingParaPrId(block.level || 1);
|
|
22826
23549
|
const cId = headingCharPrId(block.level || 1);
|
|
22827
|
-
|
|
23550
|
+
const styleId = gongmun ? Math.min(block.level || 1, 4) : 0;
|
|
23551
|
+
let hText = block.text || "";
|
|
23552
|
+
if (gongmun && (block.level || 1) === 2 && gongmun.h2Marker !== "none") {
|
|
23553
|
+
const title = stripChapterNumber(hText);
|
|
23554
|
+
hText = gongmun.h2Marker === "box" ? `\u25A1 ${title}` : `${++h2Seq}. ${title}`;
|
|
23555
|
+
}
|
|
23556
|
+
xml = generateParagraph(hText, pId, cId, void 0, styleId);
|
|
22828
23557
|
break;
|
|
22829
23558
|
}
|
|
22830
23559
|
case "paragraph": {
|
|
23560
|
+
if (measured && (block.text || "").trimStart().startsWith("\u203B")) {
|
|
23561
|
+
xml = generateParagraph((block.text || "").trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23562
|
+
break;
|
|
23563
|
+
}
|
|
22831
23564
|
const ctr = gongmun && /^<center>([\s\S]*)<\/center>$/i.exec((block.text || "").trim());
|
|
23565
|
+
const rgt = gongmun && /^<right>([\s\S]*)<\/right>$/i.exec((block.text || "").trim());
|
|
22832
23566
|
if (ctr) {
|
|
22833
23567
|
xml = generateParagraph(ctr[1].trim(), GONGMUN_CENTER);
|
|
23568
|
+
} else if (rgt) {
|
|
23569
|
+
xml = generateParagraph(rgt[1].trim(), GONGMUN_RIGHT);
|
|
22834
23570
|
} else {
|
|
22835
|
-
xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx) : void 0);
|
|
23571
|
+
xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx, vBase) : void 0);
|
|
22836
23572
|
}
|
|
22837
23573
|
break;
|
|
22838
23574
|
}
|
|
@@ -22865,22 +23601,37 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22865
23601
|
xml = generateEquationParagraph(block.text || "", blockIdx);
|
|
22866
23602
|
break;
|
|
22867
23603
|
}
|
|
22868
|
-
case "blockquote":
|
|
23604
|
+
case "blockquote": {
|
|
23605
|
+
if (measured) {
|
|
23606
|
+
const t = (block.text || "").trim();
|
|
23607
|
+
if (t) xml = generateParagraph(t.startsWith("\u203B") ? t : `\u203B ${t}`, GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23608
|
+
break;
|
|
23609
|
+
}
|
|
22869
23610
|
xml = generateParagraph(
|
|
22870
23611
|
block.text || "",
|
|
22871
23612
|
PARA_QUOTE,
|
|
22872
23613
|
theme.hasQuoteOption ? CHAR_QUOTE : CHAR_NORMAL
|
|
22873
23614
|
);
|
|
22874
23615
|
break;
|
|
23616
|
+
}
|
|
22875
23617
|
case "list_item": {
|
|
22876
23618
|
if (gongmun && gongmunList) {
|
|
22877
23619
|
const info = gongmunList.get(blockIdx);
|
|
22878
23620
|
const depth = info?.depth ?? 0;
|
|
22879
23621
|
const marker2 = info?.marker ?? "";
|
|
22880
23622
|
const content = block.text || "";
|
|
23623
|
+
if (measured && content.trimStart().startsWith("\u203B")) {
|
|
23624
|
+
xml = generateParagraph(content.trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23625
|
+
break;
|
|
23626
|
+
}
|
|
22881
23627
|
const text = marker2 ? `${marker2} ${content}` : content;
|
|
22882
|
-
|
|
22883
|
-
|
|
23628
|
+
let listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
|
|
23629
|
+
let mapId = fit ? variantMapper(fit, blockIdx, vBase) : void 0;
|
|
23630
|
+
if (measured && depth === 0 && gongmun.numbering !== "standard") {
|
|
23631
|
+
listCharPr = GJ_CHAR_DAE;
|
|
23632
|
+
mapId = (id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id;
|
|
23633
|
+
}
|
|
23634
|
+
xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr, mapId);
|
|
22884
23635
|
break;
|
|
22885
23636
|
}
|
|
22886
23637
|
const indent = block.indent || 0;
|
|
@@ -22907,7 +23658,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22907
23658
|
break;
|
|
22908
23659
|
}
|
|
22909
23660
|
case "hr":
|
|
22910
|
-
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>`;
|
|
23661
|
+
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>`;
|
|
22911
23662
|
break;
|
|
22912
23663
|
case "table":
|
|
22913
23664
|
if (block.rows) {
|
|
@@ -22916,18 +23667,19 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22916
23667
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
22917
23668
|
isFirst = false;
|
|
22918
23669
|
}
|
|
22919
|
-
xml = generateTable(block.rows, theme, remap, tableSeq++);
|
|
23670
|
+
xml = generateTable(block.rows, theme, tableStyle, remap, tableSeq++);
|
|
22920
23671
|
}
|
|
22921
23672
|
break;
|
|
22922
23673
|
case "html_table": {
|
|
22923
|
-
const
|
|
22924
|
-
|
|
23674
|
+
const htmlW = tableStyle ? bfReg ? tableStyle.totalWidth - DATA_TABLE_INSET : tableStyle.totalWidth : 44e3;
|
|
23675
|
+
const tbl2 = generateHtmlTableXml(block.text || "", theme, htmlW, tableStyle, remap, tableSeq++);
|
|
23676
|
+
if (tbl2) {
|
|
22925
23677
|
if (isFirst) {
|
|
22926
23678
|
const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
|
|
22927
23679
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
22928
23680
|
isFirst = false;
|
|
22929
23681
|
}
|
|
22930
|
-
xml = `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${
|
|
23682
|
+
xml = `<hp:p paraPrIDRef="${tableStyle && bfReg ? GONGMUN_RIGHT : 0}" styleIDRef="0"><hp:run charPrIDRef="0">${tbl2}</hp:run></hp:p>`;
|
|
22931
23683
|
} else {
|
|
22932
23684
|
const plain = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
22933
23685
|
xml = plain ? generateParagraph(plain) : "";
|
|
@@ -22943,8 +23695,20 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22943
23695
|
);
|
|
22944
23696
|
isFirst = false;
|
|
22945
23697
|
}
|
|
23698
|
+
if (pendingPageBreak) {
|
|
23699
|
+
xml = xml.replace(/^<hp:p /, `<hp:p pageBreak="1" `);
|
|
23700
|
+
pendingPageBreak = false;
|
|
23701
|
+
}
|
|
23702
|
+
if (pendingNewNum) {
|
|
23703
|
+
xml = xml.replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${newPageNumCtrl(1)}`);
|
|
23704
|
+
pendingNewNum = false;
|
|
23705
|
+
}
|
|
22946
23706
|
paraXmls.push(xml);
|
|
22947
23707
|
}
|
|
23708
|
+
if (gongmun?.endMark && paraXmls.length > 0) {
|
|
23709
|
+
const lastText = [...blocks].reverse().find((b) => (b.type === "paragraph" || b.type === "list_item") && (b.text || "").trim())?.text ?? "";
|
|
23710
|
+
if (!hasEndMark(lastText)) paraXmls.push(buildEndMark());
|
|
23711
|
+
}
|
|
22948
23712
|
if (paraXmls.length === 0) {
|
|
22949
23713
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run></hp:p>`);
|
|
22950
23714
|
}
|
|
@@ -22958,23 +23722,28 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22958
23722
|
async function markdownToHwpx(markdown, options) {
|
|
22959
23723
|
const theme = resolveTheme(options?.theme);
|
|
22960
23724
|
const gongmun = options?.gongmun ? resolveGongmun(options.gongmun) : null;
|
|
23725
|
+
const gaejosik = gongmun?.preset === "gaejosik";
|
|
23726
|
+
const measured = !!gongmun && usesReportFonts(gongmun.preset);
|
|
22961
23727
|
const blocks = parseMarkdownToBlocks(markdown);
|
|
22962
23728
|
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
22963
23729
|
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
22964
|
-
const
|
|
23730
|
+
const staticBfEnd = gongmun ? gaejosik ? 11 : 4 : 3;
|
|
23731
|
+
const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(measured) + (fit?.variants?.length ?? 0) * 4, staticBfEnd) : null;
|
|
23732
|
+
const bfReg = gongmun ? new TableBfRegistry(staticBfEnd + (remap?.borderFillXmls.length ?? 0)) : null;
|
|
22965
23733
|
const chartParts = [];
|
|
22966
|
-
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, remap);
|
|
23734
|
+
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap);
|
|
22967
23735
|
if (remap && remap.tables.length > 0) {
|
|
22968
23736
|
const unused = remap.tables.filter((t) => !t.used).length;
|
|
22969
23737
|
if (unused === remap.tables.length) {
|
|
22970
23738
|
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)`);
|
|
22971
23739
|
}
|
|
22972
23740
|
}
|
|
23741
|
+
const extraBorderFills = [...remap?.borderFillXmls ?? [], ...bfReg?.emit() ?? []];
|
|
22973
23742
|
const zip = new JSZip7();
|
|
22974
23743
|
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
22975
23744
|
zip.file("META-INF/container.xml", generateContainerXml());
|
|
22976
23745
|
zip.file("Contents/content.hpf", generateManifest(chartParts));
|
|
22977
|
-
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? [], remap));
|
|
23746
|
+
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? [], extraBorderFills, remap?.charPrXmls ?? []));
|
|
22978
23747
|
zip.file("Contents/section0.xml", sectionXml);
|
|
22979
23748
|
for (const part of chartParts) zip.file(part.name, part.xml);
|
|
22980
23749
|
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
@@ -23244,6 +24013,12 @@ function parseParaGeom(el) {
|
|
|
23244
24013
|
g.spaceBefore = v("prev");
|
|
23245
24014
|
g.spaceAfter = v("next");
|
|
23246
24015
|
}
|
|
24016
|
+
const bs = findDeep(el, "breakSetting");
|
|
24017
|
+
if (bs) {
|
|
24018
|
+
const nl = bs.getAttribute("breakNonLatinWord");
|
|
24019
|
+
if (nl === "BREAK_WORD") g.wrapMode = "keep";
|
|
24020
|
+
else if (nl === "KEEP_WORD") g.wrapMode = "charAll";
|
|
24021
|
+
}
|
|
23247
24022
|
return g;
|
|
23248
24023
|
}
|
|
23249
24024
|
function parseRenderStyles(headXml) {
|
|
@@ -23351,9 +24126,9 @@ function collectSites(scan) {
|
|
|
23351
24126
|
if (depth > 16) return;
|
|
23352
24127
|
for (const t of tables) {
|
|
23353
24128
|
for (const row of t.rows) {
|
|
23354
|
-
for (const
|
|
23355
|
-
for (const p of
|
|
23356
|
-
walkTables(
|
|
24129
|
+
for (const cell2 of row) {
|
|
24130
|
+
for (const p of cell2.paragraphs) sites.push({ para: p, cell: cell2, table: t, nested: depth > 0, outer: outer.length ? outer : void 0 });
|
|
24131
|
+
walkTables(cell2.tables, depth + 1, [...outer, { cell: cell2, table: t }]);
|
|
23357
24132
|
}
|
|
23358
24133
|
}
|
|
23359
24134
|
}
|
|
@@ -23367,18 +24142,18 @@ function attrOf(openTag, name) {
|
|
|
23367
24142
|
const m = openTag.match(new RegExp(`\\b${name}="([^"]*)"`));
|
|
23368
24143
|
return m?.[1];
|
|
23369
24144
|
}
|
|
23370
|
-
function paraOpenTag(xml,
|
|
23371
|
-
const end = xml.indexOf(">",
|
|
23372
|
-
return end === -1 ? "" : xml.slice(
|
|
24145
|
+
function paraOpenTag(xml, para2) {
|
|
24146
|
+
const end = xml.indexOf(">", para2.start);
|
|
24147
|
+
return end === -1 ? "" : xml.slice(para2.start, end + 1);
|
|
23373
24148
|
}
|
|
23374
|
-
function anchorRunInfo(xml,
|
|
23375
|
-
let tr =
|
|
24149
|
+
function anchorRunInfo(xml, para2, anchor) {
|
|
24150
|
+
let tr = para2.tRanges.find((r) => !r.selfClosing && xml.slice(r.contentStart, r.contentEnd).includes(anchor));
|
|
23376
24151
|
if (!tr) {
|
|
23377
24152
|
const head = anchor[0];
|
|
23378
|
-
tr =
|
|
24153
|
+
tr = para2.tRanges.find((r) => !r.selfClosing && xml.slice(r.contentStart, r.contentEnd).includes(head)) ?? para2.tRanges[para2.tRanges.length - 1];
|
|
23379
24154
|
}
|
|
23380
24155
|
if (!tr) return null;
|
|
23381
|
-
const before = xml.slice(Math.max(0,
|
|
24156
|
+
const before = xml.slice(Math.max(0, para2.start), tr.contentStart);
|
|
23382
24157
|
const runOpen = [...before.matchAll(/<([A-Za-z0-9]+):run\b[^>]*>/g)].pop();
|
|
23383
24158
|
const prefix = runOpen?.[1] ?? tr.prefix ?? "hp";
|
|
23384
24159
|
const charPr2 = runOpen && attrOf(runOpen[0], "charPrIDRef") || "0";
|
|
@@ -23386,37 +24161,37 @@ function anchorRunInfo(xml, para, anchor) {
|
|
|
23386
24161
|
if (close === -1) return null;
|
|
23387
24162
|
return { charPr: charPr2, prefix, insertAt: close + `</${prefix}:run>`.length };
|
|
23388
24163
|
}
|
|
23389
|
-
function cellAddrWindow(xml,
|
|
23390
|
-
if (!
|
|
23391
|
-
return xml.slice(
|
|
24164
|
+
function cellAddrWindow(xml, cell2) {
|
|
24165
|
+
if (!cell2.addrTagRange) return null;
|
|
24166
|
+
return xml.slice(cell2.addrTagRange.end, cell2.addrTagRange.end + 400);
|
|
23392
24167
|
}
|
|
23393
|
-
function cellSzWidthHu(xml,
|
|
23394
|
-
const win = cellAddrWindow(xml,
|
|
24168
|
+
function cellSzWidthHu(xml, cell2) {
|
|
24169
|
+
const win = cellAddrWindow(xml, cell2);
|
|
23395
24170
|
if (win) {
|
|
23396
24171
|
const m = win.match(/<[A-Za-z0-9]+:cellSz\b[^>]*\bwidth="(\d+)"/);
|
|
23397
24172
|
if (m) return Number(m[1]);
|
|
23398
24173
|
}
|
|
23399
|
-
const firstPara =
|
|
24174
|
+
const firstPara = cell2.paragraphs[0];
|
|
23400
24175
|
if (!firstPara) return null;
|
|
23401
24176
|
const upto = xml.slice(0, firstPara.start);
|
|
23402
24177
|
const szMatch = [...upto.matchAll(/<[A-Za-z0-9]+:cellSz\b[^>]*\bwidth="(\d+)"[^>]*>/g)].pop();
|
|
23403
24178
|
return szMatch ? Number(szMatch[1]) : null;
|
|
23404
24179
|
}
|
|
23405
|
-
function cellContentWidthMm(xml,
|
|
23406
|
-
const width = cellSzWidthHu(xml,
|
|
24180
|
+
function cellContentWidthMm(xml, cell2) {
|
|
24181
|
+
const width = cellSzWidthHu(xml, cell2);
|
|
23407
24182
|
if (width === null) return null;
|
|
23408
24183
|
let content = width;
|
|
23409
|
-
const win = cellAddrWindow(xml,
|
|
24184
|
+
const win = cellAddrWindow(xml, cell2);
|
|
23410
24185
|
const mg = win?.match(/<[A-Za-z0-9]+:cellMargin\b[^>]*>/);
|
|
23411
24186
|
if (mg) {
|
|
23412
24187
|
content -= Number(attrOf(mg[0], "left") ?? 0) + Number(attrOf(mg[0], "right") ?? 0);
|
|
23413
24188
|
}
|
|
23414
24189
|
return content > 0 ? content / HU_PER_MM2 : null;
|
|
23415
24190
|
}
|
|
23416
|
-
function cellLeftOffsetMm(xml,
|
|
23417
|
-
if (
|
|
24191
|
+
function cellLeftOffsetMm(xml, table2, cell2) {
|
|
24192
|
+
if (cell2.colAddr === void 0) return 0;
|
|
23418
24193
|
const colW = /* @__PURE__ */ new Map();
|
|
23419
|
-
for (const row of
|
|
24194
|
+
for (const row of table2.rows) {
|
|
23420
24195
|
for (const c of row) {
|
|
23421
24196
|
if (c.colAddr === void 0 || colW.has(c.colAddr)) continue;
|
|
23422
24197
|
if (c.colSpan > 1) continue;
|
|
@@ -23425,7 +24200,7 @@ function cellLeftOffsetMm(xml, table, cell) {
|
|
|
23425
24200
|
}
|
|
23426
24201
|
}
|
|
23427
24202
|
let sum = 0;
|
|
23428
|
-
for (let col = 0; col <
|
|
24203
|
+
for (let col = 0; col < cell2.colAddr; col++) sum += colW.get(col) ?? 0;
|
|
23429
24204
|
return sum / HU_PER_MM2;
|
|
23430
24205
|
}
|
|
23431
24206
|
function bodyColumnWidthMm(xml) {
|
|
@@ -23664,8 +24439,8 @@ function parseCharPrs(headerDoc) {
|
|
|
23664
24439
|
}
|
|
23665
24440
|
return map;
|
|
23666
24441
|
}
|
|
23667
|
-
function isTopLevelTable(
|
|
23668
|
-
let p =
|
|
24442
|
+
function isTopLevelTable(tbl2) {
|
|
24443
|
+
let p = tbl2.parentNode;
|
|
23669
24444
|
while (p) {
|
|
23670
24445
|
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
23671
24446
|
if (tag === "tbl") return false;
|
|
@@ -23678,45 +24453,45 @@ function num(s) {
|
|
|
23678
24453
|
const n = parseInt(s, 10);
|
|
23679
24454
|
return Number.isFinite(n) ? n : void 0;
|
|
23680
24455
|
}
|
|
23681
|
-
function parseTable3(
|
|
23682
|
-
const rows = num(
|
|
23683
|
-
const cols = num(
|
|
23684
|
-
const sz = findChildByLocalName(
|
|
24456
|
+
function parseTable3(tbl2, tableIndex, borderFills, charPrs) {
|
|
24457
|
+
const rows = num(tbl2.getAttribute("rowCnt")) ?? 0;
|
|
24458
|
+
const cols = num(tbl2.getAttribute("colCnt")) ?? 0;
|
|
24459
|
+
const sz = findChildByLocalName(tbl2, "sz");
|
|
23685
24460
|
const width = sz?.getAttribute("width") || void 0;
|
|
23686
24461
|
const cells = [];
|
|
23687
24462
|
const usedBf = /* @__PURE__ */ new Set();
|
|
23688
24463
|
const usedCp = /* @__PURE__ */ new Set();
|
|
23689
24464
|
const colWidths = new Array(cols).fill(void 0);
|
|
23690
24465
|
let anchorText = "";
|
|
23691
|
-
for (const
|
|
23692
|
-
if (nearestTable(
|
|
23693
|
-
const addr = findChildByLocalName(
|
|
23694
|
-
const span = findChildByLocalName(
|
|
23695
|
-
const csz = findChildByLocalName(
|
|
24466
|
+
for (const tc2 of elemsByLocal(tbl2, "tc")) {
|
|
24467
|
+
if (nearestTable(tc2) !== tbl2) continue;
|
|
24468
|
+
const addr = findChildByLocalName(tc2, "cellAddr");
|
|
24469
|
+
const span = findChildByLocalName(tc2, "cellSpan");
|
|
24470
|
+
const csz = findChildByLocalName(tc2, "cellSz");
|
|
23696
24471
|
const row = num(addr?.getAttribute("rowAddr")) ?? 0;
|
|
23697
24472
|
const col = num(addr?.getAttribute("colAddr")) ?? 0;
|
|
23698
|
-
if (row === 0 && col === 0 && !anchorText) anchorText = directCellText(
|
|
24473
|
+
if (row === 0 && col === 0 && !anchorText) anchorText = directCellText(tc2);
|
|
23699
24474
|
const colSpan = num(span?.getAttribute("colSpan")) ?? 1;
|
|
23700
24475
|
const rowSpan = num(span?.getAttribute("rowSpan")) ?? 1;
|
|
23701
|
-
const bfId =
|
|
23702
|
-
const cpId = firstRunCharPr(
|
|
23703
|
-
const
|
|
24476
|
+
const bfId = tc2.getAttribute("borderFillIDRef") || void 0;
|
|
24477
|
+
const cpId = firstRunCharPr(tc2);
|
|
24478
|
+
const cell2 = { row, col, rowSpan, colSpan };
|
|
23704
24479
|
const w = csz?.getAttribute("width");
|
|
23705
24480
|
const hh = csz?.getAttribute("height");
|
|
23706
|
-
if (w)
|
|
23707
|
-
if (hh)
|
|
24481
|
+
if (w) cell2.width_hwpunit = w;
|
|
24482
|
+
if (hh) cell2.height_hwpunit = hh;
|
|
23708
24483
|
if (bfId) {
|
|
23709
|
-
|
|
24484
|
+
cell2.borderFillIDRef = bfId;
|
|
23710
24485
|
usedBf.add(bfId);
|
|
23711
24486
|
}
|
|
23712
24487
|
if (cpId) {
|
|
23713
|
-
|
|
24488
|
+
cell2.charPrIDRef = cpId;
|
|
23714
24489
|
usedCp.add(cpId);
|
|
23715
24490
|
}
|
|
23716
|
-
cells.push(
|
|
24491
|
+
cells.push(cell2);
|
|
23717
24492
|
if (row === 0 && colSpan === 1 && col < cols && w) colWidths[col] = w;
|
|
23718
24493
|
}
|
|
23719
|
-
const
|
|
24494
|
+
const table2 = {
|
|
23720
24495
|
table_index: tableIndex,
|
|
23721
24496
|
rows,
|
|
23722
24497
|
cols,
|
|
@@ -23724,15 +24499,15 @@ function parseTable3(tbl, tableIndex, borderFills, charPrs) {
|
|
|
23724
24499
|
used_border_fills: pick(borderFills, usedBf)
|
|
23725
24500
|
};
|
|
23726
24501
|
const anchor = normalizeAnchor(anchorText);
|
|
23727
|
-
if (anchor)
|
|
23728
|
-
if (width)
|
|
23729
|
-
if (colWidths.every((w) => w != null))
|
|
24502
|
+
if (anchor) table2.anchor_text = anchor;
|
|
24503
|
+
if (width) table2.width_hwpunit = width;
|
|
24504
|
+
if (colWidths.every((w) => w != null)) table2.col_widths_hwpunit = colWidths;
|
|
23730
24505
|
const cp = pick(charPrs, usedCp);
|
|
23731
|
-
if (Object.keys(cp).length)
|
|
23732
|
-
return
|
|
24506
|
+
if (Object.keys(cp).length) table2.used_char_prs = cp;
|
|
24507
|
+
return table2;
|
|
23733
24508
|
}
|
|
23734
|
-
function nearestTable(
|
|
23735
|
-
let p =
|
|
24509
|
+
function nearestTable(tc2) {
|
|
24510
|
+
let p = tc2.parentNode;
|
|
23736
24511
|
while (p) {
|
|
23737
24512
|
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
23738
24513
|
if (tag === "tbl") return p;
|
|
@@ -23740,9 +24515,9 @@ function nearestTable(tc) {
|
|
|
23740
24515
|
}
|
|
23741
24516
|
return null;
|
|
23742
24517
|
}
|
|
23743
|
-
function firstRunCharPr(
|
|
23744
|
-
for (const run of elemsByLocal(
|
|
23745
|
-
if (nearestCell(run) !==
|
|
24518
|
+
function firstRunCharPr(tc2) {
|
|
24519
|
+
for (const run of elemsByLocal(tc2, "run")) {
|
|
24520
|
+
if (nearestCell(run) !== tc2) continue;
|
|
23746
24521
|
const id = run.getAttribute("charPrIDRef");
|
|
23747
24522
|
if (id) return id;
|
|
23748
24523
|
}
|
|
@@ -23757,10 +24532,10 @@ function nearestCell(el) {
|
|
|
23757
24532
|
}
|
|
23758
24533
|
return null;
|
|
23759
24534
|
}
|
|
23760
|
-
function directCellText(
|
|
24535
|
+
function directCellText(tc2) {
|
|
23761
24536
|
let out = "";
|
|
23762
|
-
for (const t of elemsByLocal(
|
|
23763
|
-
if (nearestCell(t) !==
|
|
24537
|
+
for (const t of elemsByLocal(tc2, "t")) {
|
|
24538
|
+
if (nearestCell(t) !== tc2) continue;
|
|
23764
24539
|
out += t.textContent ?? "";
|
|
23765
24540
|
if (out.length >= 64) break;
|
|
23766
24541
|
}
|
|
@@ -23789,14 +24564,304 @@ async function hwpxToProfile(input) {
|
|
|
23789
24564
|
let tableIndex = 0;
|
|
23790
24565
|
for (const f of sectionFiles) {
|
|
23791
24566
|
const doc = parser.parseFromString(await f.async("text"), "text/xml");
|
|
23792
|
-
for (const
|
|
23793
|
-
if (!isTopLevelTable(
|
|
23794
|
-
tables.push(parseTable3(
|
|
24567
|
+
for (const tbl2 of elemsByLocal(doc, "tbl")) {
|
|
24568
|
+
if (!isTopLevelTable(tbl2)) continue;
|
|
24569
|
+
tables.push(parseTable3(tbl2, tableIndex++, borderFills, charPrs));
|
|
23795
24570
|
}
|
|
23796
24571
|
}
|
|
23797
24572
|
return { schema_version: "0.2.0", tables };
|
|
23798
24573
|
}
|
|
23799
24574
|
|
|
24575
|
+
// src/hwpx/font-catalog.ts
|
|
24576
|
+
var HANCOM_BUNDLED = [
|
|
24577
|
+
"\uD568\uCD08\uB86C\uBC14\uD0D5",
|
|
24578
|
+
"\uD568\uCD08\uB86C\uB3CB\uC6C0",
|
|
24579
|
+
"\uD55C\uCEF4\uBC14\uD0D5",
|
|
24580
|
+
"\uD55C\uCEF4\uB3CB\uC6C0",
|
|
24581
|
+
"\uD55C\uCEF4 \uACE0\uB515",
|
|
24582
|
+
"\uD55C\uCEF4\uACE0\uB515",
|
|
24583
|
+
"\uD55C\uCEF4 \uB9D0\uB791\uB9D0\uB791",
|
|
24584
|
+
"\uD55C\uCEF4\uC0B0\uB73B\uB3CB\uC6C0",
|
|
24585
|
+
"\uD55C\uCEF4\uC194\uC78E",
|
|
24586
|
+
"HY\uD5E4\uB4DC\uB77C\uC778M",
|
|
24587
|
+
"HY\uACAC\uACE0\uB515",
|
|
24588
|
+
"HY\uACAC\uBA85\uC870",
|
|
24589
|
+
"HY\uC911\uACE0\uB515",
|
|
24590
|
+
"HY\uC2E0\uBA85\uC870",
|
|
24591
|
+
"HY\uBA85\uC870",
|
|
24592
|
+
"HY\uADF8\uB798\uD53DM",
|
|
24593
|
+
"HY\uAD81\uC11C",
|
|
24594
|
+
"HY\uAC15M",
|
|
24595
|
+
"HY\uAC15B",
|
|
24596
|
+
"HY\uC6B8\uB989\uB3C4M",
|
|
24597
|
+
"HY\uC6B8\uB989\uB3C4B",
|
|
24598
|
+
"HY\uD0DC\uBC31B",
|
|
24599
|
+
"HY\uC218\uD3C9\uC120M",
|
|
24600
|
+
"HY\uC218\uD3C9\uC120B",
|
|
24601
|
+
"HY\uC13C\uC2A4L",
|
|
24602
|
+
"HY\uC595\uC740\uC0D8\uBB3CM",
|
|
24603
|
+
"HY\uBAA9\uD310L",
|
|
24604
|
+
"HY\uC5FD\uC11CM",
|
|
24605
|
+
"HY\uC5FD\uC11CL",
|
|
24606
|
+
"HY\uB3D9\uB158M",
|
|
24607
|
+
"HY\uB3D9\uB158B",
|
|
24608
|
+
"\uD55C\uC591\uC2E0\uBA85\uC870",
|
|
24609
|
+
"\uD55C\uC591\uC911\uACE0\uB515",
|
|
24610
|
+
"\uD55C\uC591\uACAC\uBA85\uC870",
|
|
24611
|
+
"\uD55C\uC591\uACAC\uACE0\uB515",
|
|
24612
|
+
"\uD55C\uC591\uAD81\uC11C",
|
|
24613
|
+
"\uD55C\uC591\uADF8\uB798\uD53D",
|
|
24614
|
+
"\uD734\uBA3C\uBA85\uC870",
|
|
24615
|
+
"\uD734\uBA3C\uACE0\uB515",
|
|
24616
|
+
"\uD734\uBA3C\uAD75\uC740\uD338\uCCB4",
|
|
24617
|
+
"\uD734\uBA3C\uAC00\uB294\uD338\uCCB4",
|
|
24618
|
+
"\uD734\uBA3C\uAD75\uC740\uC0D8\uCCB4",
|
|
24619
|
+
"\uD734\uBA3C\uAC00\uB294\uC0D8\uCCB4",
|
|
24620
|
+
"\uD734\uBA3C\uC61B\uCCB4",
|
|
24621
|
+
"\uD734\uBA3C\uC544\uBBF8\uCCB4",
|
|
24622
|
+
"\uD734\uBA3C\uD3B8\uC9C0\uCCB4",
|
|
24623
|
+
"\uD734\uBA3C\uB465\uADFC\uD5E4\uB4DC\uB77C\uC778",
|
|
24624
|
+
"\uD734\uBA3C\uBAA8\uC74CT",
|
|
24625
|
+
"\uD0DC \uB098\uBB34",
|
|
24626
|
+
"\uD0DC \uADF8\uB298",
|
|
24627
|
+
"\uC591\uC7AC\uAE68\uBE44\uCCB4B",
|
|
24628
|
+
"\uC591\uC7AC\uB09C\uCD08\uCCB4M",
|
|
24629
|
+
"\uC591\uC7AC\uB458\uAE30\uCCB4M",
|
|
24630
|
+
"\uC591\uC7AC\uBE14\uB7ED\uCCB4",
|
|
24631
|
+
"\uBB38\uCCB4\uBD80 \uAD81\uCCB4 \uC815\uC790\uCCB4",
|
|
24632
|
+
"\uBB38\uCCB4\uBD80 \uAD81\uCCB4 \uD758\uB9BC\uCCB4",
|
|
24633
|
+
"\uBB38\uCCB4\uBD80 \uB3CB\uC6C0\uCCB4",
|
|
24634
|
+
"\uBB38\uCCB4\uBD80 \uBC14\uD0D5\uCCB4",
|
|
24635
|
+
"\uBB38\uCCB4\uBD80 \uC4F0\uAE30 \uC815\uCCB4",
|
|
24636
|
+
"\uBB38\uCCB4\uBD80 \uC81C\uBAA9 \uB3CB\uC6C0\uCCB4",
|
|
24637
|
+
"\uBB38\uCCB4\uBD80 \uC81C\uBAA9 \uBC14\uD0D5\uCCB4",
|
|
24638
|
+
"\uC2E0\uBA85 \uC2E0\uBA85\uC870",
|
|
24639
|
+
"\uC2E0\uBA85 \uC2E0\uC2E0\uBA85\uC870",
|
|
24640
|
+
"\uC2E0\uBA85 \uACAC\uBA85\uC870",
|
|
24641
|
+
"\uC2E0\uBA85 \uC911\uACE0\uB515",
|
|
24642
|
+
"\uC2E0\uBA85 \uD0DC\uACE0\uB515",
|
|
24643
|
+
"\uC2E0\uBA85 \uACAC\uACE0\uB515",
|
|
24644
|
+
"\uC2E0\uBA85 \uC2E0\uBB38\uBA85\uC870",
|
|
24645
|
+
"MD\uAC1C\uC131\uCCB4",
|
|
24646
|
+
"MD\uC544\uB871\uCCB4",
|
|
24647
|
+
"MD\uC194\uCCB4",
|
|
24648
|
+
"MD\uC774\uC19D\uCCB4",
|
|
24649
|
+
"MD\uC544\uD2B8\uCCB4",
|
|
24650
|
+
"\uAC00\uB294\uC548\uC0C1\uC218\uCCB4",
|
|
24651
|
+
"\uC911\uAC04\uC548\uC0C1\uC218\uCCB4",
|
|
24652
|
+
"\uAD75\uC740\uC548\uC0C1\uC218\uCCB4",
|
|
24653
|
+
"HCI Poppy",
|
|
24654
|
+
"HCI Tulip",
|
|
24655
|
+
"-\uC544\uC774\uB9AC\uC2A4M"
|
|
24656
|
+
];
|
|
24657
|
+
var WINDOWS_DEFAULT = [
|
|
24658
|
+
"\uB9D1\uC740 \uACE0\uB515",
|
|
24659
|
+
"\uB9D1\uC740\uACE0\uB515",
|
|
24660
|
+
"Malgun Gothic",
|
|
24661
|
+
"\uAD74\uB9BC",
|
|
24662
|
+
"\uAD74\uB9BC\uCCB4",
|
|
24663
|
+
"\uB3CB\uC6C0",
|
|
24664
|
+
"\uB3CB\uC6C0\uCCB4",
|
|
24665
|
+
"\uBC14\uD0D5",
|
|
24666
|
+
"\uBC14\uD0D5\uCCB4",
|
|
24667
|
+
"\uAD81\uC11C",
|
|
24668
|
+
"\uAD81\uC11C\uCCB4",
|
|
24669
|
+
"Arial",
|
|
24670
|
+
"Arial Black",
|
|
24671
|
+
"Times New Roman",
|
|
24672
|
+
"Courier New",
|
|
24673
|
+
"Consolas",
|
|
24674
|
+
"Calibri",
|
|
24675
|
+
"Cambria",
|
|
24676
|
+
"Segoe UI",
|
|
24677
|
+
"Tahoma",
|
|
24678
|
+
"Verdana",
|
|
24679
|
+
"Georgia",
|
|
24680
|
+
"Symbol"
|
|
24681
|
+
];
|
|
24682
|
+
var COMMON_FREE = [
|
|
24683
|
+
"\uB098\uB214\uACE0\uB515",
|
|
24684
|
+
"\uB098\uB214\uBA85\uC870",
|
|
24685
|
+
"\uB098\uB214\uBC14\uB978\uACE0\uB515",
|
|
24686
|
+
"\uB098\uB214\uC2A4\uD018\uC5B4",
|
|
24687
|
+
"\uB098\uB214\uC190\uAE00\uC528 \uBD93",
|
|
24688
|
+
"\uB098\uB214\uC190\uAE00\uC528 \uD39C",
|
|
24689
|
+
"NanumGothic",
|
|
24690
|
+
"NanumMyeongjo",
|
|
24691
|
+
"Noto Sans KR",
|
|
24692
|
+
"Noto Serif KR",
|
|
24693
|
+
"\uBCF8\uACE0\uB515",
|
|
24694
|
+
"\uBCF8\uBA85\uC870",
|
|
24695
|
+
"Pretendard",
|
|
24696
|
+
"\uD504\uB9AC\uD150\uB2E4\uB4DC",
|
|
24697
|
+
"KoPub\uB3CB\uC6C0",
|
|
24698
|
+
"KoPub\uBC14\uD0D5",
|
|
24699
|
+
"KoPubWorld\uB3CB\uC6C0",
|
|
24700
|
+
"KoPubWorld\uBC14\uD0D5",
|
|
24701
|
+
"\uC5D0\uC2A4\uCF54\uC5B4 \uB4DC\uB9BC",
|
|
24702
|
+
"S-Core Dream",
|
|
24703
|
+
"G\uB9C8\uCF13 \uC0B0\uC2A4",
|
|
24704
|
+
"Gmarket Sans",
|
|
24705
|
+
"\uC724\uACE0\uB515",
|
|
24706
|
+
"\uC724\uACE0\uB515320",
|
|
24707
|
+
"\uC724\uACE0\uB515330",
|
|
24708
|
+
"\uC724\uACE0\uB515340",
|
|
24709
|
+
"\uC724\uBA85\uC870"
|
|
24710
|
+
];
|
|
24711
|
+
function norm(name) {
|
|
24712
|
+
return name.replace(/\s+/g, "").toLowerCase();
|
|
24713
|
+
}
|
|
24714
|
+
var KNOWN = new Set([...HANCOM_BUNDLED, ...WINDOWS_DEFAULT, ...COMMON_FREE].map(norm));
|
|
24715
|
+
function isKnownFont(name) {
|
|
24716
|
+
return KNOWN.has(norm(name));
|
|
24717
|
+
}
|
|
24718
|
+
function unknownFontWarnings(fonts) {
|
|
24719
|
+
const warnings = [];
|
|
24720
|
+
for (const [role, name] of Object.entries(fonts)) {
|
|
24721
|
+
if (!name || isKnownFont(name)) continue;
|
|
24722
|
+
warnings.push(
|
|
24723
|
+
`\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)`
|
|
24724
|
+
);
|
|
24725
|
+
}
|
|
24726
|
+
return warnings;
|
|
24727
|
+
}
|
|
24728
|
+
|
|
24729
|
+
// src/hwpx/gongmun-lint.ts
|
|
24730
|
+
var RULES = [
|
|
24731
|
+
// 날짜 ─ 온점 뒤 한 칸, 0 패딩 금지, 연도 4자리, 끝 마침표
|
|
24732
|
+
{
|
|
24733
|
+
code: "DATE_NO_SPACE",
|
|
24734
|
+
severity: "error",
|
|
24735
|
+
pattern: /\b\d{4}\.\d{1,2}\.\d{1,2}\.?/g,
|
|
24736
|
+
message: "\uB0A0\uC9DC \uC628\uC810 \uB4A4\uC5D0 \uD55C \uCE78\uC529 \uB744\uC6CC\uC57C \uD568",
|
|
24737
|
+
suggest: "\uC608) 2025. 1. 6."
|
|
24738
|
+
},
|
|
24739
|
+
{
|
|
24740
|
+
code: "DATE_ZERO_PAD",
|
|
24741
|
+
severity: "error",
|
|
24742
|
+
pattern: /\b\d{4}\.\s*0\d\.|\.\s*0\d\./g,
|
|
24743
|
+
message: "\uC6D4\xB7\uC77C \uC55E\uC758 '0'\uC740 \uD45C\uAE30\uD558\uC9C0 \uC54A\uC74C",
|
|
24744
|
+
suggest: "\uC608) 2025. 1. 6. (2025. 01. 06. \u2715)"
|
|
24745
|
+
},
|
|
24746
|
+
{
|
|
24747
|
+
code: "DATE_2DIGIT_YR",
|
|
24748
|
+
severity: "error",
|
|
24749
|
+
pattern: /(?<!\d)['’]\d{2}\.\s*\d/g,
|
|
24750
|
+
message: "\uC5F0\uB3C4\uB294 \uB124 \uC790\uB9AC\uB85C \uD45C\uAE30('24 \u2715)",
|
|
24751
|
+
suggest: "\uC608) 2025. 1. 6."
|
|
24752
|
+
},
|
|
24753
|
+
{
|
|
24754
|
+
code: "DATE_NO_END_DOT",
|
|
24755
|
+
severity: "warning",
|
|
24756
|
+
pattern: /\b\d{4}\.\s\d{1,2}\.\s\d{1,2}(?!\s*[.\d(])/g,
|
|
24757
|
+
message: "\uB0A0\uC9DC\uC758 '\uC77C' \uB2E4\uC74C\uC5D0 \uB9C8\uCE68\uD45C(.)\uB97C \uCC0D\uC5B4\uC57C \uD568",
|
|
24758
|
+
suggest: "\uC608) 2025. 1. 6."
|
|
24759
|
+
},
|
|
24760
|
+
// 시간 ─ 24시각제, 쌍점 붙여쓰기
|
|
24761
|
+
{
|
|
24762
|
+
code: "TIME_AMPM",
|
|
24763
|
+
severity: "error",
|
|
24764
|
+
pattern: /(오전|오후|아침|밤|낮)\s*\d{1,2}\s*시/g,
|
|
24765
|
+
message: "24\uC2DC\uAC01\uC81C \uC22B\uC790\uB85C \uD45C\uAE30(\uC624\uC804/\uC624\uD6C4 \uC0AC\uC6A9 \uC548 \uD568)",
|
|
24766
|
+
suggest: "\uC608) 09:00, 15:30"
|
|
24767
|
+
},
|
|
24768
|
+
{
|
|
24769
|
+
code: "TIME_24H",
|
|
24770
|
+
severity: "warning",
|
|
24771
|
+
pattern: /(?<!\d)24\s*시(?!각)/g,
|
|
24772
|
+
message: "'24\uC2DC'\uBCF4\uB2E4 \uC775\uC77C 00:00 \uB610\uB294 '18:00\uAE4C\uC9C0' \uAD8C\uC7A5",
|
|
24773
|
+
suggest: "\uC608) 18:00"
|
|
24774
|
+
},
|
|
24775
|
+
{
|
|
24776
|
+
code: "TIME_COLON_SP",
|
|
24777
|
+
severity: "error",
|
|
24778
|
+
pattern: /\b\d{1,2}\s+:\s*\d{2}\b|\b\d{1,2}:\s+\d{2}\b/g,
|
|
24779
|
+
message: "\uC2DC\uC640 \uBD84 \uC0AC\uC774 \uC30D\uC810\uC740 \uC591\uCABD\uC744 \uBD99\uC5EC \uC500",
|
|
24780
|
+
suggest: "\uC608) 13:20"
|
|
24781
|
+
},
|
|
24782
|
+
// 금액 ─ '천원' 금지, 금+숫자 붙여쓰기
|
|
24783
|
+
{
|
|
24784
|
+
code: "MONEY_CHEONWON",
|
|
24785
|
+
severity: "error",
|
|
24786
|
+
pattern: /\d+\s*천\s*원/g,
|
|
24787
|
+
message: "\uAE08\uC561\uC740 '\uCC9C\uC6D0'\uC73C\uB85C \uC904\uC774\uC9C0 \uC54A\uACE0 \uC544\uB77C\uBE44\uC544 \uC22B\uC790\uB85C",
|
|
24788
|
+
suggest: "\uC608) 345,000\uC6D0"
|
|
24789
|
+
},
|
|
24790
|
+
{
|
|
24791
|
+
code: "MONEY_GEUM_SP",
|
|
24792
|
+
severity: "warning",
|
|
24793
|
+
pattern: /금\s+\d/g,
|
|
24794
|
+
message: "'\uAE08'\uACFC \uC22B\uC790 \uC0AC\uC774\uB294 \uBD99\uC5EC \uC4F0\uB294 \uAC83\uC774 \uC6D0\uCE59",
|
|
24795
|
+
suggest: "\uC608) \uAE08113,560\uC6D0"
|
|
24796
|
+
},
|
|
24797
|
+
// 붙임 ─ 쌍점 금지(2타 띄움)
|
|
24798
|
+
{
|
|
24799
|
+
code: "BUNIM_COLON",
|
|
24800
|
+
severity: "error",
|
|
24801
|
+
pattern: /붙\s*임\s*:/g,
|
|
24802
|
+
message: "'\uBD99\uC784' \uB2E4\uC74C\uC5D0 \uC30D\uC810(:)\uC744 \uBD99\uC774\uC9C0 \uC54A\uC74C(2\uD0C0 \uB744\uC6C0)",
|
|
24803
|
+
suggest: "\uC608) \uBD99\uC784 \uACC4\uD68D\uC11C 1\uBD80."
|
|
24804
|
+
},
|
|
24805
|
+
// 표기 ─ 물결표+까지 중복, 한글 먼저, 쌍점 띄어쓰기
|
|
24806
|
+
{
|
|
24807
|
+
code: "KKAJI_DUP",
|
|
24808
|
+
severity: "error",
|
|
24809
|
+
pattern: /[∼~~][^\n]{0,20}?까지/g,
|
|
24810
|
+
message: "\uBB3C\uACB0\uD45C(\u223C)\uC640 '\uAE4C\uC9C0'\uB97C \uD568\uAED8 \uC4F0\uC9C0 \uC54A\uC74C",
|
|
24811
|
+
suggest: "\uC608) 2. 20.\u223C2. 24."
|
|
24812
|
+
},
|
|
24813
|
+
{
|
|
24814
|
+
code: "FOREIGN_FIRST",
|
|
24815
|
+
severity: "warning",
|
|
24816
|
+
pattern: /\b[A-Z]{2,5}\s*\([가-힣]/g,
|
|
24817
|
+
message: "\uD55C\uAE00\uC744 \uBA3C\uC800 \uC4F0\uACE0 \uAD04\uD638 \uC548\uC5D0 \uC678\uAD6D\uC5B4\uB97C \uBCD1\uAE30",
|
|
24818
|
+
suggest: "\uC608) \uC5C5\uBB34 \uD611\uC57D(MOU)"
|
|
24819
|
+
},
|
|
24820
|
+
// 쌍점 — URL(https:// 등)·시각(13:20)은 제외
|
|
24821
|
+
{
|
|
24822
|
+
code: "COLON_SPACE",
|
|
24823
|
+
severity: "warning",
|
|
24824
|
+
pattern: /\S\s+:\S|\S:(?!\/\/)[^\s\d]/g,
|
|
24825
|
+
message: "\uC30D\uC810\uC740 \uC55E\uB9D0\uC5D0 \uBD99\uC774\uACE0 \uB4A4\uB294 \uD55C \uCE78 \uB744\uC6C0",
|
|
24826
|
+
suggest: "\uC608) \uC6D0\uC7A5: \uAE40\uAC11\uB3D9"
|
|
24827
|
+
}
|
|
24828
|
+
];
|
|
24829
|
+
function lintGongmunText(text) {
|
|
24830
|
+
const findings = [];
|
|
24831
|
+
let inFence = false;
|
|
24832
|
+
const lines = text.split(/\r?\n/);
|
|
24833
|
+
for (let i = 0; i < lines.length; i++) {
|
|
24834
|
+
const line = lines[i];
|
|
24835
|
+
if (/^\s*(```|~~~)/.test(line)) {
|
|
24836
|
+
inFence = !inFence;
|
|
24837
|
+
continue;
|
|
24838
|
+
}
|
|
24839
|
+
if (inFence) continue;
|
|
24840
|
+
for (const r of RULES) {
|
|
24841
|
+
r.pattern.lastIndex = 0;
|
|
24842
|
+
for (const m of line.matchAll(r.pattern)) {
|
|
24843
|
+
findings.push({
|
|
24844
|
+
line: i + 1,
|
|
24845
|
+
match: m[0].trim(),
|
|
24846
|
+
rule: r.code,
|
|
24847
|
+
severity: r.severity,
|
|
24848
|
+
message: r.message,
|
|
24849
|
+
suggest: r.suggest
|
|
24850
|
+
});
|
|
24851
|
+
}
|
|
24852
|
+
}
|
|
24853
|
+
}
|
|
24854
|
+
return findings;
|
|
24855
|
+
}
|
|
24856
|
+
function gongmunLintWarnings(text, limit = 10) {
|
|
24857
|
+
const findings = lintGongmunText(text);
|
|
24858
|
+
const shown = findings.slice(0, limit).map(
|
|
24859
|
+
(f) => `\uD45C\uAE30\uBC95 [${f.rule}] L${f.line} "${f.match}" \u2014 ${f.message}${f.suggest ? ` (${f.suggest})` : ""}`
|
|
24860
|
+
);
|
|
24861
|
+
if (findings.length > limit) shown.push(`\uD45C\uAE30\uBC95 \uACBD\uACE0 ${findings.length - limit}\uAC74 \uB354 \uC788\uC74C \u2014 kordoc lint\uB85C \uC804\uCCB4 \uD655\uC778`);
|
|
24862
|
+
return shown;
|
|
24863
|
+
}
|
|
24864
|
+
|
|
23800
24865
|
// src/roundtrip/patcher.ts
|
|
23801
24866
|
import JSZip10 from "jszip";
|
|
23802
24867
|
|
|
@@ -23804,10 +24869,10 @@ import JSZip10 from "jszip";
|
|
|
23804
24869
|
var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
|
|
23805
24870
|
var TAG_AT_RE = /<[A-Za-z0-9_:]+(?:"[^"]*"|'[^']*'|[^>"'])*>/y;
|
|
23806
24871
|
function patchTableRows(input) {
|
|
23807
|
-
const { table, scanTable, ctx, skip, origKeys, editedKeys } = input;
|
|
24872
|
+
const { table: table2, scanTable, ctx, skip, origKeys, editedKeys } = input;
|
|
23808
24873
|
const xml = ctx.scans[scanTable.sectionIndex]?.xml;
|
|
23809
24874
|
if (!xml) return skip("\uC139\uC158 XML \uB9E4\uD551 \uC2E4\uD328");
|
|
23810
|
-
const numRows =
|
|
24875
|
+
const numRows = table2.rows;
|
|
23811
24876
|
if (origKeys.length !== numRows) return skip("\uD45C \uD589 \uC88C\uD45C \uBD88\uC77C\uCE58 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
23812
24877
|
if (scanTable.rows.length !== numRows || scanTable.rowRanges.length !== numRows) {
|
|
23813
24878
|
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");
|
|
@@ -23878,8 +24943,8 @@ function patchTableRows(input) {
|
|
|
23878
24943
|
if (template < 0) template = kept[0];
|
|
23879
24944
|
const cells = input.editedCells(ins.ei);
|
|
23880
24945
|
if (!cells) return skip("\uC0BD\uC785 \uD589\uC5D0 \uC774\uBBF8\uC9C0/\uC911\uCCA9\uD45C \uD3EC\uD568 \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
|
|
23881
|
-
for (const
|
|
23882
|
-
const unstable =
|
|
24946
|
+
for (const cell2 of cells) {
|
|
24947
|
+
const unstable = cell2.lines.find((l) => sanitizeText(l) !== l);
|
|
23883
24948
|
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");
|
|
23884
24949
|
}
|
|
23885
24950
|
const tmplCells = scanTable.rows[template];
|
|
@@ -23889,7 +24954,7 @@ function patchTableRows(input) {
|
|
|
23889
24954
|
}
|
|
23890
24955
|
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");
|
|
23891
24956
|
const tmplWidth = tmplCells.reduce((s, c) => s + c.colSpan, 0);
|
|
23892
|
-
if (tmplWidth !==
|
|
24957
|
+
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");
|
|
23893
24958
|
if (cells.length !== tmplCells.length) {
|
|
23894
24959
|
return skip(`\uC0BD\uC785 \uD589 \uC140 \uC218(${cells.length}) \u2260 \uAE30\uC900 \uD589 \uC140 \uC218(${tmplCells.length}) \u2014 \uBBF8\uC9C0\uC6D0`);
|
|
23895
24960
|
}
|
|
@@ -23946,8 +25011,8 @@ function patchTableRows(input) {
|
|
|
23946
25011
|
for (const k of keeps) {
|
|
23947
25012
|
const fi = finalIndex.get(k);
|
|
23948
25013
|
if (fi === k.oi) continue;
|
|
23949
|
-
for (const
|
|
23950
|
-
const sp = rowAddrRewrite(xml,
|
|
25014
|
+
for (const cell2 of scanTable.rows[k.oi]) {
|
|
25015
|
+
const sp = rowAddrRewrite(xml, cell2, fi);
|
|
23951
25016
|
if (sp) splices.push(sp);
|
|
23952
25017
|
}
|
|
23953
25018
|
}
|
|
@@ -23996,13 +25061,13 @@ function buildRowFragment(xml, scanTable, template, cells, finalRow, hasExplicit
|
|
|
23996
25061
|
const patched = applySplices(wrapped, splices);
|
|
23997
25062
|
return patched.slice(FRAG_OPEN.length, patched.length - FRAG_CLOSE.length);
|
|
23998
25063
|
}
|
|
23999
|
-
function rowAddrRewrite(xml,
|
|
24000
|
-
if (!
|
|
24001
|
-
const tag = xml.slice(
|
|
25064
|
+
function rowAddrRewrite(xml, cell2, newRow) {
|
|
25065
|
+
if (!cell2.addrTagRange) return null;
|
|
25066
|
+
const tag = xml.slice(cell2.addrTagRange.start, cell2.addrTagRange.end);
|
|
24002
25067
|
const m = tag.match(/\browAddr\s*=\s*"(\d+)"/);
|
|
24003
25068
|
if (!m || m.index === void 0) return null;
|
|
24004
25069
|
if (parseInt(m[1], 10) === newRow) return null;
|
|
24005
|
-
const valStart =
|
|
25070
|
+
const valStart = cell2.addrTagRange.start + m.index + m[0].indexOf('"') + 1;
|
|
24006
25071
|
return { start: valStart, end: valStart + m[1].length, replacement: String(newRow) };
|
|
24007
25072
|
}
|
|
24008
25073
|
function rowHeightOf(fragment) {
|
|
@@ -24028,8 +25093,8 @@ function tableSzHeightSplice(xml, scanTable, tblOpenLen, delta) {
|
|
|
24028
25093
|
}
|
|
24029
25094
|
|
|
24030
25095
|
// src/roundtrip/table-patch.ts
|
|
24031
|
-
function patchGfmTable(
|
|
24032
|
-
const replica = replicateGfmTable(
|
|
25096
|
+
function patchGfmTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
25097
|
+
const replica = replicateGfmTable(table2);
|
|
24033
25098
|
if (!replica) return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
24034
25099
|
const origRows = parseGfmTable(orig.lines);
|
|
24035
25100
|
const editedRows = parseGfmTable(edited.lines);
|
|
@@ -24037,15 +25102,15 @@ function patchGfmTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
24037
25102
|
return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
24038
25103
|
}
|
|
24039
25104
|
if (editedRows.length !== origRows.length) {
|
|
24040
|
-
return patchGfmTableRows(
|
|
25105
|
+
return patchGfmTableRows(table2, scanTable, origRows, editedRows, replica, ctx, skip);
|
|
24041
25106
|
}
|
|
24042
25107
|
let applied = 0;
|
|
24043
25108
|
for (let r = 0; r < origRows.length; r++) {
|
|
24044
|
-
applied += patchGfmRowPair(
|
|
25109
|
+
applied += patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, r, r, ctx, skip);
|
|
24045
25110
|
}
|
|
24046
25111
|
return applied;
|
|
24047
25112
|
}
|
|
24048
|
-
function patchGfmRowPair(
|
|
25113
|
+
function patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, r, er, ctx, skip) {
|
|
24049
25114
|
if (editedRows[er].length !== origRows[r].length) {
|
|
24050
25115
|
skip(`\uD45C ${r + 1}\uD589 \uC5F4 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
|
|
24051
25116
|
return 0;
|
|
@@ -24062,7 +25127,7 @@ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er,
|
|
|
24062
25127
|
}
|
|
24063
25128
|
const newLines = unescapeGfmCell(stripCellTokens(editedRows[er][c])).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
24064
25129
|
const origLines = unescapeGfmCell(stripCellTokens(origRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
24065
|
-
const n = applyCellEdit(
|
|
25130
|
+
const n = applyCellEdit(table2, scanTable, gridR, gridC, newLines, ctx, origRows[r][c], editedRows[er][c], origLines.length);
|
|
24066
25131
|
if (n > 0 && origTokens) {
|
|
24067
25132
|
ctx.skipped.push({
|
|
24068
25133
|
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)",
|
|
@@ -24075,19 +25140,19 @@ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er,
|
|
|
24075
25140
|
}
|
|
24076
25141
|
return applied;
|
|
24077
25142
|
}
|
|
24078
|
-
function patchGfmTableRows(
|
|
24079
|
-
if (replica.length !==
|
|
25143
|
+
function patchGfmTableRows(table2, scanTable, origRows, editedRows, replica, ctx, skip) {
|
|
25144
|
+
if (replica.length !== table2.rows || replica.some((row, r) => row.some((c) => c.gridR !== r))) {
|
|
24080
25145
|
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");
|
|
24081
25146
|
}
|
|
24082
|
-
if (
|
|
25147
|
+
if (table2.cells.some((row) => row.some((c) => c && (c.colSpan > 1 || c.rowSpan > 1)))) {
|
|
24083
25148
|
return skip("\uBCD1\uD569 \uC140 \uD45C \u2014 GFM \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
|
|
24084
25149
|
}
|
|
24085
|
-
if (!gfmRenderStable(editedRows,
|
|
25150
|
+
if (!gfmRenderStable(editedRows, table2.cols)) {
|
|
24086
25151
|
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");
|
|
24087
25152
|
}
|
|
24088
25153
|
const key = (row) => row.join("\0");
|
|
24089
25154
|
return patchTableRows({
|
|
24090
|
-
table,
|
|
25155
|
+
table: table2,
|
|
24091
25156
|
scanTable,
|
|
24092
25157
|
ctx,
|
|
24093
25158
|
skip,
|
|
@@ -24102,7 +25167,7 @@ function patchGfmTableRows(table, scanTable, origRows, editedRows, replica, ctx,
|
|
|
24102
25167
|
}
|
|
24103
25168
|
return cells;
|
|
24104
25169
|
},
|
|
24105
|
-
patchMatched: (oi, ei) => patchGfmRowPair(
|
|
25170
|
+
patchMatched: (oi, ei) => patchGfmRowPair(table2, scanTable, origRows, editedRows, replica, oi, ei, ctx, skip)
|
|
24106
25171
|
});
|
|
24107
25172
|
}
|
|
24108
25173
|
function gfmRenderStable(editedRows, cols) {
|
|
@@ -24119,13 +25184,13 @@ function gfmRenderStable(editedRows, cols) {
|
|
|
24119
25184
|
if (!replica || replica.length !== editedRows.length) return false;
|
|
24120
25185
|
return replica.every((row, r) => row.length === editedRows[r].length && row.every((c, j) => c.text === editedRows[r][j]));
|
|
24121
25186
|
}
|
|
24122
|
-
function patchHtmlTable(
|
|
24123
|
-
return patchHtmlTableRaw(
|
|
25187
|
+
function patchHtmlTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
25188
|
+
return patchHtmlTableRaw(table2, scanTable, orig.raw, edited.raw, ctx, skip, 0);
|
|
24124
25189
|
}
|
|
24125
|
-
function patchHtmlTableRaw(
|
|
25190
|
+
function patchHtmlTableRaw(table2, scanTable, origRaw, editedRaw, ctx, skip, depth) {
|
|
24126
25191
|
if (depth > 8) return skip("\uC911\uCCA9\uD45C \uAE4A\uC774 \uCD08\uACFC");
|
|
24127
|
-
if (replicateTableToHtml(
|
|
24128
|
-
const replica = replicateHtmlTable(
|
|
25192
|
+
if (replicateTableToHtml(table2) !== origRaw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
25193
|
+
const replica = replicateHtmlTable(table2);
|
|
24129
25194
|
const origRows = parseHtmlTable(origRaw);
|
|
24130
25195
|
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))) {
|
|
24131
25196
|
return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -24133,15 +25198,15 @@ function patchHtmlTableRaw(table, scanTable, origRaw, editedRaw, ctx, skip, dept
|
|
|
24133
25198
|
const editedRows = parseHtmlTable(editedRaw);
|
|
24134
25199
|
if (!editedRows) return skip("\uD3B8\uC9D1\uB41C HTML \uD45C \uD30C\uC2F1 \uC2E4\uD328");
|
|
24135
25200
|
if (editedRows.length !== replica.length) {
|
|
24136
|
-
return patchHtmlTableRows(
|
|
25201
|
+
return patchHtmlTableRows(table2, scanTable, replica, editedRows, ctx, skip, depth);
|
|
24137
25202
|
}
|
|
24138
25203
|
let applied = 0;
|
|
24139
25204
|
for (let r = 0; r < replica.length; r++) {
|
|
24140
|
-
applied += patchHtmlRowPair(
|
|
25205
|
+
applied += patchHtmlRowPair(table2, scanTable, replica, editedRows, r, r, ctx, skip, depth);
|
|
24141
25206
|
}
|
|
24142
25207
|
return applied;
|
|
24143
25208
|
}
|
|
24144
|
-
function patchHtmlRowPair(
|
|
25209
|
+
function patchHtmlRowPair(table2, scanTable, replica, editedRows, r, er, ctx, skip, depth) {
|
|
24145
25210
|
if (editedRows[er].cells.length !== replica[r].cells.length) {
|
|
24146
25211
|
skip(`\uD45C ${r + 1}\uD589 \uC140 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
|
|
24147
25212
|
return 0;
|
|
@@ -24169,23 +25234,23 @@ function patchHtmlRowPair(table, scanTable, replica, editedRows, r, er, ctx, ski
|
|
|
24169
25234
|
continue;
|
|
24170
25235
|
}
|
|
24171
25236
|
if (origTables.join("\n") !== editedTables.join("\n")) {
|
|
24172
|
-
applied += patchNestedTables(
|
|
25237
|
+
applied += patchNestedTables(table2, scanTable, oc, origTables, editedTables, ctx, skip, depth);
|
|
24173
25238
|
}
|
|
24174
25239
|
}
|
|
24175
25240
|
if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
|
|
24176
25241
|
const newLines = editedContent.lines.map((l) => unescapeGfm(l));
|
|
24177
|
-
applied += applyCellEdit(
|
|
25242
|
+
applied += applyCellEdit(table2, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
|
|
24178
25243
|
}
|
|
24179
25244
|
}
|
|
24180
25245
|
return applied;
|
|
24181
25246
|
}
|
|
24182
|
-
function patchHtmlTableRows(
|
|
24183
|
-
if (replica.length !==
|
|
25247
|
+
function patchHtmlTableRows(table2, scanTable, replica, editedRows, ctx, skip, depth) {
|
|
25248
|
+
if (replica.length !== table2.rows || replica.some((row, r) => row.cells.some((c) => c.gridR !== r))) {
|
|
24184
25249
|
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");
|
|
24185
25250
|
}
|
|
24186
25251
|
const key = (row) => row.cells.map((c) => `${c.colSpan}x${c.rowSpan}:${c.inner}`).join("\0");
|
|
24187
25252
|
return patchTableRows({
|
|
24188
|
-
table,
|
|
25253
|
+
table: table2,
|
|
24189
25254
|
scanTable,
|
|
24190
25255
|
ctx,
|
|
24191
25256
|
skip,
|
|
@@ -24193,18 +25258,18 @@ function patchHtmlTableRows(table, scanTable, replica, editedRows, ctx, skip, de
|
|
|
24193
25258
|
editedKeys: editedRows.map(key),
|
|
24194
25259
|
editedCells: (ei) => {
|
|
24195
25260
|
const cells = [];
|
|
24196
|
-
for (const
|
|
24197
|
-
const content = htmlCellInnerToLines(
|
|
25261
|
+
for (const cell2 of editedRows[ei].cells) {
|
|
25262
|
+
const content = htmlCellInnerToLines(cell2.inner);
|
|
24198
25263
|
if (content.hadNonText) return null;
|
|
24199
|
-
cells.push({ lines: content.lines.map((l) => unescapeGfm(l)), colSpan:
|
|
25264
|
+
cells.push({ lines: content.lines.map((l) => unescapeGfm(l)), colSpan: cell2.colSpan, rowSpan: cell2.rowSpan });
|
|
24200
25265
|
}
|
|
24201
25266
|
return cells;
|
|
24202
25267
|
},
|
|
24203
|
-
patchMatched: (oi, ei) => patchHtmlRowPair(
|
|
25268
|
+
patchMatched: (oi, ei) => patchHtmlRowPair(table2, scanTable, replica, editedRows, oi, ei, ctx, skip, depth)
|
|
24204
25269
|
});
|
|
24205
25270
|
}
|
|
24206
|
-
function patchNestedTables(
|
|
24207
|
-
const irCell =
|
|
25271
|
+
function patchNestedTables(table2, scanTable, oc, origTables, editedTables, ctx, skip, depth) {
|
|
25272
|
+
const irCell = table2.cells[oc.gridR]?.[oc.gridC];
|
|
24208
25273
|
const scanCell = scanTable.cellByAnchor.get(`${oc.gridR},${oc.gridC}`);
|
|
24209
25274
|
const nestedIRs = (irCell?.blocks ?? []).filter((b) => b.type === "table" && b.table).map((b) => b.table);
|
|
24210
25275
|
if (!scanCell || nestedIRs.length !== origTables.length || scanCell.tables.length !== origTables.length) {
|
|
@@ -24227,9 +25292,9 @@ function extractCellTokens(text) {
|
|
|
24227
25292
|
function stripCellTokens(text) {
|
|
24228
25293
|
return text.replace(CELL_TOKEN_RE, "");
|
|
24229
25294
|
}
|
|
24230
|
-
function patchTextChunkTable(
|
|
24231
|
-
if (
|
|
24232
|
-
const content = sanitizeText(
|
|
25295
|
+
function patchTextChunkTable(table2, scanTable, orig, edited, ctx, skip) {
|
|
25296
|
+
if (table2.rows === 1 && table2.cols === 1) {
|
|
25297
|
+
const content = sanitizeText(table2.cells[0][0].text);
|
|
24233
25298
|
const replicaLines = content.split(/\n/).map((line) => {
|
|
24234
25299
|
const t = line.trim();
|
|
24235
25300
|
if (!t) return "";
|
|
@@ -24243,12 +25308,12 @@ function patchTextChunkTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
24243
25308
|
const unwrap = m && /^\d+\.\s/.test(unescapeGfm(m[1]));
|
|
24244
25309
|
return stripCellTokens(unescapeGfm(unwrap ? m[1] : l)).trim();
|
|
24245
25310
|
}).filter(Boolean);
|
|
24246
|
-
return applyCellEdit(
|
|
25311
|
+
return applyCellEdit(table2, scanTable, 0, 0, newLines, ctx, orig.raw, edited.raw, orig.lines.length);
|
|
24247
25312
|
}
|
|
24248
|
-
if (
|
|
25313
|
+
if (table2.cols === 1 && table2.rows >= 2) {
|
|
24249
25314
|
const replica = [];
|
|
24250
|
-
for (let r = 0; r <
|
|
24251
|
-
const line = escapeGfm(sanitizeText(
|
|
25315
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
25316
|
+
const line = escapeGfm(sanitizeText(table2.cells[r][0].text)).replace(/\n/g, " ");
|
|
24252
25317
|
if (line) replica.push({ line, gridR: r });
|
|
24253
25318
|
}
|
|
24254
25319
|
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");
|
|
@@ -24261,21 +25326,21 @@ function patchTextChunkTable(table, scanTable, orig, edited, ctx, skip) {
|
|
|
24261
25326
|
continue;
|
|
24262
25327
|
}
|
|
24263
25328
|
const newLines = [stripCellTokens(unescapeGfm(edited.lines[i])).trim()].filter(Boolean);
|
|
24264
|
-
applied += applyCellEdit(
|
|
25329
|
+
applied += applyCellEdit(table2, scanTable, replica[i].gridR, 0, newLines, ctx, replica[i].line, edited.lines[i], 1);
|
|
24265
25330
|
}
|
|
24266
25331
|
return applied;
|
|
24267
25332
|
}
|
|
24268
25333
|
return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
24269
25334
|
}
|
|
24270
|
-
function applyCellEdit(
|
|
25335
|
+
function applyCellEdit(table2, scanTable, gridR, gridC, newLines, ctx, before, after, origLineCount) {
|
|
24271
25336
|
const skip = (reason) => {
|
|
24272
25337
|
ctx.skipped.push({ reason, before: summarize(before), after: summarize(after) });
|
|
24273
25338
|
return 0;
|
|
24274
25339
|
};
|
|
24275
|
-
const
|
|
24276
|
-
if (!
|
|
24277
|
-
const irCell =
|
|
24278
|
-
const scanJoined =
|
|
25340
|
+
const cell2 = scanTable.cellByAnchor.get(`${gridR},${gridC}`);
|
|
25341
|
+
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)");
|
|
25342
|
+
const irCell = table2.cells[gridR]?.[gridC];
|
|
25343
|
+
const scanJoined = cell2.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
|
|
24279
25344
|
if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
24280
25345
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
24281
25346
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -24285,7 +25350,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
|
|
|
24285
25350
|
}
|
|
24286
25351
|
}
|
|
24287
25352
|
}
|
|
24288
|
-
const nonEmpty =
|
|
25353
|
+
const nonEmpty = cell2.paragraphs.filter((p) => normForMatch(p.text) !== "");
|
|
24289
25354
|
if (origLineCount !== void 0 && nonEmpty.length > 0 && origLineCount !== nonEmpty.length) {
|
|
24290
25355
|
return skip("\uC140 \uC904 \uACBD\uACC4 \uB9E4\uD551 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 <br>/\uBB38\uB2E8 \uB0B4 \uC904\uBC14\uAFC8) \u2014 \uBBF8\uC9C0\uC6D0");
|
|
24291
25356
|
}
|
|
@@ -24295,7 +25360,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
|
|
|
24295
25360
|
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");
|
|
24296
25361
|
if (nonEmpty.length === 0) {
|
|
24297
25362
|
if (newLines.length === 0) return 0;
|
|
24298
|
-
const target =
|
|
25363
|
+
const target = cell2.paragraphs[0];
|
|
24299
25364
|
if (!target) return skip("\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00");
|
|
24300
25365
|
const sp = buildParagraphSplices(target, newLines.join(" "), ctx.scans[target.sectionIndex]?.xml);
|
|
24301
25366
|
if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
|
|
@@ -24380,16 +25445,16 @@ function buildTableParagraphXml(rows, opts) {
|
|
|
24380
25445
|
const trElements = rows.map((row, rowIdx) => {
|
|
24381
25446
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
24382
25447
|
const isHeaderRow = rowIdx === 0;
|
|
24383
|
-
const tdElements = cells.map((
|
|
24384
|
-
const text = escapeXmlText(cellPlainText(
|
|
25448
|
+
const tdElements = cells.map((cell2, colIdx) => {
|
|
25449
|
+
const text = escapeXmlText(cellPlainText(cell2));
|
|
24385
25450
|
const cellP = `<hp:p paraPrIDRef="${cellParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}"><hp:t>${text}</hp:t></hp:run></hp:p>`;
|
|
24386
25451
|
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>`;
|
|
24387
25452
|
}).join("");
|
|
24388
25453
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
24389
25454
|
}).join("");
|
|
24390
25455
|
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;
|
|
24391
|
-
const
|
|
24392
|
-
return `<hp:p paraPrIDRef="${outerParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}">${
|
|
25456
|
+
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>`;
|
|
25457
|
+
return `<hp:p paraPrIDRef="${outerParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}">${tbl2}</hp:run></hp:p>`;
|
|
24393
25458
|
}
|
|
24394
25459
|
|
|
24395
25460
|
// src/roundtrip/hwpx-entries.ts
|
|
@@ -24561,12 +25626,12 @@ function buildTableOrdinals(blocks) {
|
|
|
24561
25626
|
function resolveParagraphMappings(blocks, scans) {
|
|
24562
25627
|
const buckets = /* @__PURE__ */ new Map();
|
|
24563
25628
|
for (const scan of scans) {
|
|
24564
|
-
for (const
|
|
24565
|
-
const key = normForMatch(
|
|
25629
|
+
for (const para2 of scan.bodyParagraphs) {
|
|
25630
|
+
const key = normForMatch(para2.text);
|
|
24566
25631
|
if (!key) continue;
|
|
24567
25632
|
let list = buckets.get(key);
|
|
24568
25633
|
if (!list) buckets.set(key, list = []);
|
|
24569
|
-
list.push(
|
|
25634
|
+
list.push(para2);
|
|
24570
25635
|
}
|
|
24571
25636
|
}
|
|
24572
25637
|
const headerNorms = new Set(scans.flatMap((s) => s.headerTexts.map(normForMatch)).filter(Boolean));
|
|
@@ -24652,11 +25717,11 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
24652
25717
|
if (!ti) return skip("\uBB38\uB2E8\u2192\uD45C \uBCC0\uD658 \uBD88\uAC00 \u2014 header \uC5D4\uD2B8\uB9AC(borderFills) \uD574\uC11D \uC2E4\uD328");
|
|
24653
25718
|
const mapping = ctx.paraMap.get(orig.blockIdx);
|
|
24654
25719
|
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");
|
|
24655
|
-
const
|
|
24656
|
-
if (
|
|
24657
|
-
const scan = ctx.scans[
|
|
25720
|
+
const para2 = mapping.para;
|
|
25721
|
+
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");
|
|
25722
|
+
const scan = ctx.scans[para2.sectionIndex];
|
|
24658
25723
|
if (!scan) return skip("\uC139\uC158 \uB9E4\uD551 \uC2E4\uD328");
|
|
24659
|
-
const pEnd = findElementEnd(scan.xml,
|
|
25724
|
+
const pEnd = findElementEnd(scan.xml, para2.start);
|
|
24660
25725
|
if (pEnd < 0) return skip("\uBB38\uB2E8 \uB05D \uC704\uCE58 \uD0D0\uC0C9 \uC2E4\uD328");
|
|
24661
25726
|
const rows = parseGfmTable(edited.lines);
|
|
24662
25727
|
if (rows.length === 0 || rows.every((r) => r.length === 0)) return skip("\uD45C \uB0B4\uC6A9\uC774 \uBE44\uC5B4 \uC788\uC74C");
|
|
@@ -24666,7 +25731,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
24666
25731
|
ti.borderFillId = inj.borderFillId;
|
|
24667
25732
|
ti.headerSplices.push(...inj.headerSplices);
|
|
24668
25733
|
}
|
|
24669
|
-
const outerParaPrId = extractParaPrIdRef(scan.xml,
|
|
25734
|
+
const outerParaPrId = extractParaPrIdRef(scan.xml, para2.start) ?? 0;
|
|
24670
25735
|
const tableXml = buildTableParagraphXml(rows, {
|
|
24671
25736
|
borderFillId: ti.borderFillId,
|
|
24672
25737
|
outerParaPrId,
|
|
@@ -24674,7 +25739,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
|
|
|
24674
25739
|
cellCharPrId: 0,
|
|
24675
25740
|
tableId: ti.nextId++
|
|
24676
25741
|
});
|
|
24677
|
-
ctx.sectionSplices[
|
|
25742
|
+
ctx.sectionSplices[para2.sectionIndex].push({ start: para2.start, end: pEnd, replacement: tableXml });
|
|
24678
25743
|
return 1;
|
|
24679
25744
|
}
|
|
24680
25745
|
function patchParagraphUnit(block, orig, edited, ctx, skip) {
|
|
@@ -25155,7 +26220,7 @@ function scanSection(stream, sectionIndex, compressed) {
|
|
|
25155
26220
|
}
|
|
25156
26221
|
}
|
|
25157
26222
|
const kind = !ctrlSeen || !nonGso ? "body" : "other";
|
|
25158
|
-
const
|
|
26223
|
+
const para2 = {
|
|
25159
26224
|
sectionIndex,
|
|
25160
26225
|
headerIdx: i,
|
|
25161
26226
|
kind,
|
|
@@ -25167,8 +26232,8 @@ function scanSection(stream, sectionIndex, compressed) {
|
|
|
25167
26232
|
nCharsRaw: rec.data.readUInt32LE(0),
|
|
25168
26233
|
rawText: state.text
|
|
25169
26234
|
};
|
|
25170
|
-
paras.push(
|
|
25171
|
-
parasByHeader.set(i,
|
|
26235
|
+
paras.push(para2);
|
|
26236
|
+
parasByHeader.set(i, para2);
|
|
25172
26237
|
}
|
|
25173
26238
|
const tables = [];
|
|
25174
26239
|
for (let i = 0; i < records.length; i++) {
|
|
@@ -25321,13 +26386,13 @@ function msg(err) {
|
|
|
25321
26386
|
function resolveParaMappings(blocks, scans) {
|
|
25322
26387
|
const buckets = /* @__PURE__ */ new Map();
|
|
25323
26388
|
for (const scan of scans) {
|
|
25324
|
-
for (const
|
|
25325
|
-
if (
|
|
25326
|
-
const key = normForMatch(
|
|
26389
|
+
for (const para2 of scan.paras) {
|
|
26390
|
+
if (para2.kind === "other") continue;
|
|
26391
|
+
const key = normForMatch(para2.rawText);
|
|
25327
26392
|
if (!key) continue;
|
|
25328
26393
|
let list = buckets.get(key);
|
|
25329
26394
|
if (!list) buckets.set(key, list = []);
|
|
25330
|
-
list.push(
|
|
26395
|
+
list.push(para2);
|
|
25331
26396
|
}
|
|
25332
26397
|
}
|
|
25333
26398
|
const usable = (list) => list.length === 1 || list.every((p) => p.kind === "body");
|
|
@@ -25363,18 +26428,18 @@ function resolveTableMappings(blocks, scanTables) {
|
|
|
25363
26428
|
const result = /* @__PURE__ */ new Map();
|
|
25364
26429
|
let si = 0;
|
|
25365
26430
|
for (let i = 0; i < blocks.length; i++) {
|
|
25366
|
-
const
|
|
25367
|
-
if (blocks[i].type !== "table" || !
|
|
26431
|
+
const table2 = blocks[i].table;
|
|
26432
|
+
if (blocks[i].type !== "table" || !table2) continue;
|
|
25368
26433
|
const cands = [];
|
|
25369
26434
|
for (let k = si; k < scanTables.length; k++) {
|
|
25370
|
-
if (scanTables[k].rows ===
|
|
26435
|
+
if (scanTables[k].rows === table2.rows && scanTables[k].cols === table2.cols) cands.push(k);
|
|
25371
26436
|
}
|
|
25372
26437
|
if (cands.length === 0) continue;
|
|
25373
26438
|
let pick2 = cands[0];
|
|
25374
26439
|
if (cands.length > 1) {
|
|
25375
|
-
let best = tableContentScore(
|
|
26440
|
+
let best = tableContentScore(table2, scanTables[cands[0]]);
|
|
25376
26441
|
for (let ci = 1; ci < cands.length; ci++) {
|
|
25377
|
-
const sc = tableContentScore(
|
|
26442
|
+
const sc = tableContentScore(table2, scanTables[cands[ci]]);
|
|
25378
26443
|
if (sc > best) {
|
|
25379
26444
|
best = sc;
|
|
25380
26445
|
pick2 = cands[ci];
|
|
@@ -25475,14 +26540,14 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25475
26540
|
ctx.skipped.push({ reason, before: summarize(origRows[r][c]), after: summarize(editedRows[r][c]) });
|
|
25476
26541
|
return 0;
|
|
25477
26542
|
};
|
|
25478
|
-
const
|
|
25479
|
-
if (!
|
|
26543
|
+
const cell2 = scanTable.cells.get(`${r},${c}`);
|
|
26544
|
+
if (!cell2) {
|
|
25480
26545
|
cellSkip("\uBCD1\uD569 \uC601\uC5ED \uC140 \u2014 \uC575\uCEE4 \uC140\uC774 \uC544\uB2C8\uBBC0\uB85C \uBBF8\uC9C0\uC6D0");
|
|
25481
26546
|
continue;
|
|
25482
26547
|
}
|
|
25483
26548
|
const beforeParts = origRows[r][c].split(/<br\s*\/?>/i);
|
|
25484
26549
|
const afterParts = editedRows[r][c].split(/<br\s*\/?>/i);
|
|
25485
|
-
if (
|
|
26550
|
+
if (cell2.paras.length === 1) {
|
|
25486
26551
|
const beforeEach = beforeParts.map(gfmCellToPlain);
|
|
25487
26552
|
const afterEach = afterParts.map(gfmCellToPlain);
|
|
25488
26553
|
if (beforeEach.some((p) => p === null) || afterEach.some((p) => p === null)) {
|
|
@@ -25492,8 +26557,8 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25492
26557
|
const before = beforeEach.join("\n");
|
|
25493
26558
|
const after = afterEach.join("\n");
|
|
25494
26559
|
if (before === after) continue;
|
|
25495
|
-
const
|
|
25496
|
-
if (normForMatch(
|
|
26560
|
+
const para2 = cell2.paras[0];
|
|
26561
|
+
if (normForMatch(para2.rawText) !== normForMatch(before)) {
|
|
25497
26562
|
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
25498
26563
|
continue;
|
|
25499
26564
|
}
|
|
@@ -25501,14 +26566,14 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25501
26566
|
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25502
26567
|
continue;
|
|
25503
26568
|
}
|
|
25504
|
-
applied += stageParaPatch(ctx.scans[
|
|
26569
|
+
applied += stageParaPatch(ctx.scans[para2.sectionIndex], para2, after, cellSkip);
|
|
25505
26570
|
continue;
|
|
25506
26571
|
}
|
|
25507
|
-
if (beforeParts.length !==
|
|
26572
|
+
if (beforeParts.length !== cell2.paras.length || afterParts.length !== cell2.paras.length) {
|
|
25508
26573
|
cellSkip("\uC140 \uBB38\uB2E8 \uC218 \uBCC0\uACBD \u2014 \uBBF8\uC9C0\uC6D0 (\uBB38\uB2E8 \uCD94\uAC00/\uC0AD\uC81C)");
|
|
25509
26574
|
continue;
|
|
25510
26575
|
}
|
|
25511
|
-
for (let k = 0; k <
|
|
26576
|
+
for (let k = 0; k < cell2.paras.length; k++) {
|
|
25512
26577
|
const before = gfmCellToPlain(beforeParts[k]);
|
|
25513
26578
|
const after = gfmCellToPlain(afterParts[k]);
|
|
25514
26579
|
if (before === null || after === null) {
|
|
@@ -25520,8 +26585,8 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25520
26585
|
cellSkip("\uC140 \uB0B4 \uC904\uBC14\uAFC8 \uCD94\uAC00\uB294 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
25521
26586
|
break;
|
|
25522
26587
|
}
|
|
25523
|
-
const
|
|
25524
|
-
if (normForMatch(
|
|
26588
|
+
const para2 = cell2.paras[k];
|
|
26589
|
+
if (normForMatch(para2.rawText) !== normForMatch(before)) {
|
|
25525
26590
|
cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
25526
26591
|
break;
|
|
25527
26592
|
}
|
|
@@ -25529,15 +26594,15 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
|
|
|
25529
26594
|
cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25530
26595
|
break;
|
|
25531
26596
|
}
|
|
25532
|
-
applied += stageParaPatch(ctx.scans[
|
|
26597
|
+
applied += stageParaPatch(ctx.scans[para2.sectionIndex], para2, after, cellSkip);
|
|
25533
26598
|
}
|
|
25534
26599
|
}
|
|
25535
26600
|
}
|
|
25536
26601
|
return applied;
|
|
25537
26602
|
}
|
|
25538
|
-
function patchHtmlCells5(
|
|
25539
|
-
if (replicateTableToHtml(
|
|
25540
|
-
const replica = replicateHtmlTable(
|
|
26603
|
+
function patchHtmlCells5(table2, scanTable, orig, edited, ctx, skip) {
|
|
26604
|
+
if (replicateTableToHtml(table2) !== orig.raw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
26605
|
+
const replica = replicateHtmlTable(table2);
|
|
25541
26606
|
const origRows = parseHtmlTable(orig.raw);
|
|
25542
26607
|
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))) {
|
|
25543
26608
|
return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
|
|
@@ -25573,15 +26638,15 @@ function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
25573
26638
|
}
|
|
25574
26639
|
if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
|
|
25575
26640
|
const newLines = editedContent.lines.map((l) => unescapeGfm(l));
|
|
25576
|
-
applied += applyCellEdit5(
|
|
26641
|
+
applied += applyCellEdit5(table2, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
|
|
25577
26642
|
}
|
|
25578
26643
|
}
|
|
25579
26644
|
}
|
|
25580
26645
|
return applied;
|
|
25581
26646
|
}
|
|
25582
|
-
function patchTextChunk5(
|
|
25583
|
-
if (
|
|
25584
|
-
const content = sanitizeText(
|
|
26647
|
+
function patchTextChunk5(table2, scanTable, orig, edited, ctx, skip) {
|
|
26648
|
+
if (table2.rows === 1 && table2.cols === 1) {
|
|
26649
|
+
const content = sanitizeText(table2.cells[0][0].text);
|
|
25585
26650
|
const replicaLines = content.split(/\n/).map((line) => {
|
|
25586
26651
|
const t = line.trim();
|
|
25587
26652
|
if (!t) return "";
|
|
@@ -25595,12 +26660,12 @@ function patchTextChunk5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
25595
26660
|
const unwrap = m && /^\d+\.\s/.test(unescapeGfm(m[1]));
|
|
25596
26661
|
return stripCellTokens(unescapeGfm(unwrap ? m[1] : l)).trim();
|
|
25597
26662
|
}).filter(Boolean);
|
|
25598
|
-
return applyCellEdit5(
|
|
26663
|
+
return applyCellEdit5(table2, scanTable, 0, 0, newLines, ctx, orig.raw, edited.raw, orig.lines.length);
|
|
25599
26664
|
}
|
|
25600
|
-
if (
|
|
26665
|
+
if (table2.cols === 1 && table2.rows >= 2) {
|
|
25601
26666
|
const replica = [];
|
|
25602
|
-
for (let r = 0; r <
|
|
25603
|
-
const line = escapeGfm(sanitizeText(
|
|
26667
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
26668
|
+
const line = escapeGfm(sanitizeText(table2.cells[r][0].text)).replace(/\n/g, " ");
|
|
25604
26669
|
if (line) replica.push({ line, gridR: r });
|
|
25605
26670
|
}
|
|
25606
26671
|
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");
|
|
@@ -25613,21 +26678,21 @@ function patchTextChunk5(table, scanTable, orig, edited, ctx, skip) {
|
|
|
25613
26678
|
continue;
|
|
25614
26679
|
}
|
|
25615
26680
|
const newLines = [stripCellTokens(unescapeGfm(edited.lines[i])).trim()].filter(Boolean);
|
|
25616
|
-
applied += applyCellEdit5(
|
|
26681
|
+
applied += applyCellEdit5(table2, scanTable, replica[i].gridR, 0, newLines, ctx, replica[i].line, edited.lines[i], 1);
|
|
25617
26682
|
}
|
|
25618
26683
|
return applied;
|
|
25619
26684
|
}
|
|
25620
26685
|
return skip("\uD45C \uB80C\uB354 \uACBD\uB85C \uC2DD\uBCC4 \uC2E4\uD328");
|
|
25621
26686
|
}
|
|
25622
|
-
function applyCellEdit5(
|
|
26687
|
+
function applyCellEdit5(table2, scanTable, gridR, gridC, newLines, ctx, before, after, origLineCount) {
|
|
25623
26688
|
const skip = (reason) => {
|
|
25624
26689
|
ctx.skipped.push({ reason, before: summarize(before), after: summarize(after) });
|
|
25625
26690
|
return 0;
|
|
25626
26691
|
};
|
|
25627
|
-
const
|
|
25628
|
-
if (!
|
|
25629
|
-
const irCell =
|
|
25630
|
-
const scanJoined =
|
|
26692
|
+
const cell2 = scanTable.cells.get(`${gridR},${gridC}`);
|
|
26693
|
+
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)");
|
|
26694
|
+
const irCell = table2.cells[gridR]?.[gridC];
|
|
26695
|
+
const scanJoined = cell2.paras.map((p) => p.rawText).filter((t) => normForMatch(t)).join("\n");
|
|
25631
26696
|
if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
25632
26697
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
25633
26698
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -25637,13 +26702,13 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
|
|
|
25637
26702
|
}
|
|
25638
26703
|
}
|
|
25639
26704
|
}
|
|
25640
|
-
const nonEmpty =
|
|
26705
|
+
const nonEmpty = cell2.paras.filter((p) => normForMatch(p.rawText) !== "");
|
|
25641
26706
|
if (origLineCount !== void 0 && nonEmpty.length > 0 && origLineCount !== nonEmpty.length) {
|
|
25642
26707
|
return skip("\uC140 \uC904 \uACBD\uACC4 \uB9E4\uD551 \uBAA8\uD638 (\uBB38\uB2E8 \uB0B4 \uC904\uBC14\uAFC8) \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25643
26708
|
}
|
|
25644
26709
|
const unstable = newLines.find((l) => sanitizeText(l) !== l);
|
|
25645
26710
|
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");
|
|
25646
|
-
const targets = nonEmpty.length > 0 ? nonEmpty :
|
|
26711
|
+
const targets = nonEmpty.length > 0 ? nonEmpty : cell2.paras;
|
|
25647
26712
|
if (targets.length === 0) return skip("\uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC74C \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25648
26713
|
const assigned = [];
|
|
25649
26714
|
for (let i = 0; i < targets.length; i++) {
|
|
@@ -25793,67 +26858,67 @@ function synthesizeLineSegs(lineSegData, newRaw, startUnits) {
|
|
|
25793
26858
|
}
|
|
25794
26859
|
return { buf: Buffer.concat(segs), count: lines.length };
|
|
25795
26860
|
}
|
|
25796
|
-
function stageParaPatch(scan,
|
|
26861
|
+
function stageParaPatch(scan, para2, newPlain, skip) {
|
|
25797
26862
|
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");
|
|
25798
|
-
if (
|
|
25799
|
-
if (
|
|
25800
|
-
if (
|
|
25801
|
-
if (scan.repl.has(
|
|
26863
|
+
if (para2.textIdx === -2) return skip("\uBCF5\uC218 PARA_TEXT \uB808\uCF54\uB4DC \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
26864
|
+
if (para2.rangeTagCount > 0) return skip("\uBC94\uC704 \uD0DC\uADF8(\uD615\uAD11\uD39C/\uAD50\uC815\uBD80\uD638) \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
|
|
26865
|
+
if (para2.charShapeIdx < 0 || para2.lineSegIdx < 0) return skip("\uBB38\uB2E8 \uB808\uCF54\uB4DC \uAD6C\uC131 \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
26866
|
+
if (scan.repl.has(para2.headerIdx)) return skip("\uB3D9\uC77C \uBB38\uB2E8 \uC911\uBCF5 \uC218\uC815 \u2014 \uCCAB \uC218\uC815\uB9CC \uC801\uC6A9");
|
|
25802
26867
|
if (/[\u0000-\u0009\u000b-\u001f]/.test(newPlain)) return skip("\uC0C8 \uD14D\uC2A4\uD2B8\uC5D0 \uC81C\uC5B4\uBB38\uC790 \uD3EC\uD568 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25803
26868
|
const records = scan.records;
|
|
25804
|
-
const headerRec = records[
|
|
25805
|
-
const charShapeRec = records[
|
|
26869
|
+
const headerRec = records[para2.headerIdx];
|
|
26870
|
+
const charShapeRec = records[para2.charShapeIdx];
|
|
25806
26871
|
if (charShapeRec.data.length < 8) {
|
|
25807
26872
|
return skip("CHAR_SHAPE \uB808\uCF54\uB4DC \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25808
26873
|
}
|
|
25809
|
-
if (
|
|
25810
|
-
const nCharsLow =
|
|
26874
|
+
if (para2.textIdx === -1) {
|
|
26875
|
+
const nCharsLow = para2.nCharsRaw & 2147483647;
|
|
25811
26876
|
if (nCharsLow > 1) return skip("PARA_TEXT \uC5C6\uB294 \uBB38\uB2E8\uC758 nChars \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
|
|
25812
26877
|
const paraEnd = nCharsLow === 1 ? Buffer.from([13, 0]) : Buffer.alloc(0);
|
|
25813
|
-
const at =
|
|
26878
|
+
const at = para2.headerIdx + 1;
|
|
25814
26879
|
const list = scan.inserts.get(at) ?? [];
|
|
25815
26880
|
list.push({ tagId: TAG_PARA_TEXT, level: headerRec.level + 1, data: Buffer.concat([Buffer.from(newPlain, "utf16le"), paraEnd]) });
|
|
25816
26881
|
scan.inserts.set(at, list);
|
|
25817
26882
|
const newHeader2 = Buffer.from(headerRec.data);
|
|
25818
|
-
newHeader2.writeUInt32LE((
|
|
26883
|
+
newHeader2.writeUInt32LE((para2.nCharsRaw & 2147483648 | newPlain.length + nCharsLow) >>> 0, 0);
|
|
25819
26884
|
const cs2 = rebuildCharShape(charShapeRec.data, 0);
|
|
25820
|
-
scan.repl.set(
|
|
26885
|
+
scan.repl.set(para2.charShapeIdx, cs2.buf);
|
|
25821
26886
|
newHeader2.writeUInt16LE(cs2.count, 12);
|
|
25822
26887
|
if (newPlain.includes("\n")) {
|
|
25823
|
-
const synth = synthesizeLineSegs(records[
|
|
26888
|
+
const synth = synthesizeLineSegs(records[para2.lineSegIdx].data, newPlain, 0);
|
|
25824
26889
|
if (synth) {
|
|
25825
|
-
scan.repl.set(
|
|
26890
|
+
scan.repl.set(para2.lineSegIdx, synth.buf);
|
|
25826
26891
|
newHeader2.writeUInt16LE(synth.count, 16);
|
|
25827
26892
|
}
|
|
25828
26893
|
}
|
|
25829
|
-
scan.repl.set(
|
|
26894
|
+
scan.repl.set(para2.headerIdx, newHeader2);
|
|
25830
26895
|
return 1;
|
|
25831
26896
|
}
|
|
25832
|
-
const textRec = records[
|
|
26897
|
+
const textRec = records[para2.textIdx];
|
|
25833
26898
|
const seg = splitParaText(textRec.data);
|
|
25834
26899
|
if (!seg) {
|
|
25835
|
-
return skip(
|
|
26900
|
+
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");
|
|
25836
26901
|
}
|
|
25837
|
-
if (seg.core !==
|
|
25838
|
-
const lead =
|
|
25839
|
-
const trail =
|
|
25840
|
-
const newRaw =
|
|
26902
|
+
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");
|
|
26903
|
+
const lead = para2.rawText.match(/^\s*/)[0];
|
|
26904
|
+
const trail = para2.rawText.match(/\s*$/)[0];
|
|
26905
|
+
const newRaw = para2.rawText.trim() === para2.rawText ? newPlain : lead + newPlain + trail;
|
|
25841
26906
|
const newText = Buffer.concat([seg.prefix, Buffer.from(newRaw, "utf16le"), seg.suffix]);
|
|
25842
|
-
scan.repl.set(
|
|
26907
|
+
scan.repl.set(para2.textIdx, newText);
|
|
25843
26908
|
const newHeader = Buffer.from(headerRec.data);
|
|
25844
26909
|
const nChars = seg.prefixUnits + newRaw.length + seg.suffixUnits;
|
|
25845
|
-
newHeader.writeUInt32LE((
|
|
26910
|
+
newHeader.writeUInt32LE((para2.nCharsRaw & 2147483648 | nChars) >>> 0, 0);
|
|
25846
26911
|
const cs = rebuildCharShape(charShapeRec.data, seg.prefixUnits);
|
|
25847
|
-
scan.repl.set(
|
|
26912
|
+
scan.repl.set(para2.charShapeIdx, cs.buf);
|
|
25848
26913
|
newHeader.writeUInt16LE(cs.count, 12);
|
|
25849
26914
|
if (newRaw.includes("\n")) {
|
|
25850
|
-
const synth = synthesizeLineSegs(records[
|
|
26915
|
+
const synth = synthesizeLineSegs(records[para2.lineSegIdx].data, newRaw, seg.prefixUnits);
|
|
25851
26916
|
if (synth) {
|
|
25852
|
-
scan.repl.set(
|
|
26917
|
+
scan.repl.set(para2.lineSegIdx, synth.buf);
|
|
25853
26918
|
newHeader.writeUInt16LE(synth.count, 16);
|
|
25854
26919
|
}
|
|
25855
26920
|
}
|
|
25856
|
-
scan.repl.set(
|
|
26921
|
+
scan.repl.set(para2.headerIdx, newHeader);
|
|
25857
26922
|
return 1;
|
|
25858
26923
|
}
|
|
25859
26924
|
|
|
@@ -26018,9 +27083,9 @@ var HwpxSession = class _HwpxSession {
|
|
|
26018
27083
|
const block = st.blocks[blockIndex];
|
|
26019
27084
|
if (!block) return void 0;
|
|
26020
27085
|
if (block.type === "paragraph" || block.type === "heading") {
|
|
26021
|
-
const
|
|
26022
|
-
if (!
|
|
26023
|
-
return { kind: "paragraph", sectionIndex:
|
|
27086
|
+
const para2 = st.paraMap.get(blockIndex)?.para;
|
|
27087
|
+
if (!para2) return void 0;
|
|
27088
|
+
return { kind: "paragraph", sectionIndex: para2.sectionIndex, xmlStart: para2.start };
|
|
26024
27089
|
}
|
|
26025
27090
|
if (block.type === "table" && block.table) {
|
|
26026
27091
|
if (st.tableOrdinals.size !== st.scanTables.length) return void 0;
|
|
@@ -26057,13 +27122,13 @@ var HwpxSession = class _HwpxSession {
|
|
|
26057
27122
|
if (!scanTable) {
|
|
26058
27123
|
return { capability: "locked", reason: "\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328" };
|
|
26059
27124
|
}
|
|
26060
|
-
const
|
|
27125
|
+
const table2 = block.table;
|
|
26061
27126
|
const cells = [];
|
|
26062
27127
|
let anyEditable = false;
|
|
26063
|
-
for (let r = 0; r <
|
|
27128
|
+
for (let r = 0; r < table2.rows; r++) {
|
|
26064
27129
|
const row = [];
|
|
26065
|
-
for (let c = 0; c <
|
|
26066
|
-
const info = cellStaticCheck(
|
|
27130
|
+
for (let c = 0; c < table2.cols; c++) {
|
|
27131
|
+
const info = cellStaticCheck(table2, scanTable, r, c);
|
|
26067
27132
|
if (info.editable) anyEditable = true;
|
|
26068
27133
|
row.push(info);
|
|
26069
27134
|
}
|
|
@@ -26252,12 +27317,12 @@ var HwpxSession = class _HwpxSession {
|
|
|
26252
27317
|
return 1;
|
|
26253
27318
|
}
|
|
26254
27319
|
};
|
|
26255
|
-
function cellStaticCheck(
|
|
26256
|
-
const irCell =
|
|
27320
|
+
function cellStaticCheck(table2, scanTable, r, c) {
|
|
27321
|
+
const irCell = table2.cells[r]?.[c];
|
|
26257
27322
|
if (!irCell) return { editable: false, reason: "\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16" };
|
|
26258
|
-
const
|
|
26259
|
-
if (!
|
|
26260
|
-
const scanJoined =
|
|
27323
|
+
const cell2 = scanTable.cellByAnchor.get(`${r},${c}`);
|
|
27324
|
+
if (!cell2) return { editable: false, reason: "\uBCD1\uD569 \uC601\uC5ED\uC758 \uBE48 \uCE78\uC774\uAC70\uB098 \uC88C\uD45C \uBD88\uC77C\uCE58" };
|
|
27325
|
+
const scanJoined = cell2.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
|
|
26261
27326
|
if (normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
|
|
26262
27327
|
if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
|
|
26263
27328
|
const flatBlocks = (irCell.blocks ?? []).filter((b) => b.type === "paragraph" || b.type === "heading");
|
|
@@ -26267,9 +27332,9 @@ function cellStaticCheck(table, scanTable, r, c) {
|
|
|
26267
27332
|
}
|
|
26268
27333
|
}
|
|
26269
27334
|
}
|
|
26270
|
-
const nonEmpty =
|
|
27335
|
+
const nonEmpty = cell2.paragraphs.filter((p) => normForMatch(p.text) !== "");
|
|
26271
27336
|
if (nonEmpty.length === 0) {
|
|
26272
|
-
if (
|
|
27337
|
+
if (cell2.paragraphs.length === 0) {
|
|
26273
27338
|
return { editable: false, reason: "\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00" };
|
|
26274
27339
|
}
|
|
26275
27340
|
return { editable: true };
|
|
@@ -26587,7 +27652,8 @@ function reflowPara(p, doc, styles, areaW, startV, mode) {
|
|
|
26587
27652
|
const firstWidth = avail;
|
|
26588
27653
|
const contWidth = Math.max(500, avail + Math.min(0, geom.marginIntent));
|
|
26589
27654
|
const contHorz = marginL - Math.min(0, geom.marginIntent);
|
|
26590
|
-
const
|
|
27655
|
+
const paraMode = geom.wrapMode ?? mode;
|
|
27656
|
+
const wrap = text.length === 0 ? { lines: 1, starts: [0], lastLineWidth: 0 } : simulateWrap(text, firstWidth, contWidth, height, ratio, paraMode, { spacingPct });
|
|
26591
27657
|
const pitch = pitchFor(height, geom);
|
|
26592
27658
|
const baseline = Math.round(height * BASELINE_RATIO);
|
|
26593
27659
|
const spacing = Math.max(0, pitch - height);
|
|
@@ -26625,15 +27691,15 @@ function reflowTablesIn(p, doc, styles, mode, counter) {
|
|
|
26625
27691
|
if (ln(obj) !== "tbl") continue;
|
|
26626
27692
|
for (const tr of elements(obj)) {
|
|
26627
27693
|
if (ln(tr) !== "tr") continue;
|
|
26628
|
-
for (const
|
|
26629
|
-
if (ln(
|
|
26630
|
-
const csz = findChildByLocalName(
|
|
26631
|
-
const cm = findChildByLocalName(
|
|
27694
|
+
for (const tc2 of elements(tr)) {
|
|
27695
|
+
if (ln(tc2) !== "tc") continue;
|
|
27696
|
+
const csz = findChildByLocalName(tc2, "cellSz");
|
|
27697
|
+
const cm = findChildByLocalName(tc2, "cellMargin");
|
|
26632
27698
|
const cellW = num2(csz, "width");
|
|
26633
27699
|
const mL = cm ? num2(cm, "left", 141) : 141;
|
|
26634
27700
|
const mR = cm ? num2(cm, "right", 141) : 141;
|
|
26635
27701
|
const areaW = Math.max(500, cellW - mL - mR);
|
|
26636
|
-
const sub = findChildByLocalName(
|
|
27702
|
+
const sub = findChildByLocalName(tc2, "subList");
|
|
26637
27703
|
if (sub) reflowBlockFlow(sub, doc, styles, areaW, mode, counter, 0);
|
|
26638
27704
|
}
|
|
26639
27705
|
}
|
|
@@ -27041,10 +28107,10 @@ function drawShape(o, x, y, ctx, depth) {
|
|
|
27041
28107
|
for (const p of elements2(sub)) if (ln2(p) === "p") drawPara(p, x, y, w, ctx, depth + 1);
|
|
27042
28108
|
}
|
|
27043
28109
|
}
|
|
27044
|
-
function cellContentExtent(
|
|
27045
|
-
if (!
|
|
28110
|
+
function cellContentExtent(cell2) {
|
|
28111
|
+
if (!cell2.sub) return 0;
|
|
27046
28112
|
let ext = 0;
|
|
27047
|
-
for (const p of elements2(
|
|
28113
|
+
for (const p of elements2(cell2.sub)) {
|
|
27048
28114
|
if (ln2(p) !== "p") continue;
|
|
27049
28115
|
const m = buildPara(p);
|
|
27050
28116
|
for (const s of m.segs) ext = Math.max(ext, s.vertpos + s.textheight);
|
|
@@ -27069,30 +28135,30 @@ function edgeLine(x1, y1, x2, y2, e) {
|
|
|
27069
28135
|
const dash = /DASH|DOT/.test(e.type) ? ` stroke-dasharray="${e.type.includes("DOT") ? "1,1.5" : "3,1.5"}"` : "";
|
|
27070
28136
|
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}/>`;
|
|
27071
28137
|
}
|
|
27072
|
-
function collectCells(
|
|
27073
|
-
const inMargin = findChildByLocalName(
|
|
28138
|
+
function collectCells(tbl2) {
|
|
28139
|
+
const inMargin = findChildByLocalName(tbl2, "inMargin");
|
|
27074
28140
|
const defL = num3(inMargin, "left", 141), defR = num3(inMargin, "right", 141);
|
|
27075
28141
|
const defT = num3(inMargin, "top", 141), defB = num3(inMargin, "bottom", 141);
|
|
27076
28142
|
const cells = [];
|
|
27077
|
-
for (const tr of elements2(
|
|
28143
|
+
for (const tr of elements2(tbl2)) {
|
|
27078
28144
|
if (ln2(tr) !== "tr") continue;
|
|
27079
|
-
for (const
|
|
27080
|
-
if (ln2(
|
|
27081
|
-
const addr = findChildByLocalName(
|
|
27082
|
-
const span = findChildByLocalName(
|
|
27083
|
-
const csz = findChildByLocalName(
|
|
27084
|
-
const cm = findChildByLocalName(
|
|
28145
|
+
for (const tc2 of elements2(tr)) {
|
|
28146
|
+
if (ln2(tc2) !== "tc") continue;
|
|
28147
|
+
const addr = findChildByLocalName(tc2, "cellAddr");
|
|
28148
|
+
const span = findChildByLocalName(tc2, "cellSpan");
|
|
28149
|
+
const csz = findChildByLocalName(tc2, "cellSz");
|
|
28150
|
+
const cm = findChildByLocalName(tc2, "cellMargin");
|
|
27085
28151
|
if (!addr || !csz) continue;
|
|
27086
28152
|
cells.push({
|
|
27087
|
-
el:
|
|
28153
|
+
el: tc2,
|
|
27088
28154
|
ca: num3(addr, "colAddr"),
|
|
27089
28155
|
ra: num3(addr, "rowAddr"),
|
|
27090
28156
|
cs: Math.max(1, num3(span, "colSpan", 1)),
|
|
27091
28157
|
rs: Math.max(1, num3(span, "rowSpan", 1)),
|
|
27092
28158
|
w: num3(csz, "width"),
|
|
27093
28159
|
h: num3(csz, "height"),
|
|
27094
|
-
bfId:
|
|
27095
|
-
sub: findChildByLocalName(
|
|
28160
|
+
bfId: tc2.getAttribute("borderFillIDRef"),
|
|
28161
|
+
sub: findChildByLocalName(tc2, "subList"),
|
|
27096
28162
|
marginL: cm ? num3(cm, "left", defL) : defL,
|
|
27097
28163
|
marginR: cm ? num3(cm, "right", defR) : defR,
|
|
27098
28164
|
marginT: cm ? num3(cm, "top", defT) : defT,
|
|
@@ -27102,8 +28168,8 @@ function collectCells(tbl) {
|
|
|
27102
28168
|
}
|
|
27103
28169
|
return cells;
|
|
27104
28170
|
}
|
|
27105
|
-
function measureTableHeight(
|
|
27106
|
-
const cells = collectCells(
|
|
28171
|
+
function measureTableHeight(tbl2) {
|
|
28172
|
+
const cells = collectCells(tbl2);
|
|
27107
28173
|
if (cells.length === 0 || cells.length > 4096) return 0;
|
|
27108
28174
|
const nRows = Math.max(...cells.map((c) => c.ra + c.rs));
|
|
27109
28175
|
const rowH = solveRowHeights(
|
|
@@ -27114,14 +28180,14 @@ function measureTableHeight(tbl) {
|
|
|
27114
28180
|
for (const h of rowH) sum += h;
|
|
27115
28181
|
return sum;
|
|
27116
28182
|
}
|
|
27117
|
-
function drawTable(
|
|
28183
|
+
function drawTable(tbl2, tx, ty, ctx, depth) {
|
|
27118
28184
|
if (depth > 16) {
|
|
27119
28185
|
warnOnce(ctx, "depth", "\uC911\uCCA9 \uAE4A\uC774 16 \uCD08\uACFC \u2014 \uC774\uD558 \uC0DD\uB7B5");
|
|
27120
28186
|
return;
|
|
27121
28187
|
}
|
|
27122
28188
|
ctx.stats.tables++;
|
|
27123
|
-
const tblSz = findChildByLocalName(
|
|
27124
|
-
const cells = collectCells(
|
|
28189
|
+
const tblSz = findChildByLocalName(tbl2, "sz");
|
|
28190
|
+
const cells = collectCells(tbl2);
|
|
27125
28191
|
if (cells.length === 0 || cells.length > 4096) return;
|
|
27126
28192
|
const nCols = Math.max(...cells.map((c) => c.ca + c.cs));
|
|
27127
28193
|
const nRows = Math.max(...cells.map((c) => c.ra + c.rs));
|
|
@@ -27485,7 +28551,7 @@ async function parseHwp(buffer, options) {
|
|
|
27485
28551
|
async function parsePdf(buffer, options) {
|
|
27486
28552
|
let parsePdfDocument;
|
|
27487
28553
|
try {
|
|
27488
|
-
const mod = await import("./parser-
|
|
28554
|
+
const mod = await import("./parser-G433UZMX.js");
|
|
27489
28555
|
parsePdfDocument = mod.parsePdfDocument;
|
|
27490
28556
|
} catch {
|
|
27491
28557
|
return {
|
|
@@ -27600,13 +28666,16 @@ export {
|
|
|
27600
28666
|
fillWithUniqueGuard,
|
|
27601
28667
|
fitRatioForFewerLines,
|
|
27602
28668
|
formatFillValue,
|
|
28669
|
+
gongmunLintWarnings,
|
|
27603
28670
|
hwpxToProfile,
|
|
27604
28671
|
inferFieldType,
|
|
27605
28672
|
isHwpxFile,
|
|
28673
|
+
isKnownFont,
|
|
27606
28674
|
isLabelCell,
|
|
27607
28675
|
isOldHwpFile,
|
|
27608
28676
|
isPdfFile,
|
|
27609
28677
|
isZipFile,
|
|
28678
|
+
lintGongmunText,
|
|
27610
28679
|
markdownToHwpx,
|
|
27611
28680
|
markdownToPdf,
|
|
27612
28681
|
measureTextWidth,
|
|
@@ -27630,6 +28699,7 @@ export {
|
|
|
27630
28699
|
scanSectionXml,
|
|
27631
28700
|
simulateWrap,
|
|
27632
28701
|
simulateWrapKeepWord,
|
|
28702
|
+
unknownFontWarnings,
|
|
27633
28703
|
validateHwpx
|
|
27634
28704
|
};
|
|
27635
28705
|
//# sourceMappingURL=index.js.map
|