kordoc 4.12.2 → 4.12.3

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 (121) hide show
  1. package/README.md +12 -1
  2. package/dist/{-EZH6NKTE.js → -FWGDIOV4.js} +8 -8
  3. package/dist/{chunk-OEYECZGV.js → chunk-2DAFWDV2.js} +9 -5
  4. package/dist/chunk-2DAFWDV2.js.map +1 -0
  5. package/dist/{chunk-5RPYBC2Q.js → chunk-3KQOI6R6.js} +27 -2
  6. package/dist/chunk-3KQOI6R6.js.map +1 -0
  7. package/dist/{chunk-DBGEUDBY.js → chunk-6L3B44DH.js} +2 -2
  8. package/dist/{chunk-ONNAHSPV.cjs → chunk-7BIXTQZ3.cjs} +14 -10
  9. package/dist/chunk-7BIXTQZ3.cjs.map +1 -0
  10. package/dist/{chunk-IOJX4Q63.js → chunk-B63QEHYL.js} +3 -3
  11. package/dist/{chunk-JCMBQC5N.js → chunk-BAZMKQZW.js} +2 -2
  12. package/dist/{chunk-V5BUPZ6I.cjs → chunk-BOATAEXU.cjs} +7 -4
  13. package/dist/chunk-BOATAEXU.cjs.map +1 -0
  14. package/dist/{chunk-KX7IYCCZ.js → chunk-CKYDP34A.js} +3 -3
  15. package/dist/{chunk-7XUXSDH5.js → chunk-DUGUCM7K.js} +9 -5
  16. package/dist/chunk-DUGUCM7K.js.map +1 -0
  17. package/dist/{chunk-2LKYJ4G3.cjs → chunk-FFITS3NY.cjs} +6 -6
  18. package/dist/{chunk-2LKYJ4G3.cjs.map → chunk-FFITS3NY.cjs.map} +1 -1
  19. package/dist/{chunk-2B7OIEJJ.js → chunk-HB56YANA.js} +5 -2
  20. package/dist/chunk-HB56YANA.js.map +1 -0
  21. package/dist/{chunk-2HBYWA5X.js → chunk-IC6HHXFL.js} +2 -2
  22. package/dist/{chunk-LD2K4K5V.js → chunk-INFYDSZL.js} +111 -22
  23. package/dist/chunk-INFYDSZL.js.map +1 -0
  24. package/dist/{chunk-62IU4NV3.cjs → chunk-ISCI5LKN.cjs} +2 -2
  25. package/dist/{chunk-62IU4NV3.cjs.map → chunk-ISCI5LKN.cjs.map} +1 -1
  26. package/dist/{chunk-XXDZ2KTW.js → chunk-KLO6RHX2.js} +2 -2
  27. package/dist/{chunk-MUYU4JI5.js → chunk-KRE2SREV.js} +2 -2
  28. package/dist/{chunk-QBCMFNHS.js → chunk-OJDMMZ5Z.js} +2 -2
  29. package/dist/{chunk-UL2MDA5C.js → chunk-PL4V523B.js} +3 -3
  30. package/dist/{chunk-FBLMVHDK.js → chunk-PUZZFYLV.js} +2 -2
  31. package/dist/{chunk-2LO525TL.js → chunk-SJEPQOVW.js} +2 -2
  32. package/dist/{chunk-QM2RSJ2S.js → chunk-TWKXX343.js} +3 -3
  33. package/dist/{chunk-2LPBIW2B.cjs → chunk-W3H2H55O.cjs} +3 -3
  34. package/dist/{chunk-2LPBIW2B.cjs.map → chunk-W3H2H55O.cjs.map} +1 -1
  35. package/dist/{chunk-FVBR7SC3.js → chunk-YBZJMAE2.js} +2 -2
  36. package/dist/{chunk-Q6ETEJFK.js → chunk-ZASGH5EN.js} +5 -2
  37. package/dist/chunk-ZASGH5EN.js.map +1 -0
  38. package/dist/chunks-VICNQMNE.js +10 -0
  39. package/dist/cli.js +30 -23
  40. package/dist/cli.js.map +1 -1
  41. package/dist/{formula-NW33S4TA.js → formula-R7IWAAYR.js} +3 -3
  42. package/dist/{formula-6RQX4NMJ.js → formula-YJWKEPUK.js} +4 -4
  43. package/dist/{formula-NBEO6CFC.cjs → formula-ZYHUXTK5.cjs} +9 -9
  44. package/dist/{formula-NBEO6CFC.cjs.map → formula-ZYHUXTK5.cjs.map} +1 -1
  45. package/dist/{image-ocr-V4KY373B.cjs → image-ocr-6O6ZXKUD.cjs} +11 -11
  46. package/dist/{image-ocr-V4KY373B.cjs.map → image-ocr-6O6ZXKUD.cjs.map} +1 -1
  47. package/dist/{image-ocr-SO56VETS.js → image-ocr-G4JVF2UH.js} +7 -7
  48. package/dist/{image-ocr-CAVU2TNZ.js → image-ocr-OLTSKQWD.js} +5 -5
  49. package/dist/index.cjs +455 -366
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.d.cts +17 -0
  52. package/dist/index.d.ts +17 -0
  53. package/dist/index.js +107 -18
  54. package/dist/index.js.map +1 -1
  55. package/dist/mcp.js +20 -17
  56. package/dist/mcp.js.map +1 -1
  57. package/dist/{model-bundle-EIJF34DR.js → model-bundle-IFD2D5CW.js} +5 -5
  58. package/dist/{models-6V4CPQXC.js → models-FJ3IUNTB.js} +5 -5
  59. package/dist/{parser-OBHNXEQM.js → parser-I7TC35V6.js} +31 -10
  60. package/dist/parser-I7TC35V6.js.map +1 -0
  61. package/dist/{parser-GIREMEPD.js → parser-JRT3B6OK.js} +31 -10
  62. package/dist/parser-JRT3B6OK.js.map +1 -0
  63. package/dist/{parser-OMT25WH2.cjs → parser-YLLIYOIZ.cjs} +59 -38
  64. package/dist/parser-YLLIYOIZ.cjs.map +1 -0
  65. package/dist/pdf-ocr-ADUP2LPU.cjs +14 -0
  66. package/dist/{pdf-ocr-TFYVK4FI.cjs.map → pdf-ocr-ADUP2LPU.cjs.map} +1 -1
  67. package/dist/pdf-ocr-ATJTB2B3.js +13 -0
  68. package/dist/pdf-ocr-P75KSZFV.js +16 -0
  69. package/dist/{profile-io-PZVMM66V.js → profile-io-BPJQQZLQ.js} +3 -3
  70. package/dist/{rasterize-NRWP2C6L.js → rasterize-ALCNU53T.js} +2 -2
  71. package/dist/render-MDLTQUUV.js +10 -0
  72. package/dist/seal-K4K3KPE3.js +10 -0
  73. package/dist/{setup-V55AJP6H.js → setup-O2DALZKF.js} +3 -3
  74. package/dist/{watch-7CQSMDDP.js → watch-GPWYJAS2.js} +9 -9
  75. package/package.json +1 -1
  76. package/dist/chunk-2B7OIEJJ.js.map +0 -1
  77. package/dist/chunk-5RPYBC2Q.js.map +0 -1
  78. package/dist/chunk-7XUXSDH5.js.map +0 -1
  79. package/dist/chunk-LD2K4K5V.js.map +0 -1
  80. package/dist/chunk-OEYECZGV.js.map +0 -1
  81. package/dist/chunk-ONNAHSPV.cjs.map +0 -1
  82. package/dist/chunk-Q6ETEJFK.js.map +0 -1
  83. package/dist/chunk-V5BUPZ6I.cjs.map +0 -1
  84. package/dist/chunks-TT7ZE5QQ.js +0 -10
  85. package/dist/parser-GIREMEPD.js.map +0 -1
  86. package/dist/parser-OBHNXEQM.js.map +0 -1
  87. package/dist/parser-OMT25WH2.cjs.map +0 -1
  88. package/dist/pdf-ocr-IRXQ5GBM.js +0 -13
  89. package/dist/pdf-ocr-SL4GCOGS.js +0 -16
  90. package/dist/pdf-ocr-TFYVK4FI.cjs +0 -14
  91. package/dist/render-V5ZPTZQ7.js +0 -10
  92. package/dist/seal-LVG2DGAB.js +0 -10
  93. /package/dist/{-EZH6NKTE.js.map → -FWGDIOV4.js.map} +0 -0
  94. /package/dist/{chunk-DBGEUDBY.js.map → chunk-6L3B44DH.js.map} +0 -0
  95. /package/dist/{chunk-IOJX4Q63.js.map → chunk-B63QEHYL.js.map} +0 -0
  96. /package/dist/{chunk-JCMBQC5N.js.map → chunk-BAZMKQZW.js.map} +0 -0
  97. /package/dist/{chunk-KX7IYCCZ.js.map → chunk-CKYDP34A.js.map} +0 -0
  98. /package/dist/{chunk-2HBYWA5X.js.map → chunk-IC6HHXFL.js.map} +0 -0
  99. /package/dist/{chunk-XXDZ2KTW.js.map → chunk-KLO6RHX2.js.map} +0 -0
  100. /package/dist/{chunk-MUYU4JI5.js.map → chunk-KRE2SREV.js.map} +0 -0
  101. /package/dist/{chunk-QBCMFNHS.js.map → chunk-OJDMMZ5Z.js.map} +0 -0
  102. /package/dist/{chunk-UL2MDA5C.js.map → chunk-PL4V523B.js.map} +0 -0
  103. /package/dist/{chunk-FBLMVHDK.js.map → chunk-PUZZFYLV.js.map} +0 -0
  104. /package/dist/{chunk-2LO525TL.js.map → chunk-SJEPQOVW.js.map} +0 -0
  105. /package/dist/{chunk-QM2RSJ2S.js.map → chunk-TWKXX343.js.map} +0 -0
  106. /package/dist/{chunk-FVBR7SC3.js.map → chunk-YBZJMAE2.js.map} +0 -0
  107. /package/dist/{chunks-TT7ZE5QQ.js.map → chunks-VICNQMNE.js.map} +0 -0
  108. /package/dist/{formula-NW33S4TA.js.map → formula-R7IWAAYR.js.map} +0 -0
  109. /package/dist/{formula-6RQX4NMJ.js.map → formula-YJWKEPUK.js.map} +0 -0
  110. /package/dist/{image-ocr-SO56VETS.js.map → image-ocr-G4JVF2UH.js.map} +0 -0
  111. /package/dist/{image-ocr-CAVU2TNZ.js.map → image-ocr-OLTSKQWD.js.map} +0 -0
  112. /package/dist/{model-bundle-EIJF34DR.js.map → model-bundle-IFD2D5CW.js.map} +0 -0
  113. /package/dist/{models-6V4CPQXC.js.map → models-FJ3IUNTB.js.map} +0 -0
  114. /package/dist/{pdf-ocr-IRXQ5GBM.js.map → pdf-ocr-ATJTB2B3.js.map} +0 -0
  115. /package/dist/{pdf-ocr-SL4GCOGS.js.map → pdf-ocr-P75KSZFV.js.map} +0 -0
  116. /package/dist/{profile-io-PZVMM66V.js.map → profile-io-BPJQQZLQ.js.map} +0 -0
  117. /package/dist/{rasterize-NRWP2C6L.js.map → rasterize-ALCNU53T.js.map} +0 -0
  118. /package/dist/{render-V5ZPTZQ7.js.map → render-MDLTQUUV.js.map} +0 -0
  119. /package/dist/{seal-LVG2DGAB.js.map → seal-K4K3KPE3.js.map} +0 -0
  120. /package/dist/{setup-V55AJP6H.js.map → setup-O2DALZKF.js.map} +0 -0
  121. /package/dist/{watch-7CQSMDDP.js.map → watch-GPWYJAS2.js.map} +0 -0
@@ -22,7 +22,7 @@ import {
22
22
  paraTextPureT,
23
23
  patchZipEntries,
24
24
  scanSectionXml
25
- } from "./chunk-KX7IYCCZ.js";
25
+ } from "./chunk-CKYDP34A.js";
26
26
  import {
27
27
  MAX_COLS,
28
28
  MAX_ROWS,
@@ -32,14 +32,14 @@ import {
32
32
  dedupeRunningHeaders,
33
33
  flattenLayoutTables,
34
34
  mapPuaText
35
- } from "./chunk-Q6ETEJFK.js";
35
+ } from "./chunk-ZASGH5EN.js";
36
36
  import {
37
37
  SPACE_EM_FIXED,
38
38
  charWidthEm1000,
39
39
  fitRatioForFewerLines,
40
40
  measureTextWidth,
41
41
  simulateWrap
42
- } from "./chunk-IOJX4Q63.js";
42
+ } from "./chunk-B63QEHYL.js";
43
43
  import {
44
44
  MAX_DECOMPRESS_SIZE,
45
45
  MAX_XML_DEPTH,
@@ -55,7 +55,7 @@ import {
55
55
  findChildByLocalName,
56
56
  localName,
57
57
  rawTextContent
58
- } from "./chunk-FVBR7SC3.js";
58
+ } from "./chunk-YBZJMAE2.js";
59
59
  import {
60
60
  KordocError,
61
61
  classifyError,
@@ -67,7 +67,7 @@ import {
67
67
  sanitizeHref,
68
68
  stripDtd,
69
69
  toArrayBuffer
70
- } from "./chunk-FBLMVHDK.js";
70
+ } from "./chunk-PUZZFYLV.js";
71
71
 
72
72
  // src/index.ts
73
73
  import { readFile } from "fs/promises";
@@ -2717,8 +2717,9 @@ function appendParaText(state, data, resolveControl) {
2717
2717
  case CHAR_PARA:
2718
2718
  break;
2719
2719
  // 문단 끝
2720
+ // 하이픈(24)은 한컴이 그리지 않는다 — 한컴 PDF·rhwp export-hwpx 모두 "60g/㎡"(licbyl2 17855137,
2721
+ // 전 코퍼스 유일 출현). 실렌더가 진실이므로 방출하지 않는다 (v4.12.3, 종전 "-")
2720
2722
  case CHAR_HYPHEN:
2721
- result += "-";
2722
2723
  break;
2723
2724
  case CHAR_NBSP:
2724
2725
  result += "\xA0";
@@ -22036,6 +22037,36 @@ function validateGongmunOptions(opts) {
22036
22037
  if (opts.approval && opts.approval.length > 6) {
22037
22038
  throw new KordocError("approval must contain at most 6 labels");
22038
22039
  }
22040
+ if (opts.levels) {
22041
+ for (const [key, st] of Object.entries(opts.levels)) {
22042
+ const depth = Number(key);
22043
+ if (!Number.isInteger(depth) || depth < 0 || depth >= GONGMUN_LEVEL_COUNT) {
22044
+ throw new KordocError(`levels: depth must be an integer between 0 and ${GONGMUN_LEVEL_COUNT - 1} (got "${key}")`);
22045
+ }
22046
+ if (!st || typeof st !== "object") throw new KordocError(`levels.${key} must be an object {font, pt, bold}`);
22047
+ if (st.pt !== void 0) assertFiniteRange(`levels.${key}.pt`, st.pt, 6, 60);
22048
+ if (st.font !== void 0 && (typeof st.font !== "string" || !st.font.trim())) {
22049
+ throw new KordocError(`levels.${key}.font must be a non-empty string`);
22050
+ }
22051
+ }
22052
+ }
22053
+ }
22054
+ var GONGMUN_LEVEL_COUNT = 8;
22055
+ function resolveLevels(levels, bodyHeight) {
22056
+ if (!levels) return null;
22057
+ const out = {};
22058
+ for (const [key, st] of Object.entries(levels)) {
22059
+ if (st.font === void 0 && st.pt === void 0 && st.bold === void 0) continue;
22060
+ out[Number(key)] = {
22061
+ font: st.font?.trim() || null,
22062
+ height: st.pt !== void 0 ? Math.round(st.pt * 100) : bodyHeight,
22063
+ bold: !!st.bold
22064
+ };
22065
+ }
22066
+ return Object.keys(out).length > 0 ? out : null;
22067
+ }
22068
+ function levelMarkerHeight(g, depth) {
22069
+ return g.levels?.[depth]?.height ?? g.bodyHeight;
22039
22070
  }
22040
22071
  function incompatibleGongmunWarnings(opts) {
22041
22072
  const warns = [];
@@ -22080,6 +22111,7 @@ function resolveGongmun(opts) {
22080
22111
  toc: preset !== "press" && (opts.toc ?? gaejosik),
22081
22112
  fonts: opts.fonts ?? {},
22082
22113
  sizes: opts.sizes ?? {},
22114
+ levels: resolveLevels(opts.levels, Math.round(bodyPt * 100)),
22083
22115
  // 쪽번호 — 보고서 계열 관행(실측: 2_보고서 양식·추진계획·공고문 전부 하단 중앙)
22084
22116
  pageNumbers: opts.pageNumbers ?? (gaejosik || preset === "report" || preset === "plan"),
22085
22117
  // 머리말·꼬리말 — 실측: 보고서 계열 15mm(GT3·t2·춘천·브라더), 공고·보도 10mm,
@@ -22138,10 +22170,10 @@ function markerWidth(marker, bodyHeight) {
22138
22170
  for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
22139
22171
  return Math.round(em / 1e3 * bodyHeight);
22140
22172
  }
22141
- function levelIndent(depth, bodyHeight, numbering, sizes = {}, bullet2 = "\u25CB", asteriskThird = false) {
22173
+ function levelIndent(depth, bodyHeight, numbering, sizes = {}, bullet2 = "\u25CB", asteriskThird = false, markerHeight = bodyHeight) {
22142
22174
  if (numbering === "gaejosik") return gaejosikLevelIndent(depth, bodyHeight, sizes, bullet2);
22143
22175
  const marker = numbering === "report" ? reportMarker(depth, bullet2, asteriskThird) : standardMarker(depth, 0);
22144
- return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, bodyHeight) };
22176
+ return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, markerHeight) };
22145
22177
  }
22146
22178
  function computeSuppression(depths) {
22147
22179
  const counts = /* @__PURE__ */ new Map();
@@ -22234,13 +22266,13 @@ function headingCharPrId(level) {
22234
22266
  if (level === 3) return CHAR_H3;
22235
22267
  return CHAR_H4;
22236
22268
  }
22237
- function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100) {
22269
+ function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100, restFont = fontId) {
22238
22270
  const boldAttr = bold ? ` bold="1"` : "";
22239
22271
  const italicAttr = italic ? ` italic="1"` : "";
22240
22272
  const effFont = fontId;
22241
22273
  const boldEl = bold ? `<hh:bold/>` : "";
22242
22274
  return ` <hh:charPr id="${id}" height="${height}" textColor="${escapeXml(textColor)}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
22243
- <hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
22275
+ <hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${restFont}" japanese="${restFont}" other="${restFont}" symbol="${restFont}" user="${restFont}"/>
22244
22276
  <hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
22245
22277
  <hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
22246
22278
  <hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
@@ -22956,7 +22988,7 @@ ${base2.join("\n")}
22956
22988
  ];
22957
22989
  const listAlign = gongmun.numbering === "gaejosik" || gongmun.numbering === "report" ? "LEFT" : "JUSTIFY";
22958
22990
  for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
22959
- const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, usesAsteriskThird(gongmun.preset));
22991
+ const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, usesAsteriskThird(gongmun.preset), levelMarkerHeight(gongmun, d));
22960
22992
  const sectionGap = gongmun.numbering === "gaejosik" || gongmun.numbering === "report" ? gaejosikSpaceBefore(d, gongmun.bodyHeight) : 0;
22961
22993
  const keepNext = (gongmun.numbering === "gaejosik" || gongmun.numbering === "report") && d === 0;
22962
22994
  base.push(paraPr(GONGMUN_LIST_BASE + d, { align: listAlign, lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext }));
@@ -23385,6 +23417,7 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
23385
23417
  if (block.type === "list_item" && gongmunList.items.has(i)) {
23386
23418
  const { marker, depth, indentVariant } = gongmunList.items.get(i);
23387
23419
  if (gongmun.numbering === "gaejosik" && (depth === 0 || (block.text || "").trimStart().startsWith("\u203B"))) continue;
23420
+ if (gongmun.levels?.[depth]) continue;
23388
23421
  const content = plainRenderText(block.text || "");
23389
23422
  text = marker ? `${marker} ${content}` : content;
23390
23423
  const li = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, usesAsteriskThird(gongmun.preset));
@@ -23450,8 +23483,9 @@ function precomputeGongmunList(blocks, gongmun) {
23450
23483
  const variantIdx = /* @__PURE__ */ new Map();
23451
23484
  const variantOf = (marker, depth) => {
23452
23485
  if (!marker || gongmun.numbering !== "standard") return void 0;
23453
- const w = markerWidth(marker, gongmun.bodyHeight);
23454
- const rep = -levelIndent(depth, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, usesAsteriskThird(gongmun.preset)).indent;
23486
+ const h = levelMarkerHeight(gongmun, depth);
23487
+ const w = markerWidth(marker, h);
23488
+ const rep = -levelIndent(depth, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, usesAsteriskThird(gongmun.preset), h).indent;
23455
23489
  if (w === rep) return void 0;
23456
23490
  const key = `${depth}:${w}`;
23457
23491
  let vi = variantIdx.get(key);
@@ -25630,6 +25664,11 @@ function renderListItem(block, blockIdx, ctx) {
25630
25664
  mapId = void 0;
25631
25665
  }
25632
25666
  }
25667
+ const lv = ctx.levelIds?.[depth];
25668
+ if (lv) {
25669
+ listCharPr = lv.normal;
25670
+ mapId = (id) => id === CHAR_BOLD ? lv.bold : id === CHAR_NORMAL ? lv.normal : id;
25671
+ }
25633
25672
  return generateParagraph(text, listParaPr, listCharPr, mapId);
25634
25673
  }
25635
25674
  const indent = block.indent || 0;
@@ -25690,7 +25729,7 @@ function appendPostamble(blocks, ctx) {
25690
25729
  paraXmls.push(...buildPressContact(gongmun, dfIds, tableStyle.totalWidth, bfReg));
25691
25730
  }
25692
25731
  }
25693
- function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null, dfIds = null, images = null, page = null) {
25732
+ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null, dfIds = null, images = null, page = null, levelIds = null) {
25694
25733
  resetTableIds();
25695
25734
  resetGjTableIds();
25696
25735
  resetExtraTableIds();
@@ -25706,6 +25745,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
25706
25745
  remap,
25707
25746
  dfIds,
25708
25747
  images,
25748
+ levelIds,
25709
25749
  gaejosik: gongmun?.preset === "gaejosik",
25710
25750
  measured,
25711
25751
  richAssets,
@@ -25810,6 +25850,41 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
25810
25850
  </hs:sec>`;
25811
25851
  }
25812
25852
 
25853
+ // src/hwpx/gen-levels.ts
25854
+ function levelDepths(g) {
25855
+ return g.levels ? Object.keys(g.levels).map(Number).sort((a, b) => a - b) : [];
25856
+ }
25857
+ function levelFontFaces(g) {
25858
+ const out = [];
25859
+ for (const d of levelDepths(g)) {
25860
+ const f = g.levels[d].font;
25861
+ if (f && !out.includes(f)) out.push(f);
25862
+ }
25863
+ return out;
25864
+ }
25865
+ function levelCharIds(g, base) {
25866
+ const depths = levelDepths(g);
25867
+ if (depths.length === 0) return null;
25868
+ const ids = {};
25869
+ depths.forEach((d, i) => {
25870
+ ids[d] = { normal: base + i * 2, bold: base + i * 2 + 1 };
25871
+ });
25872
+ return ids;
25873
+ }
25874
+ function levelCharPrXmls(g, base, fontBase, bodyFontId) {
25875
+ const ids = levelCharIds(g, base);
25876
+ if (!ids) return [];
25877
+ const faces = levelFontFaces(g);
25878
+ const out = [];
25879
+ for (const d of levelDepths(g)) {
25880
+ const st = g.levels[d];
25881
+ const fontId = st.font ? fontBase + faces.indexOf(st.font) : bodyFontId;
25882
+ out.push(charPr(ids[d].normal, st.height, st.bold, false, fontId, void 0, GONGMUN_BODY_RATIO, bodyFontId));
25883
+ out.push(charPr(ids[d].bold, st.height, true, false, fontId, void 0, GONGMUN_BODY_RATIO, bodyFontId));
25884
+ }
25885
+ return out;
25886
+ }
25887
+
25813
25888
  // src/hwpx/generator.ts
25814
25889
  async function markdownToHwpx(markdown, options) {
25815
25890
  const theme = resolveTheme(options?.theme);
@@ -25829,10 +25904,15 @@ async function markdownToHwpx(markdown, options) {
25829
25904
  const dfActive = !!gongmun && docframeActive(gongmun);
25830
25905
  const dfBase = charVariantBase(richAssets, !!gongmun) + (fit?.variants?.length ?? 0) * 4 + (remap?.charPrXmls.length ?? 0);
25831
25906
  const dfIds = dfActive ? docframeIds(dfBase) : null;
25907
+ const dfXmls = dfActive ? docframeCharPrXmls(dfBase, richAssets) : [];
25908
+ const lvBase = dfBase + dfXmls.length;
25909
+ const lvIds = gongmun ? levelCharIds(gongmun, lvBase) : null;
25910
+ const lvFonts = gongmun ? levelFontFaces(gongmun) : [];
25911
+ const lvXmls = gongmun ? levelCharPrXmls(gongmun, lvBase, staticFontNext(gongmun) + (remap?.fontFaces.length ?? 0), richAssets ? 4 : 0) : [];
25832
25912
  const chartParts = [];
25833
25913
  const supplied = options?.images ? new Map(Object.entries(options.images).map(([k, v]) => [k, v instanceof Uint8Array ? v : new Uint8Array(v)])) : void 0;
25834
25914
  const images = new ImageRegistry(supplied);
25835
- const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap, dfIds, images, page);
25915
+ const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap, dfIds, images, page, lvIds);
25836
25916
  if (remap && remap.tables.length > 0) {
25837
25917
  const unused = remap.tables.filter((t) => !t.used).length;
25838
25918
  if (unused === remap.tables.length) {
@@ -25850,9 +25930,9 @@ async function markdownToHwpx(markdown, options) {
25850
25930
  gongmun,
25851
25931
  fit?.variants ?? [],
25852
25932
  extraBorderFills,
25853
- [...remap?.charPrXmls ?? [], ...dfActive ? docframeCharPrXmls(dfBase, richAssets) : []],
25933
+ [...remap?.charPrXmls ?? [], ...dfXmls, ...lvXmls],
25854
25934
  gongmunList?.indentVariants ?? [],
25855
- remap?.fontFaces ?? []
25935
+ [...remap?.fontFaces ?? [], ...lvFonts]
25856
25936
  ));
25857
25937
  zip.file("Contents/section0.xml", sectionXml);
25858
25938
  for (const part of chartParts) zip.file(part.name, part.xml);
@@ -26505,10 +26585,12 @@ var DISCRIM_FIXES = [
26505
26585
  var DISCRIM_RE = new RegExp(DISCRIM_FIXES.map(([w]) => w).sort((a, b) => b.length - a.length).join("|"), "g");
26506
26586
  var RULES = [
26507
26587
  // 날짜 ─ 온점 뒤 한 칸, 0 패딩 금지, 연도 4자리, 끝 마침표
26588
+ // 법령 연혁 표기 `<개정 2012.2.14>`·`삭제 <2016.2.29.>`·`[시행일:2017.9.8.]` 는 법제처 정본 형식(별지서식 표제) —
26589
+ // 편람 날짜 규칙 대상이 아니다 (v4.12.3: 서식 595건 DATE 156건 전부 이 꼴, 기안문 0건)
26508
26590
  {
26509
26591
  code: "DATE_NO_SPACE",
26510
26592
  severity: "error",
26511
- pattern: /\b\d{4}\.\d{1,2}\.\d{1,2}\.?/g,
26593
+ pattern: /(?<!<(?:개정|신설|전문개정|전부개정|일부개정|제정)\s*)(?<!삭제\s*<)(?<!시행일\s*:\s*)\b\d{4}\.\d{1,2}\.\d{1,2}\.?/g,
26512
26594
  message: "\uB0A0\uC9DC \uC628\uC810 \uB4A4\uC5D0 \uD55C \uCE78\uC529 \uB744\uC6CC\uC57C \uD568",
26513
26595
  suggest: "\uC608) 2025. 1. 6."
26514
26596
  },
@@ -26594,10 +26676,15 @@ var RULES = [
26594
26676
  suggest: "\uC608) \uC5C5\uBB34 \uD611\uC57D(MOU)"
26595
26677
  },
26596
26678
  // 쌍점 — URL(https:// 등)·시각(13:20)은 제외
26679
+ // 편람: 쌍점은 앞말에 붙이고 뒤는 1타(원장: 김갑동). 표 셀은 제외(skipTable) — 법정 별지서식
26680
+ // 자체가 "성 명 :"·"주 소 :" 라벨 셀을 쓰므로 서식 라벨은 이 규칙의 대상이 아니다(v4.12.3 실측:
26681
+ // 서식 595건의 표 셀 801건 전부 라벨, 기안문 206건은 본문 414건이 "일 시 : 값" 꼴 — 편람상 위반).
26682
+ // 뒤 글자에서 `<`(HTML 태그)·`*`·`_`(마크다운 강조 닫힘)는 제외 — "성명:</td>"·"과정:** 붙임" 오탐
26597
26683
  {
26598
26684
  code: "COLON_SPACE",
26599
26685
  severity: "warning",
26600
- pattern: /\S\s+:(?!\/\/)|\S:(?!\/\/)[^\s\d]/g,
26686
+ skipTable: true,
26687
+ pattern: /\S\s+:(?!\/\/)|\S:(?!\/\/)[^\s\d<*_]/g,
26601
26688
  message: "\uC30D\uC810\uC740 \uC55E\uB9D0\uC5D0 \uBD99\uC774\uACE0 \uB4A4\uB294 \uD55C \uCE78 \uB744\uC6C0",
26602
26689
  suggest: "\uC608) \uC6D0\uC7A5: \uAE40\uAC11\uB3D9"
26603
26690
  },
@@ -26677,7 +26764,9 @@ function lintGongmunText(text, opts) {
26677
26764
  continue;
26678
26765
  }
26679
26766
  if (fenceMarker !== null) continue;
26767
+ const tableLine = /^\s*\|/.test(line) || /<t[dhr][\s>]/i.test(line);
26680
26768
  for (const r of RULES) {
26769
+ if (r.skipTable && tableLine) continue;
26681
26770
  r.pattern.lastIndex = 0;
26682
26771
  for (const m of line.matchAll(r.pattern)) {
26683
26772
  findings.push({
@@ -29731,7 +29820,7 @@ async function dispatch(format, buffer, opts) {
29731
29820
  }
29732
29821
  async function parseImage(buffer, options) {
29733
29822
  try {
29734
- const { parseImageDocument } = await import("./image-ocr-SO56VETS.js");
29823
+ const { parseImageDocument } = await import("./image-ocr-G4JVF2UH.js");
29735
29824
  const { blocks, warnings } = await parseImageDocument(buffer, options);
29736
29825
  return {
29737
29826
  success: true,
@@ -29790,7 +29879,7 @@ async function parseHwp(buffer, options) {
29790
29879
  async function parsePdf(buffer, options) {
29791
29880
  let parsePdfDocument;
29792
29881
  try {
29793
- const mod = await import("./parser-OBHNXEQM.js");
29882
+ const mod = await import("./parser-I7TC35V6.js");
29794
29883
  parsePdfDocument = mod.parsePdfDocument;
29795
29884
  } catch {
29796
29885
  return {
@@ -29941,4 +30030,4 @@ export {
29941
30030
  parseHwpml,
29942
30031
  fillForm
29943
30032
  };
29944
- //# sourceMappingURL=chunk-LD2K4K5V.js.map
30033
+ //# sourceMappingURL=chunk-INFYDSZL.js.map