kordoc 3.5.3 → 3.7.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 (38) hide show
  1. package/README.md +16 -1
  2. package/dist/{-N2SJBI4R.js → -7UC4ZWBS.js} +21 -5
  3. package/dist/chunk-DCZVOIEO.cjs.map +1 -1
  4. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  5. package/dist/{chunk-3Z2RAKIL.js → chunk-IJJMVTU5.js} +2 -2
  6. package/dist/chunk-IJJMVTU5.js.map +1 -0
  7. package/dist/{chunk-JOLDAN3Q.js → chunk-MEVKYW55.js} +2 -2
  8. package/dist/chunk-MEVKYW55.js.map +1 -0
  9. package/dist/{chunk-GUDFEDFK.js → chunk-NXRABCWW.js} +1588 -695
  10. package/dist/chunk-NXRABCWW.js.map +1 -0
  11. package/dist/{chunk-53XNKPN6.cjs → chunk-QZCP3UWU.cjs} +2 -2
  12. package/dist/chunk-QZCP3UWU.cjs.map +1 -0
  13. package/dist/cli.js +4 -4
  14. package/dist/formula-5NKVS2LR.cjs.map +1 -1
  15. package/dist/index.cjs +1787 -894
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +130 -8
  18. package/dist/index.d.ts +130 -8
  19. package/dist/index.js +1588 -695
  20. package/dist/index.js.map +1 -1
  21. package/dist/mcp.js +3 -3
  22. package/dist/page-range-P7SDW6LR.cjs.map +1 -1
  23. package/dist/{parser-IAROZTY3.js → parser-DR5CTZ74.js} +2 -2
  24. package/dist/{parser-CK5C6FF4.cjs → parser-RFLPUZ7P.cjs} +14 -14
  25. package/dist/parser-RFLPUZ7P.cjs.map +1 -0
  26. package/dist/{parser-CPFIB47T.js → parser-ZHJFQR44.js} +2 -2
  27. package/dist/provider-G4C2V2PD.cjs.map +1 -1
  28. package/dist/{watch-ZYNP3QFT.js → watch-UIX447QV.js} +3 -3
  29. package/package.json +1 -1
  30. package/dist/chunk-3Z2RAKIL.js.map +0 -1
  31. package/dist/chunk-53XNKPN6.cjs.map +0 -1
  32. package/dist/chunk-GUDFEDFK.js.map +0 -1
  33. package/dist/chunk-JOLDAN3Q.js.map +0 -1
  34. package/dist/parser-CK5C6FF4.cjs.map +0 -1
  35. /package/dist/{-N2SJBI4R.js.map → -7UC4ZWBS.js.map} +0 -0
  36. /package/dist/{parser-IAROZTY3.js.map → parser-DR5CTZ74.js.map} +0 -0
  37. /package/dist/{parser-CPFIB47T.js.map → parser-ZHJFQR44.js.map} +0 -0
  38. /package/dist/{watch-ZYNP3QFT.js.map → watch-UIX447QV.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5;
2
2
 
3
3
 
4
4
 
@@ -19,7 +19,7 @@
19
19
 
20
20
 
21
21
 
22
- var _chunk53XNKPN6cjs = require('./chunk-53XNKPN6.cjs');
22
+ var _chunkQZCP3UWUcjs = require('./chunk-QZCP3UWU.cjs');
23
23
 
24
24
 
25
25
  var _chunkDCZVOIEOcjs = require('./chunk-DCZVOIEO.cjs');
@@ -845,7 +845,7 @@ function createSectionShared() {
845
845
  function createXmlParser(warnings) {
846
846
  return new (0, _xmldom.DOMParser)({
847
847
  onError(level, msg2) {
848
- if (level === "fatalError") throw new (0, _chunk53XNKPN6cjs.KordocError)(`XML \uD30C\uC2F1 \uC2E4\uD328: ${msg2}`);
848
+ if (level === "fatalError") throw new (0, _chunkQZCP3UWUcjs.KordocError)(`XML \uD30C\uC2F1 \uC2E4\uD328: ${msg2}`);
849
849
  _optionalChain([warnings, 'optionalAccess', _3 => _3.push, 'call', _4 => _4({ code: "MALFORMED_XML", message: `XML ${level === "warn" ? "\uACBD\uACE0" : "\uC624\uB958"}: ${msg2}` })]);
850
850
  }
851
851
  });
@@ -867,10 +867,10 @@ async function extractHwpxStyles(zip, decompressed) {
867
867
  const xml = await file.async("text");
868
868
  if (decompressed) {
869
869
  decompressed.total += xml.length * 2;
870
- if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
870
+ if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
871
871
  }
872
872
  const parser = createXmlParser();
873
- const doc = parser.parseFromString(_chunk53XNKPN6cjs.stripDtd.call(void 0, xml), "text/xml");
873
+ const doc = parser.parseFromString(_chunkQZCP3UWUcjs.stripDtd.call(void 0, xml), "text/xml");
874
874
  if (!doc.documentElement) continue;
875
875
  parseCharProperties(doc, result.charProperties);
876
876
  parseStyleElements(doc, result.styles);
@@ -1092,7 +1092,7 @@ function resolveParaHeading(paraEl, ctx) {
1092
1092
  return { prefix, headingLevel };
1093
1093
  }
1094
1094
  async function parseHwpxDocument(buffer, options) {
1095
- _chunk53XNKPN6cjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE, MAX_ZIP_ENTRIES);
1095
+ _chunkQZCP3UWUcjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE, MAX_ZIP_ENTRIES);
1096
1096
  let zip;
1097
1097
  try {
1098
1098
  zip = await _jszip2.default.loadAsync(buffer);
@@ -1101,7 +1101,7 @@ async function parseHwpxDocument(buffer, options) {
1101
1101
  }
1102
1102
  const actualEntryCount = Object.keys(zip.files).length;
1103
1103
  if (actualEntryCount > MAX_ZIP_ENTRIES) {
1104
- throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP \uC5D4\uD2B8\uB9AC \uC218 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1104
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP \uC5D4\uD2B8\uB9AC \uC218 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1105
1105
  }
1106
1106
  const manifestFile = zip.file("META-INF/manifest.xml");
1107
1107
  if (manifestFile) {
@@ -1113,7 +1113,7 @@ async function parseHwpxDocument(buffer, options) {
1113
1113
  return comResultToParseResult(pages, pageCount, warnings2);
1114
1114
  }
1115
1115
  }
1116
- throw new (0, _chunk53XNKPN6cjs.KordocError)("DRM \uC554\uD638\uD654\uB41C HWPX \uD30C\uC77C\uC785\uB2C8\uB2E4. Windows + \uD55C\uCEF4 \uC624\uD53C\uC2A4 \uC124\uCE58 \uC2DC \uC790\uB3D9 \uCD94\uCD9C\uB429\uB2C8\uB2E4.");
1116
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("DRM \uC554\uD638\uD654\uB41C HWPX \uD30C\uC77C\uC785\uB2C8\uB2E4. Windows + \uD55C\uCEF4 \uC624\uD53C\uC2A4 \uC124\uCE58 \uC2DC \uC790\uB3D9 \uCD94\uCD9C\uB429\uB2C8\uB2E4.");
1117
1117
  }
1118
1118
  }
1119
1119
  const decompressed = { total: 0 };
@@ -1122,7 +1122,7 @@ async function parseHwpxDocument(buffer, options) {
1122
1122
  const styleMap = await extractHwpxStyles(zip, decompressed);
1123
1123
  const warnings = [];
1124
1124
  const sectionPaths = await resolveSectionPaths(zip);
1125
- if (sectionPaths.length === 0) throw new (0, _chunk53XNKPN6cjs.KordocError)("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
1125
+ if (sectionPaths.length === 0) throw new (0, _chunkQZCP3UWUcjs.KordocError)("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
1126
1126
  metadata.pageCount = sectionPaths.length;
1127
1127
  const pageFilter = _optionalChain([options, 'optionalAccess', _12 => _12.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, sectionPaths.length) : null;
1128
1128
  const totalTarget = pageFilter ? pageFilter.size : sectionPaths.length;
@@ -1136,12 +1136,12 @@ async function parseHwpxDocument(buffer, options) {
1136
1136
  try {
1137
1137
  const xml = await file.async("text");
1138
1138
  decompressed.total += xml.length * 2;
1139
- if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1139
+ if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1140
1140
  blocks.push(...parseSectionXml(xml, styleMap, warnings, si + 1, shared));
1141
1141
  parsedSections++;
1142
1142
  _optionalChain([options, 'optionalAccess', _13 => _13.onProgress, 'optionalCall', _14 => _14(parsedSections, totalTarget)]);
1143
1143
  } catch (secErr) {
1144
- if (secErr instanceof _chunk53XNKPN6cjs.KordocError) throw secErr;
1144
+ if (secErr instanceof _chunkQZCP3UWUcjs.KordocError) throw secErr;
1145
1145
  warnings.push({ page: si + 1, message: `\uC139\uC158 ${si + 1} \uD30C\uC2F1 \uC2E4\uD328: ${secErr instanceof Error ? secErr.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`, code: "PARTIAL_PARSE" });
1146
1146
  }
1147
1147
  }
@@ -1149,7 +1149,7 @@ async function parseHwpxDocument(buffer, options) {
1149
1149
  const images = await extractImagesFromZip(zip, blocks, decompressed, warnings);
1150
1150
  detectHwpxHeadings(blocks, styleMap);
1151
1151
  const outline = blocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
1152
- const markdown = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, blocks);
1152
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, blocks);
1153
1153
  return { markdown, blocks, metadata, outline: outline.length > 0 ? outline : void 0, warnings: warnings.length > 0 ? warnings : void 0, images: images.length > 0 ? images : void 0 };
1154
1154
  }
1155
1155
  function applyPageText(blocks, shared) {
@@ -1238,13 +1238,13 @@ async function extractImagesFromZip(zip, blocks, decompressed, warnings) {
1238
1238
  let found = false;
1239
1239
  const allCandidates = resolvedPath ? [resolvedPath, ...candidates] : candidates;
1240
1240
  for (const path of allCandidates) {
1241
- if (_chunk53XNKPN6cjs.isPathTraversal.call(void 0, path)) continue;
1241
+ if (_chunkQZCP3UWUcjs.isPathTraversal.call(void 0, path)) continue;
1242
1242
  const file = zip.file(path);
1243
1243
  if (!file) continue;
1244
1244
  try {
1245
1245
  const data = await file.async("uint8array");
1246
1246
  decompressed.total += data.length;
1247
- if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1247
+ if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1248
1248
  const actualPath = path;
1249
1249
  const ext = actualPath.includes(".") ? actualPath.split(".").pop() || "png" : "png";
1250
1250
  const mimeType = imageExtToMime(ext);
@@ -1257,7 +1257,7 @@ async function extractImagesFromZip(zip, blocks, decompressed, warnings) {
1257
1257
  found = true;
1258
1258
  break;
1259
1259
  } catch (err) {
1260
- if (err instanceof _chunk53XNKPN6cjs.KordocError) throw err;
1260
+ if (err instanceof _chunkQZCP3UWUcjs.KordocError) throw err;
1261
1261
  }
1262
1262
  }
1263
1263
  if (!found) {
@@ -1278,7 +1278,7 @@ async function extractHwpxMetadata(zip, metadata, decompressed) {
1278
1278
  const xml = await file.async("text");
1279
1279
  if (decompressed) {
1280
1280
  decompressed.total += xml.length * 2;
1281
- if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1281
+ if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1282
1282
  }
1283
1283
  parseDublinCoreMetadata(xml, metadata);
1284
1284
  if (metadata.title || metadata.author) return;
@@ -1288,7 +1288,7 @@ async function extractHwpxMetadata(zip, metadata, decompressed) {
1288
1288
  }
1289
1289
  function parseDublinCoreMetadata(xml, metadata) {
1290
1290
  const parser = createXmlParser();
1291
- const doc = parser.parseFromString(_chunk53XNKPN6cjs.stripDtd.call(void 0, xml), "text/xml");
1291
+ const doc = parser.parseFromString(_chunkQZCP3UWUcjs.stripDtd.call(void 0, xml), "text/xml");
1292
1292
  if (!doc.documentElement) return;
1293
1293
  const getText = (tagNames) => {
1294
1294
  for (const tag of tagNames) {
@@ -1348,7 +1348,7 @@ function extractFromBrokenZip(buffer) {
1348
1348
  }
1349
1349
  const nameBytes = data.slice(pos + 30, pos + 30 + nameLen);
1350
1350
  const name = new TextDecoder().decode(nameBytes);
1351
- if (_chunk53XNKPN6cjs.isPathTraversal.call(void 0, name)) {
1351
+ if (_chunkQZCP3UWUcjs.isPathTraversal.call(void 0, name)) {
1352
1352
  pos = fileStart + compSize;
1353
1353
  continue;
1354
1354
  }
@@ -1366,16 +1366,16 @@ function extractFromBrokenZip(buffer) {
1366
1366
  continue;
1367
1367
  }
1368
1368
  totalDecompressed += content.length * 2;
1369
- if (totalDecompressed > MAX_DECOMPRESS_SIZE) throw new (0, _chunk53XNKPN6cjs.KordocError)("\uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC");
1369
+ if (totalDecompressed > MAX_DECOMPRESS_SIZE) throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC");
1370
1370
  sectionNum++;
1371
1371
  blocks.push(...parseSectionXml(content, void 0, warnings, sectionNum, shared));
1372
1372
  } catch (e14) {
1373
1373
  continue;
1374
1374
  }
1375
1375
  }
1376
- if (blocks.length === 0) throw new (0, _chunk53XNKPN6cjs.KordocError)("\uC190\uC0C1\uB41C HWPX\uC5D0\uC11C \uC139\uC158 \uB370\uC774\uD130\uB97C \uBCF5\uAD6C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
1376
+ if (blocks.length === 0) throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uC190\uC0C1\uB41C HWPX\uC5D0\uC11C \uC139\uC158 \uB370\uC774\uD130\uB97C \uBCF5\uAD6C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
1377
1377
  applyPageText(blocks, shared);
1378
- const markdown = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, blocks);
1378
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, blocks);
1379
1379
  return { markdown, blocks, warnings: warnings.length > 0 ? warnings : void 0 };
1380
1380
  }
1381
1381
  async function resolveSectionPaths(zip) {
@@ -1389,18 +1389,18 @@ async function resolveSectionPaths(zip) {
1389
1389
  if (paths.length > 0) return paths;
1390
1390
  }
1391
1391
  const sectionFiles = zip.file(/[Ss]ection\d+\.xml$/);
1392
- return sectionFiles.map((f) => f.name).sort(_chunk53XNKPN6cjs.compareSectionPaths);
1392
+ return sectionFiles.map((f) => f.name).sort(_chunkQZCP3UWUcjs.compareSectionPaths);
1393
1393
  }
1394
1394
  function parseSectionPathsFromManifest(xml) {
1395
1395
  const parser = createXmlParser();
1396
- const doc = parser.parseFromString(_chunk53XNKPN6cjs.stripDtd.call(void 0, xml), "text/xml");
1396
+ const doc = parser.parseFromString(_chunkQZCP3UWUcjs.stripDtd.call(void 0, xml), "text/xml");
1397
1397
  const items = doc.getElementsByTagName("opf:item");
1398
1398
  const spine = doc.getElementsByTagName("opf:itemref");
1399
1399
  const idToHref = /* @__PURE__ */ new Map();
1400
1400
  for (let i = 0; i < items.length; i++) {
1401
1401
  const item = items[i];
1402
1402
  const id = item.getAttribute("id") || "";
1403
- const href = _chunk53XNKPN6cjs.normalizeSectionHref.call(void 0, item.getAttribute("href") || "");
1403
+ const href = _chunkQZCP3UWUcjs.normalizeSectionHref.call(void 0, item.getAttribute("href") || "");
1404
1404
  if (id && href) idToHref.set(id, href);
1405
1405
  }
1406
1406
  if (spine.length > 0) {
@@ -1411,7 +1411,7 @@ function parseSectionPathsFromManifest(xml) {
1411
1411
  }
1412
1412
  if (ordered.length > 0) return ordered;
1413
1413
  }
1414
- return Array.from(idToHref.values()).sort(_chunk53XNKPN6cjs.compareSectionPaths);
1414
+ return Array.from(idToHref.values()).sort(_chunkQZCP3UWUcjs.compareSectionPaths);
1415
1415
  }
1416
1416
  function detectHwpxHeadings(blocks, styleMap) {
1417
1417
  if (blocks.some((b) => b.type === "heading")) return;
@@ -1436,9 +1436,9 @@ function detectHwpxHeadings(blocks, styleMap) {
1436
1436
  let level = 0;
1437
1437
  if (baseFontSize > 0 && _optionalChain([block, 'access', _25 => _25.style, 'optionalAccess', _26 => _26.fontSize])) {
1438
1438
  const ratio = block.style.fontSize / baseFontSize;
1439
- if (ratio >= _chunk53XNKPN6cjs.HEADING_RATIO_H1) level = 1;
1440
- else if (ratio >= _chunk53XNKPN6cjs.HEADING_RATIO_H2) level = 2;
1441
- else if (ratio >= _chunk53XNKPN6cjs.HEADING_RATIO_H3) level = 3;
1439
+ if (ratio >= _chunkQZCP3UWUcjs.HEADING_RATIO_H1) level = 1;
1440
+ else if (ratio >= _chunkQZCP3UWUcjs.HEADING_RATIO_H2) level = 2;
1441
+ else if (ratio >= _chunkQZCP3UWUcjs.HEADING_RATIO_H3) level = 3;
1442
1442
  }
1443
1443
  const compactText = text.replace(/\s+/g, "");
1444
1444
  if (/^제\d+[조장절편]/.test(compactText) && text.length <= 50) {
@@ -1451,17 +1451,40 @@ function detectHwpxHeadings(blocks, styleMap) {
1451
1451
  }
1452
1452
  }
1453
1453
  function buildTableWithCellMeta(state) {
1454
- const table = _chunk53XNKPN6cjs.buildTable.call(void 0, state.rows);
1454
+ const table = _chunkQZCP3UWUcjs.buildTable.call(void 0, state.rows);
1455
1455
  if (state.caption) table.caption = state.caption;
1456
+ const anchors = [];
1457
+ {
1458
+ const covered = /* @__PURE__ */ new Set();
1459
+ for (let r = 0; r < table.rows; r++) {
1460
+ for (let c = 0; c < table.cols; c++) {
1461
+ if (covered.has(`${r},${c}`)) continue;
1462
+ const cell = _optionalChain([table, 'access', _27 => _27.cells, 'access', _28 => _28[r], 'optionalAccess', _29 => _29[c]]);
1463
+ if (!cell) continue;
1464
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
1465
+ for (let dc = 0; dc < cell.colSpan; dc++) {
1466
+ if (dr === 0 && dc === 0) continue;
1467
+ if (r + dr < table.rows && c + dc < table.cols) covered.add(`${r + dr},${c + dc}`);
1468
+ }
1469
+ }
1470
+ anchors.push(cell);
1471
+ c += cell.colSpan - 1;
1472
+ }
1473
+ }
1474
+ }
1475
+ const srcCount = state.rows.reduce((s, r) => s + r.length, 0);
1476
+ const ordinalReliable = anchors.length === srcCount;
1456
1477
  const claimed = /* @__PURE__ */ new Set();
1478
+ let flatIdx = -1;
1457
1479
  for (const row of state.rows) {
1458
1480
  for (const src of row) {
1481
+ flatIdx++;
1459
1482
  const needsBlocks = src.hasStructure && src.blocks && src.blocks.length > 0;
1460
1483
  if (!needsBlocks && !src.isHeader) continue;
1461
1484
  let target;
1462
1485
  const trimmed = src.text.trim();
1463
1486
  if (src.rowAddr !== void 0 && src.colAddr !== void 0) {
1464
- const cand = _optionalChain([table, 'access', _27 => _27.cells, 'access', _28 => _28[src.rowAddr], 'optionalAccess', _29 => _29[src.colAddr]]);
1487
+ const cand = _optionalChain([table, 'access', _30 => _30.cells, 'access', _31 => _31[src.rowAddr], 'optionalAccess', _32 => _32[src.colAddr]]);
1465
1488
  if (cand && cand.text === trimmed && !claimed.has(cand)) target = cand;
1466
1489
  }
1467
1490
  if (!target) {
@@ -1474,6 +1497,10 @@ function buildTableWithCellMeta(state) {
1474
1497
  }
1475
1498
  }
1476
1499
  }
1500
+ if (!target && ordinalReliable) {
1501
+ const cand = anchors[flatIdx];
1502
+ if (cand && !claimed.has(cand)) target = cand;
1503
+ }
1477
1504
  if (!target) continue;
1478
1505
  claimed.add(target);
1479
1506
  if (needsBlocks) target.blocks = src.blocks;
@@ -1490,11 +1517,11 @@ function completeTable(newTable, tableStack, blocks, ctx) {
1490
1517
  }
1491
1518
  const ir = buildTableWithCellMeta(newTable);
1492
1519
  const block = { type: "table", table: ir, pageNumber: ctx.sectionNum };
1493
- if (_optionalChain([parentTable, 'optionalAccess', _30 => _30.cell])) {
1520
+ if (_optionalChain([parentTable, 'optionalAccess', _33 => _33.cell])) {
1494
1521
  const cell = parentTable.cell;
1495
1522
  (cell.blocks ??= []).push(block);
1496
1523
  cell.hasStructure = true;
1497
- let flat = _chunk53XNKPN6cjs.convertTableToText.call(void 0, newTable.rows);
1524
+ let flat = _chunkQZCP3UWUcjs.convertTableToText.call(void 0, newTable.rows);
1498
1525
  if (newTable.caption) flat = newTable.caption + (flat ? "\n" + flat : "");
1499
1526
  if (flat) cell.text += (cell.text ? "\n" : "") + flat;
1500
1527
  } else {
@@ -1504,7 +1531,7 @@ function completeTable(newTable, tableStack, blocks, ctx) {
1504
1531
  }
1505
1532
  function parseSectionXml(xml, styleMap, warnings, sectionNum, shared) {
1506
1533
  const parser = createXmlParser(warnings);
1507
- const doc = parser.parseFromString(_chunk53XNKPN6cjs.stripDtd.call(void 0, xml), "text/xml");
1534
+ const doc = parser.parseFromString(_chunkQZCP3UWUcjs.stripDtd.call(void 0, xml), "text/xml");
1508
1535
  if (!doc.documentElement) return [];
1509
1536
  const ctx = { styleMap, warnings, sectionNum, shared: _nullishCoalesce(shared, () => ( createSectionShared())) };
1510
1537
  ctx.shared.track.deleteDepth = 0;
@@ -1582,7 +1609,7 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1582
1609
  }
1583
1610
  break;
1584
1611
  case "cellAddr":
1585
- if (_optionalChain([tableCtx, 'optionalAccess', _31 => _31.cell])) {
1612
+ if (_optionalChain([tableCtx, 'optionalAccess', _34 => _34.cell])) {
1586
1613
  const ca = parseInt(el.getAttribute("colAddr") || "", 10);
1587
1614
  const ra = parseInt(el.getAttribute("rowAddr") || "", 10);
1588
1615
  if (!isNaN(ca)) tableCtx.cell.colAddr = ca;
@@ -1590,13 +1617,13 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1590
1617
  }
1591
1618
  break;
1592
1619
  case "cellSpan":
1593
- if (_optionalChain([tableCtx, 'optionalAccess', _32 => _32.cell])) {
1620
+ if (_optionalChain([tableCtx, 'optionalAccess', _35 => _35.cell])) {
1594
1621
  const rawCs = parseInt(el.getAttribute("colSpan") || "1", 10);
1595
1622
  const cs = isNaN(rawCs) ? 1 : rawCs;
1596
1623
  const rawRs = parseInt(el.getAttribute("rowSpan") || "1", 10);
1597
1624
  const rs = isNaN(rawRs) ? 1 : rawRs;
1598
- tableCtx.cell.colSpan = clampSpan(cs, _chunk53XNKPN6cjs.MAX_COLS);
1599
- tableCtx.cell.rowSpan = clampSpan(rs, _chunk53XNKPN6cjs.MAX_ROWS);
1625
+ tableCtx.cell.colSpan = clampSpan(cs, _chunkQZCP3UWUcjs.MAX_COLS);
1626
+ tableCtx.cell.rowSpan = clampSpan(rs, _chunkQZCP3UWUcjs.MAX_ROWS);
1600
1627
  }
1601
1628
  break;
1602
1629
  case "p": {
@@ -1605,11 +1632,11 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1605
1632
  let headingLevel;
1606
1633
  if (text) {
1607
1634
  const ph = resolveParaHeading(el, ctx);
1608
- if (_optionalChain([ph, 'optionalAccess', _33 => _33.prefix])) text = ph.prefix + " " + text;
1609
- headingLevel = _optionalChain([ph, 'optionalAccess', _34 => _34.headingLevel]);
1635
+ if (_optionalChain([ph, 'optionalAccess', _36 => _36.prefix])) text = ph.prefix + " " + text;
1636
+ headingLevel = _optionalChain([ph, 'optionalAccess', _37 => _37.headingLevel]);
1610
1637
  }
1611
1638
  if (text) {
1612
- if (_optionalChain([tableCtx, 'optionalAccess', _35 => _35.cell])) {
1639
+ if (_optionalChain([tableCtx, 'optionalAccess', _38 => _38.cell])) {
1613
1640
  const cell = tableCtx.cell;
1614
1641
  if (footnote) text += ` (\uC8FC: ${footnote})`;
1615
1642
  cell.text += (cell.text ? "\n" : "") + text;
@@ -1632,7 +1659,7 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1632
1659
  case "pic":
1633
1660
  case "shape":
1634
1661
  case "drawingObject": {
1635
- if (_optionalChain([tableCtx, 'optionalAccess', _36 => _36.cell])) {
1662
+ if (_optionalChain([tableCtx, 'optionalAccess', _39 => _39.cell])) {
1636
1663
  const sink = [];
1637
1664
  handleShape(el, sink, ctx);
1638
1665
  mergeBlocksIntoCell(tableCtx.cell, sink);
@@ -1741,7 +1768,7 @@ function walkParagraphChildren(node, blocks, tableCtx, tableStack, ctx, depth =
1741
1768
  walkSection(el, blocks, newTable, tableStack, ctx, d + 1);
1742
1769
  tableCtx = completeTable(newTable, tableStack, blocks, ctx);
1743
1770
  } else if (localTag === "pic" || localTag === "shape" || localTag === "drawingObject") {
1744
- if (_optionalChain([tableCtx, 'optionalAccess', _37 => _37.cell])) {
1771
+ if (_optionalChain([tableCtx, 'optionalAccess', _40 => _40.cell])) {
1745
1772
  const sink = [];
1746
1773
  handleShape(el, sink, ctx);
1747
1774
  mergeBlocksIntoCell(tableCtx.cell, sink);
@@ -1749,7 +1776,7 @@ function walkParagraphChildren(node, blocks, tableCtx, tableStack, ctx, depth =
1749
1776
  handleShape(el, blocks, ctx);
1750
1777
  }
1751
1778
  } else if (localTag === "drawText") {
1752
- if (_optionalChain([tableCtx, 'optionalAccess', _38 => _38.cell])) {
1779
+ if (_optionalChain([tableCtx, 'optionalAccess', _41 => _41.cell])) {
1753
1780
  const sink = [];
1754
1781
  extractDrawTextBlocks(el, sink, ctx);
1755
1782
  mergeBlocksIntoCell(tableCtx.cell, sink);
@@ -1793,7 +1820,7 @@ function extractDrawTextBlocks(drawTextNode, blocks, ctx) {
1793
1820
  let text = info.text.trim();
1794
1821
  if (text) {
1795
1822
  const ph = resolveParaHeading(child, ctx);
1796
- if (_optionalChain([ph, 'optionalAccess', _39 => _39.prefix])) text = ph.prefix + " " + text;
1823
+ if (_optionalChain([ph, 'optionalAccess', _42 => _42.prefix])) text = ph.prefix + " " + text;
1797
1824
  const block = { type: "paragraph", text, style: _nullishCoalesce(info.style, () => ( void 0)), pageNumber: ctx.sectionNum };
1798
1825
  if (info.href) block.href = info.href;
1799
1826
  if (info.footnote) block.footnoteText = info.footnote;
@@ -1818,13 +1845,13 @@ function extractHyperlinkHref(fieldBegin) {
1818
1845
  let url = (ch.textContent || "").trim();
1819
1846
  if (!url) continue;
1820
1847
  url = url.replace(/^https?:\/\/(?=https?:\/\/)/i, "");
1821
- const safe = _chunk53XNKPN6cjs.sanitizeHref.call(void 0, url);
1848
+ const safe = _chunkQZCP3UWUcjs.sanitizeHref.call(void 0, url);
1822
1849
  if (safe) return safe;
1823
1850
  }
1824
1851
  return void 0;
1825
1852
  }
1826
1853
  function isInDeletedRange(ctx) {
1827
- return (_nullishCoalesce(_optionalChain([ctx, 'optionalAccess', _40 => _40.shared, 'access', _41 => _41.track, 'access', _42 => _42.deleteDepth]), () => ( 0))) > 0;
1854
+ return (_nullishCoalesce(_optionalChain([ctx, 'optionalAccess', _43 => _43.shared, 'access', _44 => _44.track, 'access', _45 => _45.deleteDepth]), () => ( 0))) > 0;
1828
1855
  }
1829
1856
  function extractParagraphInfo(para, styleMap, ctx) {
1830
1857
  let text = "";
@@ -1878,7 +1905,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
1878
1905
  // 삽입분은 최종본에 포함
1879
1906
  // 숨은 설명 — 본문 혼입 차단
1880
1907
  case "hiddenComment": {
1881
- if (_optionalChain([ctx, 'optionalAccess', _43 => _43.warnings]) && extractTextFromNode(k)) {
1908
+ if (_optionalChain([ctx, 'optionalAccess', _46 => _46.warnings]) && extractTextFromNode(k)) {
1882
1909
  ctx.warnings.push({ page: ctx.sectionNum, message: "\uC228\uC740 \uC124\uBA85 \uD14D\uC2A4\uD2B8 \uC81C\uC678: hiddenComment", code: "HIDDEN_TEXT_FILTERED" });
1883
1910
  }
1884
1911
  break;
@@ -1895,7 +1922,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
1895
1922
  break;
1896
1923
  // 미지원 요소 — 텍스트를 가졌으면 무음 손실 대신 경고
1897
1924
  default: {
1898
- if (_optionalChain([ctx, 'optionalAccess', _44 => _44.warnings]) && extractTextFromNode(k)) {
1925
+ if (_optionalChain([ctx, 'optionalAccess', _47 => _47.warnings]) && extractTextFromNode(k)) {
1899
1926
  ctx.warnings.push({ page: ctx.sectionNum, message: `\uBBF8\uC9C0\uC6D0 \uC81C\uC5B4 \uC694\uC18C\uC758 \uD14D\uC2A4\uD2B8 \uC190\uC2E4: ${ktag}`, code: "UNSUPPORTED_ELEMENT" });
1900
1927
  }
1901
1928
  }
@@ -1912,7 +1939,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
1912
1939
  if (isInDeletedRange(ctx)) {
1913
1940
  if (t && ctx && !ctx.shared.track.warned) {
1914
1941
  ctx.shared.track.warned = true;
1915
- _optionalChain([ctx, 'access', _45 => _45.warnings, 'optionalAccess', _46 => _46.push, 'call', _47 => _47({ page: ctx.sectionNum, message: "\uBCC0\uACBD\uCD94\uC801 \uC0AD\uC81C \uD14D\uC2A4\uD2B8 \uCD9C\uB825 \uC81C\uC678", code: "HIDDEN_TEXT_FILTERED" })]);
1942
+ _optionalChain([ctx, 'access', _48 => _48.warnings, 'optionalAccess', _49 => _49.push, 'call', _50 => _50({ page: ctx.sectionNum, message: "\uBCC0\uACBD\uCD94\uC801 \uC0AD\uC81C \uD14D\uC2A4\uD2B8 \uCD9C\uB825 \uC81C\uC678", code: "HIDDEN_TEXT_FILTERED" })]);
1916
1943
  }
1917
1944
  } else {
1918
1945
  text += t;
@@ -1953,7 +1980,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
1953
1980
  case "hyperlink": {
1954
1981
  const url = child.getAttribute("url") || child.getAttribute("href") || "";
1955
1982
  if (url) {
1956
- const safe = _chunk53XNKPN6cjs.sanitizeHref.call(void 0, url);
1983
+ const safe = _chunkQZCP3UWUcjs.sanitizeHref.call(void 0, url);
1957
1984
  if (safe) href = safe;
1958
1985
  }
1959
1986
  walk(child);
@@ -2143,7 +2170,7 @@ function decompressStream(data) {
2143
2170
  return _zlib.inflateRawSync.call(void 0, data, opts);
2144
2171
  }
2145
2172
  function parseFileHeader(data) {
2146
- if (data.length < 40) throw new (0, _chunk53XNKPN6cjs.KordocError)("FileHeader\uAC00 \uB108\uBB34 \uC9E7\uC2B5\uB2C8\uB2E4 (\uCD5C\uC18C 40\uBC14\uC774\uD2B8)");
2173
+ if (data.length < 40) throw new (0, _chunkQZCP3UWUcjs.KordocError)("FileHeader\uAC00 \uB108\uBB34 \uC9E7\uC2B5\uB2C8\uB2E4 (\uCD5C\uC18C 40\uBC14\uC774\uD2B8)");
2147
2174
  const sig = data.subarray(0, 32).toString("utf8").replace(/\0+$/, "");
2148
2175
  return {
2149
2176
  signature: sig,
@@ -2276,7 +2303,7 @@ function appendParaText(state, data, resolveControl) {
2276
2303
  const resolveAt = (byteOffset, extended) => {
2277
2304
  const ctrlId = data.readUInt32LE(byteOffset);
2278
2305
  const idx = extended ? state.ctrlIdx : -1;
2279
- const replacement = _optionalChain([resolveControl, 'optionalCall', _48 => _48(idx, ctrlId)]);
2306
+ const replacement = _optionalChain([resolveControl, 'optionalCall', _51 => _51(idx, ctrlId)]);
2280
2307
  if (replacement) result += replacement;
2281
2308
  if (extended) state.ctrlIdx++;
2282
2309
  };
@@ -2638,7 +2665,7 @@ function extractHwp5Images(fileIndex, blocks, warnings) {
2638
2665
  const binDataMap = /* @__PURE__ */ new Map();
2639
2666
  if (fileIndex) {
2640
2667
  for (const entry of fileIndex) {
2641
- if (!_optionalChain([entry, 'optionalAccess', _49 => _49.name]) || !entry.content) continue;
2668
+ if (!_optionalChain([entry, 'optionalAccess', _52 => _52.name]) || !entry.content) continue;
2642
2669
  const match = entry.name.match(BIN_ENTRY_RE);
2643
2670
  if (!match) continue;
2644
2671
  const idx = parseInt(match[1], 16);
@@ -3667,22 +3694,22 @@ function parseHwp5Document(buffer, options) {
3667
3694
  lenientCfb = parseLenientCfb(buffer);
3668
3695
  warnings.push({ message: "\uC190\uC0C1\uB41C CFB \uCEE8\uD14C\uC774\uB108 \u2014 lenient \uBAA8\uB4DC\uB85C \uBCF5\uAD6C", code: "LENIENT_CFB_RECOVERY" });
3669
3696
  } catch (e21) {
3670
- throw new (0, _chunk53XNKPN6cjs.KordocError)("CFB \uCEE8\uD14C\uC774\uB108 \uD30C\uC2F1 \uC2E4\uD328 (strict \uBC0F lenient \uBAA8\uB450)");
3697
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("CFB \uCEE8\uD14C\uC774\uB108 \uD30C\uC2F1 \uC2E4\uD328 (strict \uBC0F lenient \uBAA8\uB450)");
3671
3698
  }
3672
3699
  }
3673
3700
  const findStream = (path) => {
3674
3701
  if (cfb) {
3675
3702
  const entry = CFB.find(cfb, path);
3676
- return _optionalChain([entry, 'optionalAccess', _50 => _50.content]) ? Buffer.from(entry.content) : null;
3703
+ return _optionalChain([entry, 'optionalAccess', _53 => _53.content]) ? Buffer.from(entry.content) : null;
3677
3704
  }
3678
3705
  return lenientCfb.findStream(path);
3679
3706
  };
3680
3707
  const headerData = findStream("/FileHeader");
3681
- if (!headerData) throw new (0, _chunk53XNKPN6cjs.KordocError)("FileHeader \uC2A4\uD2B8\uB9BC \uC5C6\uC74C");
3708
+ if (!headerData) throw new (0, _chunkQZCP3UWUcjs.KordocError)("FileHeader \uC2A4\uD2B8\uB9BC \uC5C6\uC74C");
3682
3709
  const header = parseFileHeader(headerData);
3683
- if (header.signature !== "HWP Document File") throw new (0, _chunk53XNKPN6cjs.KordocError)("HWP \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
3684
- if (header.flags & FLAG_ENCRYPTED) throw new (0, _chunk53XNKPN6cjs.KordocError)("\uC554\uD638\uD654\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
3685
- if (header.flags & FLAG_DRM) throw new (0, _chunk53XNKPN6cjs.KordocError)("DRM \uBCF4\uD638\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
3710
+ if (header.signature !== "HWP Document File") throw new (0, _chunkQZCP3UWUcjs.KordocError)("HWP \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
3711
+ if (header.flags & FLAG_ENCRYPTED) throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uC554\uD638\uD654\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
3712
+ if (header.flags & FLAG_DRM) throw new (0, _chunkQZCP3UWUcjs.KordocError)("DRM \uBCF4\uD638\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
3686
3713
  const compressed = (header.flags & FLAG_COMPRESSED) !== 0;
3687
3714
  const distribution = (header.flags & FLAG_DISTRIBUTION) !== 0;
3688
3715
  const metadata = {
@@ -3691,9 +3718,9 @@ function parseHwp5Document(buffer, options) {
3691
3718
  if (cfb) extractHwp5Metadata(cfb, metadata);
3692
3719
  const docInfo = cfb ? parseDocInfoStream(cfb, compressed) : parseDocInfoFromStream(findStream("/DocInfo"), compressed);
3693
3720
  const sections = distribution ? cfb ? findViewTextSections(cfb, compressed) : findViewTextSectionsLenient(lenientCfb, compressed) : cfb ? findSections(cfb) : findSectionsLenient(lenientCfb, compressed);
3694
- if (sections.length === 0) throw new (0, _chunk53XNKPN6cjs.KordocError)("\uC139\uC158 \uC2A4\uD2B8\uB9BC\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
3721
+ if (sections.length === 0) throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uC139\uC158 \uC2A4\uD2B8\uB9BC\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
3695
3722
  metadata.pageCount = sections.length;
3696
- const pageFilter = _optionalChain([options, 'optionalAccess', _51 => _51.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, sections.length) : null;
3723
+ const pageFilter = _optionalChain([options, 'optionalAccess', _54 => _54.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, sections.length) : null;
3697
3724
  const totalTarget = pageFilter ? pageFilter.size : sections.length;
3698
3725
  const bodyBlocks = [];
3699
3726
  const doc = createHwp5DocState();
@@ -3705,31 +3732,31 @@ function parseHwp5Document(buffer, options) {
3705
3732
  const sectionData = sections[si];
3706
3733
  const data = !distribution && compressed ? decompressStream(Buffer.from(sectionData)) : Buffer.from(sectionData);
3707
3734
  totalDecompressed += data.length;
3708
- if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunk53XNKPN6cjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3735
+ if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3709
3736
  const records = readRecords(data);
3710
3737
  const sectionBlocks = parseSection(records, docInfo, warnings, si + 1, doc);
3711
3738
  bodyBlocks.push(...sectionBlocks);
3712
3739
  parsedSections++;
3713
- _optionalChain([options, 'optionalAccess', _52 => _52.onProgress, 'optionalCall', _53 => _53(parsedSections, totalTarget)]);
3740
+ _optionalChain([options, 'optionalAccess', _55 => _55.onProgress, 'optionalCall', _56 => _56(parsedSections, totalTarget)]);
3714
3741
  } catch (secErr) {
3715
- if (secErr instanceof _chunk53XNKPN6cjs.KordocError) throw secErr;
3742
+ if (secErr instanceof _chunkQZCP3UWUcjs.KordocError) throw secErr;
3716
3743
  warnings.push({ page: si + 1, message: `\uC139\uC158 ${si + 1} \uD30C\uC2F1 \uC2E4\uD328: ${secErr instanceof Error ? secErr.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`, code: "PARTIAL_PARSE" });
3717
3744
  }
3718
3745
  }
3719
3746
  const blocks = [...doc.headerBlocks, ...bodyBlocks, ...doc.footerBlocks];
3720
3747
  const images = cfb ? extractHwp5Images(cfb.FileIndex, blocks, warnings) : extractHwp5ImagesLenient(lenientCfb, blocks, warnings);
3721
- const flatBlocks = _chunk53XNKPN6cjs.flattenLayoutTables.call(void 0, blocks);
3748
+ const flatBlocks = _chunkQZCP3UWUcjs.flattenLayoutTables.call(void 0, blocks);
3722
3749
  if (docInfo) {
3723
3750
  detectHwp5Headings(flatBlocks, docInfo);
3724
3751
  }
3725
3752
  const outline = flatBlocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
3726
- const markdown = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, flatBlocks);
3753
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, flatBlocks);
3727
3754
  return { markdown, blocks: flatBlocks, metadata, outline: outline.length > 0 ? outline : void 0, warnings: warnings.length > 0 ? warnings : void 0, images: images.length > 0 ? images : void 0 };
3728
3755
  }
3729
3756
  function parseDocInfoStream(cfb, compressed) {
3730
3757
  try {
3731
3758
  const entry = CFB.find(cfb, "/DocInfo");
3732
- if (!_optionalChain([entry, 'optionalAccess', _54 => _54.content])) return null;
3759
+ if (!_optionalChain([entry, 'optionalAccess', _57 => _57.content])) return null;
3733
3760
  const data = compressed ? decompressStream(Buffer.from(entry.content)) : Buffer.from(entry.content);
3734
3761
  const records = readRecords(data);
3735
3762
  return parseDocInfo(records);
@@ -3750,7 +3777,7 @@ function detectHwp5Headings(blocks, docInfo) {
3750
3777
  let baseFontSize = 0;
3751
3778
  const sizeFreq = /* @__PURE__ */ new Map();
3752
3779
  for (const b of blocks) {
3753
- if (_optionalChain([b, 'access', _55 => _55.style, 'optionalAccess', _56 => _56.fontSize]) && b.text) {
3780
+ if (_optionalChain([b, 'access', _58 => _58.style, 'optionalAccess', _59 => _59.fontSize]) && b.text) {
3754
3781
  sizeFreq.set(b.style.fontSize, (sizeFreq.get(b.style.fontSize) || 0) + b.text.length);
3755
3782
  }
3756
3783
  }
@@ -3766,7 +3793,7 @@ function detectHwp5Headings(blocks, docInfo) {
3766
3793
  const name = (style.nameKo || style.name).toLowerCase();
3767
3794
  if (name.includes("\uBC14\uD0D5") || name.includes("\uBCF8\uBB38") || name === "normal" || name === "body") {
3768
3795
  const cs = docInfo.charShapes[style.charShapeId];
3769
- if (_optionalChain([cs, 'optionalAccess', _57 => _57.fontSize]) > 0) {
3796
+ if (_optionalChain([cs, 'optionalAccess', _60 => _60.fontSize]) > 0) {
3770
3797
  baseFontSize = cs.fontSize / 10;
3771
3798
  break;
3772
3799
  }
@@ -3781,11 +3808,11 @@ function detectHwp5Headings(blocks, docInfo) {
3781
3808
  if (text.length === 0 || text.length > 200) continue;
3782
3809
  if (/^\d+$/.test(text)) continue;
3783
3810
  let level = 0;
3784
- if (_optionalChain([block, 'access', _58 => _58.style, 'optionalAccess', _59 => _59.fontSize]) && baseFontSize > 0) {
3811
+ if (_optionalChain([block, 'access', _61 => _61.style, 'optionalAccess', _62 => _62.fontSize]) && baseFontSize > 0) {
3785
3812
  const ratio = block.style.fontSize / baseFontSize;
3786
- if (ratio >= _chunk53XNKPN6cjs.HEADING_RATIO_H1) level = 1;
3787
- else if (ratio >= _chunk53XNKPN6cjs.HEADING_RATIO_H2) level = 2;
3788
- else if (ratio >= _chunk53XNKPN6cjs.HEADING_RATIO_H3) level = 3;
3813
+ if (ratio >= _chunkQZCP3UWUcjs.HEADING_RATIO_H1) level = 1;
3814
+ else if (ratio >= _chunkQZCP3UWUcjs.HEADING_RATIO_H2) level = 2;
3815
+ else if (ratio >= _chunkQZCP3UWUcjs.HEADING_RATIO_H3) level = 3;
3789
3816
  }
3790
3817
  if (/^제\d+[장절편]\s/.test(text) && text.length <= 50) {
3791
3818
  if (level === 0) level = 2;
@@ -3801,7 +3828,7 @@ function detectHwp5Headings(blocks, docInfo) {
3801
3828
  function extractHwp5Metadata(cfb, metadata) {
3802
3829
  try {
3803
3830
  const summaryEntry = CFB.find(cfb, "/HwpSummaryInformation") || CFB.find(cfb, "/SummaryInformation");
3804
- if (!_optionalChain([summaryEntry, 'optionalAccess', _60 => _60.content])) return;
3831
+ if (!_optionalChain([summaryEntry, 'optionalAccess', _63 => _63.content])) return;
3805
3832
  const data = Buffer.from(summaryEntry.content);
3806
3833
  if (data.length < 48) return;
3807
3834
  const numSets = data.readUInt32LE(24);
@@ -3834,7 +3861,7 @@ function findViewTextSections(cfb, compressed) {
3834
3861
  const sections = [];
3835
3862
  for (let i = 0; i < MAX_SECTIONS; i++) {
3836
3863
  const entry = CFB.find(cfb, `/ViewText/Section${i}`);
3837
- if (!_optionalChain([entry, 'optionalAccess', _61 => _61.content])) break;
3864
+ if (!_optionalChain([entry, 'optionalAccess', _64 => _64.content])) break;
3838
3865
  try {
3839
3866
  const decrypted = decryptViewText(Buffer.from(entry.content), compressed);
3840
3867
  sections.push({ idx: i, content: decrypted });
@@ -3848,13 +3875,13 @@ function findSections(cfb) {
3848
3875
  const sections = [];
3849
3876
  for (let i = 0; i < MAX_SECTIONS; i++) {
3850
3877
  const entry = CFB.find(cfb, `/BodyText/Section${i}`);
3851
- if (!_optionalChain([entry, 'optionalAccess', _62 => _62.content])) break;
3878
+ if (!_optionalChain([entry, 'optionalAccess', _65 => _65.content])) break;
3852
3879
  sections.push({ idx: i, content: Buffer.from(entry.content) });
3853
3880
  }
3854
3881
  if (sections.length === 0 && cfb.FileIndex) {
3855
3882
  for (const entry of cfb.FileIndex) {
3856
3883
  if (sections.length >= MAX_SECTIONS) break;
3857
- if (_optionalChain([entry, 'access', _63 => _63.name, 'optionalAccess', _64 => _64.startsWith, 'call', _65 => _65("Section")]) && entry.content) {
3884
+ if (_optionalChain([entry, 'access', _66 => _66.name, 'optionalAccess', _67 => _67.startsWith, 'call', _68 => _68("Section")]) && entry.content) {
3858
3885
  const idx = parseInt(entry.name.replace("Section", ""), 10) || 0;
3859
3886
  sections.push({ idx, content: Buffer.from(entry.content) });
3860
3887
  }
@@ -3870,7 +3897,7 @@ function findSectionsLenient(lcfb, compressed) {
3870
3897
  if (!raw) break;
3871
3898
  const content = compressed ? decompressStream(raw) : raw;
3872
3899
  totalDecompressed += content.length;
3873
- if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunk53XNKPN6cjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3900
+ if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3874
3901
  sections.push({ idx: i, content });
3875
3902
  }
3876
3903
  if (sections.length === 0) {
@@ -3882,7 +3909,7 @@ function findSectionsLenient(lcfb, compressed) {
3882
3909
  if (raw) {
3883
3910
  const content = compressed ? decompressStream(raw) : raw;
3884
3911
  totalDecompressed += content.length;
3885
- if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunk53XNKPN6cjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3912
+ if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3886
3913
  sections.push({ idx, content });
3887
3914
  }
3888
3915
  }
@@ -3899,7 +3926,7 @@ function findViewTextSectionsLenient(lcfb, compressed) {
3899
3926
  try {
3900
3927
  const content = decryptViewText(raw, compressed);
3901
3928
  totalDecompressed += content.length;
3902
- if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunk53XNKPN6cjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3929
+ if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3903
3930
  sections.push({ idx: i, content });
3904
3931
  } catch (e26) {
3905
3932
  break;
@@ -4000,9 +4027,9 @@ function parseParagraph(records, start, end, ctx) {
4000
4027
  const applied = [];
4001
4028
  for (const r of ranges) {
4002
4029
  const ctrl = ctrls[r.ctrlIdx];
4003
- if (!_optionalChain([ctrl, 'optionalAccess', _66 => _66.href]) || r.end <= r.start) continue;
4030
+ if (!_optionalChain([ctrl, 'optionalAccess', _69 => _69.href]) || r.end <= r.start) continue;
4004
4031
  if (applied.some(([s, e]) => r.start < e && r.end > s)) continue;
4005
- const href = _chunk53XNKPN6cjs.sanitizeHref.call(void 0, ctrl.href);
4032
+ const href = _chunkQZCP3UWUcjs.sanitizeHref.call(void 0, ctrl.href);
4006
4033
  if (!href) continue;
4007
4034
  const anchor = text.slice(r.start, r.end);
4008
4035
  if (!anchor.trim()) continue;
@@ -4020,7 +4047,7 @@ function parseParagraph(records, start, end, ctx) {
4020
4047
  }
4021
4048
  if (ps.headType === 1 || ps.headType === 2) {
4022
4049
  const nid = ps.numberingId || (ps.headType === 1 ? ctx.doc.outlineNumberingId : 0);
4023
- const numbering = nid >= 1 ? _optionalChain([ctx, 'access', _67 => _67.docInfo, 'optionalAccess', _68 => _68.numberings, 'access', _69 => _69[nid - 1]]) : void 0;
4050
+ const numbering = nid >= 1 ? _optionalChain([ctx, 'access', _70 => _70.docInfo, 'optionalAccess', _71 => _71.numberings, 'access', _72 => _72[nid - 1]]) : void 0;
4024
4051
  if (numbering) {
4025
4052
  const counters = ctx.doc.numbering.advance(nid, ps.paraLevel);
4026
4053
  const fmt = numbering.levelFormats[Math.min(ps.paraLevel, 6)];
@@ -4030,7 +4057,7 @@ function parseParagraph(records, start, end, ctx) {
4030
4057
  }
4031
4058
  }
4032
4059
  } else if (ps.headType === 3) {
4033
- const bullet = ps.numberingId >= 1 ? _optionalChain([ctx, 'access', _70 => _70.docInfo, 'optionalAccess', _71 => _71.bullets, 'access', _72 => _72[ps.numberingId - 1]]) : void 0;
4060
+ const bullet = ps.numberingId >= 1 ? _optionalChain([ctx, 'access', _73 => _73.docInfo, 'optionalAccess', _74 => _74.bullets, 'access', _75 => _75[ps.numberingId - 1]]) : void 0;
4034
4061
  if (bullet && bullet.char !== "\uFFFF") headMarker = bullet.char;
4035
4062
  }
4036
4063
  }
@@ -4235,8 +4262,8 @@ function parseTableControl(ctrl, records, ctx) {
4235
4262
  let tableIdx = -1;
4236
4263
  for (let i2 = childStart; i2 < childEnd; i2++) {
4237
4264
  if (records[i2].tagId === TAG_TABLE && records[i2].data.length >= 8) {
4238
- rows = Math.min(records[i2].data.readUInt16LE(4), _chunk53XNKPN6cjs.MAX_ROWS);
4239
- cols = Math.min(records[i2].data.readUInt16LE(6), _chunk53XNKPN6cjs.MAX_COLS);
4265
+ rows = Math.min(records[i2].data.readUInt16LE(4), _chunkQZCP3UWUcjs.MAX_ROWS);
4266
+ cols = Math.min(records[i2].data.readUInt16LE(6), _chunkQZCP3UWUcjs.MAX_COLS);
4240
4267
  tableIdx = i2;
4241
4268
  break;
4242
4269
  }
@@ -4276,7 +4303,7 @@ function parseTableControl(ctrl, records, ctx) {
4276
4303
  const cellRows2 = arrangeCells(rows, cols, cells);
4277
4304
  const irCells = cellRows2.map((row) => row.map((c) => {
4278
4305
  const ir = { text: c.text.trim(), colSpan: c.colSpan, rowSpan: c.rowSpan };
4279
- if (_optionalChain([c, 'access', _73 => _73.blocks, 'optionalAccess', _74 => _74.length])) ir.blocks = c.blocks;
4306
+ if (_optionalChain([c, 'access', _76 => _76.blocks, 'optionalAccess', _77 => _77.length])) ir.blocks = c.blocks;
4280
4307
  if (c.isHeader) ir.isHeader = true;
4281
4308
  return ir;
4282
4309
  }));
@@ -4285,7 +4312,7 @@ function parseTableControl(ctrl, records, ctx) {
4285
4312
  return table2;
4286
4313
  }
4287
4314
  const cellRows = arrangeCells(rows, cols, cells);
4288
- const table = _chunk53XNKPN6cjs.buildTable.call(void 0, cellRows);
4315
+ const table = _chunkQZCP3UWUcjs.buildTable.call(void 0, cellRows);
4289
4316
  if (caption && table.rows > 0) table.caption = caption;
4290
4317
  return table.rows > 0 ? table : null;
4291
4318
  }
@@ -4302,8 +4329,8 @@ function parseCell(records, lhIdx, end, ctx) {
4302
4329
  rowAddr = rec.data.readUInt16LE(10);
4303
4330
  const cs = rec.data.readUInt16LE(12);
4304
4331
  const rs = rec.data.readUInt16LE(14);
4305
- if (cs > 0) colSpan = Math.min(cs, _chunk53XNKPN6cjs.MAX_COLS);
4306
- if (rs > 0) rowSpan = Math.min(rs, _chunk53XNKPN6cjs.MAX_ROWS);
4332
+ if (cs > 0) colSpan = Math.min(cs, _chunkQZCP3UWUcjs.MAX_COLS);
4333
+ if (rs > 0) rowSpan = Math.min(rs, _chunkQZCP3UWUcjs.MAX_ROWS);
4307
4334
  }
4308
4335
  const blocks = ctx.depth < MAX_NEST_DEPTH ? parseParagraphList(records, lhIdx + 1, end, { ...ctx, depth: ctx.depth + 1 }) : [];
4309
4336
  const parts = [];
@@ -4313,7 +4340,7 @@ function parseCell(records, lhIdx, end, ctx) {
4313
4340
  parts.push(`![image](hwp5bin:${b.text})`);
4314
4341
  hasStructure = true;
4315
4342
  } else if (b.type === "table" && b.table) {
4316
- const flat = _chunk53XNKPN6cjs.convertTableToText.call(void 0, b.table.cells);
4343
+ const flat = _chunkQZCP3UWUcjs.convertTableToText.call(void 0, b.table.cells);
4317
4344
  if (flat) parts.push(flat);
4318
4345
  hasStructure = true;
4319
4346
  } else if (b.text) {
@@ -4410,8 +4437,8 @@ function pictureToImageBlock(data, ctx) {
4410
4437
  if (data.length < 73) return null;
4411
4438
  const binDataId = data.readUInt16LE(71);
4412
4439
  if (binDataId === 0) return null;
4413
- const item = _optionalChain([ctx, 'access', _75 => _75.docInfo, 'optionalAccess', _76 => _76.binData, 'access', _77 => _77[binDataId - 1]]);
4414
- if (_optionalChain([item, 'optionalAccess', _78 => _78.kind]) === "link") {
4440
+ const item = _optionalChain([ctx, 'access', _78 => _78.docInfo, 'optionalAccess', _79 => _79.binData, 'access', _80 => _80[binDataId - 1]]);
4441
+ if (_optionalChain([item, 'optionalAccess', _81 => _81.kind]) === "link") {
4415
4442
  ctx.warnings.push({ page: ctx.sectionNum, message: `\uC678\uBD80 \uC5F0\uACB0 \uC774\uBBF8\uC9C0 (binDataId ${binDataId})`, code: "SKIPPED_IMAGE" });
4416
4443
  return null;
4417
4444
  }
@@ -16744,10 +16771,10 @@ function getElements(parent, tagName) {
16744
16771
  return result;
16745
16772
  }
16746
16773
  function getTextContent(el) {
16747
- return _nullishCoalesce(_optionalChain([el, 'access', _79 => _79.textContent, 'optionalAccess', _80 => _80.trim, 'call', _81 => _81()]), () => ( ""));
16774
+ return _nullishCoalesce(_optionalChain([el, 'access', _82 => _82.textContent, 'optionalAccess', _83 => _83.trim, 'call', _84 => _84()]), () => ( ""));
16748
16775
  }
16749
16776
  function parseXml(text) {
16750
- return new (0, _xmldom.DOMParser)().parseFromString(_chunk53XNKPN6cjs.stripDtd.call(void 0, text), "text/xml");
16777
+ return new (0, _xmldom.DOMParser)().parseFromString(_chunkQZCP3UWUcjs.stripDtd.call(void 0, text), "text/xml");
16751
16778
  }
16752
16779
  function parseSharedStrings(xml) {
16753
16780
  const doc = parseXml(xml);
@@ -16884,14 +16911,14 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
16884
16911
  const merge = mergeMap.get(key);
16885
16912
  row.push({
16886
16913
  text,
16887
- colSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _82 => _82.colSpan]), () => ( 1)),
16888
- rowSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _83 => _83.rowSpan]), () => ( 1))
16914
+ colSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _85 => _85.colSpan]), () => ( 1)),
16915
+ rowSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _86 => _86.rowSpan]), () => ( 1))
16889
16916
  });
16890
16917
  }
16891
16918
  cellRows.push(row);
16892
16919
  }
16893
16920
  if (cellRows.length > 0) {
16894
- const table = _chunk53XNKPN6cjs.buildTable.call(void 0, cellRows);
16921
+ const table = _chunkQZCP3UWUcjs.buildTable.call(void 0, cellRows);
16895
16922
  if (table.rows > 0) {
16896
16923
  blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
16897
16924
  }
@@ -16899,12 +16926,12 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
16899
16926
  return blocks;
16900
16927
  }
16901
16928
  async function parseXlsxDocument(buffer, options) {
16902
- _chunk53XNKPN6cjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE3);
16929
+ _chunkQZCP3UWUcjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE3);
16903
16930
  const zip = await _jszip2.default.loadAsync(buffer);
16904
16931
  const warnings = [];
16905
16932
  const workbookFile = zip.file("xl/workbook.xml");
16906
16933
  if (!workbookFile) {
16907
- throw new (0, _chunk53XNKPN6cjs.KordocError)("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 XLSX \uD30C\uC77C: xl/workbook.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
16934
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 XLSX \uD30C\uC77C: xl/workbook.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
16908
16935
  }
16909
16936
  let sharedStrings = [];
16910
16937
  const ssFile = zip.file("xl/sharedStrings.xml");
@@ -16913,7 +16940,7 @@ async function parseXlsxDocument(buffer, options) {
16913
16940
  }
16914
16941
  const sheets = parseWorkbook(await workbookFile.async("text"));
16915
16942
  if (sheets.length === 0) {
16916
- throw new (0, _chunk53XNKPN6cjs.KordocError)("XLSX \uD30C\uC77C\uC5D0 \uC2DC\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4");
16943
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("XLSX \uD30C\uC77C\uC5D0 \uC2DC\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4");
16917
16944
  }
16918
16945
  let relsMap = /* @__PURE__ */ new Map();
16919
16946
  const relsFile = zip.file("xl/_rels/workbook.xml.rels");
@@ -16921,7 +16948,7 @@ async function parseXlsxDocument(buffer, options) {
16921
16948
  relsMap = parseRels(await relsFile.async("text"));
16922
16949
  }
16923
16950
  let pageFilter = null;
16924
- if (_optionalChain([options, 'optionalAccess', _84 => _84.pages])) {
16951
+ if (_optionalChain([options, 'optionalAccess', _87 => _87.pages])) {
16925
16952
  const { parsePageRange: parsePageRange2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("./page-range-P7SDW6LR.cjs")));
16926
16953
  pageFilter = parsePageRange2(options.pages, sheets.length);
16927
16954
  }
@@ -16930,7 +16957,7 @@ async function parseXlsxDocument(buffer, options) {
16930
16957
  for (let i = 0; i < processedSheets; i++) {
16931
16958
  if (pageFilter && !pageFilter.has(i + 1)) continue;
16932
16959
  const sheet = sheets[i];
16933
- _optionalChain([options, 'optionalAccess', _85 => _85.onProgress, 'optionalCall', _86 => _86(i + 1, processedSheets)]);
16960
+ _optionalChain([options, 'optionalAccess', _88 => _88.onProgress, 'optionalCall', _89 => _89(i + 1, processedSheets)]);
16934
16961
  let sheetPath = relsMap.get(sheet.rId);
16935
16962
  if (sheetPath) {
16936
16963
  if (!sheetPath.startsWith("xl/") && !sheetPath.startsWith("/")) {
@@ -16985,7 +17012,7 @@ async function parseXlsxDocument(buffer, options) {
16985
17012
  } catch (e27) {
16986
17013
  }
16987
17014
  }
16988
- const markdown = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, blocks);
17015
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, blocks);
16989
17016
  return { markdown, blocks, metadata, warnings: warnings.length > 0 ? warnings : void 0 };
16990
17017
  }
16991
17018
 
@@ -17392,11 +17419,11 @@ function processGlobals(records) {
17392
17419
  let encrypted = false;
17393
17420
  const firstBof = records[0];
17394
17421
  if (!firstBof || firstBof.opcode !== OP_BOF) {
17395
- throw new (0, _chunk53XNKPN6cjs.KordocError)("XLS: \uCCAB \uB808\uCF54\uB4DC\uAC00 BOF\uAC00 \uC544\uB2D8");
17422
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("XLS: \uCCAB \uB808\uCF54\uB4DC\uAC00 BOF\uAC00 \uC544\uB2D8");
17396
17423
  }
17397
17424
  const bof = decodeBof(firstBof.data);
17398
17425
  if (!bof || bof.dt !== DT_GLOBALS) {
17399
- throw new (0, _chunk53XNKPN6cjs.KordocError)("XLS: Globals \uC11C\uBE0C\uC2A4\uD2B8\uB9BC BOF \uB204\uB77D");
17426
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("XLS: Globals \uC11C\uBE0C\uC2A4\uD2B8\uB9BC BOF \uB204\uB77D");
17400
17427
  }
17401
17428
  let i = 1;
17402
17429
  while (i < records.length) {
@@ -17504,14 +17531,14 @@ function sheetToBlocks2(sheetName, sheet, sheetIndex) {
17504
17531
  const merge = mergeMap.get(key);
17505
17532
  row.push({
17506
17533
  text: grid[r][c],
17507
- colSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _87 => _87.colSpan]), () => ( 1)),
17508
- rowSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _88 => _88.rowSpan]), () => ( 1))
17534
+ colSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _90 => _90.colSpan]), () => ( 1)),
17535
+ rowSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _91 => _91.rowSpan]), () => ( 1))
17509
17536
  });
17510
17537
  }
17511
17538
  cellRows.push(row);
17512
17539
  }
17513
17540
  if (cellRows.length > 0) {
17514
- const table = _chunk53XNKPN6cjs.buildTable.call(void 0, cellRows);
17541
+ const table = _chunkQZCP3UWUcjs.buildTable.call(void 0, cellRows);
17515
17542
  if (table.rows > 0) {
17516
17543
  blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
17517
17544
  }
@@ -17524,21 +17551,21 @@ async function parseXlsDocument(buffer, options) {
17524
17551
  try {
17525
17552
  cfb = parseLenientCfb(buf);
17526
17553
  } catch (e) {
17527
- throw new (0, _chunk53XNKPN6cjs.KordocError)(
17554
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)(
17528
17555
  `XLS: OLE2 \uC2DC\uADF8\uB2C8\uCC98 \uAC80\uC99D \uC2E4\uD328 \u2014 ${e instanceof Error ? e.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`
17529
17556
  );
17530
17557
  }
17531
17558
  const wb = _nullishCoalesce(cfb.findStream("/Workbook"), () => ( cfb.findStream("/Book")));
17532
17559
  if (!wb) {
17533
- throw new (0, _chunk53XNKPN6cjs.KordocError)("XLS: Workbook \uC2A4\uD2B8\uB9BC\uC774 \uC5C6\uC74C (BIFF5 \uB610\uB294 \uBE44\uD45C\uC900 \uD30C\uC77C)");
17560
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("XLS: Workbook \uC2A4\uD2B8\uB9BC\uC774 \uC5C6\uC74C (BIFF5 \uB610\uB294 \uBE44\uD45C\uC900 \uD30C\uC77C)");
17534
17561
  }
17535
17562
  const records = readRecords2(wb);
17536
17563
  if (records.length === 0) {
17537
- throw new (0, _chunk53XNKPN6cjs.KordocError)("XLS: \uC2DC\uADF8\uB2C8\uCC98 \uB808\uCF54\uB4DC\uAC00 \uC5C6\uC74C (Workbook \uC2A4\uD2B8\uB9BC \uC190\uC0C1)");
17564
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("XLS: \uC2DC\uADF8\uB2C8\uCC98 \uB808\uCF54\uB4DC\uAC00 \uC5C6\uC74C (Workbook \uC2A4\uD2B8\uB9BC \uC190\uC0C1)");
17538
17565
  }
17539
17566
  const firstBof = decodeBof(records[0].data);
17540
17567
  if (firstBof && firstBof.vers !== 1536) {
17541
- throw new (0, _chunk53XNKPN6cjs.KordocError)(
17568
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)(
17542
17569
  `XLS: BIFF8(0x0600)\uB9CC \uC9C0\uC6D0 \u2014 \uBCF8 \uD30C\uC77C\uC740 0x${firstBof.vers.toString(16)}`
17543
17570
  );
17544
17571
  }
@@ -17559,7 +17586,7 @@ async function parseXlsDocument(buffer, options) {
17559
17586
  }
17560
17587
  const totalSheets = Math.min(globals.sheets.length, MAX_SHEETS2);
17561
17588
  let pageFilter = null;
17562
- if (_optionalChain([options, 'optionalAccess', _89 => _89.pages])) {
17589
+ if (_optionalChain([options, 'optionalAccess', _92 => _92.pages])) {
17563
17590
  const { parsePageRange: parsePageRange2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("./page-range-P7SDW6LR.cjs")));
17564
17591
  pageFilter = parsePageRange2(options.pages, totalSheets);
17565
17592
  }
@@ -17568,7 +17595,7 @@ async function parseXlsDocument(buffer, options) {
17568
17595
  if (pageFilter && !pageFilter.has(i + 1)) continue;
17569
17596
  const meta = globals.sheets[i];
17570
17597
  if (meta.dt !== 0) continue;
17571
- _optionalChain([options, 'optionalAccess', _90 => _90.onProgress, 'optionalCall', _91 => _91(i + 1, totalSheets)]);
17598
+ _optionalChain([options, 'optionalAccess', _93 => _93.onProgress, 'optionalCall', _94 => _94(i + 1, totalSheets)]);
17572
17599
  const bofIdx = findSheetBofIndex(records, meta.lbPlyPos);
17573
17600
  if (bofIdx < 0) {
17574
17601
  warnings.push({
@@ -17598,7 +17625,7 @@ async function parseXlsDocument(buffer, options) {
17598
17625
  pageCount: totalSheets
17599
17626
  };
17600
17627
  return {
17601
- markdown: _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, allBlocks),
17628
+ markdown: _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, allBlocks),
17602
17629
  blocks: allBlocks,
17603
17630
  metadata,
17604
17631
  warnings: warnings.length > 0 ? warnings : void 0
@@ -17611,7 +17638,7 @@ async function parseXlsDocument(buffer, options) {
17611
17638
 
17612
17639
  // src/docx/equation.ts
17613
17640
  function lname(el) {
17614
- return el.localName || _optionalChain([el, 'access', _92 => _92.tagName, 'optionalAccess', _93 => _93.replace, 'call', _94 => _94(/^[^:]+:/, "")]) || "";
17641
+ return el.localName || _optionalChain([el, 'access', _95 => _95.tagName, 'optionalAccess', _96 => _96.replace, 'call', _97 => _97(/^[^:]+:/, "")]) || "";
17615
17642
  }
17616
17643
  function kids(parent, name) {
17617
17644
  const out = [];
@@ -17984,7 +18011,7 @@ function isDisplayMath(el) {
17984
18011
  // src/docx/parser.ts
17985
18012
  var MAX_DECOMPRESS_SIZE4 = 100 * 1024 * 1024;
17986
18013
  function matchesLocal(el, localName2) {
17987
- return el.localName === localName2 || (_nullishCoalesce(_optionalChain([el, 'access', _95 => _95.tagName, 'optionalAccess', _96 => _96.endsWith, 'call', _97 => _97(`:${localName2}`)]), () => ( false)));
18014
+ return el.localName === localName2 || (_nullishCoalesce(_optionalChain([el, 'access', _98 => _98.tagName, 'optionalAccess', _99 => _99.endsWith, 'call', _100 => _100(`:${localName2}`)]), () => ( false)));
17988
18015
  }
17989
18016
  function effectiveChildElements(parent) {
17990
18017
  const result = [];
@@ -18017,7 +18044,7 @@ function findElements(parent, localName2) {
18017
18044
  const child = children[i];
18018
18045
  if (child.nodeType === 1) {
18019
18046
  const el = child;
18020
- if (el.localName === localName2 || _optionalChain([el, 'access', _98 => _98.tagName, 'optionalAccess', _99 => _99.endsWith, 'call', _100 => _100(`:${localName2}`)])) {
18047
+ if (el.localName === localName2 || _optionalChain([el, 'access', _101 => _101.tagName, 'optionalAccess', _102 => _102.endsWith, 'call', _103 => _103(`:${localName2}`)])) {
18021
18048
  result.push(el);
18022
18049
  }
18023
18050
  walk(el);
@@ -18036,7 +18063,7 @@ function getAttr(el, localName2) {
18036
18063
  return null;
18037
18064
  }
18038
18065
  function parseXml2(text) {
18039
- return new (0, _xmldom.DOMParser)().parseFromString(_chunk53XNKPN6cjs.stripDtd.call(void 0, text), "text/xml");
18066
+ return new (0, _xmldom.DOMParser)().parseFromString(_chunkQZCP3UWUcjs.stripDtd.call(void 0, text), "text/xml");
18040
18067
  }
18041
18068
  function parseStyles(xml) {
18042
18069
  const doc = parseXml2(xml);
@@ -18138,7 +18165,7 @@ function collectOmmlRoots(p) {
18138
18165
  const child = children[i];
18139
18166
  if (child.nodeType !== 1) continue;
18140
18167
  const el = child;
18141
- const tag = el.localName || _optionalChain([el, 'access', _101 => _101.tagName, 'optionalAccess', _102 => _102.replace, 'call', _103 => _103(/^[^:]+:/, "")]) || "";
18168
+ const tag = el.localName || _optionalChain([el, 'access', _104 => _104.tagName, 'optionalAccess', _105 => _105.replace, 'call', _106 => _106(/^[^:]+:/, "")]) || "";
18142
18169
  if (tag === "oMath" || tag === "oMathPara") {
18143
18170
  out.push(el);
18144
18171
  } else {
@@ -18227,7 +18254,7 @@ function parseParagraph2(p, styles, numbering, footnotes, rels) {
18227
18254
  const text = parts.join("").replace(/[ \t]{2,}/g, " ").trim();
18228
18255
  if (!text) return null;
18229
18256
  const style = styles.get(styleId);
18230
- if (_optionalChain([style, 'optionalAccess', _104 => _104.outlineLevel]) !== void 0 && style.outlineLevel >= 0 && style.outlineLevel <= 5) {
18257
+ if (_optionalChain([style, 'optionalAccess', _107 => _107.outlineLevel]) !== void 0 && style.outlineLevel >= 0 && style.outlineLevel <= 5) {
18231
18258
  return {
18232
18259
  type: "heading",
18233
18260
  text,
@@ -18236,8 +18263,8 @@ function parseParagraph2(p, styles, numbering, footnotes, rels) {
18236
18263
  }
18237
18264
  if (numId && numId !== "0") {
18238
18265
  const numDef = numbering.get(numId);
18239
- const levelInfo = _optionalChain([numDef, 'optionalAccess', _105 => _105.get, 'call', _106 => _106(ilvl)]);
18240
- const listType = _optionalChain([levelInfo, 'optionalAccess', _107 => _107.numFmt]) === "bullet" ? "unordered" : "ordered";
18266
+ const levelInfo = _optionalChain([numDef, 'optionalAccess', _108 => _108.get, 'call', _109 => _109(ilvl)]);
18267
+ const listType = _optionalChain([levelInfo, 'optionalAccess', _110 => _110.numFmt]) === "bullet" ? "unordered" : "ordered";
18241
18268
  return { type: "list", text, listType };
18242
18269
  }
18243
18270
  const block = { type: "paragraph", text };
@@ -18278,7 +18305,7 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
18278
18305
  const pElements = getChildElements(tc, "p");
18279
18306
  for (const p of pElements) {
18280
18307
  const block = parseParagraph2(p, styles, numbering, footnotes, rels);
18281
- if (_optionalChain([block, 'optionalAccess', _108 => _108.text])) cellTexts.push(block.text);
18308
+ if (_optionalChain([block, 'optionalAccess', _111 => _111.text])) cellTexts.push(block.text);
18282
18309
  }
18283
18310
  row.push({ text: cellTexts.join("\n"), colSpan, rowSpan });
18284
18311
  }
@@ -18291,7 +18318,7 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
18291
18318
  if (!cell || cell.rowSpan === 0) continue;
18292
18319
  let span = 1;
18293
18320
  for (let nr = r + 1; nr < rows.length; nr++) {
18294
- if (_optionalChain([rows, 'access', _109 => _109[nr], 'access', _110 => _110[c], 'optionalAccess', _111 => _111.rowSpan]) === 0) span++;
18321
+ if (_optionalChain([rows, 'access', _112 => _112[nr], 'access', _113 => _113[c], 'optionalAccess', _114 => _114.rowSpan]) === 0) span++;
18295
18322
  else break;
18296
18323
  }
18297
18324
  cell.rowSpan = span;
@@ -18335,7 +18362,7 @@ async function extractImages(zip, rels, doc) {
18335
18362
  try {
18336
18363
  const data = await imgFile.async("uint8array");
18337
18364
  imgIdx++;
18338
- const ext = _nullishCoalesce(_optionalChain([imgPath, 'access', _112 => _112.split, 'call', _113 => _113("."), 'access', _114 => _114.pop, 'call', _115 => _115(), 'optionalAccess', _116 => _116.toLowerCase, 'call', _117 => _117()]), () => ( "png"));
18365
+ const ext = _nullishCoalesce(_optionalChain([imgPath, 'access', _115 => _115.split, 'call', _116 => _116("."), 'access', _117 => _117.pop, 'call', _118 => _118(), 'optionalAccess', _119 => _119.toLowerCase, 'call', _120 => _120()]), () => ( "png"));
18339
18366
  const mimeMap = {
18340
18367
  png: "image/png",
18341
18368
  jpg: "image/jpeg",
@@ -18355,12 +18382,12 @@ async function extractImages(zip, rels, doc) {
18355
18382
  return { blocks, images };
18356
18383
  }
18357
18384
  async function parseDocxDocument(buffer, options) {
18358
- _chunk53XNKPN6cjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE4);
18385
+ _chunkQZCP3UWUcjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE4);
18359
18386
  const zip = await _jszip2.default.loadAsync(buffer);
18360
18387
  const warnings = [];
18361
18388
  const docFile = zip.file("word/document.xml");
18362
18389
  if (!docFile) {
18363
- throw new (0, _chunk53XNKPN6cjs.KordocError)("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 DOCX \uD30C\uC77C: word/document.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
18390
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 DOCX \uD30C\uC77C: word/document.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
18364
18391
  }
18365
18392
  let rels = /* @__PURE__ */ new Map();
18366
18393
  const relsFile = zip.file("word/_rels/document.xml.rels");
@@ -18395,13 +18422,13 @@ async function parseDocxDocument(buffer, options) {
18395
18422
  const doc = parseXml2(docXml);
18396
18423
  const body = findElements(doc, "body");
18397
18424
  if (body.length === 0) {
18398
- throw new (0, _chunk53XNKPN6cjs.KordocError)("DOCX \uBCF8\uBB38(w:body)\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
18425
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("DOCX \uBCF8\uBB38(w:body)\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
18399
18426
  }
18400
18427
  const blocks = [];
18401
18428
  const bodyEl = body[0];
18402
18429
  const topLevel = effectiveChildElements(bodyEl);
18403
18430
  for (const el of topLevel) {
18404
- const localName2 = _nullishCoalesce(el.localName, () => ( _optionalChain([el, 'access', _118 => _118.tagName, 'optionalAccess', _119 => _119.split, 'call', _120 => _120(":"), 'access', _121 => _121.pop, 'call', _122 => _122()])));
18431
+ const localName2 = _nullishCoalesce(el.localName, () => ( _optionalChain([el, 'access', _121 => _121.tagName, 'optionalAccess', _122 => _122.split, 'call', _123 => _123(":"), 'access', _124 => _124.pop, 'call', _125 => _125()])));
18405
18432
  if (localName2 === "p") {
18406
18433
  const block = parseParagraph2(el, styles, numbering, footnotes, rels);
18407
18434
  if (block) blocks.push(block);
@@ -18432,7 +18459,7 @@ async function parseDocxDocument(buffer, options) {
18432
18459
  }
18433
18460
  }
18434
18461
  const outline = blocks.filter((b) => b.type === "heading").map((b) => ({ level: _nullishCoalesce(b.level, () => ( 2)), text: _nullishCoalesce(b.text, () => ( "")) }));
18435
- const markdown = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, blocks);
18462
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, blocks);
18436
18463
  return {
18437
18464
  markdown,
18438
18465
  blocks,
@@ -18455,7 +18482,7 @@ function parseHwpmlDocument(buffer, options) {
18455
18482
  }
18456
18483
  const text = new TextDecoder("utf-8").decode(buffer).replace(/^\uFEFF/, "");
18457
18484
  const normalized = text.replace(/&nbsp;/g, "&#160;");
18458
- const xml = _chunk53XNKPN6cjs.stripDtd.call(void 0, normalized);
18485
+ const xml = _chunkQZCP3UWUcjs.stripDtd.call(void 0, normalized);
18459
18486
  const warnings = [];
18460
18487
  const parser = new (0, _xmldom.DOMParser)({
18461
18488
  onError: (_level, msg2) => {
@@ -18483,7 +18510,7 @@ function parseHwpmlDocument(buffer, options) {
18483
18510
  return { markdown: "", blocks: [], metadata, warnings };
18484
18511
  }
18485
18512
  const blocks = [];
18486
- const pageFilter = _optionalChain([options, 'optionalAccess', _123 => _123.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, countSections(body)) : null;
18513
+ const pageFilter = _optionalChain([options, 'optionalAccess', _126 => _126.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, countSections(body)) : null;
18487
18514
  let sectionIdx = 0;
18488
18515
  const children = body.childNodes;
18489
18516
  for (let i = 0; i < children.length; i++) {
@@ -18495,7 +18522,7 @@ function parseHwpmlDocument(buffer, options) {
18495
18522
  parseSection2(el, blocks, paraShapeMap, sectionIdx, warnings);
18496
18523
  }
18497
18524
  const outline = blocks.filter((b) => b.type === "heading" && b.text).map((b) => ({ level: _nullishCoalesce(b.level, () => ( 1)), text: b.text, pageNumber: b.pageNumber }));
18498
- const markdown = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, blocks);
18525
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, blocks);
18499
18526
  return {
18500
18527
  markdown,
18501
18528
  blocks,
@@ -18565,7 +18592,7 @@ function parseParagraph3(el, blocks, paraShapeMap, sectionNum) {
18565
18592
  const shapeInfo = paraShapeMap.get(paraShapeId);
18566
18593
  const text = extractParagraphText(el);
18567
18594
  if (!text) return;
18568
- if (_optionalChain([shapeInfo, 'optionalAccess', _124 => _124.headingLevel]) != null) {
18595
+ if (_optionalChain([shapeInfo, 'optionalAccess', _127 => _127.headingLevel]) != null) {
18569
18596
  blocks.push({ type: "heading", text, level: shapeInfo.headingLevel, pageNumber: sectionNum });
18570
18597
  } else {
18571
18598
  blocks.push({ type: "paragraph", text, pageNumber: sectionNum });
@@ -18637,7 +18664,7 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
18637
18664
  const cellRows = grid.map(
18638
18665
  (row) => row.map((cell) => _nullishCoalesce(cell, () => ( { text: "", colSpan: 1, rowSpan: 1 })))
18639
18666
  );
18640
- const table = _chunk53XNKPN6cjs.buildTable.call(void 0, cellRows);
18667
+ const table = _chunkQZCP3UWUcjs.buildTable.call(void 0, cellRows);
18641
18668
  blocks.push({ type: "table", table, pageNumber: sectionNum });
18642
18669
  }
18643
18670
  function extractCellText(cellEl) {
@@ -18697,6 +18724,45 @@ function countSections(body) {
18697
18724
  }
18698
18725
 
18699
18726
  // src/form/match.ts
18727
+ var ValueCursor = (_class2 = class {
18728
+ constructor(values) {;_class2.prototype.__init4.call(this);
18729
+ this.values = values;
18730
+ }
18731
+ __init4() {this.nextIdx = /* @__PURE__ */ new Map()}
18732
+ keys() {
18733
+ return this.values.keys();
18734
+ }
18735
+ has(key) {
18736
+ return this.values.has(key);
18737
+ }
18738
+ isArray(key) {
18739
+ return Array.isArray(this.values.get(key));
18740
+ }
18741
+ /** 남은 값이 있으면 true (스칼라는 항상 true) */
18742
+ available(key) {
18743
+ const v = this.values.get(key);
18744
+ if (v === void 0) return false;
18745
+ return typeof v === "string" || (_nullishCoalesce(this.nextIdx.get(key), () => ( 0))) < v.length;
18746
+ }
18747
+ /** 현재 값 미리보기 (소진 없음) */
18748
+ peek(key) {
18749
+ const v = this.values.get(key);
18750
+ if (v === void 0) return void 0;
18751
+ if (typeof v === "string") return v;
18752
+ const i = _nullishCoalesce(this.nextIdx.get(key), () => ( 0));
18753
+ return i < v.length ? v[i] : void 0;
18754
+ }
18755
+ /** 값 소비 — 배열이면 커서 전진, 소진 시 undefined */
18756
+ consume(key) {
18757
+ const v = this.values.get(key);
18758
+ if (v === void 0) return void 0;
18759
+ if (typeof v === "string") return v;
18760
+ const i = _nullishCoalesce(this.nextIdx.get(key), () => ( 0));
18761
+ if (i >= v.length) return void 0;
18762
+ this.nextIdx.set(key, i + 1);
18763
+ return v[i];
18764
+ }
18765
+ }, _class2);
18700
18766
  function normalizeLabel(label) {
18701
18767
  return label.trim().replace(/[::\s()()·]/g, "");
18702
18768
  }
@@ -18735,9 +18801,9 @@ function fillInCellPatterns(cellText, values, matchedLabels) {
18735
18801
  (match, prefix, suffix) => {
18736
18802
  const label = prefix + suffix;
18737
18803
  const normalizedLabel = normalizeLabel(label);
18738
- const matchKey = values.has(normalizedLabel) ? normalizedLabel : values.has(normalizeLabel(prefix)) ? normalizeLabel(prefix) : void 0;
18804
+ const matchKey = values.available(normalizedLabel) ? normalizedLabel : values.available(normalizeLabel(prefix)) ? normalizeLabel(prefix) : void 0;
18739
18805
  if (matchKey === void 0) return match;
18740
- const newValue = values.get(matchKey);
18806
+ const newValue = values.consume(matchKey);
18741
18807
  matchedLabels.add(matchKey);
18742
18808
  matches.push({ key: matchKey, label, value: newValue });
18743
18809
  return `${prefix}(${newValue})${suffix}`;
@@ -18747,11 +18813,12 @@ function fillInCellPatterns(cellText, values, matchedLabels) {
18747
18813
  /□([가-힣A-Za-z]+)/g,
18748
18814
  (match, keyword) => {
18749
18815
  const normalizedKw = normalizeLabel(keyword);
18750
- const matchKey = values.has(normalizedKw) ? normalizedKw : void 0;
18816
+ const matchKey = values.available(normalizedKw) ? normalizedKw : void 0;
18751
18817
  if (matchKey === void 0) return match;
18752
- const val = values.get(matchKey);
18818
+ const val = values.peek(matchKey);
18753
18819
  const isTruthy = ["\u2611", "\u2713", "\u2714", "v", "V", "true", "1", "yes", "o", "O"].includes(val.trim()) || val.trim() === "";
18754
18820
  if (!isTruthy) return match;
18821
+ values.consume(matchKey);
18755
18822
  matchedLabels.add(matchKey);
18756
18823
  matches.push({ key: matchKey, label: `\u25A1${keyword}`, value: "\u2611" });
18757
18824
  return `\u2611${keyword}`;
@@ -18761,9 +18828,9 @@ function fillInCellPatterns(cellText, values, matchedLabels) {
18761
18828
  /\(([가-힣A-Za-z]+)[::]\s{1,}\)/g,
18762
18829
  (match, keyword) => {
18763
18830
  const normalizedKw = normalizeLabel(keyword);
18764
- const matchKey = values.has(normalizedKw) ? normalizedKw : void 0;
18831
+ const matchKey = values.available(normalizedKw) ? normalizedKw : void 0;
18765
18832
  if (matchKey === void 0) return match;
18766
- const newValue = values.get(matchKey);
18833
+ const newValue = values.consume(matchKey);
18767
18834
  matchedLabels.add(matchKey);
18768
18835
  matches.push({ key: matchKey, label: keyword, value: newValue });
18769
18836
  return `(${keyword}\uFF1A${newValue})`;
@@ -18869,14 +18936,66 @@ var LABEL_KEYWORDS = /* @__PURE__ */ new Set([
18869
18936
  "\uCCAD\uAD6C\uC0AC\uC720",
18870
18937
  "\uC18C\uBA85\uC790\uB8CC"
18871
18938
  ]);
18939
+ var ENGLISH_LABEL_WORDS = /* @__PURE__ */ new Set([
18940
+ "name",
18941
+ "date",
18942
+ "address",
18943
+ "tel",
18944
+ "phone",
18945
+ "mobile",
18946
+ "fax",
18947
+ "email",
18948
+ "e-mail",
18949
+ "dept",
18950
+ "department",
18951
+ "division",
18952
+ "title",
18953
+ "position",
18954
+ "grade",
18955
+ "rank",
18956
+ "birth",
18957
+ "nationality",
18958
+ "sex",
18959
+ "gender",
18960
+ "signature",
18961
+ "sign",
18962
+ "seal",
18963
+ "remarks",
18964
+ "note",
18965
+ "period",
18966
+ "place",
18967
+ "purpose",
18968
+ "reason",
18969
+ "amount",
18970
+ "total",
18971
+ "sum",
18972
+ "qty",
18973
+ "quantity",
18974
+ "unit",
18975
+ "no",
18976
+ "id",
18977
+ "passport"
18978
+ ]);
18979
+ var ENGLISH_STOPWORDS = /* @__PURE__ */ new Set(["of", "the", "and", "or", "in"]);
18980
+ var NUMERIC_VALUE_RE = /^제?\d+(?:[.,]\d+)*[십백천만억조]*(?:원|명|건|개|회|부|매|장|점|호|번|년|월|일|시|분|초|개월|주년|차례|퍼센트)?$/;
18981
+ var SENTENCE_ENDING_RE = /(?:입니다|합니다|습니다|하세요|십시오|시오|바랍니다|바람|할 것|할것|하며|하고|한다|된다|됨|음|임)$/;
18872
18982
  function isLabelCell(text) {
18873
18983
  const trimmed = text.trim().replace(/[¹²³⁴⁵⁶⁷⁸⁹⁰*※]+$/g, "").trim();
18874
18984
  if (!trimmed || trimmed.length > 30) return false;
18875
18985
  for (const kw of LABEL_KEYWORDS) {
18876
18986
  if (trimmed.includes(kw)) return true;
18877
18987
  }
18878
- if (/^[가-힣\s()()·::]+$/.test(trimmed) && trimmed.replace(/\s/g, "").length >= 2 && trimmed.replace(/\s/g, "").length <= 8 && !/\d/.test(trimmed)) return true;
18988
+ const compact = trimmed.replace(/\s/g, "");
18989
+ if (/^[가-힣0-9()()·::\-]+$/.test(compact) && compact.length >= 2 && compact.length <= 12 && (_nullishCoalesce(compact.match(/[가-힣]/g), () => ( []))).length >= 2 && (compact.length <= 8 || trimmed.split(/\s+/).length <= 2) && !NUMERIC_VALUE_RE.test(compact) && !SENTENCE_ENDING_RE.test(trimmed) && !/^[((]주[))]|^주식회사/.test(compact)) {
18990
+ return true;
18991
+ }
18879
18992
  if (/^[가-힣A-Za-z\s]+[::]$/.test(trimmed)) return true;
18993
+ if (/^[A-Za-z][A-Za-z\s./&-]*$/.test(trimmed) && trimmed.length <= 20) {
18994
+ const words = trimmed.toLowerCase().split(/[\s/&]+/).filter((w) => w && !ENGLISH_STOPWORDS.has(w));
18995
+ if (words.length >= 1 && words.length <= 3 && words.every((w) => ENGLISH_LABEL_WORDS.has(w.replace(/\.$/, "")))) {
18996
+ return true;
18997
+ }
18998
+ }
18880
18999
  return false;
18881
19000
  }
18882
19001
  function extractFormFields(blocks) {
@@ -18906,8 +19025,8 @@ function extractFromTable(table) {
18906
19025
  if (table.cols >= 2) {
18907
19026
  for (let r = 0; r < table.rows; r++) {
18908
19027
  for (let c = 0; c < table.cols - 1; c++) {
18909
- const labelCell = _optionalChain([table, 'access', _125 => _125.cells, 'access', _126 => _126[r], 'optionalAccess', _127 => _127[c]]);
18910
- const valueCell = _optionalChain([table, 'access', _128 => _128.cells, 'access', _129 => _129[r], 'optionalAccess', _130 => _130[c + 1]]);
19028
+ const labelCell = _optionalChain([table, 'access', _128 => _128.cells, 'access', _129 => _129[r], 'optionalAccess', _130 => _130[c]]);
19029
+ const valueCell = _optionalChain([table, 'access', _131 => _131.cells, 'access', _132 => _132[r], 'optionalAccess', _133 => _133[c + 1]]);
18911
19030
  if (!labelCell || !valueCell) continue;
18912
19031
  if (isLabelCell(labelCell.text)) {
18913
19032
  fields.push({
@@ -18929,8 +19048,8 @@ function extractFromTable(table) {
18929
19048
  if (allLabels) {
18930
19049
  for (let r = 1; r < table.rows; r++) {
18931
19050
  for (let c = 0; c < table.cols; c++) {
18932
- const label = _nullishCoalesce(_optionalChain([headerRow, 'access', _131 => _131[c], 'optionalAccess', _132 => _132.text, 'access', _133 => _133.trim, 'call', _134 => _134()]), () => ( ""));
18933
- const value = _nullishCoalesce(_optionalChain([table, 'access', _135 => _135.cells, 'access', _136 => _136[r], 'optionalAccess', _137 => _137[c], 'optionalAccess', _138 => _138.text, 'access', _139 => _139.trim, 'call', _140 => _140()]), () => ( ""));
19051
+ const label = _nullishCoalesce(_optionalChain([headerRow, 'access', _134 => _134[c], 'optionalAccess', _135 => _135.text, 'access', _136 => _136.trim, 'call', _137 => _137()]), () => ( ""));
19052
+ const value = _nullishCoalesce(_optionalChain([table, 'access', _138 => _138.cells, 'access', _139 => _139[r], 'optionalAccess', _140 => _140[c], 'optionalAccess', _141 => _141.text, 'access', _142 => _142.trim, 'call', _143 => _143()]), () => ( ""));
18934
19053
  if (label && value) {
18935
19054
  fields.push({ label, value, row: r, col: c });
18936
19055
  }
@@ -19017,17 +19136,18 @@ function fillFormFields(blocks, values) {
19017
19136
  const filled = [];
19018
19137
  const matchedLabels = /* @__PURE__ */ new Set();
19019
19138
  const normalizedValues = normalizeValues(values);
19139
+ const cursor = new ValueCursor(normalizedValues);
19140
+ const allTables = collectIRTables(cloned, 0);
19020
19141
  const patternFilledCells = /* @__PURE__ */ new Set();
19021
- for (const block of cloned) {
19022
- if (block.type !== "table" || !block.table) continue;
19023
- for (let r = 0; r < block.table.rows; r++) {
19024
- for (let c = 0; c < block.table.cols; c++) {
19025
- const cell = _optionalChain([block, 'access', _141 => _141.table, 'access', _142 => _142.cells, 'access', _143 => _143[r], 'optionalAccess', _144 => _144[c]]);
19142
+ for (const table of allTables) {
19143
+ for (let r = 0; r < table.rows; r++) {
19144
+ for (let c = 0; c < table.cols; c++) {
19145
+ const cell = _optionalChain([table, 'access', _144 => _144.cells, 'access', _145 => _145[r], 'optionalAccess', _146 => _146[c]]);
19026
19146
  if (!cell) continue;
19027
- const result = fillInCellPatterns(cell.text, normalizedValues, matchedLabels);
19147
+ const result = fillInCellPatterns(cell.text, cursor, matchedLabels);
19028
19148
  if (result) {
19029
19149
  cell.text = result.text;
19030
- patternFilledCells.add(`${r},${c}`);
19150
+ patternFilledCells.add(cell);
19031
19151
  for (const m of result.matches) {
19032
19152
  filled.push({ label: m.label, value: m.value, row: r, col: c });
19033
19153
  }
@@ -19035,33 +19155,71 @@ function fillFormFields(blocks, values) {
19035
19155
  }
19036
19156
  }
19037
19157
  }
19038
- for (const block of cloned) {
19039
- if (block.type !== "table" || !block.table) continue;
19040
- fillTable(block.table, normalizedValues, filled, matchedLabels, patternFilledCells);
19158
+ for (const table of allTables) {
19159
+ fillTable(table, cursor, filled, matchedLabels, patternFilledCells);
19041
19160
  }
19042
19161
  for (const block of cloned) {
19043
19162
  if (block.type !== "paragraph" || !block.text) continue;
19044
- const newText = fillInlineFields(block.text, normalizedValues, filled, matchedLabels);
19163
+ const newText = fillInlineFields(block.text, cursor, filled, matchedLabels);
19045
19164
  if (newText !== block.text) block.text = newText;
19046
19165
  }
19047
19166
  const unmatched = resolveUnmatched(normalizedValues, matchedLabels, values);
19048
19167
  return { blocks: cloned, filled, unmatched };
19049
19168
  }
19169
+ function collectIRTables(blocks, depth) {
19170
+ if (depth > 16) return [];
19171
+ const out = [];
19172
+ for (const block of blocks) {
19173
+ if (block.type !== "table" || !block.table) continue;
19174
+ out.push(block.table);
19175
+ for (const row of block.table.cells) {
19176
+ for (const cell of row) {
19177
+ if (_optionalChain([cell, 'optionalAccess', _147 => _147.blocks, 'optionalAccess', _148 => _148.length])) out.push(...collectIRTables(cell.blocks, depth + 1));
19178
+ }
19179
+ }
19180
+ }
19181
+ return out;
19182
+ }
19183
+ function coveredPositions(table) {
19184
+ const covered = /* @__PURE__ */ new Set();
19185
+ for (let r = 0; r < table.rows; r++) {
19186
+ for (let c = 0; c < table.cols; c++) {
19187
+ if (covered.has(`${r},${c}`)) continue;
19188
+ const cell = _optionalChain([table, 'access', _149 => _149.cells, 'access', _150 => _150[r], 'optionalAccess', _151 => _151[c]]);
19189
+ if (!cell) continue;
19190
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
19191
+ for (let dc = 0; dc < cell.colSpan; dc++) {
19192
+ if (dr === 0 && dc === 0) continue;
19193
+ if (r + dr < table.rows && c + dc < table.cols) covered.add(`${r + dr},${c + dc}`);
19194
+ }
19195
+ }
19196
+ c += cell.colSpan - 1;
19197
+ }
19198
+ }
19199
+ return covered;
19200
+ }
19050
19201
  function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
19051
19202
  if (table.cols < 2) return;
19203
+ const covered = coveredPositions(table);
19052
19204
  for (let r = 0; r < table.rows; r++) {
19053
- for (let c = 0; c < table.cols - 1; c++) {
19205
+ for (let c = 0; c < table.cols; c++) {
19206
+ if (covered.has(`${r},${c}`)) continue;
19054
19207
  const labelCell = table.cells[r][c];
19055
- const valueCell = table.cells[r][c + 1];
19056
- if (!labelCell || !valueCell) continue;
19208
+ if (!labelCell) continue;
19057
19209
  if (!isLabelCell(labelCell.text)) continue;
19210
+ let vc = c + labelCell.colSpan;
19211
+ while (vc < table.cols && covered.has(`${r},${vc}`)) vc++;
19212
+ if (vc >= table.cols) continue;
19213
+ const valueCell = table.cells[r][vc];
19214
+ if (!valueCell) continue;
19058
19215
  if (isKeywordLabel(valueCell.text)) continue;
19059
19216
  const normalizedCellLabel = normalizeLabel(labelCell.text);
19060
19217
  if (!normalizedCellLabel) continue;
19061
19218
  const matchKey = findMatchingKey(normalizedCellLabel, values);
19062
19219
  if (matchKey === void 0) continue;
19063
- const newValue = values.get(matchKey);
19064
- if (_optionalChain([patternFilledCells, 'optionalAccess', _145 => _145.has, 'call', _146 => _146(`${r},${c + 1}`)])) {
19220
+ const newValue = values.consume(matchKey);
19221
+ if (newValue === void 0) continue;
19222
+ if (_optionalChain([patternFilledCells, 'optionalAccess', _152 => _152.has, 'call', _153 => _153(valueCell)])) {
19065
19223
  valueCell.text = newValue + " " + valueCell.text;
19066
19224
  } else {
19067
19225
  valueCell.text = newValue;
@@ -19084,14 +19242,16 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
19084
19242
  if (!allLabels) return;
19085
19243
  for (let r = 1; r < table.rows; r++) {
19086
19244
  for (let c = 0; c < table.cols; c++) {
19245
+ if (covered.has(`${r},${c}`)) continue;
19087
19246
  const headerCell = headerRow[c];
19088
- const valueCell = _optionalChain([table, 'access', _147 => _147.cells, 'access', _148 => _148[r], 'optionalAccess', _149 => _149[c]]);
19247
+ const valueCell = _optionalChain([table, 'access', _154 => _154.cells, 'access', _155 => _155[r], 'optionalAccess', _156 => _156[c]]);
19089
19248
  if (!headerCell || !valueCell) continue;
19090
19249
  const headerLabel = normalizeLabel(headerCell.text);
19091
19250
  const matchKey = findMatchingKey(headerLabel, values);
19092
19251
  if (matchKey === void 0) continue;
19093
- if (matchedLabels.has(matchKey)) continue;
19094
- const newValue = values.get(matchKey);
19252
+ if (!values.isArray(matchKey) && matchedLabels.has(matchKey)) continue;
19253
+ const newValue = values.consume(matchKey);
19254
+ if (newValue === void 0) continue;
19095
19255
  valueCell.text = newValue;
19096
19256
  matchedLabels.add(matchKey);
19097
19257
  filled.push({
@@ -19112,7 +19272,8 @@ function fillInlineFields(text, values, filled, matchedLabels) {
19112
19272
  for (const seg of segments) {
19113
19273
  const matchKey = findMatchingKey(normalizeLabel(seg.label), values);
19114
19274
  if (matchKey === void 0) continue;
19115
- const newValue = values.get(matchKey);
19275
+ const newValue = values.consume(matchKey);
19276
+ if (newValue === void 0) continue;
19116
19277
  matchedLabels.add(matchKey);
19117
19278
  filled.push({ label: seg.label.trim(), value: newValue, row: -1, col: -1 });
19118
19279
  out += text.slice(pos, seg.valueStart);
@@ -19219,6 +19380,7 @@ function scanSectionXml(xml, sectionIndex) {
19219
19380
  const paraStack = [];
19220
19381
  const tableStack = [];
19221
19382
  const rowStack = [];
19383
+ const trStartStack = [];
19222
19384
  const cellStack = [];
19223
19385
  let pendingT = null;
19224
19386
  const ctrlSubStack = [];
@@ -19283,11 +19445,17 @@ function scanSectionXml(xml, sectionIndex) {
19283
19445
  } else if (local2 === "tr") {
19284
19446
  const row = rowStack[rowStack.length - 1];
19285
19447
  const table = tableStack[tableStack.length - 1];
19286
- if (row && table && row.length > 0) table.rows.push(row);
19448
+ if (row && table && row.length > 0) {
19449
+ table.rows.push(row);
19450
+ const trStart = trStartStack[trStartStack.length - 1];
19451
+ if (trStart >= 0) table.rowRanges.push({ start: trStart, end: m.index + full.length });
19452
+ }
19287
19453
  if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
19454
+ if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = -1;
19288
19455
  } else if (local2 === "tbl") {
19289
19456
  const table = tableStack.pop();
19290
19457
  rowStack.pop();
19458
+ trStartStack.pop();
19291
19459
  if (table) {
19292
19460
  finalizeTable(table);
19293
19461
  if (!table.topLevel) {
@@ -19330,6 +19498,7 @@ function scanSectionXml(xml, sectionIndex) {
19330
19498
  const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
19331
19499
  if (!isNaN(ca)) cell.colAddr = ca;
19332
19500
  if (!isNaN(ra)) cell.rowAddr = ra;
19501
+ cell.addrTagRange = { start: m.index, end: m.index + full.length };
19333
19502
  }
19334
19503
  } else if (local === "cellSpan") {
19335
19504
  const cell = cellStack[cellStack.length - 1];
@@ -19380,6 +19549,7 @@ function scanSectionXml(xml, sectionIndex) {
19380
19549
  start: m.index,
19381
19550
  topLevel: false,
19382
19551
  rows: [],
19552
+ rowRanges: [],
19383
19553
  cellByAnchor: /* @__PURE__ */ new Map()
19384
19554
  };
19385
19555
  stack.pop();
@@ -19387,9 +19557,11 @@ function scanSectionXml(xml, sectionIndex) {
19387
19557
  stack.push({ local, qname, contentStart });
19388
19558
  tableStack.push(table);
19389
19559
  rowStack.push([]);
19560
+ trStartStack.push(-1);
19390
19561
  if (table.topLevel) tables.push(table);
19391
19562
  } else if (local === "tr") {
19392
19563
  if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
19564
+ if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = m.index;
19393
19565
  } else if (local === "tc") {
19394
19566
  cellStack.push({ colSpan: 1, rowSpan: 1, paragraphs: [], tables: [] });
19395
19567
  } else if (local === "cellAddr" || local === "cellSpan") {
@@ -19400,6 +19572,7 @@ function scanSectionXml(xml, sectionIndex) {
19400
19572
  const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
19401
19573
  if (!isNaN(ca)) cell.colAddr = ca;
19402
19574
  if (!isNaN(ra)) cell.rowAddr = ra;
19575
+ cell.addrTagRange = { start: m.index, end: contentStart };
19403
19576
  } else {
19404
19577
  const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
19405
19578
  const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
@@ -19664,19 +19837,19 @@ function parseCentralDirectory(buf) {
19664
19837
  }
19665
19838
  }
19666
19839
  }
19667
- if (eocdOffset < 0) throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP EOCD\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
19840
+ if (eocdOffset < 0) throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP EOCD\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
19668
19841
  const totalEntries = view.getUint16(eocdOffset + 10, true);
19669
19842
  const cdSize = view.getUint32(eocdOffset + 12, true);
19670
19843
  const cdOffset = view.getUint32(eocdOffset + 16, true);
19671
- if (cdOffset === 4294967295 || totalEntries === 65535) throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19844
+ if (cdOffset === 4294967295 || totalEntries === 65535) throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19672
19845
  if (eocdOffset >= 20 && view.getUint32(eocdOffset - 20, true) === ZIP64_EOCD_LOC_SIG) {
19673
- throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19846
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19674
19847
  }
19675
19848
  const decoder = new TextDecoder("utf-8");
19676
19849
  const entries = [];
19677
19850
  let pos = cdOffset;
19678
19851
  for (let i = 0; i < totalEntries; i++) {
19679
- if (view.getUint32(pos, true) !== CD_SIG) throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP Central Directory \uC190\uC0C1");
19852
+ if (view.getUint32(pos, true) !== CD_SIG) throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP Central Directory \uC190\uC0C1");
19680
19853
  const flags = view.getUint16(pos + 8, true);
19681
19854
  const method = view.getUint16(pos + 10, true);
19682
19855
  const crc = view.getUint32(pos + 16, true);
@@ -19687,7 +19860,7 @@ function parseCentralDirectory(buf) {
19687
19860
  const commentLen = view.getUint16(pos + 32, true);
19688
19861
  const localOffset = view.getUint32(pos + 42, true);
19689
19862
  if (compSize === 4294967295 || uncompSize === 4294967295 || localOffset === 4294967295) {
19690
- throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19863
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19691
19864
  }
19692
19865
  const name = decoder.decode(buf.subarray(pos + 46, pos + 46 + nameLen));
19693
19866
  const cdEnd = pos + 46 + nameLen + extraLen + commentLen;
@@ -19716,7 +19889,7 @@ function patchZipEntries(original, replacements) {
19716
19889
  const { entries, cdOffset, eocdOffset } = parseCentralDirectory(original);
19717
19890
  const view = new DataView(original.buffer, original.byteOffset, original.byteLength);
19718
19891
  for (const name of replacements.keys()) {
19719
- if (!entries.some((e) => e.name === name)) throw new (0, _chunk53XNKPN6cjs.KordocError)(`ZIP\uC5D0 \uC5C6\uB294 \uC5D4\uD2B8\uB9AC: ${name}`);
19892
+ if (!entries.some((e) => e.name === name)) throw new (0, _chunkQZCP3UWUcjs.KordocError)(`ZIP\uC5D0 \uC5C6\uB294 \uC5D4\uD2B8\uB9AC: ${name}`);
19720
19893
  }
19721
19894
  const byLocal = [...entries].sort((a, b) => a.localOffset - b.localOffset);
19722
19895
  const segments = [];
@@ -19734,7 +19907,7 @@ function patchZipEntries(original, replacements) {
19734
19907
  offset += seg.length;
19735
19908
  continue;
19736
19909
  }
19737
- if (view.getUint32(e.localOffset, true) !== LOCAL_SIG) throw new (0, _chunk53XNKPN6cjs.KordocError)("ZIP \uB85C\uCEEC \uD5E4\uB354 \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
19910
+ if (view.getUint32(e.localOffset, true) !== LOCAL_SIG) throw new (0, _chunkQZCP3UWUcjs.KordocError)("ZIP \uB85C\uCEEC \uD5E4\uB354 \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
19738
19911
  const nameLen = view.getUint16(e.localOffset + 26, true);
19739
19912
  const extraLen = view.getUint16(e.localOffset + 28, true);
19740
19913
  const headerLen = 30 + nameLen + extraLen;
@@ -19789,9 +19962,10 @@ async function fillHwpx(hwpxBuffer, values) {
19789
19962
  const zip = await _jszip2.default.loadAsync(hwpxBuffer);
19790
19963
  const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
19791
19964
  if (sectionPaths.length === 0) {
19792
- throw new (0, _chunk53XNKPN6cjs.KordocError)("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
19965
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
19793
19966
  }
19794
19967
  const normalizedValues = normalizeValues(values);
19968
+ const cursor = new ValueCursor(normalizedValues);
19795
19969
  const matchedLabels = /* @__PURE__ */ new Set();
19796
19970
  const filled = [];
19797
19971
  const failedKeys = /* @__PURE__ */ new Set();
@@ -19827,7 +20001,7 @@ async function fillHwpx(hwpxBuffer, values) {
19827
20001
  for (const cell of row) {
19828
20002
  for (const para of cell.paragraphs) {
19829
20003
  const text = matchText(para);
19830
- const result = fillInCellPatterns(text, normalizedValues, matchedLabels);
20004
+ const result = fillInCellPatterns(text, cursor, matchedLabels);
19831
20005
  if (!result) continue;
19832
20006
  const l = led(para);
19833
20007
  if (l.fullText !== void 0) continue;
@@ -19861,21 +20035,30 @@ async function fillHwpx(hwpxBuffer, values) {
19861
20035
  if (isKeywordLabel(cellLabelText(valueCell))) continue;
19862
20036
  const normalizedCellLabel = normalizeLabel(labelText);
19863
20037
  if (!normalizedCellLabel) continue;
19864
- const matchKey = findMatchingKey(normalizedCellLabel, normalizedValues);
20038
+ const matchKey = findMatchingKey(normalizedCellLabel, cursor);
19865
20039
  if (matchKey === void 0) continue;
19866
- const newValue = normalizedValues.get(matchKey);
19867
20040
  if (patternApplied.has(valueCell)) {
19868
20041
  const target = _nullishCoalesce(valueCell.paragraphs.find((p) => p.tRanges.length > 0), () => ( valueCell.paragraphs[0]));
19869
20042
  if (!target) continue;
19870
20043
  const l = led(target);
19871
- if (l.fullText === void 0) {
19872
- l.ranges.push({ start: 0, end: 0, replacement: newValue + " " });
19873
- l.filledIdx.push(filled.length);
19874
- l.matchKeys.push(matchKey);
19875
- }
20044
+ if (l.fullText !== void 0) continue;
20045
+ const newValue = cursor.consume(matchKey);
20046
+ if (newValue === void 0) continue;
20047
+ l.ranges.push({ start: 0, end: 0, replacement: newValue + " " });
20048
+ l.filledIdx.push(filled.length);
20049
+ l.matchKeys.push(matchKey);
20050
+ matchedLabels.add(matchKey);
20051
+ filled.push({
20052
+ label: labelText.trim().replace(/[::]\s*$/, ""),
20053
+ value: newValue,
20054
+ row: rowIdx,
20055
+ col: colIdx
20056
+ });
19876
20057
  } else {
19877
20058
  const paras = valueCell.paragraphs;
19878
20059
  if (paras.length === 0) continue;
20060
+ const newValue = cursor.consume(matchKey);
20061
+ if (newValue === void 0) continue;
19879
20062
  const l0 = led(paras[0]);
19880
20063
  l0.fullText = newValue;
19881
20064
  l0.ranges = [];
@@ -19886,14 +20069,14 @@ async function fillHwpx(hwpxBuffer, values) {
19886
20069
  lk.fullText = "";
19887
20070
  lk.ranges = [];
19888
20071
  }
20072
+ matchedLabels.add(matchKey);
20073
+ filled.push({
20074
+ label: labelText.trim().replace(/[::]\s*$/, ""),
20075
+ value: newValue,
20076
+ row: rowIdx,
20077
+ col: colIdx
20078
+ });
19889
20079
  }
19890
- matchedLabels.add(matchKey);
19891
- filled.push({
19892
- label: labelText.trim().replace(/[::]\s*$/, ""),
19893
- value: newValue,
19894
- row: rowIdx,
19895
- col: colIdx
19896
- });
19897
20080
  }
19898
20081
  }
19899
20082
  if (table.rows.length >= 2) {
@@ -19907,10 +20090,11 @@ async function fillHwpx(hwpxBuffer, values) {
19907
20090
  const dataCells = table.rows[rowIdx];
19908
20091
  for (let colIdx = 0; colIdx < Math.min(headerCells.length, dataCells.length); colIdx++) {
19909
20092
  const headerLabel = normalizeLabel(cellLabelText(headerCells[colIdx]));
19910
- const matchKey = findMatchingKey(headerLabel, normalizedValues);
20093
+ const matchKey = findMatchingKey(headerLabel, cursor);
19911
20094
  if (matchKey === void 0) continue;
19912
- if (matchedLabels.has(matchKey)) continue;
19913
- const newValue = normalizedValues.get(matchKey);
20095
+ if (!cursor.isArray(matchKey) && matchedLabels.has(matchKey)) continue;
20096
+ const newValue = cursor.consume(matchKey);
20097
+ if (newValue === void 0) continue;
19914
20098
  const paras = dataCells[colIdx].paragraphs;
19915
20099
  if (paras.length === 0) continue;
19916
20100
  const l0 = led(paras[0]);
@@ -19937,12 +20121,13 @@ async function fillHwpx(hwpxBuffer, values) {
19937
20121
  }
19938
20122
  for (const para of [...scan.bodyParagraphs, ...scan.excludedParagraphs]) {
19939
20123
  const existing = ledger.get(para);
19940
- if (_optionalChain([existing, 'optionalAccess', _150 => _150.fullText]) !== void 0) continue;
20124
+ if (_optionalChain([existing, 'optionalAccess', _157 => _157.fullText]) !== void 0) continue;
19941
20125
  const text = matchText(para);
19942
20126
  for (const seg of scanInlineSegments(text)) {
19943
- const matchKey = findMatchingKey(normalizeLabel(seg.label), normalizedValues);
20127
+ const matchKey = findMatchingKey(normalizeLabel(seg.label), cursor);
19944
20128
  if (matchKey === void 0) continue;
19945
- const newValue = normalizedValues.get(matchKey);
20129
+ const newValue = cursor.consume(matchKey);
20130
+ if (newValue === void 0) continue;
19946
20131
  const replacement = seg.valueStart === seg.valueEnd ? padInsertion(text, seg.valueStart, newValue) : newValue;
19947
20132
  const l = led(para);
19948
20133
  l.ranges.push({ start: seg.valueStart, end: seg.valueEnd, replacement });
@@ -19997,6 +20182,7 @@ async function fillHwpx(hwpxBuffer, values) {
19997
20182
  splices.push(...paraSplices);
19998
20183
  }
19999
20184
  if (splices.length > 0) {
20185
+ splices.push(...allLinesegRemovalSplices(xml));
20000
20186
  replacements.set(sectionPaths[si], encoder.encode(applySplices(xml, splices)));
20001
20187
  }
20002
20188
  }
@@ -20016,6 +20202,245 @@ async function fillHwpx(hwpxBuffer, values) {
20016
20202
  // src/hwpx/generator.ts
20017
20203
 
20018
20204
 
20205
+ // src/hwpx/text-metrics.ts
20206
+ var ASCII_W = [
20207
+ 300,
20208
+ 320,
20209
+ 320,
20210
+ 610,
20211
+ 610,
20212
+ 830,
20213
+ 724,
20214
+ 320,
20215
+ 320,
20216
+ 320,
20217
+ 550,
20218
+ 550,
20219
+ 320,
20220
+ 550,
20221
+ 320,
20222
+ 550,
20223
+ // 0x20-0x2F
20224
+ 550,
20225
+ 550,
20226
+ 550,
20227
+ 550,
20228
+ 550,
20229
+ 550,
20230
+ 550,
20231
+ 550,
20232
+ 550,
20233
+ 550,
20234
+ 320,
20235
+ 320,
20236
+ 550,
20237
+ 550,
20238
+ 550,
20239
+ 550,
20240
+ // 0x30-0x3F
20241
+ 830,
20242
+ 706,
20243
+ 605,
20244
+ 685,
20245
+ 719,
20246
+ 627,
20247
+ 617,
20248
+ 683,
20249
+ 734,
20250
+ 305,
20251
+ 315,
20252
+ 660,
20253
+ 605,
20254
+ 839,
20255
+ 734,
20256
+ 732,
20257
+ // 0x40-0x4F
20258
+ 603,
20259
+ 705,
20260
+ 660,
20261
+ 627,
20262
+ 664,
20263
+ 731,
20264
+ 706,
20265
+ 910,
20266
+ 705,
20267
+ 705,
20268
+ 626,
20269
+ 320,
20270
+ 550,
20271
+ 320,
20272
+ 550,
20273
+ 550,
20274
+ // 0x50-0x5F
20275
+ 320,
20276
+ 569,
20277
+ 597,
20278
+ 552,
20279
+ 597,
20280
+ 536,
20281
+ 356,
20282
+ 562,
20283
+ 635,
20284
+ 287,
20285
+ 288,
20286
+ 582,
20287
+ 287,
20288
+ 907,
20289
+ 635,
20290
+ 588,
20291
+ // 0x60-0x6F
20292
+ 597,
20293
+ 579,
20294
+ 478,
20295
+ 496,
20296
+ 356,
20297
+ 635,
20298
+ 563,
20299
+ 720,
20300
+ 542,
20301
+ 543,
20302
+ 486,
20303
+ 320,
20304
+ 320,
20305
+ 320,
20306
+ 550,
20307
+ 0
20308
+ // 0x70-0x7E(+DEL)
20309
+ ];
20310
+ var SYM_W = {
20311
+ 160: 300,
20312
+ 163: 568,
20313
+ 165: 707,
20314
+ 167: 498,
20315
+ 171: 440,
20316
+ 172: 564,
20317
+ 176: 291,
20318
+ 177: 798,
20319
+ 182: 606,
20320
+ 183: 320,
20321
+ 187: 440,
20322
+ 215: 617,
20323
+ 247: 678,
20324
+ 8211: 625,
20325
+ 8212: 875,
20326
+ 8213: 875,
20327
+ 8216: 320,
20328
+ 8217: 320,
20329
+ 8220: 480,
20330
+ 8221: 480,
20331
+ 8224: 558,
20332
+ 8225: 438,
20333
+ 8229: 640,
20334
+ 8230: 960,
20335
+ 8240: 988,
20336
+ 8242: 335,
20337
+ 8243: 474,
20338
+ 8251: 770,
20339
+ 8364: 656,
20340
+ 9756: 1012,
20341
+ 9758: 1012
20342
+ };
20343
+ function charWidthEm1000(cp) {
20344
+ if (cp >= 32 && cp <= 126) return ASCII_W[cp - 32];
20345
+ const sym = SYM_W[cp];
20346
+ if (sym !== void 0) return sym;
20347
+ if (cp >= 44032 && cp <= 55203) return 970;
20348
+ if (cp >= 4352 && cp <= 4607) return 970;
20349
+ if (cp >= 12593 && cp <= 12686) return 970;
20350
+ if (cp >= 19968 && cp <= 40959 || cp >= 63744 && cp <= 64255) return 1e3;
20351
+ if (cp >= 12296 && cp <= 12305 || cp >= 12308 && cp <= 12315) return 500;
20352
+ if (cp === 12288) return 970;
20353
+ if (cp >= 8592 && cp <= 8959) return 970;
20354
+ if (cp >= 9312 && cp <= 9471) return 970;
20355
+ if (cp >= 9632 && cp <= 9983) return 970;
20356
+ if (cp >= 12800 && cp <= 13311) return 970;
20357
+ if (cp >= 65281 && cp <= 65376) return 970;
20358
+ return cp >= 11904 ? 970 : 550;
20359
+ }
20360
+ var SPACE_EM_FIXED = 500;
20361
+ var SPACE_EM_FONT = 300;
20362
+ function measureTextWidth(text, height, ratioPct, opts) {
20363
+ const spaceEm = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _158 => _158.spaceEm]), () => ( SPACE_EM_FIXED));
20364
+ const spacing = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _159 => _159.spacingPct]), () => ( 0));
20365
+ let em = 0;
20366
+ for (const ch of text) {
20367
+ const cp = ch.codePointAt(0);
20368
+ const w = cp === 32 ? spaceEm : charWidthEm1000(cp);
20369
+ em += w * (1 + spacing / 100);
20370
+ }
20371
+ return em / 1e3 * height * (ratioPct / 100);
20372
+ }
20373
+ var FORBID_START = /* @__PURE__ */ new Set([..."!%),.:;?]}\xA2\xB0\u2032\u2033\u2103\u3009\u300B\u300D\u300F\u3011\u3015!%),.:;?]}\u20A9~\u2026\xB7\u3001\u3002\u3003"]);
20374
+ var FORBID_END = /* @__PURE__ */ new Set([..."$([{\xA3\xA5\u3008\u300A\u300C\u300E\u3010\u3014$([{\u20A9"]);
20375
+ function simulateWrap(text, firstWidth, contWidth, height, ratioPct, mode = "keep", opts) {
20376
+ const EPS = 0.5;
20377
+ const spaceEm = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _160 => _160.spaceEm]), () => ( SPACE_EM_FIXED));
20378
+ const spacing = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _161 => _161.spacingPct]), () => ( 0));
20379
+ const k = height * ratioPct / 100 / 1e3;
20380
+ const cwCp = (cp) => (cp === 32 ? spaceEm : charWidthEm1000(cp)) * (1 + spacing / 100) * k;
20381
+ const charW = (ch) => cwCp(ch.codePointAt(0));
20382
+ const rangeW = (from, to) => {
20383
+ let w = 0;
20384
+ for (const ch of text.slice(from, to)) w += charW(ch);
20385
+ return w;
20386
+ };
20387
+ const units = _nullishCoalesce(text.match(mode === "keep" ? / +|[^ ]+/g : / +|[^ ]/g), () => ( []));
20388
+ const starts = [0];
20389
+ let lineW = 0;
20390
+ let avail = firstWidth;
20391
+ let pos = 0;
20392
+ const lineStart = () => starts[starts.length - 1];
20393
+ const breakBefore = (unitPos, w) => {
20394
+ let bp = unitPos;
20395
+ const u = text[unitPos];
20396
+ if (u !== void 0 && FORBID_START.has(u) && bp - 1 > lineStart() && text[bp - 1] !== " ") bp--;
20397
+ while (bp - 1 > lineStart() && FORBID_END.has(text[bp - 1])) bp--;
20398
+ if (bp <= lineStart()) bp = unitPos;
20399
+ starts.push(bp);
20400
+ avail = contWidth;
20401
+ lineW = rangeW(bp, unitPos) + w;
20402
+ };
20403
+ for (const u of units) {
20404
+ if (u[0] === " ") {
20405
+ lineW += charW(" ") * u.length;
20406
+ pos += u.length;
20407
+ continue;
20408
+ }
20409
+ const w = rangeW(pos, pos + u.length);
20410
+ if (lineW + w <= avail + EPS) {
20411
+ lineW += w;
20412
+ pos += u.length;
20413
+ continue;
20414
+ }
20415
+ if (lineW === 0 || w > contWidth + EPS) {
20416
+ let sub = 0;
20417
+ for (const ch of u) {
20418
+ const c = charW(ch);
20419
+ if (lineW + c > avail + EPS && lineW > 0) breakBefore(pos + sub, 0);
20420
+ lineW += c;
20421
+ sub += ch.length;
20422
+ }
20423
+ pos += u.length;
20424
+ continue;
20425
+ }
20426
+ breakBefore(pos, w);
20427
+ pos += u.length;
20428
+ }
20429
+ return { lines: starts.length, starts, lastLineWidth: lineW };
20430
+ }
20431
+ function simulateWrapKeepWord(text, firstWidth, contWidth, height, ratioPct, opts) {
20432
+ return simulateWrap(text, firstWidth, contWidth, height, ratioPct, "keep", opts);
20433
+ }
20434
+ function fitRatioForFewerLines(text, firstWidth, contWidth, height, baseRatio, minRatio, opts) {
20435
+ const base = simulateWrap(text, firstWidth, contWidth, height, baseRatio, "keep", opts);
20436
+ if (base.lines < 2) return null;
20437
+ for (let r = baseRatio - 1; r >= minRatio; r--) {
20438
+ const sim = simulateWrap(text, firstWidth, contWidth, height, r, "keep", opts);
20439
+ if (sim.lines < base.lines) return r;
20440
+ }
20441
+ return null;
20442
+ }
20443
+
20019
20444
  // src/hwpx/gongmun.ts
20020
20445
  var OFFICIAL_MARGINS = { top: 20, bottom: 10, left: 20, right: 20 };
20021
20446
  var PRESET_DEFAULTS = {
@@ -20051,6 +20476,7 @@ function resolveGongmun(opts) {
20051
20476
  const preset = normalizeGongmunPreset(opts.preset);
20052
20477
  const d = PRESET_DEFAULTS[preset];
20053
20478
  const bodyPt = _nullishCoalesce(opts.bodyPt, () => ( d.bodyPt));
20479
+ const autoFitMinRatio = opts.autoFit === false ? null : typeof opts.autoFit === "object" ? Math.min(Math.max(_nullishCoalesce(opts.autoFit.minRatio, () => ( 90)), 50), 99) : 90;
20054
20480
  return {
20055
20481
  preset,
20056
20482
  bodyFont: _nullishCoalesce(opts.bodyFont, () => ( "myeongjo")),
@@ -20058,7 +20484,8 @@ function resolveGongmun(opts) {
20058
20484
  lineSpacing: _nullishCoalesce(opts.lineSpacing, () => ( d.lineSpacing)),
20059
20485
  numbering: _nullishCoalesce(opts.numbering, () => ( d.numbering)),
20060
20486
  margins: _nullishCoalesce(opts.margins, () => ( OFFICIAL_MARGINS)),
20061
- centerTitle: _nullishCoalesce(opts.centerTitle, () => ( true))
20487
+ centerTitle: _nullishCoalesce(opts.centerTitle, () => ( true)),
20488
+ autoFitMinRatio
20062
20489
  };
20063
20490
  }
20064
20491
  var HANGUL_INITIALS = [0, 2, 3, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18];
@@ -20101,11 +20528,14 @@ function standardMarker(depth, n) {
20101
20528
  function reportMarker(depth) {
20102
20529
  return REPORT_BULLETS[Math.min(depth, REPORT_BULLETS.length - 1)];
20103
20530
  }
20531
+ function markerWidth(marker, bodyHeight) {
20532
+ let em = SPACE_EM_FIXED;
20533
+ for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
20534
+ return Math.round(em / 1e3 * bodyHeight);
20535
+ }
20104
20536
  function levelIndent(depth, bodyHeight, numbering) {
20105
- const ta = bodyHeight / 2;
20106
- const markerTa = numbering === "standard" && (depth === 4 || depth === 5) ? 3 : 2;
20107
- const hang = Math.round((markerTa + 1) * ta);
20108
- return { left: Math.round(depth * bodyHeight), indent: -hang };
20537
+ const marker = numbering === "report" ? reportMarker(depth) : standardMarker(depth, 0);
20538
+ return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, bodyHeight) };
20109
20539
  }
20110
20540
  function computeSuppression(depths) {
20111
20541
  const counts = /* @__PURE__ */ new Map();
@@ -20120,11 +20550,11 @@ function computeSuppression(depths) {
20120
20550
  }
20121
20551
  return keys.map((k) => (_nullishCoalesce(counts.get(k), () => ( 0))) <= 1);
20122
20552
  }
20123
- var GongmunNumberer = (_class2 = class {
20124
- constructor(numbering) {;_class2.prototype.__init4.call(this);
20553
+ var GongmunNumberer = (_class3 = class {
20554
+ constructor(numbering) {;_class3.prototype.__init5.call(this);
20125
20555
  this.numbering = numbering;
20126
20556
  }
20127
- __init4() {this.counts = []}
20557
+ __init5() {this.counts = []}
20128
20558
  /** depth 항목 하나에 대한 마커. suppress=true면 빈 문자열(부호 없음) */
20129
20559
  next(depth, suppress) {
20130
20560
  this.counts.length = depth + 1;
@@ -20136,82 +20566,58 @@ var GongmunNumberer = (_class2 = class {
20136
20566
  reset() {
20137
20567
  this.counts = [];
20138
20568
  }
20139
- }, _class2);
20569
+ }, _class3);
20140
20570
  function mmToHwpunit(mm) {
20141
20571
  return Math.round(mm * 7200 / 25.4);
20142
20572
  }
20143
20573
 
20144
- // src/hwpx/generator.ts
20145
- var NS_SECTION = "http://www.hancom.co.kr/hwpml/2011/section";
20146
- var NS_PARA = "http://www.hancom.co.kr/hwpml/2011/paragraph";
20147
- var NS_HEAD = "http://www.hancom.co.kr/hwpml/2011/head";
20148
- var NS_CORE = "http://www.hancom.co.kr/hwpml/2011/core";
20149
- var NS_OPF = "http://www.idpf.org/2007/opf/";
20150
- var NS_HPF = "http://www.hancom.co.kr/schema/2011/hpf";
20151
- var NS_OCF = "urn:oasis:names:tc:opendocument:xmlns:container";
20152
- var CHAR_NORMAL = 0;
20153
- var CHAR_BOLD = 1;
20154
- var CHAR_ITALIC = 2;
20155
- var CHAR_BOLD_ITALIC = 3;
20156
- var CHAR_CODE = 4;
20157
- var CHAR_H1 = 5;
20158
- var CHAR_H2 = 6;
20159
- var CHAR_H3 = 7;
20160
- var CHAR_H4 = 8;
20161
- var CHAR_TABLE_HEADER = 9;
20162
- var CHAR_QUOTE = 10;
20163
- var PARA_NORMAL = 0;
20164
- var PARA_H1 = 1;
20165
- var PARA_H2 = 2;
20166
- var PARA_H3 = 3;
20167
- var PARA_H4 = 4;
20168
- var PARA_CODE = 5;
20169
- var PARA_QUOTE = 6;
20170
- var PARA_LIST = 7;
20171
- var DEFAULT_TEXT_COLOR = "#000000";
20172
- function resolveTheme(theme) {
20173
- return {
20174
- h1: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _151 => _151.headingColors, 'optionalAccess', _152 => _152[1]]), () => ( DEFAULT_TEXT_COLOR)),
20175
- h2: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _153 => _153.headingColors, 'optionalAccess', _154 => _154[2]]), () => ( DEFAULT_TEXT_COLOR)),
20176
- h3: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _155 => _155.headingColors, 'optionalAccess', _156 => _156[3]]), () => ( DEFAULT_TEXT_COLOR)),
20177
- h4: _nullishCoalesce(_nullishCoalesce(_optionalChain([theme, 'optionalAccess', _157 => _157.headingColors, 'optionalAccess', _158 => _158[4]]), () => ( _optionalChain([theme, 'optionalAccess', _159 => _159.headingColors, 'optionalAccess', _160 => _160[3]]))), () => ( DEFAULT_TEXT_COLOR)),
20178
- body: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _161 => _161.bodyColor]), () => ( DEFAULT_TEXT_COLOR)),
20179
- quote: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _162 => _162.quoteColor]), () => ( DEFAULT_TEXT_COLOR)),
20180
- /** quoteColor가 명시되었는지 — blockquote charPr 분기에 사용 (baseline 호환) */
20181
- hasQuoteOption: _optionalChain([theme, 'optionalAccess', _163 => _163.quoteColor]) !== void 0,
20182
- tableHeader: _nullishCoalesce(_nullishCoalesce(_optionalChain([theme, 'optionalAccess', _164 => _164.tableHeaderColor]), () => ( _optionalChain([theme, 'optionalAccess', _165 => _165.bodyColor]))), () => ( DEFAULT_TEXT_COLOR)),
20183
- tableHeaderBold: !!_optionalChain([theme, 'optionalAccess', _166 => _166.tableHeaderBold])
20184
- };
20574
+ // src/diff/text-diff.ts
20575
+ function similarity(a, b) {
20576
+ if (a === b) return 1;
20577
+ if (!a || !b) return 0;
20578
+ const maxLen = Math.max(a.length, b.length);
20579
+ if (maxLen === 0) return 1;
20580
+ return 1 - levenshtein(a, b) / maxLen;
20185
20581
  }
20186
- async function markdownToHwpx(markdown, options) {
20187
- const theme = resolveTheme(_optionalChain([options, 'optionalAccess', _167 => _167.theme]));
20188
- const gongmun = _optionalChain([options, 'optionalAccess', _168 => _168.gongmun]) ? resolveGongmun(options.gongmun) : null;
20189
- const blocks = parseMarkdownToBlocks(markdown);
20190
- const sectionXml = blocksToSectionXml(blocks, theme, gongmun);
20191
- const zip = new (0, _jszip2.default)();
20192
- zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
20193
- zip.file("META-INF/container.xml", generateContainerXml());
20194
- zip.file("Contents/content.hpf", generateManifest());
20195
- zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun));
20196
- zip.file("Contents/section0.xml", sectionXml);
20197
- zip.file("Preview/PrvText.txt", buildPrvText(blocks));
20198
- return await zip.generateAsync({ type: "arraybuffer" });
20582
+ function normalizedSimilarity(a, b) {
20583
+ return similarity(normalize(a), normalize(b));
20199
20584
  }
20200
- function buildPrvText(blocks) {
20201
- const lines = [];
20202
- let bytes = 0;
20203
- for (const b of blocks) {
20204
- const text = b.text || (b.rows ? b.rows.map((r) => r.join(" ")).join("\n") : "");
20205
- if (!text) continue;
20206
- lines.push(text);
20207
- bytes += text.length * 3;
20208
- if (bytes > 1024) break;
20585
+ function normalize(s) {
20586
+ return s.replace(/\s+/g, " ").trim();
20587
+ }
20588
+ var MAX_LEVENSHTEIN_LEN = 1e4;
20589
+ function levenshtein(a, b) {
20590
+ if (a.length + b.length > MAX_LEVENSHTEIN_LEN) {
20591
+ const sampleLen = Math.min(500, a.length, b.length);
20592
+ let diffs = 0;
20593
+ for (let i = 0; i < sampleLen; i++) if (a[i] !== b[i]) diffs++;
20594
+ const sampleRate = sampleLen > 0 ? diffs / sampleLen : 1;
20595
+ return Math.abs(a.length - b.length) + Math.round(Math.min(a.length, b.length) * sampleRate);
20209
20596
  }
20210
- return lines.join("\n").slice(0, 1024);
20597
+ if (a.length > b.length) [a, b] = [b, a];
20598
+ const m = a.length;
20599
+ const n = b.length;
20600
+ let prev = Array.from({ length: m + 1 }, (_, i) => i);
20601
+ let curr = new Array(m + 1);
20602
+ for (let j = 1; j <= n; j++) {
20603
+ curr[0] = j;
20604
+ for (let i = 1; i <= m; i++) {
20605
+ if (a[i - 1] === b[j - 1]) {
20606
+ curr[i] = prev[i - 1];
20607
+ } else {
20608
+ curr[i] = 1 + Math.min(prev[i - 1], prev[i], curr[i - 1]);
20609
+ }
20610
+ }
20611
+ ;
20612
+ [prev, curr] = [curr, prev];
20613
+ }
20614
+ return prev[m];
20211
20615
  }
20212
- function parseMarkdownToBlocks(md2) {
20616
+
20617
+ // src/roundtrip/markdown-units.ts
20618
+ function splitMarkdownUnits(md2) {
20213
20619
  const lines = md2.split("\n");
20214
- const blocks = [];
20620
+ const units = [];
20215
20621
  let i = 0;
20216
20622
  while (i < lines.length) {
20217
20623
  const line = lines[i];
@@ -20219,69 +20625,526 @@ function parseMarkdownToBlocks(md2) {
20219
20625
  i++;
20220
20626
  continue;
20221
20627
  }
20222
- const fenceMatch = line.match(/^(`{3,}|~{3,})(.*)$/);
20223
- if (fenceMatch) {
20224
- const fence = fenceMatch[1];
20225
- const lang = fenceMatch[2].trim();
20226
- const codeLines = [];
20227
- i++;
20228
- while (i < lines.length && !lines[i].startsWith(fence)) {
20229
- codeLines.push(lines[i]);
20628
+ if (line.trim().startsWith("<table>")) {
20629
+ const collected2 = [];
20630
+ let depth = 0;
20631
+ while (i < lines.length) {
20632
+ const l = lines[i];
20633
+ collected2.push(l);
20634
+ depth += (l.match(/<table>/g) || []).length;
20635
+ depth -= (l.match(/<\/table>/g) || []).length;
20230
20636
  i++;
20637
+ if (depth <= 0) break;
20231
20638
  }
20232
- if (i < lines.length) i++;
20233
- blocks.push({ type: "code_block", text: codeLines.join("\n"), lang });
20234
- continue;
20235
- }
20236
- if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line.trim())) {
20237
- blocks.push({ type: "hr" });
20238
- i++;
20239
- continue;
20240
- }
20241
- const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
20242
- if (headingMatch) {
20243
- blocks.push({ type: "heading", text: headingMatch[2].trim(), level: headingMatch[1].length });
20244
- i++;
20639
+ units.push({ kind: "html-table", raw: collected2.join("\n"), lines: collected2 });
20245
20640
  continue;
20246
20641
  }
20247
20642
  if (line.trimStart().startsWith("|")) {
20248
- const tableRows = [];
20643
+ const collected2 = [];
20249
20644
  while (i < lines.length && lines[i].trimStart().startsWith("|")) {
20250
- const row = lines[i];
20251
- if (/^[\s|:\-]+$/.test(row)) {
20252
- i++;
20253
- continue;
20254
- }
20255
- const cells = row.split("|").slice(1, -1).map((c) => c.trim());
20256
- if (cells.length > 0) tableRows.push(cells);
20645
+ collected2.push(lines[i]);
20257
20646
  i++;
20258
20647
  }
20259
- if (tableRows.length > 0) blocks.push({ type: "table", rows: tableRows });
20648
+ units.push({ kind: "gfm-table", raw: collected2.join("\n"), lines: collected2 });
20260
20649
  continue;
20261
20650
  }
20262
- if (line.trimStart().startsWith("> ")) {
20263
- const quoteLines = [];
20264
- while (i < lines.length && (lines[i].trimStart().startsWith("> ") || lines[i].trimStart().startsWith(">"))) {
20265
- quoteLines.push(lines[i].replace(/^>\s?/, ""));
20266
- i++;
20267
- }
20268
- for (const ql of quoteLines) {
20269
- blocks.push({ type: "blockquote", text: ql.trim() || "" });
20270
- }
20651
+ if (/^-{3,}\s*$/.test(line.trim())) {
20652
+ units.push({ kind: "separator", raw: line.trim(), lines: [line.trim()] });
20653
+ i++;
20271
20654
  continue;
20272
20655
  }
20273
- const listMatch = line.match(/^(\s*)([-*+]|\d+[.)]) (.+)$/);
20274
- if (listMatch) {
20275
- const indent = Math.floor(listMatch[1].length / 2);
20276
- const ordered = /\d/.test(listMatch[2]);
20277
- blocks.push({ type: "list_item", text: listMatch[3].trim(), ordered, indent });
20656
+ if (/^!\[image\]\([^)]*\)\s*$/.test(line.trim())) {
20657
+ units.push({ kind: "image", raw: line.trim(), lines: [line.trim()] });
20278
20658
  i++;
20279
20659
  continue;
20280
20660
  }
20281
- blocks.push({ type: "paragraph", text: line.trim() });
20282
- i++;
20661
+ const collected = [];
20662
+ while (i < lines.length && lines[i].trim() && !lines[i].trimStart().startsWith("|") && !lines[i].trim().startsWith("<table>")) {
20663
+ collected.push(lines[i].trim());
20664
+ i++;
20665
+ }
20666
+ units.push({ kind: "text", raw: collected.join("\n"), lines: collected });
20283
20667
  }
20284
- return blocks;
20668
+ return units;
20669
+ }
20670
+ function alignUnits(a, b) {
20671
+ const m = a.length, n = b.length;
20672
+ if (m * n > 4e6) {
20673
+ const result2 = [];
20674
+ let pre = 0;
20675
+ while (pre < m && pre < n && a[pre] === b[pre]) {
20676
+ result2.push([pre, pre]);
20677
+ pre++;
20678
+ }
20679
+ let suf = 0;
20680
+ while (suf < m - pre && suf < n - pre && a[m - 1 - suf] === b[n - 1 - suf]) suf++;
20681
+ const aMid = m - pre - suf, bMid = n - pre - suf;
20682
+ if (aMid === bMid) {
20683
+ for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, pre + i2]);
20684
+ } else {
20685
+ for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, null]);
20686
+ for (let j2 = 0; j2 < bMid; j2++) result2.push([null, pre + j2]);
20687
+ }
20688
+ for (let s = suf - 1; s >= 0; s--) result2.push([m - 1 - s, n - 1 - s]);
20689
+ return result2;
20690
+ }
20691
+ const dp = Array.from({ length: m + 1 }, () => new Int32Array(n + 1));
20692
+ for (let i2 = 1; i2 <= m; i2++) {
20693
+ for (let j2 = 1; j2 <= n; j2++) {
20694
+ dp[i2][j2] = a[i2 - 1] === b[j2 - 1] ? dp[i2 - 1][j2 - 1] + 1 : Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
20695
+ }
20696
+ }
20697
+ const matches = [];
20698
+ let i = m, j = n;
20699
+ while (i > 0 && j > 0) {
20700
+ if (a[i - 1] === b[j - 1] && dp[i][j] === dp[i - 1][j - 1] + 1) {
20701
+ matches.push([i - 1, j - 1]);
20702
+ i--;
20703
+ j--;
20704
+ } else if (dp[i - 1][j] >= dp[i][j - 1]) i--;
20705
+ else j--;
20706
+ }
20707
+ matches.reverse();
20708
+ const result = [];
20709
+ let ai = 0, bi = 0;
20710
+ const flushGap = (aEnd, bEnd) => {
20711
+ if (aEnd - ai === bEnd - bi) {
20712
+ while (ai < aEnd) result.push([ai++, bi++]);
20713
+ return;
20714
+ }
20715
+ while (ai < aEnd && bi < bEnd) {
20716
+ const sim = normalizedSimilarity(a[ai], b[bi]);
20717
+ if (sim >= 0.4) {
20718
+ if (aEnd - ai > bEnd - bi && bestSimInRange(a, ai + 1, ai + (aEnd - ai) - (bEnd - bi), b[bi]) > sim) {
20719
+ result.push([ai++, null]);
20720
+ } else if (bEnd - bi > aEnd - ai && bestSimInRange(b, bi + 1, bi + (bEnd - bi) - (aEnd - ai), a[ai]) > sim) {
20721
+ result.push([null, bi++]);
20722
+ } else {
20723
+ result.push([ai++, bi++]);
20724
+ }
20725
+ } else if (aEnd - ai >= bEnd - bi) result.push([ai++, null]);
20726
+ else result.push([null, bi++]);
20727
+ }
20728
+ while (ai < aEnd) result.push([ai++, null]);
20729
+ while (bi < bEnd) result.push([null, bi++]);
20730
+ };
20731
+ for (const [pi, pj] of matches) {
20732
+ flushGap(pi, pj);
20733
+ result.push([ai++, bi++]);
20734
+ }
20735
+ flushGap(m, n);
20736
+ return result;
20737
+ }
20738
+ function bestSimInRange(arr, from, to, target) {
20739
+ let best = 0;
20740
+ for (let k = from; k <= to && k < arr.length; k++) {
20741
+ const s = normalizedSimilarity(arr[k], target);
20742
+ if (s > best) best = s;
20743
+ }
20744
+ return best;
20745
+ }
20746
+ function escapeGfm(text) {
20747
+ return text.replace(/~/g, "\\~");
20748
+ }
20749
+ var HWP_SHAPE_ALT_TEXT_RE = /(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|이등변 삼각형|직각 삼각형|선|직선|곡선|화살표|굵은 화살표|이중 화살표|오각형|육각형|팔각형|별|[4-8]점별|십자|십자형|구름|구름형|마름모|도넛|평행사변형|사다리꼴|부채꼴|호|반원|물결|번개|하트|빗금|블록 화살표|수식|표|그림|개체|그리기\s?개체|묶음\s?개체|글상자|수식\s?개체|OLE\s?개체)\s?입니다\.?/g;
20750
+ function sanitizeText(text) {
20751
+ let result = _chunkQZCP3UWUcjs.mapPuaText.call(void 0, text).replace(/[\u{F0000}-\u{FFFFD}]/gu, "").replace(HWP_SHAPE_ALT_TEXT_RE, "").replace(/ +/g, " ").trim();
20752
+ if (result.length <= 30 && result.includes(" ")) {
20753
+ const tokens = result.split(" ");
20754
+ const koreanSingleCharCount = tokens.filter((t) => t.length === 1 && /[가-힯ㄱ-ㆎ]/.test(t)).length;
20755
+ if (tokens.length >= 3 && koreanSingleCharCount / tokens.length >= 0.7) {
20756
+ result = tokens.join("");
20757
+ }
20758
+ }
20759
+ return result;
20760
+ }
20761
+ function normForMatch(text) {
20762
+ return sanitizeText(text).replace(/\s+/g, " ").trim();
20763
+ }
20764
+ function unescapeGfm(text) {
20765
+ return text.replace(/\\~/g, "~");
20766
+ }
20767
+ function summarize(text) {
20768
+ const t = text.replace(/\s+/g, " ").trim();
20769
+ return t.length > 80 ? t.slice(0, 77) + "..." : t;
20770
+ }
20771
+ function replicateGfmTable(table) {
20772
+ const { cells, rows: numRows, cols: numCols } = table;
20773
+ if (numRows === 0 || numCols === 0) return null;
20774
+ if (numRows === 1 && numCols === 1) return null;
20775
+ if (numCols === 1) return null;
20776
+ const display = Array.from({ length: numRows }, (_, r) => Array.from({ length: numCols }, (_2, c) => ({ text: "", gridR: r, gridC: c })));
20777
+ const skip = /* @__PURE__ */ new Set();
20778
+ for (let r = 0; r < numRows; r++) {
20779
+ for (let c = 0; c < numCols; c++) {
20780
+ if (skip.has(`${r},${c}`)) continue;
20781
+ const cell = _optionalChain([cells, 'access', _162 => _162[r], 'optionalAccess', _163 => _163[c]]);
20782
+ if (!cell) continue;
20783
+ display[r][c] = {
20784
+ text: escapeGfm(sanitizeText(cell.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
20785
+ gridR: r,
20786
+ gridC: c
20787
+ };
20788
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
20789
+ for (let dc = 0; dc < cell.colSpan; dc++) {
20790
+ if (dr === 0 && dc === 0) continue;
20791
+ if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
20792
+ }
20793
+ }
20794
+ c += cell.colSpan - 1;
20795
+ }
20796
+ }
20797
+ const uniqueRows = [];
20798
+ let pendingLabelRow = null;
20799
+ for (let r = 0; r < display.length; r++) {
20800
+ const row = display[r];
20801
+ if (row.every((cell) => cell.text === "")) continue;
20802
+ const nonEmptyCols = row.filter((cell) => cell.text !== "");
20803
+ const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
20804
+ if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
20805
+ if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
20806
+ pendingLabelRow = row;
20807
+ continue;
20808
+ }
20809
+ if (pendingLabelRow) {
20810
+ if (row[0].text === "") row[0] = pendingLabelRow[0];
20811
+ else uniqueRows.push(pendingLabelRow);
20812
+ pendingLabelRow = null;
20813
+ }
20814
+ uniqueRows.push(row);
20815
+ }
20816
+ if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
20817
+ return uniqueRows.length > 0 ? uniqueRows : null;
20818
+ }
20819
+ function parseGfmTable(lines) {
20820
+ const rows = [];
20821
+ for (const line of lines) {
20822
+ const trimmed = line.trim();
20823
+ if (!trimmed.startsWith("|")) continue;
20824
+ const cells = trimmed.split(/(?<!\\)\|/).slice(1, -1).map((c) => c.trim());
20825
+ if (cells.length === 0) continue;
20826
+ if (cells.every((c) => /^:?-{3,}:?$/.test(c))) continue;
20827
+ rows.push(cells);
20828
+ }
20829
+ return rows;
20830
+ }
20831
+ function unescapeGfmCell(text) {
20832
+ return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\~/g, "~");
20833
+ }
20834
+ function replicateCellInnerHtml(cell) {
20835
+ if (_optionalChain([cell, 'access', _164 => _164.blocks, 'optionalAccess', _165 => _165.length])) {
20836
+ return cell.blocks.map((b) => {
20837
+ if (b.type === "table" && b.table) {
20838
+ const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
20839
+ return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
20840
+ }
20841
+ if (b.type === "image" && b.text) return `<img src="${b.text}" alt="image">`;
20842
+ const t = sanitizeText(_nullishCoalesce(b.text, () => ( "")));
20843
+ return t ? t.replace(/\n/g, "<br>") : "";
20844
+ }).filter(Boolean).join("<br>");
20845
+ }
20846
+ return sanitizeText(cell.text).replace(/\n/g, "<br>");
20847
+ }
20848
+ function replicateTableToHtml(table) {
20849
+ const rows = replicateHtmlTable(table);
20850
+ const lines = ["<table>"];
20851
+ for (let r = 0; r < rows.length; r++) {
20852
+ const tag = rows[r].tag;
20853
+ const rowHtml = rows[r].cells.map((cell) => {
20854
+ const attrs = [];
20855
+ if (cell.colSpan > 1) attrs.push(`colspan="${cell.colSpan}"`);
20856
+ if (cell.rowSpan > 1) attrs.push(`rowspan="${cell.rowSpan}"`);
20857
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
20858
+ return `<${tag}${attrStr}>${cell.inner}</${tag}>`;
20859
+ });
20860
+ if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
20861
+ }
20862
+ lines.push("</table>");
20863
+ return lines.join("\n");
20864
+ }
20865
+ function replicateHtmlTable(table) {
20866
+ const { cells, rows: numRows, cols: numCols } = table;
20867
+ const skip = /* @__PURE__ */ new Set();
20868
+ const result = [];
20869
+ for (let r = 0; r < numRows; r++) {
20870
+ const tag = r === 0 ? "th" : "td";
20871
+ const rowCells = [];
20872
+ for (let c = 0; c < numCols; c++) {
20873
+ if (skip.has(`${r},${c}`)) continue;
20874
+ const cell = _optionalChain([cells, 'access', _166 => _166[r], 'optionalAccess', _167 => _167[c]]);
20875
+ if (!cell) continue;
20876
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
20877
+ for (let dc = 0; dc < cell.colSpan; dc++) {
20878
+ if (dr === 0 && dc === 0) continue;
20879
+ if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
20880
+ }
20881
+ }
20882
+ rowCells.push({
20883
+ inner: replicateCellInnerHtml(cell),
20884
+ colSpan: cell.colSpan,
20885
+ rowSpan: cell.rowSpan,
20886
+ gridR: r,
20887
+ gridC: c
20888
+ });
20889
+ }
20890
+ if (rowCells.length) result.push({ tag, cells: rowCells });
20891
+ }
20892
+ return result;
20893
+ }
20894
+ function parseHtmlTable(raw) {
20895
+ const re = /<(\/?)(table|tr|td|th)((?:"[^"]*"|'[^']*'|[^>"'])*?)>/gi;
20896
+ let depth = 0;
20897
+ let currentRow = null;
20898
+ let cellStart = -1;
20899
+ let cellInfo = null;
20900
+ const rows = [];
20901
+ let m;
20902
+ while ((m = re.exec(raw)) !== null) {
20903
+ const isClose = m[1] === "/";
20904
+ const tag = m[2].toLowerCase();
20905
+ const attrs = m[3] || "";
20906
+ if (tag === "table") {
20907
+ depth += isClose ? -1 : 1;
20908
+ if (depth < 0) return null;
20909
+ continue;
20910
+ }
20911
+ if (depth !== 1) continue;
20912
+ if (tag === "tr") {
20913
+ if (!isClose) currentRow = [];
20914
+ else if (currentRow) {
20915
+ rows.push({ tag: rows.length === 0 ? "th" : "td", cells: currentRow });
20916
+ currentRow = null;
20917
+ }
20918
+ } else {
20919
+ if (!isClose) {
20920
+ const cs = parseInt(_optionalChain([attrs, 'access', _168 => _168.match, 'call', _169 => _169(/colspan\s*=\s*"(\d+)"/i), 'optionalAccess', _170 => _170[1]]) || "1", 10);
20921
+ const rs = parseInt(_optionalChain([attrs, 'access', _171 => _171.match, 'call', _172 => _172(/rowspan\s*=\s*"(\d+)"/i), 'optionalAccess', _173 => _173[1]]) || "1", 10);
20922
+ cellStart = m.index + m[0].length;
20923
+ cellInfo = { colSpan: isNaN(cs) ? 1 : cs, rowSpan: isNaN(rs) ? 1 : rs };
20924
+ } else if (cellStart >= 0 && cellInfo && currentRow) {
20925
+ currentRow.push({ inner: raw.slice(cellStart, m.index), colSpan: cellInfo.colSpan, rowSpan: cellInfo.rowSpan });
20926
+ cellStart = -1;
20927
+ cellInfo = null;
20928
+ }
20929
+ }
20930
+ }
20931
+ if (depth !== 0) return null;
20932
+ return rows;
20933
+ }
20934
+ var AUTONUM_PREFIX_RE = /^(?:[0-90-9a-zA-Z가-힣]{1,6}[.)\]:]|[([][0-90-9a-zA-Z가-힣]{1,6}[)\]][.:]?|[ⅰ-ⅹⅠ-Ⅹ①-⑮][.)\]:]?)$/u;
20935
+ function htmlCellInnerToLines(inner) {
20936
+ let hadNonText = false;
20937
+ let work = inner;
20938
+ if (/<table[\s>]/i.test(work)) {
20939
+ hadNonText = true;
20940
+ work = removeNestedTables(work);
20941
+ }
20942
+ if (/<img\s/i.test(work)) {
20943
+ hadNonText = true;
20944
+ work = work.replace(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi, "");
20945
+ }
20946
+ const lines = work.split(/<br\s*\/?>/gi).map((s) => s.trim()).filter((s) => s.length > 0);
20947
+ return { lines, hadNonText };
20948
+ }
20949
+ function extractTopLevelTables(html) {
20950
+ const result = [];
20951
+ let depth = 0;
20952
+ let start = -1;
20953
+ const re = /<(\/?)table(?:[\s>]|>)/gi;
20954
+ let m;
20955
+ while ((m = re.exec(html)) !== null) {
20956
+ if (m[1] !== "/") {
20957
+ if (depth === 0) start = m.index;
20958
+ depth++;
20959
+ } else {
20960
+ depth--;
20961
+ if (depth === 0 && start >= 0) {
20962
+ result.push(html.slice(start, m.index + m[0].length));
20963
+ start = -1;
20964
+ }
20965
+ if (depth < 0) depth = 0;
20966
+ }
20967
+ }
20968
+ return result;
20969
+ }
20970
+ function removeNestedTables(html) {
20971
+ let result = "";
20972
+ let depth = 0;
20973
+ const re = /<(\/?)table(?:[\s>]|>)/gi;
20974
+ let last = 0;
20975
+ let m;
20976
+ while ((m = re.exec(html)) !== null) {
20977
+ if (m[1] !== "/") {
20978
+ if (depth === 0) result += html.slice(last, m.index);
20979
+ depth++;
20980
+ } else {
20981
+ depth--;
20982
+ if (depth === 0) last = m.index + m[0].length;
20983
+ if (depth < 0) depth = 0;
20984
+ }
20985
+ }
20986
+ if (depth === 0) result += html.slice(last);
20987
+ return result;
20988
+ }
20989
+
20990
+ // src/hwpx/generator.ts
20991
+ var NS_SECTION = "http://www.hancom.co.kr/hwpml/2011/section";
20992
+ var NS_PARA = "http://www.hancom.co.kr/hwpml/2011/paragraph";
20993
+ var NS_HEAD = "http://www.hancom.co.kr/hwpml/2011/head";
20994
+ var NS_CORE = "http://www.hancom.co.kr/hwpml/2011/core";
20995
+ var NS_OPF = "http://www.idpf.org/2007/opf/";
20996
+ var NS_HPF = "http://www.hancom.co.kr/schema/2011/hpf";
20997
+ var NS_OCF = "urn:oasis:names:tc:opendocument:xmlns:container";
20998
+ var CHAR_NORMAL = 0;
20999
+ var CHAR_BOLD = 1;
21000
+ var CHAR_ITALIC = 2;
21001
+ var CHAR_BOLD_ITALIC = 3;
21002
+ var CHAR_CODE = 4;
21003
+ var CHAR_H1 = 5;
21004
+ var CHAR_H2 = 6;
21005
+ var CHAR_H3 = 7;
21006
+ var CHAR_H4 = 8;
21007
+ var CHAR_TABLE_HEADER = 9;
21008
+ var CHAR_QUOTE = 10;
21009
+ var PARA_NORMAL = 0;
21010
+ var PARA_H1 = 1;
21011
+ var PARA_H2 = 2;
21012
+ var PARA_H3 = 3;
21013
+ var PARA_H4 = 4;
21014
+ var PARA_CODE = 5;
21015
+ var PARA_QUOTE = 6;
21016
+ var PARA_LIST = 7;
21017
+ var DEFAULT_TEXT_COLOR = "#000000";
21018
+ function resolveTheme(theme) {
21019
+ return {
21020
+ h1: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _174 => _174.headingColors, 'optionalAccess', _175 => _175[1]]), () => ( DEFAULT_TEXT_COLOR)),
21021
+ h2: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _176 => _176.headingColors, 'optionalAccess', _177 => _177[2]]), () => ( DEFAULT_TEXT_COLOR)),
21022
+ h3: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _178 => _178.headingColors, 'optionalAccess', _179 => _179[3]]), () => ( DEFAULT_TEXT_COLOR)),
21023
+ h4: _nullishCoalesce(_nullishCoalesce(_optionalChain([theme, 'optionalAccess', _180 => _180.headingColors, 'optionalAccess', _181 => _181[4]]), () => ( _optionalChain([theme, 'optionalAccess', _182 => _182.headingColors, 'optionalAccess', _183 => _183[3]]))), () => ( DEFAULT_TEXT_COLOR)),
21024
+ body: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _184 => _184.bodyColor]), () => ( DEFAULT_TEXT_COLOR)),
21025
+ quote: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _185 => _185.quoteColor]), () => ( DEFAULT_TEXT_COLOR)),
21026
+ /** quoteColor가 명시되었는지 — blockquote charPr 분기에 사용 (baseline 호환) */
21027
+ hasQuoteOption: _optionalChain([theme, 'optionalAccess', _186 => _186.quoteColor]) !== void 0,
21028
+ tableHeader: _nullishCoalesce(_nullishCoalesce(_optionalChain([theme, 'optionalAccess', _187 => _187.tableHeaderColor]), () => ( _optionalChain([theme, 'optionalAccess', _188 => _188.bodyColor]))), () => ( DEFAULT_TEXT_COLOR)),
21029
+ tableHeaderBold: !!_optionalChain([theme, 'optionalAccess', _189 => _189.tableHeaderBold])
21030
+ };
21031
+ }
21032
+ async function markdownToHwpx(markdown, options) {
21033
+ const theme = resolveTheme(_optionalChain([options, 'optionalAccess', _190 => _190.theme]));
21034
+ const gongmun = _optionalChain([options, 'optionalAccess', _191 => _191.gongmun]) ? resolveGongmun(options.gongmun) : null;
21035
+ const blocks = parseMarkdownToBlocks(markdown);
21036
+ const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
21037
+ const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
21038
+ const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit);
21039
+ const zip = new (0, _jszip2.default)();
21040
+ zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
21041
+ zip.file("META-INF/container.xml", generateContainerXml());
21042
+ zip.file("Contents/content.hpf", generateManifest());
21043
+ zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, _nullishCoalesce(_optionalChain([fit, 'optionalAccess', _192 => _192.variants]), () => ( []))));
21044
+ zip.file("Contents/section0.xml", sectionXml);
21045
+ zip.file("Preview/PrvText.txt", buildPrvText(blocks));
21046
+ return await zip.generateAsync({ type: "arraybuffer" });
21047
+ }
21048
+ function buildPrvText(blocks) {
21049
+ const lines = [];
21050
+ let bytes = 0;
21051
+ for (const b of blocks) {
21052
+ let text = b.text || (b.rows ? b.rows.map((r) => r.join(" ")).join("\n") : "");
21053
+ if (b.type === "html_table") text = text.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
21054
+ if (!text) continue;
21055
+ lines.push(text);
21056
+ bytes += text.length * 3;
21057
+ if (bytes > 1024) break;
21058
+ }
21059
+ return lines.join("\n").slice(0, 1024);
21060
+ }
21061
+ function parseMarkdownToBlocks(md2) {
21062
+ const lines = md2.split("\n");
21063
+ const blocks = [];
21064
+ let i = 0;
21065
+ while (i < lines.length) {
21066
+ const line = lines[i];
21067
+ if (!line.trim()) {
21068
+ i++;
21069
+ continue;
21070
+ }
21071
+ const fenceMatch = line.match(/^(`{3,}|~{3,})(.*)$/);
21072
+ if (fenceMatch) {
21073
+ const fence = fenceMatch[1];
21074
+ const lang = fenceMatch[2].trim();
21075
+ const codeLines = [];
21076
+ i++;
21077
+ while (i < lines.length && !lines[i].startsWith(fence)) {
21078
+ codeLines.push(lines[i]);
21079
+ i++;
21080
+ }
21081
+ if (i < lines.length) i++;
21082
+ blocks.push({ type: "code_block", text: codeLines.join("\n"), lang });
21083
+ continue;
21084
+ }
21085
+ if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line.trim())) {
21086
+ blocks.push({ type: "hr" });
21087
+ i++;
21088
+ continue;
21089
+ }
21090
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
21091
+ if (headingMatch) {
21092
+ blocks.push({ type: "heading", text: headingMatch[2].trim(), level: headingMatch[1].length });
21093
+ i++;
21094
+ continue;
21095
+ }
21096
+ if (/^<table[\s>]/i.test(line.trimStart())) {
21097
+ const htmlLines = [];
21098
+ let depth = 0;
21099
+ while (i < lines.length) {
21100
+ const l = lines[i];
21101
+ htmlLines.push(l);
21102
+ depth += (_nullishCoalesce(l.match(/<table[\s>]/gi), () => ( []))).length;
21103
+ depth -= (_nullishCoalesce(l.match(/<\/table>/gi), () => ( []))).length;
21104
+ i++;
21105
+ if (depth <= 0) break;
21106
+ }
21107
+ blocks.push({ type: "html_table", text: htmlLines.join("\n") });
21108
+ continue;
21109
+ }
21110
+ if (line.trimStart().startsWith("|")) {
21111
+ const tableRows = [];
21112
+ while (i < lines.length && lines[i].trimStart().startsWith("|")) {
21113
+ const row = lines[i];
21114
+ if (/^[\s|:\-]+$/.test(row)) {
21115
+ i++;
21116
+ continue;
21117
+ }
21118
+ const cells = row.split("|").slice(1, -1).map((c) => c.trim());
21119
+ if (cells.length > 0) tableRows.push(cells);
21120
+ i++;
21121
+ }
21122
+ if (tableRows.length > 0) blocks.push({ type: "table", rows: tableRows });
21123
+ continue;
21124
+ }
21125
+ if (line.trimStart().startsWith("> ")) {
21126
+ const quoteLines = [];
21127
+ while (i < lines.length && (lines[i].trimStart().startsWith("> ") || lines[i].trimStart().startsWith(">"))) {
21128
+ quoteLines.push(lines[i].replace(/^>\s?/, ""));
21129
+ i++;
21130
+ }
21131
+ for (const ql of quoteLines) {
21132
+ blocks.push({ type: "blockquote", text: ql.trim() || "" });
21133
+ }
21134
+ continue;
21135
+ }
21136
+ const listMatch = line.match(/^(\s*)([-*+]|\d+[.)]) (.+)$/);
21137
+ if (listMatch) {
21138
+ const indent = Math.floor(listMatch[1].length / 2);
21139
+ const ordered = /\d/.test(listMatch[2]);
21140
+ blocks.push({ type: "list_item", text: listMatch[3].trim(), ordered, indent });
21141
+ i++;
21142
+ continue;
21143
+ }
21144
+ blocks.push({ type: "paragraph", text: line.trim() });
21145
+ i++;
21146
+ }
21147
+ return blocks;
20285
21148
  }
20286
21149
  function parseInlineMarkdown(text) {
20287
21150
  text = text.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1");
@@ -20325,18 +21188,19 @@ function spanToCharPrId(span) {
20325
21188
  function escapeXml(text) {
20326
21189
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
20327
21190
  }
20328
- function generateRuns(text, defaultCharPr = CHAR_NORMAL) {
21191
+ function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
20329
21192
  const spans = parseInlineMarkdown(text);
20330
21193
  return spans.map((span) => {
20331
- const charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
21194
+ let charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
21195
+ if (mapCharId) charId = mapCharId(charId);
20332
21196
  return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
20333
21197
  }).join("");
20334
21198
  }
20335
- function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL) {
21199
+ function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId) {
20336
21200
  if (paraPrId === PARA_CODE) {
20337
21201
  return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
20338
21202
  }
20339
- const runs = generateRuns(text, charPrId);
21203
+ const runs = generateRuns(text, charPrId, mapCharId);
20340
21204
  return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0">${runs}</hp:p>`;
20341
21205
  }
20342
21206
  function headingParaPrId(level) {
@@ -20376,7 +21240,7 @@ function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_C
20376
21240
  const boldAttr = bold ? ` bold="1"` : "";
20377
21241
  const italicAttr = italic ? ` italic="1"` : "";
20378
21242
  const effFont = bold ? 2 : fontId;
20379
- return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="0"${boldAttr}${italicAttr}>
21243
+ return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
20380
21244
  <hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
20381
21245
  <hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
20382
21246
  <hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
@@ -20395,13 +21259,58 @@ function paraPr(id, opts = {}) {
20395
21259
  <hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
20396
21260
  <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>
20397
21261
  <hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
20398
- <hh:border borderFillIDRef="0" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0"/>
21262
+ <hh:border borderFillIDRef="1" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0"/>
20399
21263
  </hh:paraPr>`;
20400
21264
  }
20401
21265
  var GONGMUN_LIST_BASE = 8;
20402
21266
  var GONGMUN_LIST_LEVELS = 8;
20403
21267
  var GONGMUN_CENTER = GONGMUN_LIST_BASE + GONGMUN_LIST_LEVELS;
20404
- function buildCharProperties(theme, gongmun) {
21268
+ var CHAR_VARIANT_BASE = 11;
21269
+ var GONGMUN_BODY_RATIO = 95;
21270
+ function plainRenderText(text) {
21271
+ return parseInlineMarkdown(text).map((s) => s.text).join("");
21272
+ }
21273
+ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
21274
+ const minRatio = gongmun.autoFitMinRatio;
21275
+ if (minRatio === null || minRatio >= GONGMUN_BODY_RATIO) return null;
21276
+ const pageW = 59528 - mmToHwpunit(gongmun.margins.left) - mmToHwpunit(gongmun.margins.right);
21277
+ const ratioByBlock = /* @__PURE__ */ new Map();
21278
+ const variants = [];
21279
+ for (let i = 0; i < blocks.length; i++) {
21280
+ const block = blocks[i];
21281
+ let text;
21282
+ let firstW;
21283
+ let contW;
21284
+ if (block.type === "list_item" && gongmunList.has(i)) {
21285
+ const { marker, depth } = gongmunList.get(i);
21286
+ const content = plainRenderText(block.text || "");
21287
+ text = marker ? `${marker} ${content}` : content;
21288
+ const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
21289
+ firstW = pageW - left - Math.max(indent, 0);
21290
+ contW = pageW - left - Math.max(-indent, 0);
21291
+ } else if (block.type === "paragraph") {
21292
+ const raw = (block.text || "").trim();
21293
+ if (/^<center>[\s\S]*<\/center>$/i.test(raw)) continue;
21294
+ text = plainRenderText(raw);
21295
+ firstW = contW = pageW;
21296
+ } else {
21297
+ continue;
21298
+ }
21299
+ if (!text) continue;
21300
+ const r = fitRatioForFewerLines(text, firstW, contW, gongmun.bodyHeight, GONGMUN_BODY_RATIO, minRatio);
21301
+ if (r === null) continue;
21302
+ ratioByBlock.set(i, r);
21303
+ if (!variants.includes(r)) variants.push(r);
21304
+ }
21305
+ return ratioByBlock.size > 0 ? { ratioByBlock, variants } : null;
21306
+ }
21307
+ function variantMapper(fit, blockIdx) {
21308
+ const r = fit.ratioByBlock.get(blockIdx);
21309
+ if (r === void 0) return void 0;
21310
+ const vi = fit.variants.indexOf(r);
21311
+ return (id) => id >= 0 && id <= 3 ? CHAR_VARIANT_BASE + vi * 4 + id : id;
21312
+ }
21313
+ function buildCharProperties(theme, gongmun, ratioVariants = []) {
20405
21314
  let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
20406
21315
  if (gongmun) {
20407
21316
  body = gongmun.bodyHeight;
@@ -20411,7 +21320,7 @@ function buildCharProperties(theme, gongmun) {
20411
21320
  h3 = body;
20412
21321
  h4 = Math.max(body - 100, 1300);
20413
21322
  }
20414
- const bodyRatio = gongmun ? 95 : 100;
21323
+ const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
20415
21324
  const rows = [
20416
21325
  charPr(0, body, false, false, 0, theme.body, bodyRatio),
20417
21326
  charPr(1, body, true, false, 0, theme.body, bodyRatio),
@@ -20425,6 +21334,14 @@ function buildCharProperties(theme, gongmun) {
20425
21334
  charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, 0, theme.tableHeader),
20426
21335
  charPr(CHAR_QUOTE, body, false, true, 0, theme.quote)
20427
21336
  ];
21337
+ for (const r of ratioVariants) {
21338
+ rows.push(
21339
+ charPr(rows.length, body, false, false, 0, theme.body, r),
21340
+ charPr(rows.length + 1, body, true, false, 0, theme.body, r),
21341
+ charPr(rows.length + 2, body, false, true, 0, theme.body, r),
21342
+ charPr(rows.length + 3, body, true, true, 0, theme.body, r)
21343
+ );
21344
+ }
20428
21345
  return `<hh:charProperties itemCnt="${rows.length}">
20429
21346
  ${rows.join("\n")}
20430
21347
  </hh:charProperties>`;
@@ -20467,9 +21384,9 @@ ${base2.join("\n")}
20467
21384
  ${base.join("\n")}
20468
21385
  </hh:paraProperties>`;
20469
21386
  }
20470
- function generateHeaderXml(theme, gongmun) {
20471
- const bodyFace = _optionalChain([gongmun, 'optionalAccess', _169 => _169.bodyFont]) === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5";
20472
- const charPropsXml = buildCharProperties(theme, gongmun);
21387
+ function generateHeaderXml(theme, gongmun, ratioVariants = []) {
21388
+ const bodyFace = _optionalChain([gongmun, 'optionalAccess', _193 => _193.bodyFont]) === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5";
21389
+ const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants);
20473
21390
  const paraPropsXml = buildParaProperties(gongmun);
20474
21391
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
20475
21392
  <hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" xmlns:hc="${NS_CORE}" version="1.4" secCnt="1">
@@ -20525,25 +21442,21 @@ function generateHeaderXml(theme, gongmun) {
20525
21442
  </hh:fontface>
20526
21443
  </hh:fontfaces>
20527
21444
  <hh:borderFills itemCnt="2">
20528
- <hh:borderFill id="0" threeD="0" shadow="0" centerLine="0" breakCellSeparateLine="0">
21445
+ <hh:borderFill id="1" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
20529
21446
  <hh:slash type="NONE" Crooked="0" isCounter="0"/>
20530
21447
  <hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
20531
21448
  <hh:leftBorder type="NONE" width="0.1 mm" color="#000000"/>
20532
21449
  <hh:rightBorder type="NONE" width="0.1 mm" color="#000000"/>
20533
21450
  <hh:topBorder type="NONE" width="0.1 mm" color="#000000"/>
20534
21451
  <hh:bottomBorder type="NONE" width="0.1 mm" color="#000000"/>
20535
- <hh:diagonal type="NONE" width="0.1 mm" color="#000000"/>
20536
- <hh:fillInfo/>
20537
21452
  </hh:borderFill>
20538
- <hh:borderFill id="1" threeD="0" shadow="0" centerLine="0" breakCellSeparateLine="0">
21453
+ <hh:borderFill id="2" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
20539
21454
  <hh:slash type="NONE" Crooked="0" isCounter="0"/>
20540
21455
  <hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
20541
21456
  <hh:leftBorder type="SOLID" width="0.12 mm" color="#000000"/>
20542
21457
  <hh:rightBorder type="SOLID" width="0.12 mm" color="#000000"/>
20543
21458
  <hh:topBorder type="SOLID" width="0.12 mm" color="#000000"/>
20544
21459
  <hh:bottomBorder type="SOLID" width="0.12 mm" color="#000000"/>
20545
- <hh:diagonal type="NONE" width="0.1 mm" color="#000000"/>
20546
- <hh:fillInfo/>
20547
21460
  </hh:borderFill>
20548
21461
  </hh:borderFills>
20549
21462
  ${charPropsXml}
@@ -20590,14 +21503,74 @@ function generateTable(rows, theme) {
20590
21503
  const tdElements = cells.map((cell, colIdx) => {
20591
21504
  const runs = generateRuns(cell, headerCharPr);
20592
21505
  const p = `<hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p>`;
20593
- return `<hp:tc name="" header="${isHeaderRow ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="1"><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="${cellW}" height="${cellH}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
21506
+ return `<hp:tc name="" header="${isHeaderRow ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="2"><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="${cellW}" height="${cellH}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
20594
21507
  }).join("");
20595
21508
  return `<hp:tr>${tdElements}</hp:tr>`;
20596
21509
  }).join("");
20597
21510
  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;
20598
- const tbl = `<hp:tbl id="${tblId}" zOrder="0" numberingType="TABLE" pageBreak="CELL" repeatHeader="0" rowCnt="${rowCnt}" colCnt="${colCnt}" cellSpacing="0" borderFillIDRef="1" noShading="0">${tblInner}</hp:tbl>`;
21511
+ 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>`;
20599
21512
  return `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${tbl}</hp:run></hp:p>`;
20600
21513
  }
21514
+ function layoutHtmlRows(rows) {
21515
+ const occupied = /* @__PURE__ */ new Set();
21516
+ const placed = [];
21517
+ let colCnt = 0;
21518
+ for (let r = 0; r < rows.length; r++) {
21519
+ let c = 0;
21520
+ for (const cell of rows[r].cells) {
21521
+ while (occupied.has(`${r},${c}`)) c++;
21522
+ const colSpan = Math.max(1, cell.colSpan);
21523
+ const rowSpan = Math.max(1, cell.rowSpan);
21524
+ placed.push({ r, c, colSpan, rowSpan, inner: cell.inner, isHeader: rows[r].tag === "th" });
21525
+ for (let dr = 0; dr < rowSpan; dr++) {
21526
+ for (let dc = 0; dc < colSpan; dc++) occupied.add(`${r + dr},${c + dc}`);
21527
+ }
21528
+ c += colSpan;
21529
+ colCnt = Math.max(colCnt, c);
21530
+ }
21531
+ }
21532
+ return { placed, rowCnt: rows.length, colCnt };
21533
+ }
21534
+ function unescapeHtml(s) {
21535
+ return s.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&");
21536
+ }
21537
+ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3) {
21538
+ const rows = parseHtmlTable(rawHtml);
21539
+ if (!rows || rows.length === 0) return null;
21540
+ const { placed, rowCnt, colCnt } = layoutHtmlRows(rows);
21541
+ if (rowCnt === 0 || colCnt === 0) return null;
21542
+ const colW = Math.floor(totalWidth / colCnt);
21543
+ const cellH = 1500;
21544
+ const tblW = colW * colCnt;
21545
+ const tblId = nextTableId();
21546
+ const useHeaderStyle = theme.tableHeader !== theme.body || theme.tableHeaderBold;
21547
+ const tcXmls = placed.map((cell) => {
21548
+ const headerCharPr = cell.isHeader && useHeaderStyle ? CHAR_TABLE_HEADER : CHAR_NORMAL;
21549
+ const { lines } = htmlCellInnerToLines(cell.inner);
21550
+ const paras = lines.map(
21551
+ (line) => `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="${headerCharPr}"><hp:t>${escapeXml(unescapeHtml(line))}</hp:t></hp:run></hp:p>`
21552
+ );
21553
+ let nestedH = 0;
21554
+ for (const nested of extractTopLevelTables(cell.inner)) {
21555
+ const nestedXml = generateHtmlTableXml(nested, theme, Math.max(colW * cell.colSpan - 1020, 4e3));
21556
+ if (nestedXml) {
21557
+ paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${nestedXml}</hp:run></hp:p>`);
21558
+ nestedH += (_nullishCoalesce(nested.match(/<tr[\s>]/gi), () => ( []))).length * cellH + 300;
21559
+ }
21560
+ }
21561
+ if (paras.length === 0) {
21562
+ paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="${headerCharPr}"><hp:t></hp:t></hp:run></hp:p>`);
21563
+ }
21564
+ const cellHeight = Math.max(cellH * cell.rowSpan, Math.max(lines.length, 1) * 800 + nestedH);
21565
+ return `<hp:tc name="" header="${cell.isHeader ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="2"><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="${colW * cell.colSpan}" height="${cellHeight}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
21566
+ });
21567
+ const trXmls = [];
21568
+ for (let r = 0; r < rowCnt; r++) {
21569
+ const rowTcs = tcXmls.filter((_, i) => placed[i].r === r);
21570
+ trXmls.push(`<hp:tr>${rowTcs.join("")}</hp:tr>`);
21571
+ }
21572
+ 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>`;
21573
+ }
20601
21574
  function precomputeGongmunList(blocks, gongmun) {
20602
21575
  const result = /* @__PURE__ */ new Map();
20603
21576
  let i = 0;
@@ -20621,12 +21594,11 @@ function precomputeGongmunList(blocks, gongmun) {
20621
21594
  }
20622
21595
  return result;
20623
21596
  }
20624
- function blocksToSectionXml(blocks, theme, gongmun) {
21597
+ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null) {
20625
21598
  const paraXmls = [];
20626
21599
  let isFirst = true;
20627
21600
  const orderedCounters = {};
20628
21601
  let prevWasOrdered = false;
20629
- const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
20630
21602
  for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
20631
21603
  const block = blocks[blockIdx];
20632
21604
  let xml = "";
@@ -20648,7 +21620,7 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20648
21620
  if (ctr) {
20649
21621
  xml = generateParagraph(ctr[1].trim(), GONGMUN_CENTER);
20650
21622
  } else {
20651
- xml = generateParagraph(block.text || "");
21623
+ xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx) : void 0);
20652
21624
  }
20653
21625
  break;
20654
21626
  }
@@ -20667,12 +21639,12 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20667
21639
  case "list_item": {
20668
21640
  if (gongmun && gongmunList) {
20669
21641
  const info = gongmunList.get(blockIdx);
20670
- const depth = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _170 => _170.depth]), () => ( 0));
20671
- const marker2 = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _171 => _171.marker]), () => ( ""));
21642
+ const depth = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _194 => _194.depth]), () => ( 0));
21643
+ const marker2 = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _195 => _195.marker]), () => ( ""));
20672
21644
  const content = block.text || "";
20673
21645
  const text = marker2 ? `${marker2} ${content}` : content;
20674
21646
  const listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
20675
- xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr);
21647
+ xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr, fit ? variantMapper(fit, blockIdx) : void 0);
20676
21648
  break;
20677
21649
  }
20678
21650
  const indent = block.indent || 0;
@@ -20708,6 +21680,21 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20708
21680
  xml = generateTable(block.rows, theme);
20709
21681
  }
20710
21682
  break;
21683
+ case "html_table": {
21684
+ const tbl = generateHtmlTableXml(block.text || "", theme);
21685
+ if (tbl) {
21686
+ if (isFirst) {
21687
+ const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
21688
+ paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
21689
+ isFirst = false;
21690
+ }
21691
+ xml = `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${tbl}</hp:run></hp:p>`;
21692
+ } else {
21693
+ const plain = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
21694
+ xml = plain ? generateParagraph(plain) : "";
21695
+ }
21696
+ break;
21697
+ }
20711
21698
  }
20712
21699
  if (!xml) continue;
20713
21700
  if (isFirst && block.type !== "table") {
@@ -20728,49 +21715,6 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20728
21715
  </hs:sec>`;
20729
21716
  }
20730
21717
 
20731
- // src/diff/text-diff.ts
20732
- function similarity(a, b) {
20733
- if (a === b) return 1;
20734
- if (!a || !b) return 0;
20735
- const maxLen = Math.max(a.length, b.length);
20736
- if (maxLen === 0) return 1;
20737
- return 1 - levenshtein(a, b) / maxLen;
20738
- }
20739
- function normalizedSimilarity(a, b) {
20740
- return similarity(normalize(a), normalize(b));
20741
- }
20742
- function normalize(s) {
20743
- return s.replace(/\s+/g, " ").trim();
20744
- }
20745
- var MAX_LEVENSHTEIN_LEN = 1e4;
20746
- function levenshtein(a, b) {
20747
- if (a.length + b.length > MAX_LEVENSHTEIN_LEN) {
20748
- const sampleLen = Math.min(500, a.length, b.length);
20749
- let diffs = 0;
20750
- for (let i = 0; i < sampleLen; i++) if (a[i] !== b[i]) diffs++;
20751
- const sampleRate = sampleLen > 0 ? diffs / sampleLen : 1;
20752
- return Math.abs(a.length - b.length) + Math.round(Math.min(a.length, b.length) * sampleRate);
20753
- }
20754
- if (a.length > b.length) [a, b] = [b, a];
20755
- const m = a.length;
20756
- const n = b.length;
20757
- let prev = Array.from({ length: m + 1 }, (_, i) => i);
20758
- let curr = new Array(m + 1);
20759
- for (let j = 1; j <= n; j++) {
20760
- curr[0] = j;
20761
- for (let i = 1; i <= m; i++) {
20762
- if (a[i - 1] === b[j - 1]) {
20763
- curr[i] = prev[i - 1];
20764
- } else {
20765
- curr[i] = 1 + Math.min(prev[i - 1], prev[i], curr[i - 1]);
20766
- }
20767
- }
20768
- ;
20769
- [prev, curr] = [curr, prev];
20770
- }
20771
- return prev[m];
20772
- }
20773
-
20774
21718
  // src/diff/compare.ts
20775
21719
  var SIMILARITY_THRESHOLD = 0.4;
20776
21720
  async function compare(bufferA, bufferB, options) {
@@ -20897,311 +21841,242 @@ function diffTableCells(a, b) {
20897
21841
  if (cellA === void 0) type = "added";
20898
21842
  else if (cellB === void 0) type = "removed";
20899
21843
  else if (cellA === cellB) type = "unchanged";
20900
- else type = "modified";
20901
- row.push({ type, before: cellA, after: cellB });
20902
- }
20903
- result.push(row);
20904
- }
20905
- return result;
20906
- }
20907
-
20908
- // src/roundtrip/patcher.ts
20909
-
20910
-
20911
- // src/roundtrip/markdown-units.ts
20912
- function splitMarkdownUnits(md2) {
20913
- const lines = md2.split("\n");
20914
- const units = [];
20915
- let i = 0;
20916
- while (i < lines.length) {
20917
- const line = lines[i];
20918
- if (!line.trim()) {
20919
- i++;
20920
- continue;
20921
- }
20922
- if (line.trim().startsWith("<table>")) {
20923
- const collected2 = [];
20924
- let depth = 0;
20925
- while (i < lines.length) {
20926
- const l = lines[i];
20927
- collected2.push(l);
20928
- depth += (l.match(/<table>/g) || []).length;
20929
- depth -= (l.match(/<\/table>/g) || []).length;
20930
- i++;
20931
- if (depth <= 0) break;
20932
- }
20933
- units.push({ kind: "html-table", raw: collected2.join("\n"), lines: collected2 });
20934
- continue;
20935
- }
20936
- if (line.trimStart().startsWith("|")) {
20937
- const collected2 = [];
20938
- while (i < lines.length && lines[i].trimStart().startsWith("|")) {
20939
- collected2.push(lines[i]);
20940
- i++;
20941
- }
20942
- units.push({ kind: "gfm-table", raw: collected2.join("\n"), lines: collected2 });
20943
- continue;
20944
- }
20945
- if (/^-{3,}\s*$/.test(line.trim())) {
20946
- units.push({ kind: "separator", raw: line.trim(), lines: [line.trim()] });
20947
- i++;
20948
- continue;
20949
- }
20950
- if (/^!\[image\]\([^)]*\)\s*$/.test(line.trim())) {
20951
- units.push({ kind: "image", raw: line.trim(), lines: [line.trim()] });
20952
- i++;
20953
- continue;
20954
- }
20955
- const collected = [];
20956
- while (i < lines.length && lines[i].trim() && !lines[i].trimStart().startsWith("|") && !lines[i].trim().startsWith("<table>")) {
20957
- collected.push(lines[i].trim());
20958
- i++;
20959
- }
20960
- units.push({ kind: "text", raw: collected.join("\n"), lines: collected });
20961
- }
20962
- return units;
20963
- }
20964
- function escapeGfm(text) {
20965
- return text.replace(/~/g, "\\~");
20966
- }
20967
- var HWP_SHAPE_ALT_TEXT_RE = /(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|이등변 삼각형|직각 삼각형|선|직선|곡선|화살표|굵은 화살표|이중 화살표|오각형|육각형|팔각형|별|[4-8]점별|십자|십자형|구름|구름형|마름모|도넛|평행사변형|사다리꼴|부채꼴|호|반원|물결|번개|하트|빗금|블록 화살표|수식|표|그림|개체|그리기\s?개체|묶음\s?개체|글상자|수식\s?개체|OLE\s?개체)\s?입니다\.?/g;
20968
- function sanitizeText(text) {
20969
- let result = _chunk53XNKPN6cjs.mapPuaText.call(void 0, text).replace(/[\u{F0000}-\u{FFFFD}]/gu, "").replace(HWP_SHAPE_ALT_TEXT_RE, "").replace(/ +/g, " ").trim();
20970
- if (result.length <= 30 && result.includes(" ")) {
20971
- const tokens = result.split(" ");
20972
- const koreanSingleCharCount = tokens.filter((t) => t.length === 1 && /[가-힯ㄱ-ㆎ]/.test(t)).length;
20973
- if (tokens.length >= 3 && koreanSingleCharCount / tokens.length >= 0.7) {
20974
- result = tokens.join("");
20975
- }
20976
- }
20977
- return result;
20978
- }
20979
- function normForMatch(text) {
20980
- return sanitizeText(text).replace(/\s+/g, " ").trim();
20981
- }
20982
- function unescapeGfm(text) {
20983
- return text.replace(/\\~/g, "~");
20984
- }
20985
- function summarize(text) {
20986
- const t = text.replace(/\s+/g, " ").trim();
20987
- return t.length > 80 ? t.slice(0, 77) + "..." : t;
20988
- }
20989
- function replicateGfmTable(table) {
20990
- const { cells, rows: numRows, cols: numCols } = table;
20991
- if (numRows === 0 || numCols === 0) return null;
20992
- if (numRows === 1 && numCols === 1) return null;
20993
- if (numCols === 1) return null;
20994
- const display = Array.from({ length: numRows }, (_, r) => Array.from({ length: numCols }, (_2, c) => ({ text: "", gridR: r, gridC: c })));
20995
- const skip = /* @__PURE__ */ new Set();
20996
- for (let r = 0; r < numRows; r++) {
20997
- for (let c = 0; c < numCols; c++) {
20998
- if (skip.has(`${r},${c}`)) continue;
20999
- const cell = _optionalChain([cells, 'access', _172 => _172[r], 'optionalAccess', _173 => _173[c]]);
21000
- if (!cell) continue;
21001
- display[r][c] = {
21002
- text: escapeGfm(sanitizeText(cell.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
21003
- gridR: r,
21004
- gridC: c
21005
- };
21006
- for (let dr = 0; dr < cell.rowSpan; dr++) {
21007
- for (let dc = 0; dc < cell.colSpan; dc++) {
21008
- if (dr === 0 && dc === 0) continue;
21009
- if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
21010
- }
21011
- }
21012
- c += cell.colSpan - 1;
21013
- }
21014
- }
21015
- const uniqueRows = [];
21016
- let pendingLabelRow = null;
21017
- for (let r = 0; r < display.length; r++) {
21018
- const row = display[r];
21019
- if (row.every((cell) => cell.text === "")) continue;
21020
- const nonEmptyCols = row.filter((cell) => cell.text !== "");
21021
- const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
21022
- if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
21023
- if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
21024
- pendingLabelRow = row;
21025
- continue;
21026
- }
21027
- if (pendingLabelRow) {
21028
- if (row[0].text === "") row[0] = pendingLabelRow[0];
21029
- else uniqueRows.push(pendingLabelRow);
21030
- pendingLabelRow = null;
21031
- }
21032
- uniqueRows.push(row);
21033
- }
21034
- if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
21035
- return uniqueRows.length > 0 ? uniqueRows : null;
21036
- }
21037
- function parseGfmTable(lines) {
21038
- const rows = [];
21039
- for (const line of lines) {
21040
- const trimmed = line.trim();
21041
- if (!trimmed.startsWith("|")) continue;
21042
- const cells = trimmed.split(/(?<!\\)\|/).slice(1, -1).map((c) => c.trim());
21043
- if (cells.length === 0) continue;
21044
- if (cells.every((c) => /^:?-{3,}:?$/.test(c))) continue;
21045
- rows.push(cells);
21046
- }
21047
- return rows;
21048
- }
21049
- function unescapeGfmCell(text) {
21050
- return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\~/g, "~");
21051
- }
21052
- function replicateCellInnerHtml(cell) {
21053
- if (_optionalChain([cell, 'access', _174 => _174.blocks, 'optionalAccess', _175 => _175.length])) {
21054
- return cell.blocks.map((b) => {
21055
- if (b.type === "table" && b.table) {
21056
- const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
21057
- return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
21058
- }
21059
- if (b.type === "image" && b.text) return `<img src="${b.text}" alt="image">`;
21060
- const t = sanitizeText(_nullishCoalesce(b.text, () => ( "")));
21061
- return t ? t.replace(/\n/g, "<br>") : "";
21062
- }).filter(Boolean).join("<br>");
21063
- }
21064
- return sanitizeText(cell.text).replace(/\n/g, "<br>");
21065
- }
21066
- function replicateTableToHtml(table) {
21067
- const rows = replicateHtmlTable(table);
21068
- const lines = ["<table>"];
21069
- for (let r = 0; r < rows.length; r++) {
21070
- const tag = rows[r].tag;
21071
- const rowHtml = rows[r].cells.map((cell) => {
21072
- const attrs = [];
21073
- if (cell.colSpan > 1) attrs.push(`colspan="${cell.colSpan}"`);
21074
- if (cell.rowSpan > 1) attrs.push(`rowspan="${cell.rowSpan}"`);
21075
- const attrStr = attrs.length ? " " + attrs.join(" ") : "";
21076
- return `<${tag}${attrStr}>${cell.inner}</${tag}>`;
21077
- });
21078
- if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
21079
- }
21080
- lines.push("</table>");
21081
- return lines.join("\n");
21082
- }
21083
- function replicateHtmlTable(table) {
21084
- const { cells, rows: numRows, cols: numCols } = table;
21085
- const skip = /* @__PURE__ */ new Set();
21086
- const result = [];
21087
- for (let r = 0; r < numRows; r++) {
21088
- const tag = r === 0 ? "th" : "td";
21089
- const rowCells = [];
21090
- for (let c = 0; c < numCols; c++) {
21091
- if (skip.has(`${r},${c}`)) continue;
21092
- const cell = _optionalChain([cells, 'access', _176 => _176[r], 'optionalAccess', _177 => _177[c]]);
21093
- if (!cell) continue;
21094
- for (let dr = 0; dr < cell.rowSpan; dr++) {
21095
- for (let dc = 0; dc < cell.colSpan; dc++) {
21096
- if (dr === 0 && dc === 0) continue;
21097
- if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
21098
- }
21099
- }
21100
- rowCells.push({
21101
- inner: replicateCellInnerHtml(cell),
21102
- colSpan: cell.colSpan,
21103
- rowSpan: cell.rowSpan,
21104
- gridR: r,
21105
- gridC: c
21106
- });
21844
+ else type = "modified";
21845
+ row.push({ type, before: cellA, after: cellB });
21107
21846
  }
21108
- if (rowCells.length) result.push({ tag, cells: rowCells });
21847
+ result.push(row);
21109
21848
  }
21110
21849
  return result;
21111
21850
  }
21112
- function parseHtmlTable(raw) {
21113
- const re = /<(\/?)(table|tr|td|th)((?:"[^"]*"|'[^']*'|[^>"'])*?)>/gi;
21114
- let depth = 0;
21115
- let currentRow = null;
21116
- let cellStart = -1;
21117
- let cellInfo = null;
21118
- const rows = [];
21119
- let m;
21120
- while ((m = re.exec(raw)) !== null) {
21121
- const isClose = m[1] === "/";
21122
- const tag = m[2].toLowerCase();
21123
- const attrs = m[3] || "";
21124
- if (tag === "table") {
21125
- depth += isClose ? -1 : 1;
21126
- if (depth < 0) return null;
21127
- continue;
21851
+
21852
+ // src/roundtrip/patcher.ts
21853
+
21854
+
21855
+ // src/roundtrip/table-rows.ts
21856
+ var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
21857
+ var TAG_AT_RE = /<[A-Za-z0-9_:]+(?:"[^"]*"|'[^']*'|[^>"'])*>/y;
21858
+ function patchTableRows(input) {
21859
+ const { table, scanTable, ctx, skip, origKeys, editedKeys } = input;
21860
+ const xml = _optionalChain([ctx, 'access', _196 => _196.scans, 'access', _197 => _197[scanTable.sectionIndex], 'optionalAccess', _198 => _198.xml]);
21861
+ if (!xml) return skip("\uC139\uC158 XML \uB9E4\uD551 \uC2E4\uD328");
21862
+ const numRows = table.rows;
21863
+ if (origKeys.length !== numRows) return skip("\uD45C \uD589 \uC88C\uD45C \uBD88\uC77C\uCE58 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21864
+ if (scanTable.rows.length !== numRows || scanTable.rowRanges.length !== numRows) {
21865
+ 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");
21866
+ }
21867
+ for (let r = 0; r < numRows; r++) {
21868
+ if (scanTable.rows[r].some((c) => c.rowAddr !== r)) {
21869
+ return skip("\uD589 \uC8FC\uC18C \uBE44\uC5F0\uC18D \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21128
21870
  }
21129
- if (depth !== 1) continue;
21130
- if (tag === "tr") {
21131
- if (!isClose) currentRow = [];
21132
- else if (currentRow) {
21133
- rows.push({ tag: rows.length === 0 ? "th" : "td", cells: currentRow });
21134
- currentRow = null;
21871
+ }
21872
+ const allCells = scanTable.rows.flat();
21873
+ const explicitAddr = (c) => !!c.addrTagRange && /\browAddr\s*=\s*"/.test(xml.slice(c.addrTagRange.start, c.addrTagRange.end));
21874
+ const explicitCount = allCells.filter(explicitAddr).length;
21875
+ if (explicitCount !== 0 && explicitCount !== allCells.length) {
21876
+ return skip("\uC140 \uC8FC\uC18C(cellAddr) \uD45C\uAE30 \uD63C\uC7AC \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21877
+ }
21878
+ const hasExplicitAddr = explicitCount > 0;
21879
+ const pairs = alignUnits(origKeys, editedKeys);
21880
+ const seq = [];
21881
+ let lastOrig = -1;
21882
+ for (const [oi, ei] of pairs) {
21883
+ if (oi !== null && ei !== null) {
21884
+ seq.push({ kind: "keep", oi, ei });
21885
+ lastOrig = oi;
21886
+ } else if (oi !== null) {
21887
+ seq.push({ kind: "del", oi });
21888
+ lastOrig = oi;
21889
+ } else if (ei !== null) seq.push({ kind: "ins", ei, insertAt: lastOrig + 1 });
21890
+ }
21891
+ const dels = seq.filter((e) => e.kind === "del");
21892
+ const inss = seq.filter((e) => e.kind === "ins");
21893
+ const keeps = seq.filter((e) => e.kind === "keep");
21894
+ if (dels.length === 0 && inss.length === 0) {
21895
+ return skip("\uD45C \uD589 \uC815\uB82C \uC2E4\uD328 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21896
+ }
21897
+ if (keeps.length + inss.length === 0) return skip("\uBAA8\uB4E0 \uD589 \uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0");
21898
+ if (keeps.length === 0) return skip("\uD589 \uC804\uBA74 \uAD50\uCCB4 \u2014 \uC11C\uC2DD \uAE30\uC900 \uD589\uC774 \uC5C6\uC5B4 \uBBF8\uC9C0\uC6D0");
21899
+ const spans = allCells.filter((c) => (_nullishCoalesce(c.rowSpan, () => ( 1))) > 1);
21900
+ for (const d of dels) {
21901
+ if (spans.some((s) => s.rowAddr <= d.oi && s.rowAddr + s.rowSpan > d.oi)) {
21902
+ return skip(`\uD45C ${d.oi + 1}\uD589 \uC0AD\uC81C\uAC00 \uC138\uB85C \uBCD1\uD569\uACFC \uACB9\uCE68 \u2014 \uBBF8\uC9C0\uC6D0`);
21903
+ }
21904
+ }
21905
+ for (const ins of inss) {
21906
+ const p = ins.insertAt;
21907
+ if (spans.some((s) => s.rowAddr < p && s.rowAddr + s.rowSpan > p)) {
21908
+ return skip("\uD589 \uC0BD\uC785 \uC704\uCE58\uAC00 \uC138\uB85C \uBCD1\uD569 \uB0B4\uBD80 \u2014 \uBBF8\uC9C0\uC6D0");
21909
+ }
21910
+ }
21911
+ for (const d of dels) {
21912
+ const rr = scanTable.rowRanges[d.oi];
21913
+ if (ROW_OBJECT_RE.test(xml.slice(rr.start, rr.end))) {
21914
+ return skip(`\uD45C ${d.oi + 1}\uD589\uC5D0 \uAC1C\uCCB4(\uC911\uCCA9\uD45C/\uC774\uBBF8\uC9C0/\uD544\uB4DC) \uD3EC\uD568 \u2014 \uD589 \uC0AD\uC81C \uBBF8\uC9C0\uC6D0`);
21915
+ }
21916
+ }
21917
+ const keptSet = new Set(keeps.map((k) => k.oi));
21918
+ const insertPlans = [];
21919
+ for (const ins of inss) {
21920
+ const p = ins.insertAt;
21921
+ const kept = [...keptSet].sort((a, b) => a - b);
21922
+ let template = -1;
21923
+ for (const k of kept) {
21924
+ if (k < p) template = k;
21925
+ }
21926
+ if (template <= 0 && p >= 1) {
21927
+ const following = kept.find((k) => k >= 1);
21928
+ if (following !== void 0) template = following;
21929
+ }
21930
+ if (template < 0) template = kept[0];
21931
+ const cells = input.editedCells(ins.ei);
21932
+ if (!cells) return skip("\uC0BD\uC785 \uD589\uC5D0 \uC774\uBBF8\uC9C0/\uC911\uCCA9\uD45C \uD3EC\uD568 \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
21933
+ for (const cell of cells) {
21934
+ const unstable = cell.lines.find((l) => sanitizeText(l) !== l);
21935
+ 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");
21936
+ }
21937
+ const tmplCells = scanTable.rows[template];
21938
+ const rr = scanTable.rowRanges[template];
21939
+ if (ROW_OBJECT_RE.test(xml.slice(rr.start, rr.end))) {
21940
+ return skip("\uC11C\uC2DD \uAE30\uC900 \uD589\uC5D0 \uAC1C\uCCB4(\uC911\uCCA9\uD45C/\uC774\uBBF8\uC9C0/\uD544\uB4DC) \uD3EC\uD568 \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
21941
+ }
21942
+ 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");
21943
+ const tmplWidth = tmplCells.reduce((s, c) => s + c.colSpan, 0);
21944
+ 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");
21945
+ if (cells.length !== tmplCells.length) {
21946
+ return skip(`\uC0BD\uC785 \uD589 \uC140 \uC218(${cells.length}) \u2260 \uAE30\uC900 \uD589 \uC140 \uC218(${tmplCells.length}) \u2014 \uBBF8\uC9C0\uC6D0`);
21947
+ }
21948
+ for (let i = 0; i < cells.length; i++) {
21949
+ if (cells[i].rowSpan !== 1 || cells[i].colSpan !== tmplCells[i].colSpan) {
21950
+ return skip("\uC0BD\uC785 \uD589 \uBCD1\uD569 \uAD6C\uC870\uAC00 \uAE30\uC900 \uD589\uACFC \uB2E4\uB984 \u2014 \uBBF8\uC9C0\uC6D0");
21135
21951
  }
21136
- } else {
21137
- if (!isClose) {
21138
- const cs = parseInt(_optionalChain([attrs, 'access', _178 => _178.match, 'call', _179 => _179(/colspan\s*=\s*"(\d+)"/i), 'optionalAccess', _180 => _180[1]]) || "1", 10);
21139
- const rs = parseInt(_optionalChain([attrs, 'access', _181 => _181.match, 'call', _182 => _182(/rowspan\s*=\s*"(\d+)"/i), 'optionalAccess', _183 => _183[1]]) || "1", 10);
21140
- cellStart = m.index + m[0].length;
21141
- cellInfo = { colSpan: isNaN(cs) ? 1 : cs, rowSpan: isNaN(rs) ? 1 : rs };
21142
- } else if (cellStart >= 0 && cellInfo && currentRow) {
21143
- currentRow.push({ inner: raw.slice(cellStart, m.index), colSpan: cellInfo.colSpan, rowSpan: cellInfo.rowSpan });
21144
- cellStart = -1;
21145
- cellInfo = null;
21952
+ }
21953
+ insertPlans.push({ entry: ins, template, cells });
21954
+ }
21955
+ const net = inss.length - dels.length;
21956
+ TAG_AT_RE.lastIndex = scanTable.start;
21957
+ const tblOpen = TAG_AT_RE.exec(xml);
21958
+ if (!tblOpen || tblOpen.index !== scanTable.start) return skip("\uD45C \uC5EC\uB294 \uD0DC\uADF8 \uD574\uC11D \uC2E4\uD328");
21959
+ const rowCntM = tblOpen[0].match(/\browCnt\s*=\s*"(\d+)"/);
21960
+ if (!rowCntM || rowCntM.index === void 0) return skip("\uD45C rowCnt \uC18D\uC131 \uC5C6\uC74C \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21961
+ if (parseInt(rowCntM[1], 10) !== numRows) return skip("rowCnt\uC640 \uC2E4\uC81C \uD589 \uC218 \uBD88\uC77C\uCE58 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21962
+ const finalIndex = /* @__PURE__ */ new Map();
21963
+ {
21964
+ let fi = 0;
21965
+ for (const e of seq) {
21966
+ if (e.kind !== "del") finalIndex.set(e, fi++);
21967
+ }
21968
+ }
21969
+ const splices = [];
21970
+ let applied = 0;
21971
+ for (const d of dels) {
21972
+ const rr = scanTable.rowRanges[d.oi];
21973
+ splices.push({ start: rr.start, end: rr.end, replacement: "" });
21974
+ applied++;
21975
+ }
21976
+ const fragmentsByAnchor = /* @__PURE__ */ new Map();
21977
+ let heightDelta = 0;
21978
+ for (const plan of insertPlans) {
21979
+ const finalRow = finalIndex.get(plan.entry);
21980
+ const fragment = buildRowFragment(xml, scanTable, plan.template, plan.cells, finalRow, hasExplicitAddr, ctx);
21981
+ if (fragment === null) return skip("\uD589 \uBCF5\uC81C \uC2E4\uD328 (\uC140 \uBB38\uB2E8 \uAD6C\uC870 \uBBF8\uC9C0\uC6D0)");
21982
+ const p = plan.entry.insertAt;
21983
+ const anchor = p === 0 ? scanTable.rowRanges[0].start : scanTable.rowRanges[p - 1].end;
21984
+ let list = fragmentsByAnchor.get(anchor);
21985
+ if (!list) fragmentsByAnchor.set(anchor, list = []);
21986
+ list.push(fragment);
21987
+ heightDelta += rowHeightOf(fragment);
21988
+ applied++;
21989
+ }
21990
+ for (const [anchor, fragments] of fragmentsByAnchor) {
21991
+ splices.push({ start: anchor, end: anchor, replacement: fragments.join("") });
21992
+ }
21993
+ for (const d of dels) {
21994
+ const rr = scanTable.rowRanges[d.oi];
21995
+ heightDelta -= rowHeightOf(xml.slice(rr.start, rr.end));
21996
+ }
21997
+ if (hasExplicitAddr) {
21998
+ for (const k of keeps) {
21999
+ const fi = finalIndex.get(k);
22000
+ if (fi === k.oi) continue;
22001
+ for (const cell of scanTable.rows[k.oi]) {
22002
+ const sp = rowAddrRewrite(xml, cell, fi);
22003
+ if (sp) splices.push(sp);
21146
22004
  }
21147
22005
  }
21148
22006
  }
21149
- if (depth !== 0) return null;
21150
- return rows;
21151
- }
21152
- function htmlCellInnerToLines(inner) {
21153
- let hadNonText = false;
21154
- let work = inner;
21155
- if (/<table[\s>]/i.test(work)) {
21156
- hadNonText = true;
21157
- work = removeNestedTables(work);
22007
+ {
22008
+ const valStart = scanTable.start + rowCntM.index + rowCntM[0].indexOf('"') + 1;
22009
+ splices.push({ start: valStart, end: valStart + rowCntM[1].length, replacement: String(numRows + net) });
21158
22010
  }
21159
- if (/<img\s/i.test(work)) {
21160
- hadNonText = true;
21161
- work = work.replace(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi, "");
22011
+ if (heightDelta !== 0) {
22012
+ const sp = tableSzHeightSplice(xml, scanTable, tblOpen[0].length, heightDelta);
22013
+ if (sp) splices.push(sp);
21162
22014
  }
21163
- const lines = work.split(/<br\s*\/?>/gi).map((s) => s.trim()).filter((s) => s.length > 0);
21164
- return { lines, hadNonText };
22015
+ ctx.sectionSplices[scanTable.sectionIndex].push(...splices);
22016
+ for (const k of keeps) {
22017
+ if (origKeys[k.oi] !== editedKeys[k.ei]) applied += input.patchMatched(k.oi, k.ei);
22018
+ }
22019
+ return applied;
21165
22020
  }
21166
- function extractTopLevelTables(html) {
21167
- const result = [];
21168
- let depth = 0;
21169
- let start = -1;
21170
- const re = /<(\/?)table(?:[\s>]|>)/gi;
21171
- let m;
21172
- while ((m = re.exec(html)) !== null) {
21173
- if (m[1] !== "/") {
21174
- if (depth === 0) start = m.index;
21175
- depth++;
21176
- } else {
21177
- depth--;
21178
- if (depth === 0 && start >= 0) {
21179
- result.push(html.slice(start, m.index + m[0].length));
21180
- start = -1;
21181
- }
21182
- if (depth < 0) depth = 0;
22021
+ var FRAG_OPEN = "<hp:tbl>";
22022
+ var FRAG_CLOSE = "</hp:tbl>";
22023
+ function buildRowFragment(xml, scanTable, template, cells, finalRow, hasExplicitAddr, ctx) {
22024
+ const rr = scanTable.rowRanges[template];
22025
+ const wrapped = FRAG_OPEN + xml.slice(rr.start, rr.end) + FRAG_CLOSE;
22026
+ const scan = scanSectionXml(wrapped, 0);
22027
+ const row = _optionalChain([scan, 'access', _199 => _199.tables, 'access', _200 => _200[0], 'optionalAccess', _201 => _201.rows, 'access', _202 => _202[0]]);
22028
+ if (!row || row.length !== cells.length) return null;
22029
+ const splices = allLinesegRemovalSplices(wrapped);
22030
+ for (let i = 0; i < cells.length; i++) {
22031
+ const paras = row[i].paragraphs;
22032
+ let lines = cells[i].lines;
22033
+ if (lines.length > 0 && paras.length === 0) return null;
22034
+ if (lines.length > paras.length) {
22035
+ lines = [...lines.slice(0, paras.length - 1), lines.slice(paras.length - 1).join(" ")];
22036
+ ctx.skipped.push({ reason: "\uC0BD\uC785 \uD589 \uC140\uC758 \uC904 \uC218\uAC00 \uBB38\uB2E8 \uC218 \uCD08\uACFC \u2014 \uB9C8\uC9C0\uB9C9 \uBB38\uB2E8\uC5D0 \uBCD1\uD569 \uC801\uC6A9", after: summarize(cells[i].lines.join(" ")), partial: true });
22037
+ }
22038
+ for (let p = 0; p < paras.length; p++) {
22039
+ const sp = buildParagraphSplices(paras[p], _nullishCoalesce(lines[p], () => ( "")), wrapped);
22040
+ if (sp === null) return null;
22041
+ splices.push(...sp);
22042
+ }
22043
+ if (hasExplicitAddr) {
22044
+ const sp = rowAddrRewrite(wrapped, row[i], finalRow);
22045
+ if (sp) splices.push(sp);
21183
22046
  }
21184
22047
  }
21185
- return result;
22048
+ const patched = applySplices(wrapped, splices);
22049
+ return patched.slice(FRAG_OPEN.length, patched.length - FRAG_CLOSE.length);
21186
22050
  }
21187
- function removeNestedTables(html) {
21188
- let result = "";
21189
- let depth = 0;
21190
- const re = /<(\/?)table(?:[\s>]|>)/gi;
21191
- let last = 0;
21192
- let m;
21193
- while ((m = re.exec(html)) !== null) {
21194
- if (m[1] !== "/") {
21195
- if (depth === 0) result += html.slice(last, m.index);
21196
- depth++;
21197
- } else {
21198
- depth--;
21199
- if (depth === 0) last = m.index + m[0].length;
21200
- if (depth < 0) depth = 0;
21201
- }
22051
+ function rowAddrRewrite(xml, cell, newRow) {
22052
+ if (!cell.addrTagRange) return null;
22053
+ const tag = xml.slice(cell.addrTagRange.start, cell.addrTagRange.end);
22054
+ const m = tag.match(/\browAddr\s*=\s*"(\d+)"/);
22055
+ if (!m || m.index === void 0) return null;
22056
+ if (parseInt(m[1], 10) === newRow) return null;
22057
+ const valStart = cell.addrTagRange.start + m.index + m[0].indexOf('"') + 1;
22058
+ return { start: valStart, end: valStart + m[1].length, replacement: String(newRow) };
22059
+ }
22060
+ function rowHeightOf(fragment) {
22061
+ let max = 0;
22062
+ for (const m of fragment.matchAll(/<(?:[A-Za-z0-9_]+:)?cellSz\b(?:"[^"]*"|'[^']*'|[^>"'])*>/g)) {
22063
+ const h = m[0].match(/\bheight\s*=\s*"(\d+)"/);
22064
+ if (h) max = Math.max(max, parseInt(h[1], 10));
21202
22065
  }
21203
- if (depth === 0) result += html.slice(last);
21204
- return result;
22066
+ return max;
22067
+ }
22068
+ function tableSzHeightSplice(xml, scanTable, tblOpenLen, delta) {
22069
+ const from = scanTable.start + tblOpenLen;
22070
+ const to = _nullishCoalesce(_optionalChain([scanTable, 'access', _203 => _203.rowRanges, 'access', _204 => _204[0], 'optionalAccess', _205 => _205.start]), () => ( from));
22071
+ const slice = xml.slice(from, to);
22072
+ const szM = slice.match(/<(?:[A-Za-z0-9_]+:)?sz\b(?:"[^"]*"|'[^']*'|[^>"'])*>/);
22073
+ if (!szM || szM.index === void 0) return null;
22074
+ const hM = szM[0].match(/\bheight\s*=\s*"(\d+)"/);
22075
+ if (!hM || hM.index === void 0) return null;
22076
+ const oldH = parseInt(hM[1], 10);
22077
+ const newH = Math.max(0, oldH + delta);
22078
+ const valStart = from + szM.index + hM.index + hM[0].indexOf('"') + 1;
22079
+ return { start: valStart, end: valStart + hM[1].length, replacement: String(newH) };
21205
22080
  }
21206
22081
 
21207
22082
  // src/roundtrip/table-patch.ts
@@ -21213,37 +22088,89 @@ function patchGfmTable(table, scanTable, orig, edited, ctx, skip) {
21213
22088
  if (replica.length !== origRows.length || replica.some((row, r) => row.length !== origRows[r].length || row.some((c, j) => c.text !== origRows[r][j]))) {
21214
22089
  return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
21215
22090
  }
21216
- if (editedRows.length !== origRows.length) return skip("\uD45C \uD589 \uCD94\uAC00/\uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0 (\uD45C \uAD6C\uC870 \uBCC0\uACBD)");
22091
+ if (editedRows.length !== origRows.length) {
22092
+ return patchGfmTableRows(table, scanTable, origRows, editedRows, replica, ctx, skip);
22093
+ }
21217
22094
  let applied = 0;
21218
22095
  for (let r = 0; r < origRows.length; r++) {
21219
- if (editedRows[r].length !== origRows[r].length) {
21220
- skip(`\uD45C ${r + 1}\uD589 \uC5F4 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
22096
+ applied += patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, r, ctx, skip);
22097
+ }
22098
+ return applied;
22099
+ }
22100
+ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er, ctx, skip) {
22101
+ if (editedRows[er].length !== origRows[r].length) {
22102
+ skip(`\uD45C ${r + 1}\uD589 \uC5F4 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
22103
+ return 0;
22104
+ }
22105
+ let applied = 0;
22106
+ for (let c = 0; c < origRows[r].length; c++) {
22107
+ if (origRows[r][c] === editedRows[er][c]) continue;
22108
+ const { gridR, gridC } = replica[r][c];
22109
+ const origTokens = extractCellTokens(origRows[r][c]);
22110
+ const editedTokens = extractCellTokens(editedRows[er][c]);
22111
+ if (origTokens !== editedTokens) {
22112
+ skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
21221
22113
  continue;
21222
22114
  }
21223
- for (let c = 0; c < origRows[r].length; c++) {
21224
- if (origRows[r][c] === editedRows[r][c]) continue;
21225
- const { gridR, gridC } = replica[r][c];
21226
- const origTokens = extractCellTokens(origRows[r][c]);
21227
- const editedTokens = extractCellTokens(editedRows[r][c]);
21228
- if (origTokens !== editedTokens) {
21229
- skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
21230
- continue;
21231
- }
21232
- const newLines = unescapeGfmCell(stripCellTokens(editedRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
21233
- const origLines = unescapeGfmCell(stripCellTokens(origRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
21234
- const n = applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, origRows[r][c], editedRows[r][c], origLines.length);
21235
- if (n > 0 && origTokens) {
21236
- ctx.skipped.push({
21237
- 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)",
21238
- before: summarize(origRows[r][c]),
21239
- after: summarize(editedRows[r][c])
21240
- });
21241
- }
21242
- applied += n;
22115
+ const newLines = unescapeGfmCell(stripCellTokens(editedRows[er][c])).split("\n").map((s) => s.trim()).filter(Boolean);
22116
+ const origLines = unescapeGfmCell(stripCellTokens(origRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
22117
+ const n = applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, origRows[r][c], editedRows[er][c], origLines.length);
22118
+ if (n > 0 && origTokens) {
22119
+ ctx.skipped.push({
22120
+ 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)",
22121
+ before: summarize(origRows[r][c]),
22122
+ after: summarize(editedRows[er][c]),
22123
+ partial: true
22124
+ });
21243
22125
  }
22126
+ applied += n;
21244
22127
  }
21245
22128
  return applied;
21246
22129
  }
22130
+ function patchGfmTableRows(table, scanTable, origRows, editedRows, replica, ctx, skip) {
22131
+ if (replica.length !== table.rows || replica.some((row, r) => row.some((c) => c.gridR !== r))) {
22132
+ 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");
22133
+ }
22134
+ if (table.cells.some((row) => row.some((c) => c && (c.colSpan > 1 || c.rowSpan > 1)))) {
22135
+ return skip("\uBCD1\uD569 \uC140 \uD45C \u2014 GFM \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
22136
+ }
22137
+ if (!gfmRenderStable(editedRows, table.cols)) {
22138
+ 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");
22139
+ }
22140
+ const key = (row) => row.join("\0");
22141
+ return patchTableRows({
22142
+ table,
22143
+ scanTable,
22144
+ ctx,
22145
+ skip,
22146
+ origKeys: origRows.map(key),
22147
+ editedKeys: editedRows.map(key),
22148
+ editedCells: (ei) => {
22149
+ const cells = [];
22150
+ for (const cellMd of editedRows[ei]) {
22151
+ if (extractCellTokens(cellMd)) return null;
22152
+ const lines = unescapeGfmCell(cellMd).split("\n").map((s) => s.trim()).filter(Boolean);
22153
+ cells.push({ lines, colSpan: 1, rowSpan: 1 });
22154
+ }
22155
+ return cells;
22156
+ },
22157
+ patchMatched: (oi, ei) => patchGfmRowPair(table, scanTable, origRows, editedRows, replica, oi, ei, ctx, skip)
22158
+ });
22159
+ }
22160
+ function gfmRenderStable(editedRows, cols) {
22161
+ const sim = {
22162
+ rows: editedRows.length,
22163
+ cols,
22164
+ hasHeader: editedRows.length > 1,
22165
+ cells: editedRows.map((row) => {
22166
+ const padded = row.length < cols ? [...row, ...Array(cols - row.length).fill("")] : row;
22167
+ return padded.map((md2) => ({ text: unescapeGfmCell(md2), colSpan: 1, rowSpan: 1 }));
22168
+ })
22169
+ };
22170
+ const replica = replicateGfmTable(sim);
22171
+ if (!replica || replica.length !== editedRows.length) return false;
22172
+ return replica.every((row, r) => row.length === editedRows[r].length && row.every((c, j) => c.text === editedRows[r][j]));
22173
+ }
21247
22174
  function patchHtmlTable(table, scanTable, orig, edited, ctx, skip) {
21248
22175
  return patchHtmlTableRaw(table, scanTable, orig.raw, edited.raw, ctx, skip, 0);
21249
22176
  }
@@ -21257,50 +22184,81 @@ function patchHtmlTableRaw(table, scanTable, origRaw, editedRaw, ctx, skip, dept
21257
22184
  }
21258
22185
  const editedRows = parseHtmlTable(editedRaw);
21259
22186
  if (!editedRows) return skip("\uD3B8\uC9D1\uB41C HTML \uD45C \uD30C\uC2F1 \uC2E4\uD328");
21260
- if (editedRows.length !== replica.length) return skip("\uD45C \uD589 \uCD94\uAC00/\uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0 (\uD45C \uAD6C\uC870 \uBCC0\uACBD)");
22187
+ if (editedRows.length !== replica.length) {
22188
+ return patchHtmlTableRows(table, scanTable, replica, editedRows, ctx, skip, depth);
22189
+ }
21261
22190
  let applied = 0;
21262
22191
  for (let r = 0; r < replica.length; r++) {
21263
- if (editedRows[r].cells.length !== replica[r].cells.length) {
21264
- skip(`\uD45C ${r + 1}\uD589 \uC140 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
22192
+ applied += patchHtmlRowPair(table, scanTable, replica, editedRows, r, r, ctx, skip, depth);
22193
+ }
22194
+ return applied;
22195
+ }
22196
+ function patchHtmlRowPair(table, scanTable, replica, editedRows, r, er, ctx, skip, depth) {
22197
+ if (editedRows[er].cells.length !== replica[r].cells.length) {
22198
+ skip(`\uD45C ${r + 1}\uD589 \uC140 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
22199
+ return 0;
22200
+ }
22201
+ let applied = 0;
22202
+ for (let c = 0; c < replica[r].cells.length; c++) {
22203
+ const oc = replica[r].cells[c];
22204
+ const ec = editedRows[er].cells[c];
22205
+ if (oc.colSpan !== ec.colSpan || oc.rowSpan !== ec.rowSpan) {
22206
+ skip(`\uC140 \uBCD1\uD569(colspan/rowspan) \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
21265
22207
  continue;
21266
22208
  }
21267
- for (let c = 0; c < replica[r].cells.length; c++) {
21268
- const oc = replica[r].cells[c];
21269
- const ec = editedRows[r].cells[c];
21270
- if (oc.colSpan !== ec.colSpan || oc.rowSpan !== ec.rowSpan) {
21271
- skip(`\uC140 \uBCD1\uD569(colspan/rowspan) \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
22209
+ if (oc.inner === ec.inner) continue;
22210
+ const origContent = htmlCellInnerToLines(oc.inner);
22211
+ const editedContent = htmlCellInnerToLines(ec.inner);
22212
+ if (origContent.hadNonText || editedContent.hadNonText) {
22213
+ if (extractImgTags(oc.inner) !== extractImgTags(ec.inner)) {
22214
+ skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
21272
22215
  continue;
21273
22216
  }
21274
- if (oc.inner === ec.inner) continue;
21275
- const origContent = htmlCellInnerToLines(oc.inner);
21276
- const editedContent = htmlCellInnerToLines(ec.inner);
21277
- if (origContent.hadNonText || editedContent.hadNonText) {
21278
- if (extractImgTags(oc.inner) !== extractImgTags(ec.inner)) {
21279
- skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
21280
- continue;
21281
- }
21282
- const origTables = extractTopLevelTables(oc.inner);
21283
- const editedTables = extractTopLevelTables(ec.inner);
21284
- if (origTables.length !== editedTables.length) {
21285
- skip("\uC140 \uB0B4 \uC911\uCCA9\uD45C \uCD94\uAC00/\uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0");
21286
- continue;
21287
- }
21288
- if (origTables.join("\n") !== editedTables.join("\n")) {
21289
- applied += patchNestedTables(table, scanTable, oc, origTables, editedTables, ctx, skip, depth);
21290
- }
22217
+ const origTables = extractTopLevelTables(oc.inner);
22218
+ const editedTables = extractTopLevelTables(ec.inner);
22219
+ if (origTables.length !== editedTables.length) {
22220
+ skip("\uC140 \uB0B4 \uC911\uCCA9\uD45C \uCD94\uAC00/\uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0");
22221
+ continue;
21291
22222
  }
21292
- if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
21293
- const newLines = editedContent.lines.map((l) => unescapeGfm(l));
21294
- applied += applyCellEdit(table, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
22223
+ if (origTables.join("\n") !== editedTables.join("\n")) {
22224
+ applied += patchNestedTables(table, scanTable, oc, origTables, editedTables, ctx, skip, depth);
21295
22225
  }
21296
22226
  }
22227
+ if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
22228
+ const newLines = editedContent.lines.map((l) => unescapeGfm(l));
22229
+ applied += applyCellEdit(table, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
22230
+ }
21297
22231
  }
21298
22232
  return applied;
21299
22233
  }
22234
+ function patchHtmlTableRows(table, scanTable, replica, editedRows, ctx, skip, depth) {
22235
+ if (replica.length !== table.rows || replica.some((row, r) => row.cells.some((c) => c.gridR !== r))) {
22236
+ 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");
22237
+ }
22238
+ const key = (row) => row.cells.map((c) => `${c.colSpan}x${c.rowSpan}:${c.inner}`).join("\0");
22239
+ return patchTableRows({
22240
+ table,
22241
+ scanTable,
22242
+ ctx,
22243
+ skip,
22244
+ origKeys: replica.map(key),
22245
+ editedKeys: editedRows.map(key),
22246
+ editedCells: (ei) => {
22247
+ const cells = [];
22248
+ for (const cell of editedRows[ei].cells) {
22249
+ const content = htmlCellInnerToLines(cell.inner);
22250
+ if (content.hadNonText) return null;
22251
+ cells.push({ lines: content.lines.map((l) => unescapeGfm(l)), colSpan: cell.colSpan, rowSpan: cell.rowSpan });
22252
+ }
22253
+ return cells;
22254
+ },
22255
+ patchMatched: (oi, ei) => patchHtmlRowPair(table, scanTable, replica, editedRows, oi, ei, ctx, skip, depth)
22256
+ });
22257
+ }
21300
22258
  function patchNestedTables(table, scanTable, oc, origTables, editedTables, ctx, skip, depth) {
21301
- const irCell = _optionalChain([table, 'access', _184 => _184.cells, 'access', _185 => _185[oc.gridR], 'optionalAccess', _186 => _186[oc.gridC]]);
22259
+ const irCell = _optionalChain([table, 'access', _206 => _206.cells, 'access', _207 => _207[oc.gridR], 'optionalAccess', _208 => _208[oc.gridC]]);
21302
22260
  const scanCell = scanTable.cellByAnchor.get(`${oc.gridR},${oc.gridC}`);
21303
- const nestedIRs = (_nullishCoalesce(_optionalChain([irCell, 'optionalAccess', _187 => _187.blocks]), () => ( []))).filter((b) => b.type === "table" && b.table).map((b) => b.table);
22261
+ const nestedIRs = (_nullishCoalesce(_optionalChain([irCell, 'optionalAccess', _209 => _209.blocks]), () => ( []))).filter((b) => b.type === "table" && b.table).map((b) => b.table);
21304
22262
  if (!scanCell || nestedIRs.length !== origTables.length || scanCell.tables.length !== origTables.length) {
21305
22263
  return skip("\uC911\uCCA9\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328");
21306
22264
  }
@@ -21368,7 +22326,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21368
22326
  };
21369
22327
  const cell = scanTable.cellByAnchor.get(`${gridR},${gridC}`);
21370
22328
  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)");
21371
- const irCell = _optionalChain([table, 'access', _188 => _188.cells, 'access', _189 => _189[gridR], 'optionalAccess', _190 => _190[gridC]]);
22329
+ const irCell = _optionalChain([table, 'access', _210 => _210.cells, 'access', _211 => _211[gridR], 'optionalAccess', _212 => _212[gridC]]);
21372
22330
  const scanJoined = cell.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
21373
22331
  if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
21374
22332
  if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
@@ -21391,12 +22349,12 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21391
22349
  if (newLines.length === 0) return 0;
21392
22350
  const target = cell.paragraphs[0];
21393
22351
  if (!target) return skip("\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00");
21394
- const sp = buildParagraphSplices(target, newLines.join(" "), _optionalChain([ctx, 'access', _191 => _191.scans, 'access', _192 => _192[target.sectionIndex], 'optionalAccess', _193 => _193.xml]));
22352
+ const sp = buildParagraphSplices(target, newLines.join(" "), _optionalChain([ctx, 'access', _213 => _213.scans, 'access', _214 => _214[target.sectionIndex], 'optionalAccess', _215 => _215.xml]));
21395
22353
  if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21396
22354
  splices.push(...sp);
21397
22355
  sectionIndex = target.sectionIndex;
21398
22356
  if (newLines.length > 1) {
21399
- ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uCD94\uAC00\uB294 \uBB38\uB2E8 \uC0DD\uC131 \uBBF8\uC9C0\uC6D0 \u2014 \uD55C \uBB38\uB2E8\uC73C\uB85C \uBCD1\uD569 \uC801\uC6A9", after: summarize(after) });
22357
+ ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uCD94\uAC00\uB294 \uBB38\uB2E8 \uC0DD\uC131 \uBBF8\uC9C0\uC6D0 \u2014 \uD55C \uBB38\uB2E8\uC73C\uB85C \uBCD1\uD569 \uC801\uC6A9", after: summarize(after), partial: true });
21400
22358
  }
21401
22359
  } else {
21402
22360
  const assigned = [];
@@ -21408,11 +22366,13 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21408
22366
  }
21409
22367
  }
21410
22368
  if (newLines.length > nonEmpty.length) {
21411
- ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uCD94\uAC00\uB294 \uBB38\uB2E8 \uC0DD\uC131 \uBBF8\uC9C0\uC6D0 \u2014 \uB9C8\uC9C0\uB9C9 \uBB38\uB2E8\uC5D0 \uBCD1\uD569 \uC801\uC6A9", after: summarize(after) });
22369
+ ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uCD94\uAC00\uB294 \uBB38\uB2E8 \uC0DD\uC131 \uBBF8\uC9C0\uC6D0 \u2014 \uB9C8\uC9C0\uB9C9 \uBB38\uB2E8\uC5D0 \uBCD1\uD569 \uC801\uC6A9", after: summarize(after), partial: true });
22370
+ } else if (newLines.length < nonEmpty.length && nonEmpty.length > 1) {
22371
+ ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uC0AD\uC81C\uB294 \uBB38\uB2E8 \uC81C\uAC70 \uBBF8\uC9C0\uC6D0 \u2014 \uBE48 \uBB38\uB2E8 \uC794\uC874(\uBDF0\uC5B4\uC5D0 \uBE48 \uC904 \uD45C\uC2DC \uAC00\uB2A5)", before: summarize(before), after: summarize(after), partial: true });
21412
22372
  }
21413
22373
  for (let i = 0; i < nonEmpty.length; i++) {
21414
22374
  if (assigned[i] === nonEmpty[i].text || normForMatch(assigned[i]) === normForMatch(nonEmpty[i].text)) continue;
21415
- const sp = buildParagraphSplices(nonEmpty[i], assigned[i], _optionalChain([ctx, 'access', _194 => _194.scans, 'access', _195 => _195[nonEmpty[i].sectionIndex], 'optionalAccess', _196 => _196.xml]));
22375
+ const sp = buildParagraphSplices(nonEmpty[i], assigned[i], _optionalChain([ctx, 'access', _216 => _216.scans, 'access', _217 => _217[nonEmpty[i].sectionIndex], 'optionalAccess', _218 => _218.xml]));
21416
22376
  if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21417
22377
  splices.push(...sp);
21418
22378
  sectionIndex = nonEmpty[i].sectionIndex;
@@ -21493,7 +22453,7 @@ async function resolveSectionEntryNames(zip) {
21493
22453
  const paths = sectionPathsFromManifest(xml).filter((p) => zip.file(p) !== null);
21494
22454
  if (paths.length > 0) return paths;
21495
22455
  }
21496
- return Object.keys(zip.files).filter((n) => /[Ss]ection\d+\.xml$/.test(n)).sort(_chunk53XNKPN6cjs.compareSectionPaths);
22456
+ return Object.keys(zip.files).filter((n) => /[Ss]ection\d+\.xml$/.test(n)).sort(_chunkQZCP3UWUcjs.compareSectionPaths);
21497
22457
  }
21498
22458
  function sectionPathsFromManifest(xml) {
21499
22459
  const attr = (tag, name) => {
@@ -21503,7 +22463,7 @@ function sectionPathsFromManifest(xml) {
21503
22463
  const idToHref = /* @__PURE__ */ new Map();
21504
22464
  for (const m of xml.matchAll(/<opf:item(\s(?:"[^"]*"|'[^']*'|[^>"'])*?)\/?>/g)) {
21505
22465
  const id = attr(m[1], "id");
21506
- const href = _chunk53XNKPN6cjs.normalizeSectionHref.call(void 0, attr(m[1], "href"));
22466
+ const href = _chunkQZCP3UWUcjs.normalizeSectionHref.call(void 0, attr(m[1], "href"));
21507
22467
  if (id && href) idToHref.set(id, href);
21508
22468
  }
21509
22469
  const ordered = [];
@@ -21512,7 +22472,7 @@ function sectionPathsFromManifest(xml) {
21512
22472
  if (href) ordered.push(href);
21513
22473
  }
21514
22474
  if (ordered.length > 0) return ordered;
21515
- return Array.from(idToHref.values()).sort(_chunk53XNKPN6cjs.compareSectionPaths);
22475
+ return Array.from(idToHref.values()).sort(_chunkQZCP3UWUcjs.compareSectionPaths);
21516
22476
  }
21517
22477
 
21518
22478
  // src/roundtrip/patcher.ts
@@ -21581,7 +22541,8 @@ async function patchHwpx(original, editedMarkdown, options) {
21581
22541
  try {
21582
22542
  for (let i = 0; i < scans.length; i++) {
21583
22543
  if (sectionSplices[i].length === 0) continue;
21584
- sectionSplices[i].push(...allLinesegRemovalSplices(scans[i].xml));
22544
+ const claimed = sectionSplices[i].filter((s) => s.end > s.start);
22545
+ sectionSplices[i].push(...allLinesegRemovalSplices(scans[i].xml).filter((ls) => !claimed.some((c) => ls.start >= c.start && ls.end <= c.end)));
21585
22546
  const newXml = applySplices(scans[i].xml, sectionSplices[i]);
21586
22547
  replacements.set(sectionPaths[i], encoder.encode(newXml));
21587
22548
  }
@@ -21603,7 +22564,7 @@ async function patchHwpx(original, editedMarkdown, options) {
21603
22564
  }
21604
22565
  }
21605
22566
  let verification;
21606
- if (_optionalChain([options, 'optionalAccess', _197 => _197.verify]) !== false) {
22567
+ if (_optionalChain([options, 'optionalAccess', _219 => _219.verify]) !== false) {
21607
22568
  try {
21608
22569
  const reparsed = await parseHwpxDocument(u8ToArrayBuffer(data));
21609
22570
  verification = diffUnitLists(splitMarkdownUnits(reparsed.markdown), editedUnits);
@@ -21621,17 +22582,17 @@ function buildOrigUnits(blocks) {
21621
22582
  let chunk;
21622
22583
  if (block.type === "paragraph" && block.text && /^\[별표\s*\d+/.test(sanitizeText(block.text))) {
21623
22584
  const next = blocks[i + 1];
21624
- if (_optionalChain([next, 'optionalAccess', _198 => _198.type]) === "paragraph" && next.text && /관련\)?$/.test(next.text)) consume = 2;
21625
- chunk = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, blocks.slice(i, i + consume));
22585
+ if (_optionalChain([next, 'optionalAccess', _220 => _220.type]) === "paragraph" && next.text && /관련\)?$/.test(next.text)) consume = 2;
22586
+ chunk = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, blocks.slice(i, i + consume));
21626
22587
  } else {
21627
- chunk = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, [block]);
22588
+ chunk = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, [block]);
21628
22589
  }
21629
22590
  if (chunk) {
21630
22591
  const subUnits = splitMarkdownUnits(chunk);
21631
22592
  const isFragment = consume === 2 || (block.type === "paragraph" || block.type === "heading") && subUnits.length > 1;
21632
22593
  for (let s = 0; s < subUnits.length; s++) {
21633
22594
  const u = { ...subUnits[s], blockIdx: i, fragment: isFragment || void 0 };
21634
- if (block.type === "table" && _optionalChain([block, 'access', _199 => _199.table, 'optionalAccess', _200 => _200.caption]) && s === 0 && subUnits.length > 1 && u.kind === "text" && u.raw.startsWith("**")) {
22595
+ if (block.type === "table" && _optionalChain([block, 'access', _221 => _221.table, 'optionalAccess', _222 => _222.caption]) && s === 0 && subUnits.length > 1 && u.kind === "text" && u.raw.startsWith("**")) {
21635
22596
  u.role = "caption";
21636
22597
  }
21637
22598
  units.push(u);
@@ -21649,82 +22610,6 @@ function buildTableOrdinals(blocks) {
21649
22610
  }
21650
22611
  return map;
21651
22612
  }
21652
- function alignUnits(a, b) {
21653
- const m = a.length, n = b.length;
21654
- if (m * n > 4e6) {
21655
- const result2 = [];
21656
- let pre = 0;
21657
- while (pre < m && pre < n && a[pre] === b[pre]) {
21658
- result2.push([pre, pre]);
21659
- pre++;
21660
- }
21661
- let suf = 0;
21662
- while (suf < m - pre && suf < n - pre && a[m - 1 - suf] === b[n - 1 - suf]) suf++;
21663
- const aMid = m - pre - suf, bMid = n - pre - suf;
21664
- if (aMid === bMid) {
21665
- for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, pre + i2]);
21666
- } else {
21667
- for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, null]);
21668
- for (let j2 = 0; j2 < bMid; j2++) result2.push([null, pre + j2]);
21669
- }
21670
- for (let s = suf - 1; s >= 0; s--) result2.push([m - 1 - s, n - 1 - s]);
21671
- return result2;
21672
- }
21673
- const dp = Array.from({ length: m + 1 }, () => new Int32Array(n + 1));
21674
- for (let i2 = 1; i2 <= m; i2++) {
21675
- for (let j2 = 1; j2 <= n; j2++) {
21676
- dp[i2][j2] = a[i2 - 1] === b[j2 - 1] ? dp[i2 - 1][j2 - 1] + 1 : Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
21677
- }
21678
- }
21679
- const matches = [];
21680
- let i = m, j = n;
21681
- while (i > 0 && j > 0) {
21682
- if (a[i - 1] === b[j - 1] && dp[i][j] === dp[i - 1][j - 1] + 1) {
21683
- matches.push([i - 1, j - 1]);
21684
- i--;
21685
- j--;
21686
- } else if (dp[i - 1][j] >= dp[i][j - 1]) i--;
21687
- else j--;
21688
- }
21689
- matches.reverse();
21690
- const result = [];
21691
- let ai = 0, bi = 0;
21692
- const flushGap = (aEnd, bEnd) => {
21693
- if (aEnd - ai === bEnd - bi) {
21694
- while (ai < aEnd) result.push([ai++, bi++]);
21695
- return;
21696
- }
21697
- while (ai < aEnd && bi < bEnd) {
21698
- const sim = normalizedSimilarity(a[ai], b[bi]);
21699
- if (sim >= 0.4) {
21700
- if (aEnd - ai > bEnd - bi && bestSimInRange(a, ai + 1, ai + (aEnd - ai) - (bEnd - bi), b[bi]) > sim) {
21701
- result.push([ai++, null]);
21702
- } else if (bEnd - bi > aEnd - ai && bestSimInRange(b, bi + 1, bi + (bEnd - bi) - (aEnd - ai), a[ai]) > sim) {
21703
- result.push([null, bi++]);
21704
- } else {
21705
- result.push([ai++, bi++]);
21706
- }
21707
- } else if (aEnd - ai >= bEnd - bi) result.push([ai++, null]);
21708
- else result.push([null, bi++]);
21709
- }
21710
- while (ai < aEnd) result.push([ai++, null]);
21711
- while (bi < bEnd) result.push([null, bi++]);
21712
- };
21713
- for (const [pi, pj] of matches) {
21714
- flushGap(pi, pj);
21715
- result.push([ai++, bi++]);
21716
- }
21717
- flushGap(m, n);
21718
- return result;
21719
- }
21720
- function bestSimInRange(arr, from, to, target) {
21721
- let best = 0;
21722
- for (let k = from; k <= to && k < arr.length; k++) {
21723
- const s = normalizedSimilarity(arr[k], target);
21724
- if (s > best) best = s;
21725
- }
21726
- return best;
21727
- }
21728
22613
  function resolveParagraphMappings(blocks, scans) {
21729
22614
  const buckets = /* @__PURE__ */ new Map();
21730
22615
  for (const scan of scans) {
@@ -21818,7 +22703,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
21818
22703
  const ti = ctx.tableInsert;
21819
22704
  if (!ti) return skip("\uBB38\uB2E8\u2192\uD45C \uBCC0\uD658 \uBD88\uAC00 \u2014 header \uC5D4\uD2B8\uB9AC(borderFills) \uD574\uC11D \uC2E4\uD328");
21820
22705
  const mapping = ctx.paraMap.get(orig.blockIdx);
21821
- if (!_optionalChain([mapping, 'optionalAccess', _201 => _201.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");
22706
+ if (!_optionalChain([mapping, 'optionalAccess', _223 => _223.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");
21822
22707
  const para = mapping.para;
21823
22708
  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");
21824
22709
  const scan = ctx.scans[para.sectionIndex];
@@ -21846,7 +22731,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
21846
22731
  }
21847
22732
  function patchParagraphUnit(block, orig, edited, ctx, skip) {
21848
22733
  const mapping = ctx.paraMap.get(orig.blockIdx);
21849
- if (!_optionalChain([mapping, 'optionalAccess', _202 => _202.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)");
22734
+ if (!_optionalChain([mapping, 'optionalAccess', _224 => _224.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)");
21850
22735
  if (block.text && block.text.includes("\n")) {
21851
22736
  return skip("\uBB38\uB2E8 \uB0B4 \uAC15\uC81C \uC904\uBC14\uAFC8 \uD3EC\uD568 \u2014 \uC218\uC815 \uC2DC \uC904\uBC14\uAFC8 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0 (v1)");
21852
22737
  }
@@ -21867,7 +22752,7 @@ function patchParagraphUnit(block, orig, edited, ctx, skip) {
21867
22752
  const origPrefix = block.text.split(" ", 1)[0];
21868
22753
  const sp = newPlain.indexOf(" ");
21869
22754
  const newFirst = sp > 0 ? newPlain.slice(0, sp) : newPlain;
21870
- if (newFirst === origPrefix || /^(?:[0-90-9a-zA-Z가-힣]{1,6}[.)\]:]|[([][0-90-9a-zA-Z가-힣]{1,6}[)\]][.:]?|[ⅰ-ⅹⅠ-Ⅹ①-⑮][.)\]:]?)$/u.test(newFirst)) {
22755
+ if (newFirst === origPrefix || AUTONUM_PREFIX_RE.test(newFirst)) {
21871
22756
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
21872
22757
  } else {
21873
22758
  ctx.skipped.push({ reason: "\uC790\uB3D9\uBC88\uD638 \uC811\uB450 \uC2DD\uBCC4 \uC2E4\uD328 \u2014 \uBC88\uD638 \uD3EC\uD568 \uD14D\uC2A4\uD2B8\uB85C \uC801\uC6A9 (\uBDF0\uC5B4\uC5D0\uC11C \uC911\uBCF5 \uD45C\uC2DC \uAC00\uB2A5)", after: summarize(newPlain) });
@@ -21877,7 +22762,7 @@ function patchParagraphUnit(block, orig, edited, ctx, skip) {
21877
22762
  if (sanitizeText(newPlain) !== newPlain) {
21878
22763
  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");
21879
22764
  }
21880
- const splices = buildParagraphSplices(mapping.para, newPlain, _optionalChain([ctx, 'access', _203 => _203.scans, 'access', _204 => _204[mapping.para.sectionIndex], 'optionalAccess', _205 => _205.xml]));
22765
+ const splices = buildParagraphSplices(mapping.para, newPlain, _optionalChain([ctx, 'access', _225 => _225.scans, 'access', _226 => _226[mapping.para.sectionIndex], 'optionalAccess', _227 => _227.xml]));
21881
22766
  if (splices === null) return skip("\uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21882
22767
  ctx.sectionSplices[mapping.para.sectionIndex].push(...splices);
21883
22768
  return 1;
@@ -21961,16 +22846,16 @@ function replaceOleStream(file, path, newData) {
21961
22846
  surgeon.replace(path, newData);
21962
22847
  return surgeon.finish();
21963
22848
  }
21964
- var Surgeon = (_class3 = class {
22849
+ var Surgeon = (_class4 = class {
21965
22850
 
21966
- __init5() {this.fat = []}
22851
+ __init6() {this.fat = []}
21967
22852
  /** FAT 배열을 구성하는 섹터 번호들 (DIFAT 순서) */
21968
- __init6() {this.fatSectors = []}
21969
- __init7() {this.miniFat = []}
21970
- __init8() {this.miniFatSectors = []}
21971
- __init9() {this.dirSectors = []}
21972
- __init10() {this.entries = []}
21973
- constructor(file) {;_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);
22853
+ __init7() {this.fatSectors = []}
22854
+ __init8() {this.miniFat = []}
22855
+ __init9() {this.miniFatSectors = []}
22856
+ __init10() {this.dirSectors = []}
22857
+ __init11() {this.entries = []}
22858
+ constructor(file) {;_class4.prototype.__init6.call(this);_class4.prototype.__init7.call(this);_class4.prototype.__init8.call(this);_class4.prototype.__init9.call(this);_class4.prototype.__init10.call(this);_class4.prototype.__init11.call(this);
21974
22859
  if (file.length < SECTOR || file.readUInt32LE(0) !== 3759263696) {
21975
22860
  throw new OleSurgeonError("OLE \uC2DC\uADF8\uB2C8\uCC98\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
21976
22861
  }
@@ -22063,7 +22948,7 @@ var Surgeon = (_class3 = class {
22063
22948
  /** 디렉토리 트리에서 경로 해석 (형제 = L/R 이진 트리, 자식 = child) */
22064
22949
  findEntry(path) {
22065
22950
  const parts = path.replace(/^\//, "").split("/");
22066
- let scope = _nullishCoalesce(_optionalChain([this, 'access', _206 => _206.entries, 'access', _207 => _207[0], 'optionalAccess', _208 => _208.child]), () => ( -1));
22951
+ let scope = _nullishCoalesce(_optionalChain([this, 'access', _228 => _228.entries, 'access', _229 => _229[0], 'optionalAccess', _230 => _230.child]), () => ( -1));
22067
22952
  let current;
22068
22953
  for (const part of parts) {
22069
22954
  const search = (idx) => {
@@ -22226,7 +23111,7 @@ var Surgeon = (_class3 = class {
22226
23111
  this.flushFat();
22227
23112
  return this.buf;
22228
23113
  }
22229
- }, _class3);
23114
+ }, _class4);
22230
23115
 
22231
23116
  // src/roundtrip/hwp5-patch.ts
22232
23117
  var require3 = _module.createRequire.call(void 0, _chunkGS7T56RPcjs.importMetaUrl);
@@ -22269,7 +23154,7 @@ function readRecordsStrict(stream) {
22269
23154
  function serializeRecords(recs, repl) {
22270
23155
  const parts = [];
22271
23156
  for (let i = 0; i < recs.length; i++) {
22272
- const data = _nullishCoalesce(_optionalChain([repl, 'optionalAccess', _209 => _209.get, 'call', _210 => _210(i)]), () => ( recs[i].data));
23157
+ const data = _nullishCoalesce(_optionalChain([repl, 'optionalAccess', _231 => _231.get, 'call', _232 => _232(i)]), () => ( recs[i].data));
22273
23158
  const ext = data.length >= 4095;
22274
23159
  const header = Buffer.alloc(ext ? 8 : 4);
22275
23160
  header.writeUInt32LE((recs[i].tagId & 1023 | (recs[i].level & 1023) << 10 | (ext ? 4095 : data.length) << 20) >>> 0, 0);
@@ -22392,7 +23277,7 @@ async function patchHwp(original, editedMarkdown, options) {
22392
23277
  return fail(`CFB \uCEE8\uD14C\uC774\uB108 \uD30C\uC2F1 \uC2E4\uD328: ${msg(err)}`);
22393
23278
  }
22394
23279
  const fhEntry = CFB2.find(cfb, "/FileHeader");
22395
- if (!_optionalChain([fhEntry, 'optionalAccess', _211 => _211.content])) return fail("FileHeader \uC2A4\uD2B8\uB9BC\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 HWP 5.x \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4");
23280
+ if (!_optionalChain([fhEntry, 'optionalAccess', _233 => _233.content])) return fail("FileHeader \uC2A4\uD2B8\uB9BC\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 HWP 5.x \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4");
22396
23281
  let flags;
22397
23282
  try {
22398
23283
  flags = parseFileHeader(Buffer.from(fhEntry.content)).flags;
@@ -22414,7 +23299,7 @@ async function patchHwp(original, editedMarkdown, options) {
22414
23299
  const scans = [];
22415
23300
  for (let i = 0; i < sectionPaths.length; i++) {
22416
23301
  const entry = CFB2.find(cfb, sectionPaths[i]);
22417
- if (!_optionalChain([entry, 'optionalAccess', _212 => _212.content])) return fail(`\uC139\uC158 \uC2A4\uD2B8\uB9BC \uC77D\uAE30 \uC2E4\uD328: ${sectionPaths[i]}`);
23302
+ if (!_optionalChain([entry, 'optionalAccess', _234 => _234.content])) return fail(`\uC139\uC158 \uC2A4\uD2B8\uB9BC \uC77D\uAE30 \uC2E4\uD328: ${sectionPaths[i]}`);
22418
23303
  let stream;
22419
23304
  try {
22420
23305
  stream = compressed ? decompressStream(Buffer.from(entry.content)) : Buffer.from(entry.content);
@@ -22465,7 +23350,7 @@ async function patchHwp(original, editedMarkdown, options) {
22465
23350
  }
22466
23351
  }
22467
23352
  let verification;
22468
- if (_optionalChain([options, 'optionalAccess', _213 => _213.verify]) !== false) {
23353
+ if (_optionalChain([options, 'optionalAccess', _235 => _235.verify]) !== false) {
22469
23354
  try {
22470
23355
  const reparsed = parseHwp5Document(Buffer.from(data));
22471
23356
  verification = diffUnitLists(splitMarkdownUnits(reparsed.markdown), editedUnits);
@@ -22554,7 +23439,7 @@ function tableContentScore(irTable, scanTable) {
22554
23439
  for (const [key, scanCell] of scanTable.cells) {
22555
23440
  const comma = key.indexOf(",");
22556
23441
  const r = Number(key.slice(0, comma)), c = Number(key.slice(comma + 1));
22557
- const irCell = _optionalChain([irTable, 'access', _214 => _214.cells, 'access', _215 => _215[r], 'optionalAccess', _216 => _216[c]]);
23442
+ const irCell = _optionalChain([irTable, 'access', _236 => _236.cells, 'access', _237 => _237[r], 'optionalAccess', _238 => _238[c]]);
22558
23443
  if (!irCell) continue;
22559
23444
  const a = normForMatch(scanCell.paras.map((p) => p.rawText).join(" "));
22560
23445
  const b = normForMatch(stripCellTokens(irCell.text));
@@ -22590,7 +23475,7 @@ function handleModified(orig, edited, ctx) {
22590
23475
  }
22591
23476
  function patchParagraph(block, orig, edited, ctx, skip) {
22592
23477
  const mapping = ctx.paraMap.get(orig.blockIdx);
22593
- if (!_optionalChain([mapping, 'optionalAccess', _217 => _217.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)");
23478
+ if (!_optionalChain([mapping, 'optionalAccess', _239 => _239.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)");
22594
23479
  if (block.text && block.text.includes("\n")) {
22595
23480
  return skip("\uBB38\uB2E8 \uB0B4 \uAC15\uC81C \uC904\uBC14\uAFC8 \uD3EC\uD568 \u2014 \uC218\uC815 \uC2DC \uC904\uBC14\uAFC8 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0 (v1)");
22596
23481
  }
@@ -22610,7 +23495,7 @@ function patchParagraph(block, orig, edited, ctx, skip) {
22610
23495
  const origPrefix = block.text.split(" ", 1)[0];
22611
23496
  const sp = newPlain.indexOf(" ");
22612
23497
  const newFirst = sp > 0 ? newPlain.slice(0, sp) : newPlain;
22613
- if (newFirst === origPrefix || /^(?:[0-90-9a-zA-Z가-힣]{1,6}[.)\]:]|[([][0-90-9a-zA-Z가-힣]{1,6}[)\]][.:]?|[ⅰ-ⅹⅠ-Ⅹ①-⑮][.)\]:]?)$/u.test(newFirst)) {
23498
+ if (newFirst === origPrefix || AUTONUM_PREFIX_RE.test(newFirst)) {
22614
23499
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
22615
23500
  } else {
22616
23501
  ctx.skipped.push({ reason: "\uC790\uB3D9\uBC88\uD638 \uC811\uB450 \uC2DD\uBCC4 \uC2E4\uD328 \u2014 \uBC88\uD638 \uD3EC\uD568 \uD14D\uC2A4\uD2B8\uB85C \uC801\uC6A9 (\uBDF0\uC5B4\uC5D0\uC11C \uC911\uBCF5 \uD45C\uC2DC \uAC00\uB2A5)", after: summarize(newPlain) });
@@ -22675,9 +23560,6 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
22675
23560
  }
22676
23561
  return applied;
22677
23562
  }
22678
- function extractImgTags5(inner) {
22679
- return (inner.match(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi) || []).join(" ");
22680
- }
22681
23563
  function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
22682
23564
  if (replicateTableToHtml(table) !== orig.raw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
22683
23565
  const replica = replicateHtmlTable(table);
@@ -22705,7 +23587,7 @@ function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
22705
23587
  const origContent = htmlCellInnerToLines(oc.inner);
22706
23588
  const editedContent = htmlCellInnerToLines(ec.inner);
22707
23589
  if (origContent.hadNonText || editedContent.hadNonText) {
22708
- if (extractImgTags5(oc.inner) !== extractImgTags5(ec.inner)) {
23590
+ if (extractImgTags(oc.inner) !== extractImgTags(ec.inner)) {
22709
23591
  skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
22710
23592
  continue;
22711
23593
  }
@@ -22769,7 +23651,7 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
22769
23651
  };
22770
23652
  const cell = scanTable.cells.get(`${gridR},${gridC}`);
22771
23653
  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)");
22772
- const irCell = _optionalChain([table, 'access', _218 => _218.cells, 'access', _219 => _219[gridR], 'optionalAccess', _220 => _220[gridC]]);
23654
+ const irCell = _optionalChain([table, 'access', _240 => _240.cells, 'access', _241 => _241[gridR], 'optionalAccess', _242 => _242[gridC]]);
22773
23655
  const scanJoined = cell.paras.map((p) => p.rawText).filter((t) => normForMatch(t)).join("\n");
22774
23656
  if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
22775
23657
  if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
@@ -22796,7 +23678,9 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
22796
23678
  }
22797
23679
  }
22798
23680
  if (newLines.length > nonEmpty.length) {
22799
- ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uCD94\uAC00\uB294 \uBB38\uB2E8 \uC0DD\uC131 \uBBF8\uC9C0\uC6D0 \u2014 \uB9C8\uC9C0\uB9C9 \uBB38\uB2E8\uC5D0 \uBCD1\uD569 \uC801\uC6A9", after: summarize(after) });
23681
+ ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uCD94\uAC00\uB294 \uBB38\uB2E8 \uC0DD\uC131 \uBBF8\uC9C0\uC6D0 \u2014 \uB9C8\uC9C0\uB9C9 \uBB38\uB2E8\uC5D0 \uBCD1\uD569 \uC801\uC6A9", after: summarize(after), partial: true });
23682
+ } else if (newLines.length < nonEmpty.length && nonEmpty.length > 1) {
23683
+ ctx.skipped.push({ reason: "\uC140 \uB0B4 \uC904 \uC0AD\uC81C\uB294 \uBB38\uB2E8 \uC81C\uAC70 \uBBF8\uC9C0\uC6D0 \u2014 \uBE48 \uBB38\uB2E8 \uC794\uC874(\uBDF0\uC5B4\uC5D0 \uBE48 \uC904 \uD45C\uC2DC \uAC00\uB2A5)", before: summarize(before), after: summarize(after), partial: true });
22800
23684
  }
22801
23685
  let staged = 0;
22802
23686
  for (let i = 0; i < nonEmpty.length; i++) {
@@ -22984,9 +23868,9 @@ function u8ToArrayBuffer2(u8) {
22984
23868
  function irCellLines(text) {
22985
23869
  return stripCellTokens(sanitizeText(text)).split("\n").map((s) => s.trim()).filter(Boolean);
22986
23870
  }
22987
- var HwpxSession = (_class4 = class _HwpxSession {
23871
+ var HwpxSession = (_class5 = class _HwpxSession {
22988
23872
 
22989
- constructor(state) {;_class4.prototype.__init11.call(this);
23873
+ constructor(state) {;_class5.prototype.__init12.call(this);
22990
23874
  this.state = state;
22991
23875
  }
22992
23876
  /** HWPX 바이트로 세션을 연다 (입력은 복사되어 외부 변이와 격리) */
@@ -23012,7 +23896,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23012
23896
  const block = st.blocks[blockIndex];
23013
23897
  if (!block) return void 0;
23014
23898
  if (block.type === "paragraph" || block.type === "heading") {
23015
- const para = _optionalChain([st, 'access', _221 => _221.paraMap, 'access', _222 => _222.get, 'call', _223 => _223(blockIndex), 'optionalAccess', _224 => _224.para]);
23899
+ const para = _optionalChain([st, 'access', _243 => _243.paraMap, 'access', _244 => _244.get, 'call', _245 => _245(blockIndex), 'optionalAccess', _246 => _246.para]);
23016
23900
  if (!para) return void 0;
23017
23901
  return { kind: "paragraph", sectionIndex: para.sectionIndex, xmlStart: para.start };
23018
23902
  }
@@ -23037,7 +23921,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23037
23921
  if (block.text && block.text.includes("\n")) {
23038
23922
  return { capability: "locked", reason: "\uBB38\uB2E8 \uB0B4 \uAC15\uC81C \uC904\uBC14\uAFC8 \uD3EC\uD568 \u2014 \uC218\uC815 \uC2DC \uC904\uBC14\uAFC8 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0 (v1)" };
23039
23923
  }
23040
- if (!_optionalChain([st, 'access', _225 => _225.paraMap, 'access', _226 => _226.get, 'call', _227 => _227(blockIndex), 'optionalAccess', _228 => _228.para])) {
23924
+ if (!_optionalChain([st, 'access', _247 => _247.paraMap, 'access', _248 => _248.get, 'call', _249 => _249(blockIndex), 'optionalAccess', _250 => _250.para])) {
23041
23925
  return { capability: "locked", reason: "\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)" };
23042
23926
  }
23043
23927
  return { capability: "text" };
@@ -23086,7 +23970,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23086
23970
  this.opQueue = run.then(() => void 0, () => void 0);
23087
23971
  return run;
23088
23972
  }
23089
- __init11() {this.opQueue = Promise.resolve()}
23973
+ __init12() {this.opQueue = Promise.resolve()}
23090
23974
  async patchBlocksInner(edits, options) {
23091
23975
  const st = this.state;
23092
23976
  const skipped = [];
@@ -23103,7 +23987,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23103
23987
  continue;
23104
23988
  }
23105
23989
  if (block.type === "table" && block.table) {
23106
- if (!_optionalChain([edit, 'access', _229 => _229.cells, 'optionalAccess', _230 => _230.length])) {
23990
+ if (!_optionalChain([edit, 'access', _251 => _251.cells, 'optionalAccess', _252 => _252.length])) {
23107
23991
  skipped.push({ reason: "\uD45C \uBE14\uB85D\uC5D0\uB294 cells \uD3B8\uC9D1\uB9CC \uC9C0\uC6D0", before: summarize(_nullishCoalesce(block.table.caption, () => ( "(\uD45C)"))) });
23108
23992
  continue;
23109
23993
  }
@@ -23123,7 +24007,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23123
24007
  skipped.push({ reason: "\uAC19\uC740 \uC140\uC5D0 \uC911\uBCF5 \uD3B8\uC9D1 \u2014 \uBA3C\uC800 \uC801\uC6A9\uB41C \uD3B8\uC9D1 \uC720\uC9C0", after: summarize(cellEdit.text) });
23124
24008
  continue;
23125
24009
  }
23126
- const irCell = _optionalChain([block, 'access', _231 => _231.table, 'access', _232 => _232.cells, 'access', _233 => _233[cellEdit.row], 'optionalAccess', _234 => _234[cellEdit.col]]);
24010
+ const irCell = _optionalChain([block, 'access', _253 => _253.table, 'access', _254 => _254.cells, 'access', _255 => _255[cellEdit.row], 'optionalAccess', _256 => _256[cellEdit.col]]);
23127
24011
  if (!irCell) {
23128
24012
  skipped.push({ reason: `\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16: ${cellEdit.row},${cellEdit.col}`, after: summarize(cellEdit.text) });
23129
24013
  continue;
@@ -23171,6 +24055,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23171
24055
  try {
23172
24056
  for (let s = 0; s < st.scans.length; s++) {
23173
24057
  if (sectionSplices[s].length === 0) continue;
24058
+ sectionSplices[s].push(...allLinesegRemovalSplices(st.scans[s].xml));
23174
24059
  replacements.set(st.sectionPaths[s], encoder.encode(applySplices(st.scans[s].xml, sectionSplices[s])));
23175
24060
  }
23176
24061
  } catch (err) {
@@ -23178,7 +24063,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23178
24063
  }
23179
24064
  if (replacements.size === 0) {
23180
24065
  let changes2;
23181
- if (_optionalChain([options, 'optionalAccess', _235 => _235.verify]) !== false) {
24066
+ if (_optionalChain([options, 'optionalAccess', _257 => _257.verify]) !== false) {
23182
24067
  const units = splitMarkdownUnits(st.markdown);
23183
24068
  changes2 = diffUnitLists(units, units);
23184
24069
  }
@@ -23199,7 +24084,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23199
24084
  }
23200
24085
  this.state = newState;
23201
24086
  let changes;
23202
- if (_optionalChain([options, 'optionalAccess', _236 => _236.verify]) !== false) {
24087
+ if (_optionalChain([options, 'optionalAccess', _258 => _258.verify]) !== false) {
23203
24088
  changes = diffUnitLists(splitMarkdownUnits(beforeMarkdown), splitMarkdownUnits(newState.markdown));
23204
24089
  }
23205
24090
  return { success: true, data: new Uint8Array(data), applied, skipped, changes };
@@ -23219,7 +24104,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23219
24104
  return skip("\uBB38\uB2E8 \uB0B4 \uAC15\uC81C \uC904\uBC14\uAFC8 \uD3EC\uD568 \u2014 \uC218\uC815 \uC2DC \uC904\uBC14\uAFC8 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0 (v1)");
23220
24105
  }
23221
24106
  const mapping = st.paraMap.get(blockIndex);
23222
- if (!_optionalChain([mapping, 'optionalAccess', _237 => _237.para])) {
24107
+ if (!_optionalChain([mapping, 'optionalAccess', _259 => _259.para])) {
23223
24108
  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)");
23224
24109
  }
23225
24110
  let newPlain = newTextRaw.split("\n").map((l) => l.trim()).filter(Boolean).join(" ");
@@ -23227,7 +24112,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23227
24112
  const origPrefix = block.text.split(" ", 1)[0];
23228
24113
  const sp = newPlain.indexOf(" ");
23229
24114
  const newFirst = sp > 0 ? newPlain.slice(0, sp) : newPlain;
23230
- if (newFirst === origPrefix || /^(?:[0-90-9a-zA-Z가-힣]{1,6}[.)\]:]|[([][0-90-9a-zA-Z가-힣]{1,6}[)\]][.:]?|[ⅰ-ⅹⅠ-Ⅹ①-⑮][.)\]:]?)$/u.test(newFirst)) {
24115
+ if (newFirst === origPrefix || AUTONUM_PREFIX_RE.test(newFirst)) {
23231
24116
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
23232
24117
  } else {
23233
24118
  skipped.push({ reason: "\uC790\uB3D9\uBC88\uD638 \uC811\uB450 \uC2DD\uBCC4 \uC2E4\uD328 \u2014 \uBC88\uD638 \uD3EC\uD568 \uD14D\uC2A4\uD2B8\uB85C \uC801\uC6A9 (\uBDF0\uC5B4\uC5D0\uC11C \uC911\uBCF5 \uD45C\uC2DC \uAC00\uB2A5)", after: summarize(newPlain) });
@@ -23239,14 +24124,14 @@ var HwpxSession = (_class4 = class _HwpxSession {
23239
24124
  if (sanitizeText(newPlain) !== newPlain) {
23240
24125
  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");
23241
24126
  }
23242
- const splices = buildParagraphSplices(mapping.para, newPlain, _optionalChain([st, 'access', _238 => _238.scans, 'access', _239 => _239[mapping.para.sectionIndex], 'optionalAccess', _240 => _240.xml]));
24127
+ const splices = buildParagraphSplices(mapping.para, newPlain, _optionalChain([st, 'access', _260 => _260.scans, 'access', _261 => _261[mapping.para.sectionIndex], 'optionalAccess', _262 => _262.xml]));
23243
24128
  if (splices === null) return skip("\uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
23244
24129
  sectionSplices[mapping.para.sectionIndex].push(...splices);
23245
24130
  return 1;
23246
24131
  }
23247
- }, _class4);
24132
+ }, _class5);
23248
24133
  function cellStaticCheck(table, scanTable, r, c) {
23249
- const irCell = _optionalChain([table, 'access', _241 => _241.cells, 'access', _242 => _242[r], 'optionalAccess', _243 => _243[c]]);
24134
+ const irCell = _optionalChain([table, 'access', _263 => _263.cells, 'access', _264 => _264[r], 'optionalAccess', _265 => _265[c]]);
23250
24135
  if (!irCell) return { editable: false, reason: "\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16" };
23251
24136
  const cell = scanTable.cellByAnchor.get(`${r},${c}`);
23252
24137
  if (!cell) return { editable: false, reason: "\uBCD1\uD569 \uC601\uC5ED\uC758 \uBE48 \uCE78\uC774\uAC70\uB098 \uC88C\uD45C \uBD88\uC77C\uCE58" };
@@ -23330,11 +24215,11 @@ var md = new (0, _markdownit2.default)({
23330
24215
  breaks: false
23331
24216
  });
23332
24217
  function renderHtml(markdown, options) {
23333
- const preset = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _244 => _244.preset]), () => ( "default"));
23334
- const css = PRESETS[preset] + (_nullishCoalesce(_optionalChain([options, 'optionalAccess', _245 => _245.extraCss]), () => ( "")));
24218
+ const preset = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _266 => _266.preset]), () => ( "default"));
24219
+ const css = PRESETS[preset] + (_nullishCoalesce(_optionalChain([options, 'optionalAccess', _267 => _267.extraCss]), () => ( "")));
23335
24220
  const body = md.render(markdown);
23336
- const watermark = _optionalChain([options, 'optionalAccess', _246 => _246.watermark]) ? `<div class="watermark">${escapeHtml(options.watermark)}</div>` : "";
23337
- const watermarkCss = _optionalChain([options, 'optionalAccess', _247 => _247.watermark]) ? `
24221
+ const watermark = _optionalChain([options, 'optionalAccess', _268 => _268.watermark]) ? `<div class="watermark">${escapeHtml(options.watermark)}</div>` : "";
24222
+ const watermarkCss = _optionalChain([options, 'optionalAccess', _269 => _269.watermark]) ? `
23338
24223
  .watermark {
23339
24224
  position: fixed;
23340
24225
  top: 50%; left: 50%;
@@ -23365,13 +24250,13 @@ async function htmlToPdf(html, options) {
23365
24250
  try {
23366
24251
  puppeteer = await Promise.resolve().then(() => _interopRequireWildcard(require("puppeteer-core")));
23367
24252
  } catch (e35) {
23368
- throw new (0, _chunk53XNKPN6cjs.KordocError)(
24253
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)(
23369
24254
  "PDF \uC0DD\uC131\uC5D0 puppeteer-core\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC124\uCE58: npm install puppeteer-core"
23370
24255
  );
23371
24256
  }
23372
24257
  const executablePath = _nullishCoalesce(process.env.PUPPETEER_EXECUTABLE_PATH, () => ( findChromiumPath()));
23373
24258
  if (!executablePath) {
23374
- throw new (0, _chunk53XNKPN6cjs.KordocError)(
24259
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)(
23375
24260
  "Chromium \uC2E4\uD589 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. PUPPETEER_EXECUTABLE_PATH \uD658\uACBD\uBCC0\uC218\uB97C \uC124\uC815\uD558\uC138\uC694."
23376
24261
  );
23377
24262
  }
@@ -23383,10 +24268,10 @@ async function htmlToPdf(html, options) {
23383
24268
  try {
23384
24269
  const page = await browser.newPage();
23385
24270
  await page.setContent(html, { waitUntil: "networkidle0" });
23386
- const margin = _optionalChain([options, 'optionalAccess', _248 => _248.margin]);
24271
+ const margin = _optionalChain([options, 'optionalAccess', _270 => _270.margin]);
23387
24272
  const pdf = await page.pdf({
23388
- format: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _249 => _249.pageSize]), () => ( "A4")),
23389
- landscape: _optionalChain([options, 'optionalAccess', _250 => _250.orientation]) === "landscape",
24273
+ format: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _271 => _271.pageSize]), () => ( "A4")),
24274
+ landscape: _optionalChain([options, 'optionalAccess', _272 => _272.orientation]) === "landscape",
23390
24275
  printBackground: true,
23391
24276
  margin: margin ? {
23392
24277
  top: toCss(margin.top),
@@ -23394,9 +24279,9 @@ async function htmlToPdf(html, options) {
23394
24279
  bottom: toCss(margin.bottom),
23395
24280
  left: toCss(margin.left)
23396
24281
  } : void 0,
23397
- displayHeaderFooter: !!(_optionalChain([options, 'optionalAccess', _251 => _251.header]) || _optionalChain([options, 'optionalAccess', _252 => _252.footer])),
23398
- headerTemplate: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _253 => _253.header]), () => ( "<div></div>")),
23399
- footerTemplate: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _254 => _254.footer]), () => ( '<div style="font-size:8pt;width:100%;text-align:center;color:#777;"><span class="pageNumber"></span>/<span class="totalPages"></span></div>'))
24282
+ displayHeaderFooter: !!(_optionalChain([options, 'optionalAccess', _273 => _273.header]) || _optionalChain([options, 'optionalAccess', _274 => _274.footer])),
24283
+ headerTemplate: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _275 => _275.header]), () => ( "<div></div>")),
24284
+ footerTemplate: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _276 => _276.footer]), () => ( '<div style="font-size:8pt;width:100%;text-align:center;color:#777;"><span class="pageNumber"></span>/<span class="totalPages"></span></div>'))
23400
24285
  });
23401
24286
  return Buffer.from(pdf);
23402
24287
  } finally {
@@ -23430,24 +24315,24 @@ async function markdownToPdf(markdown, options) {
23430
24315
  return htmlToPdf(html, options);
23431
24316
  }
23432
24317
  async function blocksToPdf(blocks, options) {
23433
- const markdown = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, blocks);
24318
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, blocks);
23434
24319
  return markdownToPdf(markdown, options);
23435
24320
  }
23436
24321
 
23437
24322
  // src/index.ts
23438
24323
  async function parse(input, options) {
23439
24324
  let buffer;
23440
- const opts = typeof input === "string" && !_optionalChain([options, 'optionalAccess', _255 => _255.filePath]) ? { ...options, filePath: input } : options;
24325
+ const opts = typeof input === "string" && !_optionalChain([options, 'optionalAccess', _277 => _277.filePath]) ? { ...options, filePath: input } : options;
23441
24326
  if (typeof input === "string") {
23442
24327
  try {
23443
24328
  const buf = await _promises.readFile.call(void 0, input);
23444
- buffer = _chunk53XNKPN6cjs.toArrayBuffer.call(void 0, buf);
24329
+ buffer = _chunkQZCP3UWUcjs.toArrayBuffer.call(void 0, buf);
23445
24330
  } catch (err) {
23446
24331
  const msg2 = err instanceof Error && "code" in err && err.code === "ENOENT" ? `\uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${input}` : `\uD30C\uC77C \uC77D\uAE30 \uC2E4\uD328: ${input}`;
23447
24332
  return { success: false, fileType: "unknown", error: msg2, code: "PARSE_ERROR" };
23448
24333
  }
23449
24334
  } else if (Buffer.isBuffer(input)) {
23450
- buffer = _chunk53XNKPN6cjs.toArrayBuffer.call(void 0, input);
24335
+ buffer = _chunkQZCP3UWUcjs.toArrayBuffer.call(void 0, input);
23451
24336
  } else {
23452
24337
  buffer = input;
23453
24338
  }
@@ -23482,21 +24367,21 @@ async function parseHwp3(buffer, options) {
23482
24367
  const { markdown, blocks, metadata, outline, warnings } = parseHwp3Document(buffer, options);
23483
24368
  return { success: true, fileType: "hwp3", markdown, blocks, metadata, outline, warnings };
23484
24369
  } catch (err) {
23485
- return { success: false, fileType: "hwp3", error: err instanceof Error ? err.message : "HWP3 \uD30C\uC2F1 \uC2E4\uD328", code: _chunk53XNKPN6cjs.classifyError.call(void 0, err) };
24370
+ return { success: false, fileType: "hwp3", error: err instanceof Error ? err.message : "HWP3 \uD30C\uC2F1 \uC2E4\uD328", code: _chunkQZCP3UWUcjs.classifyError.call(void 0, err) };
23486
24371
  }
23487
24372
  }
23488
24373
  async function parseHwpx(buffer, options) {
23489
24374
  try {
23490
24375
  const { markdown, blocks, metadata, outline, warnings, images } = await parseHwpxDocument(buffer, options);
23491
- return { success: true, fileType: "hwpx", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _256 => _256.length]) ? images : void 0 };
24376
+ return { success: true, fileType: "hwpx", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _278 => _278.length]) ? images : void 0 };
23492
24377
  } catch (err) {
23493
- return { success: false, fileType: "hwpx", error: err instanceof Error ? err.message : "HWPX \uD30C\uC2F1 \uC2E4\uD328", code: _chunk53XNKPN6cjs.classifyError.call(void 0, err) };
24378
+ return { success: false, fileType: "hwpx", error: err instanceof Error ? err.message : "HWPX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkQZCP3UWUcjs.classifyError.call(void 0, err) };
23494
24379
  }
23495
24380
  }
23496
24381
  async function parseHwp(buffer, options) {
23497
24382
  try {
23498
24383
  const { markdown, blocks, metadata, outline, warnings, images } = parseHwp5Document(Buffer.from(buffer), options);
23499
- if (isDistributionSentinel(markdown) && isComFallbackAvailable() && _optionalChain([options, 'optionalAccess', _257 => _257.filePath])) {
24384
+ if (isDistributionSentinel(markdown) && isComFallbackAvailable() && _optionalChain([options, 'optionalAccess', _279 => _279.filePath])) {
23500
24385
  try {
23501
24386
  const { pages, pageCount, warnings: comWarns } = extractTextViaCom(options.filePath);
23502
24387
  if (pages.some((p) => p && p.trim().length > 0)) {
@@ -23513,15 +24398,15 @@ async function parseHwp(buffer, options) {
23513
24398
  } catch (e36) {
23514
24399
  }
23515
24400
  }
23516
- return { success: true, fileType: "hwp", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _258 => _258.length]) ? images : void 0 };
24401
+ return { success: true, fileType: "hwp", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _280 => _280.length]) ? images : void 0 };
23517
24402
  } catch (err) {
23518
- return { success: false, fileType: "hwp", error: err instanceof Error ? err.message : "HWP \uD30C\uC2F1 \uC2E4\uD328", code: _chunk53XNKPN6cjs.classifyError.call(void 0, err) };
24403
+ return { success: false, fileType: "hwp", error: err instanceof Error ? err.message : "HWP \uD30C\uC2F1 \uC2E4\uD328", code: _chunkQZCP3UWUcjs.classifyError.call(void 0, err) };
23519
24404
  }
23520
24405
  }
23521
24406
  async function parsePdf(buffer, options) {
23522
24407
  let parsePdfDocument;
23523
24408
  try {
23524
- const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./parser-CK5C6FF4.cjs")));
24409
+ const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./parser-RFLPUZ7P.cjs")));
23525
24410
  parsePdfDocument = mod.parsePdfDocument;
23526
24411
  } catch (e37) {
23527
24412
  return {
@@ -23536,7 +24421,7 @@ async function parsePdf(buffer, options) {
23536
24421
  return { success: true, fileType: "pdf", markdown, blocks, metadata, outline, warnings, isImageBased, pageQuality, qualitySummary };
23537
24422
  } catch (err) {
23538
24423
  const isImageBased = err instanceof Error && "isImageBased" in err ? true : void 0;
23539
- return { success: false, fileType: "pdf", error: err instanceof Error ? err.message : "PDF \uD30C\uC2F1 \uC2E4\uD328", code: _chunk53XNKPN6cjs.classifyError.call(void 0, err), isImageBased };
24424
+ return { success: false, fileType: "pdf", error: err instanceof Error ? err.message : "PDF \uD30C\uC2F1 \uC2E4\uD328", code: _chunkQZCP3UWUcjs.classifyError.call(void 0, err), isImageBased };
23540
24425
  }
23541
24426
  }
23542
24427
  async function parseXlsx(buffer, options) {
@@ -23544,7 +24429,7 @@ async function parseXlsx(buffer, options) {
23544
24429
  const { markdown, blocks, metadata, warnings } = await parseXlsxDocument(buffer, options);
23545
24430
  return { success: true, fileType: "xlsx", markdown, blocks, metadata, warnings };
23546
24431
  } catch (err) {
23547
- return { success: false, fileType: "xlsx", error: err instanceof Error ? err.message : "XLSX \uD30C\uC2F1 \uC2E4\uD328", code: _chunk53XNKPN6cjs.classifyError.call(void 0, err) };
24432
+ return { success: false, fileType: "xlsx", error: err instanceof Error ? err.message : "XLSX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkQZCP3UWUcjs.classifyError.call(void 0, err) };
23548
24433
  }
23549
24434
  }
23550
24435
  async function parseXls(buffer, options) {
@@ -23552,15 +24437,15 @@ async function parseXls(buffer, options) {
23552
24437
  const { markdown, blocks, metadata, warnings } = await parseXlsDocument(buffer, options);
23553
24438
  return { success: true, fileType: "xls", markdown, blocks, metadata, warnings };
23554
24439
  } catch (err) {
23555
- return { success: false, fileType: "xls", error: err instanceof Error ? err.message : "XLS \uD30C\uC2F1 \uC2E4\uD328", code: _chunk53XNKPN6cjs.classifyError.call(void 0, err) };
24440
+ return { success: false, fileType: "xls", error: err instanceof Error ? err.message : "XLS \uD30C\uC2F1 \uC2E4\uD328", code: _chunkQZCP3UWUcjs.classifyError.call(void 0, err) };
23556
24441
  }
23557
24442
  }
23558
24443
  async function parseDocx(buffer, options) {
23559
24444
  try {
23560
24445
  const { markdown, blocks, metadata, outline, warnings, images } = await parseDocxDocument(buffer, options);
23561
- return { success: true, fileType: "docx", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _259 => _259.length]) ? images : void 0 };
24446
+ return { success: true, fileType: "docx", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _281 => _281.length]) ? images : void 0 };
23562
24447
  } catch (err) {
23563
- return { success: false, fileType: "docx", error: err instanceof Error ? err.message : "DOCX \uD30C\uC2F1 \uC2E4\uD328", code: _chunk53XNKPN6cjs.classifyError.call(void 0, err) };
24448
+ return { success: false, fileType: "docx", error: err instanceof Error ? err.message : "DOCX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkQZCP3UWUcjs.classifyError.call(void 0, err) };
23564
24449
  }
23565
24450
  }
23566
24451
  async function parseHwpml(buffer, options) {
@@ -23568,16 +24453,16 @@ async function parseHwpml(buffer, options) {
23568
24453
  const { markdown, blocks, metadata, outline, warnings } = parseHwpmlDocument(buffer, options);
23569
24454
  return { success: true, fileType: "hwpml", markdown, blocks, metadata, outline, warnings };
23570
24455
  } catch (err) {
23571
- return { success: false, fileType: "hwpml", error: err instanceof Error ? err.message : "HWPML \uD30C\uC2F1 \uC2E4\uD328", code: _chunk53XNKPN6cjs.classifyError.call(void 0, err) };
24456
+ return { success: false, fileType: "hwpml", error: err instanceof Error ? err.message : "HWPML \uD30C\uC2F1 \uC2E4\uD328", code: _chunkQZCP3UWUcjs.classifyError.call(void 0, err) };
23572
24457
  }
23573
24458
  }
23574
24459
  async function fillForm(input, values, outputFormat = "markdown") {
23575
24460
  let buffer;
23576
24461
  if (typeof input === "string") {
23577
24462
  const buf = await _promises.readFile.call(void 0, input);
23578
- buffer = _chunk53XNKPN6cjs.toArrayBuffer.call(void 0, buf);
24463
+ buffer = _chunkQZCP3UWUcjs.toArrayBuffer.call(void 0, buf);
23579
24464
  } else if (Buffer.isBuffer(input)) {
23580
- buffer = _chunk53XNKPN6cjs.toArrayBuffer.call(void 0, input);
24465
+ buffer = _chunkQZCP3UWUcjs.toArrayBuffer.call(void 0, input);
23581
24466
  } else {
23582
24467
  buffer = input;
23583
24468
  }
@@ -23603,7 +24488,7 @@ async function fillForm(input, values, outputFormat = "markdown") {
23603
24488
  throw new Error(`\uC11C\uC2DD \uD30C\uC2F1 \uC2E4\uD328: ${parsed.error}`);
23604
24489
  }
23605
24490
  const fill = fillFormFields(parsed.blocks, values);
23606
- const markdown = _chunk53XNKPN6cjs.blocksToMarkdown.call(void 0, fill.blocks);
24491
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, fill.blocks);
23607
24492
  if (outputFormat === "hwpx") {
23608
24493
  const hwpxBuffer = await markdownToHwpx(markdown);
23609
24494
  return { output: hwpxBuffer, format: "hwpx", fill };
@@ -23653,5 +24538,13 @@ async function fillForm(input, values, outputFormat = "markdown") {
23653
24538
 
23654
24539
 
23655
24540
 
23656
- exports.HwpxSession = HwpxSession; exports.PRESET_ALIAS = PRESET_ALIAS; exports.VERSION = _chunk53XNKPN6cjs.VERSION; exports.applySplices = applySplices; exports.blocksToMarkdown = _chunk53XNKPN6cjs.blocksToMarkdown; exports.blocksToPdf = blocksToPdf; exports.buildParagraphSplices = buildParagraphSplices; exports.buildRangeSplices = buildRangeSplices; exports.compare = compare; exports.detectFormat = detectFormat; exports.detectOle2Format = detectOle2Format; exports.detectZipFormat = detectZipFormat; exports.diffBlocks = diffBlocks; exports.extractFormFields = extractFormFields; exports.extractFormSchema = extractFormSchema; exports.fillForm = fillForm; exports.fillFormFields = fillFormFields; exports.fillHwpx = fillHwpx; exports.inferFieldType = inferFieldType; exports.isHwpxFile = isHwpxFile; exports.isLabelCell = isLabelCell; exports.isOldHwpFile = isOldHwpFile; exports.isPdfFile = isPdfFile; exports.isZipFile = isZipFile; exports.markdownToHwpx = markdownToHwpx; exports.markdownToPdf = markdownToPdf; exports.normalizeGongmunPreset = normalizeGongmunPreset; exports.openHwpxDocument = openHwpxDocument; exports.parse = parse; exports.parseDocx = parseDocx; exports.parseHwp = parseHwp; exports.parseHwp3 = parseHwp3; exports.parseHwpml = parseHwpml; exports.parseHwpx = parseHwpx; exports.parsePdf = parsePdf; exports.parseXls = parseXls; exports.parseXlsx = parseXlsx; exports.patchHwp = patchHwp; exports.patchHwpx = patchHwpx; exports.patchHwpxBlocks = patchHwpxBlocks; exports.renderHtml = renderHtml; exports.scanSectionXml = scanSectionXml;
24541
+
24542
+
24543
+
24544
+
24545
+
24546
+
24547
+
24548
+
24549
+ exports.HwpxSession = HwpxSession; exports.PRESET_ALIAS = PRESET_ALIAS; exports.SPACE_EM_FIXED = SPACE_EM_FIXED; exports.SPACE_EM_FONT = SPACE_EM_FONT; exports.VERSION = _chunkQZCP3UWUcjs.VERSION; exports.ValueCursor = ValueCursor; exports.applySplices = applySplices; exports.blocksToMarkdown = _chunkQZCP3UWUcjs.blocksToMarkdown; exports.blocksToPdf = blocksToPdf; exports.buildParagraphSplices = buildParagraphSplices; exports.buildRangeSplices = buildRangeSplices; exports.charWidthEm1000 = charWidthEm1000; exports.compare = compare; exports.detectFormat = detectFormat; exports.detectOle2Format = detectOle2Format; exports.detectZipFormat = detectZipFormat; exports.diffBlocks = diffBlocks; exports.extractFormFields = extractFormFields; exports.extractFormSchema = extractFormSchema; exports.fillForm = fillForm; exports.fillFormFields = fillFormFields; exports.fillHwpx = fillHwpx; exports.fitRatioForFewerLines = fitRatioForFewerLines; exports.inferFieldType = inferFieldType; exports.isHwpxFile = isHwpxFile; exports.isLabelCell = isLabelCell; exports.isOldHwpFile = isOldHwpFile; exports.isPdfFile = isPdfFile; exports.isZipFile = isZipFile; exports.markdownToHwpx = markdownToHwpx; exports.markdownToPdf = markdownToPdf; exports.measureTextWidth = measureTextWidth; exports.normalizeGongmunPreset = normalizeGongmunPreset; exports.openHwpxDocument = openHwpxDocument; exports.parse = parse; exports.parseDocx = parseDocx; exports.parseHwp = parseHwp; exports.parseHwp3 = parseHwp3; exports.parseHwpml = parseHwpml; exports.parseHwpx = parseHwpx; exports.parsePdf = parsePdf; exports.parseXls = parseXls; exports.parseXlsx = parseXlsx; exports.patchHwp = patchHwp; exports.patchHwpx = patchHwpx; exports.patchHwpxBlocks = patchHwpxBlocks; exports.renderHtml = renderHtml; exports.scanSectionXml = scanSectionXml; exports.simulateWrap = simulateWrap; exports.simulateWrapKeepWord = simulateWrapKeepWord;
23657
24550
  //# sourceMappingURL=index.cjs.map