kordoc 3.4.0 → 3.5.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 (85) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +590 -584
  3. package/dist/{-56JCPGII.js → -GKNSTVEZ.js} +9 -5
  4. package/dist/{chunk-MOL7MDBG.js → chunk-3TBUDJDE.js} +1 -1
  5. package/dist/chunk-3TBUDJDE.js.map +1 -0
  6. package/dist/{chunk-YYKQN7SA.cjs → chunk-4JLD2IT7.cjs} +2 -2
  7. package/dist/chunk-4JLD2IT7.cjs.map +1 -0
  8. package/dist/{chunk-MHYDBT2Q.js → chunk-A4LSWJEC.js} +2 -2
  9. package/dist/chunk-A4LSWJEC.js.map +1 -0
  10. package/dist/{chunk-ZPLRG2SJ.js → chunk-AHDNELBR.js} +2 -2
  11. package/dist/chunk-AHDNELBR.js.map +1 -0
  12. package/dist/{chunk-GE43BE46.js → chunk-AIQ3ISQU.js} +1 -1
  13. package/dist/chunk-AIQ3ISQU.js.map +1 -0
  14. package/dist/{chunk-MEPHGCPQ.js → chunk-CFQLK3LM.js} +1 -1
  15. package/dist/chunk-CFQLK3LM.js.map +1 -0
  16. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  17. package/dist/{chunk-YFNBHLLM.js → chunk-GTCJQANY.js} +199 -30
  18. package/dist/chunk-GTCJQANY.js.map +1 -0
  19. package/dist/{chunk-DCZVOIEO.cjs → chunk-X34YWRL5.cjs} +1 -1
  20. package/dist/chunk-X34YWRL5.cjs.map +1 -0
  21. package/dist/cli.js +10 -27
  22. package/dist/cli.js.map +1 -1
  23. package/dist/{detect-RI2MQ33K.js → detect-NTR2FUEG.js} +2 -2
  24. package/dist/{formula-JCNF43NE.js → formula-KOQV353G.js} +1 -1
  25. package/dist/formula-KOQV353G.js.map +1 -0
  26. package/dist/{formula-RXVSQPXI.js → formula-MEDGYQXS.js} +1 -1
  27. package/dist/formula-MEDGYQXS.js.map +1 -0
  28. package/dist/{formula-5NKVS2LR.cjs → formula-ZYUDQHD3.cjs} +1 -1
  29. package/dist/formula-ZYUDQHD3.cjs.map +1 -0
  30. package/dist/index.cjs +368 -199
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +9 -3
  33. package/dist/index.d.ts +9 -3
  34. package/dist/index.js +197 -28
  35. package/dist/index.js.map +1 -1
  36. package/dist/mcp.js +42 -6
  37. package/dist/mcp.js.map +1 -1
  38. package/dist/page-range-CIRRJPXJ.js +7 -0
  39. package/dist/page-range-OF5I4PQY.js +8 -0
  40. package/dist/page-range-TPIRSA3J.cjs +8 -0
  41. package/dist/page-range-TPIRSA3J.cjs.map +1 -0
  42. package/dist/{parser-XDW6I25C.cjs → parser-25ISHR7Q.cjs} +18 -18
  43. package/dist/parser-25ISHR7Q.cjs.map +1 -0
  44. package/dist/{parser-VZL3MK5X.js → parser-LBLPN3KY.js} +5 -5
  45. package/dist/parser-LBLPN3KY.js.map +1 -0
  46. package/dist/{parser-PQDICHD5.js → parser-LMBDB7RM.js} +5 -5
  47. package/dist/parser-LMBDB7RM.js.map +1 -0
  48. package/dist/{provider-G4C2V2PD.cjs → provider-5K7O3Z2O.cjs} +1 -1
  49. package/dist/provider-5K7O3Z2O.cjs.map +1 -0
  50. package/dist/{provider-AKROB7WQ.js → provider-7H4CPZYS.js} +1 -1
  51. package/dist/provider-7H4CPZYS.js.map +1 -0
  52. package/dist/{provider-4ZJKV3DC.js → provider-H4WWSPOV.js} +1 -1
  53. package/dist/provider-H4WWSPOV.js.map +1 -0
  54. package/dist/{setup-57FB3LSP.js → setup-QSJ2INNS.js} +1 -1
  55. package/dist/setup-QSJ2INNS.js.map +1 -0
  56. package/dist/{watch-KERZCCNR.js → watch-77CYT54V.js} +5 -5
  57. package/dist/watch-77CYT54V.js.map +1 -0
  58. package/package.json +98 -98
  59. package/dist/chunk-DCZVOIEO.cjs.map +0 -1
  60. package/dist/chunk-GE43BE46.js.map +0 -1
  61. package/dist/chunk-MEPHGCPQ.js.map +0 -1
  62. package/dist/chunk-MHYDBT2Q.js.map +0 -1
  63. package/dist/chunk-MOL7MDBG.js.map +0 -1
  64. package/dist/chunk-YFNBHLLM.js.map +0 -1
  65. package/dist/chunk-YYKQN7SA.cjs.map +0 -1
  66. package/dist/chunk-ZPLRG2SJ.js.map +0 -1
  67. package/dist/formula-5NKVS2LR.cjs.map +0 -1
  68. package/dist/formula-JCNF43NE.js.map +0 -1
  69. package/dist/formula-RXVSQPXI.js.map +0 -1
  70. package/dist/page-range-737B4EZW.js +0 -8
  71. package/dist/page-range-LNMXJU6W.js +0 -7
  72. package/dist/page-range-P7SDW6LR.cjs +0 -8
  73. package/dist/page-range-P7SDW6LR.cjs.map +0 -1
  74. package/dist/parser-PQDICHD5.js.map +0 -1
  75. package/dist/parser-VZL3MK5X.js.map +0 -1
  76. package/dist/parser-XDW6I25C.cjs.map +0 -1
  77. package/dist/provider-4ZJKV3DC.js.map +0 -1
  78. package/dist/provider-AKROB7WQ.js.map +0 -1
  79. package/dist/provider-G4C2V2PD.cjs.map +0 -1
  80. package/dist/setup-57FB3LSP.js.map +0 -1
  81. package/dist/watch-KERZCCNR.js.map +0 -1
  82. /package/dist/{-56JCPGII.js.map → -GKNSTVEZ.js.map} +0 -0
  83. /package/dist/{detect-RI2MQ33K.js.map → detect-NTR2FUEG.js.map} +0 -0
  84. /package/dist/{page-range-737B4EZW.js.map → page-range-CIRRJPXJ.js.map} +0 -0
  85. /package/dist/{page-range-LNMXJU6W.js.map → page-range-OF5I4PQY.js.map} +0 -0
@@ -4,7 +4,7 @@ import {
4
4
  detectOle2Format,
5
5
  detectZipFormat,
6
6
  parseLenientCfb
7
- } from "./chunk-MEPHGCPQ.js";
7
+ } from "./chunk-CFQLK3LM.js";
8
8
  import {
9
9
  HEADING_RATIO_H1,
10
10
  HEADING_RATIO_H2,
@@ -23,10 +23,10 @@ import {
23
23
  sanitizeHref,
24
24
  stripDtd,
25
25
  toArrayBuffer
26
- } from "./chunk-MHYDBT2Q.js";
26
+ } from "./chunk-A4LSWJEC.js";
27
27
  import {
28
28
  parsePageRange
29
- } from "./chunk-MOL7MDBG.js";
29
+ } from "./chunk-3TBUDJDE.js";
30
30
 
31
31
  // src/index.ts
32
32
  import { readFile } from "fs/promises";
@@ -16689,7 +16689,7 @@ async function parseXlsxDocument(buffer, options) {
16689
16689
  }
16690
16690
  let pageFilter = null;
16691
16691
  if (options?.pages) {
16692
- const { parsePageRange: parsePageRange2 } = await import("./page-range-737B4EZW.js");
16692
+ const { parsePageRange: parsePageRange2 } = await import("./page-range-OF5I4PQY.js");
16693
16693
  pageFilter = parsePageRange2(options.pages, sheets.length);
16694
16694
  }
16695
16695
  const blocks = [];
@@ -17327,7 +17327,7 @@ async function parseXlsDocument(buffer, options) {
17327
17327
  const totalSheets = Math.min(globals.sheets.length, MAX_SHEETS2);
17328
17328
  let pageFilter = null;
17329
17329
  if (options?.pages) {
17330
- const { parsePageRange: parsePageRange2 } = await import("./page-range-737B4EZW.js");
17330
+ const { parsePageRange: parsePageRange2 } = await import("./page-range-OF5I4PQY.js");
17331
17331
  pageFilter = parsePageRange2(options.pages, totalSheets);
17332
17332
  }
17333
17333
  const allBlocks = [];
@@ -17750,20 +17750,32 @@ function isDisplayMath(el) {
17750
17750
 
17751
17751
  // src/docx/parser.ts
17752
17752
  var MAX_DECOMPRESS_SIZE4 = 100 * 1024 * 1024;
17753
- function getChildElements(parent, localName2) {
17753
+ function matchesLocal(el, localName2) {
17754
+ return el.localName === localName2 || (el.tagName?.endsWith(`:${localName2}`) ?? false);
17755
+ }
17756
+ function effectiveChildElements(parent) {
17754
17757
  const result = [];
17755
17758
  const children = parent.childNodes;
17756
17759
  for (let i = 0; i < children.length; i++) {
17757
17760
  const node = children[i];
17758
- if (node.nodeType === 1) {
17759
- const el = node;
17760
- if (el.localName === localName2 || el.tagName?.endsWith(`:${localName2}`)) {
17761
- result.push(el);
17761
+ if (node.nodeType !== 1) continue;
17762
+ const el = node;
17763
+ if (matchesLocal(el, "sdt")) {
17764
+ for (let j = 0; j < el.childNodes.length; j++) {
17765
+ const c = el.childNodes[j];
17766
+ if (c.nodeType === 1 && matchesLocal(c, "sdtContent")) {
17767
+ result.push(...effectiveChildElements(c));
17768
+ }
17762
17769
  }
17770
+ } else {
17771
+ result.push(el);
17763
17772
  }
17764
17773
  }
17765
17774
  return result;
17766
17775
  }
17776
+ function getChildElements(parent, localName2) {
17777
+ return effectiveChildElements(parent).filter((el) => matchesLocal(el, localName2));
17778
+ }
17767
17779
  function findElements(parent, localName2) {
17768
17780
  const result = [];
17769
17781
  const walk = (node) => {
@@ -18154,11 +18166,8 @@ async function parseDocxDocument(buffer, options) {
18154
18166
  }
18155
18167
  const blocks = [];
18156
18168
  const bodyEl = body[0];
18157
- const children = bodyEl.childNodes;
18158
- for (let i = 0; i < children.length; i++) {
18159
- const node = children[i];
18160
- if (node.nodeType !== 1) continue;
18161
- const el = node;
18169
+ const topLevel = effectiveChildElements(bodyEl);
18170
+ for (const el of topLevel) {
18162
18171
  const localName2 = el.localName ?? el.tagName?.split(":").pop();
18163
18172
  if (localName2 === "p") {
18164
18173
  const block = parseParagraph2(el, styles, numbering, footnotes, rels);
@@ -18664,8 +18673,9 @@ function extractFromTable(table) {
18664
18673
  if (table.cols >= 2) {
18665
18674
  for (let r = 0; r < table.rows; r++) {
18666
18675
  for (let c = 0; c < table.cols - 1; c++) {
18667
- const labelCell = table.cells[r][c];
18668
- const valueCell = table.cells[r][c + 1];
18676
+ const labelCell = table.cells[r]?.[c];
18677
+ const valueCell = table.cells[r]?.[c + 1];
18678
+ if (!labelCell || !valueCell) continue;
18669
18679
  if (isLabelCell(labelCell.text)) {
18670
18680
  fields.push({
18671
18681
  label: labelCell.text.trim().replace(/[::]\s*$/, ""),
@@ -18686,8 +18696,8 @@ function extractFromTable(table) {
18686
18696
  if (allLabels) {
18687
18697
  for (let r = 1; r < table.rows; r++) {
18688
18698
  for (let c = 0; c < table.cols; c++) {
18689
- const label = headerRow[c].text.trim();
18690
- const value = table.cells[r][c].text.trim();
18699
+ const label = headerRow[c]?.text.trim() ?? "";
18700
+ const value = table.cells[r]?.[c]?.text.trim() ?? "";
18691
18701
  if (label && value) {
18692
18702
  fields.push({ label, value, row: r, col: c });
18693
18703
  }
@@ -18841,15 +18851,18 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
18841
18851
  if (!allLabels) return;
18842
18852
  for (let r = 1; r < table.rows; r++) {
18843
18853
  for (let c = 0; c < table.cols; c++) {
18844
- const headerLabel = normalizeLabel(headerRow[c].text);
18854
+ const headerCell = headerRow[c];
18855
+ const valueCell = table.cells[r]?.[c];
18856
+ if (!headerCell || !valueCell) continue;
18857
+ const headerLabel = normalizeLabel(headerCell.text);
18845
18858
  const matchKey = findMatchingKey(headerLabel, values);
18846
18859
  if (matchKey === void 0) continue;
18847
18860
  if (matchedLabels.has(matchKey)) continue;
18848
18861
  const newValue = values.get(matchKey);
18849
- table.cells[r][c].text = newValue;
18862
+ valueCell.text = newValue;
18850
18863
  matchedLabels.add(matchKey);
18851
18864
  filled.push({
18852
- label: headerRow[c].text.trim(),
18865
+ label: headerCell.text.trim(),
18853
18866
  value: newValue,
18854
18867
  row: r,
18855
18868
  col: c
@@ -19779,8 +19792,30 @@ var PRESET_DEFAULTS = {
19779
19792
  notice: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
19780
19793
  minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" }
19781
19794
  };
19795
+ var PRESET_ALIAS = {
19796
+ official: "official",
19797
+ \uAE30\uC548\uBB38: "official",
19798
+ \uC2DC\uD589\uBB38: "official",
19799
+ \uACF5\uBB38: "official",
19800
+ \uACF5\uBB38\uC11C: "official",
19801
+ report: "report",
19802
+ \uBCF4\uACE0\uC11C: "report",
19803
+ plan: "plan",
19804
+ \uACC4\uD68D\uC11C: "plan",
19805
+ \uACC4\uD68D: "plan",
19806
+ notice: "notice",
19807
+ \uD1B5\uC9C0: "notice",
19808
+ \uC54C\uB9BC: "notice",
19809
+ \uC548\uB0B4: "notice",
19810
+ minutes: "minutes",
19811
+ \uD68C\uC758\uB85D: "minutes"
19812
+ };
19813
+ function normalizeGongmunPreset(preset) {
19814
+ if (!preset) return "official";
19815
+ return PRESET_ALIAS[preset.trim()] ?? "official";
19816
+ }
19782
19817
  function resolveGongmun(opts) {
19783
- const preset = opts.preset ?? "official";
19818
+ const preset = normalizeGongmunPreset(opts.preset);
19784
19819
  const d = PRESET_DEFAULTS[preset];
19785
19820
  const bodyPt = opts.bodyPt ?? d.bodyPt;
19786
19821
  return {
@@ -21150,6 +21185,67 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21150
21185
  return 1;
21151
21186
  }
21152
21187
 
21188
+ // src/roundtrip/table-insert.ts
21189
+ var TABLE_USABLE_WIDTH = 44e3;
21190
+ var TABLE_ROW_HEIGHT = 1500;
21191
+ function collectMaxNumericId(xmls) {
21192
+ let max = -1;
21193
+ for (const xml of xmls) {
21194
+ for (const m of xml.matchAll(/\bid(?:Ref)?="(\d{1,10})"/g)) {
21195
+ const v = parseInt(m[1], 10);
21196
+ if (!isNaN(v) && v > max) max = v;
21197
+ }
21198
+ }
21199
+ return max;
21200
+ }
21201
+ function cellBorderFillXml(id) {
21202
+ return `<hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="0" breakCellSeparateLine="0"><hh:slash type="NONE" Crooked="0" isCounter="0"/><hh:backSlash type="NONE" Crooked="0" isCounter="0"/><hh:leftBorder type="SOLID" width="0.12 mm" color="#000000"/><hh:rightBorder type="SOLID" width="0.12 mm" color="#000000"/><hh:topBorder type="SOLID" width="0.12 mm" color="#000000"/><hh:bottomBorder type="SOLID" width="0.12 mm" color="#000000"/><hh:diagonal type="NONE" width="0.1 mm" color="#000000"/><hh:fillInfo/></hh:borderFill>`;
21203
+ }
21204
+ function injectCellBorderFill(headerXml, newId) {
21205
+ const openM = headerXml.match(/<hh:borderFills\b([^>]*)>/);
21206
+ if (!openM || openM.index === void 0) return null;
21207
+ const closeIdx = headerXml.indexOf("</hh:borderFills>");
21208
+ if (closeIdx < 0) return null;
21209
+ const splices = [];
21210
+ const itemCntM = openM[1].match(/\bitemCnt="(\d+)"/);
21211
+ if (itemCntM && itemCntM.index !== void 0) {
21212
+ const cnt = parseInt(itemCntM[1], 10);
21213
+ const attrStart = openM.index + "<hh:borderFills".length + itemCntM.index;
21214
+ const valStart = attrStart + itemCntM[0].indexOf('"') + 1;
21215
+ const valEnd = valStart + String(cnt).length;
21216
+ splices.push({ start: valStart, end: valEnd, replacement: String(cnt + 1) });
21217
+ }
21218
+ splices.push({ start: closeIdx, end: closeIdx, replacement: cellBorderFillXml(newId) });
21219
+ return { borderFillId: newId, headerSplices: splices };
21220
+ }
21221
+ function cellPlainText(raw) {
21222
+ let t = unescapeGfmCell(raw);
21223
+ t = t.replace(/\*\*\*([^*]+)\*\*\*/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/`([^`]+)`/g, "$1");
21224
+ return t.replace(/\s*\n\s*/g, " ").trim();
21225
+ }
21226
+ function buildTableParagraphXml(rows, opts) {
21227
+ const { borderFillId, outerParaPrId, cellParaPrId, cellCharPrId, tableId } = opts;
21228
+ const rowCnt = rows.length;
21229
+ const colCnt = Math.max(...rows.map((r) => r.length), 1);
21230
+ const cellW = Math.floor(TABLE_USABLE_WIDTH / colCnt);
21231
+ const cellH = TABLE_ROW_HEIGHT;
21232
+ const tblW = cellW * colCnt;
21233
+ const tblH = cellH * rowCnt;
21234
+ const trElements = rows.map((row, rowIdx) => {
21235
+ const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
21236
+ const isHeaderRow = rowIdx === 0;
21237
+ const tdElements = cells.map((cell, colIdx) => {
21238
+ const text = escapeXmlText(cellPlainText(cell));
21239
+ const cellP = `<hp:p paraPrIDRef="${cellParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}"><hp:t>${text}</hp:t></hp:run></hp:p>`;
21240
+ 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>`;
21241
+ }).join("");
21242
+ return `<hp:tr>${tdElements}</hp:tr>`;
21243
+ }).join("");
21244
+ 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;
21245
+ 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>`;
21246
+ return `<hp:p paraPrIDRef="${outerParaPrId}" styleIDRef="0"><hp:run charPrIDRef="${cellCharPrId}">${tbl}</hp:run></hp:p>`;
21247
+ }
21248
+
21153
21249
  // src/roundtrip/hwpx-entries.ts
21154
21250
  async function resolveSectionEntryNames(zip) {
21155
21251
  for (const mp of ["Contents/content.hpf", "content.hpf"]) {
@@ -21211,6 +21307,13 @@ async function patchHwpx(original, editedMarkdown, options) {
21211
21307
  const xml = await zip.file(sectionPaths[i]).async("text");
21212
21308
  scans.push(scanSectionXml(xml, i));
21213
21309
  }
21310
+ let tableInsert;
21311
+ const headerEntryName = await resolveHeaderEntryName(zip);
21312
+ if (headerEntryName) {
21313
+ const headerXml = await zip.file(headerEntryName).async("text");
21314
+ const maxId = collectMaxNumericId([...scans.map((s) => s.xml), headerXml]);
21315
+ tableInsert = { headerEntryName, headerXml, headerSplices: [], borderFillId: null, nextId: maxId + 1 };
21316
+ }
21214
21317
  const origUnits = buildOrigUnits(origBlocks);
21215
21318
  const editedUnits = splitMarkdownUnits(editedMarkdown);
21216
21319
  const pairs = alignUnits(origUnits.map((u) => u.raw), editedUnits.map((u) => u.raw));
@@ -21230,7 +21333,8 @@ async function patchHwpx(original, editedMarkdown, options) {
21230
21333
  scanTables,
21231
21334
  obTableOrdinals,
21232
21335
  sectionSplices,
21233
- skipped
21336
+ skipped,
21337
+ tableInsert
21234
21338
  });
21235
21339
  } else if (oi !== null) {
21236
21340
  skipped.push({ reason: "\uBE14\uB85D \uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0 (v1) \u2014 \uC6D0\uBCF8 \uC720\uC9C0", before: summarize(origUnits[oi].raw) });
@@ -21247,6 +21351,10 @@ async function patchHwpx(original, editedMarkdown, options) {
21247
21351
  const newXml = applySplices(scans[i].xml, sectionSplices[i]);
21248
21352
  replacements.set(sectionPaths[i], encoder.encode(newXml));
21249
21353
  }
21354
+ if (tableInsert && tableInsert.headerSplices.length > 0) {
21355
+ const newHeader = applySplices(tableInsert.headerXml, tableInsert.headerSplices);
21356
+ replacements.set(tableInsert.headerEntryName, encoder.encode(newHeader));
21357
+ }
21250
21358
  } catch (err) {
21251
21359
  return { success: false, applied: 0, skipped, error: `\uC18C\uC2A4\uB9F5 splice \uC2E4\uD328: ${err instanceof Error ? err.message : String(err)}` };
21252
21360
  }
@@ -21459,11 +21567,49 @@ function handleModifiedUnit(orig, edited, ctx) {
21459
21567
  if (orig.kind === "html-table") return patchHtmlTable(block.table, scanTable, orig, edited, ctx, skip);
21460
21568
  return patchTextChunkTable(block.table, scanTable, orig, edited, ctx, skip);
21461
21569
  }
21462
- if ((block.type === "paragraph" || block.type === "heading") && orig.kind === "text" && edited.kind === "text") {
21463
- return patchParagraphUnit(block, orig, edited, ctx, skip);
21570
+ if ((block.type === "paragraph" || block.type === "heading") && orig.kind === "text") {
21571
+ if (edited.kind === "text") return patchParagraphUnit(block, orig, edited, ctx, skip);
21572
+ if (edited.kind === "gfm-table") return convertParagraphToTable(block, orig, edited, ctx, skip);
21573
+ if (edited.kind === "html-table") return skip("\uBB38\uB2E8\u2192\uBCD1\uD569\uD45C(HTML) \uBCC0\uD658\uC740 \uBBF8\uC9C0\uC6D0 \u2014 GFM \uD45C(| \uD5E4\uB354 | \u2026 |)\uB85C \uC791\uC131\uD558\uC138\uC694");
21464
21574
  }
21465
21575
  return skip("\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uBE14\uB85D \uC720\uD615 \uBCC0\uACBD");
21466
21576
  }
21577
+ function extractParaPrIdRef(xml, start) {
21578
+ const gt = xml.indexOf(">", start);
21579
+ if (gt < 0) return null;
21580
+ const m = xml.slice(start, gt + 1).match(/paraPrIDRef="(\d+)"/);
21581
+ return m ? parseInt(m[1], 10) : null;
21582
+ }
21583
+ function convertParagraphToTable(block, orig, edited, ctx, skip) {
21584
+ const ti = ctx.tableInsert;
21585
+ if (!ti) return skip("\uBB38\uB2E8\u2192\uD45C \uBCC0\uD658 \uBD88\uAC00 \u2014 header \uC5D4\uD2B8\uB9AC(borderFills) \uD574\uC11D \uC2E4\uD328");
21586
+ const mapping = ctx.paraMap.get(orig.blockIdx);
21587
+ 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");
21588
+ const para = mapping.para;
21589
+ 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");
21590
+ const scan = ctx.scans[para.sectionIndex];
21591
+ if (!scan) return skip("\uC139\uC158 \uB9E4\uD551 \uC2E4\uD328");
21592
+ const pEnd = findElementEnd(scan.xml, para.start);
21593
+ if (pEnd < 0) return skip("\uBB38\uB2E8 \uB05D \uC704\uCE58 \uD0D0\uC0C9 \uC2E4\uD328");
21594
+ const rows = parseGfmTable(edited.lines);
21595
+ if (rows.length === 0 || rows.every((r) => r.length === 0)) return skip("\uD45C \uB0B4\uC6A9\uC774 \uBE44\uC5B4 \uC788\uC74C");
21596
+ if (ti.borderFillId === null) {
21597
+ const inj = injectCellBorderFill(ti.headerXml, ti.nextId++);
21598
+ if (!inj) return skip("header <hh:borderFills> \uAD6C\uC870\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4 \uD45C \uD14C\uB450\uB9AC \uC0DD\uC131 \uBD88\uAC00");
21599
+ ti.borderFillId = inj.borderFillId;
21600
+ ti.headerSplices.push(...inj.headerSplices);
21601
+ }
21602
+ const outerParaPrId = extractParaPrIdRef(scan.xml, para.start) ?? 0;
21603
+ const tableXml = buildTableParagraphXml(rows, {
21604
+ borderFillId: ti.borderFillId,
21605
+ outerParaPrId,
21606
+ cellParaPrId: 0,
21607
+ cellCharPrId: 0,
21608
+ tableId: ti.nextId++
21609
+ });
21610
+ ctx.sectionSplices[para.sectionIndex].push({ start: para.start, end: pEnd, replacement: tableXml });
21611
+ return 1;
21612
+ }
21467
21613
  function patchParagraphUnit(block, orig, edited, ctx, skip) {
21468
21614
  const mapping = ctx.paraMap.get(orig.blockIdx);
21469
21615
  if (!mapping?.para) return skip("\uBB38\uB2E8 \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328 (\uBA38\uB9AC\uB9D0/\uAE00\uC0C1\uC790/\uCEA1\uC158 \uC601\uC5ED\uC774\uAC70\uB098 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58)");
@@ -21544,6 +21690,24 @@ function unitToBlock(u) {
21544
21690
  function u8ToArrayBuffer(u8) {
21545
21691
  return u8.buffer.slice(u8.byteOffset, u8.byteOffset + u8.byteLength);
21546
21692
  }
21693
+ async function resolveHeaderEntryName(zip) {
21694
+ for (const p of ["Contents/header.xml", "header.xml"]) {
21695
+ if (zip.file(p)) return p;
21696
+ }
21697
+ for (const mp of ["Contents/content.hpf", "content.hpf"]) {
21698
+ const f = zip.file(mp);
21699
+ if (!f) continue;
21700
+ const xml = await f.async("text");
21701
+ const m = xml.match(/<opf:item\b[^>]*\bid="header"[^>]*\bhref="([^"]+)"/i) || xml.match(/<opf:item\b[^>]*\bhref="([^"]*header[^"]*\.xml)"/i);
21702
+ if (m) {
21703
+ let href = m[1];
21704
+ if (!href.startsWith("/") && !href.startsWith("Contents/")) href = "Contents/" + href;
21705
+ if (zip.file(href)) return href;
21706
+ }
21707
+ }
21708
+ const found = Object.keys(zip.files).find((n) => /header\.xml$/i.test(n));
21709
+ return found ?? null;
21710
+ }
21547
21711
 
21548
21712
  // src/roundtrip/hwp5-patch.ts
21549
21713
  import { deflateRawSync as deflateRawSync2 } from "zlib";
@@ -22182,8 +22346,11 @@ function handleModified(orig, edited, ctx) {
22182
22346
  if (orig.kind === "html-table") return patchHtmlCells5(block.table, scanTable, orig, edited, ctx, skip);
22183
22347
  return patchTextChunk5(block.table, scanTable, orig, edited, ctx, skip);
22184
22348
  }
22185
- if ((block.type === "paragraph" || block.type === "heading") && orig.kind === "text" && edited.kind === "text") {
22186
- return patchParagraph(block, orig, edited, ctx, skip);
22349
+ if ((block.type === "paragraph" || block.type === "heading") && orig.kind === "text") {
22350
+ if (edited.kind === "text") return patchParagraph(block, orig, edited, ctx, skip);
22351
+ if (edited.kind === "gfm-table" || edited.kind === "html-table") {
22352
+ return skip("HWP5(.hwp) \uBC14\uC774\uB108\uB9AC\uB294 \uBB38\uB2E8\u2192\uD45C \uC778\uD50C\uB808\uC774\uC2A4 \uBCC0\uD658 \uBBF8\uC9C0\uC6D0 \u2014 generate\uB85C \uC0C8 \uBB38\uC11C\uB97C \uB9CC\uB4E4\uAC70\uB098, HWPX(.hwpx)\uB85C \uC800\uC7A5 \uD6C4 patch\uD558\uC138\uC694");
22353
+ }
22187
22354
  }
22188
22355
  return skip("\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uBE14\uB85D \uC720\uD615 \uBCC0\uACBD");
22189
22356
  }
@@ -23120,7 +23287,7 @@ async function parseHwp(buffer, options) {
23120
23287
  async function parsePdf(buffer, options) {
23121
23288
  let parsePdfDocument;
23122
23289
  try {
23123
- const mod = await import("./parser-PQDICHD5.js");
23290
+ const mod = await import("./parser-LMBDB7RM.js");
23124
23291
  parsePdfDocument = mod.parsePdfDocument;
23125
23292
  } catch {
23126
23293
  return {
@@ -23223,6 +23390,8 @@ export {
23223
23390
  buildRangeSplices,
23224
23391
  applySplices,
23225
23392
  fillHwpx,
23393
+ PRESET_ALIAS,
23394
+ normalizeGongmunPreset,
23226
23395
  markdownToHwpx,
23227
23396
  compare,
23228
23397
  diffBlocks,
@@ -23245,4 +23414,4 @@ export {
23245
23414
  parseHwpml,
23246
23415
  fillForm
23247
23416
  };
23248
- //# sourceMappingURL=chunk-YFNBHLLM.js.map
23417
+ //# sourceMappingURL=chunk-GTCJQANY.js.map