kordoc 3.5.4 → 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 (31) hide show
  1. package/README.md +16 -1
  2. package/dist/{-KX7VLNW5.js → -7UC4ZWBS.js} +21 -5
  3. package/dist/{chunk-WEAP42T3.js → chunk-IJJMVTU5.js} +2 -2
  4. package/dist/chunk-IJJMVTU5.js.map +1 -0
  5. package/dist/{chunk-VEB43O2L.js → chunk-MEVKYW55.js} +2 -2
  6. package/dist/chunk-MEVKYW55.js.map +1 -0
  7. package/dist/{chunk-DK2IE43H.js → chunk-NXRABCWW.js} +1584 -701
  8. package/dist/chunk-NXRABCWW.js.map +1 -0
  9. package/dist/{chunk-XZTDYOZV.cjs → chunk-QZCP3UWU.cjs} +2 -2
  10. package/dist/{chunk-XZTDYOZV.cjs.map → chunk-QZCP3UWU.cjs.map} +1 -1
  11. package/dist/cli.js +4 -4
  12. package/dist/index.cjs +1783 -900
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +130 -8
  15. package/dist/index.d.ts +130 -8
  16. package/dist/index.js +1584 -701
  17. package/dist/index.js.map +1 -1
  18. package/dist/mcp.js +3 -3
  19. package/dist/{parser-W5TBEAVX.js → parser-DR5CTZ74.js} +2 -2
  20. package/dist/{parser-CPTBEGQP.cjs → parser-RFLPUZ7P.cjs} +14 -14
  21. package/dist/{parser-CPTBEGQP.cjs.map → parser-RFLPUZ7P.cjs.map} +1 -1
  22. package/dist/{parser-XT65AEDJ.js → parser-ZHJFQR44.js} +2 -2
  23. package/dist/{watch-VOSNRZAY.js → watch-UIX447QV.js} +3 -3
  24. package/package.json +1 -1
  25. package/dist/chunk-DK2IE43H.js.map +0 -1
  26. package/dist/chunk-VEB43O2L.js.map +0 -1
  27. package/dist/chunk-WEAP42T3.js.map +0 -1
  28. /package/dist/{-KX7VLNW5.js.map → -7UC4ZWBS.js.map} +0 -0
  29. /package/dist/{parser-W5TBEAVX.js.map → parser-DR5CTZ74.js.map} +0 -0
  30. /package/dist/{parser-XT65AEDJ.js.map → parser-ZHJFQR44.js.map} +0 -0
  31. /package/dist/{watch-VOSNRZAY.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 _chunkXZTDYOZVcjs = require('./chunk-XZTDYOZV.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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(_chunkXZTDYOZVcjs.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
- _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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 _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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 (_chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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 _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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(_chunkXZTDYOZVcjs.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 (_chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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(_chunkXZTDYOZVcjs.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(_chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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(_chunkXZTDYOZVcjs.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 >= _chunkXZTDYOZVcjs.HEADING_RATIO_H1) level = 1;
1440
- else if (ratio >= _chunkXZTDYOZVcjs.HEADING_RATIO_H2) level = 2;
1441
- else if (ratio >= _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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(_chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.MAX_COLS);
1599
- tableCtx.cell.rowSpan = clampSpan(rs, _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.KordocError)("HWP \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
3684
- if (header.flags & FLAG_ENCRYPTED) throw new (0, _chunkXZTDYOZVcjs.KordocError)("\uC554\uD638\uD654\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
3685
- if (header.flags & FLAG_DRM) throw new (0, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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 _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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 >= _chunkXZTDYOZVcjs.HEADING_RATIO_H1) level = 1;
3787
- else if (ratio >= _chunkXZTDYOZVcjs.HEADING_RATIO_H2) level = 2;
3788
- else if (ratio >= _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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), _chunkXZTDYOZVcjs.MAX_ROWS);
4239
- cols = Math.min(records[i2].data.readUInt16LE(6), _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.MAX_COLS);
4306
- if (rs > 0) rowSpan = Math.min(rs, _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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(_chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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
- _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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: _chunkXZTDYOZVcjs.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(_chunkXZTDYOZVcjs.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
- _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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 = _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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, _chunkXZTDYOZVcjs.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,17 +20528,10 @@ function standardMarker(depth, n) {
20101
20528
  function reportMarker(depth) {
20102
20529
  return REPORT_BULLETS[Math.min(depth, REPORT_BULLETS.length - 1)];
20103
20530
  }
20104
- var MARKER_FULLWIDTH = "\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468\u2469\u246A\u246B\u246C\u246D\u246E\u246F\u2470\u2471\u2472\u2473\u326E\u326F\u3270\u3271\u3272\u3273\u3274\u3275\u3276\u3277\u3278\u3279\u327A\u327B\u25A1\u25CB\u25E6\u25AA\u25C7\u25B3\u25B6\u318D";
20105
20531
  function markerWidth(marker, bodyHeight) {
20106
- const ta = bodyHeight / 2;
20107
- let w = 0;
20108
- for (const c of marker) {
20109
- if (/[가-힣]/.test(c) || MARKER_FULLWIDTH.includes(c)) w += bodyHeight;
20110
- else if (c === "." || c === ",") w += Math.round(bodyHeight * 0.25);
20111
- else if (c === "(" || c === ")") w += Math.round(bodyHeight * 0.45);
20112
- else w += Math.round(ta);
20113
- }
20114
- return Math.round(w + ta);
20532
+ let em = SPACE_EM_FIXED;
20533
+ for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
20534
+ return Math.round(em / 1e3 * bodyHeight);
20115
20535
  }
20116
20536
  function levelIndent(depth, bodyHeight, numbering) {
20117
20537
  const marker = numbering === "report" ? reportMarker(depth) : standardMarker(depth, 0);
@@ -20130,11 +20550,11 @@ function computeSuppression(depths) {
20130
20550
  }
20131
20551
  return keys.map((k) => (_nullishCoalesce(counts.get(k), () => ( 0))) <= 1);
20132
20552
  }
20133
- var GongmunNumberer = (_class2 = class {
20134
- constructor(numbering) {;_class2.prototype.__init4.call(this);
20553
+ var GongmunNumberer = (_class3 = class {
20554
+ constructor(numbering) {;_class3.prototype.__init5.call(this);
20135
20555
  this.numbering = numbering;
20136
20556
  }
20137
- __init4() {this.counts = []}
20557
+ __init5() {this.counts = []}
20138
20558
  /** depth 항목 하나에 대한 마커. suppress=true면 빈 문자열(부호 없음) */
20139
20559
  next(depth, suppress) {
20140
20560
  this.counts.length = depth + 1;
@@ -20146,82 +20566,58 @@ var GongmunNumberer = (_class2 = class {
20146
20566
  reset() {
20147
20567
  this.counts = [];
20148
20568
  }
20149
- }, _class2);
20569
+ }, _class3);
20150
20570
  function mmToHwpunit(mm) {
20151
20571
  return Math.round(mm * 7200 / 25.4);
20152
20572
  }
20153
20573
 
20154
- // src/hwpx/generator.ts
20155
- var NS_SECTION = "http://www.hancom.co.kr/hwpml/2011/section";
20156
- var NS_PARA = "http://www.hancom.co.kr/hwpml/2011/paragraph";
20157
- var NS_HEAD = "http://www.hancom.co.kr/hwpml/2011/head";
20158
- var NS_CORE = "http://www.hancom.co.kr/hwpml/2011/core";
20159
- var NS_OPF = "http://www.idpf.org/2007/opf/";
20160
- var NS_HPF = "http://www.hancom.co.kr/schema/2011/hpf";
20161
- var NS_OCF = "urn:oasis:names:tc:opendocument:xmlns:container";
20162
- var CHAR_NORMAL = 0;
20163
- var CHAR_BOLD = 1;
20164
- var CHAR_ITALIC = 2;
20165
- var CHAR_BOLD_ITALIC = 3;
20166
- var CHAR_CODE = 4;
20167
- var CHAR_H1 = 5;
20168
- var CHAR_H2 = 6;
20169
- var CHAR_H3 = 7;
20170
- var CHAR_H4 = 8;
20171
- var CHAR_TABLE_HEADER = 9;
20172
- var CHAR_QUOTE = 10;
20173
- var PARA_NORMAL = 0;
20174
- var PARA_H1 = 1;
20175
- var PARA_H2 = 2;
20176
- var PARA_H3 = 3;
20177
- var PARA_H4 = 4;
20178
- var PARA_CODE = 5;
20179
- var PARA_QUOTE = 6;
20180
- var PARA_LIST = 7;
20181
- var DEFAULT_TEXT_COLOR = "#000000";
20182
- function resolveTheme(theme) {
20183
- return {
20184
- h1: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _151 => _151.headingColors, 'optionalAccess', _152 => _152[1]]), () => ( DEFAULT_TEXT_COLOR)),
20185
- h2: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _153 => _153.headingColors, 'optionalAccess', _154 => _154[2]]), () => ( DEFAULT_TEXT_COLOR)),
20186
- h3: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _155 => _155.headingColors, 'optionalAccess', _156 => _156[3]]), () => ( DEFAULT_TEXT_COLOR)),
20187
- 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)),
20188
- body: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _161 => _161.bodyColor]), () => ( DEFAULT_TEXT_COLOR)),
20189
- quote: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _162 => _162.quoteColor]), () => ( DEFAULT_TEXT_COLOR)),
20190
- /** quoteColor가 명시되었는지 — blockquote charPr 분기에 사용 (baseline 호환) */
20191
- hasQuoteOption: _optionalChain([theme, 'optionalAccess', _163 => _163.quoteColor]) !== void 0,
20192
- tableHeader: _nullishCoalesce(_nullishCoalesce(_optionalChain([theme, 'optionalAccess', _164 => _164.tableHeaderColor]), () => ( _optionalChain([theme, 'optionalAccess', _165 => _165.bodyColor]))), () => ( DEFAULT_TEXT_COLOR)),
20193
- tableHeaderBold: !!_optionalChain([theme, 'optionalAccess', _166 => _166.tableHeaderBold])
20194
- };
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;
20195
20581
  }
20196
- async function markdownToHwpx(markdown, options) {
20197
- const theme = resolveTheme(_optionalChain([options, 'optionalAccess', _167 => _167.theme]));
20198
- const gongmun = _optionalChain([options, 'optionalAccess', _168 => _168.gongmun]) ? resolveGongmun(options.gongmun) : null;
20199
- const blocks = parseMarkdownToBlocks(markdown);
20200
- const sectionXml = blocksToSectionXml(blocks, theme, gongmun);
20201
- const zip = new (0, _jszip2.default)();
20202
- zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
20203
- zip.file("META-INF/container.xml", generateContainerXml());
20204
- zip.file("Contents/content.hpf", generateManifest());
20205
- zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun));
20206
- zip.file("Contents/section0.xml", sectionXml);
20207
- zip.file("Preview/PrvText.txt", buildPrvText(blocks));
20208
- return await zip.generateAsync({ type: "arraybuffer" });
20582
+ function normalizedSimilarity(a, b) {
20583
+ return similarity(normalize(a), normalize(b));
20209
20584
  }
20210
- function buildPrvText(blocks) {
20211
- const lines = [];
20212
- let bytes = 0;
20213
- for (const b of blocks) {
20214
- const text = b.text || (b.rows ? b.rows.map((r) => r.join(" ")).join("\n") : "");
20215
- if (!text) continue;
20216
- lines.push(text);
20217
- bytes += text.length * 3;
20218
- 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);
20219
20596
  }
20220
- 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];
20221
20615
  }
20222
- function parseMarkdownToBlocks(md2) {
20616
+
20617
+ // src/roundtrip/markdown-units.ts
20618
+ function splitMarkdownUnits(md2) {
20223
20619
  const lines = md2.split("\n");
20224
- const blocks = [];
20620
+ const units = [];
20225
20621
  let i = 0;
20226
20622
  while (i < lines.length) {
20227
20623
  const line = lines[i];
@@ -20229,69 +20625,526 @@ function parseMarkdownToBlocks(md2) {
20229
20625
  i++;
20230
20626
  continue;
20231
20627
  }
20232
- const fenceMatch = line.match(/^(`{3,}|~{3,})(.*)$/);
20233
- if (fenceMatch) {
20234
- const fence = fenceMatch[1];
20235
- const lang = fenceMatch[2].trim();
20236
- const codeLines = [];
20237
- i++;
20238
- while (i < lines.length && !lines[i].startsWith(fence)) {
20239
- 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;
20240
20636
  i++;
20637
+ if (depth <= 0) break;
20241
20638
  }
20242
- if (i < lines.length) i++;
20243
- blocks.push({ type: "code_block", text: codeLines.join("\n"), lang });
20244
- continue;
20245
- }
20246
- if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line.trim())) {
20247
- blocks.push({ type: "hr" });
20248
- i++;
20249
- continue;
20250
- }
20251
- const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
20252
- if (headingMatch) {
20253
- blocks.push({ type: "heading", text: headingMatch[2].trim(), level: headingMatch[1].length });
20254
- i++;
20639
+ units.push({ kind: "html-table", raw: collected2.join("\n"), lines: collected2 });
20255
20640
  continue;
20256
20641
  }
20257
20642
  if (line.trimStart().startsWith("|")) {
20258
- const tableRows = [];
20643
+ const collected2 = [];
20259
20644
  while (i < lines.length && lines[i].trimStart().startsWith("|")) {
20260
- const row = lines[i];
20261
- if (/^[\s|:\-]+$/.test(row)) {
20262
- i++;
20263
- continue;
20264
- }
20265
- const cells = row.split("|").slice(1, -1).map((c) => c.trim());
20266
- if (cells.length > 0) tableRows.push(cells);
20645
+ collected2.push(lines[i]);
20267
20646
  i++;
20268
20647
  }
20269
- if (tableRows.length > 0) blocks.push({ type: "table", rows: tableRows });
20648
+ units.push({ kind: "gfm-table", raw: collected2.join("\n"), lines: collected2 });
20270
20649
  continue;
20271
20650
  }
20272
- if (line.trimStart().startsWith("> ")) {
20273
- const quoteLines = [];
20274
- while (i < lines.length && (lines[i].trimStart().startsWith("> ") || lines[i].trimStart().startsWith(">"))) {
20275
- quoteLines.push(lines[i].replace(/^>\s?/, ""));
20276
- i++;
20277
- }
20278
- for (const ql of quoteLines) {
20279
- blocks.push({ type: "blockquote", text: ql.trim() || "" });
20280
- }
20651
+ if (/^-{3,}\s*$/.test(line.trim())) {
20652
+ units.push({ kind: "separator", raw: line.trim(), lines: [line.trim()] });
20653
+ i++;
20281
20654
  continue;
20282
20655
  }
20283
- const listMatch = line.match(/^(\s*)([-*+]|\d+[.)]) (.+)$/);
20284
- if (listMatch) {
20285
- const indent = Math.floor(listMatch[1].length / 2);
20286
- const ordered = /\d/.test(listMatch[2]);
20287
- 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()] });
20288
20658
  i++;
20289
20659
  continue;
20290
20660
  }
20291
- blocks.push({ type: "paragraph", text: line.trim() });
20292
- 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 });
20293
20667
  }
20294
- 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;
20295
21148
  }
20296
21149
  function parseInlineMarkdown(text) {
20297
21150
  text = text.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1");
@@ -20335,18 +21188,19 @@ function spanToCharPrId(span) {
20335
21188
  function escapeXml(text) {
20336
21189
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
20337
21190
  }
20338
- function generateRuns(text, defaultCharPr = CHAR_NORMAL) {
21191
+ function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
20339
21192
  const spans = parseInlineMarkdown(text);
20340
21193
  return spans.map((span) => {
20341
- 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);
20342
21196
  return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
20343
21197
  }).join("");
20344
21198
  }
20345
- function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL) {
21199
+ function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId) {
20346
21200
  if (paraPrId === PARA_CODE) {
20347
21201
  return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
20348
21202
  }
20349
- const runs = generateRuns(text, charPrId);
21203
+ const runs = generateRuns(text, charPrId, mapCharId);
20350
21204
  return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0">${runs}</hp:p>`;
20351
21205
  }
20352
21206
  function headingParaPrId(level) {
@@ -20386,7 +21240,7 @@ function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_C
20386
21240
  const boldAttr = bold ? ` bold="1"` : "";
20387
21241
  const italicAttr = italic ? ` italic="1"` : "";
20388
21242
  const effFont = bold ? 2 : fontId;
20389
- 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}>
20390
21244
  <hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
20391
21245
  <hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
20392
21246
  <hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
@@ -20405,13 +21259,58 @@ function paraPr(id, opts = {}) {
20405
21259
  <hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
20406
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>
20407
21261
  <hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
20408
- <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"/>
20409
21263
  </hh:paraPr>`;
20410
21264
  }
20411
21265
  var GONGMUN_LIST_BASE = 8;
20412
21266
  var GONGMUN_LIST_LEVELS = 8;
20413
21267
  var GONGMUN_CENTER = GONGMUN_LIST_BASE + GONGMUN_LIST_LEVELS;
20414
- 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 = []) {
20415
21314
  let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
20416
21315
  if (gongmun) {
20417
21316
  body = gongmun.bodyHeight;
@@ -20421,7 +21320,7 @@ function buildCharProperties(theme, gongmun) {
20421
21320
  h3 = body;
20422
21321
  h4 = Math.max(body - 100, 1300);
20423
21322
  }
20424
- const bodyRatio = gongmun ? 95 : 100;
21323
+ const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
20425
21324
  const rows = [
20426
21325
  charPr(0, body, false, false, 0, theme.body, bodyRatio),
20427
21326
  charPr(1, body, true, false, 0, theme.body, bodyRatio),
@@ -20435,6 +21334,14 @@ function buildCharProperties(theme, gongmun) {
20435
21334
  charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, 0, theme.tableHeader),
20436
21335
  charPr(CHAR_QUOTE, body, false, true, 0, theme.quote)
20437
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
+ }
20438
21345
  return `<hh:charProperties itemCnt="${rows.length}">
20439
21346
  ${rows.join("\n")}
20440
21347
  </hh:charProperties>`;
@@ -20477,9 +21384,9 @@ ${base2.join("\n")}
20477
21384
  ${base.join("\n")}
20478
21385
  </hh:paraProperties>`;
20479
21386
  }
20480
- function generateHeaderXml(theme, gongmun) {
20481
- const bodyFace = _optionalChain([gongmun, 'optionalAccess', _169 => _169.bodyFont]) === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5";
20482
- 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);
20483
21390
  const paraPropsXml = buildParaProperties(gongmun);
20484
21391
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
20485
21392
  <hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" xmlns:hc="${NS_CORE}" version="1.4" secCnt="1">
@@ -20535,25 +21442,21 @@ function generateHeaderXml(theme, gongmun) {
20535
21442
  </hh:fontface>
20536
21443
  </hh:fontfaces>
20537
21444
  <hh:borderFills itemCnt="2">
20538
- <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">
20539
21446
  <hh:slash type="NONE" Crooked="0" isCounter="0"/>
20540
21447
  <hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
20541
21448
  <hh:leftBorder type="NONE" width="0.1 mm" color="#000000"/>
20542
21449
  <hh:rightBorder type="NONE" width="0.1 mm" color="#000000"/>
20543
21450
  <hh:topBorder type="NONE" width="0.1 mm" color="#000000"/>
20544
21451
  <hh:bottomBorder type="NONE" width="0.1 mm" color="#000000"/>
20545
- <hh:diagonal type="NONE" width="0.1 mm" color="#000000"/>
20546
- <hh:fillInfo/>
20547
21452
  </hh:borderFill>
20548
- <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">
20549
21454
  <hh:slash type="NONE" Crooked="0" isCounter="0"/>
20550
21455
  <hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
20551
21456
  <hh:leftBorder type="SOLID" width="0.12 mm" color="#000000"/>
20552
21457
  <hh:rightBorder type="SOLID" width="0.12 mm" color="#000000"/>
20553
21458
  <hh:topBorder type="SOLID" width="0.12 mm" color="#000000"/>
20554
21459
  <hh:bottomBorder type="SOLID" width="0.12 mm" color="#000000"/>
20555
- <hh:diagonal type="NONE" width="0.1 mm" color="#000000"/>
20556
- <hh:fillInfo/>
20557
21460
  </hh:borderFill>
20558
21461
  </hh:borderFills>
20559
21462
  ${charPropsXml}
@@ -20600,14 +21503,74 @@ function generateTable(rows, theme) {
20600
21503
  const tdElements = cells.map((cell, colIdx) => {
20601
21504
  const runs = generateRuns(cell, headerCharPr);
20602
21505
  const p = `<hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p>`;
20603
- 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>`;
20604
21507
  }).join("");
20605
21508
  return `<hp:tr>${tdElements}</hp:tr>`;
20606
21509
  }).join("");
20607
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;
20608
- 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>`;
20609
21512
  return `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${tbl}</hp:run></hp:p>`;
20610
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
+ }
20611
21574
  function precomputeGongmunList(blocks, gongmun) {
20612
21575
  const result = /* @__PURE__ */ new Map();
20613
21576
  let i = 0;
@@ -20631,12 +21594,11 @@ function precomputeGongmunList(blocks, gongmun) {
20631
21594
  }
20632
21595
  return result;
20633
21596
  }
20634
- function blocksToSectionXml(blocks, theme, gongmun) {
21597
+ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null) {
20635
21598
  const paraXmls = [];
20636
21599
  let isFirst = true;
20637
21600
  const orderedCounters = {};
20638
21601
  let prevWasOrdered = false;
20639
- const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
20640
21602
  for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
20641
21603
  const block = blocks[blockIdx];
20642
21604
  let xml = "";
@@ -20658,7 +21620,7 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20658
21620
  if (ctr) {
20659
21621
  xml = generateParagraph(ctr[1].trim(), GONGMUN_CENTER);
20660
21622
  } else {
20661
- xml = generateParagraph(block.text || "");
21623
+ xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx) : void 0);
20662
21624
  }
20663
21625
  break;
20664
21626
  }
@@ -20677,12 +21639,12 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20677
21639
  case "list_item": {
20678
21640
  if (gongmun && gongmunList) {
20679
21641
  const info = gongmunList.get(blockIdx);
20680
- const depth = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _170 => _170.depth]), () => ( 0));
20681
- 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]), () => ( ""));
20682
21644
  const content = block.text || "";
20683
21645
  const text = marker2 ? `${marker2} ${content}` : content;
20684
21646
  const listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
20685
- xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr);
21647
+ xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr, fit ? variantMapper(fit, blockIdx) : void 0);
20686
21648
  break;
20687
21649
  }
20688
21650
  const indent = block.indent || 0;
@@ -20718,6 +21680,21 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20718
21680
  xml = generateTable(block.rows, theme);
20719
21681
  }
20720
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
+ }
20721
21698
  }
20722
21699
  if (!xml) continue;
20723
21700
  if (isFirst && block.type !== "table") {
@@ -20738,49 +21715,6 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20738
21715
  </hs:sec>`;
20739
21716
  }
20740
21717
 
20741
- // src/diff/text-diff.ts
20742
- function similarity(a, b) {
20743
- if (a === b) return 1;
20744
- if (!a || !b) return 0;
20745
- const maxLen = Math.max(a.length, b.length);
20746
- if (maxLen === 0) return 1;
20747
- return 1 - levenshtein(a, b) / maxLen;
20748
- }
20749
- function normalizedSimilarity(a, b) {
20750
- return similarity(normalize(a), normalize(b));
20751
- }
20752
- function normalize(s) {
20753
- return s.replace(/\s+/g, " ").trim();
20754
- }
20755
- var MAX_LEVENSHTEIN_LEN = 1e4;
20756
- function levenshtein(a, b) {
20757
- if (a.length + b.length > MAX_LEVENSHTEIN_LEN) {
20758
- const sampleLen = Math.min(500, a.length, b.length);
20759
- let diffs = 0;
20760
- for (let i = 0; i < sampleLen; i++) if (a[i] !== b[i]) diffs++;
20761
- const sampleRate = sampleLen > 0 ? diffs / sampleLen : 1;
20762
- return Math.abs(a.length - b.length) + Math.round(Math.min(a.length, b.length) * sampleRate);
20763
- }
20764
- if (a.length > b.length) [a, b] = [b, a];
20765
- const m = a.length;
20766
- const n = b.length;
20767
- let prev = Array.from({ length: m + 1 }, (_, i) => i);
20768
- let curr = new Array(m + 1);
20769
- for (let j = 1; j <= n; j++) {
20770
- curr[0] = j;
20771
- for (let i = 1; i <= m; i++) {
20772
- if (a[i - 1] === b[j - 1]) {
20773
- curr[i] = prev[i - 1];
20774
- } else {
20775
- curr[i] = 1 + Math.min(prev[i - 1], prev[i], curr[i - 1]);
20776
- }
20777
- }
20778
- ;
20779
- [prev, curr] = [curr, prev];
20780
- }
20781
- return prev[m];
20782
- }
20783
-
20784
21718
  // src/diff/compare.ts
20785
21719
  var SIMILARITY_THRESHOLD = 0.4;
20786
21720
  async function compare(bufferA, bufferB, options) {
@@ -20907,311 +21841,242 @@ function diffTableCells(a, b) {
20907
21841
  if (cellA === void 0) type = "added";
20908
21842
  else if (cellB === void 0) type = "removed";
20909
21843
  else if (cellA === cellB) type = "unchanged";
20910
- else type = "modified";
20911
- row.push({ type, before: cellA, after: cellB });
20912
- }
20913
- result.push(row);
20914
- }
20915
- return result;
20916
- }
20917
-
20918
- // src/roundtrip/patcher.ts
20919
-
20920
-
20921
- // src/roundtrip/markdown-units.ts
20922
- function splitMarkdownUnits(md2) {
20923
- const lines = md2.split("\n");
20924
- const units = [];
20925
- let i = 0;
20926
- while (i < lines.length) {
20927
- const line = lines[i];
20928
- if (!line.trim()) {
20929
- i++;
20930
- continue;
20931
- }
20932
- if (line.trim().startsWith("<table>")) {
20933
- const collected2 = [];
20934
- let depth = 0;
20935
- while (i < lines.length) {
20936
- const l = lines[i];
20937
- collected2.push(l);
20938
- depth += (l.match(/<table>/g) || []).length;
20939
- depth -= (l.match(/<\/table>/g) || []).length;
20940
- i++;
20941
- if (depth <= 0) break;
20942
- }
20943
- units.push({ kind: "html-table", raw: collected2.join("\n"), lines: collected2 });
20944
- continue;
20945
- }
20946
- if (line.trimStart().startsWith("|")) {
20947
- const collected2 = [];
20948
- while (i < lines.length && lines[i].trimStart().startsWith("|")) {
20949
- collected2.push(lines[i]);
20950
- i++;
20951
- }
20952
- units.push({ kind: "gfm-table", raw: collected2.join("\n"), lines: collected2 });
20953
- continue;
20954
- }
20955
- if (/^-{3,}\s*$/.test(line.trim())) {
20956
- units.push({ kind: "separator", raw: line.trim(), lines: [line.trim()] });
20957
- i++;
20958
- continue;
20959
- }
20960
- if (/^!\[image\]\([^)]*\)\s*$/.test(line.trim())) {
20961
- units.push({ kind: "image", raw: line.trim(), lines: [line.trim()] });
20962
- i++;
20963
- continue;
20964
- }
20965
- const collected = [];
20966
- while (i < lines.length && lines[i].trim() && !lines[i].trimStart().startsWith("|") && !lines[i].trim().startsWith("<table>")) {
20967
- collected.push(lines[i].trim());
20968
- i++;
20969
- }
20970
- units.push({ kind: "text", raw: collected.join("\n"), lines: collected });
20971
- }
20972
- return units;
20973
- }
20974
- function escapeGfm(text) {
20975
- return text.replace(/~/g, "\\~");
20976
- }
20977
- var HWP_SHAPE_ALT_TEXT_RE = /(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|이등변 삼각형|직각 삼각형|선|직선|곡선|화살표|굵은 화살표|이중 화살표|오각형|육각형|팔각형|별|[4-8]점별|십자|십자형|구름|구름형|마름모|도넛|평행사변형|사다리꼴|부채꼴|호|반원|물결|번개|하트|빗금|블록 화살표|수식|표|그림|개체|그리기\s?개체|묶음\s?개체|글상자|수식\s?개체|OLE\s?개체)\s?입니다\.?/g;
20978
- function sanitizeText(text) {
20979
- let result = _chunkXZTDYOZVcjs.mapPuaText.call(void 0, text).replace(/[\u{F0000}-\u{FFFFD}]/gu, "").replace(HWP_SHAPE_ALT_TEXT_RE, "").replace(/ +/g, " ").trim();
20980
- if (result.length <= 30 && result.includes(" ")) {
20981
- const tokens = result.split(" ");
20982
- const koreanSingleCharCount = tokens.filter((t) => t.length === 1 && /[가-힯ㄱ-ㆎ]/.test(t)).length;
20983
- if (tokens.length >= 3 && koreanSingleCharCount / tokens.length >= 0.7) {
20984
- result = tokens.join("");
20985
- }
20986
- }
20987
- return result;
20988
- }
20989
- function normForMatch(text) {
20990
- return sanitizeText(text).replace(/\s+/g, " ").trim();
20991
- }
20992
- function unescapeGfm(text) {
20993
- return text.replace(/\\~/g, "~");
20994
- }
20995
- function summarize(text) {
20996
- const t = text.replace(/\s+/g, " ").trim();
20997
- return t.length > 80 ? t.slice(0, 77) + "..." : t;
20998
- }
20999
- function replicateGfmTable(table) {
21000
- const { cells, rows: numRows, cols: numCols } = table;
21001
- if (numRows === 0 || numCols === 0) return null;
21002
- if (numRows === 1 && numCols === 1) return null;
21003
- if (numCols === 1) return null;
21004
- const display = Array.from({ length: numRows }, (_, r) => Array.from({ length: numCols }, (_2, c) => ({ text: "", gridR: r, gridC: c })));
21005
- const skip = /* @__PURE__ */ new Set();
21006
- for (let r = 0; r < numRows; r++) {
21007
- for (let c = 0; c < numCols; c++) {
21008
- if (skip.has(`${r},${c}`)) continue;
21009
- const cell = _optionalChain([cells, 'access', _172 => _172[r], 'optionalAccess', _173 => _173[c]]);
21010
- if (!cell) continue;
21011
- display[r][c] = {
21012
- text: escapeGfm(sanitizeText(cell.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
21013
- gridR: r,
21014
- gridC: c
21015
- };
21016
- for (let dr = 0; dr < cell.rowSpan; dr++) {
21017
- for (let dc = 0; dc < cell.colSpan; dc++) {
21018
- if (dr === 0 && dc === 0) continue;
21019
- if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
21020
- }
21021
- }
21022
- c += cell.colSpan - 1;
21023
- }
21024
- }
21025
- const uniqueRows = [];
21026
- let pendingLabelRow = null;
21027
- for (let r = 0; r < display.length; r++) {
21028
- const row = display[r];
21029
- if (row.every((cell) => cell.text === "")) continue;
21030
- const nonEmptyCols = row.filter((cell) => cell.text !== "");
21031
- const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
21032
- if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
21033
- if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
21034
- pendingLabelRow = row;
21035
- continue;
21036
- }
21037
- if (pendingLabelRow) {
21038
- if (row[0].text === "") row[0] = pendingLabelRow[0];
21039
- else uniqueRows.push(pendingLabelRow);
21040
- pendingLabelRow = null;
21041
- }
21042
- uniqueRows.push(row);
21043
- }
21044
- if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
21045
- return uniqueRows.length > 0 ? uniqueRows : null;
21046
- }
21047
- function parseGfmTable(lines) {
21048
- const rows = [];
21049
- for (const line of lines) {
21050
- const trimmed = line.trim();
21051
- if (!trimmed.startsWith("|")) continue;
21052
- const cells = trimmed.split(/(?<!\\)\|/).slice(1, -1).map((c) => c.trim());
21053
- if (cells.length === 0) continue;
21054
- if (cells.every((c) => /^:?-{3,}:?$/.test(c))) continue;
21055
- rows.push(cells);
21056
- }
21057
- return rows;
21058
- }
21059
- function unescapeGfmCell(text) {
21060
- return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\~/g, "~");
21061
- }
21062
- function replicateCellInnerHtml(cell) {
21063
- if (_optionalChain([cell, 'access', _174 => _174.blocks, 'optionalAccess', _175 => _175.length])) {
21064
- return cell.blocks.map((b) => {
21065
- if (b.type === "table" && b.table) {
21066
- const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
21067
- return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
21068
- }
21069
- if (b.type === "image" && b.text) return `<img src="${b.text}" alt="image">`;
21070
- const t = sanitizeText(_nullishCoalesce(b.text, () => ( "")));
21071
- return t ? t.replace(/\n/g, "<br>") : "";
21072
- }).filter(Boolean).join("<br>");
21073
- }
21074
- return sanitizeText(cell.text).replace(/\n/g, "<br>");
21075
- }
21076
- function replicateTableToHtml(table) {
21077
- const rows = replicateHtmlTable(table);
21078
- const lines = ["<table>"];
21079
- for (let r = 0; r < rows.length; r++) {
21080
- const tag = rows[r].tag;
21081
- const rowHtml = rows[r].cells.map((cell) => {
21082
- const attrs = [];
21083
- if (cell.colSpan > 1) attrs.push(`colspan="${cell.colSpan}"`);
21084
- if (cell.rowSpan > 1) attrs.push(`rowspan="${cell.rowSpan}"`);
21085
- const attrStr = attrs.length ? " " + attrs.join(" ") : "";
21086
- return `<${tag}${attrStr}>${cell.inner}</${tag}>`;
21087
- });
21088
- if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
21089
- }
21090
- lines.push("</table>");
21091
- return lines.join("\n");
21092
- }
21093
- function replicateHtmlTable(table) {
21094
- const { cells, rows: numRows, cols: numCols } = table;
21095
- const skip = /* @__PURE__ */ new Set();
21096
- const result = [];
21097
- for (let r = 0; r < numRows; r++) {
21098
- const tag = r === 0 ? "th" : "td";
21099
- const rowCells = [];
21100
- for (let c = 0; c < numCols; c++) {
21101
- if (skip.has(`${r},${c}`)) continue;
21102
- const cell = _optionalChain([cells, 'access', _176 => _176[r], 'optionalAccess', _177 => _177[c]]);
21103
- if (!cell) continue;
21104
- for (let dr = 0; dr < cell.rowSpan; dr++) {
21105
- for (let dc = 0; dc < cell.colSpan; dc++) {
21106
- if (dr === 0 && dc === 0) continue;
21107
- if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
21108
- }
21109
- }
21110
- rowCells.push({
21111
- inner: replicateCellInnerHtml(cell),
21112
- colSpan: cell.colSpan,
21113
- rowSpan: cell.rowSpan,
21114
- gridR: r,
21115
- gridC: c
21116
- });
21844
+ else type = "modified";
21845
+ row.push({ type, before: cellA, after: cellB });
21117
21846
  }
21118
- if (rowCells.length) result.push({ tag, cells: rowCells });
21847
+ result.push(row);
21119
21848
  }
21120
21849
  return result;
21121
21850
  }
21122
- function parseHtmlTable(raw) {
21123
- const re = /<(\/?)(table|tr|td|th)((?:"[^"]*"|'[^']*'|[^>"'])*?)>/gi;
21124
- let depth = 0;
21125
- let currentRow = null;
21126
- let cellStart = -1;
21127
- let cellInfo = null;
21128
- const rows = [];
21129
- let m;
21130
- while ((m = re.exec(raw)) !== null) {
21131
- const isClose = m[1] === "/";
21132
- const tag = m[2].toLowerCase();
21133
- const attrs = m[3] || "";
21134
- if (tag === "table") {
21135
- depth += isClose ? -1 : 1;
21136
- if (depth < 0) return null;
21137
- 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");
21138
21870
  }
21139
- if (depth !== 1) continue;
21140
- if (tag === "tr") {
21141
- if (!isClose) currentRow = [];
21142
- else if (currentRow) {
21143
- rows.push({ tag: rows.length === 0 ? "th" : "td", cells: currentRow });
21144
- 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");
21145
21951
  }
21146
- } else {
21147
- if (!isClose) {
21148
- const cs = parseInt(_optionalChain([attrs, 'access', _178 => _178.match, 'call', _179 => _179(/colspan\s*=\s*"(\d+)"/i), 'optionalAccess', _180 => _180[1]]) || "1", 10);
21149
- const rs = parseInt(_optionalChain([attrs, 'access', _181 => _181.match, 'call', _182 => _182(/rowspan\s*=\s*"(\d+)"/i), 'optionalAccess', _183 => _183[1]]) || "1", 10);
21150
- cellStart = m.index + m[0].length;
21151
- cellInfo = { colSpan: isNaN(cs) ? 1 : cs, rowSpan: isNaN(rs) ? 1 : rs };
21152
- } else if (cellStart >= 0 && cellInfo && currentRow) {
21153
- currentRow.push({ inner: raw.slice(cellStart, m.index), colSpan: cellInfo.colSpan, rowSpan: cellInfo.rowSpan });
21154
- cellStart = -1;
21155
- 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);
21156
22004
  }
21157
22005
  }
21158
22006
  }
21159
- if (depth !== 0) return null;
21160
- return rows;
21161
- }
21162
- function htmlCellInnerToLines(inner) {
21163
- let hadNonText = false;
21164
- let work = inner;
21165
- if (/<table[\s>]/i.test(work)) {
21166
- hadNonText = true;
21167
- 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) });
21168
22010
  }
21169
- if (/<img\s/i.test(work)) {
21170
- hadNonText = true;
21171
- 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);
21172
22014
  }
21173
- const lines = work.split(/<br\s*\/?>/gi).map((s) => s.trim()).filter((s) => s.length > 0);
21174
- 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;
21175
22020
  }
21176
- function extractTopLevelTables(html) {
21177
- const result = [];
21178
- let depth = 0;
21179
- let start = -1;
21180
- const re = /<(\/?)table(?:[\s>]|>)/gi;
21181
- let m;
21182
- while ((m = re.exec(html)) !== null) {
21183
- if (m[1] !== "/") {
21184
- if (depth === 0) start = m.index;
21185
- depth++;
21186
- } else {
21187
- depth--;
21188
- if (depth === 0 && start >= 0) {
21189
- result.push(html.slice(start, m.index + m[0].length));
21190
- start = -1;
21191
- }
21192
- 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);
21193
22046
  }
21194
22047
  }
21195
- return result;
22048
+ const patched = applySplices(wrapped, splices);
22049
+ return patched.slice(FRAG_OPEN.length, patched.length - FRAG_CLOSE.length);
21196
22050
  }
21197
- function removeNestedTables(html) {
21198
- let result = "";
21199
- let depth = 0;
21200
- const re = /<(\/?)table(?:[\s>]|>)/gi;
21201
- let last = 0;
21202
- let m;
21203
- while ((m = re.exec(html)) !== null) {
21204
- if (m[1] !== "/") {
21205
- if (depth === 0) result += html.slice(last, m.index);
21206
- depth++;
21207
- } else {
21208
- depth--;
21209
- if (depth === 0) last = m.index + m[0].length;
21210
- if (depth < 0) depth = 0;
21211
- }
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));
21212
22065
  }
21213
- if (depth === 0) result += html.slice(last);
21214
- 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) };
21215
22080
  }
21216
22081
 
21217
22082
  // src/roundtrip/table-patch.ts
@@ -21223,37 +22088,89 @@ function patchGfmTable(table, scanTable, orig, edited, ctx, skip) {
21223
22088
  if (replica.length !== origRows.length || replica.some((row, r) => row.length !== origRows[r].length || row.some((c, j) => c.text !== origRows[r][j]))) {
21224
22089
  return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
21225
22090
  }
21226
- 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
+ }
21227
22094
  let applied = 0;
21228
22095
  for (let r = 0; r < origRows.length; r++) {
21229
- if (editedRows[r].length !== origRows[r].length) {
21230
- 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");
21231
22113
  continue;
21232
22114
  }
21233
- for (let c = 0; c < origRows[r].length; c++) {
21234
- if (origRows[r][c] === editedRows[r][c]) continue;
21235
- const { gridR, gridC } = replica[r][c];
21236
- const origTokens = extractCellTokens(origRows[r][c]);
21237
- const editedTokens = extractCellTokens(editedRows[r][c]);
21238
- if (origTokens !== editedTokens) {
21239
- skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
21240
- continue;
21241
- }
21242
- const newLines = unescapeGfmCell(stripCellTokens(editedRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
21243
- const origLines = unescapeGfmCell(stripCellTokens(origRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
21244
- const n = applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, origRows[r][c], editedRows[r][c], origLines.length);
21245
- if (n > 0 && origTokens) {
21246
- ctx.skipped.push({
21247
- 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)",
21248
- before: summarize(origRows[r][c]),
21249
- after: summarize(editedRows[r][c])
21250
- });
21251
- }
21252
- 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
+ });
21253
22125
  }
22126
+ applied += n;
21254
22127
  }
21255
22128
  return applied;
21256
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
+ }
21257
22174
  function patchHtmlTable(table, scanTable, orig, edited, ctx, skip) {
21258
22175
  return patchHtmlTableRaw(table, scanTable, orig.raw, edited.raw, ctx, skip, 0);
21259
22176
  }
@@ -21267,50 +22184,81 @@ function patchHtmlTableRaw(table, scanTable, origRaw, editedRaw, ctx, skip, dept
21267
22184
  }
21268
22185
  const editedRows = parseHtmlTable(editedRaw);
21269
22186
  if (!editedRows) return skip("\uD3B8\uC9D1\uB41C HTML \uD45C \uD30C\uC2F1 \uC2E4\uD328");
21270
- 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
+ }
21271
22190
  let applied = 0;
21272
22191
  for (let r = 0; r < replica.length; r++) {
21273
- if (editedRows[r].cells.length !== replica[r].cells.length) {
21274
- 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`);
21275
22207
  continue;
21276
22208
  }
21277
- for (let c = 0; c < replica[r].cells.length; c++) {
21278
- const oc = replica[r].cells[c];
21279
- const ec = editedRows[r].cells[c];
21280
- if (oc.colSpan !== ec.colSpan || oc.rowSpan !== ec.rowSpan) {
21281
- 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");
21282
22215
  continue;
21283
22216
  }
21284
- if (oc.inner === ec.inner) continue;
21285
- const origContent = htmlCellInnerToLines(oc.inner);
21286
- const editedContent = htmlCellInnerToLines(ec.inner);
21287
- if (origContent.hadNonText || editedContent.hadNonText) {
21288
- if (extractImgTags(oc.inner) !== extractImgTags(ec.inner)) {
21289
- skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
21290
- continue;
21291
- }
21292
- const origTables = extractTopLevelTables(oc.inner);
21293
- const editedTables = extractTopLevelTables(ec.inner);
21294
- if (origTables.length !== editedTables.length) {
21295
- skip("\uC140 \uB0B4 \uC911\uCCA9\uD45C \uCD94\uAC00/\uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0");
21296
- continue;
21297
- }
21298
- if (origTables.join("\n") !== editedTables.join("\n")) {
21299
- applied += patchNestedTables(table, scanTable, oc, origTables, editedTables, ctx, skip, depth);
21300
- }
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;
21301
22222
  }
21302
- if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
21303
- const newLines = editedContent.lines.map((l) => unescapeGfm(l));
21304
- 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);
21305
22225
  }
21306
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
+ }
21307
22231
  }
21308
22232
  return applied;
21309
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
+ }
21310
22258
  function patchNestedTables(table, scanTable, oc, origTables, editedTables, ctx, skip, depth) {
21311
- 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]]);
21312
22260
  const scanCell = scanTable.cellByAnchor.get(`${oc.gridR},${oc.gridC}`);
21313
- 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);
21314
22262
  if (!scanCell || nestedIRs.length !== origTables.length || scanCell.tables.length !== origTables.length) {
21315
22263
  return skip("\uC911\uCCA9\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328");
21316
22264
  }
@@ -21378,7 +22326,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21378
22326
  };
21379
22327
  const cell = scanTable.cellByAnchor.get(`${gridR},${gridC}`);
21380
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)");
21381
- 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]]);
21382
22330
  const scanJoined = cell.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
21383
22331
  if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
21384
22332
  if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
@@ -21401,12 +22349,12 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21401
22349
  if (newLines.length === 0) return 0;
21402
22350
  const target = cell.paragraphs[0];
21403
22351
  if (!target) return skip("\uBE48 \uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uD14D\uC2A4\uD2B8 \uC0BD\uC785 \uBD88\uAC00");
21404
- 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]));
21405
22353
  if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21406
22354
  splices.push(...sp);
21407
22355
  sectionIndex = target.sectionIndex;
21408
22356
  if (newLines.length > 1) {
21409
- 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 });
21410
22358
  }
21411
22359
  } else {
21412
22360
  const assigned = [];
@@ -21418,11 +22366,13 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21418
22366
  }
21419
22367
  }
21420
22368
  if (newLines.length > nonEmpty.length) {
21421
- 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 });
21422
22372
  }
21423
22373
  for (let i = 0; i < nonEmpty.length; i++) {
21424
22374
  if (assigned[i] === nonEmpty[i].text || normForMatch(assigned[i]) === normForMatch(nonEmpty[i].text)) continue;
21425
- 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]));
21426
22376
  if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21427
22377
  splices.push(...sp);
21428
22378
  sectionIndex = nonEmpty[i].sectionIndex;
@@ -21503,7 +22453,7 @@ async function resolveSectionEntryNames(zip) {
21503
22453
  const paths = sectionPathsFromManifest(xml).filter((p) => zip.file(p) !== null);
21504
22454
  if (paths.length > 0) return paths;
21505
22455
  }
21506
- return Object.keys(zip.files).filter((n) => /[Ss]ection\d+\.xml$/.test(n)).sort(_chunkXZTDYOZVcjs.compareSectionPaths);
22456
+ return Object.keys(zip.files).filter((n) => /[Ss]ection\d+\.xml$/.test(n)).sort(_chunkQZCP3UWUcjs.compareSectionPaths);
21507
22457
  }
21508
22458
  function sectionPathsFromManifest(xml) {
21509
22459
  const attr = (tag, name) => {
@@ -21513,7 +22463,7 @@ function sectionPathsFromManifest(xml) {
21513
22463
  const idToHref = /* @__PURE__ */ new Map();
21514
22464
  for (const m of xml.matchAll(/<opf:item(\s(?:"[^"]*"|'[^']*'|[^>"'])*?)\/?>/g)) {
21515
22465
  const id = attr(m[1], "id");
21516
- const href = _chunkXZTDYOZVcjs.normalizeSectionHref.call(void 0, attr(m[1], "href"));
22466
+ const href = _chunkQZCP3UWUcjs.normalizeSectionHref.call(void 0, attr(m[1], "href"));
21517
22467
  if (id && href) idToHref.set(id, href);
21518
22468
  }
21519
22469
  const ordered = [];
@@ -21522,7 +22472,7 @@ function sectionPathsFromManifest(xml) {
21522
22472
  if (href) ordered.push(href);
21523
22473
  }
21524
22474
  if (ordered.length > 0) return ordered;
21525
- return Array.from(idToHref.values()).sort(_chunkXZTDYOZVcjs.compareSectionPaths);
22475
+ return Array.from(idToHref.values()).sort(_chunkQZCP3UWUcjs.compareSectionPaths);
21526
22476
  }
21527
22477
 
21528
22478
  // src/roundtrip/patcher.ts
@@ -21591,7 +22541,8 @@ async function patchHwpx(original, editedMarkdown, options) {
21591
22541
  try {
21592
22542
  for (let i = 0; i < scans.length; i++) {
21593
22543
  if (sectionSplices[i].length === 0) continue;
21594
- 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)));
21595
22546
  const newXml = applySplices(scans[i].xml, sectionSplices[i]);
21596
22547
  replacements.set(sectionPaths[i], encoder.encode(newXml));
21597
22548
  }
@@ -21613,7 +22564,7 @@ async function patchHwpx(original, editedMarkdown, options) {
21613
22564
  }
21614
22565
  }
21615
22566
  let verification;
21616
- if (_optionalChain([options, 'optionalAccess', _197 => _197.verify]) !== false) {
22567
+ if (_optionalChain([options, 'optionalAccess', _219 => _219.verify]) !== false) {
21617
22568
  try {
21618
22569
  const reparsed = await parseHwpxDocument(u8ToArrayBuffer(data));
21619
22570
  verification = diffUnitLists(splitMarkdownUnits(reparsed.markdown), editedUnits);
@@ -21631,17 +22582,17 @@ function buildOrigUnits(blocks) {
21631
22582
  let chunk;
21632
22583
  if (block.type === "paragraph" && block.text && /^\[별표\s*\d+/.test(sanitizeText(block.text))) {
21633
22584
  const next = blocks[i + 1];
21634
- if (_optionalChain([next, 'optionalAccess', _198 => _198.type]) === "paragraph" && next.text && /관련\)?$/.test(next.text)) consume = 2;
21635
- chunk = _chunkXZTDYOZVcjs.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));
21636
22587
  } else {
21637
- chunk = _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, [block]);
22588
+ chunk = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, [block]);
21638
22589
  }
21639
22590
  if (chunk) {
21640
22591
  const subUnits = splitMarkdownUnits(chunk);
21641
22592
  const isFragment = consume === 2 || (block.type === "paragraph" || block.type === "heading") && subUnits.length > 1;
21642
22593
  for (let s = 0; s < subUnits.length; s++) {
21643
22594
  const u = { ...subUnits[s], blockIdx: i, fragment: isFragment || void 0 };
21644
- 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("**")) {
21645
22596
  u.role = "caption";
21646
22597
  }
21647
22598
  units.push(u);
@@ -21659,82 +22610,6 @@ function buildTableOrdinals(blocks) {
21659
22610
  }
21660
22611
  return map;
21661
22612
  }
21662
- function alignUnits(a, b) {
21663
- const m = a.length, n = b.length;
21664
- if (m * n > 4e6) {
21665
- const result2 = [];
21666
- let pre = 0;
21667
- while (pre < m && pre < n && a[pre] === b[pre]) {
21668
- result2.push([pre, pre]);
21669
- pre++;
21670
- }
21671
- let suf = 0;
21672
- while (suf < m - pre && suf < n - pre && a[m - 1 - suf] === b[n - 1 - suf]) suf++;
21673
- const aMid = m - pre - suf, bMid = n - pre - suf;
21674
- if (aMid === bMid) {
21675
- for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, pre + i2]);
21676
- } else {
21677
- for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, null]);
21678
- for (let j2 = 0; j2 < bMid; j2++) result2.push([null, pre + j2]);
21679
- }
21680
- for (let s = suf - 1; s >= 0; s--) result2.push([m - 1 - s, n - 1 - s]);
21681
- return result2;
21682
- }
21683
- const dp = Array.from({ length: m + 1 }, () => new Int32Array(n + 1));
21684
- for (let i2 = 1; i2 <= m; i2++) {
21685
- for (let j2 = 1; j2 <= n; j2++) {
21686
- 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]);
21687
- }
21688
- }
21689
- const matches = [];
21690
- let i = m, j = n;
21691
- while (i > 0 && j > 0) {
21692
- if (a[i - 1] === b[j - 1] && dp[i][j] === dp[i - 1][j - 1] + 1) {
21693
- matches.push([i - 1, j - 1]);
21694
- i--;
21695
- j--;
21696
- } else if (dp[i - 1][j] >= dp[i][j - 1]) i--;
21697
- else j--;
21698
- }
21699
- matches.reverse();
21700
- const result = [];
21701
- let ai = 0, bi = 0;
21702
- const flushGap = (aEnd, bEnd) => {
21703
- if (aEnd - ai === bEnd - bi) {
21704
- while (ai < aEnd) result.push([ai++, bi++]);
21705
- return;
21706
- }
21707
- while (ai < aEnd && bi < bEnd) {
21708
- const sim = normalizedSimilarity(a[ai], b[bi]);
21709
- if (sim >= 0.4) {
21710
- if (aEnd - ai > bEnd - bi && bestSimInRange(a, ai + 1, ai + (aEnd - ai) - (bEnd - bi), b[bi]) > sim) {
21711
- result.push([ai++, null]);
21712
- } else if (bEnd - bi > aEnd - ai && bestSimInRange(b, bi + 1, bi + (bEnd - bi) - (aEnd - ai), a[ai]) > sim) {
21713
- result.push([null, bi++]);
21714
- } else {
21715
- result.push([ai++, bi++]);
21716
- }
21717
- } else if (aEnd - ai >= bEnd - bi) result.push([ai++, null]);
21718
- else result.push([null, bi++]);
21719
- }
21720
- while (ai < aEnd) result.push([ai++, null]);
21721
- while (bi < bEnd) result.push([null, bi++]);
21722
- };
21723
- for (const [pi, pj] of matches) {
21724
- flushGap(pi, pj);
21725
- result.push([ai++, bi++]);
21726
- }
21727
- flushGap(m, n);
21728
- return result;
21729
- }
21730
- function bestSimInRange(arr, from, to, target) {
21731
- let best = 0;
21732
- for (let k = from; k <= to && k < arr.length; k++) {
21733
- const s = normalizedSimilarity(arr[k], target);
21734
- if (s > best) best = s;
21735
- }
21736
- return best;
21737
- }
21738
22613
  function resolveParagraphMappings(blocks, scans) {
21739
22614
  const buckets = /* @__PURE__ */ new Map();
21740
22615
  for (const scan of scans) {
@@ -21828,7 +22703,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
21828
22703
  const ti = ctx.tableInsert;
21829
22704
  if (!ti) return skip("\uBB38\uB2E8\u2192\uD45C \uBCC0\uD658 \uBD88\uAC00 \u2014 header \uC5D4\uD2B8\uB9AC(borderFills) \uD574\uC11D \uC2E4\uD328");
21830
22705
  const mapping = ctx.paraMap.get(orig.blockIdx);
21831
- 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");
21832
22707
  const para = mapping.para;
21833
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");
21834
22709
  const scan = ctx.scans[para.sectionIndex];
@@ -21856,7 +22731,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
21856
22731
  }
21857
22732
  function patchParagraphUnit(block, orig, edited, ctx, skip) {
21858
22733
  const mapping = ctx.paraMap.get(orig.blockIdx);
21859
- 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)");
21860
22735
  if (block.text && block.text.includes("\n")) {
21861
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)");
21862
22737
  }
@@ -21877,7 +22752,7 @@ function patchParagraphUnit(block, orig, edited, ctx, skip) {
21877
22752
  const origPrefix = block.text.split(" ", 1)[0];
21878
22753
  const sp = newPlain.indexOf(" ");
21879
22754
  const newFirst = sp > 0 ? newPlain.slice(0, sp) : newPlain;
21880
- 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)) {
21881
22756
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
21882
22757
  } else {
21883
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) });
@@ -21887,7 +22762,7 @@ function patchParagraphUnit(block, orig, edited, ctx, skip) {
21887
22762
  if (sanitizeText(newPlain) !== newPlain) {
21888
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");
21889
22764
  }
21890
- 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]));
21891
22766
  if (splices === null) return skip("\uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21892
22767
  ctx.sectionSplices[mapping.para.sectionIndex].push(...splices);
21893
22768
  return 1;
@@ -21971,16 +22846,16 @@ function replaceOleStream(file, path, newData) {
21971
22846
  surgeon.replace(path, newData);
21972
22847
  return surgeon.finish();
21973
22848
  }
21974
- var Surgeon = (_class3 = class {
22849
+ var Surgeon = (_class4 = class {
21975
22850
 
21976
- __init5() {this.fat = []}
22851
+ __init6() {this.fat = []}
21977
22852
  /** FAT 배열을 구성하는 섹터 번호들 (DIFAT 순서) */
21978
- __init6() {this.fatSectors = []}
21979
- __init7() {this.miniFat = []}
21980
- __init8() {this.miniFatSectors = []}
21981
- __init9() {this.dirSectors = []}
21982
- __init10() {this.entries = []}
21983
- 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);
21984
22859
  if (file.length < SECTOR || file.readUInt32LE(0) !== 3759263696) {
21985
22860
  throw new OleSurgeonError("OLE \uC2DC\uADF8\uB2C8\uCC98\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
21986
22861
  }
@@ -22073,7 +22948,7 @@ var Surgeon = (_class3 = class {
22073
22948
  /** 디렉토리 트리에서 경로 해석 (형제 = L/R 이진 트리, 자식 = child) */
22074
22949
  findEntry(path) {
22075
22950
  const parts = path.replace(/^\//, "").split("/");
22076
- 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));
22077
22952
  let current;
22078
22953
  for (const part of parts) {
22079
22954
  const search = (idx) => {
@@ -22236,7 +23111,7 @@ var Surgeon = (_class3 = class {
22236
23111
  this.flushFat();
22237
23112
  return this.buf;
22238
23113
  }
22239
- }, _class3);
23114
+ }, _class4);
22240
23115
 
22241
23116
  // src/roundtrip/hwp5-patch.ts
22242
23117
  var require3 = _module.createRequire.call(void 0, _chunkGS7T56RPcjs.importMetaUrl);
@@ -22279,7 +23154,7 @@ function readRecordsStrict(stream) {
22279
23154
  function serializeRecords(recs, repl) {
22280
23155
  const parts = [];
22281
23156
  for (let i = 0; i < recs.length; i++) {
22282
- 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));
22283
23158
  const ext = data.length >= 4095;
22284
23159
  const header = Buffer.alloc(ext ? 8 : 4);
22285
23160
  header.writeUInt32LE((recs[i].tagId & 1023 | (recs[i].level & 1023) << 10 | (ext ? 4095 : data.length) << 20) >>> 0, 0);
@@ -22402,7 +23277,7 @@ async function patchHwp(original, editedMarkdown, options) {
22402
23277
  return fail(`CFB \uCEE8\uD14C\uC774\uB108 \uD30C\uC2F1 \uC2E4\uD328: ${msg(err)}`);
22403
23278
  }
22404
23279
  const fhEntry = CFB2.find(cfb, "/FileHeader");
22405
- 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");
22406
23281
  let flags;
22407
23282
  try {
22408
23283
  flags = parseFileHeader(Buffer.from(fhEntry.content)).flags;
@@ -22424,7 +23299,7 @@ async function patchHwp(original, editedMarkdown, options) {
22424
23299
  const scans = [];
22425
23300
  for (let i = 0; i < sectionPaths.length; i++) {
22426
23301
  const entry = CFB2.find(cfb, sectionPaths[i]);
22427
- 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]}`);
22428
23303
  let stream;
22429
23304
  try {
22430
23305
  stream = compressed ? decompressStream(Buffer.from(entry.content)) : Buffer.from(entry.content);
@@ -22475,7 +23350,7 @@ async function patchHwp(original, editedMarkdown, options) {
22475
23350
  }
22476
23351
  }
22477
23352
  let verification;
22478
- if (_optionalChain([options, 'optionalAccess', _213 => _213.verify]) !== false) {
23353
+ if (_optionalChain([options, 'optionalAccess', _235 => _235.verify]) !== false) {
22479
23354
  try {
22480
23355
  const reparsed = parseHwp5Document(Buffer.from(data));
22481
23356
  verification = diffUnitLists(splitMarkdownUnits(reparsed.markdown), editedUnits);
@@ -22564,7 +23439,7 @@ function tableContentScore(irTable, scanTable) {
22564
23439
  for (const [key, scanCell] of scanTable.cells) {
22565
23440
  const comma = key.indexOf(",");
22566
23441
  const r = Number(key.slice(0, comma)), c = Number(key.slice(comma + 1));
22567
- 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]]);
22568
23443
  if (!irCell) continue;
22569
23444
  const a = normForMatch(scanCell.paras.map((p) => p.rawText).join(" "));
22570
23445
  const b = normForMatch(stripCellTokens(irCell.text));
@@ -22600,7 +23475,7 @@ function handleModified(orig, edited, ctx) {
22600
23475
  }
22601
23476
  function patchParagraph(block, orig, edited, ctx, skip) {
22602
23477
  const mapping = ctx.paraMap.get(orig.blockIdx);
22603
- 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)");
22604
23479
  if (block.text && block.text.includes("\n")) {
22605
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)");
22606
23481
  }
@@ -22620,7 +23495,7 @@ function patchParagraph(block, orig, edited, ctx, skip) {
22620
23495
  const origPrefix = block.text.split(" ", 1)[0];
22621
23496
  const sp = newPlain.indexOf(" ");
22622
23497
  const newFirst = sp > 0 ? newPlain.slice(0, sp) : newPlain;
22623
- 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)) {
22624
23499
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
22625
23500
  } else {
22626
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) });
@@ -22685,9 +23560,6 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
22685
23560
  }
22686
23561
  return applied;
22687
23562
  }
22688
- function extractImgTags5(inner) {
22689
- return (inner.match(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi) || []).join(" ");
22690
- }
22691
23563
  function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
22692
23564
  if (replicateTableToHtml(table) !== orig.raw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
22693
23565
  const replica = replicateHtmlTable(table);
@@ -22715,7 +23587,7 @@ function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
22715
23587
  const origContent = htmlCellInnerToLines(oc.inner);
22716
23588
  const editedContent = htmlCellInnerToLines(ec.inner);
22717
23589
  if (origContent.hadNonText || editedContent.hadNonText) {
22718
- if (extractImgTags5(oc.inner) !== extractImgTags5(ec.inner)) {
23590
+ if (extractImgTags(oc.inner) !== extractImgTags(ec.inner)) {
22719
23591
  skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
22720
23592
  continue;
22721
23593
  }
@@ -22779,7 +23651,7 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
22779
23651
  };
22780
23652
  const cell = scanTable.cells.get(`${gridR},${gridC}`);
22781
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)");
22782
- 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]]);
22783
23655
  const scanJoined = cell.paras.map((p) => p.rawText).filter((t) => normForMatch(t)).join("\n");
22784
23656
  if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
22785
23657
  if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
@@ -22806,7 +23678,9 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
22806
23678
  }
22807
23679
  }
22808
23680
  if (newLines.length > nonEmpty.length) {
22809
- 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 });
22810
23684
  }
22811
23685
  let staged = 0;
22812
23686
  for (let i = 0; i < nonEmpty.length; i++) {
@@ -22994,9 +23868,9 @@ function u8ToArrayBuffer2(u8) {
22994
23868
  function irCellLines(text) {
22995
23869
  return stripCellTokens(sanitizeText(text)).split("\n").map((s) => s.trim()).filter(Boolean);
22996
23870
  }
22997
- var HwpxSession = (_class4 = class _HwpxSession {
23871
+ var HwpxSession = (_class5 = class _HwpxSession {
22998
23872
 
22999
- constructor(state) {;_class4.prototype.__init11.call(this);
23873
+ constructor(state) {;_class5.prototype.__init12.call(this);
23000
23874
  this.state = state;
23001
23875
  }
23002
23876
  /** HWPX 바이트로 세션을 연다 (입력은 복사되어 외부 변이와 격리) */
@@ -23022,7 +23896,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23022
23896
  const block = st.blocks[blockIndex];
23023
23897
  if (!block) return void 0;
23024
23898
  if (block.type === "paragraph" || block.type === "heading") {
23025
- 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]);
23026
23900
  if (!para) return void 0;
23027
23901
  return { kind: "paragraph", sectionIndex: para.sectionIndex, xmlStart: para.start };
23028
23902
  }
@@ -23047,7 +23921,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23047
23921
  if (block.text && block.text.includes("\n")) {
23048
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)" };
23049
23923
  }
23050
- 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])) {
23051
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)" };
23052
23926
  }
23053
23927
  return { capability: "text" };
@@ -23096,7 +23970,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23096
23970
  this.opQueue = run.then(() => void 0, () => void 0);
23097
23971
  return run;
23098
23972
  }
23099
- __init11() {this.opQueue = Promise.resolve()}
23973
+ __init12() {this.opQueue = Promise.resolve()}
23100
23974
  async patchBlocksInner(edits, options) {
23101
23975
  const st = this.state;
23102
23976
  const skipped = [];
@@ -23113,7 +23987,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23113
23987
  continue;
23114
23988
  }
23115
23989
  if (block.type === "table" && block.table) {
23116
- if (!_optionalChain([edit, 'access', _229 => _229.cells, 'optionalAccess', _230 => _230.length])) {
23990
+ if (!_optionalChain([edit, 'access', _251 => _251.cells, 'optionalAccess', _252 => _252.length])) {
23117
23991
  skipped.push({ reason: "\uD45C \uBE14\uB85D\uC5D0\uB294 cells \uD3B8\uC9D1\uB9CC \uC9C0\uC6D0", before: summarize(_nullishCoalesce(block.table.caption, () => ( "(\uD45C)"))) });
23118
23992
  continue;
23119
23993
  }
@@ -23133,7 +24007,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23133
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) });
23134
24008
  continue;
23135
24009
  }
23136
- 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]]);
23137
24011
  if (!irCell) {
23138
24012
  skipped.push({ reason: `\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16: ${cellEdit.row},${cellEdit.col}`, after: summarize(cellEdit.text) });
23139
24013
  continue;
@@ -23181,6 +24055,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23181
24055
  try {
23182
24056
  for (let s = 0; s < st.scans.length; s++) {
23183
24057
  if (sectionSplices[s].length === 0) continue;
24058
+ sectionSplices[s].push(...allLinesegRemovalSplices(st.scans[s].xml));
23184
24059
  replacements.set(st.sectionPaths[s], encoder.encode(applySplices(st.scans[s].xml, sectionSplices[s])));
23185
24060
  }
23186
24061
  } catch (err) {
@@ -23188,7 +24063,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23188
24063
  }
23189
24064
  if (replacements.size === 0) {
23190
24065
  let changes2;
23191
- if (_optionalChain([options, 'optionalAccess', _235 => _235.verify]) !== false) {
24066
+ if (_optionalChain([options, 'optionalAccess', _257 => _257.verify]) !== false) {
23192
24067
  const units = splitMarkdownUnits(st.markdown);
23193
24068
  changes2 = diffUnitLists(units, units);
23194
24069
  }
@@ -23209,7 +24084,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23209
24084
  }
23210
24085
  this.state = newState;
23211
24086
  let changes;
23212
- if (_optionalChain([options, 'optionalAccess', _236 => _236.verify]) !== false) {
24087
+ if (_optionalChain([options, 'optionalAccess', _258 => _258.verify]) !== false) {
23213
24088
  changes = diffUnitLists(splitMarkdownUnits(beforeMarkdown), splitMarkdownUnits(newState.markdown));
23214
24089
  }
23215
24090
  return { success: true, data: new Uint8Array(data), applied, skipped, changes };
@@ -23229,7 +24104,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23229
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)");
23230
24105
  }
23231
24106
  const mapping = st.paraMap.get(blockIndex);
23232
- if (!_optionalChain([mapping, 'optionalAccess', _237 => _237.para])) {
24107
+ if (!_optionalChain([mapping, 'optionalAccess', _259 => _259.para])) {
23233
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)");
23234
24109
  }
23235
24110
  let newPlain = newTextRaw.split("\n").map((l) => l.trim()).filter(Boolean).join(" ");
@@ -23237,7 +24112,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23237
24112
  const origPrefix = block.text.split(" ", 1)[0];
23238
24113
  const sp = newPlain.indexOf(" ");
23239
24114
  const newFirst = sp > 0 ? newPlain.slice(0, sp) : newPlain;
23240
- 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)) {
23241
24116
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
23242
24117
  } else {
23243
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) });
@@ -23249,14 +24124,14 @@ var HwpxSession = (_class4 = class _HwpxSession {
23249
24124
  if (sanitizeText(newPlain) !== newPlain) {
23250
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");
23251
24126
  }
23252
- 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]));
23253
24128
  if (splices === null) return skip("\uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
23254
24129
  sectionSplices[mapping.para.sectionIndex].push(...splices);
23255
24130
  return 1;
23256
24131
  }
23257
- }, _class4);
24132
+ }, _class5);
23258
24133
  function cellStaticCheck(table, scanTable, r, c) {
23259
- 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]]);
23260
24135
  if (!irCell) return { editable: false, reason: "\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16" };
23261
24136
  const cell = scanTable.cellByAnchor.get(`${r},${c}`);
23262
24137
  if (!cell) return { editable: false, reason: "\uBCD1\uD569 \uC601\uC5ED\uC758 \uBE48 \uCE78\uC774\uAC70\uB098 \uC88C\uD45C \uBD88\uC77C\uCE58" };
@@ -23340,11 +24215,11 @@ var md = new (0, _markdownit2.default)({
23340
24215
  breaks: false
23341
24216
  });
23342
24217
  function renderHtml(markdown, options) {
23343
- const preset = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _244 => _244.preset]), () => ( "default"));
23344
- 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]), () => ( "")));
23345
24220
  const body = md.render(markdown);
23346
- const watermark = _optionalChain([options, 'optionalAccess', _246 => _246.watermark]) ? `<div class="watermark">${escapeHtml(options.watermark)}</div>` : "";
23347
- 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]) ? `
23348
24223
  .watermark {
23349
24224
  position: fixed;
23350
24225
  top: 50%; left: 50%;
@@ -23375,13 +24250,13 @@ async function htmlToPdf(html, options) {
23375
24250
  try {
23376
24251
  puppeteer = await Promise.resolve().then(() => _interopRequireWildcard(require("puppeteer-core")));
23377
24252
  } catch (e35) {
23378
- throw new (0, _chunkXZTDYOZVcjs.KordocError)(
24253
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)(
23379
24254
  "PDF \uC0DD\uC131\uC5D0 puppeteer-core\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC124\uCE58: npm install puppeteer-core"
23380
24255
  );
23381
24256
  }
23382
24257
  const executablePath = _nullishCoalesce(process.env.PUPPETEER_EXECUTABLE_PATH, () => ( findChromiumPath()));
23383
24258
  if (!executablePath) {
23384
- throw new (0, _chunkXZTDYOZVcjs.KordocError)(
24259
+ throw new (0, _chunkQZCP3UWUcjs.KordocError)(
23385
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."
23386
24261
  );
23387
24262
  }
@@ -23393,10 +24268,10 @@ async function htmlToPdf(html, options) {
23393
24268
  try {
23394
24269
  const page = await browser.newPage();
23395
24270
  await page.setContent(html, { waitUntil: "networkidle0" });
23396
- const margin = _optionalChain([options, 'optionalAccess', _248 => _248.margin]);
24271
+ const margin = _optionalChain([options, 'optionalAccess', _270 => _270.margin]);
23397
24272
  const pdf = await page.pdf({
23398
- format: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _249 => _249.pageSize]), () => ( "A4")),
23399
- 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",
23400
24275
  printBackground: true,
23401
24276
  margin: margin ? {
23402
24277
  top: toCss(margin.top),
@@ -23404,9 +24279,9 @@ async function htmlToPdf(html, options) {
23404
24279
  bottom: toCss(margin.bottom),
23405
24280
  left: toCss(margin.left)
23406
24281
  } : void 0,
23407
- displayHeaderFooter: !!(_optionalChain([options, 'optionalAccess', _251 => _251.header]) || _optionalChain([options, 'optionalAccess', _252 => _252.footer])),
23408
- headerTemplate: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _253 => _253.header]), () => ( "<div></div>")),
23409
- 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>'))
23410
24285
  });
23411
24286
  return Buffer.from(pdf);
23412
24287
  } finally {
@@ -23440,24 +24315,24 @@ async function markdownToPdf(markdown, options) {
23440
24315
  return htmlToPdf(html, options);
23441
24316
  }
23442
24317
  async function blocksToPdf(blocks, options) {
23443
- const markdown = _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, blocks);
24318
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, blocks);
23444
24319
  return markdownToPdf(markdown, options);
23445
24320
  }
23446
24321
 
23447
24322
  // src/index.ts
23448
24323
  async function parse(input, options) {
23449
24324
  let buffer;
23450
- 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;
23451
24326
  if (typeof input === "string") {
23452
24327
  try {
23453
24328
  const buf = await _promises.readFile.call(void 0, input);
23454
- buffer = _chunkXZTDYOZVcjs.toArrayBuffer.call(void 0, buf);
24329
+ buffer = _chunkQZCP3UWUcjs.toArrayBuffer.call(void 0, buf);
23455
24330
  } catch (err) {
23456
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}`;
23457
24332
  return { success: false, fileType: "unknown", error: msg2, code: "PARSE_ERROR" };
23458
24333
  }
23459
24334
  } else if (Buffer.isBuffer(input)) {
23460
- buffer = _chunkXZTDYOZVcjs.toArrayBuffer.call(void 0, input);
24335
+ buffer = _chunkQZCP3UWUcjs.toArrayBuffer.call(void 0, input);
23461
24336
  } else {
23462
24337
  buffer = input;
23463
24338
  }
@@ -23492,21 +24367,21 @@ async function parseHwp3(buffer, options) {
23492
24367
  const { markdown, blocks, metadata, outline, warnings } = parseHwp3Document(buffer, options);
23493
24368
  return { success: true, fileType: "hwp3", markdown, blocks, metadata, outline, warnings };
23494
24369
  } catch (err) {
23495
- return { success: false, fileType: "hwp3", error: err instanceof Error ? err.message : "HWP3 \uD30C\uC2F1 \uC2E4\uD328", code: _chunkXZTDYOZVcjs.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) };
23496
24371
  }
23497
24372
  }
23498
24373
  async function parseHwpx(buffer, options) {
23499
24374
  try {
23500
24375
  const { markdown, blocks, metadata, outline, warnings, images } = await parseHwpxDocument(buffer, options);
23501
- 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 };
23502
24377
  } catch (err) {
23503
- return { success: false, fileType: "hwpx", error: err instanceof Error ? err.message : "HWPX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkXZTDYOZVcjs.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) };
23504
24379
  }
23505
24380
  }
23506
24381
  async function parseHwp(buffer, options) {
23507
24382
  try {
23508
24383
  const { markdown, blocks, metadata, outline, warnings, images } = parseHwp5Document(Buffer.from(buffer), options);
23509
- if (isDistributionSentinel(markdown) && isComFallbackAvailable() && _optionalChain([options, 'optionalAccess', _257 => _257.filePath])) {
24384
+ if (isDistributionSentinel(markdown) && isComFallbackAvailable() && _optionalChain([options, 'optionalAccess', _279 => _279.filePath])) {
23510
24385
  try {
23511
24386
  const { pages, pageCount, warnings: comWarns } = extractTextViaCom(options.filePath);
23512
24387
  if (pages.some((p) => p && p.trim().length > 0)) {
@@ -23523,15 +24398,15 @@ async function parseHwp(buffer, options) {
23523
24398
  } catch (e36) {
23524
24399
  }
23525
24400
  }
23526
- 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 };
23527
24402
  } catch (err) {
23528
- return { success: false, fileType: "hwp", error: err instanceof Error ? err.message : "HWP \uD30C\uC2F1 \uC2E4\uD328", code: _chunkXZTDYOZVcjs.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) };
23529
24404
  }
23530
24405
  }
23531
24406
  async function parsePdf(buffer, options) {
23532
24407
  let parsePdfDocument;
23533
24408
  try {
23534
- const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./parser-CPTBEGQP.cjs")));
24409
+ const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./parser-RFLPUZ7P.cjs")));
23535
24410
  parsePdfDocument = mod.parsePdfDocument;
23536
24411
  } catch (e37) {
23537
24412
  return {
@@ -23546,7 +24421,7 @@ async function parsePdf(buffer, options) {
23546
24421
  return { success: true, fileType: "pdf", markdown, blocks, metadata, outline, warnings, isImageBased, pageQuality, qualitySummary };
23547
24422
  } catch (err) {
23548
24423
  const isImageBased = err instanceof Error && "isImageBased" in err ? true : void 0;
23549
- return { success: false, fileType: "pdf", error: err instanceof Error ? err.message : "PDF \uD30C\uC2F1 \uC2E4\uD328", code: _chunkXZTDYOZVcjs.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 };
23550
24425
  }
23551
24426
  }
23552
24427
  async function parseXlsx(buffer, options) {
@@ -23554,7 +24429,7 @@ async function parseXlsx(buffer, options) {
23554
24429
  const { markdown, blocks, metadata, warnings } = await parseXlsxDocument(buffer, options);
23555
24430
  return { success: true, fileType: "xlsx", markdown, blocks, metadata, warnings };
23556
24431
  } catch (err) {
23557
- return { success: false, fileType: "xlsx", error: err instanceof Error ? err.message : "XLSX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkXZTDYOZVcjs.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) };
23558
24433
  }
23559
24434
  }
23560
24435
  async function parseXls(buffer, options) {
@@ -23562,15 +24437,15 @@ async function parseXls(buffer, options) {
23562
24437
  const { markdown, blocks, metadata, warnings } = await parseXlsDocument(buffer, options);
23563
24438
  return { success: true, fileType: "xls", markdown, blocks, metadata, warnings };
23564
24439
  } catch (err) {
23565
- return { success: false, fileType: "xls", error: err instanceof Error ? err.message : "XLS \uD30C\uC2F1 \uC2E4\uD328", code: _chunkXZTDYOZVcjs.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) };
23566
24441
  }
23567
24442
  }
23568
24443
  async function parseDocx(buffer, options) {
23569
24444
  try {
23570
24445
  const { markdown, blocks, metadata, outline, warnings, images } = await parseDocxDocument(buffer, options);
23571
- 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 };
23572
24447
  } catch (err) {
23573
- return { success: false, fileType: "docx", error: err instanceof Error ? err.message : "DOCX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkXZTDYOZVcjs.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) };
23574
24449
  }
23575
24450
  }
23576
24451
  async function parseHwpml(buffer, options) {
@@ -23578,16 +24453,16 @@ async function parseHwpml(buffer, options) {
23578
24453
  const { markdown, blocks, metadata, outline, warnings } = parseHwpmlDocument(buffer, options);
23579
24454
  return { success: true, fileType: "hwpml", markdown, blocks, metadata, outline, warnings };
23580
24455
  } catch (err) {
23581
- return { success: false, fileType: "hwpml", error: err instanceof Error ? err.message : "HWPML \uD30C\uC2F1 \uC2E4\uD328", code: _chunkXZTDYOZVcjs.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) };
23582
24457
  }
23583
24458
  }
23584
24459
  async function fillForm(input, values, outputFormat = "markdown") {
23585
24460
  let buffer;
23586
24461
  if (typeof input === "string") {
23587
24462
  const buf = await _promises.readFile.call(void 0, input);
23588
- buffer = _chunkXZTDYOZVcjs.toArrayBuffer.call(void 0, buf);
24463
+ buffer = _chunkQZCP3UWUcjs.toArrayBuffer.call(void 0, buf);
23589
24464
  } else if (Buffer.isBuffer(input)) {
23590
- buffer = _chunkXZTDYOZVcjs.toArrayBuffer.call(void 0, input);
24465
+ buffer = _chunkQZCP3UWUcjs.toArrayBuffer.call(void 0, input);
23591
24466
  } else {
23592
24467
  buffer = input;
23593
24468
  }
@@ -23613,7 +24488,7 @@ async function fillForm(input, values, outputFormat = "markdown") {
23613
24488
  throw new Error(`\uC11C\uC2DD \uD30C\uC2F1 \uC2E4\uD328: ${parsed.error}`);
23614
24489
  }
23615
24490
  const fill = fillFormFields(parsed.blocks, values);
23616
- const markdown = _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, fill.blocks);
24491
+ const markdown = _chunkQZCP3UWUcjs.blocksToMarkdown.call(void 0, fill.blocks);
23617
24492
  if (outputFormat === "hwpx") {
23618
24493
  const hwpxBuffer = await markdownToHwpx(markdown);
23619
24494
  return { output: hwpxBuffer, format: "hwpx", fill };
@@ -23663,5 +24538,13 @@ async function fillForm(input, values, outputFormat = "markdown") {
23663
24538
 
23664
24539
 
23665
24540
 
23666
- exports.HwpxSession = HwpxSession; exports.PRESET_ALIAS = PRESET_ALIAS; exports.VERSION = _chunkXZTDYOZVcjs.VERSION; exports.applySplices = applySplices; exports.blocksToMarkdown = _chunkXZTDYOZVcjs.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;
23667
24550
  //# sourceMappingURL=index.cjs.map