kordoc 4.0.0 → 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.
- package/dist/{-URVKBXYK.js → -XMKVL3NX.js} +11 -7
- package/dist/{chunk-IA5UZZKV.js → chunk-3IYQYBUF.js} +2 -2
- package/dist/{chunk-THZVBYHE.js → chunk-67RANGFQ.js} +3 -3
- package/dist/{chunk-JUJEKFUF.js → chunk-6SD4X5PT.js} +3 -3
- package/dist/{chunk-7ETIIYGI.js → chunk-6YIYFWO2.js} +2 -2
- package/dist/{chunk-PGWAF755.js → chunk-AHWRAGXN.js} +477 -89
- package/dist/chunk-AHWRAGXN.js.map +1 -0
- package/dist/{chunk-DVUNWK6W.js → chunk-IKBIIEVJ.js} +2 -2
- package/dist/{chunk-ZKG6SBHV.js → chunk-STMLZDKR.js} +2 -2
- package/dist/{chunk-EBSCV3JC.cjs → chunk-WN7LZHII.cjs} +2 -2
- package/dist/{chunk-EBSCV3JC.cjs.map → chunk-WN7LZHII.cjs.map} +1 -1
- package/dist/cli.js +72 -14
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +730 -342
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -6
- package/dist/index.d.ts +93 -6
- package/dist/index.js +472 -84
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +60 -14
- package/dist/mcp.js.map +1 -1
- package/dist/{parser-NXHY37WH.js → parser-2Q2YKEJG.js} +2 -2
- package/dist/{parser-LHUO6UUA.js → parser-3HM2VYKK.js} +3 -3
- package/dist/{parser-6TV6JKHF.cjs → parser-6AYYGX6J.cjs} +14 -14
- package/dist/{parser-6TV6JKHF.cjs.map → parser-6AYYGX6J.cjs.map} +1 -1
- package/dist/render-W4VCJE6N.js +10 -0
- package/dist/seal-DRPTNHOP.js +10 -0
- package/dist/{watch-PNXTAWDR.js → watch-6OHF727O.js} +7 -7
- package/package.json +1 -1
- package/dist/chunk-PGWAF755.js.map +0 -1
- package/dist/render-T5O6QHBJ.js +0 -10
- package/dist/seal-7KNR5WFH.js +0 -10
- /package/dist/{-URVKBXYK.js.map → -XMKVL3NX.js.map} +0 -0
- /package/dist/{chunk-IA5UZZKV.js.map → chunk-3IYQYBUF.js.map} +0 -0
- /package/dist/{chunk-THZVBYHE.js.map → chunk-67RANGFQ.js.map} +0 -0
- /package/dist/{chunk-JUJEKFUF.js.map → chunk-6SD4X5PT.js.map} +0 -0
- /package/dist/{chunk-7ETIIYGI.js.map → chunk-6YIYFWO2.js.map} +0 -0
- /package/dist/{chunk-DVUNWK6W.js.map → chunk-IKBIIEVJ.js.map} +0 -0
- /package/dist/{chunk-ZKG6SBHV.js.map → chunk-STMLZDKR.js.map} +0 -0
- /package/dist/{parser-NXHY37WH.js.map → parser-2Q2YKEJG.js.map} +0 -0
- /package/dist/{parser-LHUO6UUA.js.map → parser-3HM2VYKK.js.map} +0 -0
- /package/dist/{render-T5O6QHBJ.js.map → render-W4VCJE6N.js.map} +0 -0
- /package/dist/{seal-7KNR5WFH.js.map → seal-DRPTNHOP.js.map} +0 -0
- /package/dist/{watch-PNXTAWDR.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-
|
|
23
|
+
} from "./chunk-3IYQYBUF.js";
|
|
24
24
|
import {
|
|
25
25
|
parsePageRange
|
|
26
26
|
} from "./chunk-GE43BE46.js";
|
|
@@ -20950,8 +20950,9 @@ function fitRatioForFewerLines(text, firstWidth, contWidth, height, baseRatio, m
|
|
|
20950
20950
|
}
|
|
20951
20951
|
|
|
20952
20952
|
// src/hwpx/gaejosik.ts
|
|
20953
|
-
var GAEJOSIK_BULLETS = ["\u25A1", "\u25CB", "
|
|
20954
|
-
function gaejosikMarker(depth) {
|
|
20953
|
+
var GAEJOSIK_BULLETS = ["\u25A1", "\u25CB", "-", "\u318D"];
|
|
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:
|
|
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,12 +21094,17 @@ 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";
|
|
21098
21103
|
return PRESET_ALIAS[preset.trim()] ?? "official";
|
|
21099
21104
|
}
|
|
21105
|
+
function usesReportFonts(preset) {
|
|
21106
|
+
return preset === "gaejosik" || preset === "report" || preset === "plan";
|
|
21107
|
+
}
|
|
21100
21108
|
function resolveGongmun(opts) {
|
|
21101
21109
|
const preset = normalizeGongmunPreset(opts.preset);
|
|
21102
21110
|
const d = PRESET_DEFAULTS[preset];
|
|
@@ -21105,13 +21113,14 @@ function resolveGongmun(opts) {
|
|
|
21105
21113
|
const coverOn = opts.cover !== void 0 ? opts.cover !== false : preset === "gaejosik";
|
|
21106
21114
|
const coverOpts = typeof opts.cover === "object" ? opts.cover : {};
|
|
21107
21115
|
const gaejosik = preset === "gaejosik";
|
|
21116
|
+
const reportFamily = gaejosik || preset === "report" || preset === "plan" || preset === "notice" || preset === "press";
|
|
21108
21117
|
return {
|
|
21109
21118
|
preset,
|
|
21110
21119
|
bodyFont: opts.bodyFont ?? "myeongjo",
|
|
21111
21120
|
bodyHeight: Math.round(bodyPt * 100),
|
|
21112
21121
|
lineSpacing: opts.lineSpacing ?? d.lineSpacing,
|
|
21113
21122
|
numbering: opts.numbering ?? d.numbering,
|
|
21114
|
-
margins: opts.margins ?? (
|
|
21123
|
+
margins: opts.margins ?? (reportFamily ? GAEJOSIK_MARGINS : OFFICIAL_MARGINS),
|
|
21115
21124
|
centerTitle: opts.centerTitle ?? true,
|
|
21116
21125
|
autoFitMinRatio,
|
|
21117
21126
|
cover: coverOn ? { date: coverOpts.date ?? null, org: coverOpts.org ?? "" } : null,
|
|
@@ -21120,12 +21129,26 @@ function resolveGongmun(opts) {
|
|
|
21120
21129
|
sizes: opts.sizes ?? {},
|
|
21121
21130
|
// 쪽번호 — 보고서 계열 관행(실측: 2_보고서 양식·추진계획·공고문 전부 하단 중앙)
|
|
21122
21131
|
pageNumbers: opts.pageNumbers ?? (gaejosik || preset === "report" || preset === "plan"),
|
|
21123
|
-
|
|
21132
|
+
// 머리말·꼬리말 — 실측: 보고서 계열 15mm(GT3·t2·춘천·브라더), 공고·보도 10mm,
|
|
21133
|
+
// 기안문 0(실결재 41/60건 h0/f0)
|
|
21134
|
+
headerFooter: usesReportFonts(preset) ? GAEJOSIK_HEADER_FOOTER : preset === "notice" || preset === "press" ? 2835 : 0,
|
|
21124
21135
|
// "끝." — 기안문 규정(본문 끝 2타+"끝."). 그 외는 opt-in
|
|
21125
21136
|
endMark: opts.endMark ?? preset === "official",
|
|
21126
21137
|
approval: opts.approval && opts.approval.length > 0 ? opts.approval : null,
|
|
21127
21138
|
// 본문 제목박스 — 실측(GT3·GT12): 목차 뒤 본문 시작에 제목 반복. 표지 켜진 개조식 기본
|
|
21128
|
-
bodyTitleBox: opts.bodyTitleBox ?? (gaejosik && coverOn)
|
|
21139
|
+
bodyTitleBox: opts.bodyTitleBox ?? (gaejosik && coverOn),
|
|
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
|
|
21129
21152
|
};
|
|
21130
21153
|
}
|
|
21131
21154
|
var HANGUL_INITIALS = [0, 2, 3, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18];
|
|
@@ -21143,6 +21166,7 @@ function circledHangul(n) {
|
|
|
21143
21166
|
return String.fromCodePoint(12910 + n % 14);
|
|
21144
21167
|
}
|
|
21145
21168
|
var REPORT_BULLETS = ["\u25A1", "\u25CB", "-", "\u318D"];
|
|
21169
|
+
var PRESS_BULLETS = ["\u25A1", "\u3147", "*", "\u318D"];
|
|
21146
21170
|
function standardMarker(depth, n) {
|
|
21147
21171
|
switch (depth) {
|
|
21148
21172
|
case 0:
|
|
@@ -21165,17 +21189,19 @@ function standardMarker(depth, n) {
|
|
|
21165
21189
|
return circledHangul(n);
|
|
21166
21190
|
}
|
|
21167
21191
|
}
|
|
21168
|
-
function reportMarker(depth) {
|
|
21169
|
-
|
|
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;
|
|
21170
21196
|
}
|
|
21171
21197
|
function markerWidth(marker, bodyHeight) {
|
|
21172
21198
|
let em = SPACE_EM_FIXED;
|
|
21173
21199
|
for (const c of marker) em += charWidthEm1000(c.codePointAt(0));
|
|
21174
21200
|
return Math.round(em / 1e3 * bodyHeight);
|
|
21175
21201
|
}
|
|
21176
|
-
function levelIndent(depth, bodyHeight, numbering, sizes = {}) {
|
|
21177
|
-
if (numbering === "gaejosik") return gaejosikLevelIndent(depth, bodyHeight, sizes);
|
|
21178
|
-
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);
|
|
21179
21205
|
return { left: Math.round(depth * bodyHeight), indent: -markerWidth(marker, bodyHeight) };
|
|
21180
21206
|
}
|
|
21181
21207
|
function computeSuppression(depths) {
|
|
@@ -21192,8 +21218,10 @@ function computeSuppression(depths) {
|
|
|
21192
21218
|
return keys.map((k) => (counts.get(k) ?? 0) <= 1);
|
|
21193
21219
|
}
|
|
21194
21220
|
var GongmunNumberer = class {
|
|
21195
|
-
constructor(numbering) {
|
|
21221
|
+
constructor(numbering, bullet2 = "\u25CB", press = false) {
|
|
21196
21222
|
this.numbering = numbering;
|
|
21223
|
+
this.bullet2 = bullet2;
|
|
21224
|
+
this.press = press;
|
|
21197
21225
|
}
|
|
21198
21226
|
counts = [];
|
|
21199
21227
|
/** depth 항목 하나에 대한 마커. suppress=true면 빈 문자열(부호 없음) */
|
|
@@ -21202,8 +21230,8 @@ var GongmunNumberer = class {
|
|
|
21202
21230
|
const n = this.counts[depth] ?? 0;
|
|
21203
21231
|
this.counts[depth] = n + 1;
|
|
21204
21232
|
if (suppress) return "";
|
|
21205
|
-
if (this.numbering === "gaejosik") return gaejosikMarker(depth);
|
|
21206
|
-
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);
|
|
21207
21235
|
}
|
|
21208
21236
|
reset() {
|
|
21209
21237
|
this.counts = [];
|
|
@@ -21270,10 +21298,10 @@ function headingCharPrId(level) {
|
|
|
21270
21298
|
if (level === 3) return CHAR_H3;
|
|
21271
21299
|
return CHAR_H4;
|
|
21272
21300
|
}
|
|
21273
|
-
function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100
|
|
21301
|
+
function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100) {
|
|
21274
21302
|
const boldAttr = bold ? ` bold="1"` : "";
|
|
21275
21303
|
const italicAttr = italic ? ` italic="1"` : "";
|
|
21276
|
-
const effFont =
|
|
21304
|
+
const effFont = fontId;
|
|
21277
21305
|
const boldEl = bold ? `<hh:bold/>` : "";
|
|
21278
21306
|
return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
21279
21307
|
<hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
|
|
@@ -21325,6 +21353,7 @@ var GJ_PARA_COVER = 21;
|
|
|
21325
21353
|
var GJ_PARA_TOC_ITEM = 22;
|
|
21326
21354
|
var GJ_PARA_CHAPTER = 23;
|
|
21327
21355
|
var GJ_PARA_BAR = 24;
|
|
21356
|
+
var GONGMUN_LIST_PLAIN_BASE = 25;
|
|
21328
21357
|
var GJ_BF_CHAPTER_NUM = 3;
|
|
21329
21358
|
var GJ_BF_CHAPTER_GAP = 4;
|
|
21330
21359
|
var GJ_BF_CHAPTER_TITLE = 5;
|
|
@@ -21363,9 +21392,13 @@ function newPageNumCtrl(num4 = 1) {
|
|
|
21363
21392
|
function pageHidingCtrl(hideHeader = false) {
|
|
21364
21393
|
return `<hp:ctrl><hp:pageHiding hideHeader="${hideHeader ? 1 : 0}" hideFooter="0" hideMasterPage="0" hideBorder="0" hideFill="0" hidePageNum="1"/></hp:ctrl>`;
|
|
21365
21394
|
}
|
|
21395
|
+
var GONGMUN_TBL_CHAR = 11;
|
|
21396
|
+
var GONGMUN_TBL_CHAR_BOLD = 12;
|
|
21397
|
+
var GONGMUN_TBL_PT = 1200;
|
|
21366
21398
|
var CHAR_VARIANT_BASE = 11;
|
|
21367
|
-
function charVariantBase(
|
|
21368
|
-
|
|
21399
|
+
function charVariantBase(measured, isGongmun = true) {
|
|
21400
|
+
if (!isGongmun) return CHAR_VARIANT_BASE;
|
|
21401
|
+
return measured ? 11 + GJ_CHAR_COUNT : 11 + 2;
|
|
21369
21402
|
}
|
|
21370
21403
|
var GONGMUN_BODY_RATIO = 95;
|
|
21371
21404
|
|
|
@@ -21613,7 +21646,7 @@ function generateManifest(chartParts = []) {
|
|
|
21613
21646
|
</opf:package>`;
|
|
21614
21647
|
}
|
|
21615
21648
|
function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls = []) {
|
|
21616
|
-
const
|
|
21649
|
+
const measured = !!gongmun && usesReportFonts(gongmun.preset);
|
|
21617
21650
|
let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
|
|
21618
21651
|
if (gongmun) {
|
|
21619
21652
|
body = gongmun.bodyHeight;
|
|
@@ -21623,7 +21656,9 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
|
|
|
21623
21656
|
h3 = body;
|
|
21624
21657
|
h4 = Math.max(body - 100, 1300);
|
|
21625
21658
|
}
|
|
21626
|
-
const bodyFont =
|
|
21659
|
+
const bodyFont = measured ? 4 : 0;
|
|
21660
|
+
const hFont = measured ? 3 : 1;
|
|
21661
|
+
const hBold = !measured;
|
|
21627
21662
|
const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
|
|
21628
21663
|
const rows = [
|
|
21629
21664
|
charPr(0, body, false, false, bodyFont, theme.body, bodyRatio),
|
|
@@ -21631,25 +21666,31 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
|
|
|
21631
21666
|
charPr(2, body, false, true, bodyFont, theme.body, bodyRatio),
|
|
21632
21667
|
charPr(3, body, true, true, bodyFont, theme.body, bodyRatio),
|
|
21633
21668
|
charPr(4, code, false, false, 1),
|
|
21634
|
-
charPr(5, h1,
|
|
21635
|
-
charPr(6, h2,
|
|
21636
|
-
charPr(7, h3,
|
|
21637
|
-
charPr(8, h4,
|
|
21669
|
+
charPr(5, h1, hBold, false, hFont, theme.h1),
|
|
21670
|
+
charPr(6, h2, hBold, false, hFont, theme.h2),
|
|
21671
|
+
charPr(7, h3, hBold, false, hFont, theme.h3),
|
|
21672
|
+
charPr(8, h4, hBold, false, hFont, theme.h4),
|
|
21638
21673
|
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, bodyFont, theme.tableHeader),
|
|
21639
21674
|
charPr(CHAR_QUOTE, body, false, true, bodyFont, theme.quote)
|
|
21640
21675
|
];
|
|
21641
|
-
if (
|
|
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
|
+
}
|
|
21682
|
+
if (measured) {
|
|
21642
21683
|
const sz = gaejosikSizes(body, gongmun.sizes);
|
|
21643
21684
|
rows.push(
|
|
21644
21685
|
charPr(11, sz.dae, false, false, 3),
|
|
21645
21686
|
// □ HY헤드라인M
|
|
21646
|
-
charPr(12, sz.dae, true, false, 3
|
|
21687
|
+
charPr(12, sz.dae, true, false, 3),
|
|
21647
21688
|
// □ bold
|
|
21648
21689
|
charPr(13, sz.cham, false, false, 5),
|
|
21649
21690
|
// ※ 한양중고딕
|
|
21650
|
-
charPr(14, sz.cham, true, false, 5
|
|
21691
|
+
charPr(14, sz.cham, true, false, 5),
|
|
21651
21692
|
// ※ bold
|
|
21652
|
-
charPr(15, sz.chapter, true, false, 4, "#FFFFFF"
|
|
21693
|
+
charPr(15, sz.chapter, true, false, 4, "#FFFFFF"),
|
|
21653
21694
|
// 장 로마숫자(흰)
|
|
21654
21695
|
charPr(16, sz.chapter, false, false, 3),
|
|
21655
21696
|
// 장 제목
|
|
@@ -21657,15 +21698,15 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
|
|
|
21657
21698
|
// 표지 제목
|
|
21658
21699
|
charPr(18, sz.coverSub, false, false, 3),
|
|
21659
21700
|
// 표지 날짜·기관명
|
|
21660
|
-
charPr(19, sz.tocLabel, true, false, 3
|
|
21701
|
+
charPr(19, sz.tocLabel, true, false, 3),
|
|
21661
21702
|
// 목 차
|
|
21662
|
-
charPr(20, sz.tocRoman, true, false, 6
|
|
21703
|
+
charPr(20, sz.tocRoman, true, false, 6),
|
|
21663
21704
|
// 목차 로마숫자(한양신명조)
|
|
21664
21705
|
charPr(21, sz.tocItem, false, false, 3),
|
|
21665
21706
|
// 목차 항목
|
|
21666
21707
|
charPr(22, sz.table, false, false, 7),
|
|
21667
21708
|
// 표 셀(맑은 고딕 12pt)
|
|
21668
|
-
charPr(23, sz.table, true, false, 7
|
|
21709
|
+
charPr(23, sz.table, true, false, 7),
|
|
21669
21710
|
// 표 셀 bold
|
|
21670
21711
|
charPr(24, sz.bar, false, false, 4),
|
|
21671
21712
|
// 표지 바 셀 빈 문단(6pt)
|
|
@@ -21704,10 +21745,11 @@ ${base2.join("\n")}
|
|
|
21704
21745
|
}
|
|
21705
21746
|
const ls = gongmun.lineSpacing;
|
|
21706
21747
|
const titleAlign = gongmun.centerTitle ? "CENTER" : "LEFT";
|
|
21748
|
+
const h2Geom = gongmun.h2Marker !== "none" ? { spaceBefore: Math.round(gongmun.bodyHeight * 2), spaceAfter: 0, indent: -markerWidth(gongmun.h2Marker === "box" ? "\u25A1" : "1.", 1600) } : { spaceBefore: 600, spaceAfter: 150 };
|
|
21707
21749
|
const base = [
|
|
21708
21750
|
paraPr(0, { lineSpacing: ls, keepWord: true }),
|
|
21709
21751
|
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true }),
|
|
21710
|
-
paraPr(2, { align: "LEFT",
|
|
21752
|
+
paraPr(2, { align: "LEFT", ...h2Geom, lineSpacing: ls, keepWord: true }),
|
|
21711
21753
|
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
21712
21754
|
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
21713
21755
|
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
@@ -21715,16 +21757,16 @@ ${base2.join("\n")}
|
|
|
21715
21757
|
paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
|
|
21716
21758
|
];
|
|
21717
21759
|
for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
|
|
21718
|
-
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes);
|
|
21719
|
-
const sectionGap = gongmun.numbering === "gaejosik"
|
|
21720
|
-
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;
|
|
21721
21763
|
base.push(paraPr(GONGMUN_LIST_BASE + d, { align: "JUSTIFY", lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true, keepWithNext: keepNext }));
|
|
21722
21764
|
}
|
|
21723
21765
|
base.push(paraPr(GONGMUN_CENTER, { align: "CENTER", lineSpacing: ls, keepWord: true }));
|
|
21724
21766
|
base.push(paraPr(GONGMUN_RIGHT, { align: "RIGHT", lineSpacing: ls, keepWord: true }));
|
|
21725
21767
|
base.push(paraPr(GONGMUN_TBL_CENTER, { align: "CENTER", lineSpacing: 130, keepWord: true }));
|
|
21726
21768
|
base.push(paraPr(GONGMUN_TBL_LEFT, { align: "LEFT", lineSpacing: 130, keepWord: true }));
|
|
21727
|
-
|
|
21769
|
+
{
|
|
21728
21770
|
const cham = gaejosikChamIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
21729
21771
|
const toc = gaejosikTocItemIndent(gongmun.bodyHeight, gongmun.sizes);
|
|
21730
21772
|
base.push(
|
|
@@ -21737,6 +21779,11 @@ ${base2.join("\n")}
|
|
|
21737
21779
|
paraPr(GJ_PARA_BAR, { align: "CENTER", lineSpacing: 70, keepWord: true })
|
|
21738
21780
|
);
|
|
21739
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 }));
|
|
21786
|
+
}
|
|
21740
21787
|
return `<hh:paraProperties itemCnt="${base.length}">
|
|
21741
21788
|
${base.join("\n")}
|
|
21742
21789
|
</hh:paraProperties>`;
|
|
@@ -21758,14 +21805,15 @@ function fontEntry(id, face, weight = 6) {
|
|
|
21758
21805
|
</hh:font>`;
|
|
21759
21806
|
}
|
|
21760
21807
|
function buildFontFaces(gongmun, bodyFace) {
|
|
21761
|
-
if (gongmun
|
|
21808
|
+
if (gongmun && usesReportFonts(gongmun.preset)) {
|
|
21762
21809
|
const ov = gongmun.fonts;
|
|
21810
|
+
const bodyDefault = gongmun.preset !== "gaejosik" && gongmun.bodyFont === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD734\uBA3C\uBA85\uC870";
|
|
21763
21811
|
const faces = [
|
|
21764
21812
|
"\uD568\uCD08\uB86C\uBC14\uD0D5",
|
|
21765
21813
|
"\uD568\uCD08\uB86C\uB3CB\uC6C0",
|
|
21766
21814
|
"HY\uACAC\uACE0\uB515",
|
|
21767
21815
|
ov.heading ?? "HY\uD5E4\uB4DC\uB77C\uC778M",
|
|
21768
|
-
ov.body ??
|
|
21816
|
+
ov.body ?? bodyDefault,
|
|
21769
21817
|
ov.ref ?? "\uD55C\uC591\uC911\uACE0\uB515",
|
|
21770
21818
|
"\uD55C\uC591\uC2E0\uBA85\uC870",
|
|
21771
21819
|
ov.table ?? "\uB9D1\uC740 \uACE0\uB515"
|
|
@@ -22115,7 +22163,9 @@ function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
|
22115
22163
|
if (gongmun.numbering === "gaejosik" && (depth === 0 || (block.text || "").trimStart().startsWith("\u203B"))) continue;
|
|
22116
22164
|
const content = plainRenderText(block.text || "");
|
|
22117
22165
|
text = marker ? `${marker} ${content}` : content;
|
|
22118
|
-
const
|
|
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;
|
|
22119
22169
|
firstW = pageW - left - Math.max(indent, 0);
|
|
22120
22170
|
contW = pageW - left - Math.max(-indent, 0);
|
|
22121
22171
|
} else if (block.type === "paragraph") {
|
|
@@ -22143,7 +22193,7 @@ function variantMapper(fit, blockIdx, base = CHAR_VARIANT_BASE) {
|
|
|
22143
22193
|
}
|
|
22144
22194
|
function precomputeGongmunList(blocks, gongmun) {
|
|
22145
22195
|
const result = /* @__PURE__ */ new Map();
|
|
22146
|
-
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;
|
|
22147
22197
|
let i = 0;
|
|
22148
22198
|
while (i < blocks.length) {
|
|
22149
22199
|
if (blocks[i].type !== "list_item") {
|
|
@@ -22170,8 +22220,8 @@ function precomputeGongmunList(blocks, gongmun) {
|
|
|
22170
22220
|
break;
|
|
22171
22221
|
}
|
|
22172
22222
|
const depths = run.map((bi) => Math.min(Math.max((blocks[bi].indent || 0) + depthOffset, 0), GONGMUN_LIST_LEVELS - 1));
|
|
22173
|
-
const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
|
|
22174
|
-
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");
|
|
22175
22225
|
run.forEach((bi, k) => {
|
|
22176
22226
|
const marker = numberer.next(depths[k], suppress[k]);
|
|
22177
22227
|
result.set(bi, { marker, depth: depths[k] });
|
|
@@ -22201,7 +22251,8 @@ function cell(opts) {
|
|
|
22201
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>`;
|
|
22202
22252
|
}
|
|
22203
22253
|
function table(rows, w, h, cols, tblBf = 1) {
|
|
22204
|
-
|
|
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>`;
|
|
22205
22256
|
}
|
|
22206
22257
|
function buildGaejosikCover(title, gongmun) {
|
|
22207
22258
|
const g = coverGeom(gongmun.bodyHeight, gongmun.sizes);
|
|
@@ -22864,7 +22915,7 @@ function profileColWidths(tp, colCnt) {
|
|
|
22864
22915
|
if (tp.width) return Array(colCnt).fill(Math.floor(tp.width / colCnt));
|
|
22865
22916
|
return null;
|
|
22866
22917
|
}
|
|
22867
|
-
var CELL_PAD =
|
|
22918
|
+
var CELL_PAD = 1200;
|
|
22868
22919
|
function cellContentWidth(text, charHeight) {
|
|
22869
22920
|
let max = 0;
|
|
22870
22921
|
for (const seg of text.replace(/\*\*|__|`/g, "").split(/<br\s*\/?>/i)) {
|
|
@@ -22873,35 +22924,51 @@ function cellContentWidth(text, charHeight) {
|
|
|
22873
22924
|
}
|
|
22874
22925
|
return max;
|
|
22875
22926
|
}
|
|
22876
|
-
function
|
|
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 = []) {
|
|
22877
22938
|
const colCnt = colMax.length;
|
|
22878
22939
|
const minW = Math.min(Math.max(2e3, Math.round(totalWidth * 0.06)), Math.floor(totalWidth / colCnt));
|
|
22879
22940
|
const cap = Math.round(totalWidth * 0.8);
|
|
22880
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));
|
|
22881
22943
|
const widths = Array(colCnt).fill(0);
|
|
22882
22944
|
const free = new Set(raw.map((_, i) => i));
|
|
22883
22945
|
let budget = totalWidth;
|
|
22884
|
-
|
|
22885
|
-
for (
|
|
22886
|
-
|
|
22887
|
-
|
|
22888
|
-
|
|
22889
|
-
|
|
22890
|
-
|
|
22891
|
-
|
|
22892
|
-
|
|
22893
|
-
|
|
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) {
|
|
22894
22958
|
const sumRaw = raw.reduce((a, b) => a + b, 0);
|
|
22895
|
-
for (let i = 0; i < colCnt; i++) widths[i]
|
|
22959
|
+
for (let i = 0; i < colCnt; i++) widths[i] = raw[i] + Math.floor(raw[i] / sumRaw * (totalWidth - sumRaw));
|
|
22960
|
+
free.clear();
|
|
22896
22961
|
} else {
|
|
22897
22962
|
for (; ; ) {
|
|
22898
22963
|
const sum2 = [...free].reduce((a, i) => a + raw[i], 0);
|
|
22899
|
-
const short = [...free].filter((i) => raw[i] / sum2 * budget <
|
|
22964
|
+
const short = [...free].filter((i) => raw[i] / sum2 * budget < floor[i]);
|
|
22900
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);
|
|
22901
22968
|
for (const i of short) {
|
|
22902
|
-
widths[i] = minW;
|
|
22969
|
+
widths[i] = Math.max(minW, Math.floor(floor[i] * scale));
|
|
22903
22970
|
free.delete(i);
|
|
22904
|
-
budget -=
|
|
22971
|
+
budget -= widths[i];
|
|
22905
22972
|
}
|
|
22906
22973
|
if (free.size === 0) break;
|
|
22907
22974
|
}
|
|
@@ -22934,12 +23001,15 @@ function generateTable(rows, theme, style = null, remap = null, seq = 0) {
|
|
|
22934
23001
|
const prof = takeProfile(remap, rowCnt, colCnt, anchorOfMarkdownCell(rows[0]?.[0] ?? ""), seq);
|
|
22935
23002
|
const colMax = Array(colCnt).fill(0);
|
|
22936
23003
|
const colMaxBody = Array(colCnt).fill(0);
|
|
23004
|
+
const colMinWord = Array(colCnt).fill(0);
|
|
22937
23005
|
rows.forEach((row, r) => row.forEach((cell2, c) => {
|
|
22938
23006
|
const w = cellContentWidth(cell2, measureH);
|
|
22939
23007
|
if (w > colMax[c]) colMax[c] = w;
|
|
22940
23008
|
if (r > 0 && w > colMaxBody[c]) colMaxBody[c] = w;
|
|
23009
|
+
const mw = cellMinWordWidth(cell2, measureH);
|
|
23010
|
+
if (mw > colMinWord[c]) colMinWord[c] = mw;
|
|
22941
23011
|
}));
|
|
22942
|
-
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW);
|
|
23012
|
+
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalW, colMinWord);
|
|
22943
23013
|
const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
|
|
22944
23014
|
const labelCol0 = !!reg && colCnt === 2 && colCentered[0] && rows.every((r) => (r[0] ?? "").replace(/\*\*|__|`/g, "").length <= 12);
|
|
22945
23015
|
const tblId = nextTableId();
|
|
@@ -23018,16 +23088,19 @@ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, style = null, r
|
|
|
23018
23088
|
const prof = takeProfile(remap, rowCnt, colCnt, first ? anchorOfHtmlCell(first.inner) : "", seq);
|
|
23019
23089
|
const colMax = Array(colCnt).fill(0);
|
|
23020
23090
|
const colMaxBody = Array(colCnt).fill(0);
|
|
23091
|
+
const colMinWord = Array(colCnt).fill(0);
|
|
23021
23092
|
const cellLines = placed.map((cell2) => htmlCellInnerToLines(cell2.inner).lines);
|
|
23022
23093
|
placed.forEach((cell2, i) => {
|
|
23023
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;
|
|
23024
23096
|
for (let dc = 0; dc < cell2.colSpan; dc++) {
|
|
23025
23097
|
const c = cell2.c + dc;
|
|
23026
23098
|
if (w > colMax[c]) colMax[c] = w;
|
|
23027
23099
|
if (!cell2.isHeader && w > colMaxBody[c]) colMaxBody[c] = w;
|
|
23100
|
+
if (dc === 0 && mw > colMinWord[c]) colMinWord[c] = mw;
|
|
23028
23101
|
}
|
|
23029
23102
|
});
|
|
23030
|
-
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth);
|
|
23103
|
+
const colWidths = profileColWidths(prof, colCnt) ?? computeColWidths(colMax, totalWidth, colMinWord);
|
|
23031
23104
|
const colCentered = colWidths.map((w, c) => colMaxBody[c] + CELL_PAD <= w);
|
|
23032
23105
|
const cellH = style ? Math.round(measureH * 1.6) + 282 : 1500;
|
|
23033
23106
|
const tblW = colWidths.reduce((a, b) => a + b, 0);
|
|
@@ -23139,6 +23212,118 @@ function buildTitleBox(title, titleCharPr, bodyWidth, reg) {
|
|
|
23139
23212
|
return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${table2}</hp:run></hp:p>`;
|
|
23140
23213
|
}
|
|
23141
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
|
+
|
|
23142
23327
|
// src/hwpx/equation-generate.ts
|
|
23143
23328
|
var MAX_EQUATION_SOURCE = 1e4;
|
|
23144
23329
|
var MAX_GROUP_DEPTH = 64;
|
|
@@ -23431,21 +23616,25 @@ function generateSecPr(gongmun) {
|
|
|
23431
23616
|
m.footer = gongmun.headerFooter;
|
|
23432
23617
|
}
|
|
23433
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>`;
|
|
23434
|
-
|
|
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() : "");
|
|
23435
23621
|
}
|
|
23436
|
-
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) {
|
|
23437
23623
|
const paraXmls = [];
|
|
23438
23624
|
let isFirst = true;
|
|
23439
23625
|
let tableSeq = 0;
|
|
23440
23626
|
const orderedCounters = {};
|
|
23441
23627
|
let prevWasOrdered = false;
|
|
23442
23628
|
const gaejosik = gongmun?.preset === "gaejosik";
|
|
23443
|
-
const
|
|
23629
|
+
const measured = !!gongmun && usesReportFonts(gongmun.preset);
|
|
23630
|
+
const vBase = charVariantBase(measured, !!gongmun);
|
|
23444
23631
|
const tableStyle = gongmun ? {
|
|
23445
23632
|
totalWidth: mmToHwpunit(210 - gongmun.margins.left - gongmun.margins.right),
|
|
23446
|
-
|
|
23447
|
-
|
|
23448
|
-
|
|
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,
|
|
23449
23638
|
headerBf: gongmunTableHeaderBf(gaejosik),
|
|
23450
23639
|
centerParaPr: GONGMUN_CENTER,
|
|
23451
23640
|
tblCenterParaPr: GONGMUN_TBL_CENTER,
|
|
@@ -23455,15 +23644,29 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
23455
23644
|
} : null;
|
|
23456
23645
|
const chamMap = (id) => id === CHAR_BOLD ? GJ_CHAR_CHAM_BOLD : id;
|
|
23457
23646
|
let chapterNo = 0;
|
|
23647
|
+
let h2Seq = 0;
|
|
23458
23648
|
let coverH1Idx = -1;
|
|
23459
23649
|
let pendingPageBreak = false;
|
|
23460
23650
|
let pendingNewNum = false;
|
|
23461
23651
|
let titleBoxH1Idx = -1;
|
|
23652
|
+
let pressH1Idx = -1;
|
|
23462
23653
|
let hasFrontPages = false;
|
|
23463
23654
|
const preamble = [];
|
|
23655
|
+
if (gongmun?.reportInfo && dfIds) {
|
|
23656
|
+
preamble.push(buildReportInfo(gongmun, dfIds));
|
|
23657
|
+
}
|
|
23464
23658
|
if (gongmun?.approval && bfReg) {
|
|
23465
23659
|
preamble.push(buildApprovalTable(gongmun.approval, gongmun, bfReg));
|
|
23466
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
|
+
}
|
|
23467
23670
|
if (gaejosik && gongmun) {
|
|
23468
23671
|
const h1Idx = blocks.findIndex((b) => b.type === "heading" && (b.level ?? 1) === 1);
|
|
23469
23672
|
const chapters = blocks.filter((b) => b.type === "heading" && b.level === 2).map((b) => stripChapterNumber(b.text || ""));
|
|
@@ -23488,6 +23691,8 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
23488
23691
|
}
|
|
23489
23692
|
} else if (gongmun && !gaejosik && bfReg && (gongmun.preset === "report" || gongmun.preset === "plan" || gongmun.preset === "notice")) {
|
|
23490
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);
|
|
23491
23696
|
}
|
|
23492
23697
|
if (preamble.length > 0) {
|
|
23493
23698
|
preamble[0] = preamble[0].replace(` pageBreak="1"`, "").replace(/<hp:run charPrIDRef="(\d+)">/, `<hp:run charPrIDRef="$1">${generateSecPr(gongmun)}`);
|
|
@@ -23507,8 +23712,16 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
23507
23712
|
}
|
|
23508
23713
|
switch (block.type) {
|
|
23509
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
|
+
}
|
|
23510
23723
|
if (gongmun && blockIdx === titleBoxH1Idx && tableStyle && bfReg) {
|
|
23511
|
-
xml = buildTitleBox((block.text || "").trim(), CHAR_H1, tableStyle.totalWidth, bfReg);
|
|
23724
|
+
xml = buildTitleBox((block.text || "").trim(), measured ? GJ_CHAR_BODY_TITLE : CHAR_H1, tableStyle.totalWidth, bfReg);
|
|
23512
23725
|
break;
|
|
23513
23726
|
}
|
|
23514
23727
|
if (gaejosik) {
|
|
@@ -23525,18 +23738,24 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
23525
23738
|
(id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id
|
|
23526
23739
|
);
|
|
23527
23740
|
} else {
|
|
23528
|
-
xml = generateParagraph(
|
|
23741
|
+
xml = generateParagraph(`${gongmun.bullet2} ${block.text || ""}`, GONGMUN_LIST_BASE + 1, CHAR_NORMAL);
|
|
23529
23742
|
}
|
|
23530
23743
|
break;
|
|
23531
23744
|
}
|
|
23532
23745
|
const pId = headingParaPrId(block.level || 1);
|
|
23533
23746
|
const cId = headingCharPrId(block.level || 1);
|
|
23534
23747
|
const styleId = gongmun ? Math.min(block.level || 1, 4) : 0;
|
|
23535
|
-
|
|
23748
|
+
let hText = block.text || "";
|
|
23749
|
+
if (gongmun && (block.level || 1) === 2 && gongmun.h2Marker !== "none") {
|
|
23750
|
+
const title = stripChapterNumber(hText);
|
|
23751
|
+
hText = gongmun.h2Marker === "box" ? `\u25A1 ${title}` : `${++h2Seq}. ${title}`;
|
|
23752
|
+
}
|
|
23753
|
+
xml = generateParagraph(hText, pId, cId, void 0, styleId);
|
|
23536
23754
|
break;
|
|
23537
23755
|
}
|
|
23538
23756
|
case "paragraph": {
|
|
23539
|
-
|
|
23757
|
+
const pTrim = (block.text || "").trimStart();
|
|
23758
|
+
if (measured && (pTrim.startsWith("\u203B") || /^\*\s/.test(pTrim))) {
|
|
23540
23759
|
xml = generateParagraph((block.text || "").trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23541
23760
|
break;
|
|
23542
23761
|
}
|
|
@@ -23581,7 +23800,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
23581
23800
|
break;
|
|
23582
23801
|
}
|
|
23583
23802
|
case "blockquote": {
|
|
23584
|
-
if (
|
|
23803
|
+
if (measured) {
|
|
23585
23804
|
const t = (block.text || "").trim();
|
|
23586
23805
|
if (t) xml = generateParagraph(t.startsWith("\u203B") ? t : `\u203B ${t}`, GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23587
23806
|
break;
|
|
@@ -23599,18 +23818,30 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
23599
23818
|
const depth = info?.depth ?? 0;
|
|
23600
23819
|
const marker2 = info?.marker ?? "";
|
|
23601
23820
|
const content = block.text || "";
|
|
23602
|
-
if (
|
|
23821
|
+
if (measured && content.trimStart().startsWith("\u203B")) {
|
|
23603
23822
|
xml = generateParagraph(content.trim(), GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23604
23823
|
break;
|
|
23605
23824
|
}
|
|
23825
|
+
if (measured && block.marker === "*") {
|
|
23826
|
+
xml = generateParagraph(`* ${content.trim()}`, GJ_PARA_CHAM, GJ_CHAR_CHAM, chamMap);
|
|
23827
|
+
break;
|
|
23828
|
+
}
|
|
23606
23829
|
const text = marker2 ? `${marker2} ${content}` : content;
|
|
23830
|
+
const listParaPr = marker2 ? GONGMUN_LIST_BASE + depth : GONGMUN_LIST_PLAIN_BASE + depth;
|
|
23607
23831
|
let listCharPr = gongmun.numbering === "report" && depth === 0 ? CHAR_BOLD : CHAR_NORMAL;
|
|
23608
23832
|
let mapId = fit ? variantMapper(fit, blockIdx, vBase) : void 0;
|
|
23609
|
-
if (
|
|
23833
|
+
if (measured && depth === 0 && gongmun.numbering !== "standard") {
|
|
23610
23834
|
listCharPr = GJ_CHAR_DAE;
|
|
23611
23835
|
mapId = (id) => id === CHAR_BOLD ? GJ_CHAR_DAE_BOLD : id;
|
|
23612
23836
|
}
|
|
23613
|
-
|
|
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);
|
|
23614
23845
|
break;
|
|
23615
23846
|
}
|
|
23616
23847
|
const indent = block.indent || 0;
|
|
@@ -23684,10 +23915,19 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
23684
23915
|
}
|
|
23685
23916
|
paraXmls.push(xml);
|
|
23686
23917
|
}
|
|
23918
|
+
if (gongmun?.noticeHead && dfIds) {
|
|
23919
|
+
paraXmls.push(...buildNoticeFoot(gongmun));
|
|
23920
|
+
}
|
|
23687
23921
|
if (gongmun?.endMark && paraXmls.length > 0) {
|
|
23688
23922
|
const lastText = [...blocks].reverse().find((b) => (b.type === "paragraph" || b.type === "list_item") && (b.text || "").trim())?.text ?? "";
|
|
23689
23923
|
if (!hasEndMark(lastText)) paraXmls.push(buildEndMark());
|
|
23690
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
|
+
}
|
|
23691
23931
|
if (paraXmls.length === 0) {
|
|
23692
23932
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run></hp:p>`);
|
|
23693
23933
|
}
|
|
@@ -23702,14 +23942,18 @@ async function markdownToHwpx(markdown, options) {
|
|
|
23702
23942
|
const theme = resolveTheme(options?.theme);
|
|
23703
23943
|
const gongmun = options?.gongmun ? resolveGongmun(options.gongmun) : null;
|
|
23704
23944
|
const gaejosik = gongmun?.preset === "gaejosik";
|
|
23945
|
+
const measured = !!gongmun && usesReportFonts(gongmun.preset);
|
|
23705
23946
|
const blocks = parseMarkdownToBlocks(markdown);
|
|
23706
23947
|
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
23707
23948
|
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
23708
23949
|
const staticBfEnd = gongmun ? gaejosik ? 11 : 4 : 3;
|
|
23709
|
-
const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(
|
|
23950
|
+
const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(measured, !!gongmun) + (fit?.variants?.length ?? 0) * 4, staticBfEnd) : null;
|
|
23710
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;
|
|
23711
23955
|
const chartParts = [];
|
|
23712
|
-
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap);
|
|
23956
|
+
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap, dfIds);
|
|
23713
23957
|
if (remap && remap.tables.length > 0) {
|
|
23714
23958
|
const unused = remap.tables.filter((t) => !t.used).length;
|
|
23715
23959
|
if (unused === remap.tables.length) {
|
|
@@ -23721,7 +23965,13 @@ async function markdownToHwpx(markdown, options) {
|
|
|
23721
23965
|
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
23722
23966
|
zip.file("META-INF/container.xml", generateContainerXml());
|
|
23723
23967
|
zip.file("Contents/content.hpf", generateManifest(chartParts));
|
|
23724
|
-
zip.file("Contents/header.xml", generateHeaderXml(
|
|
23968
|
+
zip.file("Contents/header.xml", generateHeaderXml(
|
|
23969
|
+
theme,
|
|
23970
|
+
gongmun,
|
|
23971
|
+
fit?.variants ?? [],
|
|
23972
|
+
extraBorderFills,
|
|
23973
|
+
[...remap?.charPrXmls ?? [], ...dfActive ? docframeCharPrXmls(dfBase, measured) : []]
|
|
23974
|
+
));
|
|
23725
23975
|
zip.file("Contents/section0.xml", sectionXml);
|
|
23726
23976
|
for (const part of chartParts) zip.file(part.name, part.xml);
|
|
23727
23977
|
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
@@ -24704,6 +24954,142 @@ function unknownFontWarnings(fonts) {
|
|
|
24704
24954
|
return warnings;
|
|
24705
24955
|
}
|
|
24706
24956
|
|
|
24957
|
+
// src/hwpx/gongmun-lint.ts
|
|
24958
|
+
var RULES = [
|
|
24959
|
+
// 날짜 ─ 온점 뒤 한 칸, 0 패딩 금지, 연도 4자리, 끝 마침표
|
|
24960
|
+
{
|
|
24961
|
+
code: "DATE_NO_SPACE",
|
|
24962
|
+
severity: "error",
|
|
24963
|
+
pattern: /\b\d{4}\.\d{1,2}\.\d{1,2}\.?/g,
|
|
24964
|
+
message: "\uB0A0\uC9DC \uC628\uC810 \uB4A4\uC5D0 \uD55C \uCE78\uC529 \uB744\uC6CC\uC57C \uD568",
|
|
24965
|
+
suggest: "\uC608) 2025. 1. 6."
|
|
24966
|
+
},
|
|
24967
|
+
{
|
|
24968
|
+
code: "DATE_ZERO_PAD",
|
|
24969
|
+
severity: "error",
|
|
24970
|
+
pattern: /\b\d{4}\.\s*0\d\.|\.\s*0\d\./g,
|
|
24971
|
+
message: "\uC6D4\xB7\uC77C \uC55E\uC758 '0'\uC740 \uD45C\uAE30\uD558\uC9C0 \uC54A\uC74C",
|
|
24972
|
+
suggest: "\uC608) 2025. 1. 6. (2025. 01. 06. \u2715)"
|
|
24973
|
+
},
|
|
24974
|
+
{
|
|
24975
|
+
code: "DATE_2DIGIT_YR",
|
|
24976
|
+
severity: "error",
|
|
24977
|
+
pattern: /(?<!\d)['’]\d{2}\.\s*\d/g,
|
|
24978
|
+
message: "\uC5F0\uB3C4\uB294 \uB124 \uC790\uB9AC\uB85C \uD45C\uAE30('24 \u2715)",
|
|
24979
|
+
suggest: "\uC608) 2025. 1. 6."
|
|
24980
|
+
},
|
|
24981
|
+
{
|
|
24982
|
+
code: "DATE_NO_END_DOT",
|
|
24983
|
+
severity: "warning",
|
|
24984
|
+
pattern: /\b\d{4}\.\s\d{1,2}\.\s\d{1,2}(?!\s*[.\d(])/g,
|
|
24985
|
+
message: "\uB0A0\uC9DC\uC758 '\uC77C' \uB2E4\uC74C\uC5D0 \uB9C8\uCE68\uD45C(.)\uB97C \uCC0D\uC5B4\uC57C \uD568",
|
|
24986
|
+
suggest: "\uC608) 2025. 1. 6."
|
|
24987
|
+
},
|
|
24988
|
+
// 시간 ─ 24시각제, 쌍점 붙여쓰기
|
|
24989
|
+
{
|
|
24990
|
+
code: "TIME_AMPM",
|
|
24991
|
+
severity: "error",
|
|
24992
|
+
pattern: /(오전|오후|아침|밤|낮)\s*\d{1,2}\s*시/g,
|
|
24993
|
+
message: "24\uC2DC\uAC01\uC81C \uC22B\uC790\uB85C \uD45C\uAE30(\uC624\uC804/\uC624\uD6C4 \uC0AC\uC6A9 \uC548 \uD568)",
|
|
24994
|
+
suggest: "\uC608) 09:00, 15:30"
|
|
24995
|
+
},
|
|
24996
|
+
{
|
|
24997
|
+
code: "TIME_24H",
|
|
24998
|
+
severity: "warning",
|
|
24999
|
+
pattern: /(?<!\d)24\s*시(?!각)/g,
|
|
25000
|
+
message: "'24\uC2DC'\uBCF4\uB2E4 \uC775\uC77C 00:00 \uB610\uB294 '18:00\uAE4C\uC9C0' \uAD8C\uC7A5",
|
|
25001
|
+
suggest: "\uC608) 18:00"
|
|
25002
|
+
},
|
|
25003
|
+
{
|
|
25004
|
+
code: "TIME_COLON_SP",
|
|
25005
|
+
severity: "error",
|
|
25006
|
+
pattern: /\b\d{1,2}\s+:\s*\d{2}\b|\b\d{1,2}:\s+\d{2}\b/g,
|
|
25007
|
+
message: "\uC2DC\uC640 \uBD84 \uC0AC\uC774 \uC30D\uC810\uC740 \uC591\uCABD\uC744 \uBD99\uC5EC \uC500",
|
|
25008
|
+
suggest: "\uC608) 13:20"
|
|
25009
|
+
},
|
|
25010
|
+
// 금액 ─ '천원' 금지, 금+숫자 붙여쓰기
|
|
25011
|
+
{
|
|
25012
|
+
code: "MONEY_CHEONWON",
|
|
25013
|
+
severity: "error",
|
|
25014
|
+
pattern: /\d+\s*천\s*원/g,
|
|
25015
|
+
message: "\uAE08\uC561\uC740 '\uCC9C\uC6D0'\uC73C\uB85C \uC904\uC774\uC9C0 \uC54A\uACE0 \uC544\uB77C\uBE44\uC544 \uC22B\uC790\uB85C",
|
|
25016
|
+
suggest: "\uC608) 345,000\uC6D0"
|
|
25017
|
+
},
|
|
25018
|
+
{
|
|
25019
|
+
code: "MONEY_GEUM_SP",
|
|
25020
|
+
severity: "warning",
|
|
25021
|
+
pattern: /금\s+\d/g,
|
|
25022
|
+
message: "'\uAE08'\uACFC \uC22B\uC790 \uC0AC\uC774\uB294 \uBD99\uC5EC \uC4F0\uB294 \uAC83\uC774 \uC6D0\uCE59",
|
|
25023
|
+
suggest: "\uC608) \uAE08113,560\uC6D0"
|
|
25024
|
+
},
|
|
25025
|
+
// 붙임 ─ 쌍점 금지(2타 띄움)
|
|
25026
|
+
{
|
|
25027
|
+
code: "BUNIM_COLON",
|
|
25028
|
+
severity: "error",
|
|
25029
|
+
pattern: /붙\s*임\s*:/g,
|
|
25030
|
+
message: "'\uBD99\uC784' \uB2E4\uC74C\uC5D0 \uC30D\uC810(:)\uC744 \uBD99\uC774\uC9C0 \uC54A\uC74C(2\uD0C0 \uB744\uC6C0)",
|
|
25031
|
+
suggest: "\uC608) \uBD99\uC784 \uACC4\uD68D\uC11C 1\uBD80."
|
|
25032
|
+
},
|
|
25033
|
+
// 표기 ─ 물결표+까지 중복, 한글 먼저, 쌍점 띄어쓰기
|
|
25034
|
+
{
|
|
25035
|
+
code: "KKAJI_DUP",
|
|
25036
|
+
severity: "error",
|
|
25037
|
+
pattern: /[∼~~][^\n]{0,20}?까지/g,
|
|
25038
|
+
message: "\uBB3C\uACB0\uD45C(\u223C)\uC640 '\uAE4C\uC9C0'\uB97C \uD568\uAED8 \uC4F0\uC9C0 \uC54A\uC74C",
|
|
25039
|
+
suggest: "\uC608) 2. 20.\u223C2. 24."
|
|
25040
|
+
},
|
|
25041
|
+
{
|
|
25042
|
+
code: "FOREIGN_FIRST",
|
|
25043
|
+
severity: "warning",
|
|
25044
|
+
pattern: /\b[A-Z]{2,5}\s*\([가-힣]/g,
|
|
25045
|
+
message: "\uD55C\uAE00\uC744 \uBA3C\uC800 \uC4F0\uACE0 \uAD04\uD638 \uC548\uC5D0 \uC678\uAD6D\uC5B4\uB97C \uBCD1\uAE30",
|
|
25046
|
+
suggest: "\uC608) \uC5C5\uBB34 \uD611\uC57D(MOU)"
|
|
25047
|
+
},
|
|
25048
|
+
// 쌍점 — URL(https:// 등)·시각(13:20)은 제외
|
|
25049
|
+
{
|
|
25050
|
+
code: "COLON_SPACE",
|
|
25051
|
+
severity: "warning",
|
|
25052
|
+
pattern: /\S\s+:\S|\S:(?!\/\/)[^\s\d]/g,
|
|
25053
|
+
message: "\uC30D\uC810\uC740 \uC55E\uB9D0\uC5D0 \uBD99\uC774\uACE0 \uB4A4\uB294 \uD55C \uCE78 \uB744\uC6C0",
|
|
25054
|
+
suggest: "\uC608) \uC6D0\uC7A5: \uAE40\uAC11\uB3D9"
|
|
25055
|
+
}
|
|
25056
|
+
];
|
|
25057
|
+
function lintGongmunText(text) {
|
|
25058
|
+
const findings = [];
|
|
25059
|
+
let inFence = false;
|
|
25060
|
+
const lines = text.split(/\r?\n/);
|
|
25061
|
+
for (let i = 0; i < lines.length; i++) {
|
|
25062
|
+
const line = lines[i];
|
|
25063
|
+
if (/^\s*(```|~~~)/.test(line)) {
|
|
25064
|
+
inFence = !inFence;
|
|
25065
|
+
continue;
|
|
25066
|
+
}
|
|
25067
|
+
if (inFence) continue;
|
|
25068
|
+
for (const r of RULES) {
|
|
25069
|
+
r.pattern.lastIndex = 0;
|
|
25070
|
+
for (const m of line.matchAll(r.pattern)) {
|
|
25071
|
+
findings.push({
|
|
25072
|
+
line: i + 1,
|
|
25073
|
+
match: m[0].trim(),
|
|
25074
|
+
rule: r.code,
|
|
25075
|
+
severity: r.severity,
|
|
25076
|
+
message: r.message,
|
|
25077
|
+
suggest: r.suggest
|
|
25078
|
+
});
|
|
25079
|
+
}
|
|
25080
|
+
}
|
|
25081
|
+
}
|
|
25082
|
+
return findings;
|
|
25083
|
+
}
|
|
25084
|
+
function gongmunLintWarnings(text, limit = 10) {
|
|
25085
|
+
const findings = lintGongmunText(text);
|
|
25086
|
+
const shown = findings.slice(0, limit).map(
|
|
25087
|
+
(f) => `\uD45C\uAE30\uBC95 [${f.rule}] L${f.line} "${f.match}" \u2014 ${f.message}${f.suggest ? ` (${f.suggest})` : ""}`
|
|
25088
|
+
);
|
|
25089
|
+
if (findings.length > limit) shown.push(`\uD45C\uAE30\uBC95 \uACBD\uACE0 ${findings.length - limit}\uAC74 \uB354 \uC788\uC74C \u2014 kordoc lint\uB85C \uC804\uCCB4 \uD655\uC778`);
|
|
25090
|
+
return shown;
|
|
25091
|
+
}
|
|
25092
|
+
|
|
24707
25093
|
// src/roundtrip/patcher.ts
|
|
24708
25094
|
import JSZip10 from "jszip";
|
|
24709
25095
|
|
|
@@ -28393,7 +28779,7 @@ async function parseHwp(buffer, options) {
|
|
|
28393
28779
|
async function parsePdf(buffer, options) {
|
|
28394
28780
|
let parsePdfDocument;
|
|
28395
28781
|
try {
|
|
28396
|
-
const mod = await import("./parser-
|
|
28782
|
+
const mod = await import("./parser-2Q2YKEJG.js");
|
|
28397
28783
|
parsePdfDocument = mod.parsePdfDocument;
|
|
28398
28784
|
} catch {
|
|
28399
28785
|
return {
|
|
@@ -28508,6 +28894,7 @@ export {
|
|
|
28508
28894
|
fillWithUniqueGuard,
|
|
28509
28895
|
fitRatioForFewerLines,
|
|
28510
28896
|
formatFillValue,
|
|
28897
|
+
gongmunLintWarnings,
|
|
28511
28898
|
hwpxToProfile,
|
|
28512
28899
|
inferFieldType,
|
|
28513
28900
|
isHwpxFile,
|
|
@@ -28516,6 +28903,7 @@ export {
|
|
|
28516
28903
|
isOldHwpFile,
|
|
28517
28904
|
isPdfFile,
|
|
28518
28905
|
isZipFile,
|
|
28906
|
+
lintGongmunText,
|
|
28519
28907
|
markdownToHwpx,
|
|
28520
28908
|
markdownToPdf,
|
|
28521
28909
|
measureTextWidth,
|