kordoc 3.18.0 → 4.0.0

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