kordoc 3.5.4 → 3.8.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 +23 -1
  2. package/dist/{-KX7VLNW5.js → -ATVQYFSW.js} +21 -5
  3. package/dist/{chunk-WEAP42T3.js → chunk-3R3YK7EM.js} +2 -2
  4. package/dist/chunk-3R3YK7EM.js.map +1 -0
  5. package/dist/{chunk-XZTDYOZV.cjs → chunk-ITJIALN5.cjs} +2 -2
  6. package/dist/{chunk-XZTDYOZV.cjs.map → chunk-ITJIALN5.cjs.map} +1 -1
  7. package/dist/{chunk-VEB43O2L.js → chunk-QV25HMU7.js} +2 -2
  8. package/dist/chunk-QV25HMU7.js.map +1 -0
  9. package/dist/{chunk-DK2IE43H.js → chunk-SLKF72QF.js} +1682 -718
  10. package/dist/chunk-SLKF72QF.js.map +1 -0
  11. package/dist/cli.js +4 -4
  12. package/dist/index.cjs +1908 -944
  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 +1681 -717
  17. package/dist/index.js.map +1 -1
  18. package/dist/mcp.js +3 -3
  19. package/dist/{parser-W5TBEAVX.js → parser-7G5F7PT2.js} +2 -2
  20. package/dist/{parser-XT65AEDJ.js → parser-DCK42RMA.js} +2 -2
  21. package/dist/{parser-CPTBEGQP.cjs → parser-GUSJH44K.cjs} +14 -14
  22. package/dist/{parser-CPTBEGQP.cjs.map → parser-GUSJH44K.cjs.map} +1 -1
  23. package/dist/{watch-VOSNRZAY.js → watch-GVZESOCE.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 → -ATVQYFSW.js.map} +0 -0
  29. /package/dist/{parser-W5TBEAVX.js.map → parser-7G5F7PT2.js.map} +0 -0
  30. /package/dist/{parser-XT65AEDJ.js.map → parser-DCK42RMA.js.map} +0 -0
  31. /package/dist/{watch-VOSNRZAY.js.map → watch-GVZESOCE.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 _chunkITJIALN5cjs = require('./chunk-ITJIALN5.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, _chunkITJIALN5cjs.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, _chunkITJIALN5cjs.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(_chunkITJIALN5cjs.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
+ _chunkITJIALN5cjs.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, _chunkITJIALN5cjs.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, _chunkITJIALN5cjs.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, _chunkITJIALN5cjs.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, _chunkITJIALN5cjs.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 _chunkITJIALN5cjs.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 = _chunkITJIALN5cjs.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) {
@@ -1215,57 +1215,62 @@ async function extractImagesFromZip(zip, blocks, decompressed, warnings) {
1215
1215
  let imageIndex = 0;
1216
1216
  const imageBlocks = [];
1217
1217
  collectImageBlocks(blocks, imageBlocks);
1218
+ const resolved = /* @__PURE__ */ new Map();
1218
1219
  for (const { block, ownerCell } of imageBlocks) {
1219
1220
  if (block.type !== "image" || !block.text) continue;
1220
1221
  const ref = block.text;
1221
- const candidates = [
1222
- `BinData/${ref}`,
1223
- `Contents/BinData/${ref}`,
1224
- ref
1225
- // 절대 경로일 수도 있음
1226
- ];
1227
- let resolvedPath = null;
1228
- if (!ref.includes(".")) {
1229
- const prefixes = [`BinData/${ref}`, `Contents/BinData/${ref}`];
1230
- for (const prefix of prefixes) {
1231
- const match = zip.file(new RegExp(`^${prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.[a-zA-Z0-9]+$`));
1232
- if (match.length > 0) {
1233
- resolvedPath = match[0].name;
1234
- break;
1222
+ let img = resolved.get(ref);
1223
+ if (img === void 0) {
1224
+ img = null;
1225
+ const candidates = [
1226
+ `BinData/${ref}`,
1227
+ `Contents/BinData/${ref}`,
1228
+ ref
1229
+ // 절대 경로일 수도 있음
1230
+ ];
1231
+ let resolvedPath = null;
1232
+ if (!ref.includes(".")) {
1233
+ const prefixes = [`BinData/${ref}`, `Contents/BinData/${ref}`];
1234
+ for (const prefix of prefixes) {
1235
+ const match = zip.file(new RegExp(`^${prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.[a-zA-Z0-9]+$`));
1236
+ if (match.length > 0) {
1237
+ resolvedPath = match[0].name;
1238
+ break;
1239
+ }
1235
1240
  }
1236
1241
  }
1237
- }
1238
- let found = false;
1239
- const allCandidates = resolvedPath ? [resolvedPath, ...candidates] : candidates;
1240
- for (const path of allCandidates) {
1241
- if (_chunkXZTDYOZVcjs.isPathTraversal.call(void 0, path)) continue;
1242
- const file = zip.file(path);
1243
- if (!file) continue;
1244
- try {
1245
- const data = await file.async("uint8array");
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)");
1248
- const actualPath = path;
1249
- const ext = actualPath.includes(".") ? actualPath.split(".").pop() || "png" : "png";
1250
- const mimeType = imageExtToMime(ext);
1251
- imageIndex++;
1252
- const filename = `image_${String(imageIndex).padStart(3, "0")}.${mimeToExt(mimeType)}`;
1253
- images.push({ filename, data, mimeType });
1254
- block.text = filename;
1255
- block.imageData = { data, mimeType, filename: ref };
1256
- if (ownerCell) ownerCell.text = ownerCell.text.replace(`![image](${ref})`, `![image](${filename})`);
1257
- found = true;
1258
- break;
1259
- } catch (err) {
1260
- if (err instanceof _chunkXZTDYOZVcjs.KordocError) throw err;
1242
+ const allCandidates = resolvedPath ? [resolvedPath, ...candidates] : candidates;
1243
+ for (const path of allCandidates) {
1244
+ if (_chunkITJIALN5cjs.isPathTraversal.call(void 0, path)) continue;
1245
+ const file = zip.file(path);
1246
+ if (!file) continue;
1247
+ try {
1248
+ const data = await file.async("uint8array");
1249
+ decompressed.total += data.length;
1250
+ if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1251
+ const ext = path.includes(".") ? path.split(".").pop() || "png" : "png";
1252
+ const mimeType = imageExtToMime(ext);
1253
+ imageIndex++;
1254
+ const filename = `image_${String(imageIndex).padStart(3, "0")}.${mimeToExt(mimeType)}`;
1255
+ img = { filename, data, mimeType };
1256
+ images.push(img);
1257
+ break;
1258
+ } catch (err) {
1259
+ if (err instanceof _chunkITJIALN5cjs.KordocError) throw err;
1260
+ }
1261
1261
  }
1262
+ if (!img) _optionalChain([warnings, 'optionalAccess', _17 => _17.push, 'call', _18 => _18({ page: block.pageNumber, message: `\uC774\uBBF8\uC9C0 \uD30C\uC77C \uC5C6\uC74C: ${ref}`, code: "SKIPPED_IMAGE" })]);
1263
+ resolved.set(ref, img);
1262
1264
  }
1263
- if (!found) {
1264
- _optionalChain([warnings, 'optionalAccess', _17 => _17.push, 'call', _18 => _18({ page: block.pageNumber, message: `\uC774\uBBF8\uC9C0 \uD30C\uC77C \uC5C6\uC74C: ${ref}`, code: "SKIPPED_IMAGE" })]);
1265
+ if (!img) {
1265
1266
  block.type = "paragraph";
1266
1267
  block.text = `[\uC774\uBBF8\uC9C0: ${ref}]`;
1267
1268
  if (ownerCell) ownerCell.text = ownerCell.text.replace(`![image](${ref})`, `[\uC774\uBBF8\uC9C0: ${ref}]`);
1269
+ continue;
1268
1270
  }
1271
+ block.text = img.filename;
1272
+ block.imageData = { data: img.data, mimeType: img.mimeType, filename: ref };
1273
+ if (ownerCell) ownerCell.text = ownerCell.text.replace(`![image](${ref})`, `![image](${img.filename})`);
1269
1274
  }
1270
1275
  return images;
1271
1276
  }
@@ -1278,7 +1283,7 @@ async function extractHwpxMetadata(zip, metadata, decompressed) {
1278
1283
  const xml = await file.async("text");
1279
1284
  if (decompressed) {
1280
1285
  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)");
1286
+ if (decompressed.total > MAX_DECOMPRESS_SIZE) throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (ZIP bomb \uC758\uC2EC)");
1282
1287
  }
1283
1288
  parseDublinCoreMetadata(xml, metadata);
1284
1289
  if (metadata.title || metadata.author) return;
@@ -1288,7 +1293,7 @@ async function extractHwpxMetadata(zip, metadata, decompressed) {
1288
1293
  }
1289
1294
  function parseDublinCoreMetadata(xml, metadata) {
1290
1295
  const parser = createXmlParser();
1291
- const doc = parser.parseFromString(_chunkXZTDYOZVcjs.stripDtd.call(void 0, xml), "text/xml");
1296
+ const doc = parser.parseFromString(_chunkITJIALN5cjs.stripDtd.call(void 0, xml), "text/xml");
1292
1297
  if (!doc.documentElement) return;
1293
1298
  const getText = (tagNames) => {
1294
1299
  for (const tag of tagNames) {
@@ -1348,7 +1353,7 @@ function extractFromBrokenZip(buffer) {
1348
1353
  }
1349
1354
  const nameBytes = data.slice(pos + 30, pos + 30 + nameLen);
1350
1355
  const name = new TextDecoder().decode(nameBytes);
1351
- if (_chunkXZTDYOZVcjs.isPathTraversal.call(void 0, name)) {
1356
+ if (_chunkITJIALN5cjs.isPathTraversal.call(void 0, name)) {
1352
1357
  pos = fileStart + compSize;
1353
1358
  continue;
1354
1359
  }
@@ -1366,16 +1371,16 @@ function extractFromBrokenZip(buffer) {
1366
1371
  continue;
1367
1372
  }
1368
1373
  totalDecompressed += content.length * 2;
1369
- if (totalDecompressed > MAX_DECOMPRESS_SIZE) throw new (0, _chunkXZTDYOZVcjs.KordocError)("\uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC");
1374
+ if (totalDecompressed > MAX_DECOMPRESS_SIZE) throw new (0, _chunkITJIALN5cjs.KordocError)("\uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC");
1370
1375
  sectionNum++;
1371
1376
  blocks.push(...parseSectionXml(content, void 0, warnings, sectionNum, shared));
1372
1377
  } catch (e14) {
1373
1378
  continue;
1374
1379
  }
1375
1380
  }
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");
1381
+ if (blocks.length === 0) throw new (0, _chunkITJIALN5cjs.KordocError)("\uC190\uC0C1\uB41C HWPX\uC5D0\uC11C \uC139\uC158 \uB370\uC774\uD130\uB97C \uBCF5\uAD6C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
1377
1382
  applyPageText(blocks, shared);
1378
- const markdown = _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, blocks);
1383
+ const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, blocks);
1379
1384
  return { markdown, blocks, warnings: warnings.length > 0 ? warnings : void 0 };
1380
1385
  }
1381
1386
  async function resolveSectionPaths(zip) {
@@ -1389,18 +1394,18 @@ async function resolveSectionPaths(zip) {
1389
1394
  if (paths.length > 0) return paths;
1390
1395
  }
1391
1396
  const sectionFiles = zip.file(/[Ss]ection\d+\.xml$/);
1392
- return sectionFiles.map((f) => f.name).sort(_chunkXZTDYOZVcjs.compareSectionPaths);
1397
+ return sectionFiles.map((f) => f.name).sort(_chunkITJIALN5cjs.compareSectionPaths);
1393
1398
  }
1394
1399
  function parseSectionPathsFromManifest(xml) {
1395
1400
  const parser = createXmlParser();
1396
- const doc = parser.parseFromString(_chunkXZTDYOZVcjs.stripDtd.call(void 0, xml), "text/xml");
1401
+ const doc = parser.parseFromString(_chunkITJIALN5cjs.stripDtd.call(void 0, xml), "text/xml");
1397
1402
  const items = doc.getElementsByTagName("opf:item");
1398
1403
  const spine = doc.getElementsByTagName("opf:itemref");
1399
1404
  const idToHref = /* @__PURE__ */ new Map();
1400
1405
  for (let i = 0; i < items.length; i++) {
1401
1406
  const item = items[i];
1402
1407
  const id = item.getAttribute("id") || "";
1403
- const href = _chunkXZTDYOZVcjs.normalizeSectionHref.call(void 0, item.getAttribute("href") || "");
1408
+ const href = _chunkITJIALN5cjs.normalizeSectionHref.call(void 0, item.getAttribute("href") || "");
1404
1409
  if (id && href) idToHref.set(id, href);
1405
1410
  }
1406
1411
  if (spine.length > 0) {
@@ -1411,7 +1416,7 @@ function parseSectionPathsFromManifest(xml) {
1411
1416
  }
1412
1417
  if (ordered.length > 0) return ordered;
1413
1418
  }
1414
- return Array.from(idToHref.values()).sort(_chunkXZTDYOZVcjs.compareSectionPaths);
1419
+ return Array.from(idToHref.values()).sort(_chunkITJIALN5cjs.compareSectionPaths);
1415
1420
  }
1416
1421
  function detectHwpxHeadings(blocks, styleMap) {
1417
1422
  if (blocks.some((b) => b.type === "heading")) return;
@@ -1436,9 +1441,9 @@ function detectHwpxHeadings(blocks, styleMap) {
1436
1441
  let level = 0;
1437
1442
  if (baseFontSize > 0 && _optionalChain([block, 'access', _25 => _25.style, 'optionalAccess', _26 => _26.fontSize])) {
1438
1443
  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;
1444
+ if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H1) level = 1;
1445
+ else if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H2) level = 2;
1446
+ else if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H3) level = 3;
1442
1447
  }
1443
1448
  const compactText = text.replace(/\s+/g, "");
1444
1449
  if (/^제\d+[조장절편]/.test(compactText) && text.length <= 50) {
@@ -1451,17 +1456,40 @@ function detectHwpxHeadings(blocks, styleMap) {
1451
1456
  }
1452
1457
  }
1453
1458
  function buildTableWithCellMeta(state) {
1454
- const table = _chunkXZTDYOZVcjs.buildTable.call(void 0, state.rows);
1459
+ const table = _chunkITJIALN5cjs.buildTable.call(void 0, state.rows);
1455
1460
  if (state.caption) table.caption = state.caption;
1461
+ const anchors = [];
1462
+ {
1463
+ const covered = /* @__PURE__ */ new Set();
1464
+ for (let r = 0; r < table.rows; r++) {
1465
+ for (let c = 0; c < table.cols; c++) {
1466
+ if (covered.has(`${r},${c}`)) continue;
1467
+ const cell = _optionalChain([table, 'access', _27 => _27.cells, 'access', _28 => _28[r], 'optionalAccess', _29 => _29[c]]);
1468
+ if (!cell) continue;
1469
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
1470
+ for (let dc = 0; dc < cell.colSpan; dc++) {
1471
+ if (dr === 0 && dc === 0) continue;
1472
+ if (r + dr < table.rows && c + dc < table.cols) covered.add(`${r + dr},${c + dc}`);
1473
+ }
1474
+ }
1475
+ anchors.push(cell);
1476
+ c += cell.colSpan - 1;
1477
+ }
1478
+ }
1479
+ }
1480
+ const srcCount = state.rows.reduce((s, r) => s + r.length, 0);
1481
+ const ordinalReliable = anchors.length === srcCount;
1456
1482
  const claimed = /* @__PURE__ */ new Set();
1483
+ let flatIdx = -1;
1457
1484
  for (const row of state.rows) {
1458
1485
  for (const src of row) {
1486
+ flatIdx++;
1459
1487
  const needsBlocks = src.hasStructure && src.blocks && src.blocks.length > 0;
1460
1488
  if (!needsBlocks && !src.isHeader) continue;
1461
1489
  let target;
1462
1490
  const trimmed = src.text.trim();
1463
1491
  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]]);
1492
+ const cand = _optionalChain([table, 'access', _30 => _30.cells, 'access', _31 => _31[src.rowAddr], 'optionalAccess', _32 => _32[src.colAddr]]);
1465
1493
  if (cand && cand.text === trimmed && !claimed.has(cand)) target = cand;
1466
1494
  }
1467
1495
  if (!target) {
@@ -1474,6 +1502,10 @@ function buildTableWithCellMeta(state) {
1474
1502
  }
1475
1503
  }
1476
1504
  }
1505
+ if (!target && ordinalReliable) {
1506
+ const cand = anchors[flatIdx];
1507
+ if (cand && !claimed.has(cand)) target = cand;
1508
+ }
1477
1509
  if (!target) continue;
1478
1510
  claimed.add(target);
1479
1511
  if (needsBlocks) target.blocks = src.blocks;
@@ -1490,11 +1522,11 @@ function completeTable(newTable, tableStack, blocks, ctx) {
1490
1522
  }
1491
1523
  const ir = buildTableWithCellMeta(newTable);
1492
1524
  const block = { type: "table", table: ir, pageNumber: ctx.sectionNum };
1493
- if (_optionalChain([parentTable, 'optionalAccess', _30 => _30.cell])) {
1525
+ if (_optionalChain([parentTable, 'optionalAccess', _33 => _33.cell])) {
1494
1526
  const cell = parentTable.cell;
1495
1527
  (cell.blocks ??= []).push(block);
1496
1528
  cell.hasStructure = true;
1497
- let flat = _chunkXZTDYOZVcjs.convertTableToText.call(void 0, newTable.rows);
1529
+ let flat = _chunkITJIALN5cjs.convertTableToText.call(void 0, newTable.rows);
1498
1530
  if (newTable.caption) flat = newTable.caption + (flat ? "\n" + flat : "");
1499
1531
  if (flat) cell.text += (cell.text ? "\n" : "") + flat;
1500
1532
  } else {
@@ -1504,7 +1536,7 @@ function completeTable(newTable, tableStack, blocks, ctx) {
1504
1536
  }
1505
1537
  function parseSectionXml(xml, styleMap, warnings, sectionNum, shared) {
1506
1538
  const parser = createXmlParser(warnings);
1507
- const doc = parser.parseFromString(_chunkXZTDYOZVcjs.stripDtd.call(void 0, xml), "text/xml");
1539
+ const doc = parser.parseFromString(_chunkITJIALN5cjs.stripDtd.call(void 0, xml), "text/xml");
1508
1540
  if (!doc.documentElement) return [];
1509
1541
  const ctx = { styleMap, warnings, sectionNum, shared: _nullishCoalesce(shared, () => ( createSectionShared())) };
1510
1542
  ctx.shared.track.deleteDepth = 0;
@@ -1582,7 +1614,7 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1582
1614
  }
1583
1615
  break;
1584
1616
  case "cellAddr":
1585
- if (_optionalChain([tableCtx, 'optionalAccess', _31 => _31.cell])) {
1617
+ if (_optionalChain([tableCtx, 'optionalAccess', _34 => _34.cell])) {
1586
1618
  const ca = parseInt(el.getAttribute("colAddr") || "", 10);
1587
1619
  const ra = parseInt(el.getAttribute("rowAddr") || "", 10);
1588
1620
  if (!isNaN(ca)) tableCtx.cell.colAddr = ca;
@@ -1590,13 +1622,13 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1590
1622
  }
1591
1623
  break;
1592
1624
  case "cellSpan":
1593
- if (_optionalChain([tableCtx, 'optionalAccess', _32 => _32.cell])) {
1625
+ if (_optionalChain([tableCtx, 'optionalAccess', _35 => _35.cell])) {
1594
1626
  const rawCs = parseInt(el.getAttribute("colSpan") || "1", 10);
1595
1627
  const cs = isNaN(rawCs) ? 1 : rawCs;
1596
1628
  const rawRs = parseInt(el.getAttribute("rowSpan") || "1", 10);
1597
1629
  const rs = isNaN(rawRs) ? 1 : rawRs;
1598
- tableCtx.cell.colSpan = clampSpan(cs, _chunkXZTDYOZVcjs.MAX_COLS);
1599
- tableCtx.cell.rowSpan = clampSpan(rs, _chunkXZTDYOZVcjs.MAX_ROWS);
1630
+ tableCtx.cell.colSpan = clampSpan(cs, _chunkITJIALN5cjs.MAX_COLS);
1631
+ tableCtx.cell.rowSpan = clampSpan(rs, _chunkITJIALN5cjs.MAX_ROWS);
1600
1632
  }
1601
1633
  break;
1602
1634
  case "p": {
@@ -1605,11 +1637,11 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1605
1637
  let headingLevel;
1606
1638
  if (text) {
1607
1639
  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]);
1640
+ if (_optionalChain([ph, 'optionalAccess', _36 => _36.prefix])) text = ph.prefix + " " + text;
1641
+ headingLevel = _optionalChain([ph, 'optionalAccess', _37 => _37.headingLevel]);
1610
1642
  }
1611
1643
  if (text) {
1612
- if (_optionalChain([tableCtx, 'optionalAccess', _35 => _35.cell])) {
1644
+ if (_optionalChain([tableCtx, 'optionalAccess', _38 => _38.cell])) {
1613
1645
  const cell = tableCtx.cell;
1614
1646
  if (footnote) text += ` (\uC8FC: ${footnote})`;
1615
1647
  cell.text += (cell.text ? "\n" : "") + text;
@@ -1632,7 +1664,7 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1632
1664
  case "pic":
1633
1665
  case "shape":
1634
1666
  case "drawingObject": {
1635
- if (_optionalChain([tableCtx, 'optionalAccess', _36 => _36.cell])) {
1667
+ if (_optionalChain([tableCtx, 'optionalAccess', _39 => _39.cell])) {
1636
1668
  const sink = [];
1637
1669
  handleShape(el, sink, ctx);
1638
1670
  mergeBlocksIntoCell(tableCtx.cell, sink);
@@ -1741,7 +1773,7 @@ function walkParagraphChildren(node, blocks, tableCtx, tableStack, ctx, depth =
1741
1773
  walkSection(el, blocks, newTable, tableStack, ctx, d + 1);
1742
1774
  tableCtx = completeTable(newTable, tableStack, blocks, ctx);
1743
1775
  } else if (localTag === "pic" || localTag === "shape" || localTag === "drawingObject") {
1744
- if (_optionalChain([tableCtx, 'optionalAccess', _37 => _37.cell])) {
1776
+ if (_optionalChain([tableCtx, 'optionalAccess', _40 => _40.cell])) {
1745
1777
  const sink = [];
1746
1778
  handleShape(el, sink, ctx);
1747
1779
  mergeBlocksIntoCell(tableCtx.cell, sink);
@@ -1749,7 +1781,7 @@ function walkParagraphChildren(node, blocks, tableCtx, tableStack, ctx, depth =
1749
1781
  handleShape(el, blocks, ctx);
1750
1782
  }
1751
1783
  } else if (localTag === "drawText") {
1752
- if (_optionalChain([tableCtx, 'optionalAccess', _38 => _38.cell])) {
1784
+ if (_optionalChain([tableCtx, 'optionalAccess', _41 => _41.cell])) {
1753
1785
  const sink = [];
1754
1786
  extractDrawTextBlocks(el, sink, ctx);
1755
1787
  mergeBlocksIntoCell(tableCtx.cell, sink);
@@ -1793,7 +1825,7 @@ function extractDrawTextBlocks(drawTextNode, blocks, ctx) {
1793
1825
  let text = info.text.trim();
1794
1826
  if (text) {
1795
1827
  const ph = resolveParaHeading(child, ctx);
1796
- if (_optionalChain([ph, 'optionalAccess', _39 => _39.prefix])) text = ph.prefix + " " + text;
1828
+ if (_optionalChain([ph, 'optionalAccess', _42 => _42.prefix])) text = ph.prefix + " " + text;
1797
1829
  const block = { type: "paragraph", text, style: _nullishCoalesce(info.style, () => ( void 0)), pageNumber: ctx.sectionNum };
1798
1830
  if (info.href) block.href = info.href;
1799
1831
  if (info.footnote) block.footnoteText = info.footnote;
@@ -1818,13 +1850,13 @@ function extractHyperlinkHref(fieldBegin) {
1818
1850
  let url = (ch.textContent || "").trim();
1819
1851
  if (!url) continue;
1820
1852
  url = url.replace(/^https?:\/\/(?=https?:\/\/)/i, "");
1821
- const safe = _chunkXZTDYOZVcjs.sanitizeHref.call(void 0, url);
1853
+ const safe = _chunkITJIALN5cjs.sanitizeHref.call(void 0, url);
1822
1854
  if (safe) return safe;
1823
1855
  }
1824
1856
  return void 0;
1825
1857
  }
1826
1858
  function isInDeletedRange(ctx) {
1827
- return (_nullishCoalesce(_optionalChain([ctx, 'optionalAccess', _40 => _40.shared, 'access', _41 => _41.track, 'access', _42 => _42.deleteDepth]), () => ( 0))) > 0;
1859
+ return (_nullishCoalesce(_optionalChain([ctx, 'optionalAccess', _43 => _43.shared, 'access', _44 => _44.track, 'access', _45 => _45.deleteDepth]), () => ( 0))) > 0;
1828
1860
  }
1829
1861
  function extractParagraphInfo(para, styleMap, ctx) {
1830
1862
  let text = "";
@@ -1878,7 +1910,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
1878
1910
  // 삽입분은 최종본에 포함
1879
1911
  // 숨은 설명 — 본문 혼입 차단
1880
1912
  case "hiddenComment": {
1881
- if (_optionalChain([ctx, 'optionalAccess', _43 => _43.warnings]) && extractTextFromNode(k)) {
1913
+ if (_optionalChain([ctx, 'optionalAccess', _46 => _46.warnings]) && extractTextFromNode(k)) {
1882
1914
  ctx.warnings.push({ page: ctx.sectionNum, message: "\uC228\uC740 \uC124\uBA85 \uD14D\uC2A4\uD2B8 \uC81C\uC678: hiddenComment", code: "HIDDEN_TEXT_FILTERED" });
1883
1915
  }
1884
1916
  break;
@@ -1895,7 +1927,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
1895
1927
  break;
1896
1928
  // 미지원 요소 — 텍스트를 가졌으면 무음 손실 대신 경고
1897
1929
  default: {
1898
- if (_optionalChain([ctx, 'optionalAccess', _44 => _44.warnings]) && extractTextFromNode(k)) {
1930
+ if (_optionalChain([ctx, 'optionalAccess', _47 => _47.warnings]) && extractTextFromNode(k)) {
1899
1931
  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
1932
  }
1901
1933
  }
@@ -1912,7 +1944,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
1912
1944
  if (isInDeletedRange(ctx)) {
1913
1945
  if (t && ctx && !ctx.shared.track.warned) {
1914
1946
  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" })]);
1947
+ _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
1948
  }
1917
1949
  } else {
1918
1950
  text += t;
@@ -1953,7 +1985,7 @@ function extractParagraphInfo(para, styleMap, ctx) {
1953
1985
  case "hyperlink": {
1954
1986
  const url = child.getAttribute("url") || child.getAttribute("href") || "";
1955
1987
  if (url) {
1956
- const safe = _chunkXZTDYOZVcjs.sanitizeHref.call(void 0, url);
1988
+ const safe = _chunkITJIALN5cjs.sanitizeHref.call(void 0, url);
1957
1989
  if (safe) href = safe;
1958
1990
  }
1959
1991
  walk(child);
@@ -2143,7 +2175,7 @@ function decompressStream(data) {
2143
2175
  return _zlib.inflateRawSync.call(void 0, data, opts);
2144
2176
  }
2145
2177
  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)");
2178
+ if (data.length < 40) throw new (0, _chunkITJIALN5cjs.KordocError)("FileHeader\uAC00 \uB108\uBB34 \uC9E7\uC2B5\uB2C8\uB2E4 (\uCD5C\uC18C 40\uBC14\uC774\uD2B8)");
2147
2179
  const sig = data.subarray(0, 32).toString("utf8").replace(/\0+$/, "");
2148
2180
  return {
2149
2181
  signature: sig,
@@ -2276,7 +2308,7 @@ function appendParaText(state, data, resolveControl) {
2276
2308
  const resolveAt = (byteOffset, extended) => {
2277
2309
  const ctrlId = data.readUInt32LE(byteOffset);
2278
2310
  const idx = extended ? state.ctrlIdx : -1;
2279
- const replacement = _optionalChain([resolveControl, 'optionalCall', _48 => _48(idx, ctrlId)]);
2311
+ const replacement = _optionalChain([resolveControl, 'optionalCall', _51 => _51(idx, ctrlId)]);
2280
2312
  if (replacement) result += replacement;
2281
2313
  if (extended) state.ctrlIdx++;
2282
2314
  };
@@ -2604,32 +2636,42 @@ function resolveImageBlocks(binDataMap, blocks, warnings) {
2604
2636
  if (imageBlocks.length === 0) return [];
2605
2637
  const images = [];
2606
2638
  const renamed = /* @__PURE__ */ new Map();
2639
+ const resolved = /* @__PURE__ */ new Map();
2607
2640
  let imageIndex = 0;
2608
2641
  for (const block of imageBlocks) {
2609
2642
  if (!block.text) continue;
2610
2643
  const storageId = parseInt(block.text, 10);
2611
2644
  if (isNaN(storageId)) continue;
2612
- const bin = binDataMap.get(storageId);
2613
- if (!bin) {
2614
- warnings.push({ page: block.pageNumber, message: `BinData ${storageId} \uC5C6\uC74C`, code: "SKIPPED_IMAGE" });
2615
- block.type = "paragraph";
2616
- block.text = `[\uC774\uBBF8\uC9C0: BinData ${storageId}]`;
2617
- continue;
2645
+ let img = resolved.get(storageId);
2646
+ if (img === void 0) {
2647
+ const bin = binDataMap.get(storageId);
2648
+ if (!bin) {
2649
+ warnings.push({ page: block.pageNumber, message: `BinData ${storageId} \uC5C6\uC74C`, code: "SKIPPED_IMAGE" });
2650
+ resolved.set(storageId, null);
2651
+ } else {
2652
+ const mime = detectImageMime(bin.data);
2653
+ if (!mime) {
2654
+ warnings.push({ page: block.pageNumber, message: `BinData ${storageId}: \uC54C \uC218 \uC5C6\uB294 \uC774\uBBF8\uC9C0 \uD615\uC2DD`, code: "SKIPPED_IMAGE" });
2655
+ resolved.set(storageId, null);
2656
+ } else {
2657
+ imageIndex++;
2658
+ const ext = mime.includes("jpeg") ? "jpg" : mime.includes("png") ? "png" : mime.includes("gif") ? "gif" : mime.includes("bmp") ? "bmp" : "bin";
2659
+ img = { filename: `image_${String(imageIndex).padStart(3, "0")}.${ext}`, data: new Uint8Array(bin.data), mime };
2660
+ resolved.set(storageId, img);
2661
+ images.push({ filename: img.filename, data: img.data, mimeType: img.mime });
2662
+ renamed.set(storageId, img.filename);
2663
+ }
2664
+ }
2665
+ img = resolved.get(storageId);
2618
2666
  }
2619
- const mime = detectImageMime(bin.data);
2620
- if (!mime) {
2621
- warnings.push({ page: block.pageNumber, message: `BinData ${storageId}: \uC54C \uC218 \uC5C6\uB294 \uC774\uBBF8\uC9C0 \uD615\uC2DD`, code: "SKIPPED_IMAGE" });
2667
+ if (!img) {
2668
+ const bin = binDataMap.get(storageId);
2622
2669
  block.type = "paragraph";
2623
- block.text = `[\uC774\uBBF8\uC9C0: ${bin.name}]`;
2670
+ block.text = bin ? `[\uC774\uBBF8\uC9C0: ${bin.name}]` : `[\uC774\uBBF8\uC9C0: BinData ${storageId}]`;
2624
2671
  continue;
2625
2672
  }
2626
- imageIndex++;
2627
- const ext = mime.includes("jpeg") ? "jpg" : mime.includes("png") ? "png" : mime.includes("gif") ? "gif" : mime.includes("bmp") ? "bmp" : "bin";
2628
- const filename = `image_${String(imageIndex).padStart(3, "0")}.${ext}`;
2629
- images.push({ filename, data: new Uint8Array(bin.data), mimeType: mime });
2630
- renamed.set(storageId, filename);
2631
- block.text = filename;
2632
- block.imageData = { data: new Uint8Array(bin.data), mimeType: mime, filename: bin.name };
2673
+ block.text = img.filename;
2674
+ block.imageData = { data: img.data, mimeType: img.mime, filename: binDataMap.get(storageId).name };
2633
2675
  }
2634
2676
  resolveCellImageSentinels(blocks, renamed);
2635
2677
  return images;
@@ -2638,7 +2680,7 @@ function extractHwp5Images(fileIndex, blocks, warnings) {
2638
2680
  const binDataMap = /* @__PURE__ */ new Map();
2639
2681
  if (fileIndex) {
2640
2682
  for (const entry of fileIndex) {
2641
- if (!_optionalChain([entry, 'optionalAccess', _49 => _49.name]) || !entry.content) continue;
2683
+ if (!_optionalChain([entry, 'optionalAccess', _52 => _52.name]) || !entry.content) continue;
2642
2684
  const match = entry.name.match(BIN_ENTRY_RE);
2643
2685
  if (!match) continue;
2644
2686
  const idx = parseInt(match[1], 16);
@@ -3667,22 +3709,22 @@ function parseHwp5Document(buffer, options) {
3667
3709
  lenientCfb = parseLenientCfb(buffer);
3668
3710
  warnings.push({ message: "\uC190\uC0C1\uB41C CFB \uCEE8\uD14C\uC774\uB108 \u2014 lenient \uBAA8\uB4DC\uB85C \uBCF5\uAD6C", code: "LENIENT_CFB_RECOVERY" });
3669
3711
  } catch (e21) {
3670
- throw new (0, _chunkXZTDYOZVcjs.KordocError)("CFB \uCEE8\uD14C\uC774\uB108 \uD30C\uC2F1 \uC2E4\uD328 (strict \uBC0F lenient \uBAA8\uB450)");
3712
+ throw new (0, _chunkITJIALN5cjs.KordocError)("CFB \uCEE8\uD14C\uC774\uB108 \uD30C\uC2F1 \uC2E4\uD328 (strict \uBC0F lenient \uBAA8\uB450)");
3671
3713
  }
3672
3714
  }
3673
3715
  const findStream = (path) => {
3674
3716
  if (cfb) {
3675
3717
  const entry = CFB.find(cfb, path);
3676
- return _optionalChain([entry, 'optionalAccess', _50 => _50.content]) ? Buffer.from(entry.content) : null;
3718
+ return _optionalChain([entry, 'optionalAccess', _53 => _53.content]) ? Buffer.from(entry.content) : null;
3677
3719
  }
3678
3720
  return lenientCfb.findStream(path);
3679
3721
  };
3680
3722
  const headerData = findStream("/FileHeader");
3681
- if (!headerData) throw new (0, _chunkXZTDYOZVcjs.KordocError)("FileHeader \uC2A4\uD2B8\uB9BC \uC5C6\uC74C");
3723
+ if (!headerData) throw new (0, _chunkITJIALN5cjs.KordocError)("FileHeader \uC2A4\uD2B8\uB9BC \uC5C6\uC74C");
3682
3724
  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");
3725
+ if (header.signature !== "HWP Document File") throw new (0, _chunkITJIALN5cjs.KordocError)("HWP \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
3726
+ if (header.flags & FLAG_ENCRYPTED) throw new (0, _chunkITJIALN5cjs.KordocError)("\uC554\uD638\uD654\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
3727
+ if (header.flags & FLAG_DRM) throw new (0, _chunkITJIALN5cjs.KordocError)("DRM \uBCF4\uD638\uB41C HWP\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
3686
3728
  const compressed = (header.flags & FLAG_COMPRESSED) !== 0;
3687
3729
  const distribution = (header.flags & FLAG_DISTRIBUTION) !== 0;
3688
3730
  const metadata = {
@@ -3691,9 +3733,9 @@ function parseHwp5Document(buffer, options) {
3691
3733
  if (cfb) extractHwp5Metadata(cfb, metadata);
3692
3734
  const docInfo = cfb ? parseDocInfoStream(cfb, compressed) : parseDocInfoFromStream(findStream("/DocInfo"), compressed);
3693
3735
  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");
3736
+ if (sections.length === 0) throw new (0, _chunkITJIALN5cjs.KordocError)("\uC139\uC158 \uC2A4\uD2B8\uB9BC\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
3695
3737
  metadata.pageCount = sections.length;
3696
- const pageFilter = _optionalChain([options, 'optionalAccess', _51 => _51.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, sections.length) : null;
3738
+ const pageFilter = _optionalChain([options, 'optionalAccess', _54 => _54.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, sections.length) : null;
3697
3739
  const totalTarget = pageFilter ? pageFilter.size : sections.length;
3698
3740
  const bodyBlocks = [];
3699
3741
  const doc = createHwp5DocState();
@@ -3705,31 +3747,31 @@ function parseHwp5Document(buffer, options) {
3705
3747
  const sectionData = sections[si];
3706
3748
  const data = !distribution && compressed ? decompressStream(Buffer.from(sectionData)) : Buffer.from(sectionData);
3707
3749
  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)");
3750
+ if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkITJIALN5cjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3709
3751
  const records = readRecords(data);
3710
3752
  const sectionBlocks = parseSection(records, docInfo, warnings, si + 1, doc);
3711
3753
  bodyBlocks.push(...sectionBlocks);
3712
3754
  parsedSections++;
3713
- _optionalChain([options, 'optionalAccess', _52 => _52.onProgress, 'optionalCall', _53 => _53(parsedSections, totalTarget)]);
3755
+ _optionalChain([options, 'optionalAccess', _55 => _55.onProgress, 'optionalCall', _56 => _56(parsedSections, totalTarget)]);
3714
3756
  } catch (secErr) {
3715
- if (secErr instanceof _chunkXZTDYOZVcjs.KordocError) throw secErr;
3757
+ if (secErr instanceof _chunkITJIALN5cjs.KordocError) throw secErr;
3716
3758
  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
3759
  }
3718
3760
  }
3719
3761
  const blocks = [...doc.headerBlocks, ...bodyBlocks, ...doc.footerBlocks];
3720
3762
  const images = cfb ? extractHwp5Images(cfb.FileIndex, blocks, warnings) : extractHwp5ImagesLenient(lenientCfb, blocks, warnings);
3721
- const flatBlocks = _chunkXZTDYOZVcjs.flattenLayoutTables.call(void 0, blocks);
3763
+ const flatBlocks = _chunkITJIALN5cjs.flattenLayoutTables.call(void 0, blocks);
3722
3764
  if (docInfo) {
3723
3765
  detectHwp5Headings(flatBlocks, docInfo);
3724
3766
  }
3725
3767
  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);
3768
+ const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, flatBlocks);
3727
3769
  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
3770
  }
3729
3771
  function parseDocInfoStream(cfb, compressed) {
3730
3772
  try {
3731
3773
  const entry = CFB.find(cfb, "/DocInfo");
3732
- if (!_optionalChain([entry, 'optionalAccess', _54 => _54.content])) return null;
3774
+ if (!_optionalChain([entry, 'optionalAccess', _57 => _57.content])) return null;
3733
3775
  const data = compressed ? decompressStream(Buffer.from(entry.content)) : Buffer.from(entry.content);
3734
3776
  const records = readRecords(data);
3735
3777
  return parseDocInfo(records);
@@ -3750,7 +3792,7 @@ function detectHwp5Headings(blocks, docInfo) {
3750
3792
  let baseFontSize = 0;
3751
3793
  const sizeFreq = /* @__PURE__ */ new Map();
3752
3794
  for (const b of blocks) {
3753
- if (_optionalChain([b, 'access', _55 => _55.style, 'optionalAccess', _56 => _56.fontSize]) && b.text) {
3795
+ if (_optionalChain([b, 'access', _58 => _58.style, 'optionalAccess', _59 => _59.fontSize]) && b.text) {
3754
3796
  sizeFreq.set(b.style.fontSize, (sizeFreq.get(b.style.fontSize) || 0) + b.text.length);
3755
3797
  }
3756
3798
  }
@@ -3766,7 +3808,7 @@ function detectHwp5Headings(blocks, docInfo) {
3766
3808
  const name = (style.nameKo || style.name).toLowerCase();
3767
3809
  if (name.includes("\uBC14\uD0D5") || name.includes("\uBCF8\uBB38") || name === "normal" || name === "body") {
3768
3810
  const cs = docInfo.charShapes[style.charShapeId];
3769
- if (_optionalChain([cs, 'optionalAccess', _57 => _57.fontSize]) > 0) {
3811
+ if (_optionalChain([cs, 'optionalAccess', _60 => _60.fontSize]) > 0) {
3770
3812
  baseFontSize = cs.fontSize / 10;
3771
3813
  break;
3772
3814
  }
@@ -3781,11 +3823,11 @@ function detectHwp5Headings(blocks, docInfo) {
3781
3823
  if (text.length === 0 || text.length > 200) continue;
3782
3824
  if (/^\d+$/.test(text)) continue;
3783
3825
  let level = 0;
3784
- if (_optionalChain([block, 'access', _58 => _58.style, 'optionalAccess', _59 => _59.fontSize]) && baseFontSize > 0) {
3826
+ if (_optionalChain([block, 'access', _61 => _61.style, 'optionalAccess', _62 => _62.fontSize]) && baseFontSize > 0) {
3785
3827
  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;
3828
+ if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H1) level = 1;
3829
+ else if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H2) level = 2;
3830
+ else if (ratio >= _chunkITJIALN5cjs.HEADING_RATIO_H3) level = 3;
3789
3831
  }
3790
3832
  if (/^제\d+[장절편]\s/.test(text) && text.length <= 50) {
3791
3833
  if (level === 0) level = 2;
@@ -3801,7 +3843,7 @@ function detectHwp5Headings(blocks, docInfo) {
3801
3843
  function extractHwp5Metadata(cfb, metadata) {
3802
3844
  try {
3803
3845
  const summaryEntry = CFB.find(cfb, "/HwpSummaryInformation") || CFB.find(cfb, "/SummaryInformation");
3804
- if (!_optionalChain([summaryEntry, 'optionalAccess', _60 => _60.content])) return;
3846
+ if (!_optionalChain([summaryEntry, 'optionalAccess', _63 => _63.content])) return;
3805
3847
  const data = Buffer.from(summaryEntry.content);
3806
3848
  if (data.length < 48) return;
3807
3849
  const numSets = data.readUInt32LE(24);
@@ -3834,7 +3876,7 @@ function findViewTextSections(cfb, compressed) {
3834
3876
  const sections = [];
3835
3877
  for (let i = 0; i < MAX_SECTIONS; i++) {
3836
3878
  const entry = CFB.find(cfb, `/ViewText/Section${i}`);
3837
- if (!_optionalChain([entry, 'optionalAccess', _61 => _61.content])) break;
3879
+ if (!_optionalChain([entry, 'optionalAccess', _64 => _64.content])) break;
3838
3880
  try {
3839
3881
  const decrypted = decryptViewText(Buffer.from(entry.content), compressed);
3840
3882
  sections.push({ idx: i, content: decrypted });
@@ -3848,13 +3890,13 @@ function findSections(cfb) {
3848
3890
  const sections = [];
3849
3891
  for (let i = 0; i < MAX_SECTIONS; i++) {
3850
3892
  const entry = CFB.find(cfb, `/BodyText/Section${i}`);
3851
- if (!_optionalChain([entry, 'optionalAccess', _62 => _62.content])) break;
3893
+ if (!_optionalChain([entry, 'optionalAccess', _65 => _65.content])) break;
3852
3894
  sections.push({ idx: i, content: Buffer.from(entry.content) });
3853
3895
  }
3854
3896
  if (sections.length === 0 && cfb.FileIndex) {
3855
3897
  for (const entry of cfb.FileIndex) {
3856
3898
  if (sections.length >= MAX_SECTIONS) break;
3857
- if (_optionalChain([entry, 'access', _63 => _63.name, 'optionalAccess', _64 => _64.startsWith, 'call', _65 => _65("Section")]) && entry.content) {
3899
+ if (_optionalChain([entry, 'access', _66 => _66.name, 'optionalAccess', _67 => _67.startsWith, 'call', _68 => _68("Section")]) && entry.content) {
3858
3900
  const idx = parseInt(entry.name.replace("Section", ""), 10) || 0;
3859
3901
  sections.push({ idx, content: Buffer.from(entry.content) });
3860
3902
  }
@@ -3870,7 +3912,7 @@ function findSectionsLenient(lcfb, compressed) {
3870
3912
  if (!raw) break;
3871
3913
  const content = compressed ? decompressStream(raw) : raw;
3872
3914
  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)");
3915
+ if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkITJIALN5cjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3874
3916
  sections.push({ idx: i, content });
3875
3917
  }
3876
3918
  if (sections.length === 0) {
@@ -3882,7 +3924,7 @@ function findSectionsLenient(lcfb, compressed) {
3882
3924
  if (raw) {
3883
3925
  const content = compressed ? decompressStream(raw) : raw;
3884
3926
  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)");
3927
+ if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkITJIALN5cjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3886
3928
  sections.push({ idx, content });
3887
3929
  }
3888
3930
  }
@@ -3899,7 +3941,7 @@ function findViewTextSectionsLenient(lcfb, compressed) {
3899
3941
  try {
3900
3942
  const content = decryptViewText(raw, compressed);
3901
3943
  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)");
3944
+ if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new (0, _chunkITJIALN5cjs.KordocError)("\uCD1D \uC555\uCD95 \uD574\uC81C \uD06C\uAE30 \uCD08\uACFC (decompression bomb \uC758\uC2EC)");
3903
3945
  sections.push({ idx: i, content });
3904
3946
  } catch (e26) {
3905
3947
  break;
@@ -4000,9 +4042,9 @@ function parseParagraph(records, start, end, ctx) {
4000
4042
  const applied = [];
4001
4043
  for (const r of ranges) {
4002
4044
  const ctrl = ctrls[r.ctrlIdx];
4003
- if (!_optionalChain([ctrl, 'optionalAccess', _66 => _66.href]) || r.end <= r.start) continue;
4045
+ if (!_optionalChain([ctrl, 'optionalAccess', _69 => _69.href]) || r.end <= r.start) continue;
4004
4046
  if (applied.some(([s, e]) => r.start < e && r.end > s)) continue;
4005
- const href = _chunkXZTDYOZVcjs.sanitizeHref.call(void 0, ctrl.href);
4047
+ const href = _chunkITJIALN5cjs.sanitizeHref.call(void 0, ctrl.href);
4006
4048
  if (!href) continue;
4007
4049
  const anchor = text.slice(r.start, r.end);
4008
4050
  if (!anchor.trim()) continue;
@@ -4020,7 +4062,7 @@ function parseParagraph(records, start, end, ctx) {
4020
4062
  }
4021
4063
  if (ps.headType === 1 || ps.headType === 2) {
4022
4064
  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;
4065
+ const numbering = nid >= 1 ? _optionalChain([ctx, 'access', _70 => _70.docInfo, 'optionalAccess', _71 => _71.numberings, 'access', _72 => _72[nid - 1]]) : void 0;
4024
4066
  if (numbering) {
4025
4067
  const counters = ctx.doc.numbering.advance(nid, ps.paraLevel);
4026
4068
  const fmt = numbering.levelFormats[Math.min(ps.paraLevel, 6)];
@@ -4030,7 +4072,7 @@ function parseParagraph(records, start, end, ctx) {
4030
4072
  }
4031
4073
  }
4032
4074
  } 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;
4075
+ const bullet = ps.numberingId >= 1 ? _optionalChain([ctx, 'access', _73 => _73.docInfo, 'optionalAccess', _74 => _74.bullets, 'access', _75 => _75[ps.numberingId - 1]]) : void 0;
4034
4076
  if (bullet && bullet.char !== "\uFFFF") headMarker = bullet.char;
4035
4077
  }
4036
4078
  }
@@ -4235,8 +4277,8 @@ function parseTableControl(ctrl, records, ctx) {
4235
4277
  let tableIdx = -1;
4236
4278
  for (let i2 = childStart; i2 < childEnd; i2++) {
4237
4279
  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);
4280
+ rows = Math.min(records[i2].data.readUInt16LE(4), _chunkITJIALN5cjs.MAX_ROWS);
4281
+ cols = Math.min(records[i2].data.readUInt16LE(6), _chunkITJIALN5cjs.MAX_COLS);
4240
4282
  tableIdx = i2;
4241
4283
  break;
4242
4284
  }
@@ -4276,7 +4318,7 @@ function parseTableControl(ctrl, records, ctx) {
4276
4318
  const cellRows2 = arrangeCells(rows, cols, cells);
4277
4319
  const irCells = cellRows2.map((row) => row.map((c) => {
4278
4320
  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;
4321
+ if (_optionalChain([c, 'access', _76 => _76.blocks, 'optionalAccess', _77 => _77.length])) ir.blocks = c.blocks;
4280
4322
  if (c.isHeader) ir.isHeader = true;
4281
4323
  return ir;
4282
4324
  }));
@@ -4285,7 +4327,7 @@ function parseTableControl(ctrl, records, ctx) {
4285
4327
  return table2;
4286
4328
  }
4287
4329
  const cellRows = arrangeCells(rows, cols, cells);
4288
- const table = _chunkXZTDYOZVcjs.buildTable.call(void 0, cellRows);
4330
+ const table = _chunkITJIALN5cjs.buildTable.call(void 0, cellRows);
4289
4331
  if (caption && table.rows > 0) table.caption = caption;
4290
4332
  return table.rows > 0 ? table : null;
4291
4333
  }
@@ -4302,8 +4344,8 @@ function parseCell(records, lhIdx, end, ctx) {
4302
4344
  rowAddr = rec.data.readUInt16LE(10);
4303
4345
  const cs = rec.data.readUInt16LE(12);
4304
4346
  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);
4347
+ if (cs > 0) colSpan = Math.min(cs, _chunkITJIALN5cjs.MAX_COLS);
4348
+ if (rs > 0) rowSpan = Math.min(rs, _chunkITJIALN5cjs.MAX_ROWS);
4307
4349
  }
4308
4350
  const blocks = ctx.depth < MAX_NEST_DEPTH ? parseParagraphList(records, lhIdx + 1, end, { ...ctx, depth: ctx.depth + 1 }) : [];
4309
4351
  const parts = [];
@@ -4313,7 +4355,7 @@ function parseCell(records, lhIdx, end, ctx) {
4313
4355
  parts.push(`![image](hwp5bin:${b.text})`);
4314
4356
  hasStructure = true;
4315
4357
  } else if (b.type === "table" && b.table) {
4316
- const flat = _chunkXZTDYOZVcjs.convertTableToText.call(void 0, b.table.cells);
4358
+ const flat = _chunkITJIALN5cjs.convertTableToText.call(void 0, b.table.cells);
4317
4359
  if (flat) parts.push(flat);
4318
4360
  hasStructure = true;
4319
4361
  } else if (b.text) {
@@ -4410,8 +4452,8 @@ function pictureToImageBlock(data, ctx) {
4410
4452
  if (data.length < 73) return null;
4411
4453
  const binDataId = data.readUInt16LE(71);
4412
4454
  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") {
4455
+ const item = _optionalChain([ctx, 'access', _78 => _78.docInfo, 'optionalAccess', _79 => _79.binData, 'access', _80 => _80[binDataId - 1]]);
4456
+ if (_optionalChain([item, 'optionalAccess', _81 => _81.kind]) === "link") {
4415
4457
  ctx.warnings.push({ page: ctx.sectionNum, message: `\uC678\uBD80 \uC5F0\uACB0 \uC774\uBBF8\uC9C0 (binDataId ${binDataId})`, code: "SKIPPED_IMAGE" });
4416
4458
  return null;
4417
4459
  }
@@ -16744,10 +16786,10 @@ function getElements(parent, tagName) {
16744
16786
  return result;
16745
16787
  }
16746
16788
  function getTextContent(el) {
16747
- return _nullishCoalesce(_optionalChain([el, 'access', _79 => _79.textContent, 'optionalAccess', _80 => _80.trim, 'call', _81 => _81()]), () => ( ""));
16789
+ return _nullishCoalesce(_optionalChain([el, 'access', _82 => _82.textContent, 'optionalAccess', _83 => _83.trim, 'call', _84 => _84()]), () => ( ""));
16748
16790
  }
16749
16791
  function parseXml(text) {
16750
- return new (0, _xmldom.DOMParser)().parseFromString(_chunkXZTDYOZVcjs.stripDtd.call(void 0, text), "text/xml");
16792
+ return new (0, _xmldom.DOMParser)().parseFromString(_chunkITJIALN5cjs.stripDtd.call(void 0, text), "text/xml");
16751
16793
  }
16752
16794
  function parseSharedStrings(xml) {
16753
16795
  const doc = parseXml(xml);
@@ -16884,14 +16926,14 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
16884
16926
  const merge = mergeMap.get(key);
16885
16927
  row.push({
16886
16928
  text,
16887
- colSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _82 => _82.colSpan]), () => ( 1)),
16888
- rowSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _83 => _83.rowSpan]), () => ( 1))
16929
+ colSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _85 => _85.colSpan]), () => ( 1)),
16930
+ rowSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _86 => _86.rowSpan]), () => ( 1))
16889
16931
  });
16890
16932
  }
16891
16933
  cellRows.push(row);
16892
16934
  }
16893
16935
  if (cellRows.length > 0) {
16894
- const table = _chunkXZTDYOZVcjs.buildTable.call(void 0, cellRows);
16936
+ const table = _chunkITJIALN5cjs.buildTable.call(void 0, cellRows);
16895
16937
  if (table.rows > 0) {
16896
16938
  blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
16897
16939
  }
@@ -16899,12 +16941,12 @@ function sheetToBlocks(sheetName, grid, merges, maxRow, maxCol, sheetIndex) {
16899
16941
  return blocks;
16900
16942
  }
16901
16943
  async function parseXlsxDocument(buffer, options) {
16902
- _chunkXZTDYOZVcjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE3);
16944
+ _chunkITJIALN5cjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE3);
16903
16945
  const zip = await _jszip2.default.loadAsync(buffer);
16904
16946
  const warnings = [];
16905
16947
  const workbookFile = zip.file("xl/workbook.xml");
16906
16948
  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");
16949
+ throw new (0, _chunkITJIALN5cjs.KordocError)("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 XLSX \uD30C\uC77C: xl/workbook.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
16908
16950
  }
16909
16951
  let sharedStrings = [];
16910
16952
  const ssFile = zip.file("xl/sharedStrings.xml");
@@ -16913,7 +16955,7 @@ async function parseXlsxDocument(buffer, options) {
16913
16955
  }
16914
16956
  const sheets = parseWorkbook(await workbookFile.async("text"));
16915
16957
  if (sheets.length === 0) {
16916
- throw new (0, _chunkXZTDYOZVcjs.KordocError)("XLSX \uD30C\uC77C\uC5D0 \uC2DC\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4");
16958
+ throw new (0, _chunkITJIALN5cjs.KordocError)("XLSX \uD30C\uC77C\uC5D0 \uC2DC\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4");
16917
16959
  }
16918
16960
  let relsMap = /* @__PURE__ */ new Map();
16919
16961
  const relsFile = zip.file("xl/_rels/workbook.xml.rels");
@@ -16921,7 +16963,7 @@ async function parseXlsxDocument(buffer, options) {
16921
16963
  relsMap = parseRels(await relsFile.async("text"));
16922
16964
  }
16923
16965
  let pageFilter = null;
16924
- if (_optionalChain([options, 'optionalAccess', _84 => _84.pages])) {
16966
+ if (_optionalChain([options, 'optionalAccess', _87 => _87.pages])) {
16925
16967
  const { parsePageRange: parsePageRange2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("./page-range-P7SDW6LR.cjs")));
16926
16968
  pageFilter = parsePageRange2(options.pages, sheets.length);
16927
16969
  }
@@ -16930,7 +16972,7 @@ async function parseXlsxDocument(buffer, options) {
16930
16972
  for (let i = 0; i < processedSheets; i++) {
16931
16973
  if (pageFilter && !pageFilter.has(i + 1)) continue;
16932
16974
  const sheet = sheets[i];
16933
- _optionalChain([options, 'optionalAccess', _85 => _85.onProgress, 'optionalCall', _86 => _86(i + 1, processedSheets)]);
16975
+ _optionalChain([options, 'optionalAccess', _88 => _88.onProgress, 'optionalCall', _89 => _89(i + 1, processedSheets)]);
16934
16976
  let sheetPath = relsMap.get(sheet.rId);
16935
16977
  if (sheetPath) {
16936
16978
  if (!sheetPath.startsWith("xl/") && !sheetPath.startsWith("/")) {
@@ -16985,7 +17027,7 @@ async function parseXlsxDocument(buffer, options) {
16985
17027
  } catch (e27) {
16986
17028
  }
16987
17029
  }
16988
- const markdown = _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, blocks);
17030
+ const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, blocks);
16989
17031
  return { markdown, blocks, metadata, warnings: warnings.length > 0 ? warnings : void 0 };
16990
17032
  }
16991
17033
 
@@ -17392,11 +17434,11 @@ function processGlobals(records) {
17392
17434
  let encrypted = false;
17393
17435
  const firstBof = records[0];
17394
17436
  if (!firstBof || firstBof.opcode !== OP_BOF) {
17395
- throw new (0, _chunkXZTDYOZVcjs.KordocError)("XLS: \uCCAB \uB808\uCF54\uB4DC\uAC00 BOF\uAC00 \uC544\uB2D8");
17437
+ throw new (0, _chunkITJIALN5cjs.KordocError)("XLS: \uCCAB \uB808\uCF54\uB4DC\uAC00 BOF\uAC00 \uC544\uB2D8");
17396
17438
  }
17397
17439
  const bof = decodeBof(firstBof.data);
17398
17440
  if (!bof || bof.dt !== DT_GLOBALS) {
17399
- throw new (0, _chunkXZTDYOZVcjs.KordocError)("XLS: Globals \uC11C\uBE0C\uC2A4\uD2B8\uB9BC BOF \uB204\uB77D");
17441
+ throw new (0, _chunkITJIALN5cjs.KordocError)("XLS: Globals \uC11C\uBE0C\uC2A4\uD2B8\uB9BC BOF \uB204\uB77D");
17400
17442
  }
17401
17443
  let i = 1;
17402
17444
  while (i < records.length) {
@@ -17504,14 +17546,14 @@ function sheetToBlocks2(sheetName, sheet, sheetIndex) {
17504
17546
  const merge = mergeMap.get(key);
17505
17547
  row.push({
17506
17548
  text: grid[r][c],
17507
- colSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _87 => _87.colSpan]), () => ( 1)),
17508
- rowSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _88 => _88.rowSpan]), () => ( 1))
17549
+ colSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _90 => _90.colSpan]), () => ( 1)),
17550
+ rowSpan: _nullishCoalesce(_optionalChain([merge, 'optionalAccess', _91 => _91.rowSpan]), () => ( 1))
17509
17551
  });
17510
17552
  }
17511
17553
  cellRows.push(row);
17512
17554
  }
17513
17555
  if (cellRows.length > 0) {
17514
- const table = _chunkXZTDYOZVcjs.buildTable.call(void 0, cellRows);
17556
+ const table = _chunkITJIALN5cjs.buildTable.call(void 0, cellRows);
17515
17557
  if (table.rows > 0) {
17516
17558
  blocks.push({ type: "table", table, pageNumber: sheetIndex + 1 });
17517
17559
  }
@@ -17524,21 +17566,21 @@ async function parseXlsDocument(buffer, options) {
17524
17566
  try {
17525
17567
  cfb = parseLenientCfb(buf);
17526
17568
  } catch (e) {
17527
- throw new (0, _chunkXZTDYOZVcjs.KordocError)(
17569
+ throw new (0, _chunkITJIALN5cjs.KordocError)(
17528
17570
  `XLS: OLE2 \uC2DC\uADF8\uB2C8\uCC98 \uAC80\uC99D \uC2E4\uD328 \u2014 ${e instanceof Error ? e.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`
17529
17571
  );
17530
17572
  }
17531
17573
  const wb = _nullishCoalesce(cfb.findStream("/Workbook"), () => ( cfb.findStream("/Book")));
17532
17574
  if (!wb) {
17533
- throw new (0, _chunkXZTDYOZVcjs.KordocError)("XLS: Workbook \uC2A4\uD2B8\uB9BC\uC774 \uC5C6\uC74C (BIFF5 \uB610\uB294 \uBE44\uD45C\uC900 \uD30C\uC77C)");
17575
+ throw new (0, _chunkITJIALN5cjs.KordocError)("XLS: Workbook \uC2A4\uD2B8\uB9BC\uC774 \uC5C6\uC74C (BIFF5 \uB610\uB294 \uBE44\uD45C\uC900 \uD30C\uC77C)");
17534
17576
  }
17535
17577
  const records = readRecords2(wb);
17536
17578
  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)");
17579
+ throw new (0, _chunkITJIALN5cjs.KordocError)("XLS: \uC2DC\uADF8\uB2C8\uCC98 \uB808\uCF54\uB4DC\uAC00 \uC5C6\uC74C (Workbook \uC2A4\uD2B8\uB9BC \uC190\uC0C1)");
17538
17580
  }
17539
17581
  const firstBof = decodeBof(records[0].data);
17540
17582
  if (firstBof && firstBof.vers !== 1536) {
17541
- throw new (0, _chunkXZTDYOZVcjs.KordocError)(
17583
+ throw new (0, _chunkITJIALN5cjs.KordocError)(
17542
17584
  `XLS: BIFF8(0x0600)\uB9CC \uC9C0\uC6D0 \u2014 \uBCF8 \uD30C\uC77C\uC740 0x${firstBof.vers.toString(16)}`
17543
17585
  );
17544
17586
  }
@@ -17559,7 +17601,7 @@ async function parseXlsDocument(buffer, options) {
17559
17601
  }
17560
17602
  const totalSheets = Math.min(globals.sheets.length, MAX_SHEETS2);
17561
17603
  let pageFilter = null;
17562
- if (_optionalChain([options, 'optionalAccess', _89 => _89.pages])) {
17604
+ if (_optionalChain([options, 'optionalAccess', _92 => _92.pages])) {
17563
17605
  const { parsePageRange: parsePageRange2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("./page-range-P7SDW6LR.cjs")));
17564
17606
  pageFilter = parsePageRange2(options.pages, totalSheets);
17565
17607
  }
@@ -17568,7 +17610,7 @@ async function parseXlsDocument(buffer, options) {
17568
17610
  if (pageFilter && !pageFilter.has(i + 1)) continue;
17569
17611
  const meta = globals.sheets[i];
17570
17612
  if (meta.dt !== 0) continue;
17571
- _optionalChain([options, 'optionalAccess', _90 => _90.onProgress, 'optionalCall', _91 => _91(i + 1, totalSheets)]);
17613
+ _optionalChain([options, 'optionalAccess', _93 => _93.onProgress, 'optionalCall', _94 => _94(i + 1, totalSheets)]);
17572
17614
  const bofIdx = findSheetBofIndex(records, meta.lbPlyPos);
17573
17615
  if (bofIdx < 0) {
17574
17616
  warnings.push({
@@ -17598,7 +17640,7 @@ async function parseXlsDocument(buffer, options) {
17598
17640
  pageCount: totalSheets
17599
17641
  };
17600
17642
  return {
17601
- markdown: _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, allBlocks),
17643
+ markdown: _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, allBlocks),
17602
17644
  blocks: allBlocks,
17603
17645
  metadata,
17604
17646
  warnings: warnings.length > 0 ? warnings : void 0
@@ -17611,7 +17653,7 @@ async function parseXlsDocument(buffer, options) {
17611
17653
 
17612
17654
  // src/docx/equation.ts
17613
17655
  function lname(el) {
17614
- return el.localName || _optionalChain([el, 'access', _92 => _92.tagName, 'optionalAccess', _93 => _93.replace, 'call', _94 => _94(/^[^:]+:/, "")]) || "";
17656
+ return el.localName || _optionalChain([el, 'access', _95 => _95.tagName, 'optionalAccess', _96 => _96.replace, 'call', _97 => _97(/^[^:]+:/, "")]) || "";
17615
17657
  }
17616
17658
  function kids(parent, name) {
17617
17659
  const out = [];
@@ -17984,7 +18026,7 @@ function isDisplayMath(el) {
17984
18026
  // src/docx/parser.ts
17985
18027
  var MAX_DECOMPRESS_SIZE4 = 100 * 1024 * 1024;
17986
18028
  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)));
18029
+ return el.localName === localName2 || (_nullishCoalesce(_optionalChain([el, 'access', _98 => _98.tagName, 'optionalAccess', _99 => _99.endsWith, 'call', _100 => _100(`:${localName2}`)]), () => ( false)));
17988
18030
  }
17989
18031
  function effectiveChildElements(parent) {
17990
18032
  const result = [];
@@ -18017,7 +18059,7 @@ function findElements(parent, localName2) {
18017
18059
  const child = children[i];
18018
18060
  if (child.nodeType === 1) {
18019
18061
  const el = child;
18020
- if (el.localName === localName2 || _optionalChain([el, 'access', _98 => _98.tagName, 'optionalAccess', _99 => _99.endsWith, 'call', _100 => _100(`:${localName2}`)])) {
18062
+ if (el.localName === localName2 || _optionalChain([el, 'access', _101 => _101.tagName, 'optionalAccess', _102 => _102.endsWith, 'call', _103 => _103(`:${localName2}`)])) {
18021
18063
  result.push(el);
18022
18064
  }
18023
18065
  walk(el);
@@ -18036,7 +18078,7 @@ function getAttr(el, localName2) {
18036
18078
  return null;
18037
18079
  }
18038
18080
  function parseXml2(text) {
18039
- return new (0, _xmldom.DOMParser)().parseFromString(_chunkXZTDYOZVcjs.stripDtd.call(void 0, text), "text/xml");
18081
+ return new (0, _xmldom.DOMParser)().parseFromString(_chunkITJIALN5cjs.stripDtd.call(void 0, text), "text/xml");
18040
18082
  }
18041
18083
  function parseStyles(xml) {
18042
18084
  const doc = parseXml2(xml);
@@ -18138,7 +18180,7 @@ function collectOmmlRoots(p) {
18138
18180
  const child = children[i];
18139
18181
  if (child.nodeType !== 1) continue;
18140
18182
  const el = child;
18141
- const tag = el.localName || _optionalChain([el, 'access', _101 => _101.tagName, 'optionalAccess', _102 => _102.replace, 'call', _103 => _103(/^[^:]+:/, "")]) || "";
18183
+ const tag = el.localName || _optionalChain([el, 'access', _104 => _104.tagName, 'optionalAccess', _105 => _105.replace, 'call', _106 => _106(/^[^:]+:/, "")]) || "";
18142
18184
  if (tag === "oMath" || tag === "oMathPara") {
18143
18185
  out.push(el);
18144
18186
  } else {
@@ -18227,7 +18269,7 @@ function parseParagraph2(p, styles, numbering, footnotes, rels) {
18227
18269
  const text = parts.join("").replace(/[ \t]{2,}/g, " ").trim();
18228
18270
  if (!text) return null;
18229
18271
  const style = styles.get(styleId);
18230
- if (_optionalChain([style, 'optionalAccess', _104 => _104.outlineLevel]) !== void 0 && style.outlineLevel >= 0 && style.outlineLevel <= 5) {
18272
+ if (_optionalChain([style, 'optionalAccess', _107 => _107.outlineLevel]) !== void 0 && style.outlineLevel >= 0 && style.outlineLevel <= 5) {
18231
18273
  return {
18232
18274
  type: "heading",
18233
18275
  text,
@@ -18236,8 +18278,8 @@ function parseParagraph2(p, styles, numbering, footnotes, rels) {
18236
18278
  }
18237
18279
  if (numId && numId !== "0") {
18238
18280
  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";
18281
+ const levelInfo = _optionalChain([numDef, 'optionalAccess', _108 => _108.get, 'call', _109 => _109(ilvl)]);
18282
+ const listType = _optionalChain([levelInfo, 'optionalAccess', _110 => _110.numFmt]) === "bullet" ? "unordered" : "ordered";
18241
18283
  return { type: "list", text, listType };
18242
18284
  }
18243
18285
  const block = { type: "paragraph", text };
@@ -18278,7 +18320,7 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
18278
18320
  const pElements = getChildElements(tc, "p");
18279
18321
  for (const p of pElements) {
18280
18322
  const block = parseParagraph2(p, styles, numbering, footnotes, rels);
18281
- if (_optionalChain([block, 'optionalAccess', _108 => _108.text])) cellTexts.push(block.text);
18323
+ if (_optionalChain([block, 'optionalAccess', _111 => _111.text])) cellTexts.push(block.text);
18282
18324
  }
18283
18325
  row.push({ text: cellTexts.join("\n"), colSpan, rowSpan });
18284
18326
  }
@@ -18291,7 +18333,7 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
18291
18333
  if (!cell || cell.rowSpan === 0) continue;
18292
18334
  let span = 1;
18293
18335
  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++;
18336
+ if (_optionalChain([rows, 'access', _112 => _112[nr], 'access', _113 => _113[c], 'optionalAccess', _114 => _114.rowSpan]) === 0) span++;
18295
18337
  else break;
18296
18338
  }
18297
18339
  cell.rowSpan = span;
@@ -18317,7 +18359,7 @@ function parseTable(tbl, styles, numbering, footnotes, rels) {
18317
18359
  };
18318
18360
  return { type: "table", table };
18319
18361
  }
18320
- async function extractImages(zip, rels, doc) {
18362
+ async function extractImages(zip, rels, doc, warnings) {
18321
18363
  const blocks = [];
18322
18364
  const images = [];
18323
18365
  const drawingElements = findElements(doc.documentElement, "drawing");
@@ -18335,7 +18377,7 @@ async function extractImages(zip, rels, doc) {
18335
18377
  try {
18336
18378
  const data = await imgFile.async("uint8array");
18337
18379
  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"));
18380
+ 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
18381
  const mimeMap = {
18340
18382
  png: "image/png",
18341
18383
  jpg: "image/jpeg",
@@ -18348,19 +18390,23 @@ async function extractImages(zip, rels, doc) {
18348
18390
  const filename = `image_${String(imgIdx).padStart(3, "0")}.${ext}`;
18349
18391
  images.push({ filename, data, mimeType: _nullishCoalesce(mimeMap[ext], () => ( "image/png")) });
18350
18392
  blocks.push({ type: "image", text: filename });
18351
- } catch (e28) {
18393
+ } catch (err) {
18394
+ warnings.push({
18395
+ code: "SKIPPED_IMAGE",
18396
+ message: `DOCX \uC774\uBBF8\uC9C0 \uCD94\uCD9C \uC2E4\uD328 (${imgPath}): ${err instanceof Error ? err.message : String(err)}`
18397
+ });
18352
18398
  }
18353
18399
  }
18354
18400
  }
18355
18401
  return { blocks, images };
18356
18402
  }
18357
18403
  async function parseDocxDocument(buffer, options) {
18358
- _chunkXZTDYOZVcjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE4);
18404
+ _chunkITJIALN5cjs.precheckZipSize.call(void 0, buffer, MAX_DECOMPRESS_SIZE4);
18359
18405
  const zip = await _jszip2.default.loadAsync(buffer);
18360
18406
  const warnings = [];
18361
18407
  const docFile = zip.file("word/document.xml");
18362
18408
  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");
18409
+ throw new (0, _chunkITJIALN5cjs.KordocError)("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 DOCX \uD30C\uC77C: word/document.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
18364
18410
  }
18365
18411
  let rels = /* @__PURE__ */ new Map();
18366
18412
  const relsFile = zip.file("word/_rels/document.xml.rels");
@@ -18372,7 +18418,11 @@ async function parseDocxDocument(buffer, options) {
18372
18418
  if (stylesFile) {
18373
18419
  try {
18374
18420
  styles = parseStyles(await stylesFile.async("text"));
18375
- } catch (e29) {
18421
+ } catch (err) {
18422
+ warnings.push({
18423
+ code: "PARTIAL_PARSE",
18424
+ message: `DOCX \uC2A4\uD0C0\uC77C(styles.xml) \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uAE30\uBCF8 \uC2A4\uD0C0\uC77C\uB85C \uACC4\uC18D: ${err instanceof Error ? err.message : String(err)}`
18425
+ });
18376
18426
  }
18377
18427
  }
18378
18428
  let numbering = /* @__PURE__ */ new Map();
@@ -18380,7 +18430,11 @@ async function parseDocxDocument(buffer, options) {
18380
18430
  if (numFile) {
18381
18431
  try {
18382
18432
  numbering = parseNumbering(await numFile.async("text"));
18383
- } catch (e30) {
18433
+ } catch (err) {
18434
+ warnings.push({
18435
+ code: "PARTIAL_PARSE",
18436
+ message: `DOCX \uBC88\uD638\uB9E4\uAE30\uAE30(numbering.xml) \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uBAA9\uB85D \uBC88\uD638 \uC0DD\uB7B5: ${err instanceof Error ? err.message : String(err)}`
18437
+ });
18384
18438
  }
18385
18439
  }
18386
18440
  let footnotes = /* @__PURE__ */ new Map();
@@ -18388,20 +18442,24 @@ async function parseDocxDocument(buffer, options) {
18388
18442
  if (fnFile) {
18389
18443
  try {
18390
18444
  footnotes = parseFootnotes(await fnFile.async("text"));
18391
- } catch (e31) {
18445
+ } catch (err) {
18446
+ warnings.push({
18447
+ code: "PARTIAL_PARSE",
18448
+ message: `DOCX \uAC01\uC8FC(footnotes.xml) \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uAC01\uC8FC \uC0DD\uB7B5: ${err instanceof Error ? err.message : String(err)}`
18449
+ });
18392
18450
  }
18393
18451
  }
18394
18452
  const docXml = await docFile.async("text");
18395
18453
  const doc = parseXml2(docXml);
18396
18454
  const body = findElements(doc, "body");
18397
18455
  if (body.length === 0) {
18398
- throw new (0, _chunkXZTDYOZVcjs.KordocError)("DOCX \uBCF8\uBB38(w:body)\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
18456
+ throw new (0, _chunkITJIALN5cjs.KordocError)("DOCX \uBCF8\uBB38(w:body)\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
18399
18457
  }
18400
18458
  const blocks = [];
18401
18459
  const bodyEl = body[0];
18402
18460
  const topLevel = effectiveChildElements(bodyEl);
18403
18461
  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()])));
18462
+ 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
18463
  if (localName2 === "p") {
18406
18464
  const block = parseParagraph2(el, styles, numbering, footnotes, rels);
18407
18465
  if (block) blocks.push(block);
@@ -18410,7 +18468,7 @@ async function parseDocxDocument(buffer, options) {
18410
18468
  if (block) blocks.push(block);
18411
18469
  }
18412
18470
  }
18413
- const { blocks: imgBlocks, images } = await extractImages(zip, rels, doc);
18471
+ const { blocks: imgBlocks, images } = await extractImages(zip, rels, doc, warnings);
18414
18472
  const metadata = {};
18415
18473
  const coreFile = zip.file("docProps/core.xml");
18416
18474
  if (coreFile) {
@@ -18428,11 +18486,15 @@ async function parseDocxDocument(buffer, options) {
18428
18486
  if (created) metadata.createdAt = created;
18429
18487
  const modified = getFirst("dcterms:modified");
18430
18488
  if (modified) metadata.modifiedAt = modified;
18431
- } catch (e32) {
18489
+ } catch (err) {
18490
+ warnings.push({
18491
+ code: "PARTIAL_PARSE",
18492
+ message: `DOCX \uBA54\uD0C0\uB370\uC774\uD130(core.xml) \uD30C\uC2F1 \uC2E4\uD328: ${err instanceof Error ? err.message : String(err)}`
18493
+ });
18432
18494
  }
18433
18495
  }
18434
18496
  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);
18497
+ const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, blocks);
18436
18498
  return {
18437
18499
  markdown,
18438
18500
  blocks,
@@ -18455,7 +18517,7 @@ function parseHwpmlDocument(buffer, options) {
18455
18517
  }
18456
18518
  const text = new TextDecoder("utf-8").decode(buffer).replace(/^\uFEFF/, "");
18457
18519
  const normalized = text.replace(/&nbsp;/g, "&#160;");
18458
- const xml = _chunkXZTDYOZVcjs.stripDtd.call(void 0, normalized);
18520
+ const xml = _chunkITJIALN5cjs.stripDtd.call(void 0, normalized);
18459
18521
  const warnings = [];
18460
18522
  const parser = new (0, _xmldom.DOMParser)({
18461
18523
  onError: (_level, msg2) => {
@@ -18483,7 +18545,7 @@ function parseHwpmlDocument(buffer, options) {
18483
18545
  return { markdown: "", blocks: [], metadata, warnings };
18484
18546
  }
18485
18547
  const blocks = [];
18486
- const pageFilter = _optionalChain([options, 'optionalAccess', _123 => _123.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, countSections(body)) : null;
18548
+ const pageFilter = _optionalChain([options, 'optionalAccess', _126 => _126.pages]) ? _chunkDCZVOIEOcjs.parsePageRange.call(void 0, options.pages, countSections(body)) : null;
18487
18549
  let sectionIdx = 0;
18488
18550
  const children = body.childNodes;
18489
18551
  for (let i = 0; i < children.length; i++) {
@@ -18495,7 +18557,7 @@ function parseHwpmlDocument(buffer, options) {
18495
18557
  parseSection2(el, blocks, paraShapeMap, sectionIdx, warnings);
18496
18558
  }
18497
18559
  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);
18560
+ const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, blocks);
18499
18561
  return {
18500
18562
  markdown,
18501
18563
  blocks,
@@ -18565,7 +18627,7 @@ function parseParagraph3(el, blocks, paraShapeMap, sectionNum) {
18565
18627
  const shapeInfo = paraShapeMap.get(paraShapeId);
18566
18628
  const text = extractParagraphText(el);
18567
18629
  if (!text) return;
18568
- if (_optionalChain([shapeInfo, 'optionalAccess', _124 => _124.headingLevel]) != null) {
18630
+ if (_optionalChain([shapeInfo, 'optionalAccess', _127 => _127.headingLevel]) != null) {
18569
18631
  blocks.push({ type: "heading", text, level: shapeInfo.headingLevel, pageNumber: sectionNum });
18570
18632
  } else {
18571
18633
  blocks.push({ type: "paragraph", text, pageNumber: sectionNum });
@@ -18637,7 +18699,7 @@ function parseTable2(el, blocks, paraShapeMap, sectionNum, warnings) {
18637
18699
  const cellRows = grid.map(
18638
18700
  (row) => row.map((cell) => _nullishCoalesce(cell, () => ( { text: "", colSpan: 1, rowSpan: 1 })))
18639
18701
  );
18640
- const table = _chunkXZTDYOZVcjs.buildTable.call(void 0, cellRows);
18702
+ const table = _chunkITJIALN5cjs.buildTable.call(void 0, cellRows);
18641
18703
  blocks.push({ type: "table", table, pageNumber: sectionNum });
18642
18704
  }
18643
18705
  function extractCellText(cellEl) {
@@ -18697,6 +18759,45 @@ function countSections(body) {
18697
18759
  }
18698
18760
 
18699
18761
  // src/form/match.ts
18762
+ var ValueCursor = (_class2 = class {
18763
+ constructor(values) {;_class2.prototype.__init4.call(this);
18764
+ this.values = values;
18765
+ }
18766
+ __init4() {this.nextIdx = /* @__PURE__ */ new Map()}
18767
+ keys() {
18768
+ return this.values.keys();
18769
+ }
18770
+ has(key) {
18771
+ return this.values.has(key);
18772
+ }
18773
+ isArray(key) {
18774
+ return Array.isArray(this.values.get(key));
18775
+ }
18776
+ /** 남은 값이 있으면 true (스칼라는 항상 true) */
18777
+ available(key) {
18778
+ const v = this.values.get(key);
18779
+ if (v === void 0) return false;
18780
+ return typeof v === "string" || (_nullishCoalesce(this.nextIdx.get(key), () => ( 0))) < v.length;
18781
+ }
18782
+ /** 현재 값 미리보기 (소진 없음) */
18783
+ peek(key) {
18784
+ const v = this.values.get(key);
18785
+ if (v === void 0) return void 0;
18786
+ if (typeof v === "string") return v;
18787
+ const i = _nullishCoalesce(this.nextIdx.get(key), () => ( 0));
18788
+ return i < v.length ? v[i] : void 0;
18789
+ }
18790
+ /** 값 소비 — 배열이면 커서 전진, 소진 시 undefined */
18791
+ consume(key) {
18792
+ const v = this.values.get(key);
18793
+ if (v === void 0) return void 0;
18794
+ if (typeof v === "string") return v;
18795
+ const i = _nullishCoalesce(this.nextIdx.get(key), () => ( 0));
18796
+ if (i >= v.length) return void 0;
18797
+ this.nextIdx.set(key, i + 1);
18798
+ return v[i];
18799
+ }
18800
+ }, _class2);
18700
18801
  function normalizeLabel(label) {
18701
18802
  return label.trim().replace(/[::\s()()·]/g, "");
18702
18803
  }
@@ -18735,9 +18836,9 @@ function fillInCellPatterns(cellText, values, matchedLabels) {
18735
18836
  (match, prefix, suffix) => {
18736
18837
  const label = prefix + suffix;
18737
18838
  const normalizedLabel = normalizeLabel(label);
18738
- const matchKey = values.has(normalizedLabel) ? normalizedLabel : values.has(normalizeLabel(prefix)) ? normalizeLabel(prefix) : void 0;
18839
+ const matchKey = values.available(normalizedLabel) ? normalizedLabel : values.available(normalizeLabel(prefix)) ? normalizeLabel(prefix) : void 0;
18739
18840
  if (matchKey === void 0) return match;
18740
- const newValue = values.get(matchKey);
18841
+ const newValue = values.consume(matchKey);
18741
18842
  matchedLabels.add(matchKey);
18742
18843
  matches.push({ key: matchKey, label, value: newValue });
18743
18844
  return `${prefix}(${newValue})${suffix}`;
@@ -18747,11 +18848,12 @@ function fillInCellPatterns(cellText, values, matchedLabels) {
18747
18848
  /□([가-힣A-Za-z]+)/g,
18748
18849
  (match, keyword) => {
18749
18850
  const normalizedKw = normalizeLabel(keyword);
18750
- const matchKey = values.has(normalizedKw) ? normalizedKw : void 0;
18851
+ const matchKey = values.available(normalizedKw) ? normalizedKw : void 0;
18751
18852
  if (matchKey === void 0) return match;
18752
- const val = values.get(matchKey);
18853
+ const val = values.peek(matchKey);
18753
18854
  const isTruthy = ["\u2611", "\u2713", "\u2714", "v", "V", "true", "1", "yes", "o", "O"].includes(val.trim()) || val.trim() === "";
18754
18855
  if (!isTruthy) return match;
18856
+ values.consume(matchKey);
18755
18857
  matchedLabels.add(matchKey);
18756
18858
  matches.push({ key: matchKey, label: `\u25A1${keyword}`, value: "\u2611" });
18757
18859
  return `\u2611${keyword}`;
@@ -18761,9 +18863,9 @@ function fillInCellPatterns(cellText, values, matchedLabels) {
18761
18863
  /\(([가-힣A-Za-z]+)[::]\s{1,}\)/g,
18762
18864
  (match, keyword) => {
18763
18865
  const normalizedKw = normalizeLabel(keyword);
18764
- const matchKey = values.has(normalizedKw) ? normalizedKw : void 0;
18866
+ const matchKey = values.available(normalizedKw) ? normalizedKw : void 0;
18765
18867
  if (matchKey === void 0) return match;
18766
- const newValue = values.get(matchKey);
18868
+ const newValue = values.consume(matchKey);
18767
18869
  matchedLabels.add(matchKey);
18768
18870
  matches.push({ key: matchKey, label: keyword, value: newValue });
18769
18871
  return `(${keyword}\uFF1A${newValue})`;
@@ -18869,14 +18971,66 @@ var LABEL_KEYWORDS = /* @__PURE__ */ new Set([
18869
18971
  "\uCCAD\uAD6C\uC0AC\uC720",
18870
18972
  "\uC18C\uBA85\uC790\uB8CC"
18871
18973
  ]);
18974
+ var ENGLISH_LABEL_WORDS = /* @__PURE__ */ new Set([
18975
+ "name",
18976
+ "date",
18977
+ "address",
18978
+ "tel",
18979
+ "phone",
18980
+ "mobile",
18981
+ "fax",
18982
+ "email",
18983
+ "e-mail",
18984
+ "dept",
18985
+ "department",
18986
+ "division",
18987
+ "title",
18988
+ "position",
18989
+ "grade",
18990
+ "rank",
18991
+ "birth",
18992
+ "nationality",
18993
+ "sex",
18994
+ "gender",
18995
+ "signature",
18996
+ "sign",
18997
+ "seal",
18998
+ "remarks",
18999
+ "note",
19000
+ "period",
19001
+ "place",
19002
+ "purpose",
19003
+ "reason",
19004
+ "amount",
19005
+ "total",
19006
+ "sum",
19007
+ "qty",
19008
+ "quantity",
19009
+ "unit",
19010
+ "no",
19011
+ "id",
19012
+ "passport"
19013
+ ]);
19014
+ var ENGLISH_STOPWORDS = /* @__PURE__ */ new Set(["of", "the", "and", "or", "in"]);
19015
+ var NUMERIC_VALUE_RE = /^제?\d+(?:[.,]\d+)*[십백천만억조]*(?:원|명|건|개|회|부|매|장|점|호|번|년|월|일|시|분|초|개월|주년|차례|퍼센트)?$/;
19016
+ var SENTENCE_ENDING_RE = /(?:입니다|합니다|습니다|하세요|십시오|시오|바랍니다|바람|할 것|할것|하며|하고|한다|된다|됨|음|임)$/;
18872
19017
  function isLabelCell(text) {
18873
19018
  const trimmed = text.trim().replace(/[¹²³⁴⁵⁶⁷⁸⁹⁰*※]+$/g, "").trim();
18874
19019
  if (!trimmed || trimmed.length > 30) return false;
18875
19020
  for (const kw of LABEL_KEYWORDS) {
18876
19021
  if (trimmed.includes(kw)) return true;
18877
19022
  }
18878
- if (/^[가-힣\s()()·::]+$/.test(trimmed) && trimmed.replace(/\s/g, "").length >= 2 && trimmed.replace(/\s/g, "").length <= 8 && !/\d/.test(trimmed)) return true;
19023
+ const compact = trimmed.replace(/\s/g, "");
19024
+ 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)) {
19025
+ return true;
19026
+ }
18879
19027
  if (/^[가-힣A-Za-z\s]+[::]$/.test(trimmed)) return true;
19028
+ if (/^[A-Za-z][A-Za-z\s./&-]*$/.test(trimmed) && trimmed.length <= 20) {
19029
+ const words = trimmed.toLowerCase().split(/[\s/&]+/).filter((w) => w && !ENGLISH_STOPWORDS.has(w));
19030
+ if (words.length >= 1 && words.length <= 3 && words.every((w) => ENGLISH_LABEL_WORDS.has(w.replace(/\.$/, "")))) {
19031
+ return true;
19032
+ }
19033
+ }
18880
19034
  return false;
18881
19035
  }
18882
19036
  function extractFormFields(blocks) {
@@ -18906,8 +19060,8 @@ function extractFromTable(table) {
18906
19060
  if (table.cols >= 2) {
18907
19061
  for (let r = 0; r < table.rows; r++) {
18908
19062
  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]]);
19063
+ const labelCell = _optionalChain([table, 'access', _128 => _128.cells, 'access', _129 => _129[r], 'optionalAccess', _130 => _130[c]]);
19064
+ const valueCell = _optionalChain([table, 'access', _131 => _131.cells, 'access', _132 => _132[r], 'optionalAccess', _133 => _133[c + 1]]);
18911
19065
  if (!labelCell || !valueCell) continue;
18912
19066
  if (isLabelCell(labelCell.text)) {
18913
19067
  fields.push({
@@ -18929,8 +19083,8 @@ function extractFromTable(table) {
18929
19083
  if (allLabels) {
18930
19084
  for (let r = 1; r < table.rows; r++) {
18931
19085
  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()]), () => ( ""));
19086
+ const label = _nullishCoalesce(_optionalChain([headerRow, 'access', _134 => _134[c], 'optionalAccess', _135 => _135.text, 'access', _136 => _136.trim, 'call', _137 => _137()]), () => ( ""));
19087
+ 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
19088
  if (label && value) {
18935
19089
  fields.push({ label, value, row: r, col: c });
18936
19090
  }
@@ -19017,17 +19171,18 @@ function fillFormFields(blocks, values) {
19017
19171
  const filled = [];
19018
19172
  const matchedLabels = /* @__PURE__ */ new Set();
19019
19173
  const normalizedValues = normalizeValues(values);
19174
+ const cursor = new ValueCursor(normalizedValues);
19175
+ const allTables = collectIRTables(cloned, 0);
19020
19176
  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]]);
19177
+ for (const table of allTables) {
19178
+ for (let r = 0; r < table.rows; r++) {
19179
+ for (let c = 0; c < table.cols; c++) {
19180
+ const cell = _optionalChain([table, 'access', _144 => _144.cells, 'access', _145 => _145[r], 'optionalAccess', _146 => _146[c]]);
19026
19181
  if (!cell) continue;
19027
- const result = fillInCellPatterns(cell.text, normalizedValues, matchedLabels);
19182
+ const result = fillInCellPatterns(cell.text, cursor, matchedLabels);
19028
19183
  if (result) {
19029
19184
  cell.text = result.text;
19030
- patternFilledCells.add(`${r},${c}`);
19185
+ patternFilledCells.add(cell);
19031
19186
  for (const m of result.matches) {
19032
19187
  filled.push({ label: m.label, value: m.value, row: r, col: c });
19033
19188
  }
@@ -19035,33 +19190,71 @@ function fillFormFields(blocks, values) {
19035
19190
  }
19036
19191
  }
19037
19192
  }
19038
- for (const block of cloned) {
19039
- if (block.type !== "table" || !block.table) continue;
19040
- fillTable(block.table, normalizedValues, filled, matchedLabels, patternFilledCells);
19193
+ for (const table of allTables) {
19194
+ fillTable(table, cursor, filled, matchedLabels, patternFilledCells);
19041
19195
  }
19042
19196
  for (const block of cloned) {
19043
19197
  if (block.type !== "paragraph" || !block.text) continue;
19044
- const newText = fillInlineFields(block.text, normalizedValues, filled, matchedLabels);
19198
+ const newText = fillInlineFields(block.text, cursor, filled, matchedLabels);
19045
19199
  if (newText !== block.text) block.text = newText;
19046
19200
  }
19047
19201
  const unmatched = resolveUnmatched(normalizedValues, matchedLabels, values);
19048
19202
  return { blocks: cloned, filled, unmatched };
19049
19203
  }
19204
+ function collectIRTables(blocks, depth) {
19205
+ if (depth > 16) return [];
19206
+ const out = [];
19207
+ for (const block of blocks) {
19208
+ if (block.type !== "table" || !block.table) continue;
19209
+ out.push(block.table);
19210
+ for (const row of block.table.cells) {
19211
+ for (const cell of row) {
19212
+ if (_optionalChain([cell, 'optionalAccess', _147 => _147.blocks, 'optionalAccess', _148 => _148.length])) out.push(...collectIRTables(cell.blocks, depth + 1));
19213
+ }
19214
+ }
19215
+ }
19216
+ return out;
19217
+ }
19218
+ function coveredPositions(table) {
19219
+ const covered = /* @__PURE__ */ new Set();
19220
+ for (let r = 0; r < table.rows; r++) {
19221
+ for (let c = 0; c < table.cols; c++) {
19222
+ if (covered.has(`${r},${c}`)) continue;
19223
+ const cell = _optionalChain([table, 'access', _149 => _149.cells, 'access', _150 => _150[r], 'optionalAccess', _151 => _151[c]]);
19224
+ if (!cell) continue;
19225
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
19226
+ for (let dc = 0; dc < cell.colSpan; dc++) {
19227
+ if (dr === 0 && dc === 0) continue;
19228
+ if (r + dr < table.rows && c + dc < table.cols) covered.add(`${r + dr},${c + dc}`);
19229
+ }
19230
+ }
19231
+ c += cell.colSpan - 1;
19232
+ }
19233
+ }
19234
+ return covered;
19235
+ }
19050
19236
  function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
19051
19237
  if (table.cols < 2) return;
19238
+ const covered = coveredPositions(table);
19052
19239
  for (let r = 0; r < table.rows; r++) {
19053
- for (let c = 0; c < table.cols - 1; c++) {
19240
+ for (let c = 0; c < table.cols; c++) {
19241
+ if (covered.has(`${r},${c}`)) continue;
19054
19242
  const labelCell = table.cells[r][c];
19055
- const valueCell = table.cells[r][c + 1];
19056
- if (!labelCell || !valueCell) continue;
19243
+ if (!labelCell) continue;
19057
19244
  if (!isLabelCell(labelCell.text)) continue;
19245
+ let vc = c + labelCell.colSpan;
19246
+ while (vc < table.cols && covered.has(`${r},${vc}`)) vc++;
19247
+ if (vc >= table.cols) continue;
19248
+ const valueCell = table.cells[r][vc];
19249
+ if (!valueCell) continue;
19058
19250
  if (isKeywordLabel(valueCell.text)) continue;
19059
19251
  const normalizedCellLabel = normalizeLabel(labelCell.text);
19060
19252
  if (!normalizedCellLabel) continue;
19061
19253
  const matchKey = findMatchingKey(normalizedCellLabel, values);
19062
19254
  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}`)])) {
19255
+ const newValue = values.consume(matchKey);
19256
+ if (newValue === void 0) continue;
19257
+ if (_optionalChain([patternFilledCells, 'optionalAccess', _152 => _152.has, 'call', _153 => _153(valueCell)])) {
19065
19258
  valueCell.text = newValue + " " + valueCell.text;
19066
19259
  } else {
19067
19260
  valueCell.text = newValue;
@@ -19084,14 +19277,16 @@ function fillTable(table, values, filled, matchedLabels, patternFilledCells) {
19084
19277
  if (!allLabels) return;
19085
19278
  for (let r = 1; r < table.rows; r++) {
19086
19279
  for (let c = 0; c < table.cols; c++) {
19280
+ if (covered.has(`${r},${c}`)) continue;
19087
19281
  const headerCell = headerRow[c];
19088
- const valueCell = _optionalChain([table, 'access', _147 => _147.cells, 'access', _148 => _148[r], 'optionalAccess', _149 => _149[c]]);
19282
+ const valueCell = _optionalChain([table, 'access', _154 => _154.cells, 'access', _155 => _155[r], 'optionalAccess', _156 => _156[c]]);
19089
19283
  if (!headerCell || !valueCell) continue;
19090
19284
  const headerLabel = normalizeLabel(headerCell.text);
19091
19285
  const matchKey = findMatchingKey(headerLabel, values);
19092
19286
  if (matchKey === void 0) continue;
19093
- if (matchedLabels.has(matchKey)) continue;
19094
- const newValue = values.get(matchKey);
19287
+ if (!values.isArray(matchKey) && matchedLabels.has(matchKey)) continue;
19288
+ const newValue = values.consume(matchKey);
19289
+ if (newValue === void 0) continue;
19095
19290
  valueCell.text = newValue;
19096
19291
  matchedLabels.add(matchKey);
19097
19292
  filled.push({
@@ -19112,7 +19307,8 @@ function fillInlineFields(text, values, filled, matchedLabels) {
19112
19307
  for (const seg of segments) {
19113
19308
  const matchKey = findMatchingKey(normalizeLabel(seg.label), values);
19114
19309
  if (matchKey === void 0) continue;
19115
- const newValue = values.get(matchKey);
19310
+ const newValue = values.consume(matchKey);
19311
+ if (newValue === void 0) continue;
19116
19312
  matchedLabels.add(matchKey);
19117
19313
  filled.push({ label: seg.label.trim(), value: newValue, row: -1, col: -1 });
19118
19314
  out += text.slice(pos, seg.valueStart);
@@ -19147,7 +19343,7 @@ function decodeXmlEntities(text) {
19147
19343
  try {
19148
19344
  const code = ent[1] === "x" || ent[1] === "X" ? parseInt(ent.slice(2), 16) : parseInt(ent.slice(1), 10);
19149
19345
  if (!isNaN(code) && code >= 0 && code <= 1114111) return String.fromCodePoint(code);
19150
- } catch (e33) {
19346
+ } catch (e28) {
19151
19347
  }
19152
19348
  return m;
19153
19349
  });
@@ -19219,6 +19415,7 @@ function scanSectionXml(xml, sectionIndex) {
19219
19415
  const paraStack = [];
19220
19416
  const tableStack = [];
19221
19417
  const rowStack = [];
19418
+ const trStartStack = [];
19222
19419
  const cellStack = [];
19223
19420
  let pendingT = null;
19224
19421
  const ctrlSubStack = [];
@@ -19283,11 +19480,17 @@ function scanSectionXml(xml, sectionIndex) {
19283
19480
  } else if (local2 === "tr") {
19284
19481
  const row = rowStack[rowStack.length - 1];
19285
19482
  const table = tableStack[tableStack.length - 1];
19286
- if (row && table && row.length > 0) table.rows.push(row);
19483
+ if (row && table && row.length > 0) {
19484
+ table.rows.push(row);
19485
+ const trStart = trStartStack[trStartStack.length - 1];
19486
+ if (trStart >= 0) table.rowRanges.push({ start: trStart, end: m.index + full.length });
19487
+ }
19287
19488
  if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
19489
+ if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = -1;
19288
19490
  } else if (local2 === "tbl") {
19289
19491
  const table = tableStack.pop();
19290
19492
  rowStack.pop();
19493
+ trStartStack.pop();
19291
19494
  if (table) {
19292
19495
  finalizeTable(table);
19293
19496
  if (!table.topLevel) {
@@ -19330,6 +19533,7 @@ function scanSectionXml(xml, sectionIndex) {
19330
19533
  const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
19331
19534
  if (!isNaN(ca)) cell.colAddr = ca;
19332
19535
  if (!isNaN(ra)) cell.rowAddr = ra;
19536
+ cell.addrTagRange = { start: m.index, end: m.index + full.length };
19333
19537
  }
19334
19538
  } else if (local === "cellSpan") {
19335
19539
  const cell = cellStack[cellStack.length - 1];
@@ -19380,6 +19584,7 @@ function scanSectionXml(xml, sectionIndex) {
19380
19584
  start: m.index,
19381
19585
  topLevel: false,
19382
19586
  rows: [],
19587
+ rowRanges: [],
19383
19588
  cellByAnchor: /* @__PURE__ */ new Map()
19384
19589
  };
19385
19590
  stack.pop();
@@ -19387,9 +19592,11 @@ function scanSectionXml(xml, sectionIndex) {
19387
19592
  stack.push({ local, qname, contentStart });
19388
19593
  tableStack.push(table);
19389
19594
  rowStack.push([]);
19595
+ trStartStack.push(-1);
19390
19596
  if (table.topLevel) tables.push(table);
19391
19597
  } else if (local === "tr") {
19392
19598
  if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
19599
+ if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = m.index;
19393
19600
  } else if (local === "tc") {
19394
19601
  cellStack.push({ colSpan: 1, rowSpan: 1, paragraphs: [], tables: [] });
19395
19602
  } else if (local === "cellAddr" || local === "cellSpan") {
@@ -19400,6 +19607,7 @@ function scanSectionXml(xml, sectionIndex) {
19400
19607
  const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
19401
19608
  if (!isNaN(ca)) cell.colAddr = ca;
19402
19609
  if (!isNaN(ra)) cell.rowAddr = ra;
19610
+ cell.addrTagRange = { start: m.index, end: contentStart };
19403
19611
  } else {
19404
19612
  const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
19405
19613
  const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
@@ -19664,19 +19872,19 @@ function parseCentralDirectory(buf) {
19664
19872
  }
19665
19873
  }
19666
19874
  }
19667
- if (eocdOffset < 0) throw new (0, _chunkXZTDYOZVcjs.KordocError)("ZIP EOCD\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
19875
+ if (eocdOffset < 0) throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP EOCD\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
19668
19876
  const totalEntries = view.getUint16(eocdOffset + 10, true);
19669
19877
  const cdSize = view.getUint32(eocdOffset + 12, true);
19670
19878
  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");
19879
+ if (cdOffset === 4294967295 || totalEntries === 65535) throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19672
19880
  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");
19881
+ throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19674
19882
  }
19675
19883
  const decoder = new TextDecoder("utf-8");
19676
19884
  const entries = [];
19677
19885
  let pos = cdOffset;
19678
19886
  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");
19887
+ if (view.getUint32(pos, true) !== CD_SIG) throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP Central Directory \uC190\uC0C1");
19680
19888
  const flags = view.getUint16(pos + 8, true);
19681
19889
  const method = view.getUint16(pos + 10, true);
19682
19890
  const crc = view.getUint32(pos + 16, true);
@@ -19687,7 +19895,7 @@ function parseCentralDirectory(buf) {
19687
19895
  const commentLen = view.getUint16(pos + 32, true);
19688
19896
  const localOffset = view.getUint32(pos + 42, true);
19689
19897
  if (compSize === 4294967295 || uncompSize === 4294967295 || localOffset === 4294967295) {
19690
- throw new (0, _chunkXZTDYOZVcjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19898
+ throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19691
19899
  }
19692
19900
  const name = decoder.decode(buf.subarray(pos + 46, pos + 46 + nameLen));
19693
19901
  const cdEnd = pos + 46 + nameLen + extraLen + commentLen;
@@ -19716,7 +19924,7 @@ function patchZipEntries(original, replacements) {
19716
19924
  const { entries, cdOffset, eocdOffset } = parseCentralDirectory(original);
19717
19925
  const view = new DataView(original.buffer, original.byteOffset, original.byteLength);
19718
19926
  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}`);
19927
+ if (!entries.some((e) => e.name === name)) throw new (0, _chunkITJIALN5cjs.KordocError)(`ZIP\uC5D0 \uC5C6\uB294 \uC5D4\uD2B8\uB9AC: ${name}`);
19720
19928
  }
19721
19929
  const byLocal = [...entries].sort((a, b) => a.localOffset - b.localOffset);
19722
19930
  const segments = [];
@@ -19734,7 +19942,7 @@ function patchZipEntries(original, replacements) {
19734
19942
  offset += seg.length;
19735
19943
  continue;
19736
19944
  }
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");
19945
+ if (view.getUint32(e.localOffset, true) !== LOCAL_SIG) throw new (0, _chunkITJIALN5cjs.KordocError)("ZIP \uB85C\uCEEC \uD5E4\uB354 \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
19738
19946
  const nameLen = view.getUint16(e.localOffset + 26, true);
19739
19947
  const extraLen = view.getUint16(e.localOffset + 28, true);
19740
19948
  const headerLen = 30 + nameLen + extraLen;
@@ -19789,9 +19997,10 @@ async function fillHwpx(hwpxBuffer, values) {
19789
19997
  const zip = await _jszip2.default.loadAsync(hwpxBuffer);
19790
19998
  const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
19791
19999
  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");
20000
+ throw new (0, _chunkITJIALN5cjs.KordocError)("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
19793
20001
  }
19794
20002
  const normalizedValues = normalizeValues(values);
20003
+ const cursor = new ValueCursor(normalizedValues);
19795
20004
  const matchedLabels = /* @__PURE__ */ new Set();
19796
20005
  const filled = [];
19797
20006
  const failedKeys = /* @__PURE__ */ new Set();
@@ -19827,7 +20036,7 @@ async function fillHwpx(hwpxBuffer, values) {
19827
20036
  for (const cell of row) {
19828
20037
  for (const para of cell.paragraphs) {
19829
20038
  const text = matchText(para);
19830
- const result = fillInCellPatterns(text, normalizedValues, matchedLabels);
20039
+ const result = fillInCellPatterns(text, cursor, matchedLabels);
19831
20040
  if (!result) continue;
19832
20041
  const l = led(para);
19833
20042
  if (l.fullText !== void 0) continue;
@@ -19861,21 +20070,30 @@ async function fillHwpx(hwpxBuffer, values) {
19861
20070
  if (isKeywordLabel(cellLabelText(valueCell))) continue;
19862
20071
  const normalizedCellLabel = normalizeLabel(labelText);
19863
20072
  if (!normalizedCellLabel) continue;
19864
- const matchKey = findMatchingKey(normalizedCellLabel, normalizedValues);
20073
+ const matchKey = findMatchingKey(normalizedCellLabel, cursor);
19865
20074
  if (matchKey === void 0) continue;
19866
- const newValue = normalizedValues.get(matchKey);
19867
20075
  if (patternApplied.has(valueCell)) {
19868
20076
  const target = _nullishCoalesce(valueCell.paragraphs.find((p) => p.tRanges.length > 0), () => ( valueCell.paragraphs[0]));
19869
20077
  if (!target) continue;
19870
20078
  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
- }
20079
+ if (l.fullText !== void 0) continue;
20080
+ const newValue = cursor.consume(matchKey);
20081
+ if (newValue === void 0) continue;
20082
+ l.ranges.push({ start: 0, end: 0, replacement: newValue + " " });
20083
+ l.filledIdx.push(filled.length);
20084
+ l.matchKeys.push(matchKey);
20085
+ matchedLabels.add(matchKey);
20086
+ filled.push({
20087
+ label: labelText.trim().replace(/[::]\s*$/, ""),
20088
+ value: newValue,
20089
+ row: rowIdx,
20090
+ col: colIdx
20091
+ });
19876
20092
  } else {
19877
20093
  const paras = valueCell.paragraphs;
19878
20094
  if (paras.length === 0) continue;
20095
+ const newValue = cursor.consume(matchKey);
20096
+ if (newValue === void 0) continue;
19879
20097
  const l0 = led(paras[0]);
19880
20098
  l0.fullText = newValue;
19881
20099
  l0.ranges = [];
@@ -19886,14 +20104,14 @@ async function fillHwpx(hwpxBuffer, values) {
19886
20104
  lk.fullText = "";
19887
20105
  lk.ranges = [];
19888
20106
  }
20107
+ matchedLabels.add(matchKey);
20108
+ filled.push({
20109
+ label: labelText.trim().replace(/[::]\s*$/, ""),
20110
+ value: newValue,
20111
+ row: rowIdx,
20112
+ col: colIdx
20113
+ });
19889
20114
  }
19890
- matchedLabels.add(matchKey);
19891
- filled.push({
19892
- label: labelText.trim().replace(/[::]\s*$/, ""),
19893
- value: newValue,
19894
- row: rowIdx,
19895
- col: colIdx
19896
- });
19897
20115
  }
19898
20116
  }
19899
20117
  if (table.rows.length >= 2) {
@@ -19907,10 +20125,11 @@ async function fillHwpx(hwpxBuffer, values) {
19907
20125
  const dataCells = table.rows[rowIdx];
19908
20126
  for (let colIdx = 0; colIdx < Math.min(headerCells.length, dataCells.length); colIdx++) {
19909
20127
  const headerLabel = normalizeLabel(cellLabelText(headerCells[colIdx]));
19910
- const matchKey = findMatchingKey(headerLabel, normalizedValues);
20128
+ const matchKey = findMatchingKey(headerLabel, cursor);
19911
20129
  if (matchKey === void 0) continue;
19912
- if (matchedLabels.has(matchKey)) continue;
19913
- const newValue = normalizedValues.get(matchKey);
20130
+ if (!cursor.isArray(matchKey) && matchedLabels.has(matchKey)) continue;
20131
+ const newValue = cursor.consume(matchKey);
20132
+ if (newValue === void 0) continue;
19914
20133
  const paras = dataCells[colIdx].paragraphs;
19915
20134
  if (paras.length === 0) continue;
19916
20135
  const l0 = led(paras[0]);
@@ -19937,12 +20156,13 @@ async function fillHwpx(hwpxBuffer, values) {
19937
20156
  }
19938
20157
  for (const para of [...scan.bodyParagraphs, ...scan.excludedParagraphs]) {
19939
20158
  const existing = ledger.get(para);
19940
- if (_optionalChain([existing, 'optionalAccess', _150 => _150.fullText]) !== void 0) continue;
20159
+ if (_optionalChain([existing, 'optionalAccess', _157 => _157.fullText]) !== void 0) continue;
19941
20160
  const text = matchText(para);
19942
20161
  for (const seg of scanInlineSegments(text)) {
19943
- const matchKey = findMatchingKey(normalizeLabel(seg.label), normalizedValues);
20162
+ const matchKey = findMatchingKey(normalizeLabel(seg.label), cursor);
19944
20163
  if (matchKey === void 0) continue;
19945
- const newValue = normalizedValues.get(matchKey);
20164
+ const newValue = cursor.consume(matchKey);
20165
+ if (newValue === void 0) continue;
19946
20166
  const replacement = seg.valueStart === seg.valueEnd ? padInsertion(text, seg.valueStart, newValue) : newValue;
19947
20167
  const l = led(para);
19948
20168
  l.ranges.push({ start: seg.valueStart, end: seg.valueEnd, replacement });
@@ -19997,6 +20217,7 @@ async function fillHwpx(hwpxBuffer, values) {
19997
20217
  splices.push(...paraSplices);
19998
20218
  }
19999
20219
  if (splices.length > 0) {
20220
+ splices.push(...allLinesegRemovalSplices(xml));
20000
20221
  replacements.set(sectionPaths[si], encoder.encode(applySplices(xml, splices)));
20001
20222
  }
20002
20223
  }
@@ -20016,6 +20237,245 @@ async function fillHwpx(hwpxBuffer, values) {
20016
20237
  // src/hwpx/generator.ts
20017
20238
 
20018
20239
 
20240
+ // src/hwpx/text-metrics.ts
20241
+ var ASCII_W = [
20242
+ 300,
20243
+ 320,
20244
+ 320,
20245
+ 610,
20246
+ 610,
20247
+ 830,
20248
+ 724,
20249
+ 320,
20250
+ 320,
20251
+ 320,
20252
+ 550,
20253
+ 550,
20254
+ 320,
20255
+ 550,
20256
+ 320,
20257
+ 550,
20258
+ // 0x20-0x2F
20259
+ 550,
20260
+ 550,
20261
+ 550,
20262
+ 550,
20263
+ 550,
20264
+ 550,
20265
+ 550,
20266
+ 550,
20267
+ 550,
20268
+ 550,
20269
+ 320,
20270
+ 320,
20271
+ 550,
20272
+ 550,
20273
+ 550,
20274
+ 550,
20275
+ // 0x30-0x3F
20276
+ 830,
20277
+ 706,
20278
+ 605,
20279
+ 685,
20280
+ 719,
20281
+ 627,
20282
+ 617,
20283
+ 683,
20284
+ 734,
20285
+ 305,
20286
+ 315,
20287
+ 660,
20288
+ 605,
20289
+ 839,
20290
+ 734,
20291
+ 732,
20292
+ // 0x40-0x4F
20293
+ 603,
20294
+ 705,
20295
+ 660,
20296
+ 627,
20297
+ 664,
20298
+ 731,
20299
+ 706,
20300
+ 910,
20301
+ 705,
20302
+ 705,
20303
+ 626,
20304
+ 320,
20305
+ 550,
20306
+ 320,
20307
+ 550,
20308
+ 550,
20309
+ // 0x50-0x5F
20310
+ 320,
20311
+ 569,
20312
+ 597,
20313
+ 552,
20314
+ 597,
20315
+ 536,
20316
+ 356,
20317
+ 562,
20318
+ 635,
20319
+ 287,
20320
+ 288,
20321
+ 582,
20322
+ 287,
20323
+ 907,
20324
+ 635,
20325
+ 588,
20326
+ // 0x60-0x6F
20327
+ 597,
20328
+ 579,
20329
+ 478,
20330
+ 496,
20331
+ 356,
20332
+ 635,
20333
+ 563,
20334
+ 720,
20335
+ 542,
20336
+ 543,
20337
+ 486,
20338
+ 320,
20339
+ 320,
20340
+ 320,
20341
+ 550,
20342
+ 0
20343
+ // 0x70-0x7E(+DEL)
20344
+ ];
20345
+ var SYM_W = {
20346
+ 160: 300,
20347
+ 163: 568,
20348
+ 165: 707,
20349
+ 167: 498,
20350
+ 171: 440,
20351
+ 172: 564,
20352
+ 176: 291,
20353
+ 177: 798,
20354
+ 182: 606,
20355
+ 183: 320,
20356
+ 187: 440,
20357
+ 215: 617,
20358
+ 247: 678,
20359
+ 8211: 625,
20360
+ 8212: 875,
20361
+ 8213: 875,
20362
+ 8216: 320,
20363
+ 8217: 320,
20364
+ 8220: 480,
20365
+ 8221: 480,
20366
+ 8224: 558,
20367
+ 8225: 438,
20368
+ 8229: 640,
20369
+ 8230: 960,
20370
+ 8240: 988,
20371
+ 8242: 335,
20372
+ 8243: 474,
20373
+ 8251: 770,
20374
+ 8364: 656,
20375
+ 9756: 1012,
20376
+ 9758: 1012
20377
+ };
20378
+ function charWidthEm1000(cp) {
20379
+ if (cp >= 32 && cp <= 126) return ASCII_W[cp - 32];
20380
+ const sym = SYM_W[cp];
20381
+ if (sym !== void 0) return sym;
20382
+ if (cp >= 44032 && cp <= 55203) return 970;
20383
+ if (cp >= 4352 && cp <= 4607) return 970;
20384
+ if (cp >= 12593 && cp <= 12686) return 970;
20385
+ if (cp >= 19968 && cp <= 40959 || cp >= 63744 && cp <= 64255) return 1e3;
20386
+ if (cp >= 12296 && cp <= 12305 || cp >= 12308 && cp <= 12315) return 500;
20387
+ if (cp === 12288) return 970;
20388
+ if (cp >= 8592 && cp <= 8959) return 970;
20389
+ if (cp >= 9312 && cp <= 9471) return 970;
20390
+ if (cp >= 9632 && cp <= 9983) return 970;
20391
+ if (cp >= 12800 && cp <= 13311) return 970;
20392
+ if (cp >= 65281 && cp <= 65376) return 970;
20393
+ return cp >= 11904 ? 970 : 550;
20394
+ }
20395
+ var SPACE_EM_FIXED = 500;
20396
+ var SPACE_EM_FONT = 300;
20397
+ function measureTextWidth(text, height, ratioPct, opts) {
20398
+ const spaceEm = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _158 => _158.spaceEm]), () => ( SPACE_EM_FIXED));
20399
+ const spacing = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _159 => _159.spacingPct]), () => ( 0));
20400
+ let em = 0;
20401
+ for (const ch of text) {
20402
+ const cp = ch.codePointAt(0);
20403
+ const w = cp === 32 ? spaceEm : charWidthEm1000(cp);
20404
+ em += w * (1 + spacing / 100);
20405
+ }
20406
+ return em / 1e3 * height * (ratioPct / 100);
20407
+ }
20408
+ var FORBID_START = /* @__PURE__ */ new Set([..."!%),.:;?]}\xA2\xB0\u2032\u2033\u2103\u3009\u300B\u300D\u300F\u3011\u3015!%),.:;?]}\u20A9~\u2026\xB7\u3001\u3002\u3003"]);
20409
+ var FORBID_END = /* @__PURE__ */ new Set([..."$([{\xA3\xA5\u3008\u300A\u300C\u300E\u3010\u3014$([{\u20A9"]);
20410
+ function simulateWrap(text, firstWidth, contWidth, height, ratioPct, mode = "keep", opts) {
20411
+ const EPS = 0.5;
20412
+ const spaceEm = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _160 => _160.spaceEm]), () => ( SPACE_EM_FIXED));
20413
+ const spacing = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _161 => _161.spacingPct]), () => ( 0));
20414
+ const k = height * ratioPct / 100 / 1e3;
20415
+ const cwCp = (cp) => (cp === 32 ? spaceEm : charWidthEm1000(cp)) * (1 + spacing / 100) * k;
20416
+ const charW = (ch) => cwCp(ch.codePointAt(0));
20417
+ const rangeW = (from, to) => {
20418
+ let w = 0;
20419
+ for (const ch of text.slice(from, to)) w += charW(ch);
20420
+ return w;
20421
+ };
20422
+ const units = _nullishCoalesce(text.match(mode === "keep" ? / +|[^ ]+/g : / +|[^ ]/g), () => ( []));
20423
+ const starts = [0];
20424
+ let lineW = 0;
20425
+ let avail = firstWidth;
20426
+ let pos = 0;
20427
+ const lineStart = () => starts[starts.length - 1];
20428
+ const breakBefore = (unitPos, w) => {
20429
+ let bp = unitPos;
20430
+ const u = text[unitPos];
20431
+ if (u !== void 0 && FORBID_START.has(u) && bp - 1 > lineStart() && text[bp - 1] !== " ") bp--;
20432
+ while (bp - 1 > lineStart() && FORBID_END.has(text[bp - 1])) bp--;
20433
+ if (bp <= lineStart()) bp = unitPos;
20434
+ starts.push(bp);
20435
+ avail = contWidth;
20436
+ lineW = rangeW(bp, unitPos) + w;
20437
+ };
20438
+ for (const u of units) {
20439
+ if (u[0] === " ") {
20440
+ lineW += charW(" ") * u.length;
20441
+ pos += u.length;
20442
+ continue;
20443
+ }
20444
+ const w = rangeW(pos, pos + u.length);
20445
+ if (lineW + w <= avail + EPS) {
20446
+ lineW += w;
20447
+ pos += u.length;
20448
+ continue;
20449
+ }
20450
+ if (lineW === 0 || w > contWidth + EPS) {
20451
+ let sub = 0;
20452
+ for (const ch of u) {
20453
+ const c = charW(ch);
20454
+ if (lineW + c > avail + EPS && lineW > 0) breakBefore(pos + sub, 0);
20455
+ lineW += c;
20456
+ sub += ch.length;
20457
+ }
20458
+ pos += u.length;
20459
+ continue;
20460
+ }
20461
+ breakBefore(pos, w);
20462
+ pos += u.length;
20463
+ }
20464
+ return { lines: starts.length, starts, lastLineWidth: lineW };
20465
+ }
20466
+ function simulateWrapKeepWord(text, firstWidth, contWidth, height, ratioPct, opts) {
20467
+ return simulateWrap(text, firstWidth, contWidth, height, ratioPct, "keep", opts);
20468
+ }
20469
+ function fitRatioForFewerLines(text, firstWidth, contWidth, height, baseRatio, minRatio, opts) {
20470
+ const base = simulateWrap(text, firstWidth, contWidth, height, baseRatio, "keep", opts);
20471
+ if (base.lines < 2) return null;
20472
+ for (let r = baseRatio - 1; r >= minRatio; r--) {
20473
+ const sim = simulateWrap(text, firstWidth, contWidth, height, r, "keep", opts);
20474
+ if (sim.lines < base.lines) return r;
20475
+ }
20476
+ return null;
20477
+ }
20478
+
20019
20479
  // src/hwpx/gongmun.ts
20020
20480
  var OFFICIAL_MARGINS = { top: 20, bottom: 10, left: 20, right: 20 };
20021
20481
  var PRESET_DEFAULTS = {
@@ -20051,6 +20511,7 @@ function resolveGongmun(opts) {
20051
20511
  const preset = normalizeGongmunPreset(opts.preset);
20052
20512
  const d = PRESET_DEFAULTS[preset];
20053
20513
  const bodyPt = _nullishCoalesce(opts.bodyPt, () => ( d.bodyPt));
20514
+ const autoFitMinRatio = opts.autoFit === false ? null : typeof opts.autoFit === "object" ? Math.min(Math.max(_nullishCoalesce(opts.autoFit.minRatio, () => ( 90)), 50), 99) : 90;
20054
20515
  return {
20055
20516
  preset,
20056
20517
  bodyFont: _nullishCoalesce(opts.bodyFont, () => ( "myeongjo")),
@@ -20058,7 +20519,8 @@ function resolveGongmun(opts) {
20058
20519
  lineSpacing: _nullishCoalesce(opts.lineSpacing, () => ( d.lineSpacing)),
20059
20520
  numbering: _nullishCoalesce(opts.numbering, () => ( d.numbering)),
20060
20521
  margins: _nullishCoalesce(opts.margins, () => ( OFFICIAL_MARGINS)),
20061
- centerTitle: _nullishCoalesce(opts.centerTitle, () => ( true))
20522
+ centerTitle: _nullishCoalesce(opts.centerTitle, () => ( true)),
20523
+ autoFitMinRatio
20062
20524
  };
20063
20525
  }
20064
20526
  var HANGUL_INITIALS = [0, 2, 3, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18];
@@ -20101,17 +20563,10 @@ function standardMarker(depth, n) {
20101
20563
  function reportMarker(depth) {
20102
20564
  return REPORT_BULLETS[Math.min(depth, REPORT_BULLETS.length - 1)];
20103
20565
  }
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
20566
  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);
20567
+ let em = SPACE_EM_FIXED;
20568
+ for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
20569
+ return Math.round(em / 1e3 * bodyHeight);
20115
20570
  }
20116
20571
  function levelIndent(depth, bodyHeight, numbering) {
20117
20572
  const marker = numbering === "report" ? reportMarker(depth) : standardMarker(depth, 0);
@@ -20130,11 +20585,11 @@ function computeSuppression(depths) {
20130
20585
  }
20131
20586
  return keys.map((k) => (_nullishCoalesce(counts.get(k), () => ( 0))) <= 1);
20132
20587
  }
20133
- var GongmunNumberer = (_class2 = class {
20134
- constructor(numbering) {;_class2.prototype.__init4.call(this);
20588
+ var GongmunNumberer = (_class3 = class {
20589
+ constructor(numbering) {;_class3.prototype.__init5.call(this);
20135
20590
  this.numbering = numbering;
20136
20591
  }
20137
- __init4() {this.counts = []}
20592
+ __init5() {this.counts = []}
20138
20593
  /** depth 항목 하나에 대한 마커. suppress=true면 빈 문자열(부호 없음) */
20139
20594
  next(depth, suppress) {
20140
20595
  this.counts.length = depth + 1;
@@ -20146,82 +20601,58 @@ var GongmunNumberer = (_class2 = class {
20146
20601
  reset() {
20147
20602
  this.counts = [];
20148
20603
  }
20149
- }, _class2);
20604
+ }, _class3);
20150
20605
  function mmToHwpunit(mm) {
20151
20606
  return Math.round(mm * 7200 / 25.4);
20152
20607
  }
20153
20608
 
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
- };
20609
+ // src/diff/text-diff.ts
20610
+ function similarity(a, b) {
20611
+ if (a === b) return 1;
20612
+ if (!a || !b) return 0;
20613
+ const maxLen = Math.max(a.length, b.length);
20614
+ if (maxLen === 0) return 1;
20615
+ return 1 - levenshtein(a, b) / maxLen;
20195
20616
  }
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" });
20617
+ function normalizedSimilarity(a, b) {
20618
+ return similarity(normalize(a), normalize(b));
20209
20619
  }
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;
20620
+ function normalize(s) {
20621
+ return s.replace(/\s+/g, " ").trim();
20622
+ }
20623
+ var MAX_LEVENSHTEIN_LEN = 1e4;
20624
+ function levenshtein(a, b) {
20625
+ if (a.length + b.length > MAX_LEVENSHTEIN_LEN) {
20626
+ const sampleLen = Math.min(500, a.length, b.length);
20627
+ let diffs = 0;
20628
+ for (let i = 0; i < sampleLen; i++) if (a[i] !== b[i]) diffs++;
20629
+ const sampleRate = sampleLen > 0 ? diffs / sampleLen : 1;
20630
+ return Math.abs(a.length - b.length) + Math.round(Math.min(a.length, b.length) * sampleRate);
20219
20631
  }
20220
- return lines.join("\n").slice(0, 1024);
20632
+ if (a.length > b.length) [a, b] = [b, a];
20633
+ const m = a.length;
20634
+ const n = b.length;
20635
+ let prev = Array.from({ length: m + 1 }, (_, i) => i);
20636
+ let curr = new Array(m + 1);
20637
+ for (let j = 1; j <= n; j++) {
20638
+ curr[0] = j;
20639
+ for (let i = 1; i <= m; i++) {
20640
+ if (a[i - 1] === b[j - 1]) {
20641
+ curr[i] = prev[i - 1];
20642
+ } else {
20643
+ curr[i] = 1 + Math.min(prev[i - 1], prev[i], curr[i - 1]);
20644
+ }
20645
+ }
20646
+ ;
20647
+ [prev, curr] = [curr, prev];
20648
+ }
20649
+ return prev[m];
20221
20650
  }
20222
- function parseMarkdownToBlocks(md2) {
20651
+
20652
+ // src/roundtrip/markdown-units.ts
20653
+ function splitMarkdownUnits(md2) {
20223
20654
  const lines = md2.split("\n");
20224
- const blocks = [];
20655
+ const units = [];
20225
20656
  let i = 0;
20226
20657
  while (i < lines.length) {
20227
20658
  const line = lines[i];
@@ -20229,32 +20660,489 @@ function parseMarkdownToBlocks(md2) {
20229
20660
  i++;
20230
20661
  continue;
20231
20662
  }
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]);
20663
+ if (line.trim().startsWith("<table>")) {
20664
+ const collected2 = [];
20665
+ let depth = 0;
20666
+ while (i < lines.length) {
20667
+ const l = lines[i];
20668
+ collected2.push(l);
20669
+ depth += (l.match(/<table>/g) || []).length;
20670
+ depth -= (l.match(/<\/table>/g) || []).length;
20240
20671
  i++;
20672
+ if (depth <= 0) break;
20241
20673
  }
20242
- if (i < lines.length) i++;
20243
- blocks.push({ type: "code_block", text: codeLines.join("\n"), lang });
20674
+ units.push({ kind: "html-table", raw: collected2.join("\n"), lines: collected2 });
20244
20675
  continue;
20245
20676
  }
20246
- if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line.trim())) {
20247
- blocks.push({ type: "hr" });
20248
- i++;
20677
+ if (line.trimStart().startsWith("|")) {
20678
+ const collected2 = [];
20679
+ while (i < lines.length && lines[i].trimStart().startsWith("|")) {
20680
+ collected2.push(lines[i]);
20681
+ i++;
20682
+ }
20683
+ units.push({ kind: "gfm-table", raw: collected2.join("\n"), lines: collected2 });
20249
20684
  continue;
20250
20685
  }
20251
- const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
20252
- if (headingMatch) {
20253
- blocks.push({ type: "heading", text: headingMatch[2].trim(), level: headingMatch[1].length });
20686
+ if (/^-{3,}\s*$/.test(line.trim())) {
20687
+ units.push({ kind: "separator", raw: line.trim(), lines: [line.trim()] });
20254
20688
  i++;
20255
20689
  continue;
20256
20690
  }
20257
- if (line.trimStart().startsWith("|")) {
20691
+ if (/^!\[image\]\([^)]*\)\s*$/.test(line.trim())) {
20692
+ units.push({ kind: "image", raw: line.trim(), lines: [line.trim()] });
20693
+ i++;
20694
+ continue;
20695
+ }
20696
+ const collected = [];
20697
+ while (i < lines.length && lines[i].trim() && !lines[i].trimStart().startsWith("|") && !lines[i].trim().startsWith("<table>")) {
20698
+ collected.push(lines[i].trim());
20699
+ i++;
20700
+ }
20701
+ units.push({ kind: "text", raw: collected.join("\n"), lines: collected });
20702
+ }
20703
+ return units;
20704
+ }
20705
+ function alignUnits(a, b) {
20706
+ const m = a.length, n = b.length;
20707
+ if (m * n > 4e6) {
20708
+ const result2 = [];
20709
+ let pre = 0;
20710
+ while (pre < m && pre < n && a[pre] === b[pre]) {
20711
+ result2.push([pre, pre]);
20712
+ pre++;
20713
+ }
20714
+ let suf = 0;
20715
+ while (suf < m - pre && suf < n - pre && a[m - 1 - suf] === b[n - 1 - suf]) suf++;
20716
+ const aMid = m - pre - suf, bMid = n - pre - suf;
20717
+ if (aMid === bMid) {
20718
+ for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, pre + i2]);
20719
+ } else {
20720
+ for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, null]);
20721
+ for (let j2 = 0; j2 < bMid; j2++) result2.push([null, pre + j2]);
20722
+ }
20723
+ for (let s = suf - 1; s >= 0; s--) result2.push([m - 1 - s, n - 1 - s]);
20724
+ return result2;
20725
+ }
20726
+ const dp = Array.from({ length: m + 1 }, () => new Int32Array(n + 1));
20727
+ for (let i2 = 1; i2 <= m; i2++) {
20728
+ for (let j2 = 1; j2 <= n; j2++) {
20729
+ 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]);
20730
+ }
20731
+ }
20732
+ const matches = [];
20733
+ let i = m, j = n;
20734
+ while (i > 0 && j > 0) {
20735
+ if (a[i - 1] === b[j - 1] && dp[i][j] === dp[i - 1][j - 1] + 1) {
20736
+ matches.push([i - 1, j - 1]);
20737
+ i--;
20738
+ j--;
20739
+ } else if (dp[i - 1][j] >= dp[i][j - 1]) i--;
20740
+ else j--;
20741
+ }
20742
+ matches.reverse();
20743
+ const result = [];
20744
+ let ai = 0, bi = 0;
20745
+ const flushGap = (aEnd, bEnd) => {
20746
+ if (aEnd - ai === bEnd - bi) {
20747
+ while (ai < aEnd) result.push([ai++, bi++]);
20748
+ return;
20749
+ }
20750
+ while (ai < aEnd && bi < bEnd) {
20751
+ const sim = normalizedSimilarity(a[ai], b[bi]);
20752
+ if (sim >= 0.4) {
20753
+ if (aEnd - ai > bEnd - bi && bestSimInRange(a, ai + 1, ai + (aEnd - ai) - (bEnd - bi), b[bi]) > sim) {
20754
+ result.push([ai++, null]);
20755
+ } else if (bEnd - bi > aEnd - ai && bestSimInRange(b, bi + 1, bi + (bEnd - bi) - (aEnd - ai), a[ai]) > sim) {
20756
+ result.push([null, bi++]);
20757
+ } else {
20758
+ result.push([ai++, bi++]);
20759
+ }
20760
+ } else if (aEnd - ai >= bEnd - bi) result.push([ai++, null]);
20761
+ else result.push([null, bi++]);
20762
+ }
20763
+ while (ai < aEnd) result.push([ai++, null]);
20764
+ while (bi < bEnd) result.push([null, bi++]);
20765
+ };
20766
+ for (const [pi, pj] of matches) {
20767
+ flushGap(pi, pj);
20768
+ result.push([ai++, bi++]);
20769
+ }
20770
+ flushGap(m, n);
20771
+ return result;
20772
+ }
20773
+ function bestSimInRange(arr, from, to, target) {
20774
+ let best = 0;
20775
+ for (let k = from; k <= to && k < arr.length; k++) {
20776
+ const s = normalizedSimilarity(arr[k], target);
20777
+ if (s > best) best = s;
20778
+ }
20779
+ return best;
20780
+ }
20781
+ function escapeGfm(text) {
20782
+ return text.replace(/~/g, "\\~");
20783
+ }
20784
+ var HWP_SHAPE_ALT_TEXT_RE = /(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|이등변 삼각형|직각 삼각형|선|직선|곡선|화살표|굵은 화살표|이중 화살표|오각형|육각형|팔각형|별|[4-8]점별|십자|십자형|구름|구름형|마름모|도넛|평행사변형|사다리꼴|부채꼴|호|반원|물결|번개|하트|빗금|블록 화살표|수식|표|그림|개체|그리기\s?개체|묶음\s?개체|글상자|수식\s?개체|OLE\s?개체)\s?입니다\.?/g;
20785
+ function sanitizeText(text) {
20786
+ let result = _chunkITJIALN5cjs.mapPuaText.call(void 0, text).replace(/[\u{F0000}-\u{FFFFD}]/gu, "").replace(HWP_SHAPE_ALT_TEXT_RE, "").replace(/ +/g, " ").trim();
20787
+ if (result.length <= 30 && result.includes(" ")) {
20788
+ const tokens = result.split(" ");
20789
+ const koreanSingleCharCount = tokens.filter((t) => t.length === 1 && /[가-힯ㄱ-ㆎ]/.test(t)).length;
20790
+ if (tokens.length >= 3 && koreanSingleCharCount / tokens.length >= 0.7) {
20791
+ result = tokens.join("");
20792
+ }
20793
+ }
20794
+ return result;
20795
+ }
20796
+ function normForMatch(text) {
20797
+ return sanitizeText(text).replace(/\s+/g, " ").trim();
20798
+ }
20799
+ function unescapeGfm(text) {
20800
+ return text.replace(/\\~/g, "~");
20801
+ }
20802
+ function summarize(text) {
20803
+ const t = text.replace(/\s+/g, " ").trim();
20804
+ return t.length > 80 ? t.slice(0, 77) + "..." : t;
20805
+ }
20806
+ function replicateGfmTable(table) {
20807
+ const { cells, rows: numRows, cols: numCols } = table;
20808
+ if (numRows === 0 || numCols === 0) return null;
20809
+ if (numRows === 1 && numCols === 1) return null;
20810
+ if (numCols === 1) return null;
20811
+ const display = Array.from({ length: numRows }, (_, r) => Array.from({ length: numCols }, (_2, c) => ({ text: "", gridR: r, gridC: c })));
20812
+ const skip = /* @__PURE__ */ new Set();
20813
+ for (let r = 0; r < numRows; r++) {
20814
+ for (let c = 0; c < numCols; c++) {
20815
+ if (skip.has(`${r},${c}`)) continue;
20816
+ const cell = _optionalChain([cells, 'access', _162 => _162[r], 'optionalAccess', _163 => _163[c]]);
20817
+ if (!cell) continue;
20818
+ display[r][c] = {
20819
+ text: escapeGfm(sanitizeText(cell.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
20820
+ gridR: r,
20821
+ gridC: c
20822
+ };
20823
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
20824
+ for (let dc = 0; dc < cell.colSpan; dc++) {
20825
+ if (dr === 0 && dc === 0) continue;
20826
+ if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
20827
+ }
20828
+ }
20829
+ c += cell.colSpan - 1;
20830
+ }
20831
+ }
20832
+ const uniqueRows = [];
20833
+ let pendingLabelRow = null;
20834
+ for (let r = 0; r < display.length; r++) {
20835
+ const row = display[r];
20836
+ if (row.every((cell) => cell.text === "")) continue;
20837
+ const nonEmptyCols = row.filter((cell) => cell.text !== "");
20838
+ const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
20839
+ if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
20840
+ if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
20841
+ pendingLabelRow = row;
20842
+ continue;
20843
+ }
20844
+ if (pendingLabelRow) {
20845
+ if (row[0].text === "") row[0] = pendingLabelRow[0];
20846
+ else uniqueRows.push(pendingLabelRow);
20847
+ pendingLabelRow = null;
20848
+ }
20849
+ uniqueRows.push(row);
20850
+ }
20851
+ if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
20852
+ return uniqueRows.length > 0 ? uniqueRows : null;
20853
+ }
20854
+ function parseGfmTable(lines) {
20855
+ const rows = [];
20856
+ for (const line of lines) {
20857
+ const trimmed = line.trim();
20858
+ if (!trimmed.startsWith("|")) continue;
20859
+ const cells = trimmed.split(/(?<!\\)\|/).slice(1, -1).map((c) => c.trim());
20860
+ if (cells.length === 0) continue;
20861
+ if (cells.every((c) => /^:?-{3,}:?$/.test(c))) continue;
20862
+ rows.push(cells);
20863
+ }
20864
+ return rows;
20865
+ }
20866
+ function unescapeGfmCell(text) {
20867
+ return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\~/g, "~");
20868
+ }
20869
+ function replicateCellInnerHtml(cell) {
20870
+ if (_optionalChain([cell, 'access', _164 => _164.blocks, 'optionalAccess', _165 => _165.length])) {
20871
+ return cell.blocks.map((b) => {
20872
+ if (b.type === "table" && b.table) {
20873
+ const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
20874
+ return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
20875
+ }
20876
+ if (b.type === "image" && b.text) return `<img src="${b.text}" alt="image">`;
20877
+ const t = sanitizeText(_nullishCoalesce(b.text, () => ( "")));
20878
+ return t ? t.replace(/\n/g, "<br>") : "";
20879
+ }).filter(Boolean).join("<br>");
20880
+ }
20881
+ return sanitizeText(cell.text).replace(/\n/g, "<br>");
20882
+ }
20883
+ function replicateTableToHtml(table) {
20884
+ const rows = replicateHtmlTable(table);
20885
+ const lines = ["<table>"];
20886
+ for (let r = 0; r < rows.length; r++) {
20887
+ const tag = rows[r].tag;
20888
+ const rowHtml = rows[r].cells.map((cell) => {
20889
+ const attrs = [];
20890
+ if (cell.colSpan > 1) attrs.push(`colspan="${cell.colSpan}"`);
20891
+ if (cell.rowSpan > 1) attrs.push(`rowspan="${cell.rowSpan}"`);
20892
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
20893
+ return `<${tag}${attrStr}>${cell.inner}</${tag}>`;
20894
+ });
20895
+ if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
20896
+ }
20897
+ lines.push("</table>");
20898
+ return lines.join("\n");
20899
+ }
20900
+ function replicateHtmlTable(table) {
20901
+ const { cells, rows: numRows, cols: numCols } = table;
20902
+ const skip = /* @__PURE__ */ new Set();
20903
+ const result = [];
20904
+ for (let r = 0; r < numRows; r++) {
20905
+ const tag = r === 0 ? "th" : "td";
20906
+ const rowCells = [];
20907
+ for (let c = 0; c < numCols; c++) {
20908
+ if (skip.has(`${r},${c}`)) continue;
20909
+ const cell = _optionalChain([cells, 'access', _166 => _166[r], 'optionalAccess', _167 => _167[c]]);
20910
+ if (!cell) continue;
20911
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
20912
+ for (let dc = 0; dc < cell.colSpan; dc++) {
20913
+ if (dr === 0 && dc === 0) continue;
20914
+ if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
20915
+ }
20916
+ }
20917
+ rowCells.push({
20918
+ inner: replicateCellInnerHtml(cell),
20919
+ colSpan: cell.colSpan,
20920
+ rowSpan: cell.rowSpan,
20921
+ gridR: r,
20922
+ gridC: c
20923
+ });
20924
+ }
20925
+ if (rowCells.length) result.push({ tag, cells: rowCells });
20926
+ }
20927
+ return result;
20928
+ }
20929
+ function parseHtmlTable(raw) {
20930
+ const re = /<(\/?)(table|tr|td|th)((?:"[^"]*"|'[^']*'|[^>"'])*?)>/gi;
20931
+ let depth = 0;
20932
+ let currentRow = null;
20933
+ let cellStart = -1;
20934
+ let cellInfo = null;
20935
+ const rows = [];
20936
+ let m;
20937
+ while ((m = re.exec(raw)) !== null) {
20938
+ const isClose = m[1] === "/";
20939
+ const tag = m[2].toLowerCase();
20940
+ const attrs = m[3] || "";
20941
+ if (tag === "table") {
20942
+ depth += isClose ? -1 : 1;
20943
+ if (depth < 0) return null;
20944
+ continue;
20945
+ }
20946
+ if (depth !== 1) continue;
20947
+ if (tag === "tr") {
20948
+ if (!isClose) currentRow = [];
20949
+ else if (currentRow) {
20950
+ rows.push({ tag: rows.length === 0 ? "th" : "td", cells: currentRow });
20951
+ currentRow = null;
20952
+ }
20953
+ } else {
20954
+ if (!isClose) {
20955
+ const cs = parseInt(_optionalChain([attrs, 'access', _168 => _168.match, 'call', _169 => _169(/colspan\s*=\s*"(\d+)"/i), 'optionalAccess', _170 => _170[1]]) || "1", 10);
20956
+ const rs = parseInt(_optionalChain([attrs, 'access', _171 => _171.match, 'call', _172 => _172(/rowspan\s*=\s*"(\d+)"/i), 'optionalAccess', _173 => _173[1]]) || "1", 10);
20957
+ cellStart = m.index + m[0].length;
20958
+ cellInfo = { colSpan: isNaN(cs) ? 1 : cs, rowSpan: isNaN(rs) ? 1 : rs };
20959
+ } else if (cellStart >= 0 && cellInfo && currentRow) {
20960
+ currentRow.push({ inner: raw.slice(cellStart, m.index), colSpan: cellInfo.colSpan, rowSpan: cellInfo.rowSpan });
20961
+ cellStart = -1;
20962
+ cellInfo = null;
20963
+ }
20964
+ }
20965
+ }
20966
+ if (depth !== 0) return null;
20967
+ return rows;
20968
+ }
20969
+ var AUTONUM_PREFIX_RE = /^(?:[0-90-9a-zA-Z가-힣]{1,6}[.)\]:]|[([][0-90-9a-zA-Z가-힣]{1,6}[)\]][.:]?|[ⅰ-ⅹⅠ-Ⅹ①-⑮][.)\]:]?)$/u;
20970
+ function htmlCellInnerToLines(inner) {
20971
+ let hadNonText = false;
20972
+ let work = inner;
20973
+ if (/<table[\s>]/i.test(work)) {
20974
+ hadNonText = true;
20975
+ work = removeNestedTables(work);
20976
+ }
20977
+ if (/<img\s/i.test(work)) {
20978
+ hadNonText = true;
20979
+ work = work.replace(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi, "");
20980
+ }
20981
+ const lines = work.split(/<br\s*\/?>/gi).map((s) => s.trim()).filter((s) => s.length > 0);
20982
+ return { lines, hadNonText };
20983
+ }
20984
+ function extractTopLevelTables(html) {
20985
+ const result = [];
20986
+ let depth = 0;
20987
+ let start = -1;
20988
+ const re = /<(\/?)table(?:[\s>]|>)/gi;
20989
+ let m;
20990
+ while ((m = re.exec(html)) !== null) {
20991
+ if (m[1] !== "/") {
20992
+ if (depth === 0) start = m.index;
20993
+ depth++;
20994
+ } else {
20995
+ depth--;
20996
+ if (depth === 0 && start >= 0) {
20997
+ result.push(html.slice(start, m.index + m[0].length));
20998
+ start = -1;
20999
+ }
21000
+ if (depth < 0) depth = 0;
21001
+ }
21002
+ }
21003
+ return result;
21004
+ }
21005
+ function removeNestedTables(html) {
21006
+ let result = "";
21007
+ let depth = 0;
21008
+ const re = /<(\/?)table(?:[\s>]|>)/gi;
21009
+ let last = 0;
21010
+ let m;
21011
+ while ((m = re.exec(html)) !== null) {
21012
+ if (m[1] !== "/") {
21013
+ if (depth === 0) result += html.slice(last, m.index);
21014
+ depth++;
21015
+ } else {
21016
+ depth--;
21017
+ if (depth === 0) last = m.index + m[0].length;
21018
+ if (depth < 0) depth = 0;
21019
+ }
21020
+ }
21021
+ if (depth === 0) result += html.slice(last);
21022
+ return result;
21023
+ }
21024
+
21025
+ // src/hwpx/generator.ts
21026
+ var NS_SECTION = "http://www.hancom.co.kr/hwpml/2011/section";
21027
+ var NS_PARA = "http://www.hancom.co.kr/hwpml/2011/paragraph";
21028
+ var NS_HEAD = "http://www.hancom.co.kr/hwpml/2011/head";
21029
+ var NS_CORE = "http://www.hancom.co.kr/hwpml/2011/core";
21030
+ var NS_OPF = "http://www.idpf.org/2007/opf/";
21031
+ var NS_HPF = "http://www.hancom.co.kr/schema/2011/hpf";
21032
+ var NS_OCF = "urn:oasis:names:tc:opendocument:xmlns:container";
21033
+ var CHAR_NORMAL = 0;
21034
+ var CHAR_BOLD = 1;
21035
+ var CHAR_ITALIC = 2;
21036
+ var CHAR_BOLD_ITALIC = 3;
21037
+ var CHAR_CODE = 4;
21038
+ var CHAR_H1 = 5;
21039
+ var CHAR_H2 = 6;
21040
+ var CHAR_H3 = 7;
21041
+ var CHAR_H4 = 8;
21042
+ var CHAR_TABLE_HEADER = 9;
21043
+ var CHAR_QUOTE = 10;
21044
+ var PARA_NORMAL = 0;
21045
+ var PARA_H1 = 1;
21046
+ var PARA_H2 = 2;
21047
+ var PARA_H3 = 3;
21048
+ var PARA_H4 = 4;
21049
+ var PARA_CODE = 5;
21050
+ var PARA_QUOTE = 6;
21051
+ var PARA_LIST = 7;
21052
+ var DEFAULT_TEXT_COLOR = "#000000";
21053
+ function resolveTheme(theme) {
21054
+ return {
21055
+ h1: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _174 => _174.headingColors, 'optionalAccess', _175 => _175[1]]), () => ( DEFAULT_TEXT_COLOR)),
21056
+ h2: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _176 => _176.headingColors, 'optionalAccess', _177 => _177[2]]), () => ( DEFAULT_TEXT_COLOR)),
21057
+ h3: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _178 => _178.headingColors, 'optionalAccess', _179 => _179[3]]), () => ( DEFAULT_TEXT_COLOR)),
21058
+ 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)),
21059
+ body: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _184 => _184.bodyColor]), () => ( DEFAULT_TEXT_COLOR)),
21060
+ quote: _nullishCoalesce(_optionalChain([theme, 'optionalAccess', _185 => _185.quoteColor]), () => ( DEFAULT_TEXT_COLOR)),
21061
+ /** quoteColor가 명시되었는지 — blockquote charPr 분기에 사용 (baseline 호환) */
21062
+ hasQuoteOption: _optionalChain([theme, 'optionalAccess', _186 => _186.quoteColor]) !== void 0,
21063
+ tableHeader: _nullishCoalesce(_nullishCoalesce(_optionalChain([theme, 'optionalAccess', _187 => _187.tableHeaderColor]), () => ( _optionalChain([theme, 'optionalAccess', _188 => _188.bodyColor]))), () => ( DEFAULT_TEXT_COLOR)),
21064
+ tableHeaderBold: !!_optionalChain([theme, 'optionalAccess', _189 => _189.tableHeaderBold])
21065
+ };
21066
+ }
21067
+ async function markdownToHwpx(markdown, options) {
21068
+ const theme = resolveTheme(_optionalChain([options, 'optionalAccess', _190 => _190.theme]));
21069
+ const gongmun = _optionalChain([options, 'optionalAccess', _191 => _191.gongmun]) ? resolveGongmun(options.gongmun) : null;
21070
+ const blocks = parseMarkdownToBlocks(markdown);
21071
+ const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
21072
+ const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
21073
+ const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit);
21074
+ const zip = new (0, _jszip2.default)();
21075
+ zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
21076
+ zip.file("META-INF/container.xml", generateContainerXml());
21077
+ zip.file("Contents/content.hpf", generateManifest());
21078
+ zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, _nullishCoalesce(_optionalChain([fit, 'optionalAccess', _192 => _192.variants]), () => ( []))));
21079
+ zip.file("Contents/section0.xml", sectionXml);
21080
+ zip.file("Preview/PrvText.txt", buildPrvText(blocks));
21081
+ return await zip.generateAsync({ type: "arraybuffer" });
21082
+ }
21083
+ function buildPrvText(blocks) {
21084
+ const lines = [];
21085
+ let bytes = 0;
21086
+ for (const b of blocks) {
21087
+ let text = b.text || (b.rows ? b.rows.map((r) => r.join(" ")).join("\n") : "");
21088
+ if (b.type === "html_table") text = text.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
21089
+ if (!text) continue;
21090
+ lines.push(text);
21091
+ bytes += text.length * 3;
21092
+ if (bytes > 1024) break;
21093
+ }
21094
+ return lines.join("\n").slice(0, 1024);
21095
+ }
21096
+ function parseMarkdownToBlocks(md2) {
21097
+ const lines = md2.split("\n");
21098
+ const blocks = [];
21099
+ let i = 0;
21100
+ while (i < lines.length) {
21101
+ const line = lines[i];
21102
+ if (!line.trim()) {
21103
+ i++;
21104
+ continue;
21105
+ }
21106
+ const fenceMatch = line.match(/^(`{3,}|~{3,})(.*)$/);
21107
+ if (fenceMatch) {
21108
+ const fence = fenceMatch[1];
21109
+ const lang = fenceMatch[2].trim();
21110
+ const codeLines = [];
21111
+ i++;
21112
+ while (i < lines.length && !lines[i].startsWith(fence)) {
21113
+ codeLines.push(lines[i]);
21114
+ i++;
21115
+ }
21116
+ if (i < lines.length) i++;
21117
+ blocks.push({ type: "code_block", text: codeLines.join("\n"), lang });
21118
+ continue;
21119
+ }
21120
+ if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line.trim())) {
21121
+ blocks.push({ type: "hr" });
21122
+ i++;
21123
+ continue;
21124
+ }
21125
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
21126
+ if (headingMatch) {
21127
+ blocks.push({ type: "heading", text: headingMatch[2].trim(), level: headingMatch[1].length });
21128
+ i++;
21129
+ continue;
21130
+ }
21131
+ if (/^<table[\s>]/i.test(line.trimStart())) {
21132
+ const htmlLines = [];
21133
+ let depth = 0;
21134
+ while (i < lines.length) {
21135
+ const l = lines[i];
21136
+ htmlLines.push(l);
21137
+ depth += (_nullishCoalesce(l.match(/<table[\s>]/gi), () => ( []))).length;
21138
+ depth -= (_nullishCoalesce(l.match(/<\/table>/gi), () => ( []))).length;
21139
+ i++;
21140
+ if (depth <= 0) break;
21141
+ }
21142
+ blocks.push({ type: "html_table", text: htmlLines.join("\n") });
21143
+ continue;
21144
+ }
21145
+ if (line.trimStart().startsWith("|")) {
20258
21146
  const tableRows = [];
20259
21147
  while (i < lines.length && lines[i].trimStart().startsWith("|")) {
20260
21148
  const row = lines[i];
@@ -20335,18 +21223,19 @@ function spanToCharPrId(span) {
20335
21223
  function escapeXml(text) {
20336
21224
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
20337
21225
  }
20338
- function generateRuns(text, defaultCharPr = CHAR_NORMAL) {
21226
+ function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
20339
21227
  const spans = parseInlineMarkdown(text);
20340
21228
  return spans.map((span) => {
20341
- const charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
21229
+ let charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
21230
+ if (mapCharId) charId = mapCharId(charId);
20342
21231
  return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
20343
21232
  }).join("");
20344
21233
  }
20345
- function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL) {
21234
+ function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId) {
20346
21235
  if (paraPrId === PARA_CODE) {
20347
21236
  return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
20348
21237
  }
20349
- const runs = generateRuns(text, charPrId);
21238
+ const runs = generateRuns(text, charPrId, mapCharId);
20350
21239
  return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0">${runs}</hp:p>`;
20351
21240
  }
20352
21241
  function headingParaPrId(level) {
@@ -20386,7 +21275,7 @@ function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_C
20386
21275
  const boldAttr = bold ? ` bold="1"` : "";
20387
21276
  const italicAttr = italic ? ` italic="1"` : "";
20388
21277
  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}>
21278
+ return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
20390
21279
  <hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
20391
21280
  <hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
20392
21281
  <hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
@@ -20405,13 +21294,58 @@ function paraPr(id, opts = {}) {
20405
21294
  <hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
20406
21295
  <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
21296
  <hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
20408
- <hh:border borderFillIDRef="0" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0"/>
21297
+ <hh:border borderFillIDRef="1" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0"/>
20409
21298
  </hh:paraPr>`;
20410
21299
  }
20411
21300
  var GONGMUN_LIST_BASE = 8;
20412
21301
  var GONGMUN_LIST_LEVELS = 8;
20413
21302
  var GONGMUN_CENTER = GONGMUN_LIST_BASE + GONGMUN_LIST_LEVELS;
20414
- function buildCharProperties(theme, gongmun) {
21303
+ var CHAR_VARIANT_BASE = 11;
21304
+ var GONGMUN_BODY_RATIO = 95;
21305
+ function plainRenderText(text) {
21306
+ return parseInlineMarkdown(text).map((s) => s.text).join("");
21307
+ }
21308
+ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
21309
+ const minRatio = gongmun.autoFitMinRatio;
21310
+ if (minRatio === null || minRatio >= GONGMUN_BODY_RATIO) return null;
21311
+ const pageW = 59528 - mmToHwpunit(gongmun.margins.left) - mmToHwpunit(gongmun.margins.right);
21312
+ const ratioByBlock = /* @__PURE__ */ new Map();
21313
+ const variants = [];
21314
+ for (let i = 0; i < blocks.length; i++) {
21315
+ const block = blocks[i];
21316
+ let text;
21317
+ let firstW;
21318
+ let contW;
21319
+ if (block.type === "list_item" && gongmunList.has(i)) {
21320
+ const { marker, depth } = gongmunList.get(i);
21321
+ const content = plainRenderText(block.text || "");
21322
+ text = marker ? `${marker} ${content}` : content;
21323
+ const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
21324
+ firstW = pageW - left - Math.max(indent, 0);
21325
+ contW = pageW - left - Math.max(-indent, 0);
21326
+ } else if (block.type === "paragraph") {
21327
+ const raw = (block.text || "").trim();
21328
+ if (/^<center>[\s\S]*<\/center>$/i.test(raw)) continue;
21329
+ text = plainRenderText(raw);
21330
+ firstW = contW = pageW;
21331
+ } else {
21332
+ continue;
21333
+ }
21334
+ if (!text) continue;
21335
+ const r = fitRatioForFewerLines(text, firstW, contW, gongmun.bodyHeight, GONGMUN_BODY_RATIO, minRatio);
21336
+ if (r === null) continue;
21337
+ ratioByBlock.set(i, r);
21338
+ if (!variants.includes(r)) variants.push(r);
21339
+ }
21340
+ return ratioByBlock.size > 0 ? { ratioByBlock, variants } : null;
21341
+ }
21342
+ function variantMapper(fit, blockIdx) {
21343
+ const r = fit.ratioByBlock.get(blockIdx);
21344
+ if (r === void 0) return void 0;
21345
+ const vi = fit.variants.indexOf(r);
21346
+ return (id) => id >= 0 && id <= 3 ? CHAR_VARIANT_BASE + vi * 4 + id : id;
21347
+ }
21348
+ function buildCharProperties(theme, gongmun, ratioVariants = []) {
20415
21349
  let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
20416
21350
  if (gongmun) {
20417
21351
  body = gongmun.bodyHeight;
@@ -20421,7 +21355,7 @@ function buildCharProperties(theme, gongmun) {
20421
21355
  h3 = body;
20422
21356
  h4 = Math.max(body - 100, 1300);
20423
21357
  }
20424
- const bodyRatio = gongmun ? 95 : 100;
21358
+ const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
20425
21359
  const rows = [
20426
21360
  charPr(0, body, false, false, 0, theme.body, bodyRatio),
20427
21361
  charPr(1, body, true, false, 0, theme.body, bodyRatio),
@@ -20435,6 +21369,14 @@ function buildCharProperties(theme, gongmun) {
20435
21369
  charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, 0, theme.tableHeader),
20436
21370
  charPr(CHAR_QUOTE, body, false, true, 0, theme.quote)
20437
21371
  ];
21372
+ for (const r of ratioVariants) {
21373
+ rows.push(
21374
+ charPr(rows.length, body, false, false, 0, theme.body, r),
21375
+ charPr(rows.length + 1, body, true, false, 0, theme.body, r),
21376
+ charPr(rows.length + 2, body, false, true, 0, theme.body, r),
21377
+ charPr(rows.length + 3, body, true, true, 0, theme.body, r)
21378
+ );
21379
+ }
20438
21380
  return `<hh:charProperties itemCnt="${rows.length}">
20439
21381
  ${rows.join("\n")}
20440
21382
  </hh:charProperties>`;
@@ -20477,9 +21419,9 @@ ${base2.join("\n")}
20477
21419
  ${base.join("\n")}
20478
21420
  </hh:paraProperties>`;
20479
21421
  }
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);
21422
+ function generateHeaderXml(theme, gongmun, ratioVariants = []) {
21423
+ const bodyFace = _optionalChain([gongmun, 'optionalAccess', _193 => _193.bodyFont]) === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5";
21424
+ const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants);
20483
21425
  const paraPropsXml = buildParaProperties(gongmun);
20484
21426
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
20485
21427
  <hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" xmlns:hc="${NS_CORE}" version="1.4" secCnt="1">
@@ -20535,25 +21477,21 @@ function generateHeaderXml(theme, gongmun) {
20535
21477
  </hh:fontface>
20536
21478
  </hh:fontfaces>
20537
21479
  <hh:borderFills itemCnt="2">
20538
- <hh:borderFill id="0" threeD="0" shadow="0" centerLine="0" breakCellSeparateLine="0">
21480
+ <hh:borderFill id="1" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
20539
21481
  <hh:slash type="NONE" Crooked="0" isCounter="0"/>
20540
21482
  <hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
20541
21483
  <hh:leftBorder type="NONE" width="0.1 mm" color="#000000"/>
20542
21484
  <hh:rightBorder type="NONE" width="0.1 mm" color="#000000"/>
20543
21485
  <hh:topBorder type="NONE" width="0.1 mm" color="#000000"/>
20544
21486
  <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
21487
  </hh:borderFill>
20548
- <hh:borderFill id="1" threeD="0" shadow="0" centerLine="0" breakCellSeparateLine="0">
21488
+ <hh:borderFill id="2" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
20549
21489
  <hh:slash type="NONE" Crooked="0" isCounter="0"/>
20550
21490
  <hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
20551
21491
  <hh:leftBorder type="SOLID" width="0.12 mm" color="#000000"/>
20552
21492
  <hh:rightBorder type="SOLID" width="0.12 mm" color="#000000"/>
20553
21493
  <hh:topBorder type="SOLID" width="0.12 mm" color="#000000"/>
20554
21494
  <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
21495
  </hh:borderFill>
20558
21496
  </hh:borderFills>
20559
21497
  ${charPropsXml}
@@ -20600,14 +21538,74 @@ function generateTable(rows, theme) {
20600
21538
  const tdElements = cells.map((cell, colIdx) => {
20601
21539
  const runs = generateRuns(cell, headerCharPr);
20602
21540
  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>`;
21541
+ 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
21542
  }).join("");
20605
21543
  return `<hp:tr>${tdElements}</hp:tr>`;
20606
21544
  }).join("");
20607
21545
  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>`;
21546
+ 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
21547
  return `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${tbl}</hp:run></hp:p>`;
20610
21548
  }
21549
+ function layoutHtmlRows(rows) {
21550
+ const occupied = /* @__PURE__ */ new Set();
21551
+ const placed = [];
21552
+ let colCnt = 0;
21553
+ for (let r = 0; r < rows.length; r++) {
21554
+ let c = 0;
21555
+ for (const cell of rows[r].cells) {
21556
+ while (occupied.has(`${r},${c}`)) c++;
21557
+ const colSpan = Math.max(1, cell.colSpan);
21558
+ const rowSpan = Math.max(1, cell.rowSpan);
21559
+ placed.push({ r, c, colSpan, rowSpan, inner: cell.inner, isHeader: rows[r].tag === "th" });
21560
+ for (let dr = 0; dr < rowSpan; dr++) {
21561
+ for (let dc = 0; dc < colSpan; dc++) occupied.add(`${r + dr},${c + dc}`);
21562
+ }
21563
+ c += colSpan;
21564
+ colCnt = Math.max(colCnt, c);
21565
+ }
21566
+ }
21567
+ return { placed, rowCnt: rows.length, colCnt };
21568
+ }
21569
+ function unescapeHtml(s) {
21570
+ return s.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&");
21571
+ }
21572
+ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3) {
21573
+ const rows = parseHtmlTable(rawHtml);
21574
+ if (!rows || rows.length === 0) return null;
21575
+ const { placed, rowCnt, colCnt } = layoutHtmlRows(rows);
21576
+ if (rowCnt === 0 || colCnt === 0) return null;
21577
+ const colW = Math.floor(totalWidth / colCnt);
21578
+ const cellH = 1500;
21579
+ const tblW = colW * colCnt;
21580
+ const tblId = nextTableId();
21581
+ const useHeaderStyle = theme.tableHeader !== theme.body || theme.tableHeaderBold;
21582
+ const tcXmls = placed.map((cell) => {
21583
+ const headerCharPr = cell.isHeader && useHeaderStyle ? CHAR_TABLE_HEADER : CHAR_NORMAL;
21584
+ const { lines } = htmlCellInnerToLines(cell.inner);
21585
+ const paras = lines.map(
21586
+ (line) => `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="${headerCharPr}"><hp:t>${escapeXml(unescapeHtml(line))}</hp:t></hp:run></hp:p>`
21587
+ );
21588
+ let nestedH = 0;
21589
+ for (const nested of extractTopLevelTables(cell.inner)) {
21590
+ const nestedXml = generateHtmlTableXml(nested, theme, Math.max(colW * cell.colSpan - 1020, 4e3));
21591
+ if (nestedXml) {
21592
+ paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${nestedXml}</hp:run></hp:p>`);
21593
+ nestedH += (_nullishCoalesce(nested.match(/<tr[\s>]/gi), () => ( []))).length * cellH + 300;
21594
+ }
21595
+ }
21596
+ if (paras.length === 0) {
21597
+ paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="${headerCharPr}"><hp:t></hp:t></hp:run></hp:p>`);
21598
+ }
21599
+ const cellHeight = Math.max(cellH * cell.rowSpan, Math.max(lines.length, 1) * 800 + nestedH);
21600
+ 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>`;
21601
+ });
21602
+ const trXmls = [];
21603
+ for (let r = 0; r < rowCnt; r++) {
21604
+ const rowTcs = tcXmls.filter((_, i) => placed[i].r === r);
21605
+ trXmls.push(`<hp:tr>${rowTcs.join("")}</hp:tr>`);
21606
+ }
21607
+ 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>`;
21608
+ }
20611
21609
  function precomputeGongmunList(blocks, gongmun) {
20612
21610
  const result = /* @__PURE__ */ new Map();
20613
21611
  let i = 0;
@@ -20617,9 +21615,22 @@ function precomputeGongmunList(blocks, gongmun) {
20617
21615
  continue;
20618
21616
  }
20619
21617
  const run = [];
20620
- while (i < blocks.length && blocks[i].type === "list_item") {
20621
- run.push(i);
20622
- i++;
21618
+ while (i < blocks.length) {
21619
+ const t = blocks[i].type;
21620
+ if (t === "list_item") {
21621
+ run.push(i);
21622
+ i++;
21623
+ continue;
21624
+ }
21625
+ if (t === "table" || t === "html_table") {
21626
+ let j = i + 1;
21627
+ while (j < blocks.length && (blocks[j].type === "table" || blocks[j].type === "html_table")) j++;
21628
+ if (j < blocks.length && blocks[j].type === "list_item") {
21629
+ i = j;
21630
+ continue;
21631
+ }
21632
+ }
21633
+ break;
20623
21634
  }
20624
21635
  const depths = run.map((bi) => Math.min(Math.max(blocks[bi].indent || 0, 0), GONGMUN_LIST_LEVELS - 1));
20625
21636
  const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
@@ -20631,12 +21642,11 @@ function precomputeGongmunList(blocks, gongmun) {
20631
21642
  }
20632
21643
  return result;
20633
21644
  }
20634
- function blocksToSectionXml(blocks, theme, gongmun) {
21645
+ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null) {
20635
21646
  const paraXmls = [];
20636
21647
  let isFirst = true;
20637
21648
  const orderedCounters = {};
20638
21649
  let prevWasOrdered = false;
20639
- const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
20640
21650
  for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
20641
21651
  const block = blocks[blockIdx];
20642
21652
  let xml = "";
@@ -20658,7 +21668,7 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20658
21668
  if (ctr) {
20659
21669
  xml = generateParagraph(ctr[1].trim(), GONGMUN_CENTER);
20660
21670
  } else {
20661
- xml = generateParagraph(block.text || "");
21671
+ xml = generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx) : void 0);
20662
21672
  }
20663
21673
  break;
20664
21674
  }
@@ -20677,12 +21687,12 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20677
21687
  case "list_item": {
20678
21688
  if (gongmun && gongmunList) {
20679
21689
  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]), () => ( ""));
21690
+ const depth = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _194 => _194.depth]), () => ( 0));
21691
+ const marker2 = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _195 => _195.marker]), () => ( ""));
20682
21692
  const content = block.text || "";
20683
21693
  const text = marker2 ? `${marker2} ${content}` : content;
20684
21694
  const listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
20685
- xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr);
21695
+ xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr, fit ? variantMapper(fit, blockIdx) : void 0);
20686
21696
  break;
20687
21697
  }
20688
21698
  const indent = block.indent || 0;
@@ -20718,6 +21728,21 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20718
21728
  xml = generateTable(block.rows, theme);
20719
21729
  }
20720
21730
  break;
21731
+ case "html_table": {
21732
+ const tbl = generateHtmlTableXml(block.text || "", theme);
21733
+ if (tbl) {
21734
+ if (isFirst) {
21735
+ const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
21736
+ paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
21737
+ isFirst = false;
21738
+ }
21739
+ xml = `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${tbl}</hp:run></hp:p>`;
21740
+ } else {
21741
+ const plain = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
21742
+ xml = plain ? generateParagraph(plain) : "";
21743
+ }
21744
+ break;
21745
+ }
20721
21746
  }
20722
21747
  if (!xml) continue;
20723
21748
  if (isFirst && block.type !== "table") {
@@ -20738,49 +21763,6 @@ function blocksToSectionXml(blocks, theme, gongmun) {
20738
21763
  </hs:sec>`;
20739
21764
  }
20740
21765
 
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
21766
  // src/diff/compare.ts
20785
21767
  var SIMILARITY_THRESHOLD = 0.4;
20786
21768
  async function compare(bufferA, bufferB, options) {
@@ -20918,300 +21900,231 @@ function diffTableCells(a, b) {
20918
21900
  // src/roundtrip/patcher.ts
20919
21901
 
20920
21902
 
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
- }
21903
+ // src/roundtrip/table-rows.ts
21904
+ var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
21905
+ var TAG_AT_RE = /<[A-Za-z0-9_:]+(?:"[^"]*"|'[^']*'|[^>"'])*>/y;
21906
+ function patchTableRows(input) {
21907
+ const { table, scanTable, ctx, skip, origKeys, editedKeys } = input;
21908
+ const xml = _optionalChain([ctx, 'access', _196 => _196.scans, 'access', _197 => _197[scanTable.sectionIndex], 'optionalAccess', _198 => _198.xml]);
21909
+ if (!xml) return skip("\uC139\uC158 XML \uB9E4\uD551 \uC2E4\uD328");
21910
+ const numRows = table.rows;
21911
+ if (origKeys.length !== numRows) return skip("\uD45C \uD589 \uC88C\uD45C \uBD88\uC77C\uCE58 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21912
+ if (scanTable.rows.length !== numRows || scanTable.rowRanges.length !== numRows) {
21913
+ 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");
20986
21914
  }
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
21915
  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;
21916
+ if (scanTable.rows[r].some((c) => c.rowAddr !== r)) {
21917
+ return skip("\uD589 \uC8FC\uC18C \uBE44\uC5F0\uC18D \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21041
21918
  }
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
21919
  }
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>`);
21920
+ const allCells = scanTable.rows.flat();
21921
+ const explicitAddr = (c) => !!c.addrTagRange && /\browAddr\s*=\s*"/.test(xml.slice(c.addrTagRange.start, c.addrTagRange.end));
21922
+ const explicitCount = allCells.filter(explicitAddr).length;
21923
+ if (explicitCount !== 0 && explicitCount !== allCells.length) {
21924
+ return skip("\uC140 \uC8FC\uC18C(cellAddr) \uD45C\uAE30 \uD63C\uC7AC \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21089
21925
  }
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
- });
21926
+ const hasExplicitAddr = explicitCount > 0;
21927
+ const pairs = alignUnits(origKeys, editedKeys);
21928
+ const seq = [];
21929
+ let lastOrig = -1;
21930
+ for (const [oi, ei] of pairs) {
21931
+ if (oi !== null && ei !== null) {
21932
+ seq.push({ kind: "keep", oi, ei });
21933
+ lastOrig = oi;
21934
+ } else if (oi !== null) {
21935
+ seq.push({ kind: "del", oi });
21936
+ lastOrig = oi;
21937
+ } else if (ei !== null) seq.push({ kind: "ins", ei, insertAt: lastOrig + 1 });
21938
+ }
21939
+ const dels = seq.filter((e) => e.kind === "del");
21940
+ const inss = seq.filter((e) => e.kind === "ins");
21941
+ const keeps = seq.filter((e) => e.kind === "keep");
21942
+ if (dels.length === 0 && inss.length === 0) {
21943
+ return skip("\uD45C \uD589 \uC815\uB82C \uC2E4\uD328 \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
21944
+ }
21945
+ if (keeps.length + inss.length === 0) return skip("\uBAA8\uB4E0 \uD589 \uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0");
21946
+ if (keeps.length === 0) return skip("\uD589 \uC804\uBA74 \uAD50\uCCB4 \u2014 \uC11C\uC2DD \uAE30\uC900 \uD589\uC774 \uC5C6\uC5B4 \uBBF8\uC9C0\uC6D0");
21947
+ const spans = allCells.filter((c) => (_nullishCoalesce(c.rowSpan, () => ( 1))) > 1);
21948
+ for (const d of dels) {
21949
+ if (spans.some((s) => s.rowAddr <= d.oi && s.rowAddr + s.rowSpan > d.oi)) {
21950
+ return skip(`\uD45C ${d.oi + 1}\uD589 \uC0AD\uC81C\uAC00 \uC138\uB85C \uBCD1\uD569\uACFC \uACB9\uCE68 \u2014 \uBBF8\uC9C0\uC6D0`);
21951
+ }
21952
+ }
21953
+ for (const ins of inss) {
21954
+ const p = ins.insertAt;
21955
+ if (spans.some((s) => s.rowAddr < p && s.rowAddr + s.rowSpan > p)) {
21956
+ return skip("\uD589 \uC0BD\uC785 \uC704\uCE58\uAC00 \uC138\uB85C \uBCD1\uD569 \uB0B4\uBD80 \u2014 \uBBF8\uC9C0\uC6D0");
21957
+ }
21958
+ }
21959
+ for (const d of dels) {
21960
+ const rr = scanTable.rowRanges[d.oi];
21961
+ if (ROW_OBJECT_RE.test(xml.slice(rr.start, rr.end))) {
21962
+ 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`);
21963
+ }
21964
+ }
21965
+ const keptSet = new Set(keeps.map((k) => k.oi));
21966
+ const insertPlans = [];
21967
+ for (const ins of inss) {
21968
+ const p = ins.insertAt;
21969
+ const kept = [...keptSet].sort((a, b) => a - b);
21970
+ let template = -1;
21971
+ for (const k of kept) {
21972
+ if (k < p) template = k;
21973
+ }
21974
+ if (template <= 0 && p >= 1) {
21975
+ const following = kept.find((k) => k >= 1);
21976
+ if (following !== void 0) template = following;
21977
+ }
21978
+ if (template < 0) template = kept[0];
21979
+ const cells = input.editedCells(ins.ei);
21980
+ if (!cells) return skip("\uC0BD\uC785 \uD589\uC5D0 \uC774\uBBF8\uC9C0/\uC911\uCCA9\uD45C \uD3EC\uD568 \u2014 \uD589 \uCD94\uAC00 \uBBF8\uC9C0\uC6D0");
21981
+ for (const cell of cells) {
21982
+ const unstable = cell.lines.find((l) => sanitizeText(l) !== l);
21983
+ 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");
21984
+ }
21985
+ const tmplCells = scanTable.rows[template];
21986
+ const rr = scanTable.rowRanges[template];
21987
+ if (ROW_OBJECT_RE.test(xml.slice(rr.start, rr.end))) {
21988
+ 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");
21989
+ }
21990
+ 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");
21991
+ const tmplWidth = tmplCells.reduce((s, c) => s + c.colSpan, 0);
21992
+ 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");
21993
+ if (cells.length !== tmplCells.length) {
21994
+ return skip(`\uC0BD\uC785 \uD589 \uC140 \uC218(${cells.length}) \u2260 \uAE30\uC900 \uD589 \uC140 \uC218(${tmplCells.length}) \u2014 \uBBF8\uC9C0\uC6D0`);
21995
+ }
21996
+ for (let i = 0; i < cells.length; i++) {
21997
+ if (cells[i].rowSpan !== 1 || cells[i].colSpan !== tmplCells[i].colSpan) {
21998
+ return skip("\uC0BD\uC785 \uD589 \uBCD1\uD569 \uAD6C\uC870\uAC00 \uAE30\uC900 \uD589\uACFC \uB2E4\uB984 \u2014 \uBBF8\uC9C0\uC6D0");
21999
+ }
21117
22000
  }
21118
- if (rowCells.length) result.push({ tag, cells: rowCells });
22001
+ insertPlans.push({ entry: ins, template, cells });
21119
22002
  }
21120
- return result;
21121
- }
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;
22003
+ const net = inss.length - dels.length;
22004
+ TAG_AT_RE.lastIndex = scanTable.start;
22005
+ const tblOpen = TAG_AT_RE.exec(xml);
22006
+ if (!tblOpen || tblOpen.index !== scanTable.start) return skip("\uD45C \uC5EC\uB294 \uD0DC\uADF8 \uD574\uC11D \uC2E4\uD328");
22007
+ const rowCntM = tblOpen[0].match(/\browCnt\s*=\s*"(\d+)"/);
22008
+ if (!rowCntM || rowCntM.index === void 0) return skip("\uD45C rowCnt \uC18D\uC131 \uC5C6\uC74C \u2014 \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
22009
+ 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");
22010
+ const finalIndex = /* @__PURE__ */ new Map();
22011
+ {
22012
+ let fi = 0;
22013
+ for (const e of seq) {
22014
+ if (e.kind !== "del") finalIndex.set(e, fi++);
21138
22015
  }
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;
21145
- }
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;
22016
+ }
22017
+ const splices = [];
22018
+ let applied = 0;
22019
+ for (const d of dels) {
22020
+ const rr = scanTable.rowRanges[d.oi];
22021
+ splices.push({ start: rr.start, end: rr.end, replacement: "" });
22022
+ applied++;
22023
+ }
22024
+ const fragmentsByAnchor = /* @__PURE__ */ new Map();
22025
+ let heightDelta = 0;
22026
+ for (const plan of insertPlans) {
22027
+ const finalRow = finalIndex.get(plan.entry);
22028
+ const fragment = buildRowFragment(xml, scanTable, plan.template, plan.cells, finalRow, hasExplicitAddr, ctx);
22029
+ if (fragment === null) return skip("\uD589 \uBCF5\uC81C \uC2E4\uD328 (\uC140 \uBB38\uB2E8 \uAD6C\uC870 \uBBF8\uC9C0\uC6D0)");
22030
+ const p = plan.entry.insertAt;
22031
+ const anchor = p === 0 ? scanTable.rowRanges[0].start : scanTable.rowRanges[p - 1].end;
22032
+ let list = fragmentsByAnchor.get(anchor);
22033
+ if (!list) fragmentsByAnchor.set(anchor, list = []);
22034
+ list.push(fragment);
22035
+ heightDelta += rowHeightOf(fragment);
22036
+ applied++;
22037
+ }
22038
+ for (const [anchor, fragments] of fragmentsByAnchor) {
22039
+ splices.push({ start: anchor, end: anchor, replacement: fragments.join("") });
22040
+ }
22041
+ for (const d of dels) {
22042
+ const rr = scanTable.rowRanges[d.oi];
22043
+ heightDelta -= rowHeightOf(xml.slice(rr.start, rr.end));
22044
+ }
22045
+ if (hasExplicitAddr) {
22046
+ for (const k of keeps) {
22047
+ const fi = finalIndex.get(k);
22048
+ if (fi === k.oi) continue;
22049
+ for (const cell of scanTable.rows[k.oi]) {
22050
+ const sp = rowAddrRewrite(xml, cell, fi);
22051
+ if (sp) splices.push(sp);
21156
22052
  }
21157
22053
  }
21158
22054
  }
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);
22055
+ {
22056
+ const valStart = scanTable.start + rowCntM.index + rowCntM[0].indexOf('"') + 1;
22057
+ splices.push({ start: valStart, end: valStart + rowCntM[1].length, replacement: String(numRows + net) });
21168
22058
  }
21169
- if (/<img\s/i.test(work)) {
21170
- hadNonText = true;
21171
- work = work.replace(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi, "");
22059
+ if (heightDelta !== 0) {
22060
+ const sp = tableSzHeightSplice(xml, scanTable, tblOpen[0].length, heightDelta);
22061
+ if (sp) splices.push(sp);
21172
22062
  }
21173
- const lines = work.split(/<br\s*\/?>/gi).map((s) => s.trim()).filter((s) => s.length > 0);
21174
- return { lines, hadNonText };
22063
+ ctx.sectionSplices[scanTable.sectionIndex].push(...splices);
22064
+ for (const k of keeps) {
22065
+ if (origKeys[k.oi] !== editedKeys[k.ei]) applied += input.patchMatched(k.oi, k.ei);
22066
+ }
22067
+ return applied;
21175
22068
  }
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;
22069
+ var FRAG_OPEN = "<hp:tbl>";
22070
+ var FRAG_CLOSE = "</hp:tbl>";
22071
+ function buildRowFragment(xml, scanTable, template, cells, finalRow, hasExplicitAddr, ctx) {
22072
+ const rr = scanTable.rowRanges[template];
22073
+ const wrapped = FRAG_OPEN + xml.slice(rr.start, rr.end) + FRAG_CLOSE;
22074
+ const scan = scanSectionXml(wrapped, 0);
22075
+ const row = _optionalChain([scan, 'access', _199 => _199.tables, 'access', _200 => _200[0], 'optionalAccess', _201 => _201.rows, 'access', _202 => _202[0]]);
22076
+ if (!row || row.length !== cells.length) return null;
22077
+ const splices = allLinesegRemovalSplices(wrapped);
22078
+ for (let i = 0; i < cells.length; i++) {
22079
+ const paras = row[i].paragraphs;
22080
+ let lines = cells[i].lines;
22081
+ if (lines.length > 0 && paras.length === 0) return null;
22082
+ if (lines.length > paras.length) {
22083
+ lines = [...lines.slice(0, paras.length - 1), lines.slice(paras.length - 1).join(" ")];
22084
+ 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 });
22085
+ }
22086
+ for (let p = 0; p < paras.length; p++) {
22087
+ const sp = buildParagraphSplices(paras[p], _nullishCoalesce(lines[p], () => ( "")), wrapped);
22088
+ if (sp === null) return null;
22089
+ splices.push(...sp);
22090
+ }
22091
+ if (hasExplicitAddr) {
22092
+ const sp = rowAddrRewrite(wrapped, row[i], finalRow);
22093
+ if (sp) splices.push(sp);
21193
22094
  }
21194
22095
  }
21195
- return result;
22096
+ const patched = applySplices(wrapped, splices);
22097
+ return patched.slice(FRAG_OPEN.length, patched.length - FRAG_CLOSE.length);
21196
22098
  }
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
- }
22099
+ function rowAddrRewrite(xml, cell, newRow) {
22100
+ if (!cell.addrTagRange) return null;
22101
+ const tag = xml.slice(cell.addrTagRange.start, cell.addrTagRange.end);
22102
+ const m = tag.match(/\browAddr\s*=\s*"(\d+)"/);
22103
+ if (!m || m.index === void 0) return null;
22104
+ if (parseInt(m[1], 10) === newRow) return null;
22105
+ const valStart = cell.addrTagRange.start + m.index + m[0].indexOf('"') + 1;
22106
+ return { start: valStart, end: valStart + m[1].length, replacement: String(newRow) };
22107
+ }
22108
+ function rowHeightOf(fragment) {
22109
+ let max = 0;
22110
+ for (const m of fragment.matchAll(/<(?:[A-Za-z0-9_]+:)?cellSz\b(?:"[^"]*"|'[^']*'|[^>"'])*>/g)) {
22111
+ const h = m[0].match(/\bheight\s*=\s*"(\d+)"/);
22112
+ if (h) max = Math.max(max, parseInt(h[1], 10));
21212
22113
  }
21213
- if (depth === 0) result += html.slice(last);
21214
- return result;
22114
+ return max;
22115
+ }
22116
+ function tableSzHeightSplice(xml, scanTable, tblOpenLen, delta) {
22117
+ const from = scanTable.start + tblOpenLen;
22118
+ const to = _nullishCoalesce(_optionalChain([scanTable, 'access', _203 => _203.rowRanges, 'access', _204 => _204[0], 'optionalAccess', _205 => _205.start]), () => ( from));
22119
+ const slice = xml.slice(from, to);
22120
+ const szM = slice.match(/<(?:[A-Za-z0-9_]+:)?sz\b(?:"[^"]*"|'[^']*'|[^>"'])*>/);
22121
+ if (!szM || szM.index === void 0) return null;
22122
+ const hM = szM[0].match(/\bheight\s*=\s*"(\d+)"/);
22123
+ if (!hM || hM.index === void 0) return null;
22124
+ const oldH = parseInt(hM[1], 10);
22125
+ const newH = Math.max(0, oldH + delta);
22126
+ const valStart = from + szM.index + hM.index + hM[0].indexOf('"') + 1;
22127
+ return { start: valStart, end: valStart + hM[1].length, replacement: String(newH) };
21215
22128
  }
21216
22129
 
21217
22130
  // src/roundtrip/table-patch.ts
@@ -21223,37 +22136,89 @@ function patchGfmTable(table, scanTable, orig, edited, ctx, skip) {
21223
22136
  if (replica.length !== origRows.length || replica.some((row, r) => row.length !== origRows[r].length || row.some((c, j) => c.text !== origRows[r][j]))) {
21224
22137
  return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
21225
22138
  }
21226
- if (editedRows.length !== origRows.length) return skip("\uD45C \uD589 \uCD94\uAC00/\uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0 (\uD45C \uAD6C\uC870 \uBCC0\uACBD)");
22139
+ if (editedRows.length !== origRows.length) {
22140
+ return patchGfmTableRows(table, scanTable, origRows, editedRows, replica, ctx, skip);
22141
+ }
21227
22142
  let applied = 0;
21228
22143
  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`);
22144
+ applied += patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, r, ctx, skip);
22145
+ }
22146
+ return applied;
22147
+ }
22148
+ function patchGfmRowPair(table, scanTable, origRows, editedRows, replica, r, er, ctx, skip) {
22149
+ if (editedRows[er].length !== origRows[r].length) {
22150
+ skip(`\uD45C ${r + 1}\uD589 \uC5F4 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
22151
+ return 0;
22152
+ }
22153
+ let applied = 0;
22154
+ for (let c = 0; c < origRows[r].length; c++) {
22155
+ if (origRows[r][c] === editedRows[er][c]) continue;
22156
+ const { gridR, gridC } = replica[r][c];
22157
+ const origTokens = extractCellTokens(origRows[r][c]);
22158
+ const editedTokens = extractCellTokens(editedRows[er][c]);
22159
+ if (origTokens !== editedTokens) {
22160
+ skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
21231
22161
  continue;
21232
22162
  }
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;
22163
+ const newLines = unescapeGfmCell(stripCellTokens(editedRows[er][c])).split("\n").map((s) => s.trim()).filter(Boolean);
22164
+ const origLines = unescapeGfmCell(stripCellTokens(origRows[r][c])).split("\n").map((s) => s.trim()).filter(Boolean);
22165
+ const n = applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, origRows[r][c], editedRows[er][c], origLines.length);
22166
+ if (n > 0 && origTokens) {
22167
+ ctx.skipped.push({
22168
+ 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)",
22169
+ before: summarize(origRows[r][c]),
22170
+ after: summarize(editedRows[er][c]),
22171
+ partial: true
22172
+ });
21253
22173
  }
22174
+ applied += n;
21254
22175
  }
21255
22176
  return applied;
21256
22177
  }
22178
+ function patchGfmTableRows(table, scanTable, origRows, editedRows, replica, ctx, skip) {
22179
+ if (replica.length !== table.rows || replica.some((row, r) => row.some((c) => c.gridR !== r))) {
22180
+ 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");
22181
+ }
22182
+ if (table.cells.some((row) => row.some((c) => c && (c.colSpan > 1 || c.rowSpan > 1)))) {
22183
+ return skip("\uBCD1\uD569 \uC140 \uD45C \u2014 GFM \uD589 \uCD94\uAC00/\uC0AD\uC81C \uBBF8\uC9C0\uC6D0");
22184
+ }
22185
+ if (!gfmRenderStable(editedRows, table.cols)) {
22186
+ 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");
22187
+ }
22188
+ const key = (row) => row.join("\0");
22189
+ return patchTableRows({
22190
+ table,
22191
+ scanTable,
22192
+ ctx,
22193
+ skip,
22194
+ origKeys: origRows.map(key),
22195
+ editedKeys: editedRows.map(key),
22196
+ editedCells: (ei) => {
22197
+ const cells = [];
22198
+ for (const cellMd of editedRows[ei]) {
22199
+ if (extractCellTokens(cellMd)) return null;
22200
+ const lines = unescapeGfmCell(cellMd).split("\n").map((s) => s.trim()).filter(Boolean);
22201
+ cells.push({ lines, colSpan: 1, rowSpan: 1 });
22202
+ }
22203
+ return cells;
22204
+ },
22205
+ patchMatched: (oi, ei) => patchGfmRowPair(table, scanTable, origRows, editedRows, replica, oi, ei, ctx, skip)
22206
+ });
22207
+ }
22208
+ function gfmRenderStable(editedRows, cols) {
22209
+ const sim = {
22210
+ rows: editedRows.length,
22211
+ cols,
22212
+ hasHeader: editedRows.length > 1,
22213
+ cells: editedRows.map((row) => {
22214
+ const padded = row.length < cols ? [...row, ...Array(cols - row.length).fill("")] : row;
22215
+ return padded.map((md2) => ({ text: unescapeGfmCell(md2), colSpan: 1, rowSpan: 1 }));
22216
+ })
22217
+ };
22218
+ const replica = replicateGfmTable(sim);
22219
+ if (!replica || replica.length !== editedRows.length) return false;
22220
+ return replica.every((row, r) => row.length === editedRows[r].length && row.every((c, j) => c.text === editedRows[r][j]));
22221
+ }
21257
22222
  function patchHtmlTable(table, scanTable, orig, edited, ctx, skip) {
21258
22223
  return patchHtmlTableRaw(table, scanTable, orig.raw, edited.raw, ctx, skip, 0);
21259
22224
  }
@@ -21267,50 +22232,81 @@ function patchHtmlTableRaw(table, scanTable, origRaw, editedRaw, ctx, skip, dept
21267
22232
  }
21268
22233
  const editedRows = parseHtmlTable(editedRaw);
21269
22234
  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)");
22235
+ if (editedRows.length !== replica.length) {
22236
+ return patchHtmlTableRows(table, scanTable, replica, editedRows, ctx, skip, depth);
22237
+ }
21271
22238
  let applied = 0;
21272
22239
  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`);
22240
+ applied += patchHtmlRowPair(table, scanTable, replica, editedRows, r, r, ctx, skip, depth);
22241
+ }
22242
+ return applied;
22243
+ }
22244
+ function patchHtmlRowPair(table, scanTable, replica, editedRows, r, er, ctx, skip, depth) {
22245
+ if (editedRows[er].cells.length !== replica[r].cells.length) {
22246
+ skip(`\uD45C ${r + 1}\uD589 \uC140 \uC218 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
22247
+ return 0;
22248
+ }
22249
+ let applied = 0;
22250
+ for (let c = 0; c < replica[r].cells.length; c++) {
22251
+ const oc = replica[r].cells[c];
22252
+ const ec = editedRows[er].cells[c];
22253
+ if (oc.colSpan !== ec.colSpan || oc.rowSpan !== ec.rowSpan) {
22254
+ skip(`\uC140 \uBCD1\uD569(colspan/rowspan) \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0`);
21275
22255
  continue;
21276
22256
  }
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`);
22257
+ if (oc.inner === ec.inner) continue;
22258
+ const origContent = htmlCellInnerToLines(oc.inner);
22259
+ const editedContent = htmlCellInnerToLines(ec.inner);
22260
+ if (origContent.hadNonText || editedContent.hadNonText) {
22261
+ if (extractImgTags(oc.inner) !== extractImgTags(ec.inner)) {
22262
+ skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
21282
22263
  continue;
21283
22264
  }
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
- }
22265
+ const origTables = extractTopLevelTables(oc.inner);
22266
+ const editedTables = extractTopLevelTables(ec.inner);
22267
+ if (origTables.length !== editedTables.length) {
22268
+ skip("\uC140 \uB0B4 \uC911\uCCA9\uD45C \uCD94\uAC00/\uC0AD\uC81C\uB294 \uBBF8\uC9C0\uC6D0");
22269
+ continue;
21301
22270
  }
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);
22271
+ if (origTables.join("\n") !== editedTables.join("\n")) {
22272
+ applied += patchNestedTables(table, scanTable, oc, origTables, editedTables, ctx, skip, depth);
21305
22273
  }
21306
22274
  }
22275
+ if (origContent.lines.join("\n") !== editedContent.lines.join("\n")) {
22276
+ const newLines = editedContent.lines.map((l) => unescapeGfm(l));
22277
+ applied += applyCellEdit(table, scanTable, oc.gridR, oc.gridC, newLines, ctx, oc.inner, ec.inner, origContent.lines.length);
22278
+ }
21307
22279
  }
21308
22280
  return applied;
21309
22281
  }
22282
+ function patchHtmlTableRows(table, scanTable, replica, editedRows, ctx, skip, depth) {
22283
+ if (replica.length !== table.rows || replica.some((row, r) => row.cells.some((c) => c.gridR !== r))) {
22284
+ 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");
22285
+ }
22286
+ const key = (row) => row.cells.map((c) => `${c.colSpan}x${c.rowSpan}:${c.inner}`).join("\0");
22287
+ return patchTableRows({
22288
+ table,
22289
+ scanTable,
22290
+ ctx,
22291
+ skip,
22292
+ origKeys: replica.map(key),
22293
+ editedKeys: editedRows.map(key),
22294
+ editedCells: (ei) => {
22295
+ const cells = [];
22296
+ for (const cell of editedRows[ei].cells) {
22297
+ const content = htmlCellInnerToLines(cell.inner);
22298
+ if (content.hadNonText) return null;
22299
+ cells.push({ lines: content.lines.map((l) => unescapeGfm(l)), colSpan: cell.colSpan, rowSpan: cell.rowSpan });
22300
+ }
22301
+ return cells;
22302
+ },
22303
+ patchMatched: (oi, ei) => patchHtmlRowPair(table, scanTable, replica, editedRows, oi, ei, ctx, skip, depth)
22304
+ });
22305
+ }
21310
22306
  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]]);
22307
+ const irCell = _optionalChain([table, 'access', _206 => _206.cells, 'access', _207 => _207[oc.gridR], 'optionalAccess', _208 => _208[oc.gridC]]);
21312
22308
  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);
22309
+ const nestedIRs = (_nullishCoalesce(_optionalChain([irCell, 'optionalAccess', _209 => _209.blocks]), () => ( []))).filter((b) => b.type === "table" && b.table).map((b) => b.table);
21314
22310
  if (!scanCell || nestedIRs.length !== origTables.length || scanCell.tables.length !== origTables.length) {
21315
22311
  return skip("\uC911\uCCA9\uD45C \uC18C\uC2A4\uB9F5 \uB9E4\uD551 \uC2E4\uD328");
21316
22312
  }
@@ -21378,7 +22374,7 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21378
22374
  };
21379
22375
  const cell = scanTable.cellByAnchor.get(`${gridR},${gridC}`);
21380
22376
  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]]);
22377
+ const irCell = _optionalChain([table, 'access', _210 => _210.cells, 'access', _211 => _211[gridR], 'optionalAccess', _212 => _212[gridC]]);
21382
22378
  const scanJoined = cell.paragraphs.map((p) => p.text).filter((t) => normForMatch(t)).join("\n");
21383
22379
  if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
21384
22380
  if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
@@ -21401,12 +22397,12 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21401
22397
  if (newLines.length === 0) return 0;
21402
22398
  const target = cell.paragraphs[0];
21403
22399
  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]));
22400
+ const sp = buildParagraphSplices(target, newLines.join(" "), _optionalChain([ctx, 'access', _213 => _213.scans, 'access', _214 => _214[target.sectionIndex], 'optionalAccess', _215 => _215.xml]));
21405
22401
  if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21406
22402
  splices.push(...sp);
21407
22403
  sectionIndex = target.sectionIndex;
21408
22404
  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) });
22405
+ 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
22406
  }
21411
22407
  } else {
21412
22408
  const assigned = [];
@@ -21418,11 +22414,13 @@ function applyCellEdit(table, scanTable, gridR, gridC, newLines, ctx, before, af
21418
22414
  }
21419
22415
  }
21420
22416
  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) });
22417
+ 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 });
22418
+ } else if (newLines.length < nonEmpty.length && nonEmpty.length > 1) {
22419
+ 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
22420
  }
21423
22421
  for (let i = 0; i < nonEmpty.length; i++) {
21424
22422
  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]));
22423
+ const sp = buildParagraphSplices(nonEmpty[i], assigned[i], _optionalChain([ctx, 'access', _216 => _216.scans, 'access', _217 => _217[nonEmpty[i].sectionIndex], 'optionalAccess', _218 => _218.xml]));
21426
22424
  if (sp === null) return skip("\uC140 \uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21427
22425
  splices.push(...sp);
21428
22426
  sectionIndex = nonEmpty[i].sectionIndex;
@@ -21503,7 +22501,7 @@ async function resolveSectionEntryNames(zip) {
21503
22501
  const paths = sectionPathsFromManifest(xml).filter((p) => zip.file(p) !== null);
21504
22502
  if (paths.length > 0) return paths;
21505
22503
  }
21506
- return Object.keys(zip.files).filter((n) => /[Ss]ection\d+\.xml$/.test(n)).sort(_chunkXZTDYOZVcjs.compareSectionPaths);
22504
+ return Object.keys(zip.files).filter((n) => /[Ss]ection\d+\.xml$/.test(n)).sort(_chunkITJIALN5cjs.compareSectionPaths);
21507
22505
  }
21508
22506
  function sectionPathsFromManifest(xml) {
21509
22507
  const attr = (tag, name) => {
@@ -21513,7 +22511,7 @@ function sectionPathsFromManifest(xml) {
21513
22511
  const idToHref = /* @__PURE__ */ new Map();
21514
22512
  for (const m of xml.matchAll(/<opf:item(\s(?:"[^"]*"|'[^']*'|[^>"'])*?)\/?>/g)) {
21515
22513
  const id = attr(m[1], "id");
21516
- const href = _chunkXZTDYOZVcjs.normalizeSectionHref.call(void 0, attr(m[1], "href"));
22514
+ const href = _chunkITJIALN5cjs.normalizeSectionHref.call(void 0, attr(m[1], "href"));
21517
22515
  if (id && href) idToHref.set(id, href);
21518
22516
  }
21519
22517
  const ordered = [];
@@ -21522,7 +22520,7 @@ function sectionPathsFromManifest(xml) {
21522
22520
  if (href) ordered.push(href);
21523
22521
  }
21524
22522
  if (ordered.length > 0) return ordered;
21525
- return Array.from(idToHref.values()).sort(_chunkXZTDYOZVcjs.compareSectionPaths);
22523
+ return Array.from(idToHref.values()).sort(_chunkITJIALN5cjs.compareSectionPaths);
21526
22524
  }
21527
22525
 
21528
22526
  // src/roundtrip/patcher.ts
@@ -21539,7 +22537,7 @@ async function patchHwpx(original, editedMarkdown, options) {
21539
22537
  let zip;
21540
22538
  try {
21541
22539
  zip = await _jszip2.default.loadAsync(original);
21542
- } catch (e34) {
22540
+ } catch (e29) {
21543
22541
  return { success: false, applied: 0, skipped, error: "ZIP \uB85C\uB4DC \uC2E4\uD328" };
21544
22542
  }
21545
22543
  const sectionPaths = await resolveSectionEntryNames(zip);
@@ -21591,7 +22589,8 @@ async function patchHwpx(original, editedMarkdown, options) {
21591
22589
  try {
21592
22590
  for (let i = 0; i < scans.length; i++) {
21593
22591
  if (sectionSplices[i].length === 0) continue;
21594
- sectionSplices[i].push(...allLinesegRemovalSplices(scans[i].xml));
22592
+ const claimed = sectionSplices[i].filter((s) => s.end > s.start);
22593
+ sectionSplices[i].push(...allLinesegRemovalSplices(scans[i].xml).filter((ls) => !claimed.some((c) => ls.start >= c.start && ls.end <= c.end)));
21595
22594
  const newXml = applySplices(scans[i].xml, sectionSplices[i]);
21596
22595
  replacements.set(sectionPaths[i], encoder.encode(newXml));
21597
22596
  }
@@ -21613,7 +22612,7 @@ async function patchHwpx(original, editedMarkdown, options) {
21613
22612
  }
21614
22613
  }
21615
22614
  let verification;
21616
- if (_optionalChain([options, 'optionalAccess', _197 => _197.verify]) !== false) {
22615
+ if (_optionalChain([options, 'optionalAccess', _219 => _219.verify]) !== false) {
21617
22616
  try {
21618
22617
  const reparsed = await parseHwpxDocument(u8ToArrayBuffer(data));
21619
22618
  verification = diffUnitLists(splitMarkdownUnits(reparsed.markdown), editedUnits);
@@ -21631,17 +22630,17 @@ function buildOrigUnits(blocks) {
21631
22630
  let chunk;
21632
22631
  if (block.type === "paragraph" && block.text && /^\[별표\s*\d+/.test(sanitizeText(block.text))) {
21633
22632
  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));
22633
+ if (_optionalChain([next, 'optionalAccess', _220 => _220.type]) === "paragraph" && next.text && /관련\)?$/.test(next.text)) consume = 2;
22634
+ chunk = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, blocks.slice(i, i + consume));
21636
22635
  } else {
21637
- chunk = _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, [block]);
22636
+ chunk = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, [block]);
21638
22637
  }
21639
22638
  if (chunk) {
21640
22639
  const subUnits = splitMarkdownUnits(chunk);
21641
22640
  const isFragment = consume === 2 || (block.type === "paragraph" || block.type === "heading") && subUnits.length > 1;
21642
22641
  for (let s = 0; s < subUnits.length; s++) {
21643
22642
  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("**")) {
22643
+ 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
22644
  u.role = "caption";
21646
22645
  }
21647
22646
  units.push(u);
@@ -21659,82 +22658,6 @@ function buildTableOrdinals(blocks) {
21659
22658
  }
21660
22659
  return map;
21661
22660
  }
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
22661
  function resolveParagraphMappings(blocks, scans) {
21739
22662
  const buckets = /* @__PURE__ */ new Map();
21740
22663
  for (const scan of scans) {
@@ -21828,7 +22751,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
21828
22751
  const ti = ctx.tableInsert;
21829
22752
  if (!ti) return skip("\uBB38\uB2E8\u2192\uD45C \uBCC0\uD658 \uBD88\uAC00 \u2014 header \uC5D4\uD2B8\uB9AC(borderFills) \uD574\uC11D \uC2E4\uD328");
21830
22753
  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");
22754
+ 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
22755
  const para = mapping.para;
21833
22756
  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
22757
  const scan = ctx.scans[para.sectionIndex];
@@ -21856,7 +22779,7 @@ function convertParagraphToTable(block, orig, edited, ctx, skip) {
21856
22779
  }
21857
22780
  function patchParagraphUnit(block, orig, edited, ctx, skip) {
21858
22781
  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)");
22782
+ 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
22783
  if (block.text && block.text.includes("\n")) {
21861
22784
  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
22785
  }
@@ -21877,7 +22800,7 @@ function patchParagraphUnit(block, orig, edited, ctx, skip) {
21877
22800
  const origPrefix = block.text.split(" ", 1)[0];
21878
22801
  const sp = newPlain.indexOf(" ");
21879
22802
  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)) {
22803
+ if (newFirst === origPrefix || AUTONUM_PREFIX_RE.test(newFirst)) {
21881
22804
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
21882
22805
  } else {
21883
22806
  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 +22810,7 @@ function patchParagraphUnit(block, orig, edited, ctx, skip) {
21887
22810
  if (sanitizeText(newPlain) !== newPlain) {
21888
22811
  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
22812
  }
21890
- const splices = buildParagraphSplices(mapping.para, newPlain, _optionalChain([ctx, 'access', _203 => _203.scans, 'access', _204 => _204[mapping.para.sectionIndex], 'optionalAccess', _205 => _205.xml]));
22813
+ const splices = buildParagraphSplices(mapping.para, newPlain, _optionalChain([ctx, 'access', _225 => _225.scans, 'access', _226 => _226[mapping.para.sectionIndex], 'optionalAccess', _227 => _227.xml]));
21891
22814
  if (splices === null) return skip("\uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
21892
22815
  ctx.sectionSplices[mapping.para.sectionIndex].push(...splices);
21893
22816
  return 1;
@@ -21971,16 +22894,16 @@ function replaceOleStream(file, path, newData) {
21971
22894
  surgeon.replace(path, newData);
21972
22895
  return surgeon.finish();
21973
22896
  }
21974
- var Surgeon = (_class3 = class {
22897
+ var Surgeon = (_class4 = class {
21975
22898
 
21976
- __init5() {this.fat = []}
22899
+ __init6() {this.fat = []}
21977
22900
  /** 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);
22901
+ __init7() {this.fatSectors = []}
22902
+ __init8() {this.miniFat = []}
22903
+ __init9() {this.miniFatSectors = []}
22904
+ __init10() {this.dirSectors = []}
22905
+ __init11() {this.entries = []}
22906
+ 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
22907
  if (file.length < SECTOR || file.readUInt32LE(0) !== 3759263696) {
21985
22908
  throw new OleSurgeonError("OLE \uC2DC\uADF8\uB2C8\uCC98\uAC00 \uC544\uB2D9\uB2C8\uB2E4");
21986
22909
  }
@@ -22073,7 +22996,7 @@ var Surgeon = (_class3 = class {
22073
22996
  /** 디렉토리 트리에서 경로 해석 (형제 = L/R 이진 트리, 자식 = child) */
22074
22997
  findEntry(path) {
22075
22998
  const parts = path.replace(/^\//, "").split("/");
22076
- let scope = _nullishCoalesce(_optionalChain([this, 'access', _206 => _206.entries, 'access', _207 => _207[0], 'optionalAccess', _208 => _208.child]), () => ( -1));
22999
+ let scope = _nullishCoalesce(_optionalChain([this, 'access', _228 => _228.entries, 'access', _229 => _229[0], 'optionalAccess', _230 => _230.child]), () => ( -1));
22077
23000
  let current;
22078
23001
  for (const part of parts) {
22079
23002
  const search = (idx) => {
@@ -22236,7 +23159,7 @@ var Surgeon = (_class3 = class {
22236
23159
  this.flushFat();
22237
23160
  return this.buf;
22238
23161
  }
22239
- }, _class3);
23162
+ }, _class4);
22240
23163
 
22241
23164
  // src/roundtrip/hwp5-patch.ts
22242
23165
  var require3 = _module.createRequire.call(void 0, _chunkGS7T56RPcjs.importMetaUrl);
@@ -22276,21 +23199,24 @@ function readRecordsStrict(stream) {
22276
23199
  }
22277
23200
  return recs;
22278
23201
  }
22279
- function serializeRecords(recs, repl) {
23202
+ function serializeRecords(recs, repl, inserts) {
22280
23203
  const parts = [];
22281
- 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));
23204
+ const push = (tagId, level, data) => {
22283
23205
  const ext = data.length >= 4095;
22284
23206
  const header = Buffer.alloc(ext ? 8 : 4);
22285
- header.writeUInt32LE((recs[i].tagId & 1023 | (recs[i].level & 1023) << 10 | (ext ? 4095 : data.length) << 20) >>> 0, 0);
23207
+ header.writeUInt32LE((tagId & 1023 | (level & 1023) << 10 | (ext ? 4095 : data.length) << 20) >>> 0, 0);
22286
23208
  if (ext) header.writeUInt32LE(data.length, 4);
22287
23209
  parts.push(header, data);
23210
+ };
23211
+ for (let i = 0; i < recs.length; i++) {
23212
+ for (const ins of _nullishCoalesce(_optionalChain([inserts, 'optionalAccess', _231 => _231.get, 'call', _232 => _232(i)]), () => ( []))) push(ins.tagId, ins.level, ins.data);
23213
+ push(recs[i].tagId, recs[i].level, _nullishCoalesce(_optionalChain([repl, 'optionalAccess', _233 => _233.get, 'call', _234 => _234(i)]), () => ( recs[i].data)));
22288
23214
  }
22289
23215
  return Buffer.concat(parts);
22290
23216
  }
22291
23217
  function scanSection(stream, sectionIndex, compressed) {
22292
23218
  const records = readRecordsStrict(stream);
22293
- if (!records) return { records: [], safe: false, paras: [], tables: [], compressed, repl: /* @__PURE__ */ new Map() };
23219
+ if (!records) return { records: [], safe: false, paras: [], tables: [], compressed, repl: /* @__PURE__ */ new Map(), inserts: /* @__PURE__ */ new Map() };
22294
23220
  const safe = serializeRecords(records).equals(stream);
22295
23221
  const parent = new Int32Array(records.length).fill(-1);
22296
23222
  const stack = [];
@@ -22389,7 +23315,7 @@ function scanSection(stream, sectionIndex, compressed) {
22389
23315
  }
22390
23316
  tables.push({ sectionIndex, rows, cols, cells });
22391
23317
  }
22392
- return { records, safe, paras, tables, compressed, repl: /* @__PURE__ */ new Map() };
23318
+ return { records, safe, paras, tables, compressed, repl: /* @__PURE__ */ new Map(), inserts: /* @__PURE__ */ new Map() };
22393
23319
  }
22394
23320
  async function patchHwp(original, editedMarkdown, options) {
22395
23321
  const skipped = [];
@@ -22402,7 +23328,7 @@ async function patchHwp(original, editedMarkdown, options) {
22402
23328
  return fail(`CFB \uCEE8\uD14C\uC774\uB108 \uD30C\uC2F1 \uC2E4\uD328: ${msg(err)}`);
22403
23329
  }
22404
23330
  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");
23331
+ if (!_optionalChain([fhEntry, 'optionalAccess', _235 => _235.content])) return fail("FileHeader \uC2A4\uD2B8\uB9BC\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 HWP 5.x \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4");
22406
23332
  let flags;
22407
23333
  try {
22408
23334
  flags = parseFileHeader(Buffer.from(fhEntry.content)).flags;
@@ -22424,7 +23350,7 @@ async function patchHwp(original, editedMarkdown, options) {
22424
23350
  const scans = [];
22425
23351
  for (let i = 0; i < sectionPaths.length; i++) {
22426
23352
  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]}`);
23353
+ if (!_optionalChain([entry, 'optionalAccess', _236 => _236.content])) return fail(`\uC139\uC158 \uC2A4\uD2B8\uB9BC \uC77D\uAE30 \uC2E4\uD328: ${sectionPaths[i]}`);
22428
23354
  let stream;
22429
23355
  try {
22430
23356
  stream = compressed ? decompressStream(Buffer.from(entry.content)) : Buffer.from(entry.content);
@@ -22457,15 +23383,15 @@ async function patchHwp(original, editedMarkdown, options) {
22457
23383
  }
22458
23384
  }
22459
23385
  let data;
22460
- const dirty = scans.some((s) => s.repl.size > 0);
23386
+ const dirty = scans.some((s) => s.repl.size > 0 || s.inserts.size > 0);
22461
23387
  if (!dirty) {
22462
23388
  data = new Uint8Array(original);
22463
23389
  } else {
22464
23390
  try {
22465
23391
  let out = originalBuf;
22466
23392
  for (let i = 0; i < scans.length; i++) {
22467
- if (scans[i].repl.size === 0) continue;
22468
- const newStream = serializeRecords(scans[i].records, scans[i].repl);
23393
+ if (scans[i].repl.size === 0 && scans[i].inserts.size === 0) continue;
23394
+ const newStream = serializeRecords(scans[i].records, scans[i].repl, scans[i].inserts);
22469
23395
  const content = compressed ? _zlib.deflateRawSync.call(void 0, newStream) : newStream;
22470
23396
  out = replaceOleStream(out, sectionPaths[i], content);
22471
23397
  }
@@ -22475,7 +23401,7 @@ async function patchHwp(original, editedMarkdown, options) {
22475
23401
  }
22476
23402
  }
22477
23403
  let verification;
22478
- if (_optionalChain([options, 'optionalAccess', _213 => _213.verify]) !== false) {
23404
+ if (_optionalChain([options, 'optionalAccess', _237 => _237.verify]) !== false) {
22479
23405
  try {
22480
23406
  const reparsed = parseHwp5Document(Buffer.from(data));
22481
23407
  verification = diffUnitLists(splitMarkdownUnits(reparsed.markdown), editedUnits);
@@ -22564,7 +23490,7 @@ function tableContentScore(irTable, scanTable) {
22564
23490
  for (const [key, scanCell] of scanTable.cells) {
22565
23491
  const comma = key.indexOf(",");
22566
23492
  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]]);
23493
+ const irCell = _optionalChain([irTable, 'access', _238 => _238.cells, 'access', _239 => _239[r], 'optionalAccess', _240 => _240[c]]);
22568
23494
  if (!irCell) continue;
22569
23495
  const a = normForMatch(scanCell.paras.map((p) => p.rawText).join(" "));
22570
23496
  const b = normForMatch(stripCellTokens(irCell.text));
@@ -22600,7 +23526,7 @@ function handleModified(orig, edited, ctx) {
22600
23526
  }
22601
23527
  function patchParagraph(block, orig, edited, ctx, skip) {
22602
23528
  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)");
23529
+ if (!_optionalChain([mapping, 'optionalAccess', _241 => _241.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
23530
  if (block.text && block.text.includes("\n")) {
22605
23531
  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
23532
  }
@@ -22620,7 +23546,7 @@ function patchParagraph(block, orig, edited, ctx, skip) {
22620
23546
  const origPrefix = block.text.split(" ", 1)[0];
22621
23547
  const sp = newPlain.indexOf(" ");
22622
23548
  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)) {
23549
+ if (newFirst === origPrefix || AUTONUM_PREFIX_RE.test(newFirst)) {
22624
23550
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
22625
23551
  } else {
22626
23552
  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 +23611,6 @@ function patchGfmCells(scanTable, orig, edited, ctx, skip) {
22685
23611
  }
22686
23612
  return applied;
22687
23613
  }
22688
- function extractImgTags5(inner) {
22689
- return (inner.match(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi) || []).join(" ");
22690
- }
22691
23614
  function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
22692
23615
  if (replicateTableToHtml(table) !== orig.raw) return skip("\uD45C \uC88C\uD45C \uC7AC\uD604 \uBD88\uC77C\uCE58 \u2014 \uB9E4\uD551 \uC2E0\uB8B0 \uBD88\uAC00");
22693
23616
  const replica = replicateHtmlTable(table);
@@ -22715,7 +23638,7 @@ function patchHtmlCells5(table, scanTable, orig, edited, ctx, skip) {
22715
23638
  const origContent = htmlCellInnerToLines(oc.inner);
22716
23639
  const editedContent = htmlCellInnerToLines(ec.inner);
22717
23640
  if (origContent.hadNonText || editedContent.hadNonText) {
22718
- if (extractImgTags5(oc.inner) !== extractImgTags5(ec.inner)) {
23641
+ if (extractImgTags(oc.inner) !== extractImgTags(ec.inner)) {
22719
23642
  skip("\uC140 \uB0B4 \uC774\uBBF8\uC9C0 \uBCC0\uACBD\uC740 \uBBF8\uC9C0\uC6D0");
22720
23643
  continue;
22721
23644
  }
@@ -22779,7 +23702,7 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
22779
23702
  };
22780
23703
  const cell = scanTable.cells.get(`${gridR},${gridC}`);
22781
23704
  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]]);
23705
+ const irCell = _optionalChain([table, 'access', _242 => _242.cells, 'access', _243 => _243[gridR], 'optionalAccess', _244 => _244[gridC]]);
22783
23706
  const scanJoined = cell.paras.map((p) => p.rawText).filter((t) => normForMatch(t)).join("\n");
22784
23707
  if (irCell && normForMatch(scanJoined) !== normForMatch(stripCellTokens(irCell.text))) {
22785
23708
  if (normForMatch(irCell.text) !== "" || normForMatch(scanJoined) !== "") {
@@ -22796,22 +23719,25 @@ function applyCellEdit5(table, scanTable, gridR, gridC, newLines, ctx, before, a
22796
23719
  }
22797
23720
  const unstable = newLines.find((l) => sanitizeText(l) !== l);
22798
23721
  if (unstable !== void 0) return skip("\uACF5\uBC31 \uC815\uADDC\uD654 \uBD88\uC548\uC815 \uD14D\uC2A4\uD2B8 \u2014 \uD328\uCE58 \uC2DC \uC6D0\uBB38 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0");
22799
- if (nonEmpty.length === 0) return skip("\uBE48 \uC140 \uD14D\uC2A4\uD2B8 \uCC44\uC6B0\uAE30\uB294 HWP5 \uBBF8\uC9C0\uC6D0 (v1) \u2014 \uBB38\uB2E8 \uC0DD\uC131 \uD544\uC694");
23722
+ const targets = nonEmpty.length > 0 ? nonEmpty : cell.paras;
23723
+ if (targets.length === 0) return skip("\uC140\uC5D0 \uBB38\uB2E8\uC774 \uC5C6\uC74C \u2014 \uBBF8\uC9C0\uC6D0");
22800
23724
  const assigned = [];
22801
- for (let i = 0; i < nonEmpty.length; i++) {
23725
+ for (let i = 0; i < targets.length; i++) {
22802
23726
  if (i < newLines.length) {
22803
- assigned.push(i === nonEmpty.length - 1 && newLines.length > nonEmpty.length ? newLines.slice(i).join(" ") : newLines[i]);
23727
+ assigned.push(i === targets.length - 1 && newLines.length > targets.length ? newLines.slice(i).join(" ") : newLines[i]);
22804
23728
  } else {
22805
23729
  assigned.push("");
22806
23730
  }
22807
23731
  }
22808
- 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) });
23732
+ if (newLines.length > targets.length) {
23733
+ 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 });
23734
+ } else if (newLines.length < nonEmpty.length && nonEmpty.length > 1) {
23735
+ 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
23736
  }
22811
23737
  let staged = 0;
22812
- for (let i = 0; i < nonEmpty.length; i++) {
22813
- if (assigned[i] === nonEmpty[i].rawText || normForMatch(assigned[i]) === normForMatch(nonEmpty[i].rawText)) continue;
22814
- staged += stageParaPatch(ctx.scans[nonEmpty[i].sectionIndex], nonEmpty[i], assigned[i], skip);
23738
+ for (let i = 0; i < targets.length; i++) {
23739
+ if (assigned[i] === targets[i].rawText || normForMatch(assigned[i]) === normForMatch(targets[i].rawText)) continue;
23740
+ staged += stageParaPatch(ctx.scans[targets[i].sectionIndex], targets[i], assigned[i], skip);
22815
23741
  }
22816
23742
  return staged > 0 ? 1 : 0;
22817
23743
  }
@@ -22881,7 +23807,21 @@ function splitParaText(data) {
22881
23807
  if (firstP < 0) firstP = k;
22882
23808
  lastP = k;
22883
23809
  }
22884
- if (firstP < 0) return null;
23810
+ if (firstP < 0) {
23811
+ if (toks.some((t) => t.visible)) return null;
23812
+ let cut = data.length;
23813
+ for (const t of toks) if (data.readUInt16LE(t.start) === 13) {
23814
+ cut = t.start;
23815
+ break;
23816
+ }
23817
+ return {
23818
+ prefix: data.subarray(0, cut),
23819
+ prefixUnits: cut / 2,
23820
+ core: "",
23821
+ suffix: data.subarray(cut),
23822
+ suffixUnits: (data.length - cut) / 2
23823
+ };
23824
+ }
22885
23825
  for (let k = firstP; k <= lastP; k++) if (!toks[k].plain) return null;
22886
23826
  for (let k = 0; k < firstP; k++) if (toks[k].visible) return null;
22887
23827
  for (let k = lastP + 1; k < toks.length; k++) if (toks[k].visible) return null;
@@ -22914,7 +23854,6 @@ function rebuildCharShape(csData, coreStartUnit) {
22914
23854
  }
22915
23855
  function stageParaPatch(scan, para, newPlain, skip) {
22916
23856
  if (!scan.safe) return skip("\uC139\uC158 \uB808\uCF54\uB4DC \uC7AC\uC9C1\uB82C\uD654 \uBD88\uC77C\uCE58 \u2014 \uC548\uC804\uC744 \uC704\uD574 \uC774 \uC139\uC158\uC740 \uBBF8\uC9C0\uC6D0");
22917
- if (para.textIdx === -1) return skip("\uBE48 \uBB38\uB2E8 \uD14D\uC2A4\uD2B8 \uCD94\uAC00\uB294 \uBBF8\uC9C0\uC6D0 (v1)");
22918
23857
  if (para.textIdx === -2) return skip("\uBCF5\uC218 PARA_TEXT \uB808\uCF54\uB4DC \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
22919
23858
  if (para.rangeTagCount > 0) return skip("\uBC94\uC704 \uD0DC\uADF8(\uD615\uAD11\uD39C/\uAD50\uC815\uBD80\uD638) \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)");
22920
23859
  if (para.charShapeIdx < 0 || para.lineSegIdx < 0) return skip("\uBB38\uB2E8 \uB808\uCF54\uB4DC \uAD6C\uC131 \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
@@ -22922,11 +23861,27 @@ function stageParaPatch(scan, para, newPlain, skip) {
22922
23861
  if (/[\u0000-\u001f]/.test(newPlain)) return skip("\uC0C8 \uD14D\uC2A4\uD2B8\uC5D0 \uC81C\uC5B4\uBB38\uC790 \uD3EC\uD568 \u2014 \uBBF8\uC9C0\uC6D0");
22923
23862
  const records = scan.records;
22924
23863
  const headerRec = records[para.headerIdx];
22925
- const textRec = records[para.textIdx];
22926
23864
  const charShapeRec = records[para.charShapeIdx];
22927
23865
  if (charShapeRec.data.length < 8) {
22928
23866
  return skip("CHAR_SHAPE \uB808\uCF54\uB4DC \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
22929
23867
  }
23868
+ if (para.textIdx === -1) {
23869
+ const nCharsLow = para.nCharsRaw & 2147483647;
23870
+ if (nCharsLow > 1) return skip("PARA_TEXT \uC5C6\uB294 \uBB38\uB2E8\uC758 nChars \uBE44\uC815\uD615 \u2014 \uBBF8\uC9C0\uC6D0");
23871
+ const paraEnd = nCharsLow === 1 ? Buffer.from([13, 0]) : Buffer.alloc(0);
23872
+ const at = para.headerIdx + 1;
23873
+ const list = _nullishCoalesce(scan.inserts.get(at), () => ( []));
23874
+ list.push({ tagId: TAG_PARA_TEXT, level: headerRec.level + 1, data: Buffer.concat([Buffer.from(newPlain, "utf16le"), paraEnd]) });
23875
+ scan.inserts.set(at, list);
23876
+ const newHeader2 = Buffer.from(headerRec.data);
23877
+ newHeader2.writeUInt32LE((para.nCharsRaw & 2147483648 | newPlain.length + nCharsLow) >>> 0, 0);
23878
+ const cs2 = rebuildCharShape(charShapeRec.data, 0);
23879
+ scan.repl.set(para.charShapeIdx, cs2.buf);
23880
+ newHeader2.writeUInt16LE(cs2.count, 12);
23881
+ scan.repl.set(para.headerIdx, newHeader2);
23882
+ return 1;
23883
+ }
23884
+ const textRec = records[para.textIdx];
22930
23885
  const seg = splitParaText(textRec.data);
22931
23886
  if (!seg) {
22932
23887
  return skip(para.ctrlMask !== 0 ? "\uCEE8\uD2B8\uB864 \uBB38\uC790(\uD0ED/\uD544\uB4DC/\uD2B9\uC218\uACF5\uBC31 \uB4F1 \uD14D\uC2A4\uD2B8 \uC911\uAC04) \uD3EC\uD568 \uBB38\uB2E8 \u2014 \uBBF8\uC9C0\uC6D0 (v1)" : "PARA_TEXT \uC7AC\uAD6C\uC131 \uBD88\uC77C\uCE58 \u2014 \uC6D0\uBB38 \uBCF4\uC874 \uBD88\uAC00\uB85C \uBBF8\uC9C0\uC6D0");
@@ -22994,9 +23949,9 @@ function u8ToArrayBuffer2(u8) {
22994
23949
  function irCellLines(text) {
22995
23950
  return stripCellTokens(sanitizeText(text)).split("\n").map((s) => s.trim()).filter(Boolean);
22996
23951
  }
22997
- var HwpxSession = (_class4 = class _HwpxSession {
23952
+ var HwpxSession = (_class5 = class _HwpxSession {
22998
23953
 
22999
- constructor(state) {;_class4.prototype.__init11.call(this);
23954
+ constructor(state) {;_class5.prototype.__init12.call(this);
23000
23955
  this.state = state;
23001
23956
  }
23002
23957
  /** HWPX 바이트로 세션을 연다 (입력은 복사되어 외부 변이와 격리) */
@@ -23022,7 +23977,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23022
23977
  const block = st.blocks[blockIndex];
23023
23978
  if (!block) return void 0;
23024
23979
  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]);
23980
+ const para = _optionalChain([st, 'access', _245 => _245.paraMap, 'access', _246 => _246.get, 'call', _247 => _247(blockIndex), 'optionalAccess', _248 => _248.para]);
23026
23981
  if (!para) return void 0;
23027
23982
  return { kind: "paragraph", sectionIndex: para.sectionIndex, xmlStart: para.start };
23028
23983
  }
@@ -23047,7 +24002,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23047
24002
  if (block.text && block.text.includes("\n")) {
23048
24003
  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
24004
  }
23050
- if (!_optionalChain([st, 'access', _225 => _225.paraMap, 'access', _226 => _226.get, 'call', _227 => _227(blockIndex), 'optionalAccess', _228 => _228.para])) {
24005
+ if (!_optionalChain([st, 'access', _249 => _249.paraMap, 'access', _250 => _250.get, 'call', _251 => _251(blockIndex), 'optionalAccess', _252 => _252.para])) {
23051
24006
  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
24007
  }
23053
24008
  return { capability: "text" };
@@ -23096,7 +24051,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23096
24051
  this.opQueue = run.then(() => void 0, () => void 0);
23097
24052
  return run;
23098
24053
  }
23099
- __init11() {this.opQueue = Promise.resolve()}
24054
+ __init12() {this.opQueue = Promise.resolve()}
23100
24055
  async patchBlocksInner(edits, options) {
23101
24056
  const st = this.state;
23102
24057
  const skipped = [];
@@ -23113,7 +24068,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23113
24068
  continue;
23114
24069
  }
23115
24070
  if (block.type === "table" && block.table) {
23116
- if (!_optionalChain([edit, 'access', _229 => _229.cells, 'optionalAccess', _230 => _230.length])) {
24071
+ if (!_optionalChain([edit, 'access', _253 => _253.cells, 'optionalAccess', _254 => _254.length])) {
23117
24072
  skipped.push({ reason: "\uD45C \uBE14\uB85D\uC5D0\uB294 cells \uD3B8\uC9D1\uB9CC \uC9C0\uC6D0", before: summarize(_nullishCoalesce(block.table.caption, () => ( "(\uD45C)"))) });
23118
24073
  continue;
23119
24074
  }
@@ -23133,7 +24088,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23133
24088
  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
24089
  continue;
23135
24090
  }
23136
- const irCell = _optionalChain([block, 'access', _231 => _231.table, 'access', _232 => _232.cells, 'access', _233 => _233[cellEdit.row], 'optionalAccess', _234 => _234[cellEdit.col]]);
24091
+ const irCell = _optionalChain([block, 'access', _255 => _255.table, 'access', _256 => _256.cells, 'access', _257 => _257[cellEdit.row], 'optionalAccess', _258 => _258[cellEdit.col]]);
23137
24092
  if (!irCell) {
23138
24093
  skipped.push({ reason: `\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16: ${cellEdit.row},${cellEdit.col}`, after: summarize(cellEdit.text) });
23139
24094
  continue;
@@ -23181,6 +24136,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23181
24136
  try {
23182
24137
  for (let s = 0; s < st.scans.length; s++) {
23183
24138
  if (sectionSplices[s].length === 0) continue;
24139
+ sectionSplices[s].push(...allLinesegRemovalSplices(st.scans[s].xml));
23184
24140
  replacements.set(st.sectionPaths[s], encoder.encode(applySplices(st.scans[s].xml, sectionSplices[s])));
23185
24141
  }
23186
24142
  } catch (err) {
@@ -23188,7 +24144,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23188
24144
  }
23189
24145
  if (replacements.size === 0) {
23190
24146
  let changes2;
23191
- if (_optionalChain([options, 'optionalAccess', _235 => _235.verify]) !== false) {
24147
+ if (_optionalChain([options, 'optionalAccess', _259 => _259.verify]) !== false) {
23192
24148
  const units = splitMarkdownUnits(st.markdown);
23193
24149
  changes2 = diffUnitLists(units, units);
23194
24150
  }
@@ -23209,7 +24165,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23209
24165
  }
23210
24166
  this.state = newState;
23211
24167
  let changes;
23212
- if (_optionalChain([options, 'optionalAccess', _236 => _236.verify]) !== false) {
24168
+ if (_optionalChain([options, 'optionalAccess', _260 => _260.verify]) !== false) {
23213
24169
  changes = diffUnitLists(splitMarkdownUnits(beforeMarkdown), splitMarkdownUnits(newState.markdown));
23214
24170
  }
23215
24171
  return { success: true, data: new Uint8Array(data), applied, skipped, changes };
@@ -23229,7 +24185,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23229
24185
  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
24186
  }
23231
24187
  const mapping = st.paraMap.get(blockIndex);
23232
- if (!_optionalChain([mapping, 'optionalAccess', _237 => _237.para])) {
24188
+ if (!_optionalChain([mapping, 'optionalAccess', _261 => _261.para])) {
23233
24189
  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
24190
  }
23235
24191
  let newPlain = newTextRaw.split("\n").map((l) => l.trim()).filter(Boolean).join(" ");
@@ -23237,7 +24193,7 @@ var HwpxSession = (_class4 = class _HwpxSession {
23237
24193
  const origPrefix = block.text.split(" ", 1)[0];
23238
24194
  const sp = newPlain.indexOf(" ");
23239
24195
  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)) {
24196
+ if (newFirst === origPrefix || AUTONUM_PREFIX_RE.test(newFirst)) {
23241
24197
  newPlain = sp > 0 ? newPlain.slice(sp + 1) : "";
23242
24198
  } else {
23243
24199
  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 +24205,14 @@ var HwpxSession = (_class4 = class _HwpxSession {
23249
24205
  if (sanitizeText(newPlain) !== newPlain) {
23250
24206
  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
24207
  }
23252
- const splices = buildParagraphSplices(mapping.para, newPlain, _optionalChain([st, 'access', _238 => _238.scans, 'access', _239 => _239[mapping.para.sectionIndex], 'optionalAccess', _240 => _240.xml]));
24208
+ const splices = buildParagraphSplices(mapping.para, newPlain, _optionalChain([st, 'access', _262 => _262.scans, 'access', _263 => _263[mapping.para.sectionIndex], 'optionalAccess', _264 => _264.xml]));
23253
24209
  if (splices === null) return skip("\uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
23254
24210
  sectionSplices[mapping.para.sectionIndex].push(...splices);
23255
24211
  return 1;
23256
24212
  }
23257
- }, _class4);
24213
+ }, _class5);
23258
24214
  function cellStaticCheck(table, scanTable, r, c) {
23259
- const irCell = _optionalChain([table, 'access', _241 => _241.cells, 'access', _242 => _242[r], 'optionalAccess', _243 => _243[c]]);
24215
+ const irCell = _optionalChain([table, 'access', _265 => _265.cells, 'access', _266 => _266[r], 'optionalAccess', _267 => _267[c]]);
23260
24216
  if (!irCell) return { editable: false, reason: "\uC140 \uC88C\uD45C \uBC94\uC704 \uBC16" };
23261
24217
  const cell = scanTable.cellByAnchor.get(`${r},${c}`);
23262
24218
  if (!cell) return { editable: false, reason: "\uBCD1\uD569 \uC601\uC5ED\uC758 \uBE48 \uCE78\uC774\uAC70\uB098 \uC88C\uD45C \uBD88\uC77C\uCE58" };
@@ -23340,11 +24296,11 @@ var md = new (0, _markdownit2.default)({
23340
24296
  breaks: false
23341
24297
  });
23342
24298
  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]), () => ( "")));
24299
+ const preset = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _268 => _268.preset]), () => ( "default"));
24300
+ const css = PRESETS[preset] + (_nullishCoalesce(_optionalChain([options, 'optionalAccess', _269 => _269.extraCss]), () => ( "")));
23345
24301
  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]) ? `
24302
+ const watermark = _optionalChain([options, 'optionalAccess', _270 => _270.watermark]) ? `<div class="watermark">${escapeHtml(options.watermark)}</div>` : "";
24303
+ const watermarkCss = _optionalChain([options, 'optionalAccess', _271 => _271.watermark]) ? `
23348
24304
  .watermark {
23349
24305
  position: fixed;
23350
24306
  top: 50%; left: 50%;
@@ -23374,14 +24330,14 @@ async function htmlToPdf(html, options) {
23374
24330
  let puppeteer;
23375
24331
  try {
23376
24332
  puppeteer = await Promise.resolve().then(() => _interopRequireWildcard(require("puppeteer-core")));
23377
- } catch (e35) {
23378
- throw new (0, _chunkXZTDYOZVcjs.KordocError)(
24333
+ } catch (e30) {
24334
+ throw new (0, _chunkITJIALN5cjs.KordocError)(
23379
24335
  "PDF \uC0DD\uC131\uC5D0 puppeteer-core\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC124\uCE58: npm install puppeteer-core"
23380
24336
  );
23381
24337
  }
23382
24338
  const executablePath = _nullishCoalesce(process.env.PUPPETEER_EXECUTABLE_PATH, () => ( findChromiumPath()));
23383
24339
  if (!executablePath) {
23384
- throw new (0, _chunkXZTDYOZVcjs.KordocError)(
24340
+ throw new (0, _chunkITJIALN5cjs.KordocError)(
23385
24341
  "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
24342
  );
23387
24343
  }
@@ -23393,10 +24349,10 @@ async function htmlToPdf(html, options) {
23393
24349
  try {
23394
24350
  const page = await browser.newPage();
23395
24351
  await page.setContent(html, { waitUntil: "networkidle0" });
23396
- const margin = _optionalChain([options, 'optionalAccess', _248 => _248.margin]);
24352
+ const margin = _optionalChain([options, 'optionalAccess', _272 => _272.margin]);
23397
24353
  const pdf = await page.pdf({
23398
- format: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _249 => _249.pageSize]), () => ( "A4")),
23399
- landscape: _optionalChain([options, 'optionalAccess', _250 => _250.orientation]) === "landscape",
24354
+ format: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _273 => _273.pageSize]), () => ( "A4")),
24355
+ landscape: _optionalChain([options, 'optionalAccess', _274 => _274.orientation]) === "landscape",
23400
24356
  printBackground: true,
23401
24357
  margin: margin ? {
23402
24358
  top: toCss(margin.top),
@@ -23404,9 +24360,9 @@ async function htmlToPdf(html, options) {
23404
24360
  bottom: toCss(margin.bottom),
23405
24361
  left: toCss(margin.left)
23406
24362
  } : 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>'))
24363
+ displayHeaderFooter: !!(_optionalChain([options, 'optionalAccess', _275 => _275.header]) || _optionalChain([options, 'optionalAccess', _276 => _276.footer])),
24364
+ headerTemplate: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _277 => _277.header]), () => ( "<div></div>")),
24365
+ footerTemplate: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _278 => _278.footer]), () => ( '<div style="font-size:8pt;width:100%;text-align:center;color:#777;"><span class="pageNumber"></span>/<span class="totalPages"></span></div>'))
23410
24366
  });
23411
24367
  return Buffer.from(pdf);
23412
24368
  } finally {
@@ -23440,24 +24396,24 @@ async function markdownToPdf(markdown, options) {
23440
24396
  return htmlToPdf(html, options);
23441
24397
  }
23442
24398
  async function blocksToPdf(blocks, options) {
23443
- const markdown = _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, blocks);
24399
+ const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, blocks);
23444
24400
  return markdownToPdf(markdown, options);
23445
24401
  }
23446
24402
 
23447
24403
  // src/index.ts
23448
24404
  async function parse(input, options) {
23449
24405
  let buffer;
23450
- const opts = typeof input === "string" && !_optionalChain([options, 'optionalAccess', _255 => _255.filePath]) ? { ...options, filePath: input } : options;
24406
+ const opts = typeof input === "string" && !_optionalChain([options, 'optionalAccess', _279 => _279.filePath]) ? { ...options, filePath: input } : options;
23451
24407
  if (typeof input === "string") {
23452
24408
  try {
23453
24409
  const buf = await _promises.readFile.call(void 0, input);
23454
- buffer = _chunkXZTDYOZVcjs.toArrayBuffer.call(void 0, buf);
24410
+ buffer = _chunkITJIALN5cjs.toArrayBuffer.call(void 0, buf);
23455
24411
  } catch (err) {
23456
24412
  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
24413
  return { success: false, fileType: "unknown", error: msg2, code: "PARSE_ERROR" };
23458
24414
  }
23459
24415
  } else if (Buffer.isBuffer(input)) {
23460
- buffer = _chunkXZTDYOZVcjs.toArrayBuffer.call(void 0, input);
24416
+ buffer = _chunkITJIALN5cjs.toArrayBuffer.call(void 0, input);
23461
24417
  } else {
23462
24418
  buffer = input;
23463
24419
  }
@@ -23492,21 +24448,21 @@ async function parseHwp3(buffer, options) {
23492
24448
  const { markdown, blocks, metadata, outline, warnings } = parseHwp3Document(buffer, options);
23493
24449
  return { success: true, fileType: "hwp3", markdown, blocks, metadata, outline, warnings };
23494
24450
  } 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) };
24451
+ return { success: false, fileType: "hwp3", error: err instanceof Error ? err.message : "HWP3 \uD30C\uC2F1 \uC2E4\uD328", code: _chunkITJIALN5cjs.classifyError.call(void 0, err) };
23496
24452
  }
23497
24453
  }
23498
24454
  async function parseHwpx(buffer, options) {
23499
24455
  try {
23500
24456
  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 };
24457
+ return { success: true, fileType: "hwpx", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _280 => _280.length]) ? images : void 0 };
23502
24458
  } 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) };
24459
+ return { success: false, fileType: "hwpx", error: err instanceof Error ? err.message : "HWPX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkITJIALN5cjs.classifyError.call(void 0, err) };
23504
24460
  }
23505
24461
  }
23506
24462
  async function parseHwp(buffer, options) {
23507
24463
  try {
23508
24464
  const { markdown, blocks, metadata, outline, warnings, images } = parseHwp5Document(Buffer.from(buffer), options);
23509
- if (isDistributionSentinel(markdown) && isComFallbackAvailable() && _optionalChain([options, 'optionalAccess', _257 => _257.filePath])) {
24465
+ if (isDistributionSentinel(markdown) && isComFallbackAvailable() && _optionalChain([options, 'optionalAccess', _281 => _281.filePath])) {
23510
24466
  try {
23511
24467
  const { pages, pageCount, warnings: comWarns } = extractTextViaCom(options.filePath);
23512
24468
  if (pages.some((p) => p && p.trim().length > 0)) {
@@ -23520,20 +24476,20 @@ async function parseHwp(buffer, options) {
23520
24476
  warnings: com.warnings
23521
24477
  };
23522
24478
  }
23523
- } catch (e36) {
24479
+ } catch (e31) {
23524
24480
  }
23525
24481
  }
23526
- return { success: true, fileType: "hwp", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _258 => _258.length]) ? images : void 0 };
24482
+ return { success: true, fileType: "hwp", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _282 => _282.length]) ? images : void 0 };
23527
24483
  } 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) };
24484
+ return { success: false, fileType: "hwp", error: err instanceof Error ? err.message : "HWP \uD30C\uC2F1 \uC2E4\uD328", code: _chunkITJIALN5cjs.classifyError.call(void 0, err) };
23529
24485
  }
23530
24486
  }
23531
24487
  async function parsePdf(buffer, options) {
23532
24488
  let parsePdfDocument;
23533
24489
  try {
23534
- const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./parser-CPTBEGQP.cjs")));
24490
+ const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./parser-GUSJH44K.cjs")));
23535
24491
  parsePdfDocument = mod.parsePdfDocument;
23536
- } catch (e37) {
24492
+ } catch (e32) {
23537
24493
  return {
23538
24494
  success: false,
23539
24495
  fileType: "pdf",
@@ -23546,7 +24502,7 @@ async function parsePdf(buffer, options) {
23546
24502
  return { success: true, fileType: "pdf", markdown, blocks, metadata, outline, warnings, isImageBased, pageQuality, qualitySummary };
23547
24503
  } catch (err) {
23548
24504
  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 };
24505
+ return { success: false, fileType: "pdf", error: err instanceof Error ? err.message : "PDF \uD30C\uC2F1 \uC2E4\uD328", code: _chunkITJIALN5cjs.classifyError.call(void 0, err), isImageBased };
23550
24506
  }
23551
24507
  }
23552
24508
  async function parseXlsx(buffer, options) {
@@ -23554,7 +24510,7 @@ async function parseXlsx(buffer, options) {
23554
24510
  const { markdown, blocks, metadata, warnings } = await parseXlsxDocument(buffer, options);
23555
24511
  return { success: true, fileType: "xlsx", markdown, blocks, metadata, warnings };
23556
24512
  } 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) };
24513
+ return { success: false, fileType: "xlsx", error: err instanceof Error ? err.message : "XLSX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkITJIALN5cjs.classifyError.call(void 0, err) };
23558
24514
  }
23559
24515
  }
23560
24516
  async function parseXls(buffer, options) {
@@ -23562,15 +24518,15 @@ async function parseXls(buffer, options) {
23562
24518
  const { markdown, blocks, metadata, warnings } = await parseXlsDocument(buffer, options);
23563
24519
  return { success: true, fileType: "xls", markdown, blocks, metadata, warnings };
23564
24520
  } 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) };
24521
+ return { success: false, fileType: "xls", error: err instanceof Error ? err.message : "XLS \uD30C\uC2F1 \uC2E4\uD328", code: _chunkITJIALN5cjs.classifyError.call(void 0, err) };
23566
24522
  }
23567
24523
  }
23568
24524
  async function parseDocx(buffer, options) {
23569
24525
  try {
23570
24526
  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 };
24527
+ return { success: true, fileType: "docx", markdown, blocks, metadata, outline, warnings, images: _optionalChain([images, 'optionalAccess', _283 => _283.length]) ? images : void 0 };
23572
24528
  } 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) };
24529
+ return { success: false, fileType: "docx", error: err instanceof Error ? err.message : "DOCX \uD30C\uC2F1 \uC2E4\uD328", code: _chunkITJIALN5cjs.classifyError.call(void 0, err) };
23574
24530
  }
23575
24531
  }
23576
24532
  async function parseHwpml(buffer, options) {
@@ -23578,16 +24534,16 @@ async function parseHwpml(buffer, options) {
23578
24534
  const { markdown, blocks, metadata, outline, warnings } = parseHwpmlDocument(buffer, options);
23579
24535
  return { success: true, fileType: "hwpml", markdown, blocks, metadata, outline, warnings };
23580
24536
  } 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) };
24537
+ return { success: false, fileType: "hwpml", error: err instanceof Error ? err.message : "HWPML \uD30C\uC2F1 \uC2E4\uD328", code: _chunkITJIALN5cjs.classifyError.call(void 0, err) };
23582
24538
  }
23583
24539
  }
23584
24540
  async function fillForm(input, values, outputFormat = "markdown") {
23585
24541
  let buffer;
23586
24542
  if (typeof input === "string") {
23587
24543
  const buf = await _promises.readFile.call(void 0, input);
23588
- buffer = _chunkXZTDYOZVcjs.toArrayBuffer.call(void 0, buf);
24544
+ buffer = _chunkITJIALN5cjs.toArrayBuffer.call(void 0, buf);
23589
24545
  } else if (Buffer.isBuffer(input)) {
23590
- buffer = _chunkXZTDYOZVcjs.toArrayBuffer.call(void 0, input);
24546
+ buffer = _chunkITJIALN5cjs.toArrayBuffer.call(void 0, input);
23591
24547
  } else {
23592
24548
  buffer = input;
23593
24549
  }
@@ -23613,7 +24569,7 @@ async function fillForm(input, values, outputFormat = "markdown") {
23613
24569
  throw new Error(`\uC11C\uC2DD \uD30C\uC2F1 \uC2E4\uD328: ${parsed.error}`);
23614
24570
  }
23615
24571
  const fill = fillFormFields(parsed.blocks, values);
23616
- const markdown = _chunkXZTDYOZVcjs.blocksToMarkdown.call(void 0, fill.blocks);
24572
+ const markdown = _chunkITJIALN5cjs.blocksToMarkdown.call(void 0, fill.blocks);
23617
24573
  if (outputFormat === "hwpx") {
23618
24574
  const hwpxBuffer = await markdownToHwpx(markdown);
23619
24575
  return { output: hwpxBuffer, format: "hwpx", fill };
@@ -23663,5 +24619,13 @@ async function fillForm(input, values, outputFormat = "markdown") {
23663
24619
 
23664
24620
 
23665
24621
 
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;
24622
+
24623
+
24624
+
24625
+
24626
+
24627
+
24628
+
24629
+
24630
+ exports.HwpxSession = HwpxSession; exports.PRESET_ALIAS = PRESET_ALIAS; exports.SPACE_EM_FIXED = SPACE_EM_FIXED; exports.SPACE_EM_FONT = SPACE_EM_FONT; exports.VERSION = _chunkITJIALN5cjs.VERSION; exports.ValueCursor = ValueCursor; exports.applySplices = applySplices; exports.blocksToMarkdown = _chunkITJIALN5cjs.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
24631
  //# sourceMappingURL=index.cjs.map