kordoc 3.3.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +584 -584
  3. package/dist/{-RAVJL5UK.js → -YOQGQ22S.js} +5 -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-GE43BE46.js → chunk-AIQ3ISQU.js} +1 -1
  7. package/dist/chunk-AIQ3ISQU.js.map +1 -0
  8. package/dist/{chunk-MEPHGCPQ.js → chunk-CFQLK3LM.js} +1 -1
  9. package/dist/chunk-CFQLK3LM.js.map +1 -0
  10. package/dist/{chunk-J72F7FIT.js → chunk-CGHPBI3X.js} +256 -84
  11. package/dist/chunk-CGHPBI3X.js.map +1 -0
  12. package/dist/{chunk-HNUFTEV5.js → chunk-FPFB7AFX.js} +2 -2
  13. package/dist/chunk-FPFB7AFX.js.map +1 -0
  14. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  15. package/dist/{chunk-ESBGMBRF.js → chunk-SE3KEL4G.js} +2 -2
  16. package/dist/chunk-SE3KEL4G.js.map +1 -0
  17. package/dist/{chunk-FUB2BGXV.cjs → chunk-W7JHJQ2O.cjs} +2 -2
  18. package/dist/chunk-W7JHJQ2O.cjs.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 +8 -8
  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 +424 -252
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.js +254 -82
  33. package/dist/index.js.map +1 -1
  34. package/dist/mcp.js +6 -6
  35. package/dist/mcp.js.map +1 -1
  36. package/dist/page-range-CIRRJPXJ.js +7 -0
  37. package/dist/page-range-OF5I4PQY.js +8 -0
  38. package/dist/page-range-TPIRSA3J.cjs +8 -0
  39. package/dist/page-range-TPIRSA3J.cjs.map +1 -0
  40. package/dist/{parser-FLE2ZPAW.js → parser-5HDZZWDH.js} +5 -5
  41. package/dist/parser-5HDZZWDH.js.map +1 -0
  42. package/dist/{parser-DADWQYCQ.js → parser-ET64VEEX.js} +5 -5
  43. package/dist/parser-ET64VEEX.js.map +1 -0
  44. package/dist/{parser-YWKNDGKI.cjs → parser-JAZCZJI6.cjs} +18 -18
  45. package/dist/parser-JAZCZJI6.cjs.map +1 -0
  46. package/dist/{provider-G4C2V2PD.cjs → provider-5K7O3Z2O.cjs} +1 -1
  47. package/dist/provider-5K7O3Z2O.cjs.map +1 -0
  48. package/dist/{provider-AKROB7WQ.js → provider-7H4CPZYS.js} +1 -1
  49. package/dist/provider-7H4CPZYS.js.map +1 -0
  50. package/dist/{provider-4ZJKV3DC.js → provider-H4WWSPOV.js} +1 -1
  51. package/dist/provider-H4WWSPOV.js.map +1 -0
  52. package/dist/{setup-57FB3LSP.js → setup-QSJ2INNS.js} +1 -1
  53. package/dist/setup-QSJ2INNS.js.map +1 -0
  54. package/dist/{watch-6QPQU277.js → watch-56GNC2YN.js} +5 -5
  55. package/dist/watch-56GNC2YN.js.map +1 -0
  56. package/package.json +98 -98
  57. package/dist/chunk-DCZVOIEO.cjs.map +0 -1
  58. package/dist/chunk-ESBGMBRF.js.map +0 -1
  59. package/dist/chunk-FUB2BGXV.cjs.map +0 -1
  60. package/dist/chunk-GE43BE46.js.map +0 -1
  61. package/dist/chunk-HNUFTEV5.js.map +0 -1
  62. package/dist/chunk-J72F7FIT.js.map +0 -1
  63. package/dist/chunk-MEPHGCPQ.js.map +0 -1
  64. package/dist/chunk-MOL7MDBG.js.map +0 -1
  65. package/dist/formula-5NKVS2LR.cjs.map +0 -1
  66. package/dist/formula-JCNF43NE.js.map +0 -1
  67. package/dist/formula-RXVSQPXI.js.map +0 -1
  68. package/dist/page-range-737B4EZW.js +0 -8
  69. package/dist/page-range-LNMXJU6W.js +0 -7
  70. package/dist/page-range-P7SDW6LR.cjs +0 -8
  71. package/dist/page-range-P7SDW6LR.cjs.map +0 -1
  72. package/dist/parser-DADWQYCQ.js.map +0 -1
  73. package/dist/parser-FLE2ZPAW.js.map +0 -1
  74. package/dist/parser-YWKNDGKI.cjs.map +0 -1
  75. package/dist/provider-4ZJKV3DC.js.map +0 -1
  76. package/dist/provider-AKROB7WQ.js.map +0 -1
  77. package/dist/provider-G4C2V2PD.cjs.map +0 -1
  78. package/dist/setup-57FB3LSP.js.map +0 -1
  79. package/dist/watch-6QPQU277.js.map +0 -1
  80. /package/dist/{-RAVJL5UK.js.map → -YOQGQ22S.js.map} +0 -0
  81. /package/dist/{detect-RI2MQ33K.js.map → detect-NTR2FUEG.js.map} +0 -0
  82. /package/dist/{page-range-737B4EZW.js.map → page-range-CIRRJPXJ.js.map} +0 -0
  83. /package/dist/{page-range-LNMXJU6W.js.map → page-range-OF5I4PQY.js.map} +0 -0
package/dist/index.js CHANGED
@@ -17,10 +17,10 @@ import {
17
17
  sanitizeHref,
18
18
  stripDtd,
19
19
  toArrayBuffer
20
- } from "./chunk-ESBGMBRF.js";
20
+ } from "./chunk-SE3KEL4G.js";
21
21
  import {
22
22
  parsePageRange
23
- } from "./chunk-GE43BE46.js";
23
+ } from "./chunk-AIQ3ISQU.js";
24
24
 
25
25
  // src/index.ts
26
26
  import { readFile } from "fs/promises";
@@ -16907,7 +16907,7 @@ async function parseXlsxDocument(buffer, options) {
16907
16907
  }
16908
16908
  let pageFilter = null;
16909
16909
  if (options?.pages) {
16910
- const { parsePageRange: parsePageRange2 } = await import("./page-range-LNMXJU6W.js");
16910
+ const { parsePageRange: parsePageRange2 } = await import("./page-range-CIRRJPXJ.js");
16911
16911
  pageFilter = parsePageRange2(options.pages, sheets.length);
16912
16912
  }
16913
16913
  const blocks = [];
@@ -17545,7 +17545,7 @@ async function parseXlsDocument(buffer, options) {
17545
17545
  const totalSheets = Math.min(globals.sheets.length, MAX_SHEETS2);
17546
17546
  let pageFilter = null;
17547
17547
  if (options?.pages) {
17548
- const { parsePageRange: parsePageRange2 } = await import("./page-range-LNMXJU6W.js");
17548
+ const { parsePageRange: parsePageRange2 } = await import("./page-range-CIRRJPXJ.js");
17549
17549
  pageFilter = parsePageRange2(options.pages, totalSheets);
17550
17550
  }
17551
17551
  const allBlocks = [];
@@ -17968,20 +17968,32 @@ function isDisplayMath(el) {
17968
17968
 
17969
17969
  // src/docx/parser.ts
17970
17970
  var MAX_DECOMPRESS_SIZE4 = 100 * 1024 * 1024;
17971
- function getChildElements(parent, localName2) {
17971
+ function matchesLocal(el, localName2) {
17972
+ return el.localName === localName2 || (el.tagName?.endsWith(`:${localName2}`) ?? false);
17973
+ }
17974
+ function effectiveChildElements(parent) {
17972
17975
  const result = [];
17973
17976
  const children = parent.childNodes;
17974
17977
  for (let i = 0; i < children.length; i++) {
17975
17978
  const node = children[i];
17976
- if (node.nodeType === 1) {
17977
- const el = node;
17978
- if (el.localName === localName2 || el.tagName?.endsWith(`:${localName2}`)) {
17979
- result.push(el);
17979
+ if (node.nodeType !== 1) continue;
17980
+ const el = node;
17981
+ if (matchesLocal(el, "sdt")) {
17982
+ for (let j = 0; j < el.childNodes.length; j++) {
17983
+ const c = el.childNodes[j];
17984
+ if (c.nodeType === 1 && matchesLocal(c, "sdtContent")) {
17985
+ result.push(...effectiveChildElements(c));
17986
+ }
17980
17987
  }
17988
+ } else {
17989
+ result.push(el);
17981
17990
  }
17982
17991
  }
17983
17992
  return result;
17984
17993
  }
17994
+ function getChildElements(parent, localName2) {
17995
+ return effectiveChildElements(parent).filter((el) => matchesLocal(el, localName2));
17996
+ }
17985
17997
  function findElements(parent, localName2) {
17986
17998
  const result = [];
17987
17999
  const walk = (node) => {
@@ -18372,11 +18384,8 @@ async function parseDocxDocument(buffer, options) {
18372
18384
  }
18373
18385
  const blocks = [];
18374
18386
  const bodyEl = body[0];
18375
- const children = bodyEl.childNodes;
18376
- for (let i = 0; i < children.length; i++) {
18377
- const node = children[i];
18378
- if (node.nodeType !== 1) continue;
18379
- const el = node;
18387
+ const topLevel = effectiveChildElements(bodyEl);
18388
+ for (const el of topLevel) {
18380
18389
  const localName2 = el.localName ?? el.tagName?.split(":").pop();
18381
18390
  if (localName2 === "p") {
18382
18391
  const block = parseParagraph2(el, styles, numbering, footnotes, rels);
@@ -18882,8 +18891,9 @@ function extractFromTable(table) {
18882
18891
  if (table.cols >= 2) {
18883
18892
  for (let r = 0; r < table.rows; r++) {
18884
18893
  for (let c = 0; c < table.cols - 1; c++) {
18885
- const labelCell = table.cells[r][c];
18886
- const valueCell = table.cells[r][c + 1];
18894
+ const labelCell = table.cells[r]?.[c];
18895
+ const valueCell = table.cells[r]?.[c + 1];
18896
+ if (!labelCell || !valueCell) continue;
18887
18897
  if (isLabelCell(labelCell.text)) {
18888
18898
  fields.push({
18889
18899
  label: labelCell.text.trim().replace(/[::]\s*$/, ""),
@@ -18904,8 +18914,8 @@ function extractFromTable(table) {
18904
18914
  if (allLabels) {
18905
18915
  for (let r = 1; r < table.rows; r++) {
18906
18916
  for (let c = 0; c < table.cols; c++) {
18907
- const label = headerRow[c].text.trim();
18908
- const value = table.cells[r][c].text.trim();
18917
+ const label = headerRow[c]?.text.trim() ?? "";
18918
+ const value = table.cells[r]?.[c]?.text.trim() ?? "";
18909
18919
  if (label && value) {
18910
18920
  fields.push({ label, value, row: r, col: c });
18911
18921
  }
@@ -19059,15 +19069,18 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
19059
19069
  if (!allLabels) return;
19060
19070
  for (let r = 1; r < table.rows; r++) {
19061
19071
  for (let c = 0; c < table.cols; c++) {
19062
- const headerLabel = normalizeLabel(headerRow[c].text);
19072
+ const headerCell = headerRow[c];
19073
+ const valueCell = table.cells[r]?.[c];
19074
+ if (!headerCell || !valueCell) continue;
19075
+ const headerLabel = normalizeLabel(headerCell.text);
19063
19076
  const matchKey = findMatchingKey(headerLabel, values);
19064
19077
  if (matchKey === void 0) continue;
19065
19078
  if (matchedLabels.has(matchKey)) continue;
19066
19079
  const newValue = values.get(matchKey);
19067
- table.cells[r][c].text = newValue;
19080
+ valueCell.text = newValue;
19068
19081
  matchedLabels.add(matchKey);
19069
19082
  filled.push({
19070
- label: headerRow[c].text.trim(),
19083
+ label: headerCell.text.trim(),
19071
19084
  value: newValue,
19072
19085
  row: r,
19073
19086
  col: c
@@ -22247,14 +22260,7 @@ async function patchHwp(original, editedMarkdown, options) {
22247
22260
  const editedUnits = splitMarkdownUnits(editedMarkdown);
22248
22261
  const pairs = alignUnits(origUnits.map((u) => u.raw), editedUnits.map((u) => u.raw));
22249
22262
  const paraMap = resolveParaMappings(origBlocks, scans);
22250
- const scanTables = scans.flatMap((s) => s.tables);
22251
- const obTableOrdinals = /* @__PURE__ */ new Map();
22252
- {
22253
- let ordinal = 0;
22254
- for (let i = 0; i < origBlocks.length; i++) {
22255
- if (origBlocks[i].type === "table" && origBlocks[i].table) obTableOrdinals.set(i, ordinal++);
22256
- }
22257
- }
22263
+ const tableMap = resolveTableMappings(origBlocks, scans.flatMap((s) => s.tables));
22258
22264
  for (const [oi, ei] of pairs) {
22259
22265
  if (oi !== null && ei !== null) {
22260
22266
  const orig = origUnits[oi];
@@ -22264,8 +22270,7 @@ async function patchHwp(original, editedMarkdown, options) {
22264
22270
  origBlocks,
22265
22271
  paraMap,
22266
22272
  scans,
22267
- scanTables,
22268
- obTableOrdinals,
22273
+ tableMap,
22269
22274
  skipped
22270
22275
  });
22271
22276
  } else if (oi !== null) {
@@ -22350,6 +22355,46 @@ function resolveParaMappings(blocks, scans) {
22350
22355
  }
22351
22356
  return result;
22352
22357
  }
22358
+ function resolveTableMappings(blocks, scanTables) {
22359
+ const result = /* @__PURE__ */ new Map();
22360
+ let si = 0;
22361
+ for (let i = 0; i < blocks.length; i++) {
22362
+ const table = blocks[i].table;
22363
+ if (blocks[i].type !== "table" || !table) continue;
22364
+ const cands = [];
22365
+ for (let k = si; k < scanTables.length; k++) {
22366
+ if (scanTables[k].rows === table.rows && scanTables[k].cols === table.cols) cands.push(k);
22367
+ }
22368
+ if (cands.length === 0) continue;
22369
+ let pick = cands[0];
22370
+ if (cands.length > 1) {
22371
+ let best = tableContentScore(table, scanTables[cands[0]]);
22372
+ for (let ci = 1; ci < cands.length; ci++) {
22373
+ const sc = tableContentScore(table, scanTables[cands[ci]]);
22374
+ if (sc > best) {
22375
+ best = sc;
22376
+ pick = cands[ci];
22377
+ }
22378
+ }
22379
+ }
22380
+ result.set(i, scanTables[pick]);
22381
+ si = pick + 1;
22382
+ }
22383
+ return result;
22384
+ }
22385
+ function tableContentScore(irTable, scanTable) {
22386
+ let matched = 0;
22387
+ for (const [key, scanCell] of scanTable.cells) {
22388
+ const comma = key.indexOf(",");
22389
+ const r = Number(key.slice(0, comma)), c = Number(key.slice(comma + 1));
22390
+ const irCell = irTable.cells[r]?.[c];
22391
+ if (!irCell) continue;
22392
+ const a = normForMatch(scanCell.paras.map((p) => p.rawText).join(" "));
22393
+ const b = normForMatch(stripCellTokens(irCell.text));
22394
+ if (a && a === b) matched++;
22395
+ }
22396
+ return matched;
22397
+ }
22353
22398
  function handleModified(orig, edited, ctx) {
22354
22399
  const block = ctx.origBlocks[orig.blockIdx];
22355
22400
  const skip = (reason) => {
@@ -22362,12 +22407,10 @@ function handleModified(orig, edited, ctx) {
22362
22407
  if (orig.fragment) return skip("\uBB38\uB2E8 \uBD84\uC808(\uAC15\uC81C \uC904\uBC14\uAFC8/\uBCD1\uD569 \uC720\uB2DB) \u2014 \uBD80\uBD84 \uC218\uC815\uC740 \uBBF8\uC9C0\uC6D0 (v1)");
22363
22408
  if (block.type === "table" && block.table) {
22364
22409
  if (orig.kind !== edited.kind) return skip("\uD45C \u2194 \uBE44\uD45C \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0 (\uD45C \uAD6C\uC870 \uBCC0\uACBD)");
22365
- if (ctx.obTableOrdinals.size !== ctx.scanTables.length) return skip("\uD45C \uAC1C\uC218 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
22366
- const ordinal = ctx.obTableOrdinals.get(orig.blockIdx);
22367
- const scanTable = ordinal !== void 0 ? ctx.scanTables[ordinal] : void 0;
22368
- if (!scanTable) return skip("\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328");
22410
+ const scanTable = ctx.tableMap.get(orig.blockIdx);
22411
+ if (!scanTable) return skip("\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328 \u2014 \uD45C \uAC1C\uC218/\uAD6C\uC870 \uBD88\uC77C\uCE58\uB85C \uC2E0\uB8B0 \uBD88\uAC00");
22369
22412
  if (orig.kind === "gfm-table") return patchGfmCells(scanTable, orig, edited, ctx, skip);
22370
- if (orig.kind === "html-table") return skip("HTML \uD45C(\uBCD1\uD569/\uC904\uBC14\uAFC8 \uC140) \uC218\uC815\uC740 HWP5 \uBBF8\uC9C0\uC6D0 (v1)");
22413
+ if (orig.kind === "html-table") return patchHtmlCells5(block.table, scanTable, orig, edited, ctx, skip);
22371
22414
  return patchTextChunk5(block.table, scanTable, orig, edited, ctx, skip);
22372
22415
  }
22373
22416
  if ((block.type === "paragraph" || block.type === "heading") && orig.kind === "text" && edited.kind === "text") {
@@ -22424,35 +22467,87 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
22424
22467
  ctx.skipped.push({ reason, before: summarize(origRows[r][c]), after: summarize(editedRows[r][c]) });
22425
22468
  return 0;
22426
22469
  };
22427
- const before = gfmCellToPlain(origRows[r][c]);
22428
- const after = gfmCellToPlain(editedRows[r][c]);
22429
- if (before === null || after === null) {
22430
- cellSkip("\uC11C\uC2DD/\uB9C1\uD06C/\uC774\uBBF8\uC9C0 \uD3EC\uD568 \uC140 \uC218\uC815\uC740 \uBBF8\uC9C0\uC6D0 (v1)");
22431
- continue;
22432
- }
22433
- if (after.includes("\n")) {
22434
- cellSkip("\uC140 \uB0B4 \uC904\uBC14\uAFC8 \uCD94\uAC00\uB294 \uBBF8\uC9C0\uC6D0 (v1)");
22435
- continue;
22436
- }
22437
22470
  const cell = scanTable.cells.get(`${r},${c}`);
22438
22471
  if (!cell) {
22439
22472
  cellSkip("\uBCD1\uD569 \uC601\uC5ED \uC140 \u2014 \uC575\uCEE4 \uC140\uC774 \uC544\uB2C8\uBBC0\uB85C \uBBF8\uC9C0\uC6D0");
22440
22473
  continue;
22441
22474
  }
22442
- if (cell.paras.length !== 1) {
22443
- cellSkip("\uBCF5\uC218 \uBB38\uB2E8 \uC140 \uC218\uC815\uC740 \uBBF8\uC9C0\uC6D0 (v1)");
22475
+ const beforeParts = origRows[r][c].split(/<br\s*\/?>/i);
22476
+ const afterParts = editedRows[r][c].split(/<br\s*\/?>/i);
22477
+ if (beforeParts.length !== cell.paras.length || afterParts.length !== cell.paras.length) {
22478
+ cellSkip("\uC140 \uBB38\uB2E8 \uC218 \uBCC0\uACBD \u2014 \uBBF8\uC9C0\uC6D0 (\uBB38\uB2E8 \uCD94\uAC00/\uC0AD\uC81C)");
22444
22479
  continue;
22445
22480
  }
22446
- const para = cell.paras[0];
22447
- if (normForMatch(para.rawText) !== normForMatch(before)) {
22448
- cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
22449
- continue;
22481
+ for (let k = 0; k < cell.paras.length; k++) {
22482
+ const before = gfmCellToPlain(beforeParts[k]);
22483
+ const after = gfmCellToPlain(afterParts[k]);
22484
+ if (before === null || after === null) {
22485
+ cellSkip("\uC11C\uC2DD/\uB9C1\uD06C/\uC774\uBBF8\uC9C0 \uD3EC\uD568 \uC140 \uC218\uC815\uC740 \uBBF8\uC9C0\uC6D0 (v1)");
22486
+ break;
22487
+ }
22488
+ if (before === after) continue;
22489
+ if (after.includes("\n")) {
22490
+ cellSkip("\uC140 \uB0B4 \uC904\uBC14\uAFC8 \uCD94\uAC00\uB294 \uBBF8\uC9C0\uC6D0 (v1)");
22491
+ break;
22492
+ }
22493
+ const para = cell.paras[k];
22494
+ if (normForMatch(para.rawText) !== normForMatch(before)) {
22495
+ cellSkip("\uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58 \u2014 \uC18C\uC2A4\uB9F5 \uC2E0\uB8B0 \uBD88\uAC00");
22496
+ break;
22497
+ }
22498
+ if (sanitizeText(after) !== after) {
22499
+ cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
22500
+ break;
22501
+ }
22502
+ applied += stageParaPatch(ctx.scans[para.sectionIndex], para, after, cellSkip);
22450
22503
  }
22451
- if (sanitizeText(after) !== after) {
22452
- cellSkip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uBBF8\uC9C0\uC6D0");
22504
+ }
22505
+ }
22506
+ return applied;
22507
+ }
22508
+ function extractImgTags5(inner) {
22509
+ return (inner.match(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi) || []).join(" ");
22510
+ }
22511
+ function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
22512
+ if (replicateTableToHtml(table) !== orig.raw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
22513
+ const replica = replicateHtmlTable(table);
22514
+ const origRows = parseHtmlTable(orig.raw);
22515
+ 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))) {
22516
+ return skip("\uC140 \uACBD\uACC4 \uBAA8\uD638 (\uB9AC\uD130\uB7F4 \uD0DC\uADF8 \uC758\uC2EC) \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
22517
+ }
22518
+ const editedRows = parseHtmlTable(edited.raw);
22519
+ if (!editedRows) return skip("\uD3B8\uC9D1\uB41C HTML \uD45C \uD30C\uC2F1 \uC2E4\uD328");
22520
+ if (editedRows.length !== replica.length) return skip("\uD45C \uD589 \uCD94\uAC00/\uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0 (\uD45C \uAD6C\uC870 \uBCC0\uACBD)");
22521
+ let applied = 0;
22522
+ for (let r = 0; r < replica.length; r++) {
22523
+ if (editedRows[r].cells.length !== replica[r].cells.length) {
22524
+ skip(`\uD45C ${r + 1}\uD589 \uC140 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
22525
+ continue;
22526
+ }
22527
+ for (let c = 0; c < replica[r].cells.length; c++) {
22528
+ const oc = replica[r].cells[c];
22529
+ const ec = editedRows[r].cells[c];
22530
+ if (oc.colSpan !== ec.colSpan || oc.rowSpan !== ec.rowSpan) {
22531
+ skip("\uC140 \uBCD1\uD569(colspan/rowspan) \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
22453
22532
  continue;
22454
22533
  }
22455
- applied += stageParaPatch(ctx.scans[para.sectionIndex], para, after, cellSkip);
22534
+ if (oc.inner === ec.inner) continue;
22535
+ const origContent = htmlCellInnerToLines(oc.inner);
22536
+ const editedContent = htmlCellInnerToLines(ec.inner);
22537
+ if (origContent.hadNonText || editedContent.hadNonText) {
22538
+ if (extractImgTags5(oc.inner) !== extractImgTags5(ec.inner)) {
22539
+ skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
22540
+ continue;
22541
+ }
22542
+ if (extractTopLevelTables(oc.inner).join("\n") !== extractTopLevelTables(ec.inner).join("\n")) {
22543
+ skip("\uC140 \uB0B4 \uC911\uCCA9\uD45C \uC218\uC815\uC740 HWP5 \uBBF8\uC9C0\uC6D0 (v1)");
22544
+ continue;
22545
+ }
22546
+ }
22547
+ if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
22548
+ const newLines = editedContent.lines.map((l) => unescapeGfm(l));
22549
+ applied += applyCellEdit5(table, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
22550
+ }
22456
22551
  }
22457
22552
  }
22458
22553
  return applied;
@@ -22544,15 +22639,103 @@ function gfmCellToPlain(md2) {
22544
22639
  let t = md2.trim();
22545
22640
  const bold = t.match(/^\*\*([\s\S]+)\*\*$/);
22546
22641
  if (bold) t = bold[1];
22547
- if (/[*`]|!\[|\]\(|<(?!br\s*\/?>)/i.test(t)) return null;
22642
+ if (/[*`]|!\[|\]\(/.test(t)) return null;
22643
+ if (/<(?!br\s*\/?>)[a-zA-Z/]/i.test(t)) return null;
22548
22644
  return unescapeGfm(unescapeGfmCell(t));
22549
22645
  }
22550
- var PARA_BREAK = Buffer.from([13, 0]);
22646
+ function splitParaText(data) {
22647
+ const toks = [];
22648
+ let i = 0;
22649
+ while (i + 1 < data.length) {
22650
+ const ch = data.readUInt16LE(i);
22651
+ const start = i;
22652
+ i += 2;
22653
+ if (ch >= 32) {
22654
+ let units = 1;
22655
+ if (ch >= 55296 && ch <= 56319 && i + 1 < data.length) {
22656
+ const lo = data.readUInt16LE(i);
22657
+ if (lo >= 56320 && lo <= 57343) {
22658
+ i += 2;
22659
+ units = 2;
22660
+ }
22661
+ }
22662
+ toks.push({ start, end: i, units, plain: true, visible: true });
22663
+ continue;
22664
+ }
22665
+ switch (ch) {
22666
+ case 0:
22667
+ case 24:
22668
+ case 25:
22669
+ case 30:
22670
+ case 31:
22671
+ toks.push({ start, end: i, units: 1, plain: false, visible: true });
22672
+ break;
22673
+ case 9:
22674
+ if (i + 14 <= data.length) i += 14;
22675
+ toks.push({ start, end: i, units: 1, plain: false, visible: true });
22676
+ break;
22677
+ case 13:
22678
+ toks.push({ start, end: i, units: 1, plain: false, visible: false });
22679
+ break;
22680
+ case 10:
22681
+ if (i + 16 <= data.length && data.readUInt16LE(i) === 11) {
22682
+ i += 16;
22683
+ toks.push({ start, end: i, units: 1, plain: false, visible: false });
22684
+ } else {
22685
+ if (i + 14 <= data.length) i += 14;
22686
+ toks.push({ start, end: i, units: 1, plain: false, visible: true });
22687
+ }
22688
+ break;
22689
+ default: {
22690
+ const ext = isExtendedOnlyCtrlChar(ch);
22691
+ const inl = ch >= 4 && ch <= 9 || ch >= 19 && ch <= 20;
22692
+ if ((ext || inl) && i + 14 <= data.length) i += 14;
22693
+ toks.push({ start, end: i, units: 1, plain: false, visible: false });
22694
+ break;
22695
+ }
22696
+ }
22697
+ }
22698
+ if (i !== data.length) return null;
22699
+ let firstP = -1, lastP = -1;
22700
+ for (let k = 0; k < toks.length; k++) if (toks[k].plain) {
22701
+ if (firstP < 0) firstP = k;
22702
+ lastP = k;
22703
+ }
22704
+ if (firstP < 0) return null;
22705
+ for (let k = firstP; k <= lastP; k++) if (!toks[k].plain) return null;
22706
+ for (let k = 0; k < firstP; k++) if (toks[k].visible) return null;
22707
+ for (let k = lastP + 1; k < toks.length; k++) if (toks[k].visible) return null;
22708
+ const prefixEnd = toks[firstP].start;
22709
+ const coreEnd = toks[lastP].end;
22710
+ const prefixUnits = prefixEnd / 2;
22711
+ const suffixUnits = (data.length - coreEnd) / 2;
22712
+ return {
22713
+ prefix: data.subarray(0, prefixEnd),
22714
+ prefixUnits,
22715
+ core: data.subarray(prefixEnd, coreEnd).toString("utf16le"),
22716
+ suffix: data.subarray(coreEnd),
22717
+ suffixUnits
22718
+ };
22719
+ }
22720
+ function rebuildCharShape(csData, coreStartUnit) {
22721
+ const pairs = [];
22722
+ for (let o = 0; o + 8 <= csData.length; o += 8) pairs.push([csData.readUInt32LE(o), csData.readUInt32LE(o + 4)]);
22723
+ if (pairs.length === 0) return { buf: Buffer.from(csData.subarray(0, 8)), count: 1 };
22724
+ let coreId = pairs[0][1];
22725
+ for (const [p, id] of pairs) if (p <= coreStartUnit) coreId = id;
22726
+ const kept = pairs.filter(([p]) => p < coreStartUnit);
22727
+ if (kept.length === 0 || kept[kept.length - 1][1] !== coreId) kept.push([coreStartUnit, coreId]);
22728
+ const buf = Buffer.alloc(kept.length * 8);
22729
+ kept.forEach(([p, id], k) => {
22730
+ buf.writeUInt32LE(p >>> 0, k * 8);
22731
+ buf.writeUInt32LE(id >>> 0, k * 8 + 4);
22732
+ });
22733
+ return { buf, count: kept.length };
22734
+ }
22551
22735
  function stageParaPatch(scan, para, newPlain, skip) {
22552
22736
  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");
22553
22737
  if (para.textIdx === -1) return skip("\uBE48 \uBB38\uB2E8 \uD14D\uC2A4\uD2B8 \uCD94\uAC00\uB294 \uBBF8\uC9C0\uC6D0 (v1)");
22554
22738
  if (para.textIdx === -2) return skip("\uBCF5\uC218 PARA_TEXT \uB808\uCF54\uB4DC \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
22555
- if (para.ctrlMask !== 0) return skip("\uCEE8\uD2B8\uB864 \uBB38\uC790 \uD3EC\uD568 \uBB38\uB2E8(\uD0ED/\uAC1C\uCCB4/\uD544\uB4DC/\uD2B9\uC218\uACF5\uBC31) \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
22556
22739
  if (para.rangeTagCount > 0) return skip("\uBC94\uC704 \uD0DC\uADF8(\uD615\uAD11\uD39C/\uAD50\uC815\uBD80\uD638) \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
22557
22740
  if (para.charShapeIdx < 0 || para.lineSegIdx < 0) return skip("\uBB38\uB2E8 \uB808\uCF54\uB4DC \uAD6C\uC131 \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
22558
22741
  if (scan.repl.has(para.headerIdx)) return skip("\uB3D9\uC77C \uBB38\uB2E8 \uC911\uBCF5 \uC218\uC815 \u2014 \uCCAB \uC218\uC815\uB9CC \uC801\uC6A9");
@@ -22561,36 +22744,25 @@ function stageParaPatch(scan, para, newPlain, skip) {
22561
22744
  const headerRec = records[para.headerIdx];
22562
22745
  const textRec = records[para.textIdx];
22563
22746
  const charShapeRec = records[para.charShapeIdx];
22564
- const lineSegRec = records[para.lineSegIdx];
22565
- if (charShapeRec.data.length < 8 || lineSegRec.data.length < 36) {
22566
- return skip("CHAR_SHAPE/LINE_SEG \uB808\uCF54\uB4DC \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
22747
+ if (charShapeRec.data.length < 8) {
22748
+ return skip("CHAR_SHAPE \uB808\uCF54\uB4DC \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
22749
+ }
22750
+ const seg = splitParaText(textRec.data);
22751
+ if (!seg) {
22752
+ 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");
22567
22753
  }
22568
- const hadBreak = textRec.data.length >= 2 && textRec.data.readUInt16LE(textRec.data.length - 2) === 13;
22569
- const expect = hadBreak ? Buffer.concat([Buffer.from(para.rawText, "utf16le"), PARA_BREAK]) : Buffer.from(para.rawText, "utf16le");
22570
- if (!expect.equals(textRec.data)) return skip("PARA_TEXT \uC7AC\uAD6C\uC131 \uBD88\uC77C\uCE58 \u2014 \uC6D0\uBB38 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0");
22754
+ 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");
22571
22755
  const lead = para.rawText.match(/^\s*/)[0];
22572
22756
  const trail = para.rawText.match(/\s*$/)[0];
22573
22757
  const newRaw = para.rawText.trim() === para.rawText ? newPlain : lead + newPlain + trail;
22574
- const newText = hadBreak ? Buffer.concat([Buffer.from(newRaw, "utf16le"), PARA_BREAK]) : Buffer.from(newRaw, "utf16le");
22758
+ const newText = Buffer.concat([seg.prefix, Buffer.from(newRaw, "utf16le"), seg.suffix]);
22575
22759
  scan.repl.set(para.textIdx, newText);
22576
22760
  const newHeader = Buffer.from(headerRec.data);
22577
- const nChars = newRaw.length + (hadBreak ? 1 : 0);
22761
+ const nChars = seg.prefixUnits + newRaw.length + seg.suffixUnits;
22578
22762
  newHeader.writeUInt32LE((para.nCharsRaw & 2147483648 | nChars) >>> 0, 0);
22579
- if (charShapeRec.data.length > 8) {
22580
- newHeader.writeUInt16LE(1, 12);
22581
- scan.repl.set(para.charShapeIdx, Buffer.from(charShapeRec.data.subarray(0, 8)));
22582
- }
22583
- const csData = scan.repl.get(para.charShapeIdx) ?? Buffer.from(charShapeRec.data);
22584
- if (csData.readUInt32LE(0) !== 0) {
22585
- csData.writeUInt32LE(0, 0);
22586
- scan.repl.set(para.charShapeIdx, csData);
22587
- }
22588
- if (lineSegRec.data.length > 36 || lineSegRec.data.readUInt32LE(0) !== 0) {
22589
- const seg = Buffer.from(lineSegRec.data.subarray(0, 36));
22590
- seg.writeUInt32LE(0, 0);
22591
- newHeader.writeUInt16LE(1, 16);
22592
- scan.repl.set(para.lineSegIdx, seg);
22593
- }
22763
+ const cs = rebuildCharShape(charShapeRec.data, seg.prefixUnits);
22764
+ scan.repl.set(para.charShapeIdx, cs.buf);
22765
+ newHeader.writeUInt16LE(cs.count, 12);
22594
22766
  scan.repl.set(para.headerIdx, newHeader);
22595
22767
  return 1;
22596
22768
  }
@@ -23179,7 +23351,7 @@ async function parseHwp(buffer, options) {
23179
23351
  async function parsePdf(buffer, options) {
23180
23352
  let parsePdfDocument;
23181
23353
  try {
23182
- const mod = await import("./parser-FLE2ZPAW.js");
23354
+ const mod = await import("./parser-5HDZZWDH.js");
23183
23355
  parsePdfDocument = mod.parsePdfDocument;
23184
23356
  } catch {
23185
23357
  return {