kordoc 4.0.1 → 4.0.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 (44) hide show
  1. package/dist/{-O3AWNVPH.js → -XMKVL3NX.js} +7 -7
  2. package/dist/{chunk-3H3CVOZ3.js → chunk-3IYQYBUF.js} +2 -2
  3. package/dist/{chunk-JMLK6NTW.js → chunk-67RANGFQ.js} +3 -3
  4. package/dist/{chunk-C5ABJ7PB.js → chunk-6SD4X5PT.js} +3 -3
  5. package/dist/{chunk-33OUI7HC.js → chunk-6YIYFWO2.js} +2 -2
  6. package/dist/{chunk-SHVV3BD6.js → chunk-AHWRAGXN.js} +299 -71
  7. package/dist/chunk-AHWRAGXN.js.map +1 -0
  8. package/dist/{chunk-YEC7VG6O.js → chunk-IKBIIEVJ.js} +2 -2
  9. package/dist/{chunk-EH2KYFFO.js → chunk-STMLZDKR.js} +2 -2
  10. package/dist/{chunk-NIZXIVEI.cjs → chunk-WN7LZHII.cjs} +2 -2
  11. package/dist/{chunk-NIZXIVEI.cjs.map → chunk-WN7LZHII.cjs.map} +1 -1
  12. package/dist/cli.js +36 -14
  13. package/dist/cli.js.map +1 -1
  14. package/dist/index.cjs +552 -324
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +56 -3
  17. package/dist/index.d.ts +56 -3
  18. package/dist/index.js +294 -66
  19. package/dist/index.js.map +1 -1
  20. package/dist/mcp.js +53 -11
  21. package/dist/mcp.js.map +1 -1
  22. package/dist/{parser-G433UZMX.js → parser-2Q2YKEJG.js} +2 -2
  23. package/dist/{parser-ZOMDHCA7.js → parser-3HM2VYKK.js} +3 -3
  24. package/dist/{parser-44OPXZMP.cjs → parser-6AYYGX6J.cjs} +14 -14
  25. package/dist/{parser-44OPXZMP.cjs.map → parser-6AYYGX6J.cjs.map} +1 -1
  26. package/dist/render-W4VCJE6N.js +10 -0
  27. package/dist/seal-DRPTNHOP.js +10 -0
  28. package/dist/{watch-UYT3ZCBM.js → watch-6OHF727O.js} +7 -7
  29. package/package.json +1 -1
  30. package/dist/chunk-SHVV3BD6.js.map +0 -1
  31. package/dist/render-SQVQBORJ.js +0 -10
  32. package/dist/seal-6E26L45Z.js +0 -10
  33. /package/dist/{-O3AWNVPH.js.map → -XMKVL3NX.js.map} +0 -0
  34. /package/dist/{chunk-3H3CVOZ3.js.map → chunk-3IYQYBUF.js.map} +0 -0
  35. /package/dist/{chunk-JMLK6NTW.js.map → chunk-67RANGFQ.js.map} +0 -0
  36. /package/dist/{chunk-C5ABJ7PB.js.map → chunk-6SD4X5PT.js.map} +0 -0
  37. /package/dist/{chunk-33OUI7HC.js.map → chunk-6YIYFWO2.js.map} +0 -0
  38. /package/dist/{chunk-YEC7VG6O.js.map → chunk-IKBIIEVJ.js.map} +0 -0
  39. /package/dist/{chunk-EH2KYFFO.js.map → chunk-STMLZDKR.js.map} +0 -0
  40. /package/dist/{parser-G433UZMX.js.map → parser-2Q2YKEJG.js.map} +0 -0
  41. /package/dist/{parser-ZOMDHCA7.js.map → parser-3HM2VYKK.js.map} +0 -0
  42. /package/dist/{render-SQVQBORJ.js.map → render-W4VCJE6N.js.map} +0 -0
  43. /package/dist/{seal-6E26L45Z.js.map → seal-DRPTNHOP.js.map} +0 -0
  44. /package/dist/{watch-UYT3ZCBM.js.map → watch-6OHF727O.js.map} +0 -0
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  sanitizeHref,
21
21
  stripDtd,
22
22
  toArrayBuffer
23
- } from "./chunk-3H3CVOZ3.js";
23
+ } from "./chunk-3IYQYBUF.js";
24
24
  import {
25
25
  parsePageRange
26
26
  } from "./chunk-GE43BE46.js";
@@ -20951,7 +20951,8 @@ function fitRatioForFewerLines(text, firstWidth, contWidth, height, baseRatio, m
20951
20951
 
20952
20952
  // src/hwpx/gaejosik.ts
20953
20953
  var GAEJOSIK_BULLETS = ["\u25A1", "\u25CB", "-", "\u318D"];
20954
- function gaejosikMarker(depth) {
20954
+ function gaejosikMarker(depth, bullet2 = "\u25CB") {
20955
+ if (depth === 1) return bullet2;
20955
20956
  return GAEJOSIK_BULLETS[Math.min(depth, GAEJOSIK_BULLETS.length - 1)];
20956
20957
  }
20957
20958
  function gaejosikSizes(bodyHeight, ov = {}) {
@@ -20987,11 +20988,11 @@ function gaejosikSpaceBefore(depth, bodyHeight) {
20987
20988
  const ui = [3e3, 2e3, 1200, 600][Math.min(depth, 3)];
20988
20989
  return Math.round(ui * s);
20989
20990
  }
20990
- function gaejosikLevelIndent(depth, bodyHeight, sizes = {}) {
20991
+ function gaejosikLevelIndent(depth, bodyHeight, sizes = {}, bullet2 = "\u25CB") {
20991
20992
  const lefts = [0, 1, 1.5, 2];
20992
20993
  const left = depth <= 3 ? Math.round(lefts[depth] * bodyHeight) : Math.round((2 + (depth - 3) * 0.5) * bodyHeight);
20993
20994
  const h = depth === 0 ? gaejosikSizes(bodyHeight, sizes).dae : bodyHeight;
20994
- return { left, indent: -markerWidth(gaejosikMarker(depth), h) };
20995
+ return { left, indent: -markerWidth(gaejosikMarker(depth, bullet2), h) };
20995
20996
  }
20996
20997
  function gaejosikChamIndent(bodyHeight, sizes = {}) {
20997
20998
  const cham = gaejosikSizes(bodyHeight, sizes).cham;
@@ -21059,7 +21060,7 @@ function bodyTitleGeom(bodyHeight, ov = {}) {
21059
21060
  }
21060
21061
 
21061
21062
  // src/hwpx/gongmun.ts
21062
- var OFFICIAL_MARGINS = { top: 20, bottom: 10, left: 20, right: 20 };
21063
+ var OFFICIAL_MARGINS = { top: 20, bottom: 15, left: 20, right: 15 };
21063
21064
  var GAEJOSIK_MARGINS = { top: 15, bottom: 15, left: 20, right: 20 };
21064
21065
  var GAEJOSIK_HEADER_FOOTER = 4251;
21065
21066
  var PRESET_DEFAULTS = {
@@ -21068,7 +21069,9 @@ var PRESET_DEFAULTS = {
21068
21069
  plan: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
21069
21070
  notice: { bodyPt: 15, lineSpacing: 160, numbering: "standard" },
21070
21071
  minutes: { bodyPt: 14, lineSpacing: 130, numbering: "standard" },
21071
- gaejosik: { bodyPt: 15, lineSpacing: 160, numbering: "gaejosik" }
21072
+ gaejosik: { bodyPt: 15, lineSpacing: 160, numbering: "gaejosik" },
21073
+ // 보도자료 — 실측(국토부 실물): 본문 바탕 14pt 160%, □→ㅇ→*(각주) 부호
21074
+ press: { bodyPt: 14, lineSpacing: 160, numbering: "report" }
21072
21075
  };
21073
21076
  var PRESET_ALIAS = {
21074
21077
  official: "official",
@@ -21091,7 +21094,9 @@ var PRESET_ALIAS = {
21091
21094
  \uAC1C\uC870\uC2DD: "gaejosik",
21092
21095
  \uAC1C\uC870\uC2DD\uBCF4\uACE0\uC11C: "gaejosik",
21093
21096
  \uC815\uBD80\uBCF4\uACE0\uC11C: "gaejosik",
21094
- \uC815\uBD80\uD45C\uC900\uAC1C\uC870\uC2DD\uBCF4\uACE0\uC11C: "gaejosik"
21097
+ \uC815\uBD80\uD45C\uC900\uAC1C\uC870\uC2DD\uBCF4\uACE0\uC11C: "gaejosik",
21098
+ press: "press",
21099
+ \uBCF4\uB3C4\uC790\uB8CC: "press"
21095
21100
  };
21096
21101
  function normalizeGongmunPreset(preset) {
21097
21102
  if (!preset) return "official";
@@ -21108,13 +21113,14 @@ function resolveGongmun(opts) {
21108
21113
  const coverOn = opts.cover !== void 0 ? opts.cover !== false : preset === "gaejosik";
21109
21114
  const coverOpts = typeof opts.cover === "object" ? opts.cover : {};
21110
21115
  const gaejosik = preset === "gaejosik";
21116
+ const reportFamily = gaejosik || preset === "report" || preset === "plan" || preset === "notice" || preset === "press";
21111
21117
  return {
21112
21118
  preset,
21113
21119
  bodyFont: opts.bodyFont ?? "myeongjo",
21114
21120
  bodyHeight: Math.round(bodyPt * 100),
21115
21121
  lineSpacing: opts.lineSpacing ?? d.lineSpacing,
21116
21122
  numbering: opts.numbering ?? d.numbering,
21117
- margins: opts.margins ?? (gaejosik ? GAEJOSIK_MARGINS : OFFICIAL_MARGINS),
21123
+ margins: opts.margins ?? (reportFamily ? GAEJOSIK_MARGINS : OFFICIAL_MARGINS),
21118
21124
  centerTitle: opts.centerTitle ?? true,
21119
21125
  autoFitMinRatio,
21120
21126
  cover: coverOn ? { date: coverOpts.date ?? null, org: coverOpts.org ?? "" } : null,
@@ -21123,14 +21129,26 @@ function resolveGongmun(opts) {
21123
21129
  sizes: opts.sizes ?? {},
21124
21130
  // 쪽번호 — 보고서 계열 관행(실측: 2_보고서 양식·추진계획·공고문 전부 하단 중앙)
21125
21131
  pageNumbers: opts.pageNumbers ?? (gaejosik || preset === "report" || preset === "plan"),
21126
- headerFooter: gaejosik ? GAEJOSIK_HEADER_FOOTER : 0,
21132
+ // 머리말·꼬리말 실측: 보고서 계열 15mm(GT3·t2·춘천·브라더), 공고·보도 10mm,
21133
+ // 기안문 0(실결재 41/60건 h0/f0)
21134
+ headerFooter: usesReportFonts(preset) ? GAEJOSIK_HEADER_FOOTER : preset === "notice" || preset === "press" ? 2835 : 0,
21127
21135
  // "끝." — 기안문 규정(본문 끝 2타+"끝."). 그 외는 opt-in
21128
21136
  endMark: opts.endMark ?? preset === "official",
21129
21137
  approval: opts.approval && opts.approval.length > 0 ? opts.approval : null,
21130
21138
  // 본문 제목박스 — 실측(GT3·GT12): 목차 뒤 본문 시작에 제목 반복. 표지 켜진 개조식 기본
21131
21139
  bodyTitleBox: opts.bodyTitleBox ?? (gaejosik && coverOn),
21132
- // h2 말머리 — 실측 보고서 양식(부처별 3종)의 섹션 제목이 곧 □ 대항목 (QA-2)
21133
- h2Marker: opts.h2Marker ?? (preset === "report" || preset === "plan" ? "box" : "none")
21140
+ // h2 말머리 — 실측: 보고서 양식 □ 대항목(QA-2), 공고문 아라비아("1. 사업개요", 바이오헬스 실측)
21141
+ h2Marker: opts.h2Marker ?? (preset === "report" || preset === "plan" ? "box" : preset === "notice" ? "number" : "none"),
21142
+ // 2단계 부호 — 실결재 기안문·공고문 ㅇ 지배(60건 중 ㅇ134:○5), 보고서 양식 계열 ○
21143
+ bullet2: opts.bullet2 ?? (preset === "notice" || preset === "press" ? "\u3147" : "\u25CB"),
21144
+ // 단일 형제 부호 생략 — 규정이지만 부호 없는 계단이 실무 눈에 어색 (실무자 QA)
21145
+ suppressSingle: opts.suppressSingle ?? false,
21146
+ docHead: preset === "official" && opts.docHead ? opts.docHead : null,
21147
+ docFoot: preset === "official" && opts.docFoot ? opts.docFoot : null,
21148
+ reportInfo: opts.reportInfo?.trim() || null,
21149
+ noticeHead: preset === "notice" && opts.noticeHead ? opts.noticeHead : null,
21150
+ // 보도자료 머리박스는 프리셋 자체가 요구 — 옵션 미지정이어도 빈 객체
21151
+ press: preset === "press" ? opts.press ?? {} : null
21134
21152
  };
21135
21153
  }
21136
21154
  var HANGUL_INITIALS = [0, 2, 3, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18];
@@ -21148,6 +21166,7 @@ function circledHangul(n) {
21148
21166
  return String.fromCodePoint(12910 + n % 14);
21149
21167
  }
21150
21168
  var REPORT_BULLETS = ["\u25A1", "\u25CB", "-", "\u318D"];
21169
+ var PRESS_BULLETS = ["\u25A1", "\u3147", "*", "\u318D"];
21151
21170
  function standardMarker(depth, n) {
21152
21171
  switch (depth) {
21153
21172
  case 0:
@@ -21170,17 +21189,19 @@ function standardMarker(depth, n) {
21170
21189
  return circledHangul(n);
21171
21190
  }
21172
21191
  }
21173
- function reportMarker(depth) {
21174
- return REPORT_BULLETS[Math.min(depth, REPORT_BULLETS.length - 1)];
21192
+ function reportMarker(depth, bullet2 = "\u25CB", press = false) {
21193
+ const bullets = press ? PRESS_BULLETS : REPORT_BULLETS;
21194
+ const m = bullets[Math.min(depth, bullets.length - 1)];
21195
+ return depth === 1 && !press ? bullet2 : m;
21175
21196
  }
21176
21197
  function markerWidth(marker, bodyHeight) {
21177
21198
  let em = SPACE_EM_FIXED;
21178
21199
  for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
21179
21200
  return Math.round(em / 1e3 * bodyHeight);
21180
21201
  }
21181
- function levelIndent(depth, bodyHeight, numbering, sizes = {}) {
21182
- if (numbering === "gaejosik") return gaejosikLevelIndent(depth, bodyHeight, sizes);
21183
- const marker = numbering === "report" ? reportMarker(depth) : standardMarker(depth, 0);
21202
+ function levelIndent(depth, bodyHeight, numbering, sizes = {}, bullet2 = "\u25CB", press = false) {
21203
+ if (numbering === "gaejosik") return gaejosikLevelIndent(depth, bodyHeight, sizes, bullet2);
21204
+ const marker = numbering === "report" ? reportMarker(depth, bullet2, press) : standardMarker(depth, 0);
21184
21205
  return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, bodyHeight) };
21185
21206
  }
21186
21207
  function computeSuppression(depths) {
@@ -21197,8 +21218,10 @@ function computeSuppression(depths) {
21197
21218
  return keys.map((k) => (counts.get(k) ?? 0) <= 1);
21198
21219
  }
21199
21220
  var GongmunNumberer = class {
21200
- constructor(numbering) {
21221
+ constructor(numbering, bullet2 = "\u25CB", press = false) {
21201
21222
  this.numbering = numbering;
21223
+ this.bullet2 = bullet2;
21224
+ this.press = press;
21202
21225
  }
21203
21226
  counts = [];
21204
21227
  /** depth 항목 하나에 대한 마커. suppress=true면 빈 문자열(부호 없음) */
@@ -21207,8 +21230,8 @@ var GongmunNumberer = class {
21207
21230
  const n = this.counts[depth] ?? 0;
21208
21231
  this.counts[depth] = n + 1;
21209
21232
  if (suppress) return "";
21210
- if (this.numbering === "gaejosik") return gaejosikMarker(depth);
21211
- return this.numbering === "report" ? reportMarker(depth) : standardMarker(depth, n);
21233
+ if (this.numbering === "gaejosik") return gaejosikMarker(depth, this.bullet2);
21234
+ return this.numbering === "report" ? reportMarker(depth, this.bullet2, this.press) : standardMarker(depth, n);
21212
21235
  }
21213
21236
  reset() {
21214
21237
  this.counts = [];
@@ -21330,6 +21353,7 @@ var GJ_PARA_COVER = 21;
21330
21353
  var GJ_PARA_TOC_ITEM = 22;
21331
21354
  var GJ_PARA_CHAPTER = 23;
21332
21355
  var GJ_PARA_BAR = 24;
21356
+ var GONGMUN_LIST_PLAIN_BASE = 25;
21333
21357
  var GJ_BF_CHAPTER_NUM = 3;
21334
21358
  var GJ_BF_CHAPTER_GAP = 4;
21335
21359
  var GJ_BF_CHAPTER_TITLE = 5;
@@ -21368,9 +21392,13 @@ function newPageNumCtrl(num4 = 1) {
21368
21392
  function pageHidingCtrl(hideHeader = false) {
21369
21393
  return `<hp:ctrl><hp:pageHiding hideHeader="${hideHeader ? 1 : 0}" hideFooter="0" hideMasterPage="0" hideBorder="0" hideFill="0" hidePageNum="1"/></hp:ctrl>`;
21370
21394
  }
21395
+ var GONGMUN_TBL_CHAR = 11;
21396
+ var GONGMUN_TBL_CHAR_BOLD = 12;
21397
+ var GONGMUN_TBL_PT = 1200;
21371
21398
  var CHAR_VARIANT_BASE = 11;
21372
- function charVariantBase(measured) {
21373
- return measured ? CHAR_VARIANT_BASE + GJ_CHAR_COUNT : CHAR_VARIANT_BASE;
21399
+ function charVariantBase(measured, isGongmun = true) {
21400
+ if (!isGongmun) return CHAR_VARIANT_BASE;
21401
+ return measured ? 11 + GJ_CHAR_COUNT : 11 + 2;
21374
21402
  }
21375
21403
  var GONGMUN_BODY_RATIO = 95;
21376
21404
 
@@ -21645,6 +21673,12 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
21645
21673
  charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, bodyFont, theme.tableHeader),
21646
21674
  charPr(CHAR_QUOTE, body, false, true, bodyFont, theme.quote)
21647
21675
  ];
21676
+ if (gongmun && !measured) {
21677
+ rows.push(
21678
+ charPr(11, GONGMUN_TBL_PT, false, false, bodyFont, theme.body),
21679
+ charPr(12, GONGMUN_TBL_PT, true, false, bodyFont, theme.body)
21680
+ );
21681
+ }
21648
21682
  if (measured) {
21649
21683
  const sz = gaejosikSizes(body, gongmun.sizes);
21650
21684
  rows.push(
@@ -21723,16 +21757,16 @@ ${base2.join("\n")}
21723
21757
  paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
21724
21758
  ];
21725
21759
  for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
21726
- const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes);
21727
- const sectionGap = gongmun.numbering === "gaejosik" ? gaejosikSpaceBefore(d, gongmun.bodyHeight) : gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
21728
- const keepNext = gongmun.numbering === "gaejosik" && d === 0;
21760
+ const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, gongmun.preset === "press");
21761
+ const sectionGap = gongmun.numbering === "gaejosik" || gongmun.numbering === "report" ? gaejosikSpaceBefore(d, gongmun.bodyHeight) : 0;
21762
+ const keepNext = (gongmun.numbering === "gaejosik" || gongmun.numbering === "report") && d === 0;
21729
21763
  base.push(paraPr(GONGMUN_LIST_BASE + d, { align: "JUSTIFY", lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext }));
21730
21764
  }
21731
21765
  base.push(paraPr(GONGMUN_CENTER, { align: "CENTER", lineSpacing: ls, keepWord: true }));
21732
21766
  base.push(paraPr(GONGMUN_RIGHT, { align: "RIGHT", lineSpacing: ls, keepWord: true }));
21733
21767
  base.push(paraPr(GONGMUN_TBL_CENTER, { align: "CENTER", lineSpacing: 130, keepWord: true }));
21734
21768
  base.push(paraPr(GONGMUN_TBL_LEFT, { align: "LEFT", lineSpacing: 130, keepWord: true }));
21735
- if (gongmun.preset === "gaejosik") {
21769
+ {
21736
21770
  const cham = gaejosikChamIndent(gongmun.bodyHeight, gongmun.sizes);
21737
21771
  const toc = gaejosikTocItemIndent(gongmun.bodyHeight, gongmun.sizes);
21738
21772
  base.push(
@@ -21744,11 +21778,11 @@ ${base2.join("\n")}
21744
21778
  // 표지 장식 바 셀 빈 문단 — 저줄간격(실측 71%)으로 바 높이 818 안에 수납
21745
21779
  paraPr(GJ_PARA_BAR, { align: "CENTER", lineSpacing: 70, keepWord: true })
21746
21780
  );
21747
- } else if (usesReportFonts(gongmun.preset)) {
21748
- const cham = gaejosikChamIndent(gongmun.bodyHeight, gongmun.sizes);
21749
- base.push(
21750
- paraPr(GJ_PARA_CHAM, { align: "JUSTIFY", lineSpacing: ls, left: cham.left, indent: cham.indent, spaceBefore: gaejosikSpaceBefore(3, gongmun.bodyHeight), keepWord: true })
21751
- );
21781
+ }
21782
+ for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
21783
+ const { left } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, gongmun.preset === "press");
21784
+ const sectionGap = gongmun.numbering === "gaejosik" || gongmun.numbering === "report" ? gaejosikSpaceBefore(d, gongmun.bodyHeight) : 0;
21785
+ base.push(paraPr(GONGMUN_LIST_PLAIN_BASE + d, { align: "JUSTIFY", lineSpacing: ls, left, indent: 0, spaceBefore: sectionGap, keepWord: true }));
21752
21786
  }
21753
21787
  return `<hh:paraProperties itemCnt="${base.length}">
21754
21788
  ${base.join("\n")}
@@ -22129,7 +22163,9 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
22129
22163
  if (gongmun.numbering === "gaejosik" && (depth === 0 || (block.text || "").trimStart().startsWith("\u203B"))) continue;
22130
22164
  const content = plainRenderText(block.text || "");
22131
22165
  text = marker ? `${marker} ${content}` : content;
22132
- const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
22166
+ const li = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, gongmun.preset === "press");
22167
+ const left = li.left;
22168
+ const indent = marker ? li.indent : 0;
22133
22169
  firstW = pageW - left - Math.max(indent, 0);
22134
22170
  contW = pageW - left - Math.max(-indent, 0);
22135
22171
  } else if (block.type === "paragraph") {
@@ -22157,7 +22193,7 @@ function variantMapper(fit, blockIdx, base = CHAR_VARIANT_BASE) {
22157
22193
  }
22158
22194
  function precomputeGongmunList(blocks, gongmun) {
22159
22195
  const result = /* @__PURE__ */ new Map();
22160
- const depthOffset = gongmun.numbering === "gaejosik" && blocks.some((b) => b.type === "heading" && b.level === 3) ? 1 : 0;
22196
+ const depthOffset = gongmun.numbering === "gaejosik" && blocks.some((b) => b.type === "heading" && b.level === 3) || gongmun.numbering === "standard" && gongmun.h2Marker === "number" && blocks.some((b) => b.type === "heading" && b.level === 2) ? 1 : 0;
22161
22197
  let i = 0;
22162
22198
  while (i < blocks.length) {
22163
22199
  if (blocks[i].type !== "list_item") {
@@ -22184,8 +22220,8 @@ function precomputeGongmunList(blocks, gongmun) {
22184
22220
  break;
22185
22221
  }
22186
22222
  const depths = run.map((bi) => Math.min(Math.max((blocks[bi].indent || 0) + depthOffset, 0), GONGMUN_LIST_LEVELS - 1));
22187
- const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
22188
- const numberer = new GongmunNumberer(gongmun.numbering);
22223
+ const suppress = gongmun.suppressSingle && gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
22224
+ const numberer = new GongmunNumberer(gongmun.numbering, gongmun.bullet2, gongmun.preset === "press");
22189
22225
  run.forEach((bi, k) => {
22190
22226
  const marker = numberer.next(depths[k], suppress[k]);
22191
22227
  result.set(bi, { marker, depth: depths[k] });
@@ -22215,7 +22251,8 @@ function cell(opts) {
22215
22251
  return `<hp:tc name="" header="0" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${opts.bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="${opts.vertAlign ?? "CENTER"}" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${paras}</hp:subList><hp:cellAddr colAddr="${opts.col}" rowAddr="${opts.row ?? 0}"/><hp:cellSpan colSpan="${opts.colSpan ?? 1}" rowSpan="1"/><hp:cellSz width="${opts.w}" height="${opts.h}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
22216
22252
  }
22217
22253
  function table(rows, w, h, cols, tblBf = 1) {
22218
- return `<hp:tbl id="${++gjTableId}" zOrder="0" numberingType="TABLE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" pageBreak="CELL" repeatHeader="0" rowCnt="${rows.length}" colCnt="${cols}" cellSpacing="0" borderFillIDRef="${tblBf}" noAdjust="1"><hp:sz width="${w}" widthRelTo="ABSOLUTE" height="${h}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="1" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="283" right="283" top="283" bottom="283"/><hp:inMargin left="141" right="141" top="141" bottom="141"/>` + rows.map((r) => `<hp:tr>${r}</hp:tr>`).join("") + `</hp:tbl>`;
22254
+ const outLR = w + 566 > 48e3 ? 0 : 283;
22255
+ return `<hp:tbl id="${++gjTableId}" zOrder="0" numberingType="TABLE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" pageBreak="CELL" repeatHeader="0" rowCnt="${rows.length}" colCnt="${cols}" cellSpacing="0" borderFillIDRef="${tblBf}" noAdjust="1"><hp:sz width="${w}" widthRelTo="ABSOLUTE" height="${h}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="1" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="${outLR}" right="${outLR}" top="283" bottom="283"/><hp:inMargin left="141" right="141" top="141" bottom="141"/>` + rows.map((r) => `<hp:tr>${r}</hp:tr>`).join("") + `</hp:tbl>`;
22219
22256
  }
22220
22257
  function buildGaejosikCover(title, gongmun) {
22221
22258
  const g = coverGeom(gongmun.bodyHeight, gongmun.sizes);
@@ -22878,7 +22915,7 @@ function profileColWidths(tp, colCnt) {
22878
22915
  if (tp.width) return Array(colCnt).fill(Math.floor(tp.width / colCnt));
22879
22916
  return null;
22880
22917
  }
22881
- var CELL_PAD = 582;
22918
+ var CELL_PAD = 1200;
22882
22919
  function cellContentWidth(text, charHeight) {
22883
22920
  let max = 0;
22884
22921
  for (const seg of text.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
@@ -22887,35 +22924,51 @@ function cellContentWidth(text, charHeight) {
22887
22924
  }
22888
22925
  return max;
22889
22926
  }
22890
- function computeColWidths(colMax, totalWidth) {
22927
+ function cellMinWordWidth(text, charHeight) {
22928
+ let max = 0;
22929
+ for (const seg of text.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
22930
+ for (const word of seg.trim().split(/\s+/)) {
22931
+ const w = measureTextWidth(word, charHeight, 100);
22932
+ if (w > max) max = w;
22933
+ }
22934
+ }
22935
+ return max;
22936
+ }
22937
+ function computeColWidths(colMax, totalWidth, colMinWord = []) {
22891
22938
  const colCnt = colMax.length;
22892
22939
  const minW = Math.min(Math.max(2e3, Math.round(totalWidth * 0.06)), Math.floor(totalWidth / colCnt));
22893
22940
  const cap = Math.round(totalWidth * 0.8);
22894
22941
  const raw = colMax.map((w) => Math.min(Math.max(w + CELL_PAD, minW), cap));
22942
+ const floor = raw.map((r, i) => Math.min(Math.max(minW, (colMinWord[i] ?? 0) + CELL_PAD), r, cap));
22895
22943
  const widths = Array(colCnt).fill(0);
22896
22944
  const free = new Set(raw.map((_, i) => i));
22897
22945
  let budget = totalWidth;
22898
- const evenShare = Math.floor(totalWidth / colCnt);
22899
- for (let i = 0; i < colCnt; i++) {
22900
- const fixed = Math.min(Math.round(raw[i] * 1.12), evenShare);
22901
- if (raw[i] <= evenShare && free.size > 1) {
22902
- widths[i] = fixed;
22903
- free.delete(i);
22904
- budget -= fixed;
22905
- }
22906
- }
22907
- if (free.size === 0) {
22946
+ let sumFloorFree = floor.reduce((a, b) => a + b, 0);
22947
+ for (const i of [...raw.keys()].sort((a, b) => raw[a] - raw[b])) {
22948
+ if (free.size <= 1) break;
22949
+ const fixed = Math.round(raw[i] * 1.12);
22950
+ if (budget - fixed < sumFloorFree - floor[i]) break;
22951
+ widths[i] = fixed;
22952
+ free.delete(i);
22953
+ budget -= fixed;
22954
+ sumFloorFree -= floor[i];
22955
+ }
22956
+ const sumFreeRaw = [...free].reduce((a, i) => a + raw[i], 0);
22957
+ if (budget > sumFreeRaw * 1.6) {
22908
22958
  const sumRaw = raw.reduce((a, b) => a + b, 0);
22909
- for (let i = 0; i < colCnt; i++) widths[i] += Math.floor(raw[i] / sumRaw * (totalWidth - sumRaw));
22959
+ for (let i = 0; i < colCnt; i++) widths[i] = raw[i] + Math.floor(raw[i] / sumRaw * (totalWidth - sumRaw));
22960
+ free.clear();
22910
22961
  } else {
22911
22962
  for (; ; ) {
22912
22963
  const sum2 = [...free].reduce((a, i) => a + raw[i], 0);
22913
- const short = [...free].filter((i) => raw[i] / sum2 * budget < minW);
22964
+ const short = [...free].filter((i) => raw[i] / sum2 * budget < floor[i]);
22914
22965
  if (short.length === 0) break;
22966
+ const shortSum = short.reduce((a, i) => a + floor[i], 0);
22967
+ const scale = Math.min(1, (budget - (free.size - short.length) * minW) / shortSum);
22915
22968
  for (const i of short) {
22916
- widths[i] = minW;
22969
+ widths[i] = Math.max(minW, Math.floor(floor[i] * scale));
22917
22970
  free.delete(i);
22918
- budget -= minW;
22971
+ budget -= widths[i];
22919
22972
  }
22920
22973
  if (free.size === 0) break;
22921
22974
  }
@@ -22948,12 +23001,15 @@ function generateTable(rows, theme, style = null, remap = null, seq = 0) {
22948
23001
  const prof = takeProfile(remap, rowCnt, colCnt, anchorOfMarkdownCell(rows[0]?.[0] ?? ""), seq);
22949
23002
  const colMax = Array(colCnt).fill(0);
22950
23003
  const colMaxBody = Array(colCnt).fill(0);
23004
+ const colMinWord = Array(colCnt).fill(0);
22951
23005
  rows.forEach((row, r) => row.forEach((cell2, c) => {
22952
23006
  const w = cellContentWidth(cell2, measureH);
22953
23007
  if (w > colMax[c]) colMax[c] = w;
22954
23008
  if (r > 0 && w > colMaxBody[c]) colMaxBody[c] = w;
23009
+ const mw = cellMinWordWidth(cell2, measureH);
23010
+ if (mw > colMinWord[c]) colMinWord[c] = mw;
22955
23011
  }));
22956
- const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW);
23012
+ const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW, colMinWord);
22957
23013
  const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
22958
23014
  const labelCol0 = !!reg && colCnt === 2 && colCentered[0] && rows.every((r) => (r[0] ?? "").replace(/\*\*|__|`/g, "").length <= 12);
22959
23015
  const tblId = nextTableId();
@@ -23032,16 +23088,19 @@ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, r
23032
23088
  const prof = takeProfile(remap, rowCnt, colCnt, first ? anchorOfHtmlCell(first.inner) : "", seq);
23033
23089
  const colMax = Array(colCnt).fill(0);
23034
23090
  const colMaxBody = Array(colCnt).fill(0);
23091
+ const colMinWord = Array(colCnt).fill(0);
23035
23092
  const cellLines = placed.map((cell2) => htmlCellInnerToLines(cell2.inner).lines);
23036
23093
  placed.forEach((cell2, i) => {
23037
23094
  const w = Math.max(...cellLines[i].map((l) => measureTextWidth(unescapeHtml(l).trim(), measureH, 100)), 0) / cell2.colSpan;
23095
+ const mw = cell2.colSpan === 1 ? Math.max(...cellLines[i].map((l) => cellMinWordWidth(unescapeHtml(l), measureH)), 0) : 0;
23038
23096
  for (let dc = 0; dc < cell2.colSpan; dc++) {
23039
23097
  const c = cell2.c + dc;
23040
23098
  if (w > colMax[c]) colMax[c] = w;
23041
23099
  if (!cell2.isHeader && w > colMaxBody[c]) colMaxBody[c] = w;
23100
+ if (dc === 0 && mw > colMinWord[c]) colMinWord[c] = mw;
23042
23101
  }
23043
23102
  });
23044
- const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth);
23103
+ const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth, colMinWord);
23045
23104
  const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
23046
23105
  const cellH = style ? Math.round(measureH * 1.6) + 282 : 1500;
23047
23106
  const tblW = colWidths.reduce((a, b) => a + b, 0);
@@ -23153,6 +23212,118 @@ function buildTitleBox(title, titleCharPr, bodyWidth, reg) {
23153
23212
  return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`;
23154
23213
  }
23155
23214
 
23215
+ // src/hwpx/gen-docframe.ts
23216
+ function docframeIds(base) {
23217
+ return { org: base, sender: base + 1, foot: base + 2, small: base + 3, pressLabel: base + 4, pressHead: base + 5, pressTitle: base + 6, pressSub: base + 7, pressContact: base + 8 };
23218
+ }
23219
+ function docframeActive(g) {
23220
+ return !!(g.docHead || g.docFoot || g.reportInfo || g.noticeHead || g.press);
23221
+ }
23222
+ function docframeCharPrXmls(base, measured) {
23223
+ const body = measured ? 4 : 0;
23224
+ const ids = docframeIds(base);
23225
+ return [
23226
+ charPr(ids.org, 1800, true, false, body),
23227
+ charPr(ids.sender, 2200, true, false, body),
23228
+ charPr(ids.foot, 900, false, false, body),
23229
+ charPr(ids.small, 1200, false, false, body),
23230
+ charPr(ids.pressLabel, 2e3, true, false, body),
23231
+ charPr(ids.pressHead, 1e3, true, false, body),
23232
+ charPr(ids.pressTitle, 2500, true, false, body),
23233
+ charPr(ids.pressSub, 1500, true, false, body),
23234
+ charPr(ids.pressContact, 1e3, false, false, body)
23235
+ ];
23236
+ }
23237
+ function labeled(label, value, paraPrId) {
23238
+ return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_BOLD}"><hp:t>${escapeXml(label)}</hp:t></hp:run><hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t>${escapeXml(value)}</hp:t></hp:run></hp:p>`;
23239
+ }
23240
+ function blank() {
23241
+ return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t></hp:t></hp:run></hp:p>`;
23242
+ }
23243
+ function buildDocHead(g, ids) {
23244
+ const h = g.docHead;
23245
+ const out = [];
23246
+ if (h.org) {
23247
+ out.push(para(h.org, GONGMUN_CENTER, ids.org), blank());
23248
+ }
23249
+ if (h.to !== void 0) out.push(labeled("\uC218\uC2E0 ", h.to, PARA_NORMAL));
23250
+ out.push(para(h.via ? `(\uACBD\uC720) ${h.via}` : "(\uACBD\uC720)", PARA_NORMAL, CHAR_NORMAL));
23251
+ if (h.title !== void 0) out.push(labeled("\uC81C\uBAA9 ", h.title, PARA_NORMAL));
23252
+ out.push(blank());
23253
+ return out;
23254
+ }
23255
+ var FOOT_SEP = "\u2500".repeat(46);
23256
+ function buildDocFoot(g, ids) {
23257
+ const f = g.docFoot;
23258
+ const out = [blank()];
23259
+ if (f.sender) {
23260
+ out.push(para(f.sender, GONGMUN_CENTER, ids.sender), blank());
23261
+ }
23262
+ const foot = (text) => para(text, GONGMUN_TBL_LEFT, ids.foot);
23263
+ out.push(foot(FOOT_SEP));
23264
+ if (f.drafter || f.reviewer || f.approver)
23265
+ out.push(foot(`\uAE30\uC548\uC790 ${f.drafter ?? ""} \uAC80\uD1A0\uC790 ${f.reviewer ?? ""} \uACB0\uC7AC\uAD8C\uC790 ${f.approver ?? ""}`));
23266
+ if (f.cooperator) out.push(foot(`\uD611\uC870\uC790 ${f.cooperator}`));
23267
+ if (f.docNum || f.receive) out.push(foot(`\uC2DC\uD589 ${f.docNum ?? ""} \uC811\uC218 ${f.receive ?? ""}`));
23268
+ if (f.address || f.site) out.push(foot(`${f.address ?? ""} / ${f.site ?? ""}`));
23269
+ if (f.phone || f.fax || f.email || f.disclosure)
23270
+ out.push(foot(`\uC804\uD654 ${f.phone ?? ""} \uC804\uC1A1 ${f.fax ?? ""} / ${f.email ?? ""} / ${f.disclosure ?? ""}`));
23271
+ return out;
23272
+ }
23273
+ function buildReportInfo(g, ids) {
23274
+ return para(g.reportInfo, GONGMUN_RIGHT, ids.small);
23275
+ }
23276
+ function buildNoticeHead(g) {
23277
+ const n = g.noticeHead;
23278
+ return n.no ? [para(n.no, PARA_NORMAL, CHAR_BOLD), blank()] : [];
23279
+ }
23280
+ function buildNoticeFoot(g) {
23281
+ const n = g.noticeHead;
23282
+ const out = [];
23283
+ if (n.date) out.push(blank(), para(n.date, GONGMUN_RIGHT, CHAR_NORMAL));
23284
+ if (n.sender) out.push(blank(), para(n.sender, GONGMUN_RIGHT, CHAR_BOLD));
23285
+ return out;
23286
+ }
23287
+ var PRESS_LABEL_H = 3200;
23288
+ var PRESS_HEAD_H = 900;
23289
+ function buildPressHead(g, ids, bodyWidth, reg) {
23290
+ const p = g.press;
23291
+ const w = bodyWidth - 280;
23292
+ const thick = { t: "thick", b: "thick", l: "thick", r: "thick" };
23293
+ const rows = [tc({ bf: reg.get({ ...thick, b: "thin" }), row: 0, col: 0, w, h: PRESS_LABEL_H, paras: para("\uBCF4\uB3C4\uC790\uB8CC", GONGMUN_TBL_CENTER, ids.pressLabel) })];
23294
+ const headLine = [
23295
+ p.release ? `\uBCF4\uB3C4\uC2DC\uC810 : ${p.release}` : "",
23296
+ p.distribute ? `\uBC30\uD3EC : ${p.distribute}` : ""
23297
+ ].filter(Boolean).join(" / ");
23298
+ if (headLine) rows.push(tc({ bf: reg.get({ ...thick, t: "thin" }), row: 1, col: 0, w, h: PRESS_HEAD_H, paras: para(headLine, GONGMUN_TBL_CENTER, ids.pressHead) }));
23299
+ const table2 = tbl(rows, w, PRESS_LABEL_H + (headLine ? PRESS_HEAD_H : 0), 1);
23300
+ return [`<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`, blank()];
23301
+ }
23302
+ function buildPressContact(g, ids, bodyWidth, reg) {
23303
+ const c = g.press?.contact;
23304
+ if (!c || !c.dept && !c.manager && !c.phone) return [];
23305
+ const w = bodyWidth - 280;
23306
+ const cells = [["\uB2F4\uB2F9 \uBD80\uC11C", c.dept ?? ""], ["\uB2F4\uB2F9\uC790", c.manager ?? ""], ["\uC5F0\uB77D\uCC98", c.phone ?? ""]];
23307
+ const labelW = Math.round(w * 0.14);
23308
+ const valueW = Math.round(w / 3) - labelW;
23309
+ let col = 0;
23310
+ const row = cells.flatMap(([label, value], i) => {
23311
+ const bf = (first) => reg.get({
23312
+ t: "thick",
23313
+ b: "thick",
23314
+ l: first && i === 0 ? "thick" : "thin",
23315
+ r: !first && i === cells.length - 1 ? "thick" : "thin",
23316
+ fill: first ? "#E6E6E6" : void 0
23317
+ });
23318
+ return [
23319
+ tc({ bf: bf(true), row: 0, col: col++, w: labelW, h: 1100, paras: para(label, GONGMUN_TBL_CENTER, ids.pressHead) }),
23320
+ tc({ bf: bf(false), row: 0, col: col++, w: valueW, h: 1100, paras: para(value, GONGMUN_TBL_CENTER, ids.pressContact) })
23321
+ ];
23322
+ });
23323
+ const table2 = tbl([row.join("")], w, 1100, cells.length * 2);
23324
+ return [blank(), `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`];
23325
+ }
23326
+
23156
23327
  // src/hwpx/equation-generate.ts
23157
23328
  var MAX_EQUATION_SOURCE = 1e4;
23158
23329
  var MAX_GROUP_DEPTH = 64;
@@ -23445,9 +23616,10 @@ function generateSecPr(gongmun) {
23445
23616
  m.footer = gongmun.headerFooter;
23446
23617
  }
23447
23618
  const secPr = `<hp:secPr textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="1" memoShapeIDRef="0" textVerticalWidthHead="0" masterPageCnt="0"><hp:grid lineGrid="0" charGrid="0" wonggojiFormat="0"/><hp:startNum pageStartsOn="BOTH" page="0" pic="0" tbl="0" equation="0"/><hp:visibility hideFirstHeader="0" hideFirstFooter="0" hideFirstMasterPage="0" border="SHOW_ALL" fill="SHOW_ALL" hideFirstPageNum="0" hideFirstEmptyLine="0" showLineNumber="0"/><hp:pagePr landscape="WIDELY" width="59528" height="84188" gutterType="LEFT_ONLY"><hp:margin header="${m.header}" footer="${m.footer}" gutter="0" left="${m.left}" right="${m.right}" top="${m.top}" bottom="${m.bottom}"/></hp:pagePr><hp:footNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="-1" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="283" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="EACH_COLUMN" beneathText="0"/></hp:footNotePr><hp:endNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="14692344" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="0" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="END_OF_DOCUMENT" beneathText="0"/></hp:endNotePr></hp:secPr>`;
23448
- return gongmun?.pageNumbers ? secPr + pageNumCtrl() : secPr;
23619
+ const colPr = `<hp:ctrl><hp:colPr id="" type="NEWSPAPER" layout="LEFT" colCount="1" sameSz="1" sameGap="0"/></hp:ctrl>`;
23620
+ return secPr + colPr + (gongmun?.pageNumbers ? pageNumCtrl() : "");
23449
23621
  }
23450
- function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null) {
23622
+ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null, dfIds = null) {
23451
23623
  const paraXmls = [];
23452
23624
  let isFirst = true;
23453
23625
  let tableSeq = 0;
@@ -23455,12 +23627,14 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
23455
23627
  let prevWasOrdered = false;
23456
23628
  const gaejosik = gongmun?.preset === "gaejosik";
23457
23629
  const measured = !!gongmun && usesReportFonts(gongmun.preset);
23458
- const vBase = charVariantBase(measured);
23630
+ const vBase = charVariantBase(measured, !!gongmun);
23459
23631
  const tableStyle = gongmun ? {
23460
23632
  totalWidth: mmToHwpunit(210 - gongmun.margins.left - gongmun.margins.right),
23461
- charPr: measured ? GJ_CHAR_TABLE : CHAR_NORMAL,
23462
- boldCharPr: measured ? GJ_CHAR_TABLE_BOLD : CHAR_BOLD,
23463
- charHeight: measured ? gaejosikSizes(gongmun.bodyHeight, gongmun.sizes).table : gongmun.bodyHeight,
23633
+ // 크기 실측: 실측 프리셋 맑은 고딕 12pt(22·23), 비실측도 12pt(11·12,
23634
+ // 실결재 지배값 본문 크기 셀은 열폭 부족으로 서술 열 세로 신장, v4.0.2 QA)
23635
+ charPr: measured ? GJ_CHAR_TABLE : GONGMUN_TBL_CHAR,
23636
+ boldCharPr: measured ? GJ_CHAR_TABLE_BOLD : GONGMUN_TBL_CHAR_BOLD,
23637
+ charHeight: measured ? gaejosikSizes(gongmun.bodyHeight, gongmun.sizes).table : GONGMUN_TBL_PT,
23464
23638
  headerBf: gongmunTableHeaderBf(gaejosik),
23465
23639
  centerParaPr: GONGMUN_CENTER,
23466
23640
  tblCenterParaPr: GONGMUN_TBL_CENTER,
@@ -23475,11 +23649,24 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
23475
23649
  let pendingPageBreak = false;
23476
23650
  let pendingNewNum = false;
23477
23651
  let titleBoxH1Idx = -1;
23652
+ let pressH1Idx = -1;
23478
23653
  let hasFrontPages = false;
23479
23654
  const preamble = [];
23655
+ if (gongmun?.reportInfo && dfIds) {
23656
+ preamble.push(buildReportInfo(gongmun, dfIds));
23657
+ }
23480
23658
  if (gongmun?.approval && bfReg) {
23481
23659
  preamble.push(buildApprovalTable(gongmun.approval, gongmun, bfReg));
23482
23660
  }
23661
+ if (gongmun?.docHead && dfIds) {
23662
+ preamble.push(...buildDocHead(gongmun, dfIds));
23663
+ }
23664
+ if (gongmun?.noticeHead && dfIds) {
23665
+ preamble.push(...buildNoticeHead(gongmun));
23666
+ }
23667
+ if (gongmun?.press && dfIds && bfReg && tableStyle) {
23668
+ preamble.push(...buildPressHead(gongmun, dfIds, tableStyle.totalWidth, bfReg));
23669
+ }
23483
23670
  if (gaejosik && gongmun) {
23484
23671
  const h1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
23485
23672
  const chapters = blocks.filter((b) => b.type === "heading" && b.level === 2).map((b) => stripChapterNumber(b.text || ""));
@@ -23504,6 +23691,8 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
23504
23691
  }
23505
23692
  } else if (gongmun && !gaejosik && bfReg && (gongmun.preset === "report" || gongmun.preset === "plan" || gongmun.preset === "notice")) {
23506
23693
  titleBoxH1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
23694
+ } else if (gongmun?.press && dfIds) {
23695
+ pressH1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
23507
23696
  }
23508
23697
  if (preamble.length > 0) {
23509
23698
  preamble[0] = preamble[0].replace(` pageBreak="1"`, "").replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${generateSecPr(gongmun)}`);
@@ -23523,6 +23712,14 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
23523
23712
  }
23524
23713
  switch (block.type) {
23525
23714
  case "heading": {
23715
+ if (gongmun && blockIdx === pressH1Idx && dfIds) {
23716
+ const parts = [generateParagraph((block.text || "").trim(), GONGMUN_CENTER, dfIds.pressTitle)];
23717
+ for (const s of gongmun.press?.sub ?? []) {
23718
+ parts.push(generateParagraph(`- ${s} -`, GONGMUN_CENTER, dfIds.pressSub));
23719
+ }
23720
+ xml = parts.join("\n ");
23721
+ break;
23722
+ }
23526
23723
  if (gongmun && blockIdx === titleBoxH1Idx && tableStyle && bfReg) {
23527
23724
  xml = buildTitleBox((block.text || "").trim(), measured ? GJ_CHAR_BODY_TITLE : CHAR_H1, tableStyle.totalWidth, bfReg);
23528
23725
  break;
@@ -23541,7 +23738,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
23541
23738
  (id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id
23542
23739
  );
23543
23740
  } else {
23544
- xml = generateParagraph(`\u25CB ${block.text || ""}`, GONGMUN_LIST_BASE + 1, CHAR_NORMAL);
23741
+ xml = generateParagraph(`${gongmun.bullet2} ${block.text || ""}`, GONGMUN_LIST_BASE + 1, CHAR_NORMAL);
23545
23742
  }
23546
23743
  break;
23547
23744
  }
@@ -23557,7 +23754,8 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
23557
23754
  break;
23558
23755
  }
23559
23756
  case "paragraph": {
23560
- if (measured && (block.text || "").trimStart().startsWith("\u203B")) {
23757
+ const pTrim = (block.text || "").trimStart();
23758
+ if (measured && (pTrim.startsWith("\u203B") || /^\*\s/.test(pTrim))) {
23561
23759
  xml = generateParagraph((block.text || "").trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
23562
23760
  break;
23563
23761
  }
@@ -23624,14 +23822,26 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
23624
23822
  xml = generateParagraph(content.trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
23625
23823
  break;
23626
23824
  }
23825
+ if (measured && block.marker === "*") {
23826
+ xml = generateParagraph(`* ${content.trim()}`, GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
23827
+ break;
23828
+ }
23627
23829
  const text = marker2 ? `${marker2} ${content}` : content;
23830
+ const listParaPr = marker2 ? GONGMUN_LIST_BASE + depth : GONGMUN_LIST_PLAIN_BASE + depth;
23628
23831
  let listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
23629
23832
  let mapId = fit ? variantMapper(fit, blockIdx, vBase) : void 0;
23630
23833
  if (measured && depth === 0 && gongmun.numbering !== "standard") {
23631
23834
  listCharPr = GJ_CHAR_DAE;
23632
23835
  mapId = (id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id;
23633
23836
  }
23634
- xml = generateParagraph(text, GONGMUN_LIST_BASE + depth, listCharPr, mapId);
23837
+ if (gongmun.preset === "press") {
23838
+ if (depth === 0) listCharPr = CHAR_NORMAL;
23839
+ if (depth >= 2 && dfIds) {
23840
+ listCharPr = dfIds.small;
23841
+ mapId = void 0;
23842
+ }
23843
+ }
23844
+ xml = generateParagraph(text, listParaPr, listCharPr, mapId);
23635
23845
  break;
23636
23846
  }
23637
23847
  const indent = block.indent || 0;
@@ -23705,10 +23915,19 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
23705
23915
  }
23706
23916
  paraXmls.push(xml);
23707
23917
  }
23918
+ if (gongmun?.noticeHead && dfIds) {
23919
+ paraXmls.push(...buildNoticeFoot(gongmun));
23920
+ }
23708
23921
  if (gongmun?.endMark && paraXmls.length > 0) {
23709
23922
  const lastText = [...blocks].reverse().find((b) => (b.type === "paragraph" || b.type === "list_item") && (b.text || "").trim())?.text ?? "";
23710
23923
  if (!hasEndMark(lastText)) paraXmls.push(buildEndMark());
23711
23924
  }
23925
+ if (gongmun?.docFoot && dfIds) {
23926
+ paraXmls.push(...buildDocFoot(gongmun, dfIds));
23927
+ }
23928
+ if (gongmun?.press && dfIds && bfReg && tableStyle) {
23929
+ paraXmls.push(...buildPressContact(gongmun, dfIds, tableStyle.totalWidth, bfReg));
23930
+ }
23712
23931
  if (paraXmls.length === 0) {
23713
23932
  paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run></hp:p>`);
23714
23933
  }
@@ -23728,10 +23947,13 @@ async function markdownToHwpx(markdown, options) {
23728
23947
  const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
23729
23948
  const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
23730
23949
  const staticBfEnd = gongmun ? gaejosik ? 11 : 4 : 3;
23731
- const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(measured) + (fit?.variants?.length ?? 0) * 4, staticBfEnd) : null;
23950
+ const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(measured, !!gongmun) + (fit?.variants?.length ?? 0) * 4, staticBfEnd) : null;
23732
23951
  const bfReg = gongmun ? new TableBfRegistry(staticBfEnd + (remap?.borderFillXmls.length ?? 0)) : null;
23952
+ const dfActive = !!gongmun && docframeActive(gongmun);
23953
+ const dfBase = charVariantBase(measured, !!gongmun) + (fit?.variants?.length ?? 0) * 4 + (remap?.charPrXmls.length ?? 0);
23954
+ const dfIds = dfActive ? docframeIds(dfBase) : null;
23733
23955
  const chartParts = [];
23734
- const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap);
23956
+ const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap, dfIds);
23735
23957
  if (remap && remap.tables.length > 0) {
23736
23958
  const unused = remap.tables.filter((t) => !t.used).length;
23737
23959
  if (unused === remap.tables.length) {
@@ -23743,7 +23965,13 @@ async function markdownToHwpx(markdown, options) {
23743
23965
  zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
23744
23966
  zip.file("META-INF/container.xml", generateContainerXml());
23745
23967
  zip.file("Contents/content.hpf", generateManifest(chartParts));
23746
- zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? [], extraBorderFills, remap?.charPrXmls ?? []));
23968
+ zip.file("Contents/header.xml", generateHeaderXml(
23969
+ theme,
23970
+ gongmun,
23971
+ fit?.variants ?? [],
23972
+ extraBorderFills,
23973
+ [...remap?.charPrXmls ?? [], ...dfActive ? docframeCharPrXmls(dfBase, measured) : []]
23974
+ ));
23747
23975
  zip.file("Contents/section0.xml", sectionXml);
23748
23976
  for (const part of chartParts) zip.file(part.name, part.xml);
23749
23977
  zip.file("Preview/PrvText.txt", buildPrvText(blocks));
@@ -28551,7 +28779,7 @@ async function parseHwp(buffer, options) {
28551
28779
  async function parsePdf(buffer, options) {
28552
28780
  let parsePdfDocument;
28553
28781
  try {
28554
- const mod = await import("./parser-G433UZMX.js");
28782
+ const mod = await import("./parser-2Q2YKEJG.js");
28555
28783
  parsePdfDocument = mod.parsePdfDocument;
28556
28784
  } catch {
28557
28785
  return {