kordoc 4.14.1 → 4.14.2

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 (135) hide show
  1. package/README.md +18 -2
  2. package/dist/{-VICWZYUH.js → -AQKXLFIM.js} +10 -10
  3. package/dist/{chunk-CF4GAWY3.cjs → chunk-247ANM72.cjs} +11 -11
  4. package/dist/chunk-247ANM72.cjs.map +1 -0
  5. package/dist/{chunk-CPWFM66X.js → chunk-3DUADAY2.js} +3 -3
  6. package/dist/{chunk-AH7RY5KD.cjs → chunk-422427XJ.cjs} +6 -6
  7. package/dist/chunk-422427XJ.cjs.map +1 -0
  8. package/dist/{chunk-HG5LXXCC.js → chunk-7IAQ4HOK.js} +1 -1
  9. package/dist/{chunk-XVIJLHCW.js.map → chunk-7IAQ4HOK.js.map} +1 -1
  10. package/dist/{chunk-UANJ2RGZ.js → chunk-A7QC2ZVP.js} +3 -3
  11. package/dist/{chunk-FXXYOSDX.js → chunk-C7FQBSON.js} +2 -2
  12. package/dist/chunk-DCZVOIEO.cjs.map +1 -1
  13. package/dist/{chunk-JGPAHXY2.js → chunk-DOGPOY4B.js} +2 -2
  14. package/dist/{chunk-OAB72MEM.js → chunk-EDNJLUSE.js} +2 -2
  15. package/dist/{chunk-UDMYSLCM.js → chunk-EISO3POT.js} +286 -123
  16. package/dist/chunk-EISO3POT.js.map +1 -0
  17. package/dist/{chunk-SRAZTGVT.js → chunk-EP7KOI2V.js} +3 -3
  18. package/dist/{chunk-U2F25OPK.cjs → chunk-EQZI77PP.cjs} +3 -3
  19. package/dist/chunk-EQZI77PP.cjs.map +1 -0
  20. package/dist/{chunk-XVIJLHCW.js → chunk-FOJZNMMK.js} +1 -1
  21. package/dist/{chunk-HG5LXXCC.js.map → chunk-FOJZNMMK.js.map} +1 -1
  22. package/dist/{chunk-JXWQVSJ5.js → chunk-GDW4YP7K.js} +2 -2
  23. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  24. package/dist/{chunk-X6G2WOPN.cjs → chunk-HR2XNERB.cjs} +2 -2
  25. package/dist/chunk-HR2XNERB.cjs.map +1 -0
  26. package/dist/{chunk-Z42AC5EN.js → chunk-ILU76UF3.js} +13 -2
  27. package/dist/chunk-ILU76UF3.js.map +1 -0
  28. package/dist/{chunk-HHV2SPWW.js → chunk-JQEFP45L.js} +2 -2
  29. package/dist/{chunk-LPBPYZW2.js → chunk-KVWV4ULP.js} +3 -3
  30. package/dist/{chunk-COUGOFT3.cjs → chunk-L7DMSMAG.cjs} +1 -1
  31. package/dist/chunk-L7DMSMAG.cjs.map +1 -0
  32. package/dist/{chunk-GKGEMRDR.js → chunk-NS55SM7A.js} +2 -2
  33. package/dist/{chunk-7MET77YG.js → chunk-QC5T6D4J.js} +2 -2
  34. package/dist/{chunk-SNJS23XX.cjs → chunk-QOMNEWCQ.cjs} +4 -4
  35. package/dist/chunk-QOMNEWCQ.cjs.map +1 -0
  36. package/dist/{chunk-34T3CWLH.js → chunk-TNCKOL2O.js} +2 -2
  37. package/dist/{chunk-DIK7K4U5.js → chunk-TSFS5VKD.js} +3072 -1721
  38. package/dist/chunk-TSFS5VKD.js.map +1 -0
  39. package/dist/{chunk-BCTVEUBG.js → chunk-UET462HB.js} +2 -2
  40. package/dist/{chunk-WHNGRJAH.js → chunk-VQ5W4MYO.js} +2 -2
  41. package/dist/{chunk-VJ2DIDHY.js → chunk-ZWD734EY.js} +2 -2
  42. package/dist/{chunk-NNRY6PT6.js → chunk-ZWOFQRIB.js} +14 -6
  43. package/dist/chunk-ZWOFQRIB.js.map +1 -0
  44. package/dist/chunks-SX77P5CV.js +10 -0
  45. package/dist/cli.js +1066 -1038
  46. package/dist/cli.js.map +1 -1
  47. package/dist/{formula-ILZUU7BK.js → formula-5S7WWXGH.js} +4 -4
  48. package/dist/{formula-RS2MXVJP.js → formula-JGFTXWYT.js} +3 -3
  49. package/dist/{formula-7NOWVRJM.cjs → formula-PJJ6S3Z2.cjs} +9 -9
  50. package/dist/formula-PJJ6S3Z2.cjs.map +1 -0
  51. package/dist/{image-ocr-IZ2D5DSI.js → image-ocr-FLIL7MGN.js} +6 -6
  52. package/dist/{image-ocr-UAIVXZCE.js → image-ocr-WCAYXLOA.js} +8 -8
  53. package/dist/{image-ocr-ZBEJUOOB.cjs → image-ocr-ZTYAGV3W.cjs} +12 -12
  54. package/dist/image-ocr-ZTYAGV3W.cjs.map +1 -0
  55. package/dist/index.cjs +2917 -1386
  56. package/dist/index.cjs.map +1 -1
  57. package/dist/index.d.cts +11 -6
  58. package/dist/index.d.ts +11 -6
  59. package/dist/index.js +2532 -1001
  60. package/dist/index.js.map +1 -1
  61. package/dist/mcp.js +973 -932
  62. package/dist/mcp.js.map +1 -1
  63. package/dist/{model-bundle-3VIW5GWN.js → model-bundle-FSPZZ2EM.js} +5 -5
  64. package/dist/{models-IWKMXSRU.js → models-CJPAQK5R.js} +5 -5
  65. package/dist/page-range-P7SDW6LR.cjs.map +1 -1
  66. package/dist/{parser-AIXBPHB6.js → parser-A4TMPJAM.js} +7 -7
  67. package/dist/{parser-N5R2DFAN.js → parser-SCUTZAIJ.js} +7 -7
  68. package/dist/{parser-TWUNLQ7E.cjs → parser-VCXE4I5A.cjs} +27 -27
  69. package/dist/parser-VCXE4I5A.cjs.map +1 -0
  70. package/dist/pdf-ocr-76SAUXMZ.js +13 -0
  71. package/dist/pdf-ocr-CPU55CVF.js +16 -0
  72. package/dist/pdf-ocr-MBZZ57LD.cjs +14 -0
  73. package/dist/pdf-ocr-MBZZ57LD.cjs.map +1 -0
  74. package/dist/{profile-io-P4UUA44E.js → profile-io-LBM263K7.js} +3 -3
  75. package/dist/{rasterize-5LM4Y5I6.js → rasterize-46RG4ZF6.js} +3 -3
  76. package/dist/{render-NNPSRJQN.js → render-NGP5T24S.js} +7 -7
  77. package/dist/seal-RGUPOLXD.js +10 -0
  78. package/dist/{setup-VOMHOYB3.js → setup-AU4OCHNH.js} +3 -3
  79. package/dist/visual-NZLYIYEM.js +19 -0
  80. package/dist/{watch-K554RCHJ.js → watch-MKPUCPXM.js} +11 -11
  81. package/package.json +2 -2
  82. package/dist/chunk-AH7RY5KD.cjs.map +0 -1
  83. package/dist/chunk-CF4GAWY3.cjs.map +0 -1
  84. package/dist/chunk-COUGOFT3.cjs.map +0 -1
  85. package/dist/chunk-DIK7K4U5.js.map +0 -1
  86. package/dist/chunk-NNRY6PT6.js.map +0 -1
  87. package/dist/chunk-SNJS23XX.cjs.map +0 -1
  88. package/dist/chunk-U2F25OPK.cjs.map +0 -1
  89. package/dist/chunk-UDMYSLCM.js.map +0 -1
  90. package/dist/chunk-X6G2WOPN.cjs.map +0 -1
  91. package/dist/chunk-Z42AC5EN.js.map +0 -1
  92. package/dist/chunks-NGOBC3DO.js +0 -10
  93. package/dist/formula-7NOWVRJM.cjs.map +0 -1
  94. package/dist/image-ocr-ZBEJUOOB.cjs.map +0 -1
  95. package/dist/parser-TWUNLQ7E.cjs.map +0 -1
  96. package/dist/pdf-ocr-BR22PWP4.cjs +0 -14
  97. package/dist/pdf-ocr-BR22PWP4.cjs.map +0 -1
  98. package/dist/pdf-ocr-VVUKDMNC.js +0 -16
  99. package/dist/pdf-ocr-WDOICXDJ.js +0 -13
  100. package/dist/seal-QADZXDS5.js +0 -10
  101. package/dist/visual-ATIECH7S.js +0 -19
  102. /package/dist/{-VICWZYUH.js.map → -AQKXLFIM.js.map} +0 -0
  103. /package/dist/{chunk-CPWFM66X.js.map → chunk-3DUADAY2.js.map} +0 -0
  104. /package/dist/{chunk-UANJ2RGZ.js.map → chunk-A7QC2ZVP.js.map} +0 -0
  105. /package/dist/{chunk-FXXYOSDX.js.map → chunk-C7FQBSON.js.map} +0 -0
  106. /package/dist/{chunk-JGPAHXY2.js.map → chunk-DOGPOY4B.js.map} +0 -0
  107. /package/dist/{chunk-OAB72MEM.js.map → chunk-EDNJLUSE.js.map} +0 -0
  108. /package/dist/{chunk-SRAZTGVT.js.map → chunk-EP7KOI2V.js.map} +0 -0
  109. /package/dist/{chunk-JXWQVSJ5.js.map → chunk-GDW4YP7K.js.map} +0 -0
  110. /package/dist/{chunk-HHV2SPWW.js.map → chunk-JQEFP45L.js.map} +0 -0
  111. /package/dist/{chunk-LPBPYZW2.js.map → chunk-KVWV4ULP.js.map} +0 -0
  112. /package/dist/{chunk-GKGEMRDR.js.map → chunk-NS55SM7A.js.map} +0 -0
  113. /package/dist/{chunk-7MET77YG.js.map → chunk-QC5T6D4J.js.map} +0 -0
  114. /package/dist/{chunk-34T3CWLH.js.map → chunk-TNCKOL2O.js.map} +0 -0
  115. /package/dist/{chunk-BCTVEUBG.js.map → chunk-UET462HB.js.map} +0 -0
  116. /package/dist/{chunk-WHNGRJAH.js.map → chunk-VQ5W4MYO.js.map} +0 -0
  117. /package/dist/{chunk-VJ2DIDHY.js.map → chunk-ZWD734EY.js.map} +0 -0
  118. /package/dist/{chunks-NGOBC3DO.js.map → chunks-SX77P5CV.js.map} +0 -0
  119. /package/dist/{formula-ILZUU7BK.js.map → formula-5S7WWXGH.js.map} +0 -0
  120. /package/dist/{formula-RS2MXVJP.js.map → formula-JGFTXWYT.js.map} +0 -0
  121. /package/dist/{image-ocr-IZ2D5DSI.js.map → image-ocr-FLIL7MGN.js.map} +0 -0
  122. /package/dist/{image-ocr-UAIVXZCE.js.map → image-ocr-WCAYXLOA.js.map} +0 -0
  123. /package/dist/{model-bundle-3VIW5GWN.js.map → model-bundle-FSPZZ2EM.js.map} +0 -0
  124. /package/dist/{models-IWKMXSRU.js.map → models-CJPAQK5R.js.map} +0 -0
  125. /package/dist/{parser-AIXBPHB6.js.map → parser-A4TMPJAM.js.map} +0 -0
  126. /package/dist/{parser-N5R2DFAN.js.map → parser-SCUTZAIJ.js.map} +0 -0
  127. /package/dist/{pdf-ocr-VVUKDMNC.js.map → pdf-ocr-76SAUXMZ.js.map} +0 -0
  128. /package/dist/{pdf-ocr-WDOICXDJ.js.map → pdf-ocr-CPU55CVF.js.map} +0 -0
  129. /package/dist/{profile-io-P4UUA44E.js.map → profile-io-LBM263K7.js.map} +0 -0
  130. /package/dist/{rasterize-5LM4Y5I6.js.map → rasterize-46RG4ZF6.js.map} +0 -0
  131. /package/dist/{render-NNPSRJQN.js.map → render-NGP5T24S.js.map} +0 -0
  132. /package/dist/{seal-QADZXDS5.js.map → seal-RGUPOLXD.js.map} +0 -0
  133. /package/dist/{setup-VOMHOYB3.js.map → setup-AU4OCHNH.js.map} +0 -0
  134. /package/dist/{visual-ATIECH7S.js.map → visual-NZLYIYEM.js.map} +0 -0
  135. /package/dist/{watch-K554RCHJ.js.map → watch-MKPUCPXM.js.map} +0 -0
@@ -7,11 +7,12 @@ import {
7
7
  decodeXmlEntities,
8
8
  escapeXmlText,
9
9
  findElementEnd,
10
+ markerRunSplices,
10
11
  paraTText,
11
12
  paraTextPureT,
12
13
  patchZipEntries,
13
14
  scanSectionXml
14
- } from "./chunk-NNRY6PT6.js";
15
+ } from "./chunk-ZWOFQRIB.js";
15
16
  import {
16
17
  CONVERT_MAP,
17
18
  FLAG_COMPRESSED,
@@ -50,12 +51,12 @@ import {
50
51
  renderDocumentToScene,
51
52
  romanNumeral,
52
53
  simulateWrap
53
- } from "./chunk-DIK7K4U5.js";
54
+ } from "./chunk-TSFS5VKD.js";
54
55
  import {
55
56
  HEADING_RATIO_H1,
56
57
  HEADING_RATIO_H2,
57
58
  HEADING_RATIO_H3
58
- } from "./chunk-HG5LXXCC.js";
59
+ } from "./chunk-7IAQ4HOK.js";
59
60
  import {
60
61
  parsePageRange
61
62
  } from "./chunk-MOL7MDBG.js";
@@ -74,7 +75,7 @@ import {
74
75
  findChildByLocalName,
75
76
  localName,
76
77
  rawTextContent
77
- } from "./chunk-Z42AC5EN.js";
78
+ } from "./chunk-ILU76UF3.js";
78
79
  import {
79
80
  MAX_COLS,
80
81
  MAX_ROWS,
@@ -83,7 +84,7 @@ import {
83
84
  convertTableToText,
84
85
  hasStructuredCellContent,
85
86
  mapPuaText
86
- } from "./chunk-7MET77YG.js";
87
+ } from "./chunk-QC5T6D4J.js";
87
88
  import {
88
89
  KordocError,
89
90
  classifyError,
@@ -95,7 +96,7 @@ import {
95
96
  sanitizeHref,
96
97
  stripDtd,
97
98
  toArrayBuffer
98
- } from "./chunk-BCTVEUBG.js";
99
+ } from "./chunk-UET462HB.js";
99
100
 
100
101
  // src/table/visual.ts
101
102
  import { readFile as readFile2 } from "fs/promises";
@@ -1527,8 +1528,10 @@ function extractParagraphInfo(para2, styleMap, ctx) {
1527
1528
  text += "\n";
1528
1529
  break;
1529
1530
  // 강제 줄바꿈 — ref 추출기·소스맵 스캐너와 동일 모델
1531
+ // 고정폭·묶음 빈칸 — 묶음 빈칸(nbSpace)을 빠뜨리면 "2026.<nbSpace/>9." 가 "2026.9." 로 붙는다
1530
1532
  case "fwSpace":
1531
1533
  case "hwSpace":
1534
+ case "nbSpace":
1532
1535
  text += " ";
1533
1536
  break;
1534
1537
  // 테이블 자체는 walkSection에서 처리 — 글자취급(inline) 표만 경계 마커를 남겨
@@ -1704,7 +1707,11 @@ function extractRunSpans(para2, ctx, mode, requireMixed) {
1704
1707
  for (let k = 0; k < (tkids?.length ?? 0); k++) {
1705
1708
  const tk = tkids[k];
1706
1709
  if (tk.nodeType === 3 || tk.nodeType === 4) text += tk.textContent || "";
1707
- else if (tk.nodeType === 1) return null;
1710
+ else if (tk.nodeType === 1) {
1711
+ const ttag = (tk.tagName || tk.localName || "").replace(/^[^:]+:/, "");
1712
+ if (ttag === "tab" || ttag === "fwSpace" || ttag === "hwSpace" || ttag === "nbSpace") text += " ";
1713
+ else return null;
1714
+ }
1708
1715
  }
1709
1716
  } else if (rtag === "secPr" || rtag === "colPr") {
1710
1717
  } else if (rtag === "ctrl") {
@@ -19197,6 +19204,9 @@ function resolveTheme(theme) {
19197
19204
  function escapeXml(text) {
19198
19205
  return text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
19199
19206
  }
19207
+ function escapeTextXml(text) {
19208
+ return escapeXml(text).replace(/\u00a0/g, "<hp:nbSpace/>");
19209
+ }
19200
19210
  function headingParaPrId(level) {
19201
19211
  if (level === 1) return PARA_H1;
19202
19212
  if (level === 2) return PARA_H2;
@@ -19223,14 +19233,14 @@ function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_C
19223
19233
  </hh:charPr>`;
19224
19234
  }
19225
19235
  function paraPr(id, opts = {}) {
19226
- const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, right = 0, keepWord = false, keepWithNext = false, outlineLevel } = opts;
19236
+ const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, right = 0, keepWord = false, keepWithNext = false, outlineLevel, autoTab = false, widowOrphan = false } = opts;
19227
19237
  const breakNonLatin = keepWord ? "BREAK_WORD" : "KEEP_WORD";
19228
19238
  const snapGrid = keepWord ? "0" : "1";
19229
19239
  const heading = outlineLevel !== void 0 ? `<hh:heading type="OUTLINE" idRef="0" level="${outlineLevel}"/>` : `<hh:heading type="NONE" idRef="0" level="0"/>`;
19230
- return ` <hh:paraPr id="${id}" tabPrIDRef="0" condense="0" fontLineHeight="0" snapToGrid="${snapGrid}" suppressLineNumbers="0" checked="0" textDir="AUTO">
19240
+ return ` <hh:paraPr id="${id}" tabPrIDRef="${autoTab ? 1 : 0}" condense="0" fontLineHeight="0" snapToGrid="${snapGrid}" suppressLineNumbers="0" checked="0" textDir="AUTO">
19231
19241
  <hh:align horizontal="${align}" vertical="BASELINE"/>
19232
19242
  ${heading}
19233
- <hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="0" keepWithNext="${keepWithNext ? 1 : 0}" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
19243
+ <hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="${widowOrphan ? 1 : 0}" keepWithNext="${keepWithNext ? 1 : 0}" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
19234
19244
  <hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
19235
19245
  <hh:margin><hc:intent value="${indent}" unit="HWPUNIT"/><hc:left value="${left}" unit="HWPUNIT"/><hc:right value="${right}" unit="HWPUNIT"/><hc:prev value="${spaceBefore}" unit="HWPUNIT"/><hc:next value="${spaceAfter}" unit="HWPUNIT"/></hh:margin>
19236
19246
  <hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
@@ -19689,7 +19699,7 @@ function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
19689
19699
  }
19690
19700
  }
19691
19701
  const charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
19692
- out.push(`<hp:run charPrIDRef="${mapped(charId)}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`);
19702
+ out.push(`<hp:run charPrIDRef="${mapped(charId)}"><hp:t>${escapeTextXml(span.text)}</hp:t></hp:run>`);
19693
19703
  }
19694
19704
  closeField();
19695
19705
  return out.join("");
@@ -19916,7 +19926,7 @@ ${base2.join("\n")}
19916
19926
  const ls = gongmun.lineSpacing;
19917
19927
  const titleAlign = gongmun.centerTitle ? "CENTER" : "LEFT";
19918
19928
  const h2MarkerWidth = markerWidth(gongmun.h2Marker === "box" ? "\u25A1" : "1.", 1600);
19919
- const h2Geom = gongmun.h2Marker !== "none" ? { spaceBefore: Math.round(gongmun.bodyHeight * 2), spaceAfter: 0, indent: -h2MarkerWidth } : { spaceBefore: 600, spaceAfter: 150 };
19929
+ const h2Geom = gongmun.h2Marker !== "none" ? { spaceBefore: Math.round(gongmun.bodyHeight * 2), spaceAfter: 0, indent: -h2MarkerWidth, autoTab: true } : { spaceBefore: 600, spaceAfter: 150 };
19920
19930
  const h3Left = gongmun.h2Marker !== "none" ? h2MarkerWidth : 0;
19921
19931
  const base = [
19922
19932
  paraPr(0, { lineSpacing: ls, keepWord: true }),
@@ -19936,7 +19946,7 @@ ${base2.join("\n")}
19936
19946
  const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, usesAsteriskThird(gongmun.preset), levelMarkerHeight(gongmun, d));
19937
19947
  const sectionGap = gongmun.numbering === "gaejosik" || gongmun.numbering === "report" ? gaejosikSpaceBefore(d, gongmun.bodyHeight) : 0;
19938
19948
  const keepNext = (gongmun.numbering === "gaejosik" || gongmun.numbering === "report") && d === 0;
19939
- base.push(paraPr(GONGMUN_LIST_BASE + d, { align: listAlign, lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext }));
19949
+ base.push(paraPr(GONGMUN_LIST_BASE + d, { align: listAlign, lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext, autoTab: true }));
19940
19950
  }
19941
19951
  base.push(paraPr(GONGMUN_CENTER, { align: "CENTER", lineSpacing: ls, keepWord: true }));
19942
19952
  base.push(paraPr(GONGMUN_RIGHT, { align: "RIGHT", lineSpacing: ls, keepWord: true }));
@@ -19946,7 +19956,7 @@ ${base2.join("\n")}
19946
19956
  const cham = gaejosikChamIndent(gongmun.bodyHeight, gongmun.sizes);
19947
19957
  const toc = gaejosikTocItemIndent(gongmun.bodyHeight, gongmun.sizes);
19948
19958
  base.push(
19949
- paraPr(GJ_PARA_CHAM, { align: "LEFT", lineSpacing: ls, left: cham.left, indent: cham.indent, spaceBefore: gaejosikSpaceBefore(3, gongmun.bodyHeight), keepWord: true }),
19959
+ paraPr(GJ_PARA_CHAM, { align: "LEFT", lineSpacing: ls, left: cham.left, indent: cham.indent, spaceBefore: gaejosikSpaceBefore(3, gongmun.bodyHeight), keepWord: true, autoTab: true }),
19950
19960
  paraPr(GJ_PARA_COVER, { align: "CENTER", lineSpacing: 130, keepWord: true }),
19951
19961
  paraPr(GJ_PARA_TOC_ITEM, { align: "LEFT", lineSpacing: 160, left: toc.left, indent: toc.indent, spaceBefore: 1800, keepWord: true }),
19952
19962
  // 장 헤더는 다음 문단과 같은 쪽에 — 쪽 하단 고아 헤더 방지 (실렌더 확인 이슈)
@@ -19967,7 +19977,7 @@ ${base2.join("\n")}
19967
19977
  const { left } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, usesAsteriskThird(gongmun.preset));
19968
19978
  const sectionGap = gongmun.numbering === "gaejosik" || gongmun.numbering === "report" ? gaejosikSpaceBefore(depth, gongmun.bodyHeight) : 0;
19969
19979
  const keepNext = (gongmun.numbering === "gaejosik" || gongmun.numbering === "report") && depth === 0;
19970
- base.push(paraPr(GONGMUN_LIST_VARIANT_BASE + vi, { align: listAlign, lineSpacing: ls, left, indent: -widthHu, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext }));
19980
+ base.push(paraPr(GONGMUN_LIST_VARIANT_BASE + vi, { align: listAlign, lineSpacing: ls, left, indent: -widthHu, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext, autoTab: true }));
19971
19981
  }
19972
19982
  assertSequentialIds(base, "paraPr", 0);
19973
19983
  return `<hh:paraProperties itemCnt="${base.length}">
@@ -20100,6 +20110,10 @@ function buildStyles(gongmun) {
20100
20110
  ${items.join("\n ")}
20101
20111
  </hh:styles>`;
20102
20112
  }
20113
+ var TAB_PROPS_GONGMUN = `<hh:tabProperties itemCnt="2">
20114
+ <hh:tabPr id="0" autoTabLeft="0" autoTabRight="0"/>
20115
+ <hh:tabPr id="1" autoTabLeft="1" autoTabRight="0"/>
20116
+ </hh:tabProperties>`;
20103
20117
  function generateHeaderXml(theme, gongmun, ratioVariants = [], extraBorderFills = [], extraCharPrXmls = [], listIndentVariants = [], extraFonts = [], v5 = null) {
20104
20118
  const bodyFace = v5?.bodyFace ?? gongmun?.fonts.body ?? (gongmun?.bodyFont === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5");
20105
20119
  const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants, extraCharPrXmls, !!v5);
@@ -20111,7 +20125,7 @@ function generateHeaderXml(theme, gongmun, ratioVariants = [], extraBorderFills
20111
20125
  ${buildFontFaces(gongmun, bodyFace, extraFonts, !!v5)}
20112
20126
  ${buildBorderFills(gongmun, extraBorderFills, !!v5)}
20113
20127
  ${charPropsXml}
20114
- <hh:tabProperties itemCnt="0"/>
20128
+ ${v5 || gongmun ? TAB_PROPS_GONGMUN : `<hh:tabProperties itemCnt="0"/>`}
20115
20129
  ${buildNumberings()}
20116
20130
  <hh:bullets itemCnt="0"/>
20117
20131
  ${paraPropsXml}
@@ -20507,7 +20521,7 @@ function buildGaejosikCover(title, gongmun, bodyWidth = GAEJOSIK_BASE_WIDTH) {
20507
20521
  const sz = gaejosikSizes(gongmun.bodyHeight, gongmun.sizes);
20508
20522
  const innerW = g.totalW - 282;
20509
20523
  const titleCharPr = simulateWrap(title, innerW, innerW, sz.coverTitle, 100, "keep").lines > 2 ? GJ_CHAR_COVER_SUB : GJ_CHAR_COVER_TITLE;
20510
- const titlePara = `<hp:p paraPrIDRef="${GJ_PARA_COVER}" styleIDRef="0"><hp:run charPrIDRef="${titleCharPr}"><hp:t>${escapeXml(title)}</hp:t></hp:run></hp:p>`;
20524
+ const titlePara = `<hp:p paraPrIDRef="${GJ_PARA_COVER}" styleIDRef="0"><hp:run charPrIDRef="${titleCharPr}"><hp:t>${escapeTextXml(title)}</hp:t></hp:run></hp:p>`;
20511
20525
  const barEmpty = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
20512
20526
  const topRow = cell({ bf: GJ_BF_BAR_DARK, col: 0, colSpan: 2, row: 0, w: g.topDarkW, h: g.barH, paras: barEmpty }) + cell({ bf: GJ_BF_BAR_LIGHT, col: 2, row: 0, w: g.topLightW, h: g.barH, paras: barEmpty });
20513
20527
  const titleRow = cell({ bf: 1, col: 0, colSpan: 3, row: 1, w: g.totalW, h: g.titleH, paras: titlePara, name: "__kordoc_h1" });
@@ -20516,7 +20530,7 @@ function buildGaejosikCover(title, gongmun, bodyWidth = GAEJOSIK_BASE_WIDTH) {
20516
20530
  const host2 = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${tbl2}</hp:run></hp:p>`;
20517
20531
  const date = gongmun.cover?.date ?? formatGaejosikDate(/* @__PURE__ */ new Date());
20518
20532
  const org = gongmun.cover?.org ?? "";
20519
- const sub = (t) => `<hp:p paraPrIDRef="${GJ_PARA_COVER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_COVER_SUB}"><hp:t>${escapeXml(t)}</hp:t></hp:run></hp:p>`;
20533
+ const sub = (t) => `<hp:p paraPrIDRef="${GJ_PARA_COVER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_COVER_SUB}"><hp:t>${escapeTextXml(t)}</hp:t></hp:run></hp:p>`;
20520
20534
  const subEmpty = emptyPara(GJ_PARA_COVER, false, GJ_CHAR_COVER_SUB);
20521
20535
  return [
20522
20536
  ...Array(5).fill(emptyPara()),
@@ -20541,7 +20555,7 @@ function buildGaejosikToc(chapters, gongmun, bodyWidth = GAEJOSIK_BASE_WIDTH) {
20541
20555
  const boxW = Math.round(TOC_GEOM.boxW * bodyWidth / GAEJOSIK_BASE_WIDTH);
20542
20556
  const label = buildTocBanner(gongmun, bodyWidth);
20543
20557
  const items = chapters.map(
20544
- (title, i) => `<hp:p paraPrIDRef="${GJ_PARA_TOC_ITEM}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_TOC_ROMAN}"><hp:t>${chapterRoman(i + 1)}</hp:t></hp:run><hp:run charPrIDRef="${GJ_CHAR_TOC_ITEM}"><hp:t>. ${escapeXml(title)}</hp:t></hp:run></hp:p>`
20558
+ (title, i) => `<hp:p paraPrIDRef="${GJ_PARA_TOC_ITEM}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_TOC_ROMAN}"><hp:t>${chapterRoman(i + 1)}</hp:t></hp:run><hp:run charPrIDRef="${GJ_CHAR_TOC_ITEM}"><hp:t>. ${escapeTextXml(title)}</hp:t></hp:run></hp:p>`
20545
20559
  ).join("");
20546
20560
  const box = table(
20547
20561
  [cell({ bf: GJ_BF_TOC_BOX, col: 0, w: boxW, h: TOC_GEOM.boxH, paras: items, name: "__kordoc_toc" })],
@@ -20558,7 +20572,7 @@ function buildGaejosikBodyTitle(title, gongmun, bodyWidth = GAEJOSIK_BASE_WIDTH)
20558
20572
  const g = coverGeom(gongmun.bodyHeight, gongmun.sizes, bodyWidth);
20559
20573
  const bt = bodyTitleGeom(gongmun.bodyHeight, gongmun.sizes);
20560
20574
  const barEmpty = emptyPara(GJ_PARA_BAR, false, GJ_CHAR_BAR);
20561
- const titlePara = `<hp:p paraPrIDRef="${GONGMUN_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_BODY_TITLE}"><hp:t>${escapeXml(title)}</hp:t></hp:run></hp:p>`;
20575
+ const titlePara = `<hp:p paraPrIDRef="${GONGMUN_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_BODY_TITLE}"><hp:t>${escapeTextXml(title)}</hp:t></hp:run></hp:p>`;
20562
20576
  const topRow = cell({ bf: GJ_BF_BAR_DARK, col: 0, colSpan: 2, row: 0, w: g.topDarkW, h: bt.barH, paras: barEmpty }) + cell({ bf: GJ_BF_BAR_LIGHT, col: 2, row: 0, w: g.topLightW, h: bt.barH, paras: barEmpty });
20563
20577
  const titleRow = cell({ bf: 1, col: 0, colSpan: 3, row: 1, w: g.totalW, h: bt.titleH, paras: titlePara, name: "__kordoc_skip" });
20564
20578
  const botRow = cell({ bf: GJ_BF_BAR_DARK, col: 0, row: 2, w: g.botDarkW, h: bt.barH, paras: barEmpty }) + cell({ bf: GJ_BF_BAR_LIGHT, col: 1, colSpan: 2, row: 2, w: g.botLightW, h: bt.barH, paras: barEmpty });
@@ -20568,7 +20582,7 @@ function buildGaejosikBodyTitle(title, gongmun, bodyWidth = GAEJOSIK_BASE_WIDTH)
20568
20582
  function buildGaejosikChapter(n, title, gongmun, bodyWidth = GAEJOSIK_BASE_WIDTH, srcLevel = 2) {
20569
20583
  const g = gongmun ? chapterGeom(gongmun.bodyHeight, gongmun.sizes, bodyWidth) : chapterGeom(1500, {}, bodyWidth);
20570
20584
  const numPara = `<hp:p paraPrIDRef="${GONGMUN_CENTER}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_CHAPTER_NUM}"><hp:t>${chapterRoman(n)}</hp:t></hp:run></hp:p>`;
20571
- const titlePara = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_CHAPTER_TITLE}"><hp:t> ${escapeXml(title)}</hp:t></hp:run></hp:p>`;
20585
+ const titlePara = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${GJ_CHAR_CHAPTER_TITLE}"><hp:t> ${escapeTextXml(title)}</hp:t></hp:run></hp:p>`;
20572
20586
  const row = cell({ bf: GJ_BF_CHAPTER_NUM, col: 0, w: g.numW, h: g.rowH, paras: numPara }) + cell({ bf: GJ_BF_CHAPTER_GAP, col: 1, w: g.gapW, h: g.rowH }) + cell({ bf: GJ_BF_CHAPTER_TITLE, col: 2, w: g.titleW, h: g.rowH, paras: titlePara, name: `__kordoc_h${Math.min(Math.max(srcLevel, 1), 6)}` });
20573
20587
  const tbl2 = table([row], g.numW + g.gapW + g.titleW, g.rowH, 3, 1, bodyWidth);
20574
20588
  return `<hp:p paraPrIDRef="${GJ_PARA_CHAPTER}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${tbl2}</hp:run></hp:p>`;
@@ -21535,7 +21549,7 @@ function cellContentWidth(text, charHeight) {
21535
21549
  function cellMinWordWidth(text, charHeight) {
21536
21550
  let max = 0;
21537
21551
  for (const seg of text.replace(/!\[[^\]]*\]\([^)\s]+\)/g, "").replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
21538
- for (const word of seg.trim().split(/\s+/)) {
21552
+ for (const word of seg.trim().split(/[ \t]+/)) {
21539
21553
  const w = measureTextWidth(word, charHeight, 100, { faceClass: curFace });
21540
21554
  if (w > max) max = w;
21541
21555
  }
@@ -21553,7 +21567,10 @@ function colRoles(headers) {
21553
21567
  if (roles.length >= 3 && roles.includes("content") && roles[last] === null) roles[last] = "remark";
21554
21568
  return roles;
21555
21569
  }
21556
- function computeColWidths(colMax, totalWidth, colMinWord = [], roles = []) {
21570
+ function colSlack(faceClass) {
21571
+ return faceClass.startsWith("font:") ? 1.03 : 1.12;
21572
+ }
21573
+ function computeColWidths(colMax, totalWidth, colMinWord = [], roles = [], slack = 1.12) {
21557
21574
  const colCnt = colMax.length;
21558
21575
  const minW = Math.min(Math.max(2e3, Math.round(totalWidth * 0.06)), Math.floor(totalWidth / colCnt));
21559
21576
  const cap = Math.round(totalWidth * 0.8);
@@ -21567,7 +21584,7 @@ function computeColWidths(colMax, totalWidth, colMinWord = [], roles = []) {
21567
21584
  let sumFloorFree = floor.reduce((a, b) => a + b, 0);
21568
21585
  for (const i of [...raw.keys()].sort((a, b) => raw[a] - raw[b])) {
21569
21586
  if (free.size <= 1) break;
21570
- const fixed = roles[i] === "remark" ? Math.min(Math.round(raw[i] * 1.12), capOf[i]) : Math.round(raw[i] * 1.12);
21587
+ const fixed = roles[i] === "remark" ? Math.min(Math.round(raw[i] * slack), capOf[i]) : Math.round(raw[i] * slack);
21571
21588
  if (budget - fixed < sumFloorFree - floor[i]) break;
21572
21589
  widths[i] = fixed;
21573
21590
  free.delete(i);
@@ -21640,7 +21657,7 @@ function requiredTableWidth(rows, charHeight, faceClass = "hcr") {
21640
21657
  if (w > colMax[c]) colMax[c] = w;
21641
21658
  });
21642
21659
  curFace = prev;
21643
- return colMax.reduce((a, w) => a + Math.round((w + CELL_PAD) * 1.12), 0);
21660
+ return colMax.reduce((a, w) => a + Math.round((w + CELL_PAD) * colSlack(faceClass)), 0);
21644
21661
  }
21645
21662
  function generateTable(rows, theme, style = null, remap = null, seq = 0, images = null) {
21646
21663
  curFace = style?.faceClass ?? "hcr";
@@ -21662,7 +21679,7 @@ function generateTable(rows, theme, style = null, remap = null, seq = 0, images
21662
21679
  if (mw > colMinWord[c]) colMinWord[c] = mw;
21663
21680
  }));
21664
21681
  const roles = style ? colRoles(rows[0] ?? []) : [];
21665
- const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW, colMinWord, roles);
21682
+ const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW, colMinWord, roles, colSlack(curFace));
21666
21683
  const colCentered = colWidths.map((w, c) => roles[c] !== "content" && colMaxBody[c] + CELL_PAD <= w);
21667
21684
  const labelCol0 = !!reg && colCnt === 2 && colCentered[0] && rows.every((r) => (r[0] ?? "").replace(/\*\*|__|`/g, "").length <= 12);
21668
21685
  const tblId = nextTableId();
@@ -21762,6 +21779,7 @@ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, r
21762
21779
  const { placed, rowCnt, colCnt } = layoutHtmlRows(rows);
21763
21780
  if (rowCnt === 0 || colCnt === 0) return null;
21764
21781
  const measureH = style?.charHeight ?? 1e3;
21782
+ curFace = style?.faceClass ?? "hcr";
21765
21783
  const first = placed.find((p) => p.r === 0 && p.c === 0) ?? placed[0];
21766
21784
  const row0 = Array.from({ length: colCnt }, () => "");
21767
21785
  for (const cell2 of placed) {
@@ -21774,7 +21792,7 @@ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, r
21774
21792
  const cellParsed = placed.map((cell2) => htmlCellInnerToLines(cell2.inner));
21775
21793
  const cellLines = cellParsed.map((p) => p.lines);
21776
21794
  placed.forEach((cell2, i) => {
21777
- const w = Math.max(...cellLines[i].map((l) => measureTextWidth(unescapeHtml(l).trim(), measureH, 100)), 0) / cell2.colSpan;
21795
+ const w = Math.max(...cellLines[i].map((l) => measureTextWidth(unescapeHtml(l).trim(), measureH, 100, { faceClass: curFace })), 0) / cell2.colSpan;
21778
21796
  const mw = cell2.colSpan === 1 ? Math.max(...cellLines[i].map((l) => cellMinWordWidth(unescapeHtml(l), measureH)), 0) : 0;
21779
21797
  for (let dc = 0; dc < cell2.colSpan; dc++) {
21780
21798
  const c = cell2.c + dc;
@@ -21786,7 +21804,7 @@ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, r
21786
21804
  const headers = Array.from({ length: colCnt }, () => "");
21787
21805
  for (const [i, cell2] of placed.entries()) if (cell2.r === 0 && cell2.c < colCnt) headers[cell2.c] = unescapeHtml(cellLines[i].join(" "));
21788
21806
  const roles = style ? colRoles(headers) : [];
21789
- const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth, colMinWord, roles);
21807
+ const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth, colMinWord, roles, colSlack(curFace));
21790
21808
  const colCentered = colWidths.map((w, c) => roles[c] !== "content" && colMaxBody[c] + CELL_PAD <= w);
21791
21809
  const cellH = style ? Math.round(measureH * 1.6) + 282 : 1500;
21792
21810
  const tblW = colWidths.reduce((a, b) => a + b, 0);
@@ -21815,7 +21833,7 @@ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, r
21815
21833
  const segLines = segTexts.map((t) => htmlCellInnerToLines(t).lines);
21816
21834
  const usable = Math.max(spanW(cell2) - CELL_PAD, 1e3);
21817
21835
  let wrapLines = 0;
21818
- for (const line of lines) wrapLines += Math.max(1, Math.ceil(measureTextWidth(unescapeHtml(line).trim(), measureH, 100) / usable));
21836
+ for (const line of lines) wrapLines += Math.max(1, Math.ceil(measureTextWidth(unescapeHtml(line).trim(), measureH, 100, { faceClass: curFace }) / usable));
21819
21837
  const lineH = style ? Math.round(measureH * 1.6) : 800;
21820
21838
  const contentH = Math.max(cellH * rowSpan, Math.max(wrapLines, 1) * lineH + nestedH);
21821
21839
  const cellHeight = Math.max(prof?.cellH.get(`${cell2.r},${cell2.c}`) ?? 0, contentH);
@@ -21844,7 +21862,7 @@ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, r
21844
21862
  }
21845
21863
  }
21846
21864
  if (!images || text.trim() || picUrls.length === 0) {
21847
- paras.push(`<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`);
21865
+ paras.push(`<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeTextXml(text)}</hp:t></hp:run></hp:p>`);
21848
21866
  }
21849
21867
  };
21850
21868
  segLines.forEach((seg, si) => {
@@ -21903,7 +21921,7 @@ function tc(opts) {
21903
21921
  return `<hp:tc name="${opts.name ?? ""}" header="0" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${opts.bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="${opts.vAlign ?? "CENTER"}" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${opts.paras}</hp:subList><hp:cellAddr colAddr="${opts.col}" rowAddr="${opts.row}"/><hp:cellSpan colSpan="${opts.colSpan ?? 1}" rowSpan="${opts.rowSpan ?? 1}"/><hp:cellSz width="${opts.w}" height="${opts.h}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
21904
21922
  }
21905
21923
  function para(text, paraPrId, charPrId) {
21906
- return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
21924
+ return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${charPrId}"><hp:t>${escapeTextXml(text)}</hp:t></hp:run></hp:p>`;
21907
21925
  }
21908
21926
  var APPROVAL_COL_W = 7085;
21909
21927
  var APPROVAL_LABEL_H = 1300;
@@ -22479,6 +22497,16 @@ function buildPreamble(blocks, ctx) {
22479
22497
  ctx.paraXmls.push(...preamble);
22480
22498
  }
22481
22499
  }
22500
+ function markedParagraph(marker, content, paraPrId, charPrId, halfEm, mapCharId, styleId = 0) {
22501
+ const cid2 = mapCharId ? mapCharId(charPrId) : charPrId;
22502
+ const run = `<hp:run charPrIDRef="${cid2}"><hp:t>${escapeTextXml(marker)}<hp:tab width="${Math.round(halfEm)}" leader="0" type="1"/></hp:t></hp:run>`;
22503
+ return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="${styleId}">${run}${generateRuns(content, charPrId, mapCharId)}</hp:p>`;
22504
+ }
22505
+ function refParagraph(text, ctx) {
22506
+ const m = /^(※|\*(?=\s))\s*/.exec(text);
22507
+ const [mk, rest] = m ? [m[1], text.slice(m[0].length)] : ["\u203B", text];
22508
+ return markedParagraph(mk, rest, GJ_PARA_CHAM, GJ_CHAR_CHAM, ctx.gongmun.bodyHeight / 2, ctx.chamMap);
22509
+ }
22482
22510
  function renderHeading(block, blockIdx, ctx) {
22483
22511
  const { gongmun, dfIds, tableStyle, bfReg, measured, richAssets, gjBodyW } = ctx;
22484
22512
  if (gongmun && blockIdx === ctx.coverH1Idx) return "";
@@ -22505,24 +22533,27 @@ function renderHeading(block, blockIdx, ctx) {
22505
22533
  ctx.chapterNo = no >= 0 ? no + 1 : ctx.chapterNo + 1;
22506
22534
  return buildGaejosikChapter(ctx.chapterNo, stripChapterNumber(block.text || ""), gongmun, gjBodyW, lvl);
22507
22535
  } else if (lvl === 3) {
22508
- return generateParagraph(
22509
- `\u25A1 ${block.text || ""}`,
22536
+ return markedParagraph(
22537
+ "\u25A1",
22538
+ block.text || "",
22510
22539
  GONGMUN_LIST_BASE,
22511
22540
  GJ_CHAR_DAE,
22541
+ gongmun.bodyHeight / 2,
22512
22542
  (id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id
22513
22543
  );
22514
22544
  }
22515
- return generateParagraph(`${gongmun.bullet2} ${block.text || ""}`, GONGMUN_LIST_BASE + 1, CHAR_NORMAL);
22545
+ return markedParagraph(gongmun.bullet2, block.text || "", GONGMUN_LIST_BASE + 1, CHAR_NORMAL, gongmun.bodyHeight / 2);
22516
22546
  }
22517
22547
  const pId = headingParaPrId(block.level || 1);
22518
22548
  const cId = headingCharPrId(block.level || 1);
22519
22549
  const styleId = gongmun ? Math.min(block.level || 1, 4) : 0;
22520
- let hText = block.text || "";
22521
22550
  if (gongmun && (block.level || 1) === 2 && gongmun.h2Marker !== "none") {
22522
- const title = stripChapterNumber(hText);
22523
- hText = gongmun.h2Marker === "box" ? `\u25A1 ${title}` : `${++ctx.h2Seq}. ${title}`;
22551
+ const title = stripChapterNumber(block.text || "");
22552
+ const mk = gongmun.h2Marker === "box" ? "\u25A1" : `${++ctx.h2Seq}.`;
22553
+ if (mk.length > 2) return generateParagraph(`${mk} ${title}`, pId, cId, void 0, styleId);
22554
+ return markedParagraph(mk, title, pId, cId, gongmun.bodyHeight / 2, void 0, styleId);
22524
22555
  }
22525
- return generateParagraph(hText, pId, cId, void 0, styleId);
22556
+ return generateParagraph(block.text || "", pId, cId, void 0, styleId);
22526
22557
  }
22527
22558
  function renderParagraph(block, blockIdx, ctx) {
22528
22559
  const { gongmun, measured, fit, vBase } = ctx;
@@ -22540,7 +22571,7 @@ function renderParagraph(block, blockIdx, ctx) {
22540
22571
  }
22541
22572
  const pTrim = (block.text || "").trimStart();
22542
22573
  if (measured && (pTrim.startsWith("\u203B") || /^\*\s/.test(pTrim))) {
22543
- return generateParagraph((block.text || "").trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, ctx.chamMap);
22574
+ return refParagraph((block.text || "").trim(), ctx);
22544
22575
  }
22545
22576
  const ctr = gongmun && /^<center>([\s\S]*)<\/center>$/i.exec((block.text || "").trim());
22546
22577
  const rgt = gongmun && /^<right>([\s\S]*)<\/right>$/i.exec((block.text || "").trim());
@@ -22579,7 +22610,7 @@ function renderEquation(block, blockIdx, ctx) {
22579
22610
  function renderBlockquote(block, ctx) {
22580
22611
  if (ctx.measured) {
22581
22612
  const t = (block.text || "").replace(/\n+/g, " ").trim();
22582
- return t ? generateParagraph(t.startsWith("\u203B") ? t : `\u203B ${t}`, GJ_PARA_CHAM, GJ_CHAR_CHAM, ctx.chamMap) : "";
22613
+ return t ? refParagraph(t, ctx) : "";
22583
22614
  }
22584
22615
  const quoteChar = ctx.theme.hasQuoteOption ? CHAR_QUOTE : CHAR_NORMAL;
22585
22616
  return (block.text || "").split("\n").map((line) => generateParagraph(line, PARA_QUOTE, quoteChar)).join("\n ");
@@ -22592,12 +22623,11 @@ function renderListItem(block, blockIdx, ctx) {
22592
22623
  const marker2 = info?.marker ?? "";
22593
22624
  const content = block.text || "";
22594
22625
  if (measured && content.trimStart().startsWith("\u203B")) {
22595
- return generateParagraph(content.trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, ctx.chamMap);
22626
+ return refParagraph(content.trim(), ctx);
22596
22627
  }
22597
22628
  if (measured && block.marker === "*") {
22598
- return generateParagraph(`* ${content.trim()}`, GJ_PARA_CHAM, GJ_CHAR_CHAM, ctx.chamMap);
22629
+ return refParagraph(`* ${content.trim()}`, ctx);
22599
22630
  }
22600
- const text = marker2 ? `${marker2} ${content}` : content;
22601
22631
  const listParaPr = marker2 ? info?.indentVariant !== void 0 ? GONGMUN_LIST_VARIANT_BASE + info.indentVariant : GONGMUN_LIST_BASE + depth : GONGMUN_LIST_PLAIN_BASE + depth;
22602
22632
  let listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
22603
22633
  let mapId = fit ? variantMapper(fit, blockIdx, vBase) : void 0;
@@ -22617,7 +22647,7 @@ function renderListItem(block, blockIdx, ctx) {
22617
22647
  listCharPr = lv.normal;
22618
22648
  mapId = (id) => id === CHAR_BOLD ? lv.bold : id === CHAR_NORMAL ? lv.normal : id;
22619
22649
  }
22620
- return generateParagraph(text, listParaPr, listCharPr, mapId);
22650
+ return marker2 ? markedParagraph(marker2, content, listParaPr, listCharPr, gongmun.bodyHeight / 2, mapId) : generateParagraph(content, listParaPr, listCharPr, mapId);
22621
22651
  }
22622
22652
  const indent = block.indent || 0;
22623
22653
  let marker;
@@ -22874,7 +22904,7 @@ var StyleRegistry = class {
22874
22904
  return id;
22875
22905
  }
22876
22906
  para(spec) {
22877
- const key = `${spec.align ?? "JUSTIFY"}|${spec.left ?? 0}|${spec.right ?? 0}|${spec.indent ?? 0}|${spec.before ?? 0}|${spec.after ?? 0}|${spec.lineSp ?? 160}|${spec.keepWithNext ? 1 : 0}|${spec.keepWord === false ? 0 : 1}`;
22907
+ const key = `${spec.align ?? "JUSTIFY"}|${spec.left ?? 0}|${spec.right ?? 0}|${spec.indent ?? 0}|${spec.before ?? 0}|${spec.after ?? 0}|${spec.lineSp ?? 160}|${spec.keepWithNext ? 1 : 0}|${spec.keepWord === false ? 0 : 1}|${spec.autoTab ? 1 : 0}|${spec.widowOrphan ? 1 : 0}`;
22878
22908
  const hit = this.paras.get(key);
22879
22909
  if (hit !== void 0) return hit;
22880
22910
  const id = this.paraBase + this.paraXmls.length;
@@ -22887,7 +22917,9 @@ var StyleRegistry = class {
22887
22917
  spaceAfter: spec.after ?? 0,
22888
22918
  lineSpacing: spec.lineSp ?? 160,
22889
22919
  keepWithNext: !!spec.keepWithNext,
22890
- keepWord: spec.keepWord !== false
22920
+ keepWord: spec.keepWord !== false,
22921
+ autoTab: !!spec.autoTab,
22922
+ widowOrphan: !!spec.widowOrphan
22891
22923
  }));
22892
22924
  this.paras.set(key, id);
22893
22925
  return id;
@@ -23041,11 +23073,6 @@ function applySchemeOverrides(s, g) {
23041
23073
  function taHu(pt) {
23042
23074
  return Math.round(pt * 50);
23043
23075
  }
23044
- function levelGeometry(style, marker) {
23045
- const left = style.leadTa * taHu(style.pt);
23046
- const indent = marker ? -markerWidth(marker, style.pt * 100) : 0;
23047
- return { left, indent };
23048
- }
23049
23076
  function pickScheme(g, bodyHasBoxMarkers) {
23050
23077
  if (g.preset === "ministry") {
23051
23078
  return applySchemeOverrides(ministryScheme(g.bodyPtExplicit ? g.bodyHeight / 100 : 15, g.lineSpacingExplicit ? g.lineSpacing : 145), g);
@@ -23270,9 +23297,12 @@ function buildOutline(blocks, opts) {
23270
23297
  // src/hwpx/fit-line.ts
23271
23298
  var RATIOS = [100, 97, 95, 92, 90, 87, 85];
23272
23299
  var SPACINGS = [0, -3, -5];
23300
+ function safety(faceClass, approx) {
23301
+ return faceClass.startsWith("font:") ? 0.98 : approx;
23302
+ }
23273
23303
  function fitOneLine(text, font, pt, availHu, minPt = Math.max(pt - 3, 10), minRatio = 85) {
23274
23304
  const faceClass = faceClassForGen(font);
23275
- const avail = availHu * 0.98;
23305
+ const avail = availHu * safety(faceClass, 0.98);
23276
23306
  const fits = (p, r, s) => measureTextWidth(text, p * 100, r, { spacingPct: s, faceClass }) <= avail;
23277
23307
  if (fits(pt, 100, 0)) return { pt, ratio: 100, spacing: 0, overflow: false };
23278
23308
  const ratios = RATIOS.filter((r) => r >= minRatio);
@@ -23283,27 +23313,139 @@ function fitOneLine(text, font, pt, availHu, minPt = Math.max(pt - 3, 10), minRa
23283
23313
  }
23284
23314
  return { pt: minPt, ratio: ratios[ratios.length - 1], spacing: SPACINGS[SPACINGS.length - 1], overflow: true };
23285
23315
  }
23286
- function fitOrphanLine(text, font, pt, firstW, contW, orphanRatio = 0.2) {
23316
+ var SQUEEZE = (() => {
23317
+ const out = [];
23318
+ for (let sp = -1; sp >= -12; sp--) out.push([100, sp]);
23319
+ for (const r of [97, 95, 92, 90, 88]) for (let sp = 0; sp >= -12; sp--) out.push([r, sp]);
23320
+ return out;
23321
+ })();
23322
+ var LOOSE_LIMIT = 1;
23323
+ var PULL_TAIL = 0.5;
23324
+ var PULL_MAX = 0.15;
23325
+ var squeezeOf = (r, sp) => 1 - r / 100 * (1 + sp / 100);
23326
+ var ORPHAN_RATIO = 0.22;
23327
+ var ORPHAN_COST = 1.5;
23328
+ var COMPRESS_COST = 10;
23329
+ function worstLooseness(text, starts, firstW, contW, h, ratio, spacing, faceClass) {
23330
+ const spaceW = 0.5 * h * (ratio / 100) * (1 + spacing / 100);
23331
+ let worst = 0;
23332
+ for (let i = 0; i + 1 < starts.length; i++) {
23333
+ const seg = text.slice(starts[i], starts[i + 1]).replace(/ +$/, "");
23334
+ const slack = (i === 0 ? firstW : contW) - measureTextWidth(seg, h, ratio, { faceClass, spacingPct: spacing });
23335
+ const spaces = (seg.match(/ /g) ?? []).length;
23336
+ worst = Math.max(worst, slack / (Math.max(spaces, 1) * spaceW));
23337
+ }
23338
+ return worst;
23339
+ }
23340
+ function fitParagraph(text, font, pt, firstW, contW, minRatio = 88, orphanRatio = ORPHAN_RATIO) {
23287
23341
  const faceClass = faceClassForGen(font);
23288
23342
  const h = pt * 100;
23289
- const SAFE = 0.9;
23290
- const width = (r, sp) => measureTextWidth(text, h, r, { faceClass, spacingPct: sp });
23291
- const est = width(100, 0);
23292
- if (est <= firstW * SAFE) return null;
23293
- const combos = [];
23294
- for (let sp = -1; sp >= -12; sp--) combos.push([100, sp]);
23295
- for (const r of [97, 95, 92, 90, 88]) for (let sp = 0; sp >= -12; sp--) combos.push([r, sp]);
23296
- if (est <= firstW * 1.22) {
23297
- for (const [r, sp] of combos) if (width(r, sp) <= firstW * SAFE) return { ratio: r, spacing: sp };
23298
- return null;
23343
+ const k = safety(faceClass, 0.95);
23344
+ const f = firstW * k, c = contW * k;
23345
+ const ladder = [[100, 0], ...SQUEEZE.filter(([r]) => r >= minRatio)];
23346
+ const base = simulateWrap(text, f, c, h, 100, "keep", { faceClass });
23347
+ if (base.lines < 2) return null;
23348
+ if (base.lastLineWidth <= c * PULL_TAIL) {
23349
+ let pull = null;
23350
+ for (const [r, sp] of ladder) {
23351
+ const amt = squeezeOf(r, sp);
23352
+ if (amt > PULL_MAX + 1e-9 || pull && amt >= pull.amt - 1e-9) continue;
23353
+ const w = simulateWrap(text, f, c, h, r, "keep", { faceClass, spacingPct: sp });
23354
+ if (w.lines < base.lines && worstLooseness(text, w.starts, f, c, h, r, sp, faceClass) <= LOOSE_LIMIT) pull = { r, sp, amt };
23355
+ }
23356
+ if (pull) return { ratio: pull.r, spacing: pull.sp };
23357
+ }
23358
+ let baseLines = 0;
23359
+ let best = null;
23360
+ for (const [r, sp] of ladder) {
23361
+ const w = simulateWrap(text, f, c, h, r, "keep", { faceClass, spacingPct: sp });
23362
+ if (!best) {
23363
+ if (w.lines < 2) return null;
23364
+ baseLines = w.lines;
23365
+ }
23366
+ if (w.lines > baseLines) continue;
23367
+ const orphan = w.lines > 1 && w.lastLineWidth <= contW * orphanRatio;
23368
+ const loose = worstLooseness(text, w.starts, f, c, h, r, sp, faceClass);
23369
+ const cost = Math.max(0, loose - LOOSE_LIMIT) + (orphan ? ORPHAN_COST : 0) + squeezeOf(r, sp) * COMPRESS_COST;
23370
+ if (!best || cost < best.cost - 1e-9) best = { r, sp, cost };
23371
+ }
23372
+ return best && (best.r !== 100 || best.sp !== 0) ? { ratio: best.r, spacing: best.sp } : null;
23373
+ }
23374
+ var LIST_BREAK = /* @__PURE__ */ new Set([..."\xB7,\u3001/"]);
23375
+ function fitCharBreaks(text, font, pt, firstW, contW, minRatio = 88) {
23376
+ const faceClass = faceClassForGen(font);
23377
+ const h = pt * 100;
23378
+ const k = safety(faceClass, 0.95);
23379
+ if (!text.split(/ +/).some((w) => measureTextWidth(w, h, 100, { faceClass }) > contW * k)) return null;
23380
+ let best = null;
23381
+ for (const [r, sp] of [[100, 0], ...SQUEEZE.filter(([r2]) => r2 >= minRatio)]) {
23382
+ const amt = squeezeOf(r, sp);
23383
+ if (amt > PULL_MAX + 1e-9 || best && amt >= best.amt - 1e-9) continue;
23384
+ const wrapAt = (s) => simulateWrap(text, firstW * s, contW * s, h, r, "charAll", { faceClass, spacingPct: sp }).starts;
23385
+ const starts = wrapAt(1);
23386
+ if (wrapAt(0.99).join() !== starts.join() || wrapAt(1.01).join() !== starts.join()) continue;
23387
+ if (!starts.slice(1).every((s) => text[s - 1] === " " || LIST_BREAK.has(text[s - 1]))) continue;
23388
+ if (worstLooseness(text, starts, firstW, contW, h, r, sp, faceClass) > LOOSE_LIMIT) continue;
23389
+ best = { r, sp, amt };
23390
+ }
23391
+ return best ? { ratio: best.r, spacing: best.sp } : null;
23392
+ }
23393
+
23394
+ // src/hwpx/gen-marker.ts
23395
+ function markerLayout(font, pt, leadTa, marker) {
23396
+ const left = leadTa * taHu(pt);
23397
+ if (!marker) return { left, hang: 0, markerW: 0 };
23398
+ const markerW = Math.round(measureTextWidth(marker, pt * 100, 100, { faceClass: faceClassForGen(font) }));
23399
+ return { left, hang: markerW + taHu(pt), markerW };
23400
+ }
23401
+ function markerRunXml(marker, charPr2, lay) {
23402
+ return `<hp:run charPrIDRef="${charPr2}"><hp:t>${escapeTextXml(marker)}<hp:tab width="${lay.hang - lay.markerW}" leader="0" type="1"/></hp:t></hp:run>`;
23403
+ }
23404
+
23405
+ // src/hwpx/gongmun-typo.ts
23406
+ var NBSP = "\xA0";
23407
+ var OPENER_BEFORE = /[\s(\[{>「『〈《【〔‘“·/:,~—–-]/u;
23408
+ function bindSpaces(s) {
23409
+ return s.replace(/(\d{4}|['’]\d{2})\. (\d{1,2})\. (\d{1,2})\.(?!\d)/g, `$1.${NBSP}$2.${NBSP}$3.`).replace(/(\d{4}|['’]\d{2})\. (\d{1,2})\.(?!\d)/g, `$1.${NBSP}$2.`).replace(/(?<![\d.])(\d{1,2})\. (\d{1,2})\.(?!\d)/g, `$1.${NBSP}$2.`).replace(/(\d{1,2}:\d{2}) ([~∼-]) (\d{1,2}:\d{2})/g, `$1${NBSP}$2${NBSP}$3`).replace(/(\d(?:조|억|만|천)?) 원/g, `$1${NBSP}\uC6D0`);
23410
+ }
23411
+ function neighbor(s, i, dir) {
23412
+ for (let k = i + dir; k >= 0 && k < s.length; k += dir) if (!/[*_~]/.test(s[k])) return s[k];
23413
+ return "";
23414
+ }
23415
+ function curlQuotes(s, before = "") {
23416
+ let out = "";
23417
+ for (let i = 0; i < s.length; i++) {
23418
+ const c = s[i];
23419
+ if (c !== "'" && c !== '"') {
23420
+ out += c;
23421
+ continue;
23422
+ }
23423
+ const prev = neighbor(s, i, -1) || before;
23424
+ const opening = prev === "" || OPENER_BEFORE.test(prev);
23425
+ if (c === "'") {
23426
+ if (opening && /^\d{2}(?![\d'])/.test(s.slice(i + 1))) {
23427
+ out += "\u2019";
23428
+ continue;
23429
+ }
23430
+ out += opening ? "\u2018" : "\u2019";
23431
+ } else {
23432
+ out += opening ? "\u201C" : "\u201D";
23433
+ }
23299
23434
  }
23300
- const f = firstW * 0.95, c = contW * 0.95;
23301
- const base = simulateWrap(text, f, c, h, 100, "charAll", { faceClass });
23302
- if (base.lines < 2 || base.lastLineWidth > c * orphanRatio) return null;
23303
- for (const [r, sp] of combos) {
23304
- if (simulateWrap(text, f, c, h, r, "charAll", { faceClass, spacingPct: sp }).lines < base.lines) return { ratio: r, spacing: sp };
23435
+ return out;
23436
+ }
23437
+ function polishGongmunText(text) {
23438
+ if (!text) return text;
23439
+ let out = "";
23440
+ for (const [i, seg] of text.split(/(`[^`]*`|\]\([^)]*\))/).entries()) {
23441
+ out += i % 2 === 1 ? seg : curlQuotes(bindSpaces(seg), out.replace(/[*_~]+$/, "").slice(-1));
23305
23442
  }
23306
- return null;
23443
+ return out;
23444
+ }
23445
+ function polishGongmunBlock(b) {
23446
+ if (b.type === "table") return b.rows ? { ...b, rows: b.rows.map((r) => r.map(polishGongmunText)) } : b;
23447
+ if (b.type === "paragraph" || b.type === "heading" || b.type === "list_item" || b.type === "blockquote") return b.text ? { ...b, text: polishGongmunText(b.text) } : b;
23448
+ return b;
23307
23449
  }
23308
23450
 
23309
23451
  // src/hwpx/gen-frame-seoul.ts
@@ -23520,13 +23662,13 @@ function buildSummaryBox(text, ctx) {
23520
23662
  const { reg, bf, frame } = ctx;
23521
23663
  const w = ctx.W - 566;
23522
23664
  const avail = w - 280 - SUMMARY_PAD * 2;
23523
- const p = reg.para({ align: "JUSTIFY", lineSp: 160, left: SUMMARY_PAD, right: SUMMARY_PAD, keepWord: false });
23665
+ const p = reg.para({ align: "JUSTIFY", lineSp: 160, left: SUMMARY_PAD, right: SUMMARY_PAD });
23524
23666
  const bodies = text.split("\n").map((l) => l.trim().replace(/^[□■○ㅇ◦●\-–ㆍ·•]\s*/u, "")).filter(Boolean);
23525
23667
  let lines = 0;
23526
23668
  const paras = bodies.map((b) => {
23527
- const f = fitOrphanLine(b, frame.summaryFont, frame.summaryPt, avail, avail);
23669
+ const f = fitParagraph(b, frame.summaryFont, frame.summaryPt, avail, avail);
23528
23670
  const c = reg.char({ font: frame.summaryFont, pt: frame.summaryPt, bold: true, ratio: f?.ratio ?? 100, spacing: f?.spacing ?? 0 });
23529
- lines += simulateWrap(b, avail * 0.95, avail * 0.95, frame.summaryPt * 100, f?.ratio ?? 100, "charAll", { faceClass: "gothic", spacingPct: f?.spacing ?? 0 }).lines;
23671
+ lines += simulateWrap(b, avail * 0.995, avail * 0.995, frame.summaryPt * 100, f?.ratio ?? 100, "keep", { faceClass: faceClassForGen(frame.summaryFont), spacingPct: f?.spacing ?? 0 }).lines;
23530
23672
  return para(b, p, c);
23531
23673
  });
23532
23674
  const h = lines * Math.round(frame.summaryPt * 100 * 1.6) + 280 + 600;
@@ -23619,11 +23761,11 @@ function ministryRuns(marker, text, ctx, base, keywordColor, emphasisColor) {
23619
23761
  const { reg } = ctx;
23620
23762
  const baseId = reg.char(base);
23621
23763
  const mapper = inlineMapper(reg, base, emphasisColor);
23622
- let out = marker ? `<hp:run charPrIDRef="${baseId}"><hp:t>${escapeXml(marker + " ")}</hp:t></hp:run>` : "";
23764
+ let out = marker ? `<hp:run charPrIDRef="${baseId}"><hp:t>${escapeTextXml(marker + " ")}</hp:t></hp:run>` : "";
23623
23765
  const m = KEYWORD_RE.exec(text);
23624
23766
  if (m) {
23625
23767
  const kw = reg.char({ ...base, bold: true, color: keywordColor ?? base.color });
23626
- out += `<hp:run charPrIDRef="${kw}"><hp:t>${escapeXml(m[1] + " ")}</hp:t></hp:run>`;
23768
+ out += `<hp:run charPrIDRef="${kw}"><hp:t>${escapeTextXml(m[1] + " ")}</hp:t></hp:run>`;
23627
23769
  text = text.slice(m[0].length);
23628
23770
  }
23629
23771
  return out + generateRuns(text, baseId, mapper);
@@ -23680,8 +23822,8 @@ function buildMinistryToc(chapters, ctx) {
23680
23822
  const cCh = reg.char({ font: MINISTRY.headFont, pt: t.chapterPt });
23681
23823
  const cSub = reg.char({ font: MINISTRY.headFont, pt: t.subPt });
23682
23824
  const pLabel = reg.para({ align: "LEFT", lineSp: 130, left: pad, before: 1200, after: 2400 });
23683
- const pCh = reg.para({ align: "LEFT", lineSp: 130, left: pad, before: 2e3, keepWord: false });
23684
- const pSub = reg.para({ align: "LEFT", lineSp: 130, left: pad + 1400, before: 1200, keepWord: false });
23825
+ const pCh = reg.para({ align: "LEFT", lineSp: 130, left: pad, before: 2e3 });
23826
+ const pSub = reg.para({ align: "LEFT", lineSp: 130, left: pad + 1400, before: 1200 });
23685
23827
  const paras = [para("\uBAA9 \uCC28", pLabel, cLabel)];
23686
23828
  let h = 1200 + Math.round(t.labelPt * 130) + 2400;
23687
23829
  let roman = 0;
@@ -23761,10 +23903,10 @@ function buildMinistryItemBand(n, text, ctx, before) {
23761
23903
  const w = ctx.W;
23762
23904
  const band = bf.get({ t: s.line, b: s.line, l: NONE, r: NONE, fill: s.fill });
23763
23905
  const base = { font: MINISTRY.bandFont, pt: s.pt, bold: false };
23764
- const f = fitOrphanLine(plain(text), MINISTRY.bandFont, s.pt, w - 1800, w - 1800);
23765
- const styled = f ? { ...base, ratio: f.ratio, spacing: f.spacing } : base;
23906
+ const f = fitOneLine(plain(text), MINISTRY.bandFont, s.pt, w - 1800, s.pt);
23907
+ const styled = f.overflow || f.ratio === 100 && f.spacing === 0 ? base : { ...base, ratio: f.ratio, spacing: f.spacing };
23766
23908
  const runs = ministryRuns(circledNumber(n - 1), text, ctx, styled, MINISTRY.blue, MINISTRY.blue);
23767
- const p = reg.para({ align: "LEFT", lineSp: 130, left: 300, keepWord: false });
23909
+ const p = reg.para({ align: "LEFT", lineSp: 130, left: 300 });
23768
23910
  const cell2 = tc({ bf: band, row: 0, col: 0, w, h: s.h, paras: `<hp:p paraPrIDRef="${p}" styleIDRef="0">${runs}</hp:p>`, name: "__kordoc_h5" });
23769
23911
  return host(ftbl([cell2], w, s.h, 1, { bottomGap: 700 }), reg.para({ align: "LEFT", lineSp: 100, before, keepWithNext: true }), reg.char(base));
23770
23912
  }
@@ -23773,20 +23915,21 @@ function buildMinistrySummaryBox(text, ctx) {
23773
23915
  const s = MINISTRY.summary;
23774
23916
  const w = ctx.W - 600;
23775
23917
  const avail = w - 280 - 600;
23776
- const pItem = reg.para({ align: "LEFT", lineSp: 140, left: 300, right: 300, indent: -Math.round(s.pt * 100 * 0.9), keepWord: false });
23777
- const pRef = reg.para({ align: "LEFT", lineSp: 130, left: 300 + Math.round(s.pt * 100 * 0.9), right: 300, keepWord: false });
23918
+ const lay = markerLayout(MINISTRY.bodyFont, s.pt, 0, "\u25AA");
23919
+ const pItem = reg.para({ align: "LEFT", lineSp: 140, left: 300, right: 300, indent: -lay.hang, autoTab: true });
23920
+ const pRef = reg.para({ align: "LEFT", lineSp: 130, left: 300 + lay.hang, right: 300 });
23778
23921
  const baseItem = { font: MINISTRY.bodyFont, pt: s.pt, bold: false };
23779
23922
  const cRef = reg.char({ font: MINISTRY.refFont, pt: s.refPt });
23780
23923
  let h = 0;
23781
23924
  const paras = text.split("\n").map((raw) => raw.trim()).filter(Boolean).map((line) => {
23782
23925
  const isRef = /^(\*|※)/.test(line);
23783
23926
  if (isRef) {
23784
- h += Math.round(s.refPt * 100 * 1.3) * simulateWrap(line, avail, avail, s.refPt * 100, 100, "charAll", { faceClass: "gothic" }).lines;
23927
+ h += Math.round(s.refPt * 100 * 1.3) * simulateWrap(line, avail - lay.hang, avail - lay.hang, s.refPt * 100, 100, "keep", { faceClass: faceClassForGen(MINISTRY.refFont) }).lines;
23785
23928
  return `<hp:p paraPrIDRef="${pRef}" styleIDRef="0">${generateRuns(line, cRef, inlineMapper(reg, { font: MINISTRY.refFont, pt: s.refPt, bold: false }))}</hp:p>`;
23786
23929
  }
23787
23930
  const body = line.replace(/^[▪■□○ㅇ●\-–ㆍ·•]\s*/u, "");
23788
- h += Math.round(s.pt * 100 * 1.4) * simulateWrap(plain(body), avail, avail, s.pt * 100, 100, "charAll").lines;
23789
- return `<hp:p paraPrIDRef="${pItem}" styleIDRef="0">${ministryRuns("\u25AA", body, ctx, baseItem, MINISTRY.blue)}</hp:p>`;
23931
+ h += Math.round(s.pt * 100 * 1.4) * simulateWrap(plain(body), avail - lay.hang, avail - lay.hang, s.pt * 100, 100, "keep", { faceClass: faceClassForGen(MINISTRY.bodyFont) }).lines;
23932
+ return `<hp:p paraPrIDRef="${pItem}" styleIDRef="0">${markerRunXml("\u25AA", reg.char(baseItem), lay)}${ministryRuns("", body, ctx, baseItem, MINISTRY.blue)}</hp:p>`;
23790
23933
  });
23791
23934
  h += 280 + 600;
23792
23935
  const box = bf.get({ t: "thin", b: "thin", l: "thin", r: "thin", fill: s.fill });
@@ -23838,7 +23981,8 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
23838
23981
  const pre = buildOutline(blocks, isMinistry ? { gaejosik: true, consumeTitle: true, summaryFromQuote: true, quoteBox: true, headingFrames: true, keepMarkers: true } : { gaejosik: true, consumeTitle: true, summaryFromQuote: isReport });
23839
23982
  const scheme = pickScheme(g, pre.hasBoxMarkers);
23840
23983
  const gaejosik = scheme.kind === "gaejosik";
23841
- const outline = gaejosik ? pre : buildOutline(blocks, { gaejosik: false, consumeTitle: true, summaryFromQuote: false });
23984
+ const raw = gaejosik ? pre : buildOutline(blocks, { gaejosik: false, consumeTitle: true, summaryFromQuote: false });
23985
+ const outline = { ...raw, title: raw.title && polishGongmunText(raw.title), nodes: raw.nodes.map(polishNode) };
23842
23986
  const frame = { reg, bf: bfReg, frame: scheme.frame, W };
23843
23987
  const lineHu = (st) => Math.round(st.pt * 100 * ((st.lineSp ?? scheme.lineSp) / 100));
23844
23988
  const paras = [];
@@ -23862,15 +24006,16 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
23862
24006
  let frontKind = "start";
23863
24007
  const pushSummary = (t) => {
23864
24008
  frontKind = "summary";
23865
- const box = buildSummaryBox(t, frame);
24009
+ const box = buildSummaryBox(polishGongmunText(t), frame);
23866
24010
  if (box.lines > 3) warnings.push(`\uC694\uC57D\uBC15\uC2A4\uAC00 ${box.lines}\uC904\uC785\uB2C8\uB2E4 \u2014 \uBCF4\uACE0 \uBAA9\uC801\uC744 \uD55C \uBB38\uC7A5(\uC27C\uD45C \uD5C8\uC6A9) 3\uC904 \uC774\uB0B4 "\u2026\uD558\uACE0\uC790 \uD568"\uC73C\uB85C \uC904\uC774\uC138\uC694`);
23867
24011
  paras.push(box.xml);
23868
24012
  };
23869
- const docTitle = g.docHead?.title ?? outline.title ?? "";
24013
+ const docTitle = polishGongmunText(g.docHead?.title ?? outline.title ?? "");
24014
+ const reportInfo = g.reportInfo && polishGongmunText(g.reportInfo);
23870
24015
  if (preset === "official") {
23871
24016
  if (g.docHead) paras.push(buildDocHeadTable({ ...g.docHead, title: docTitle }, frame));
23872
24017
  else if (outline.title) paras.push(generateParagraph(outline.title, reg.para({ align: "CENTER", lineSp: scheme.lineSp, after: lineHu(scheme.body) }), reg.char({ font: scheme.body.font, pt: scheme.body.pt + 2, bold: true }), void 0, 1));
23873
- if (g.reportInfo) paras.push(generateParagraph(g.reportInfo, reg.para({ align: "RIGHT", lineSp: scheme.lineSp }), reg.char({ font: scheme.body.font, pt: 12 })));
24018
+ if (reportInfo) paras.push(generateParagraph(reportInfo, reg.para({ align: "RIGHT", lineSp: scheme.lineSp }), reg.char({ font: scheme.body.font, pt: 12 })));
23874
24019
  if (g.approval) paras.push(buildApprovalSeoul(g.approval, null, frame));
23875
24020
  } else if (isMinistry) {
23876
24021
  if (g.cover) {
@@ -23909,7 +24054,7 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
23909
24054
  paras.push(buildApprovalSeoul(g.approval, null, frame));
23910
24055
  }
23911
24056
  if (docTitle) {
23912
- const t = buildReportTitleTable(docTitle, g.reportInfo, frame);
24057
+ const t = buildReportTitleTable(docTitle, reportInfo, frame);
23913
24058
  if (t.overflow) warnings.push(`\uC81C\uBAA9\uC774 \uAE38\uC5B4 \uD55C \uC904\uC5D0 \uB2F4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(20pt\xB7\uC7A5\uD3C9 85%\uAE4C\uC9C0 \uCD95\uC18C) \u2014 \uC81C\uBAA9\uC744 \uC904\uC774\uC138\uC694: "${docTitle.slice(0, 30)}\u2026"`);
23914
24059
  if (pendingPageBreak) {
23915
24060
  paras.push(t.xml.replace(/^<hp:p /, `<hp:p pageBreak="1" `).replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${newPageNumCtrl(1)}`));
@@ -23917,7 +24062,7 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
23917
24062
  } else paras.push(t.xml);
23918
24063
  frontKind = "title";
23919
24064
  }
23920
- if (!docTitle && g.reportInfo) paras.push(generateParagraph(g.reportInfo, reg.para({ align: "RIGHT", lineSp: scheme.lineSp }), reg.char({ font: scheme.body.font, pt: 12 })));
24065
+ if (!docTitle && reportInfo) paras.push(generateParagraph(reportInfo, reg.para({ align: "RIGHT", lineSp: scheme.lineSp }), reg.char({ font: scheme.body.font, pt: 12 })));
23921
24066
  if (g.summary) pushSummary(g.summary);
23922
24067
  else if (!outline.nodes.some((n) => n.kind === "summary")) warnings.push('\uBCF4\uACE0\uC11C \uC694\uC57D\uBC15\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC81C\uBAA9 \uC9C1\uD6C4 \uC778\uC6A9\uBB38(>)\uC5D0 \uBCF4\uACE0 \uBAA9\uC801\uC744 \uD55C \uBB38\uC7A5(\uC27C\uD45C \uD5C8\uC6A9) 3\uC904 \uC774\uB0B4 "\u2026\uD558\uACE0\uC790 \uD568"\uC73C\uB85C \uB123\uAC70\uB098 summary \uC635\uC158\uC744 \uC9C0\uC815\uD558\uC138\uC694');
23923
24068
  } else {
@@ -23956,51 +24101,55 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
23956
24101
  marker = numberer.next(depth, sup);
23957
24102
  itemSeq++;
23958
24103
  }
23959
- const text = marker ? `${marker} ${node.text}` : node.text;
23960
- const geom = levelGeometry(st, marker);
23961
- const availFirst = W - geom.left;
23962
- const availCont = W - geom.left + geom.indent;
23963
- let pt = st.pt, ratio = 100, spacing = 0;
24104
+ const mk = isMinistry && node.marker ? node.marker : marker;
24105
+ const lay = markerLayout(st.font, st.pt, st.leadTa, mk);
24106
+ const textW2 = W - lay.left - lay.hang;
24107
+ let ratio = 100, spacing = 0, charBreaks = false;
23964
24108
  if (st.oneLine) {
23965
- const fit = fitOneLine(plain2(text), st.font, st.pt, availFirst, st.pt, 90);
24109
+ const fit = fitOneLine(plain2(node.text), st.font, st.pt, textW2, st.pt, 90);
23966
24110
  if (fit.overflow) warnings.push(`\u25A1 \uD56D\uBAA9\uC774 \uD55C \uC904\uC5D0 \uB2F4\uAE30\uC9C0 \uC54A\uC544 \uB450 \uC904\uB85C \uAEBE\uC785\uB2C8\uB2E4 \u2014 \uBB38\uC7A5\uC744 \uC904\uC774\uC138\uC694(\uC7A5\uD3C9 90%\xB7\uC790\uAC04 -5 \uB85C\uB3C4 \uCD08\uACFC): "${node.text.slice(0, 30)}\u2026"`);
23967
24111
  else {
23968
24112
  ratio = fit.ratio;
23969
24113
  spacing = fit.spacing;
23970
24114
  }
23971
- } else if (g.autoFitMinRatio !== null) {
23972
- const f = fitOrphanLine(plain2(text), st.font, st.pt, availFirst, availCont);
24115
+ } else {
24116
+ const t = plain2(node.text);
24117
+ const cb = fitCharBreaks(t, st.font, st.pt, textW2, textW2, g.autoFitMinRatio ?? 101);
24118
+ const f = cb ?? (g.autoFitMinRatio !== null ? fitParagraph(t, st.font, st.pt, textW2, textW2, g.autoFitMinRatio) : null);
23973
24119
  if (f) {
23974
24120
  ratio = f.ratio;
23975
24121
  spacing = f.spacing;
23976
24122
  }
24123
+ charBreaks = !!cb;
23977
24124
  }
23978
- const base = { font: st.font, pt, bold: st.bold, ratio, spacing };
23979
- const geom2 = pt !== st.pt ? levelGeometry({ ...st, pt }, marker) : geom;
24125
+ const base = { font: st.font, pt: st.pt, bold: st.bold, ratio, spacing };
23980
24126
  const consecutiveBox = prevKind === "item" && prevItemDepth === 0 && depth === 0;
23981
24127
  const afterBand = depth === 0 && (prevKind === "chapter" && chapterStyle === "band" || prevKind === "title" && !!st.blankBefore);
23982
24128
  const before = afterBand ? BOX_GAP_AFTER_BAND : st.blankBefore && !consecutiveBox && prevKind !== "chapter" && prevKind !== "start" && prevKind !== "summary" ? BOX_BLANK_HU : 0;
23983
24129
  const keepNext = !!st.keepWithNext && !!nextNode && (nextNode.kind === "item" && nextNode.depth > depth || nextNode.kind === "ref");
24130
+ const paraSpec = { align: "JUSTIFY", left: lay.left, indent: -lay.hang, before, lineSp: st.lineSp ?? scheme.lineSp, keepWithNext: keepNext, keepWord: !charBreaks, autoTab: lay.hang > 0, widowOrphan: true };
24131
+ const markerRun = mk ? markerRunXml(mk, reg.char({ font: st.font, pt: st.pt, bold: st.bold }), lay) : "";
23984
24132
  if (isMinistry) {
23985
- const mk = node.marker ?? marker;
23986
- const g2 = node.marker ? levelGeometry(st, mk) : geom2;
23987
- const paraId2 = reg.para({ align: "JUSTIFY", left: g2.left, indent: g2.indent, before, after: 600, lineSp: st.lineSp ?? scheme.lineSp, keepWithNext: keepNext, keepWord: false });
23988
- const runs = ministryRuns(mk, node.text, frame, base, depth === 0 ? MINISTRY.blue : null);
24133
+ const paraId2 = reg.para({ ...paraSpec, after: 600 });
24134
+ const runs = markerRun + ministryRuns("", node.text, frame, base, depth === 0 ? MINISTRY.blue : null);
23989
24135
  return `<hp:p paraPrIDRef="${paraId2}" styleIDRef="${styleId}">${runs}</hp:p>`;
23990
24136
  }
23991
- const paraId = reg.para({ align: "JUSTIFY", left: geom2.left, indent: geom2.indent, before, lineSp: st.lineSp ?? scheme.lineSp, keepWithNext: keepNext, keepWord: false });
23992
- return generateParagraph(text, paraId, reg.char(base), inlineMapper(reg, base), styleId);
24137
+ const paraId = reg.para(paraSpec);
24138
+ return `<hp:p paraPrIDRef="${paraId}" styleIDRef="${styleId}">${markerRun}${generateRuns(node.text, reg.char(base), inlineMapper(reg, base))}</hp:p>`;
23993
24139
  };
23994
24140
  const renderRef = (node) => {
23995
24141
  const st = scheme.ref;
23996
24142
  const marker = isMinistry ? "*" : "\u203B";
24143
+ const lay = markerLayout(st.font, st.pt, 0, marker);
23997
24144
  const left = isMinistry ? st.leadTa * taHu(st.pt) : leadLeft(node.depth, st.pt);
23998
- const geom = levelGeometry({ ...st, leadTa: 0 }, marker);
23999
- const base = { font: st.font, pt: st.pt, bold: st.bold };
24000
- const f = fitOrphanLine(plain2(`${marker} ${node.text}`), st.font, st.pt, W - left, W - left + geom.indent);
24001
- const baseF = f ? { ...base, ratio: f.ratio, spacing: f.spacing } : base;
24002
- const paraId = reg.para({ align: "JUSTIFY", left, indent: geom.indent, after: isMinistry ? 400 : 0, lineSp: isMinistry ? 130 : st.lineSp ?? scheme.lineSp, keepWord: false });
24003
- return generateParagraph(`${marker} ${node.text}`, paraId, reg.char(baseF), inlineMapper(reg, baseF));
24145
+ const textW2 = W - left - lay.hang;
24146
+ const t = plain2(node.text);
24147
+ const cb = fitCharBreaks(t, st.font, st.pt, textW2, textW2, g.autoFitMinRatio ?? 101);
24148
+ const f = cb ?? (g.autoFitMinRatio !== null ? fitParagraph(t, st.font, st.pt, textW2, textW2, g.autoFitMinRatio) : null);
24149
+ const base = { font: st.font, pt: st.pt, bold: st.bold, ratio: f?.ratio ?? 100, spacing: f?.spacing ?? 0 };
24150
+ const paraId = reg.para({ align: "JUSTIFY", left, indent: -lay.hang, after: isMinistry ? 400 : 0, lineSp: isMinistry ? 130 : st.lineSp ?? scheme.lineSp, keepWord: !cb, autoTab: true, widowOrphan: true });
24151
+ const markerRun = markerRunXml(marker, reg.char({ font: st.font, pt: st.pt, bold: st.bold }), lay);
24152
+ return `<hp:p paraPrIDRef="${paraId}" styleIDRef="0">${markerRun}${generateRuns(node.text, reg.char(base), inlineMapper(reg, base))}</hp:p>`;
24004
24153
  };
24005
24154
  const renderPara = (node) => {
24006
24155
  const st = scheme.body;
@@ -24014,16 +24163,19 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
24014
24163
  if (pics.every(Boolean)) return `<hp:p paraPrIDRef="${reg.para({ align: "CENTER", lineSp: scheme.lineSp })}" styleIDRef="0"><hp:run charPrIDRef="${reg.char({ font: st.font, pt: st.pt })}">${pics.join("")}</hp:run></hp:p>`;
24015
24164
  }
24016
24165
  }
24017
- let ratio = 100, spacing = 0;
24018
- if (!node.align && g.autoFitMinRatio !== null) {
24019
- const f = fitOrphanLine(plain2(node.text), st.font, st.pt, W, W);
24166
+ let ratio = 100, spacing = 0, charBreaks = false;
24167
+ if (!node.align) {
24168
+ const t = plain2(node.text);
24169
+ const cb = fitCharBreaks(t, st.font, st.pt, W, W, g.autoFitMinRatio ?? 101);
24170
+ const f = cb ?? (g.autoFitMinRatio !== null ? fitParagraph(t, st.font, st.pt, W, W, g.autoFitMinRatio) : null);
24020
24171
  if (f) {
24021
24172
  ratio = f.ratio;
24022
24173
  spacing = f.spacing;
24023
24174
  }
24175
+ charBreaks = !!cb;
24024
24176
  }
24025
24177
  const base = { font: st.font, pt: st.pt, bold: st.bold, ratio, spacing };
24026
- const paraId = reg.para({ align: node.align ?? "JUSTIFY", lineSp: scheme.lineSp, keepWord: false });
24178
+ const paraId = reg.para({ align: node.align ?? "JUSTIFY", lineSp: scheme.lineSp, keepWord: !charBreaks, widowOrphan: true });
24027
24179
  return generateParagraph(node.text, paraId, reg.char(base), inlineMapper(reg, base));
24028
24180
  };
24029
24181
  const renderChapter = (node) => {
@@ -24051,7 +24203,7 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
24051
24203
  const fit = fitOneLine(plain2(text), st.font, st.pt, W, st.pt - 2);
24052
24204
  const base = { font: st.font, pt: fit.pt, bold: st.bold, ratio: fit.ratio, spacing: fit.spacing };
24053
24205
  const before = prevKind === "start" || prevKind === "title" || prevKind === "summary" ? 0 : lineHu(scheme.body);
24054
- const paraId = reg.para({ align: "LEFT", before, after: Math.round(lineHu(scheme.body) * 0.3), lineSp: st.lineSp ?? scheme.lineSp, keepWithNext: true, keepWord: false });
24206
+ const paraId = reg.para({ align: "LEFT", before, after: Math.round(lineHu(scheme.body) * 0.3), lineSp: st.lineSp ?? scheme.lineSp, keepWithNext: true });
24055
24207
  return generateParagraph(text, paraId, reg.char(base), inlineMapper(reg, base), 2);
24056
24208
  };
24057
24209
  const renderAttach = (node, first) => {
@@ -24059,7 +24211,7 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
24059
24211
  let text = node.text;
24060
24212
  if (/^\s*붙\s*임/.test(text)) text = text.replace(/^\s*붙\s*임\s*[::]?\s*/, "\uBD99\uC784 ");
24061
24213
  else text = text.replace(/\s+$/, "");
24062
- const paraId = reg.para({ align: "LEFT", before: first ? lineHu(scheme.body) : 0, lineSp: st.lineSp ?? scheme.lineSp, keepWord: false });
24214
+ const paraId = reg.para({ align: "LEFT", before: first ? lineHu(scheme.body) : 0, lineSp: st.lineSp ?? scheme.lineSp });
24063
24215
  const base = { font: st.font, pt: st.pt, bold: st.bold };
24064
24216
  return generateParagraph(text, paraId, reg.char(base), inlineMapper(reg, base));
24065
24217
  };
@@ -24229,6 +24381,13 @@ function buildGongmunSectionV5(blocks, gongmun, deps, theme) {
24229
24381
  scheme
24230
24382
  };
24231
24383
  }
24384
+ function polishNode(n) {
24385
+ if (n.kind === "block") {
24386
+ const b = n.block;
24387
+ return b.type === "table" && b.rows ? { ...n, block: { ...b, rows: b.rows.map((r) => r.map(polishGongmunText)) } } : n;
24388
+ }
24389
+ return { ...n, text: polishGongmunText(n.text) };
24390
+ }
24232
24391
  function legalDepthOf(marker) {
24233
24392
  if (/^\d{1,2}\.$/.test(marker)) return 0;
24234
24393
  if (/^[가-힣]\.$/.test(marker)) return 1;
@@ -24285,7 +24444,7 @@ async function markdownToHwpx(markdown, options) {
24285
24444
  }
24286
24445
  const measured = !!gongmun && usesReportFonts(gongmun.preset);
24287
24446
  const richAssets = !!gongmun && needsGaejosikAssets(gongmun);
24288
- const blocks = parseMarkdownToBlocks(md);
24447
+ const blocks = gongmun ? parseMarkdownToBlocks(md).map(polishGongmunBlock) : parseMarkdownToBlocks(md);
24289
24448
  const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
24290
24449
  const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
24291
24450
  const staticBfEnd = staticBorderFillNext(gongmun);
@@ -26367,7 +26526,8 @@ function patchParagraphUnit(block, orig, edited, ctx, skip) {
26367
26526
  if (sanitizeText(newPlain) !== newPlain) {
26368
26527
  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");
26369
26528
  }
26370
- const splices = buildParagraphSplices(mapping.para, newPlain, ctx.scans[mapping.para.sectionIndex]?.xml);
26529
+ const xml = ctx.scans[mapping.para.sectionIndex]?.xml;
26530
+ const splices = (xml ? markerRunSplices(mapping.para, xml, newPlain) : null) ?? buildParagraphSplices(mapping.para, newPlain, xml);
26371
26531
  if (splices === null) return skip("\uBB38\uB2E8\uC5D0 \uD14D\uC2A4\uD2B8 \uB178\uB4DC\uB97C \uB9CC\uB4E4 \uC218 \uC5C6\uC74C");
26372
26532
  ctx.sectionSplices[mapping.para.sectionIndex].push(...splices);
26373
26533
  return 1;
@@ -28055,6 +28215,9 @@ async function dispatch(format, buffer, opts) {
28055
28215
  const zipFormat = await detectZipFormat(buffer);
28056
28216
  if (zipFormat === "xlsx") return parseXlsx(buffer, opts);
28057
28217
  if (zipFormat === "docx") return parseDocx(buffer, opts);
28218
+ if (zipFormat === "pptx") {
28219
+ return { success: false, fileType: "pptx", error: "PPTX \uD30C\uC77C\uC740 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD\uC785\uB2C8\uB2E4.", code: "UNSUPPORTED_FORMAT" };
28220
+ }
28058
28221
  return parseHwpx(buffer, opts);
28059
28222
  }
28060
28223
  case "hwp": {
@@ -28076,7 +28239,7 @@ async function dispatch(format, buffer, opts) {
28076
28239
  }
28077
28240
  async function parseImage(buffer, options) {
28078
28241
  try {
28079
- const { parseImageDocument } = await import("./image-ocr-UAIVXZCE.js");
28242
+ const { parseImageDocument } = await import("./image-ocr-WCAYXLOA.js");
28080
28243
  const { blocks, warnings } = await parseImageDocument(buffer, options);
28081
28244
  return {
28082
28245
  success: true,
@@ -28135,7 +28298,7 @@ async function parseHwp(buffer, options) {
28135
28298
  async function parsePdf(buffer, options) {
28136
28299
  let parsePdfDocument;
28137
28300
  try {
28138
- const mod = await import("./parser-N5R2DFAN.js");
28301
+ const mod = await import("./parser-SCUTZAIJ.js");
28139
28302
  parsePdfDocument = mod.parsePdfDocument;
28140
28303
  } catch {
28141
28304
  return {
@@ -28345,4 +28508,4 @@ export {
28345
28508
  parseHwpml,
28346
28509
  fillForm
28347
28510
  };
28348
- //# sourceMappingURL=chunk-UDMYSLCM.js.map
28511
+ //# sourceMappingURL=chunk-EISO3POT.js.map