@masumdev/markforge 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/App-JOOTPDJN.mjs +847 -0
- package/dist/{chunk-CRV7R2BG.mjs → chunk-H3ZUUSHP.mjs} +303 -98
- package/dist/{chunk-TNWZ4MFS.mjs → chunk-UNWAEVDU.mjs} +4 -3
- package/dist/cli.mjs +14 -6
- package/dist/index.d.mts +117 -50
- package/dist/index.d.ts +117 -50
- package/dist/index.js +838 -145
- package/dist/index.mjs +826 -139
- package/dist/{previewServer-XAUOBNBZ.mjs → previewServer-U47WQ5FV.mjs} +1 -1
- package/package.json +1 -1
- package/dist/App-3QDKBKHG.mjs +0 -328
package/dist/index.mjs
CHANGED
|
@@ -14,8 +14,8 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
// src/core/engine.ts
|
|
17
|
-
import * as
|
|
18
|
-
import * as
|
|
17
|
+
import * as fs7 from "fs";
|
|
18
|
+
import * as path7 from "path";
|
|
19
19
|
|
|
20
20
|
// src/core/parser.ts
|
|
21
21
|
import matter from "gray-matter";
|
|
@@ -189,7 +189,16 @@ function parseInlineSpans(text) {
|
|
|
189
189
|
remaining = remaining.slice(nextSpecial);
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
-
|
|
192
|
+
const merged = [];
|
|
193
|
+
for (const s of spans) {
|
|
194
|
+
const prev = merged[merged.length - 1];
|
|
195
|
+
if (prev && prev.type === "text" && s.type === "text") {
|
|
196
|
+
prev.content += s.content;
|
|
197
|
+
} else {
|
|
198
|
+
merged.push(s);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return merged;
|
|
193
202
|
}
|
|
194
203
|
function slugify(text) {
|
|
195
204
|
return text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -201,6 +210,7 @@ function applyHeadingNumbering(nodes, tocEntries, options) {
|
|
|
201
210
|
const counters = [0, 0, 0, 0, 0, 0];
|
|
202
211
|
for (const node of nodes) {
|
|
203
212
|
if (node.type === "heading" && node.level) {
|
|
213
|
+
if (node._numbered) continue;
|
|
204
214
|
const lvl = node.level;
|
|
205
215
|
if (lvl > depth) continue;
|
|
206
216
|
if (lvl === 1 && skipH1) continue;
|
|
@@ -216,6 +226,7 @@ function applyHeadingNumbering(nodes, tocEntries, options) {
|
|
|
216
226
|
const originalText = node.text || "";
|
|
217
227
|
node.text = fullPrefix + originalText;
|
|
218
228
|
node.inlines = parseInlineSpans(node.text);
|
|
229
|
+
node._numbered = true;
|
|
219
230
|
const toc = tocEntries.find((t) => t.id === node.id);
|
|
220
231
|
if (toc) {
|
|
221
232
|
toc.text = node.text;
|
|
@@ -578,12 +589,16 @@ import {
|
|
|
578
589
|
convertMillimetersToTwip,
|
|
579
590
|
ShadingType,
|
|
580
591
|
ExternalHyperlink,
|
|
581
|
-
TabStopType
|
|
592
|
+
TabStopType,
|
|
593
|
+
PageBreak,
|
|
594
|
+
NumberFormat,
|
|
595
|
+
SectionType
|
|
582
596
|
} from "docx";
|
|
583
597
|
|
|
584
598
|
// src/core/imageResolver.ts
|
|
585
599
|
import * as fs from "fs";
|
|
586
600
|
import * as path from "path";
|
|
601
|
+
import { fileURLToPath } from "url";
|
|
587
602
|
var memoryImageCache = /* @__PURE__ */ new Map();
|
|
588
603
|
function getMimeType(filePathOrUrl) {
|
|
589
604
|
const clean = filePathOrUrl.split("?")[0].toLowerCase();
|
|
@@ -640,9 +655,19 @@ async function resolveImage(src, baseDir = process.cwd()) {
|
|
|
640
655
|
memoryImageCache.set(cacheKey, resolved2);
|
|
641
656
|
return resolved2;
|
|
642
657
|
}
|
|
643
|
-
let localPath =
|
|
658
|
+
let localPath = src;
|
|
659
|
+
if (src.startsWith("file://")) {
|
|
660
|
+
try {
|
|
661
|
+
localPath = fileURLToPath(src);
|
|
662
|
+
} catch {
|
|
663
|
+
localPath = src;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
if (!path.isAbsolute(localPath)) {
|
|
667
|
+
localPath = path.resolve(baseDir, localPath);
|
|
668
|
+
}
|
|
644
669
|
if (!fs.existsSync(localPath)) {
|
|
645
|
-
const cwdPath = path.resolve(process.cwd(), src);
|
|
670
|
+
const cwdPath = path.resolve(process.cwd(), src.startsWith("file://") ? localPath : src);
|
|
646
671
|
if (fs.existsSync(cwdPath)) {
|
|
647
672
|
localPath = cwdPath;
|
|
648
673
|
} else {
|
|
@@ -1065,6 +1090,7 @@ var OutputFormat = /* @__PURE__ */ ((OutputFormat2) => {
|
|
|
1065
1090
|
OutputFormat2["PDF"] = "pdf";
|
|
1066
1091
|
OutputFormat2["HTML"] = "html";
|
|
1067
1092
|
OutputFormat2["PNG"] = "png";
|
|
1093
|
+
OutputFormat2["TXT"] = "txt";
|
|
1068
1094
|
return OutputFormat2;
|
|
1069
1095
|
})(OutputFormat || {});
|
|
1070
1096
|
var Theme = /* @__PURE__ */ ((Theme2) => {
|
|
@@ -1099,6 +1125,33 @@ var WatermarkPosition = /* @__PURE__ */ ((WatermarkPosition2) => {
|
|
|
1099
1125
|
WatermarkPosition2["BOTTOM_RIGHT"] = "bottom-right";
|
|
1100
1126
|
return WatermarkPosition2;
|
|
1101
1127
|
})(WatermarkPosition || {});
|
|
1128
|
+
var CoverPagePreset = /* @__PURE__ */ ((CoverPagePreset2) => {
|
|
1129
|
+
CoverPagePreset2["MODERN"] = "modern";
|
|
1130
|
+
CoverPagePreset2["CORPORATE_SPLIT"] = "corporate-split";
|
|
1131
|
+
CoverPagePreset2["MINIMAL"] = "minimal";
|
|
1132
|
+
CoverPagePreset2["CARD"] = "card";
|
|
1133
|
+
return CoverPagePreset2;
|
|
1134
|
+
})(CoverPagePreset || {});
|
|
1135
|
+
var BackCoverPreset = /* @__PURE__ */ ((BackCoverPreset2) => {
|
|
1136
|
+
BackCoverPreset2["MODERN"] = "modern";
|
|
1137
|
+
BackCoverPreset2["CORPORATE"] = "corporate";
|
|
1138
|
+
BackCoverPreset2["MINIMAL"] = "minimal";
|
|
1139
|
+
BackCoverPreset2["CONTACT_CARD"] = "contact-card";
|
|
1140
|
+
return BackCoverPreset2;
|
|
1141
|
+
})(BackCoverPreset || {});
|
|
1142
|
+
var SignatureAlign = /* @__PURE__ */ ((SignatureAlign2) => {
|
|
1143
|
+
SignatureAlign2["LEFT"] = "left";
|
|
1144
|
+
SignatureAlign2["CENTER"] = "center";
|
|
1145
|
+
SignatureAlign2["RIGHT"] = "right";
|
|
1146
|
+
SignatureAlign2["SPACE_BETWEEN"] = "space-between";
|
|
1147
|
+
return SignatureAlign2;
|
|
1148
|
+
})(SignatureAlign || {});
|
|
1149
|
+
var SignatureStyle = /* @__PURE__ */ ((SignatureStyle2) => {
|
|
1150
|
+
SignatureStyle2["LINE"] = "line";
|
|
1151
|
+
SignatureStyle2["BOX"] = "box";
|
|
1152
|
+
SignatureStyle2["CLEAN"] = "clean";
|
|
1153
|
+
return SignatureStyle2;
|
|
1154
|
+
})(SignatureStyle || {});
|
|
1102
1155
|
|
|
1103
1156
|
// src/core/html/htmlThemes.ts
|
|
1104
1157
|
var THEME_COMPONENTS = `
|
|
@@ -1125,7 +1178,7 @@ var THEME_COMPONENTS = `
|
|
|
1125
1178
|
.document-meta { font-size: 0.9rem; color: var(--mf-text-muted); display: flex; gap: 1.5rem; flex-wrap: wrap; }
|
|
1126
1179
|
|
|
1127
1180
|
/* Table of Contents */
|
|
1128
|
-
.table-of-contents { background: var(--mf-card-bg); border: 1px solid var(--mf-border); border-radius: 8px; padding: 1.5rem 2rem; margin: 2rem 0; }
|
|
1181
|
+
.table-of-contents { background: var(--mf-card-bg); border: 1px solid var(--mf-border); border-radius: 8px; padding: 1.5rem 2rem; margin: 2rem 0; page-break-after: always; break-after: page; }
|
|
1129
1182
|
.table-of-contents h2 { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--mf-text-muted); margin: 0 0 1rem 0; }
|
|
1130
1183
|
.table-of-contents ul { list-style: none; padding: 0; margin: 0; }
|
|
1131
1184
|
.table-of-contents li { padding: 0.25rem 0; }
|
|
@@ -1198,11 +1251,13 @@ var THEME_CORPORATE = `
|
|
|
1198
1251
|
}
|
|
1199
1252
|
body { background-color: var(--mf-bg); color: var(--mf-text); font-family: var(--mf-font-family); font-size: 15px; line-height: 1.65; margin: 0; padding: 2.5rem; }
|
|
1200
1253
|
.document-container { max-width: 860px; margin: 0 auto; position: relative; z-index: 1; }
|
|
1201
|
-
h1, h2, h3, h4, h5, h6 { color: var(--mf-
|
|
1202
|
-
h1 { font-size: 2.2rem; border-bottom:
|
|
1254
|
+
h1, h2, h3, h4, h5, h6 { color: var(--mf-primary-dark); font-weight: 700; margin-top: 1.8rem; margin-bottom: 0.8rem; line-height: 1.25; }
|
|
1255
|
+
h1 { font-size: 2.2rem; color: var(--mf-primary-dark); border-bottom: 2.5px solid var(--mf-primary); padding-bottom: 0.5rem; }
|
|
1203
1256
|
h2 { font-size: 1.6rem; color: var(--mf-primary-dark); border-bottom: 1px solid #CCFBF1; padding-bottom: 0.4rem; }
|
|
1204
|
-
h3 { font-size: 1.3rem; }
|
|
1205
|
-
h4 { font-size: 1.1rem; }
|
|
1257
|
+
h3 { font-size: 1.3rem; color: var(--mf-primary-dark); }
|
|
1258
|
+
h4 { font-size: 1.1rem; color: var(--mf-primary-dark); }
|
|
1259
|
+
h5 { font-size: 1.0rem; color: var(--mf-primary-dark); }
|
|
1260
|
+
h6 { font-size: 0.9rem; color: var(--mf-primary-dark); }
|
|
1206
1261
|
p { margin: 0.8rem 0; }
|
|
1207
1262
|
`;
|
|
1208
1263
|
var THEME_DEFAULT = THEME_CORPORATE;
|
|
@@ -1244,11 +1299,13 @@ function generateThemeCss(theme) {
|
|
|
1244
1299
|
}
|
|
1245
1300
|
body { background-color: var(--mf-bg); color: var(--mf-text); font-family: var(--mf-font-family); font-size: 15px; line-height: 1.65; margin: 0; padding: 2.5rem; }
|
|
1246
1301
|
.document-container { max-width: 860px; margin: 0 auto; position: relative; z-index: 1; }
|
|
1247
|
-
h1, h2, h3, h4, h5, h6 { color: var(--mf-
|
|
1248
|
-
h1 { font-size: 2.2rem; border-bottom:
|
|
1302
|
+
h1, h2, h3, h4, h5, h6 { color: var(--mf-primary-dark); font-weight: 700; margin-top: 1.8rem; margin-bottom: 0.8rem; line-height: 1.25; }
|
|
1303
|
+
h1 { font-size: 2.2rem; color: var(--mf-primary-dark); border-bottom: 2.5px solid var(--mf-primary); padding-bottom: 0.5rem; }
|
|
1249
1304
|
h2 { font-size: 1.6rem; color: var(--mf-primary-dark); border-bottom: 1px solid var(--mf-border); padding-bottom: 0.4rem; }
|
|
1250
|
-
h3 { font-size: 1.3rem; }
|
|
1251
|
-
h4 { font-size: 1.1rem; }
|
|
1305
|
+
h3 { font-size: 1.3rem; color: var(--mf-primary-dark); }
|
|
1306
|
+
h4 { font-size: 1.1rem; color: var(--mf-primary-dark); }
|
|
1307
|
+
h5 { font-size: 1.0rem; color: var(--mf-primary-dark); }
|
|
1308
|
+
h6 { font-size: 0.9rem; color: var(--mf-primary-dark); }
|
|
1252
1309
|
p { margin: 0.8rem 0; }
|
|
1253
1310
|
${theme.customCss || ""}
|
|
1254
1311
|
`;
|
|
@@ -1457,16 +1514,45 @@ function formatMarginCss(margin, defaultCss = "2.5cm") {
|
|
|
1457
1514
|
if (/^[0-9.]+$/.test(str)) return `${str}pt`;
|
|
1458
1515
|
return str;
|
|
1459
1516
|
}
|
|
1460
|
-
function replaceDocumentTokens(template = "", meta) {
|
|
1461
|
-
|
|
1462
|
-
|
|
1517
|
+
function replaceDocumentTokens(template = "", meta = {}) {
|
|
1518
|
+
if (!template) return "";
|
|
1519
|
+
const currentYear = meta.year ? String(meta.year) : (/* @__PURE__ */ new Date()).getFullYear().toString();
|
|
1520
|
+
const tokenMap = {
|
|
1521
|
+
title: meta.title ? String(meta.title) : "",
|
|
1522
|
+
subtitle: meta.subtitle ? String(meta.subtitle) : "",
|
|
1523
|
+
author: meta.author ? Array.isArray(meta.author) ? meta.author.join(", ") : String(meta.author) : "",
|
|
1524
|
+
version: meta.version ? String(meta.version) : "",
|
|
1525
|
+
date: meta.date ? String(meta.date) : "",
|
|
1526
|
+
company: meta.company ? String(meta.company) : "",
|
|
1527
|
+
year: currentYear
|
|
1528
|
+
};
|
|
1529
|
+
if (meta.metadata && typeof meta.metadata === "object") {
|
|
1530
|
+
for (const [key, val] of Object.entries(meta.metadata)) {
|
|
1531
|
+
if (val !== void 0 && val !== null) {
|
|
1532
|
+
tokenMap[key.toLowerCase()] = String(val);
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
for (const [key, val] of Object.entries(meta)) {
|
|
1537
|
+
if (val !== void 0 && val !== null && typeof val !== "object") {
|
|
1538
|
+
tokenMap[key.toLowerCase()] = String(val);
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
return template.replace(/\{([a-zA-Z0-9_\-]+)\}/gi, (match, tokenKey) => {
|
|
1542
|
+
const lowerKey = tokenKey.toLowerCase();
|
|
1543
|
+
if (lowerKey in tokenMap) {
|
|
1544
|
+
return tokenMap[lowerKey];
|
|
1545
|
+
}
|
|
1546
|
+
return match;
|
|
1547
|
+
});
|
|
1463
1548
|
}
|
|
1464
|
-
function normalizeWatermark(rawWatermark) {
|
|
1549
|
+
function normalizeWatermark(rawWatermark, tokens) {
|
|
1465
1550
|
if (!rawWatermark) {
|
|
1466
1551
|
return void 0;
|
|
1467
1552
|
}
|
|
1468
1553
|
if (typeof rawWatermark === "string") {
|
|
1469
|
-
|
|
1554
|
+
let text = rawWatermark.trim();
|
|
1555
|
+
if (tokens) text = replaceDocumentTokens(text, tokens);
|
|
1470
1556
|
if (!text) return void 0;
|
|
1471
1557
|
return {
|
|
1472
1558
|
text,
|
|
@@ -1479,8 +1565,10 @@ function normalizeWatermark(rawWatermark) {
|
|
|
1479
1565
|
}
|
|
1480
1566
|
if (typeof rawWatermark === "object") {
|
|
1481
1567
|
if (!rawWatermark.text || !rawWatermark.text.trim()) return void 0;
|
|
1568
|
+
let text = rawWatermark.text.trim();
|
|
1569
|
+
if (tokens) text = replaceDocumentTokens(text, tokens);
|
|
1482
1570
|
return {
|
|
1483
|
-
text
|
|
1571
|
+
text,
|
|
1484
1572
|
color: rawWatermark.color || "#94a3b8",
|
|
1485
1573
|
opacity: typeof rawWatermark.opacity === "number" ? rawWatermark.opacity : 0.08,
|
|
1486
1574
|
fontSize: rawWatermark.fontSize || 54,
|
|
@@ -1601,27 +1689,46 @@ function normalizeCoverPage(rawCover, tokenCtx = {}) {
|
|
|
1601
1689
|
const cfg = typeof rawCover === "object" ? rawCover : {};
|
|
1602
1690
|
if (cfg.enabled === false) return void 0;
|
|
1603
1691
|
const preset = cfg.preset || "modern";
|
|
1604
|
-
const title = cfg.title ? replaceDocumentTokens(String(cfg.title), tokenCtx) : tokenCtx.title
|
|
1605
|
-
const subtitle = cfg.subtitle ? replaceDocumentTokens(String(cfg.subtitle), tokenCtx) : tokenCtx.subtitle;
|
|
1606
|
-
const author = Array.isArray(cfg.author) ? cfg.author.join(", ") : cfg.author ? replaceDocumentTokens(String(cfg.author), tokenCtx) : tokenCtx.author;
|
|
1607
|
-
const company = cfg.company ? replaceDocumentTokens(String(cfg.company), tokenCtx) : tokenCtx.company;
|
|
1608
|
-
const version = cfg.version ? replaceDocumentTokens(String(cfg.version), tokenCtx) : tokenCtx.version;
|
|
1692
|
+
const title = cfg.title ? replaceDocumentTokens(String(cfg.title), tokenCtx) : tokenCtx.title ? String(tokenCtx.title) : "Document Title";
|
|
1693
|
+
const subtitle = cfg.subtitle ? replaceDocumentTokens(String(cfg.subtitle), tokenCtx) : tokenCtx.subtitle ? String(tokenCtx.subtitle) : void 0;
|
|
1694
|
+
const author = Array.isArray(cfg.author) ? cfg.author.join(", ") : cfg.author ? replaceDocumentTokens(String(cfg.author), tokenCtx) : tokenCtx.author ? String(tokenCtx.author) : void 0;
|
|
1695
|
+
const company = cfg.company ? replaceDocumentTokens(String(cfg.company), tokenCtx) : tokenCtx.company ? String(tokenCtx.company) : void 0;
|
|
1696
|
+
const version = cfg.version ? replaceDocumentTokens(String(cfg.version), tokenCtx) : tokenCtx.version ? String(tokenCtx.version) : void 0;
|
|
1609
1697
|
let dateStr;
|
|
1610
1698
|
if (typeof cfg.date === "string") {
|
|
1611
1699
|
dateStr = replaceDocumentTokens(cfg.date, tokenCtx);
|
|
1612
1700
|
} else if (cfg.date === true) {
|
|
1613
|
-
dateStr = tokenCtx.date
|
|
1701
|
+
dateStr = tokenCtx.date ? String(tokenCtx.date) : (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1614
1702
|
} else {
|
|
1615
|
-
dateStr = tokenCtx.date;
|
|
1703
|
+
dateStr = tokenCtx.date ? String(tokenCtx.date) : void 0;
|
|
1616
1704
|
}
|
|
1617
1705
|
const badge = cfg.badge ? replaceDocumentTokens(String(cfg.badge), tokenCtx) : void 0;
|
|
1618
1706
|
const badgeColor = typeof cfg.badgeColor === "string" ? cfg.badgeColor : void 0;
|
|
1619
1707
|
const badgeTextColor = typeof cfg.badgeTextColor === "string" ? cfg.badgeTextColor : void 0;
|
|
1620
1708
|
const logo = typeof cfg.logo === "string" ? cfg.logo : void 0;
|
|
1621
1709
|
const logoWidth = cfg.logoWidth;
|
|
1622
|
-
const bgGradient = typeof cfg.bgGradient === "string" ? cfg.bgGradient : void 0;
|
|
1710
|
+
const bgGradient = typeof cfg.bgGradient === "string" ? cfg.bgGradient : typeof cfg.backgroundColor === "string" ? cfg.backgroundColor : void 0;
|
|
1711
|
+
const backgroundColor = typeof cfg.backgroundColor === "string" ? cfg.backgroundColor : void 0;
|
|
1623
1712
|
const textColor = typeof cfg.textColor === "string" ? cfg.textColor : void 0;
|
|
1713
|
+
const titleColor = typeof cfg.titleColor === "string" ? cfg.titleColor : void 0;
|
|
1714
|
+
const subtitleColor = typeof cfg.subtitleColor === "string" ? cfg.subtitleColor : void 0;
|
|
1715
|
+
const accentColor = typeof cfg.accentColor === "string" ? cfg.accentColor : void 0;
|
|
1624
1716
|
const footerText = cfg.footerText ? replaceDocumentTokens(String(cfg.footerText), tokenCtx) : void 0;
|
|
1717
|
+
const address = cfg.address ? replaceDocumentTokens(String(cfg.address), tokenCtx) : void 0;
|
|
1718
|
+
const email = cfg.email ? replaceDocumentTokens(String(cfg.email), tokenCtx) : void 0;
|
|
1719
|
+
const phone = cfg.phone ? replaceDocumentTokens(String(cfg.phone), tokenCtx) : void 0;
|
|
1720
|
+
const website = cfg.website ? replaceDocumentTokens(String(cfg.website), tokenCtx) : void 0;
|
|
1721
|
+
let socialMap;
|
|
1722
|
+
if (cfg.social && typeof cfg.social === "object") {
|
|
1723
|
+
socialMap = {};
|
|
1724
|
+
for (const [k, v] of Object.entries(cfg.social)) {
|
|
1725
|
+
if (typeof v === "string") {
|
|
1726
|
+
socialMap[k] = replaceDocumentTokens(v, tokenCtx);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
const currentYear = (/* @__PURE__ */ new Date()).getFullYear().toString();
|
|
1731
|
+
const copyright = cfg.copyright ? replaceDocumentTokens(String(cfg.copyright), { ...tokenCtx, year: currentYear }) : void 0;
|
|
1625
1732
|
return {
|
|
1626
1733
|
enabled: true,
|
|
1627
1734
|
preset,
|
|
@@ -1637,8 +1744,18 @@ function normalizeCoverPage(rawCover, tokenCtx = {}) {
|
|
|
1637
1744
|
logo,
|
|
1638
1745
|
logoWidth,
|
|
1639
1746
|
bgGradient,
|
|
1747
|
+
backgroundColor,
|
|
1640
1748
|
textColor,
|
|
1641
|
-
|
|
1749
|
+
titleColor,
|
|
1750
|
+
subtitleColor,
|
|
1751
|
+
accentColor,
|
|
1752
|
+
footerText,
|
|
1753
|
+
address,
|
|
1754
|
+
email,
|
|
1755
|
+
phone,
|
|
1756
|
+
website,
|
|
1757
|
+
social: socialMap,
|
|
1758
|
+
copyright
|
|
1642
1759
|
};
|
|
1643
1760
|
}
|
|
1644
1761
|
function normalizeBackCover(rawBack, tokenCtx = {}) {
|
|
@@ -1648,7 +1765,10 @@ function normalizeBackCover(rawBack, tokenCtx = {}) {
|
|
|
1648
1765
|
const preset = cfg.preset || "modern";
|
|
1649
1766
|
const title = cfg.title ? replaceDocumentTokens(String(cfg.title), tokenCtx) : "Thank You";
|
|
1650
1767
|
const subtitle = cfg.subtitle ? replaceDocumentTokens(String(cfg.subtitle), tokenCtx) : void 0;
|
|
1651
|
-
const
|
|
1768
|
+
const author = Array.isArray(cfg.author) ? cfg.author.join(", ") : cfg.author ? replaceDocumentTokens(String(cfg.author), tokenCtx) : tokenCtx.author ? String(tokenCtx.author) : void 0;
|
|
1769
|
+
const company = cfg.company ? replaceDocumentTokens(String(cfg.company), tokenCtx) : tokenCtx.company ? String(tokenCtx.company) : void 0;
|
|
1770
|
+
const version = cfg.version ? replaceDocumentTokens(String(cfg.version), tokenCtx) : tokenCtx.version ? String(tokenCtx.version) : void 0;
|
|
1771
|
+
const date = typeof cfg.date === "string" ? replaceDocumentTokens(cfg.date, tokenCtx) : tokenCtx.date ? String(tokenCtx.date) : void 0;
|
|
1652
1772
|
const address = cfg.address ? replaceDocumentTokens(String(cfg.address), tokenCtx) : void 0;
|
|
1653
1773
|
const email = cfg.email ? replaceDocumentTokens(String(cfg.email), tokenCtx) : void 0;
|
|
1654
1774
|
const phone = cfg.phone ? replaceDocumentTokens(String(cfg.phone), tokenCtx) : void 0;
|
|
@@ -1664,32 +1784,45 @@ function normalizeBackCover(rawBack, tokenCtx = {}) {
|
|
|
1664
1784
|
}
|
|
1665
1785
|
const currentYear = (/* @__PURE__ */ new Date()).getFullYear().toString();
|
|
1666
1786
|
const copyright = cfg.copyright ? replaceDocumentTokens(String(cfg.copyright), { ...tokenCtx, year: currentYear }) : company ? `Copyright (c) ${currentYear} ${company}. All Rights Reserved.` : void 0;
|
|
1787
|
+
const footerText = cfg.footerText ? replaceDocumentTokens(String(cfg.footerText), tokenCtx) : void 0;
|
|
1667
1788
|
const badge = cfg.badge ? replaceDocumentTokens(String(cfg.badge), tokenCtx) : void 0;
|
|
1668
1789
|
const badgeColor = typeof cfg.badgeColor === "string" ? cfg.badgeColor : void 0;
|
|
1669
1790
|
const badgeTextColor = typeof cfg.badgeTextColor === "string" ? cfg.badgeTextColor : void 0;
|
|
1670
1791
|
const logo = typeof cfg.logo === "string" ? cfg.logo : void 0;
|
|
1671
1792
|
const logoWidth = cfg.logoWidth;
|
|
1672
|
-
const bgGradient = typeof cfg.bgGradient === "string" ? cfg.bgGradient : void 0;
|
|
1793
|
+
const bgGradient = typeof cfg.bgGradient === "string" ? cfg.bgGradient : typeof cfg.backgroundColor === "string" ? cfg.backgroundColor : void 0;
|
|
1794
|
+
const backgroundColor = typeof cfg.backgroundColor === "string" ? cfg.backgroundColor : void 0;
|
|
1673
1795
|
const textColor = typeof cfg.textColor === "string" ? cfg.textColor : void 0;
|
|
1796
|
+
const titleColor = typeof cfg.titleColor === "string" ? cfg.titleColor : void 0;
|
|
1797
|
+
const subtitleColor = typeof cfg.subtitleColor === "string" ? cfg.subtitleColor : void 0;
|
|
1798
|
+
const accentColor = typeof cfg.accentColor === "string" ? cfg.accentColor : void 0;
|
|
1674
1799
|
return {
|
|
1675
1800
|
enabled: true,
|
|
1676
1801
|
preset,
|
|
1677
1802
|
title,
|
|
1678
1803
|
subtitle,
|
|
1804
|
+
author,
|
|
1679
1805
|
company,
|
|
1806
|
+
version,
|
|
1807
|
+
date,
|
|
1680
1808
|
address,
|
|
1681
1809
|
email,
|
|
1682
1810
|
phone,
|
|
1683
1811
|
website,
|
|
1684
1812
|
social: socialMap,
|
|
1685
1813
|
copyright,
|
|
1814
|
+
footerText,
|
|
1686
1815
|
badge,
|
|
1687
1816
|
badgeColor,
|
|
1688
1817
|
badgeTextColor,
|
|
1689
1818
|
logo,
|
|
1690
1819
|
logoWidth,
|
|
1691
1820
|
bgGradient,
|
|
1692
|
-
|
|
1821
|
+
backgroundColor,
|
|
1822
|
+
textColor,
|
|
1823
|
+
titleColor,
|
|
1824
|
+
subtitleColor,
|
|
1825
|
+
accentColor
|
|
1693
1826
|
};
|
|
1694
1827
|
}
|
|
1695
1828
|
function normalizeNumberHeadings(raw) {
|
|
@@ -1729,7 +1862,15 @@ function resolveDocumentConfig(frontmatter = {}, userConfig = {}) {
|
|
|
1729
1862
|
const version = mergedMeta.version || void 0;
|
|
1730
1863
|
const company = mergedMeta.company || void 0;
|
|
1731
1864
|
const lang = mergedMeta.lang || "en";
|
|
1732
|
-
const tokenContext = {
|
|
1865
|
+
const tokenContext = {
|
|
1866
|
+
...mergedMeta,
|
|
1867
|
+
title,
|
|
1868
|
+
subtitle,
|
|
1869
|
+
author,
|
|
1870
|
+
version,
|
|
1871
|
+
date,
|
|
1872
|
+
company
|
|
1873
|
+
};
|
|
1733
1874
|
const theme = mergedMeta.theme || userConfig.theme || DEFAULT_CONFIG.theme;
|
|
1734
1875
|
const orientation = mergedMeta.orientation || userConfig.orientation || DEFAULT_CONFIG.orientation;
|
|
1735
1876
|
const paperSize = mergedMeta.paperSize || userConfig.paperSize || DEFAULT_CONFIG.paperSize;
|
|
@@ -1758,7 +1899,7 @@ function resolveDocumentConfig(frontmatter = {}, userConfig = {}) {
|
|
|
1758
1899
|
const footer = normalizeHeaderFooter(rawFooter, tokenContext);
|
|
1759
1900
|
const toc = typeof mergedMeta.toc === "boolean" ? mergedMeta.toc : typeof userConfig.toc === "boolean" ? userConfig.toc : DEFAULT_CONFIG.toc;
|
|
1760
1901
|
const rawWatermark = mergedMeta.watermark !== void 0 ? mergedMeta.watermark : userConfig.watermark !== void 0 ? userConfig.watermark : DEFAULT_CONFIG.watermark;
|
|
1761
|
-
const watermark = normalizeWatermark(rawWatermark);
|
|
1902
|
+
const watermark = normalizeWatermark(rawWatermark, tokenContext);
|
|
1762
1903
|
const rawSignatures = mergedMeta.signatures || userConfig.signatures;
|
|
1763
1904
|
const signatures = normalizeSignatures(rawSignatures, tokenContext);
|
|
1764
1905
|
const rawCover = mergedMeta.coverPage !== void 0 ? mergedMeta.coverPage : userConfig.coverPage;
|
|
@@ -1854,7 +1995,7 @@ var KATEX_INLINE_CSS = `
|
|
|
1854
1995
|
function escapeHtml(str) {
|
|
1855
1996
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1856
1997
|
}
|
|
1857
|
-
async function renderInlinesToHtml(spans = [], baseDir = process.cwd()) {
|
|
1998
|
+
async function renderInlinesToHtml(spans = [], baseDir = process.cwd(), tokens) {
|
|
1858
1999
|
let result = "";
|
|
1859
2000
|
for (const span of spans) {
|
|
1860
2001
|
if (span.type === "image" && span.url) {
|
|
@@ -1868,23 +2009,23 @@ async function renderInlinesToHtml(spans = [], baseDir = process.cwd()) {
|
|
|
1868
2009
|
continue;
|
|
1869
2010
|
}
|
|
1870
2011
|
if (span.type === "link" && span.url) {
|
|
1871
|
-
const inner = span.children ? await renderInlinesToHtml(span.children, baseDir) : escapeHtml(span.content);
|
|
2012
|
+
const inner = span.children ? await renderInlinesToHtml(span.children, baseDir, tokens) : escapeHtml(tokens ? replaceDocumentTokens(span.content, tokens) : span.content);
|
|
1872
2013
|
const title = span.title ? ` title="${escapeHtml(span.title)}"` : "";
|
|
1873
2014
|
result += `<a href="${escapeHtml(span.url)}"${title}>${inner}</a>`;
|
|
1874
2015
|
continue;
|
|
1875
2016
|
}
|
|
1876
2017
|
if (span.type === "bold") {
|
|
1877
|
-
const inner = span.children ? await renderInlinesToHtml(span.children, baseDir) : escapeHtml(span.content);
|
|
2018
|
+
const inner = span.children ? await renderInlinesToHtml(span.children, baseDir, tokens) : escapeHtml(tokens ? replaceDocumentTokens(span.content, tokens) : span.content);
|
|
1878
2019
|
result += `<strong>${inner}</strong>`;
|
|
1879
2020
|
continue;
|
|
1880
2021
|
}
|
|
1881
2022
|
if (span.type === "italic") {
|
|
1882
|
-
const inner = span.children ? await renderInlinesToHtml(span.children, baseDir) : escapeHtml(span.content);
|
|
2023
|
+
const inner = span.children ? await renderInlinesToHtml(span.children, baseDir, tokens) : escapeHtml(tokens ? replaceDocumentTokens(span.content, tokens) : span.content);
|
|
1883
2024
|
result += `<em>${inner}</em>`;
|
|
1884
2025
|
continue;
|
|
1885
2026
|
}
|
|
1886
2027
|
if (span.type === "strikethrough") {
|
|
1887
|
-
const inner = span.children ? await renderInlinesToHtml(span.children, baseDir) : escapeHtml(span.content);
|
|
2028
|
+
const inner = span.children ? await renderInlinesToHtml(span.children, baseDir, tokens) : escapeHtml(tokens ? replaceDocumentTokens(span.content, tokens) : span.content);
|
|
1888
2029
|
result += `<del>${inner}</del>`;
|
|
1889
2030
|
continue;
|
|
1890
2031
|
}
|
|
@@ -1905,21 +2046,23 @@ async function renderInlinesToHtml(spans = [], baseDir = process.cwd()) {
|
|
|
1905
2046
|
result += span.content;
|
|
1906
2047
|
continue;
|
|
1907
2048
|
}
|
|
1908
|
-
|
|
2049
|
+
const content = tokens ? replaceDocumentTokens(span.content, tokens) : span.content;
|
|
2050
|
+
result += escapeHtml(content);
|
|
1909
2051
|
}
|
|
1910
2052
|
return result;
|
|
1911
2053
|
}
|
|
1912
|
-
async function renderNodesToHtml(nodes, resolved, baseDir = process.cwd()) {
|
|
2054
|
+
async function renderNodesToHtml(nodes, resolved, baseDir = process.cwd(), tokens) {
|
|
1913
2055
|
let bodyHtml = "";
|
|
2056
|
+
const tokenCtx = tokens || resolved;
|
|
1914
2057
|
for (const node of nodes) {
|
|
1915
2058
|
if (node.type === "heading") {
|
|
1916
|
-
const inner = await renderInlinesToHtml(node.inlines, baseDir);
|
|
2059
|
+
const inner = await renderInlinesToHtml(node.inlines, baseDir, tokenCtx);
|
|
1917
2060
|
bodyHtml += ` <h${node.level} id="${node.id}">${inner}</h${node.level}>
|
|
1918
2061
|
`;
|
|
1919
2062
|
continue;
|
|
1920
2063
|
}
|
|
1921
2064
|
if (node.type === "paragraph") {
|
|
1922
|
-
const inner = await renderInlinesToHtml(node.inlines, baseDir);
|
|
2065
|
+
const inner = await renderInlinesToHtml(node.inlines, baseDir, tokenCtx);
|
|
1923
2066
|
bodyHtml += ` <p>${inner}</p>
|
|
1924
2067
|
`;
|
|
1925
2068
|
continue;
|
|
@@ -1934,7 +2077,7 @@ async function renderNodesToHtml(nodes, resolved, baseDir = process.cwd()) {
|
|
|
1934
2077
|
const gap = node.columnGap || "1.5rem";
|
|
1935
2078
|
let colChildrenHtml = "";
|
|
1936
2079
|
for (const col of node.children || []) {
|
|
1937
|
-
const colInner = await renderNodesToHtml(col.children || [], resolved, baseDir);
|
|
2080
|
+
const colInner = await renderNodesToHtml(col.children || [], resolved, baseDir, tokenCtx);
|
|
1938
2081
|
colChildrenHtml += ` <div class="markforge-col">
|
|
1939
2082
|
${colInner} </div>
|
|
1940
2083
|
`;
|
|
@@ -1960,7 +2103,7 @@ ${escapeHtml(node.text || "")}
|
|
|
1960
2103
|
continue;
|
|
1961
2104
|
}
|
|
1962
2105
|
if (node.type === "callout") {
|
|
1963
|
-
const inner = await renderInlinesToHtml(node.inlines, baseDir);
|
|
2106
|
+
const inner = await renderInlinesToHtml(node.inlines, baseDir, tokenCtx);
|
|
1964
2107
|
const CALLOUT_STYLES = {
|
|
1965
2108
|
NOTE: { bg: "#ECFDFD", border: "#33CDCF", titleColor: "#009DA0" },
|
|
1966
2109
|
TIP: { bg: "#ecfdf5", border: "#10b981", titleColor: "#10b981" },
|
|
@@ -1980,7 +2123,7 @@ ${escapeHtml(node.text || "")}
|
|
|
1980
2123
|
continue;
|
|
1981
2124
|
}
|
|
1982
2125
|
if (node.type === "blockquote") {
|
|
1983
|
-
const inner = await renderInlinesToHtml(node.inlines, baseDir);
|
|
2126
|
+
const inner = await renderInlinesToHtml(node.inlines, baseDir, tokenCtx);
|
|
1984
2127
|
bodyHtml += ` <blockquote>${inner}</blockquote>
|
|
1985
2128
|
`;
|
|
1986
2129
|
continue;
|
|
@@ -1994,7 +2137,7 @@ ${escapeHtml(node.text || "")}
|
|
|
1994
2137
|
for (const cell of row.children || []) {
|
|
1995
2138
|
const tag = cell.isHeader ? "th" : "td";
|
|
1996
2139
|
const align = cell.align ? ` align="${cell.align}"` : "";
|
|
1997
|
-
const inner = await renderInlinesToHtml(cell.inlines, baseDir);
|
|
2140
|
+
const inner = await renderInlinesToHtml(cell.inlines, baseDir, tokenCtx);
|
|
1998
2141
|
bodyHtml += ` <${tag}${align}>${inner}</${tag}>
|
|
1999
2142
|
`;
|
|
2000
2143
|
}
|
|
@@ -2010,7 +2153,7 @@ ${escapeHtml(node.text || "")}
|
|
|
2010
2153
|
bodyHtml += ` <${tag}>
|
|
2011
2154
|
`;
|
|
2012
2155
|
for (const item of node.children) {
|
|
2013
|
-
const inner = await renderInlinesToHtml(item.inlines, baseDir);
|
|
2156
|
+
const inner = await renderInlinesToHtml(item.inlines, baseDir, tokenCtx);
|
|
2014
2157
|
bodyHtml += ` <li>${inner}</li>
|
|
2015
2158
|
`;
|
|
2016
2159
|
}
|
|
@@ -2323,8 +2466,8 @@ async function renderBackCoverHtml(backCover, baseDir = process.cwd()) {
|
|
|
2323
2466
|
`;
|
|
2324
2467
|
return { html, css };
|
|
2325
2468
|
}
|
|
2326
|
-
async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
2327
|
-
var _a;
|
|
2469
|
+
async function buildHtmlDocument(doc, config = {}, baseDir = process.cwd()) {
|
|
2470
|
+
var _a, _b;
|
|
2328
2471
|
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
2329
2472
|
const baseThemeCss = generateThemeCss(resolved.theme);
|
|
2330
2473
|
let customCss = "";
|
|
@@ -2420,6 +2563,9 @@ async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2420
2563
|
bodyHtml += ` </header>
|
|
2421
2564
|
`;
|
|
2422
2565
|
}
|
|
2566
|
+
if (((_b = resolved.numberHeadings) == null ? void 0 : _b.enabled) !== false && resolved.numberHeadings) {
|
|
2567
|
+
applyHeadingNumbering(doc.nodes, doc.tocEntries, resolved.numberHeadings);
|
|
2568
|
+
}
|
|
2423
2569
|
if (resolved.toc && doc.tocEntries.length > 0) {
|
|
2424
2570
|
bodyHtml += ` <nav class="table-of-contents">
|
|
2425
2571
|
`;
|
|
@@ -2435,12 +2581,26 @@ async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2435
2581
|
</nav>
|
|
2436
2582
|
`;
|
|
2437
2583
|
}
|
|
2438
|
-
|
|
2584
|
+
const mergedTokens = {
|
|
2585
|
+
...config.metadata,
|
|
2586
|
+
...doc.metadata,
|
|
2587
|
+
...resolved,
|
|
2588
|
+
title: resolved.title,
|
|
2589
|
+
subtitle: resolved.subtitle,
|
|
2590
|
+
author: resolved.author,
|
|
2591
|
+
version: resolved.version,
|
|
2592
|
+
date: resolved.date,
|
|
2593
|
+
company: resolved.company
|
|
2594
|
+
};
|
|
2595
|
+
const nodesHtml = await renderNodesToHtml(doc.nodes, resolved, baseDir, mergedTokens);
|
|
2596
|
+
bodyHtml += ` <main class="markforge-content-body">
|
|
2597
|
+
${nodesHtml} </main>
|
|
2598
|
+
`;
|
|
2439
2599
|
let footnotesHtml = "";
|
|
2440
2600
|
if (doc.footnoteDefs && doc.footnoteDefs.length > 0) {
|
|
2441
2601
|
let fnListHtml = "";
|
|
2442
2602
|
for (const def of doc.footnoteDefs) {
|
|
2443
|
-
const defInner = await renderInlinesToHtml(def.inlines, baseDir);
|
|
2603
|
+
const defInner = await renderInlinesToHtml(def.inlines, baseDir, mergedTokens);
|
|
2444
2604
|
fnListHtml += ` <li id="fn-${escapeHtml(def.id)}">${defInner} <a href="#fnref-${escapeHtml(def.id)}" class="markforge-fn-return">↩</a></li>
|
|
2445
2605
|
`;
|
|
2446
2606
|
}
|
|
@@ -2478,17 +2638,7 @@ ${fnListHtml} </ol>
|
|
|
2478
2638
|
}
|
|
2479
2639
|
@media print {
|
|
2480
2640
|
.document-watermark {
|
|
2481
|
-
|
|
2482
|
-
top: 0;
|
|
2483
|
-
left: 0;
|
|
2484
|
-
right: 0;
|
|
2485
|
-
bottom: 0;
|
|
2486
|
-
width: 100vw;
|
|
2487
|
-
height: 100vh;
|
|
2488
|
-
pointer-events: none;
|
|
2489
|
-
z-index: 0;
|
|
2490
|
-
-webkit-print-color-adjust: exact;
|
|
2491
|
-
print-color-adjust: exact;
|
|
2641
|
+
display: none !important;
|
|
2492
2642
|
}
|
|
2493
2643
|
}
|
|
2494
2644
|
`;
|
|
@@ -2667,8 +2817,11 @@ function escapeXml(str) {
|
|
|
2667
2817
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
2668
2818
|
}
|
|
2669
2819
|
function generateWatermarkPngBuffer(chromePath, wm) {
|
|
2670
|
-
const
|
|
2671
|
-
const
|
|
2820
|
+
const tmpId = Math.random().toString(36).substring(2, 9);
|
|
2821
|
+
const tmpDir = os.tmpdir();
|
|
2822
|
+
const tmpHtml = path4.join(tmpDir, `markforge-wm-${tmpId}.html`);
|
|
2823
|
+
const tmpPng = path4.join(tmpDir, `markforge-wm-${tmpId}.png`);
|
|
2824
|
+
const tmpProfile = path4.join(tmpDir, `markforge-wm-prof-${tmpId}`);
|
|
2672
2825
|
try {
|
|
2673
2826
|
const text = escapeXml(wm.text.toUpperCase());
|
|
2674
2827
|
const fontSize = (wm.fontSize || 52) * 1.5;
|
|
@@ -2719,6 +2872,9 @@ function generateWatermarkPngBuffer(chromePath, wm) {
|
|
|
2719
2872
|
chromePath,
|
|
2720
2873
|
[
|
|
2721
2874
|
"--headless=new",
|
|
2875
|
+
`--user-data-dir=${tmpProfile}`,
|
|
2876
|
+
"--no-first-run",
|
|
2877
|
+
"--no-default-browser-check",
|
|
2722
2878
|
"--disable-gpu",
|
|
2723
2879
|
"--disable-sync",
|
|
2724
2880
|
"--disable-extensions",
|
|
@@ -2740,6 +2896,7 @@ function generateWatermarkPngBuffer(chromePath, wm) {
|
|
|
2740
2896
|
try {
|
|
2741
2897
|
if (fs4.existsSync(tmpHtml)) fs4.unlinkSync(tmpHtml);
|
|
2742
2898
|
if (fs4.existsSync(tmpPng)) fs4.unlinkSync(tmpPng);
|
|
2899
|
+
if (fs4.existsSync(tmpProfile)) fs4.rmSync(tmpProfile, { recursive: true, force: true });
|
|
2743
2900
|
} catch {
|
|
2744
2901
|
}
|
|
2745
2902
|
}
|
|
@@ -2755,6 +2912,8 @@ function findChromeExecutable() {
|
|
|
2755
2912
|
const winLocalAppData = process.env.LOCALAPPDATA ?? "";
|
|
2756
2913
|
const winProgramFiles = process.env.PROGRAMFILES ?? "C:\\Program Files";
|
|
2757
2914
|
const winProgramFilesX86 = process.env["PROGRAMFILES(X86)"] ?? "C:\\Program Files (x86)";
|
|
2915
|
+
const winProgramW6432 = process.env.ProgramW6432 ?? "C:\\Program Files";
|
|
2916
|
+
const winUserProfile = process.env.USERPROFILE ?? "";
|
|
2758
2917
|
const candidates = [
|
|
2759
2918
|
// Linux
|
|
2760
2919
|
"/usr/bin/google-chrome",
|
|
@@ -2773,17 +2932,34 @@ function findChromeExecutable() {
|
|
|
2773
2932
|
// Windows — Microsoft Edge (Native Windows 10/11 browser, enterprise whitelist friendly)
|
|
2774
2933
|
`${winProgramFiles}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
2775
2934
|
`${winProgramFilesX86}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
2935
|
+
`${winProgramW6432}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
2776
2936
|
`${winLocalAppData}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
2777
|
-
|
|
2937
|
+
`${winLocalAppData}\\Microsoft\\Edge Dev\\Application\\msedge.exe`,
|
|
2938
|
+
`${winLocalAppData}\\Microsoft\\Edge Beta\\Application\\msedge.exe`,
|
|
2939
|
+
// Windows — Google Chrome & Chrome SxS (Canary)
|
|
2778
2940
|
`${winProgramFiles}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
2779
2941
|
`${winProgramFilesX86}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
2942
|
+
`${winProgramW6432}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
2780
2943
|
`${winLocalAppData}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
2944
|
+
`${winLocalAppData}\\Google\\Chrome SxS\\Application\\chrome.exe`,
|
|
2781
2945
|
// Windows — Brave Browser
|
|
2782
2946
|
`${winProgramFiles}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
2783
2947
|
`${winProgramFilesX86}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
2948
|
+
`${winProgramW6432}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
2784
2949
|
`${winLocalAppData}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
2785
2950
|
// Windows — Chromium
|
|
2786
|
-
`${winLocalAppData}\\Chromium\\Application\\chrome.exe
|
|
2951
|
+
`${winLocalAppData}\\Chromium\\Application\\chrome.exe`,
|
|
2952
|
+
// Windows — Scoop Package Manager
|
|
2953
|
+
`${winUserProfile}\\scoop\\apps\\googlechrome\\current\\chrome.exe`,
|
|
2954
|
+
`${winUserProfile}\\scoop\\apps\\chromium\\current\\chrome.exe`,
|
|
2955
|
+
`${winUserProfile}\\scoop\\apps\\brave\\current\\brave.exe`,
|
|
2956
|
+
`${winUserProfile}\\scoop\\apps\\msedge\\current\\msedge.exe`,
|
|
2957
|
+
`${winUserProfile}\\scoop\\shims\\chrome.exe`,
|
|
2958
|
+
`${winUserProfile}\\scoop\\shims\\msedge.exe`,
|
|
2959
|
+
// Windows — Chocolatey
|
|
2960
|
+
"C:\\ProgramData\\chocolatey\\bin\\chrome.exe",
|
|
2961
|
+
"C:\\ProgramData\\chocolatey\\bin\\msedge.exe",
|
|
2962
|
+
"C:\\ProgramData\\chocolatey\\bin\\brave.exe"
|
|
2787
2963
|
].filter(Boolean);
|
|
2788
2964
|
for (const candidate of candidates) {
|
|
2789
2965
|
try {
|
|
@@ -2794,13 +2970,15 @@ function findChromeExecutable() {
|
|
|
2794
2970
|
}
|
|
2795
2971
|
}
|
|
2796
2972
|
try {
|
|
2797
|
-
const cmd = isWin ? "where" : "which";
|
|
2798
|
-
const names = isWin ? ["chrome", "msedge", "brave", "google-chrome", "chromium", "chromium-browser"] : ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser", "microsoft-edge", "brave-browser"];
|
|
2973
|
+
const cmd = isWin ? "where.exe" : "which";
|
|
2974
|
+
const names = isWin ? ["chrome.exe", "msedge.exe", "brave.exe", "chrome", "msedge", "brave", "google-chrome", "chromium", "chromium-browser"] : ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser", "microsoft-edge", "brave-browser"];
|
|
2799
2975
|
for (const name of names) {
|
|
2800
|
-
const res = spawnSync(cmd, [name], { encoding: "utf-8" });
|
|
2976
|
+
const res = spawnSync(cmd, [name], { encoding: "utf-8", windowsHide: true });
|
|
2801
2977
|
if (res.status === 0 && res.stdout.trim()) {
|
|
2802
|
-
const
|
|
2803
|
-
|
|
2978
|
+
const lines = res.stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
2979
|
+
for (const line of lines) {
|
|
2980
|
+
if (fs4.existsSync(line)) return line;
|
|
2981
|
+
}
|
|
2804
2982
|
}
|
|
2805
2983
|
}
|
|
2806
2984
|
} catch {
|
|
@@ -2808,7 +2986,7 @@ function findChromeExecutable() {
|
|
|
2808
2986
|
return null;
|
|
2809
2987
|
}
|
|
2810
2988
|
function injectPagedMediaStyles(html, config, metadata) {
|
|
2811
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
2989
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
2812
2990
|
const resolved = resolveDocumentConfig(metadata || {}, config);
|
|
2813
2991
|
const size = resolved.paperSize;
|
|
2814
2992
|
const orientation = resolved.orientation;
|
|
@@ -2883,9 +3061,11 @@ function injectPagedMediaStyles(html, config, metadata) {
|
|
|
2883
3061
|
min-height: 100vh;
|
|
2884
3062
|
height: 100vh;
|
|
2885
3063
|
box-sizing: border-box;
|
|
3064
|
+
break-before: page;
|
|
3065
|
+
break-after: avoid;
|
|
2886
3066
|
}` : "";
|
|
2887
|
-
const
|
|
2888
|
-
@page {
|
|
3067
|
+
const tocPageCss = resolved.toc ? `
|
|
3068
|
+
@page toc-page {
|
|
2889
3069
|
size: ${size} ${orientation};
|
|
2890
3070
|
margin-top: ${top};
|
|
2891
3071
|
margin-bottom: ${bottom};
|
|
@@ -2896,9 +3076,36 @@ function injectPagedMediaStyles(html, config, metadata) {
|
|
|
2896
3076
|
${buildZoneCss("top-right", (_e = resolved.header) == null ? void 0 : _e.right)}
|
|
2897
3077
|
${buildZoneCss("bottom-left", (_f = resolved.footer) == null ? void 0 : _f.left)}
|
|
2898
3078
|
${buildZoneCss("bottom-center", (_g = resolved.footer) == null ? void 0 : _g.center)}
|
|
2899
|
-
|
|
3079
|
+
@bottom-right {
|
|
3080
|
+
content: counter(page, lower-roman);
|
|
3081
|
+
font-size: 9pt;
|
|
3082
|
+
color: #94a3b8;
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
.table-of-contents {
|
|
3086
|
+
page: toc-page;
|
|
3087
|
+
page-break-after: always;
|
|
3088
|
+
break-after: page;
|
|
3089
|
+
}
|
|
3090
|
+
.markforge-content-body {
|
|
3091
|
+
counter-reset: page 1;
|
|
3092
|
+
}` : "";
|
|
3093
|
+
const pagedCss = `
|
|
3094
|
+
@page {
|
|
3095
|
+
size: ${size} ${orientation};
|
|
3096
|
+
margin-top: ${top};
|
|
3097
|
+
margin-bottom: ${bottom};
|
|
3098
|
+
margin-left: ${left};
|
|
3099
|
+
margin-right: ${right};
|
|
3100
|
+
${buildZoneCss("top-left", (_h = resolved.header) == null ? void 0 : _h.left)}
|
|
3101
|
+
${buildZoneCss("top-center", (_i = resolved.header) == null ? void 0 : _i.center)}
|
|
3102
|
+
${buildZoneCss("top-right", (_j = resolved.header) == null ? void 0 : _j.right)}
|
|
3103
|
+
${buildZoneCss("bottom-left", (_k = resolved.footer) == null ? void 0 : _k.left)}
|
|
3104
|
+
${buildZoneCss("bottom-center", (_l = resolved.footer) == null ? void 0 : _l.center)}
|
|
3105
|
+
${buildZoneCss("bottom-right", (_m = resolved.footer) == null ? void 0 : _m.right, true)}
|
|
2900
3106
|
}
|
|
2901
3107
|
${coverPageCss}
|
|
3108
|
+
${tocPageCss}
|
|
2902
3109
|
${backCoverCss}
|
|
2903
3110
|
@media print {
|
|
2904
3111
|
body { padding: 0; }
|
|
@@ -3029,9 +3236,10 @@ async function buildPdfDocument(doc, config, baseDir = process.cwd()) {
|
|
|
3029
3236
|
const wmPng = generateWatermarkPngBuffer(chromePath, resolved.watermark);
|
|
3030
3237
|
if (wmPng) {
|
|
3031
3238
|
const embeddedPng = await pdfDoc.embedPng(wmPng);
|
|
3239
|
+
const totalPages = pdfDoc.getPageCount();
|
|
3032
3240
|
const pages = pdfDoc.getPages();
|
|
3033
3241
|
const startPageIndex = ((_b = resolved.coverPage) == null ? void 0 : _b.enabled) ? 1 : 0;
|
|
3034
|
-
const endPageIndex = ((_c = resolved.backCover) == null ? void 0 : _c.enabled) ?
|
|
3242
|
+
const endPageIndex = ((_c = resolved.backCover) == null ? void 0 : _c.enabled) ? totalPages - 1 : totalPages;
|
|
3035
3243
|
for (let i = startPageIndex; i < endPageIndex; i++) {
|
|
3036
3244
|
const page = pages[i];
|
|
3037
3245
|
const { width, height } = page.getSize();
|
|
@@ -3104,6 +3312,8 @@ async function renderMermaidToPng(mermaidCode, _baseDir = process.cwd()) {
|
|
|
3104
3312
|
const tmpDir = os2.tmpdir();
|
|
3105
3313
|
const tmpHtml = path5.join(tmpDir, `mermaid_${tmpId}.html`);
|
|
3106
3314
|
const tmpScreenshot = path5.join(tmpDir, `mermaid_${tmpId}.png`);
|
|
3315
|
+
const tmpProfile = path5.join(tmpDir, `mermaid_prof_${tmpId}`);
|
|
3316
|
+
const isWin = process.platform === "win32";
|
|
3107
3317
|
const htmlContent = `<!DOCTYPE html>
|
|
3108
3318
|
<html>
|
|
3109
3319
|
<head>
|
|
@@ -3147,10 +3357,14 @@ ${mermaidCode}
|
|
|
3147
3357
|
const res = spawnSync2(
|
|
3148
3358
|
chromePath,
|
|
3149
3359
|
[
|
|
3150
|
-
"--headless",
|
|
3360
|
+
"--headless=new",
|
|
3361
|
+
`--user-data-dir=${tmpProfile}`,
|
|
3362
|
+
"--no-first-run",
|
|
3363
|
+
"--no-default-browser-check",
|
|
3151
3364
|
"--disable-gpu",
|
|
3152
|
-
"--
|
|
3153
|
-
"--disable-
|
|
3365
|
+
"--disable-sync",
|
|
3366
|
+
"--disable-extensions",
|
|
3367
|
+
...isWin ? [] : ["--no-sandbox", "--disable-setuid-sandbox"],
|
|
3154
3368
|
"--allow-file-access-from-files",
|
|
3155
3369
|
"--disable-web-security",
|
|
3156
3370
|
"--disable-software-rasterizer",
|
|
@@ -3159,7 +3373,7 @@ ${mermaidCode}
|
|
|
3159
3373
|
`--screenshot=${tmpScreenshot}`,
|
|
3160
3374
|
fileUrl
|
|
3161
3375
|
],
|
|
3162
|
-
{ timeout: 15e3 }
|
|
3376
|
+
{ timeout: 15e3, windowsHide: true }
|
|
3163
3377
|
);
|
|
3164
3378
|
if (res.status === 0 && fs5.existsSync(tmpScreenshot)) {
|
|
3165
3379
|
const buffer = fs5.readFileSync(tmpScreenshot);
|
|
@@ -3170,6 +3384,7 @@ ${mermaidCode}
|
|
|
3170
3384
|
try {
|
|
3171
3385
|
if (fs5.existsSync(tmpHtml)) fs5.unlinkSync(tmpHtml);
|
|
3172
3386
|
if (fs5.existsSync(tmpScreenshot)) fs5.unlinkSync(tmpScreenshot);
|
|
3387
|
+
if (fs5.existsSync(tmpProfile)) fs5.rmSync(tmpProfile, { recursive: true, force: true });
|
|
3173
3388
|
} catch {
|
|
3174
3389
|
}
|
|
3175
3390
|
}
|
|
@@ -3371,7 +3586,7 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd(), opt
|
|
|
3371
3586
|
return runs;
|
|
3372
3587
|
}
|
|
3373
3588
|
async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
3374
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
3589
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
3375
3590
|
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
3376
3591
|
const docElements = [];
|
|
3377
3592
|
const themeProps = typeof resolved.theme === "object" ? resolved.theme : {};
|
|
@@ -3443,6 +3658,9 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
3443
3658
|
);
|
|
3444
3659
|
}
|
|
3445
3660
|
}
|
|
3661
|
+
if (((_b = resolved.numberHeadings) == null ? void 0 : _b.enabled) !== false && resolved.numberHeadings) {
|
|
3662
|
+
applyHeadingNumbering(doc.nodes, doc.tocEntries, resolved.numberHeadings);
|
|
3663
|
+
}
|
|
3446
3664
|
if (resolved.toc) {
|
|
3447
3665
|
const headingNodes = doc.nodes.filter(
|
|
3448
3666
|
(n) => n.type === "heading" && typeof n.level === "number" && n.level >= 1 && n.level <= 3
|
|
@@ -3512,7 +3730,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
3512
3730
|
]
|
|
3513
3731
|
});
|
|
3514
3732
|
docElements.push(tocCard);
|
|
3515
|
-
docElements.push(
|
|
3733
|
+
docElements.push(
|
|
3734
|
+
new Paragraph({
|
|
3735
|
+
children: [new PageBreak()]
|
|
3736
|
+
})
|
|
3737
|
+
);
|
|
3516
3738
|
}
|
|
3517
3739
|
}
|
|
3518
3740
|
for (const node of doc.nodes) {
|
|
@@ -3522,7 +3744,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
3522
3744
|
font: defaultFont,
|
|
3523
3745
|
size: 34,
|
|
3524
3746
|
// 17pt
|
|
3525
|
-
color:
|
|
3747
|
+
color: primaryDarkHex,
|
|
3526
3748
|
bold: true
|
|
3527
3749
|
});
|
|
3528
3750
|
docElements.push(
|
|
@@ -3568,7 +3790,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
3568
3790
|
font: defaultFont,
|
|
3569
3791
|
size: 22,
|
|
3570
3792
|
// 11pt
|
|
3571
|
-
color:
|
|
3793
|
+
color: primaryDarkHex,
|
|
3572
3794
|
bold: true
|
|
3573
3795
|
});
|
|
3574
3796
|
docElements.push(
|
|
@@ -3798,7 +4020,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
3798
4020
|
}
|
|
3799
4021
|
if (node.type === "table" && node.children) {
|
|
3800
4022
|
const tableRows = [];
|
|
3801
|
-
const numCols = ((
|
|
4023
|
+
const numCols = ((_d = (_c = node.children[0]) == null ? void 0 : _c.children) == null ? void 0 : _d.length) || 1;
|
|
3802
4024
|
const colWidth = Math.floor(9e3 / numCols);
|
|
3803
4025
|
for (let rowIdx = 0; rowIdx < node.children.length; rowIdx++) {
|
|
3804
4026
|
const rowNode = node.children[rowIdx];
|
|
@@ -3808,7 +4030,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
3808
4030
|
if (rowNode.children) {
|
|
3809
4031
|
for (let colIdx = 0; colIdx < rowNode.children.length; colIdx++) {
|
|
3810
4032
|
const cellNode = rowNode.children[colIdx];
|
|
3811
|
-
const align = (
|
|
4033
|
+
const align = (_e = node.align) == null ? void 0 : _e[colIdx];
|
|
3812
4034
|
let alignment = AlignmentType.LEFT;
|
|
3813
4035
|
if (align === "center") alignment = AlignmentType.CENTER;
|
|
3814
4036
|
if (align === "right") alignment = AlignmentType.RIGHT;
|
|
@@ -4115,7 +4337,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4115
4337
|
const centerPos = Math.round(contentWidthTwip / 2);
|
|
4116
4338
|
const rightPos = contentWidthTwip;
|
|
4117
4339
|
const headerRuns = [];
|
|
4118
|
-
if ((
|
|
4340
|
+
if ((_f = resolved.header) == null ? void 0 : _f.left) {
|
|
4119
4341
|
headerRuns.push(
|
|
4120
4342
|
new TextRun({
|
|
4121
4343
|
text: resolved.header.left.text,
|
|
@@ -4128,7 +4350,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4128
4350
|
);
|
|
4129
4351
|
}
|
|
4130
4352
|
headerRuns.push(new TextRun({ text: " " }));
|
|
4131
|
-
if ((
|
|
4353
|
+
if ((_g = resolved.header) == null ? void 0 : _g.center) {
|
|
4132
4354
|
headerRuns.push(
|
|
4133
4355
|
new TextRun({
|
|
4134
4356
|
text: resolved.header.center.text,
|
|
@@ -4141,7 +4363,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4141
4363
|
);
|
|
4142
4364
|
}
|
|
4143
4365
|
headerRuns.push(new TextRun({ text: " " }));
|
|
4144
|
-
if ((
|
|
4366
|
+
if ((_h = resolved.header) == null ? void 0 : _h.right) {
|
|
4145
4367
|
headerRuns.push(
|
|
4146
4368
|
new TextRun({
|
|
4147
4369
|
text: resolved.header.right.text,
|
|
@@ -4180,7 +4402,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4180
4402
|
]
|
|
4181
4403
|
}) : void 0;
|
|
4182
4404
|
const footerRuns = [];
|
|
4183
|
-
if ((
|
|
4405
|
+
if ((_i = resolved.footer) == null ? void 0 : _i.left) {
|
|
4184
4406
|
footerRuns.push(
|
|
4185
4407
|
new TextRun({
|
|
4186
4408
|
text: resolved.footer.left.text,
|
|
@@ -4193,7 +4415,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4193
4415
|
);
|
|
4194
4416
|
}
|
|
4195
4417
|
footerRuns.push(new TextRun({ text: " " }));
|
|
4196
|
-
if ((
|
|
4418
|
+
if ((_j = resolved.footer) == null ? void 0 : _j.center) {
|
|
4197
4419
|
footerRuns.push(
|
|
4198
4420
|
new TextRun({
|
|
4199
4421
|
text: resolved.footer.center.text,
|
|
@@ -4206,7 +4428,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4206
4428
|
);
|
|
4207
4429
|
}
|
|
4208
4430
|
footerRuns.push(new TextRun({ text: " " }));
|
|
4209
|
-
if ((
|
|
4431
|
+
if ((_k = resolved.footer) == null ? void 0 : _k.right) {
|
|
4210
4432
|
const rZone = resolved.footer.right;
|
|
4211
4433
|
const rColor = rZone.color.replace("#", "");
|
|
4212
4434
|
const rSize = (rZone.fontSize || 9) * 2;
|
|
@@ -4304,6 +4526,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4304
4526
|
);
|
|
4305
4527
|
docSections.push({
|
|
4306
4528
|
properties: {
|
|
4529
|
+
type: SectionType.NEXT_PAGE,
|
|
4307
4530
|
page: {
|
|
4308
4531
|
size: {
|
|
4309
4532
|
width: resolved.paperDimensions.widthTwip,
|
|
@@ -4318,14 +4541,19 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4318
4541
|
}
|
|
4319
4542
|
}
|
|
4320
4543
|
},
|
|
4321
|
-
headers:
|
|
4322
|
-
footers:
|
|
4544
|
+
headers: { default: new Header({ children: [] }) },
|
|
4545
|
+
footers: { default: new Footer({ children: [] }) },
|
|
4323
4546
|
children: coverElements
|
|
4324
4547
|
});
|
|
4325
4548
|
}
|
|
4326
4549
|
docSections.push({
|
|
4327
4550
|
properties: {
|
|
4551
|
+
type: SectionType.NEXT_PAGE,
|
|
4328
4552
|
page: {
|
|
4553
|
+
pageNumbers: {
|
|
4554
|
+
start: 1,
|
|
4555
|
+
formatType: NumberFormat.DECIMAL
|
|
4556
|
+
},
|
|
4329
4557
|
size: {
|
|
4330
4558
|
width: resolved.paperDimensions.widthTwip,
|
|
4331
4559
|
height: resolved.paperDimensions.heightTwip,
|
|
@@ -4341,8 +4569,8 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4341
4569
|
}
|
|
4342
4570
|
}
|
|
4343
4571
|
},
|
|
4344
|
-
headers: docHeader ? { default: docHeader } :
|
|
4345
|
-
footers: docFooter ? { default: docFooter } :
|
|
4572
|
+
headers: docHeader ? { default: docHeader } : { default: new Header({ children: [] }) },
|
|
4573
|
+
footers: docFooter ? { default: docFooter } : { default: new Footer({ children: [] }) },
|
|
4346
4574
|
children: docElements
|
|
4347
4575
|
});
|
|
4348
4576
|
if (resolved.backCover && resolved.backCover.enabled) {
|
|
@@ -4357,6 +4585,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4357
4585
|
);
|
|
4358
4586
|
docSections.push({
|
|
4359
4587
|
properties: {
|
|
4588
|
+
type: SectionType.NEXT_PAGE,
|
|
4360
4589
|
page: {
|
|
4361
4590
|
size: {
|
|
4362
4591
|
width: resolved.paperDimensions.widthTwip,
|
|
@@ -4371,8 +4600,8 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
4371
4600
|
}
|
|
4372
4601
|
}
|
|
4373
4602
|
},
|
|
4374
|
-
headers:
|
|
4375
|
-
footers:
|
|
4603
|
+
headers: { default: new Header({ children: [] }) },
|
|
4604
|
+
footers: { default: new Footer({ children: [] }) },
|
|
4376
4605
|
children: backElements
|
|
4377
4606
|
});
|
|
4378
4607
|
}
|
|
@@ -4775,6 +5004,432 @@ function createEmptyDocxCell(widthDxa) {
|
|
|
4775
5004
|
});
|
|
4776
5005
|
}
|
|
4777
5006
|
|
|
5007
|
+
// src/core/text/textBuilder.ts
|
|
5008
|
+
var LINE_WIDTH = 80;
|
|
5009
|
+
var HR_DOUBLE = "=".repeat(LINE_WIDTH);
|
|
5010
|
+
var HR_SINGLE = "-".repeat(LINE_WIDTH);
|
|
5011
|
+
function centerText(text, width = LINE_WIDTH) {
|
|
5012
|
+
if (text.length >= width) return text;
|
|
5013
|
+
const leftPad = Math.floor((width - text.length) / 2);
|
|
5014
|
+
return " ".repeat(leftPad) + text;
|
|
5015
|
+
}
|
|
5016
|
+
function renderInlinesToText(spans = [], meta = {}) {
|
|
5017
|
+
let result = "";
|
|
5018
|
+
for (const span of spans) {
|
|
5019
|
+
switch (span.type) {
|
|
5020
|
+
case "text": {
|
|
5021
|
+
const content = replaceDocumentTokens(span.content, meta);
|
|
5022
|
+
result += content;
|
|
5023
|
+
break;
|
|
5024
|
+
}
|
|
5025
|
+
case "bold": {
|
|
5026
|
+
const inner = span.children ? renderInlinesToText(span.children, meta) : replaceDocumentTokens(span.content, meta);
|
|
5027
|
+
result += `**${inner}**`;
|
|
5028
|
+
break;
|
|
5029
|
+
}
|
|
5030
|
+
case "italic": {
|
|
5031
|
+
const inner = span.children ? renderInlinesToText(span.children, meta) : replaceDocumentTokens(span.content, meta);
|
|
5032
|
+
result += `*${inner}*`;
|
|
5033
|
+
break;
|
|
5034
|
+
}
|
|
5035
|
+
case "code": {
|
|
5036
|
+
result += `\`${span.content}\``;
|
|
5037
|
+
break;
|
|
5038
|
+
}
|
|
5039
|
+
case "link": {
|
|
5040
|
+
const inner = span.children ? renderInlinesToText(span.children, meta) : replaceDocumentTokens(span.content, meta);
|
|
5041
|
+
result += span.url && span.url !== inner ? `${inner} (${span.url})` : inner;
|
|
5042
|
+
break;
|
|
5043
|
+
}
|
|
5044
|
+
case "image": {
|
|
5045
|
+
result += `[Image: ${span.alt || "image"} (${span.url || ""})]`;
|
|
5046
|
+
break;
|
|
5047
|
+
}
|
|
5048
|
+
case "strikethrough": {
|
|
5049
|
+
const inner = span.children ? renderInlinesToText(span.children, meta) : replaceDocumentTokens(span.content, meta);
|
|
5050
|
+
result += `~${inner}~`;
|
|
5051
|
+
break;
|
|
5052
|
+
}
|
|
5053
|
+
case "mathInline": {
|
|
5054
|
+
result += `$${span.content}$`;
|
|
5055
|
+
break;
|
|
5056
|
+
}
|
|
5057
|
+
case "footnoteRef": {
|
|
5058
|
+
const id = span.footnoteId || span.content;
|
|
5059
|
+
result += `[${id}]`;
|
|
5060
|
+
break;
|
|
5061
|
+
}
|
|
5062
|
+
case "htmlInline": {
|
|
5063
|
+
result += span.content.replace(/<[^>]+>/g, "");
|
|
5064
|
+
break;
|
|
5065
|
+
}
|
|
5066
|
+
default: {
|
|
5067
|
+
result += span.content || "";
|
|
5068
|
+
break;
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
}
|
|
5072
|
+
return result;
|
|
5073
|
+
}
|
|
5074
|
+
async function buildTextDocument(doc, config = {}, _baseDir = process.cwd()) {
|
|
5075
|
+
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
5076
|
+
const meta = {
|
|
5077
|
+
...doc.metadata,
|
|
5078
|
+
...config.metadata,
|
|
5079
|
+
title: resolved.title,
|
|
5080
|
+
subtitle: resolved.subtitle,
|
|
5081
|
+
author: resolved.author,
|
|
5082
|
+
company: resolved.company,
|
|
5083
|
+
version: resolved.version,
|
|
5084
|
+
date: resolved.date
|
|
5085
|
+
};
|
|
5086
|
+
const nodes = JSON.parse(JSON.stringify(doc.nodes));
|
|
5087
|
+
const tocEntries = JSON.parse(JSON.stringify(doc.tocEntries));
|
|
5088
|
+
if (resolved.numberHeadings && resolved.numberHeadings.enabled) {
|
|
5089
|
+
applyHeadingNumbering(nodes, tocEntries, resolved.numberHeadings);
|
|
5090
|
+
}
|
|
5091
|
+
const lines = [];
|
|
5092
|
+
if (resolved.coverPage && resolved.coverPage.enabled) {
|
|
5093
|
+
const cover = resolved.coverPage;
|
|
5094
|
+
const coverTitle = (cover.title || meta.title || "DOCUMENT").toUpperCase();
|
|
5095
|
+
const coverSubtitle = cover.subtitle || meta.subtitle || "";
|
|
5096
|
+
const coverAuthor = cover.author || meta.author || "";
|
|
5097
|
+
const coverCompany = cover.company || meta.company || "";
|
|
5098
|
+
const coverDate = cover.date || meta.date || "";
|
|
5099
|
+
const coverVersion = cover.version || meta.version || "";
|
|
5100
|
+
const coverBadge = cover.badge || "";
|
|
5101
|
+
const coverFooter = cover.footerText || "";
|
|
5102
|
+
lines.push(HR_DOUBLE);
|
|
5103
|
+
lines.push(centerText(coverTitle));
|
|
5104
|
+
if (coverSubtitle) {
|
|
5105
|
+
lines.push(centerText(coverSubtitle));
|
|
5106
|
+
}
|
|
5107
|
+
lines.push(HR_DOUBLE);
|
|
5108
|
+
if (coverBadge) {
|
|
5109
|
+
lines.push(`[${coverBadge}]`);
|
|
5110
|
+
lines.push("");
|
|
5111
|
+
}
|
|
5112
|
+
if (coverAuthor) lines.push(`Author: ${coverAuthor}`);
|
|
5113
|
+
if (coverCompany) lines.push(`Company: ${coverCompany}`);
|
|
5114
|
+
if (coverDate) lines.push(`Date: ${coverDate}`);
|
|
5115
|
+
if (coverVersion) lines.push(`Version: ${coverVersion}`);
|
|
5116
|
+
if (coverFooter) lines.push(`Notice: ${coverFooter}`);
|
|
5117
|
+
lines.push(HR_DOUBLE);
|
|
5118
|
+
lines.push("");
|
|
5119
|
+
lines.push("");
|
|
5120
|
+
}
|
|
5121
|
+
if (resolved.toc) {
|
|
5122
|
+
const headings = nodes.filter(
|
|
5123
|
+
(n) => n.type === "heading" && (n.level || 1) <= 3
|
|
5124
|
+
);
|
|
5125
|
+
if (headings.length > 0) {
|
|
5126
|
+
const tocTitle = "TABLE OF CONTENTS";
|
|
5127
|
+
lines.push(HR_DOUBLE);
|
|
5128
|
+
lines.push(centerText(tocTitle));
|
|
5129
|
+
lines.push(HR_DOUBLE);
|
|
5130
|
+
for (const h of headings) {
|
|
5131
|
+
const level = h.level || 1;
|
|
5132
|
+
const indent = " ".repeat(level - 1);
|
|
5133
|
+
const headingText = renderInlinesToText(h.inlines, meta);
|
|
5134
|
+
const prefix = level === 1 ? "* " : "- ";
|
|
5135
|
+
lines.push(`${indent}${prefix}${headingText}`);
|
|
5136
|
+
}
|
|
5137
|
+
lines.push(HR_DOUBLE);
|
|
5138
|
+
lines.push("");
|
|
5139
|
+
lines.push("");
|
|
5140
|
+
}
|
|
5141
|
+
}
|
|
5142
|
+
function renderNode(node, listLevel = 0) {
|
|
5143
|
+
var _a;
|
|
5144
|
+
switch (node.type) {
|
|
5145
|
+
case "heading": {
|
|
5146
|
+
const level = node.level || 1;
|
|
5147
|
+
const text = renderInlinesToText(node.inlines, meta);
|
|
5148
|
+
lines.push("");
|
|
5149
|
+
if (level === 1) {
|
|
5150
|
+
lines.push(HR_DOUBLE);
|
|
5151
|
+
lines.push(text.toUpperCase());
|
|
5152
|
+
lines.push(HR_DOUBLE);
|
|
5153
|
+
} else if (level === 2) {
|
|
5154
|
+
lines.push(HR_SINGLE);
|
|
5155
|
+
lines.push(text);
|
|
5156
|
+
lines.push(HR_SINGLE);
|
|
5157
|
+
} else {
|
|
5158
|
+
const hashes = "#".repeat(level);
|
|
5159
|
+
lines.push(`${hashes} ${text}`);
|
|
5160
|
+
}
|
|
5161
|
+
lines.push("");
|
|
5162
|
+
break;
|
|
5163
|
+
}
|
|
5164
|
+
case "paragraph": {
|
|
5165
|
+
const text = renderInlinesToText(node.inlines, meta);
|
|
5166
|
+
if (text.trim()) {
|
|
5167
|
+
lines.push(text);
|
|
5168
|
+
lines.push("");
|
|
5169
|
+
}
|
|
5170
|
+
break;
|
|
5171
|
+
}
|
|
5172
|
+
case "callout": {
|
|
5173
|
+
const calloutType = (node.calloutType || "NOTE").toUpperCase();
|
|
5174
|
+
lines.push(`| [${calloutType}]`);
|
|
5175
|
+
if (node.inlines && node.inlines.length > 0) {
|
|
5176
|
+
const text = renderInlinesToText(node.inlines, meta);
|
|
5177
|
+
text.split("\n").forEach((l) => lines.push(`| ${l}`));
|
|
5178
|
+
}
|
|
5179
|
+
lines.push("");
|
|
5180
|
+
break;
|
|
5181
|
+
}
|
|
5182
|
+
case "blockquote": {
|
|
5183
|
+
if (node.inlines && node.inlines.length > 0) {
|
|
5184
|
+
const text = renderInlinesToText(node.inlines, meta);
|
|
5185
|
+
text.split("\n").forEach((l) => lines.push(`> ${l}`));
|
|
5186
|
+
lines.push("");
|
|
5187
|
+
}
|
|
5188
|
+
break;
|
|
5189
|
+
}
|
|
5190
|
+
case "codeBlock": {
|
|
5191
|
+
const lang = node.language ? `[Language: ${node.language}]` : "[Code]";
|
|
5192
|
+
lines.push(HR_SINGLE);
|
|
5193
|
+
lines.push(lang);
|
|
5194
|
+
lines.push(HR_SINGLE);
|
|
5195
|
+
const codeText = node.text || "";
|
|
5196
|
+
lines.push(codeText);
|
|
5197
|
+
lines.push(HR_SINGLE);
|
|
5198
|
+
lines.push("");
|
|
5199
|
+
break;
|
|
5200
|
+
}
|
|
5201
|
+
case "list": {
|
|
5202
|
+
if (node.children) {
|
|
5203
|
+
let itemIndex = 1;
|
|
5204
|
+
for (const item of node.children) {
|
|
5205
|
+
const indent = " ".repeat(listLevel);
|
|
5206
|
+
let prefix = node.ordered ? `${itemIndex}. ` : "* ";
|
|
5207
|
+
itemIndex++;
|
|
5208
|
+
if (item.checked !== void 0) {
|
|
5209
|
+
prefix = item.checked ? "[x] " : "[ ] ";
|
|
5210
|
+
}
|
|
5211
|
+
if (item.inlines && item.inlines.length > 0) {
|
|
5212
|
+
const text = renderInlinesToText(item.inlines, meta);
|
|
5213
|
+
lines.push(`${indent}${prefix}${text}`);
|
|
5214
|
+
}
|
|
5215
|
+
if (item.children && item.children.length > 0) {
|
|
5216
|
+
for (const subChild of item.children) {
|
|
5217
|
+
if (subChild.type === "list") {
|
|
5218
|
+
renderNode(subChild, listLevel + 1);
|
|
5219
|
+
} else if (subChild.type === "paragraph") {
|
|
5220
|
+
const text = renderInlinesToText(subChild.inlines, meta);
|
|
5221
|
+
lines.push(`${indent} ${text}`);
|
|
5222
|
+
} else {
|
|
5223
|
+
renderNode(subChild, listLevel + 1);
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
lines.push("");
|
|
5229
|
+
}
|
|
5230
|
+
break;
|
|
5231
|
+
}
|
|
5232
|
+
case "table": {
|
|
5233
|
+
const rows = node.children || [];
|
|
5234
|
+
if (rows.length === 0) break;
|
|
5235
|
+
const rowCells = [];
|
|
5236
|
+
let maxCols = 0;
|
|
5237
|
+
for (const row of rows) {
|
|
5238
|
+
const cells = row.children || [];
|
|
5239
|
+
const texts = cells.map((c) => renderInlinesToText(c.inlines, meta));
|
|
5240
|
+
const isHeader = cells.some((c) => c.isHeader);
|
|
5241
|
+
maxCols = Math.max(maxCols, texts.length);
|
|
5242
|
+
rowCells.push({ isHeader, texts });
|
|
5243
|
+
}
|
|
5244
|
+
if (maxCols === 0) break;
|
|
5245
|
+
const colWidths = new Array(maxCols).fill(3);
|
|
5246
|
+
for (const r of rowCells) {
|
|
5247
|
+
for (let col = 0; col < maxCols; col++) {
|
|
5248
|
+
const cellText = r.texts[col] || "";
|
|
5249
|
+
colWidths[col] = Math.max(colWidths[col] ?? 3, cellText.length);
|
|
5250
|
+
}
|
|
5251
|
+
}
|
|
5252
|
+
const separatorLine = "+" + colWidths.map((w) => "-".repeat(w + 2)).join("+") + "+";
|
|
5253
|
+
const formatRow = (texts) => {
|
|
5254
|
+
const paddedCells = colWidths.map((width, colIdx) => {
|
|
5255
|
+
const text = texts[colIdx] || "";
|
|
5256
|
+
return " " + text.padEnd(width, " ") + " ";
|
|
5257
|
+
});
|
|
5258
|
+
return "|" + paddedCells.join("|") + "|";
|
|
5259
|
+
};
|
|
5260
|
+
lines.push(separatorLine);
|
|
5261
|
+
for (const r of rowCells) {
|
|
5262
|
+
lines.push(formatRow(r.texts));
|
|
5263
|
+
if (r.isHeader) {
|
|
5264
|
+
lines.push(separatorLine);
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
if (!((_a = rowCells[rowCells.length - 1]) == null ? void 0 : _a.isHeader)) {
|
|
5268
|
+
lines.push(separatorLine);
|
|
5269
|
+
}
|
|
5270
|
+
lines.push("");
|
|
5271
|
+
break;
|
|
5272
|
+
}
|
|
5273
|
+
case "mathBlock": {
|
|
5274
|
+
lines.push("[Equation]");
|
|
5275
|
+
lines.push(` $$${node.text || ""} $$`);
|
|
5276
|
+
lines.push("");
|
|
5277
|
+
break;
|
|
5278
|
+
}
|
|
5279
|
+
case "mermaid": {
|
|
5280
|
+
lines.push("[Diagram: Mermaid]");
|
|
5281
|
+
lines.push(node.text || "");
|
|
5282
|
+
lines.push("");
|
|
5283
|
+
break;
|
|
5284
|
+
}
|
|
5285
|
+
case "thematicBreak": {
|
|
5286
|
+
lines.push(HR_SINGLE);
|
|
5287
|
+
lines.push("");
|
|
5288
|
+
break;
|
|
5289
|
+
}
|
|
5290
|
+
case "columns": {
|
|
5291
|
+
if (node.children) {
|
|
5292
|
+
for (const col of node.children) {
|
|
5293
|
+
if (col.children) {
|
|
5294
|
+
for (const child of col.children) {
|
|
5295
|
+
renderNode(child, listLevel);
|
|
5296
|
+
}
|
|
5297
|
+
}
|
|
5298
|
+
}
|
|
5299
|
+
}
|
|
5300
|
+
break;
|
|
5301
|
+
}
|
|
5302
|
+
default: {
|
|
5303
|
+
if (node.children && node.children.length > 0) {
|
|
5304
|
+
for (const child of node.children) {
|
|
5305
|
+
renderNode(child, listLevel);
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5308
|
+
break;
|
|
5309
|
+
}
|
|
5310
|
+
}
|
|
5311
|
+
}
|
|
5312
|
+
for (const node of nodes) {
|
|
5313
|
+
renderNode(node);
|
|
5314
|
+
}
|
|
5315
|
+
if (doc.footnoteDefs && doc.footnoteDefs.length > 0) {
|
|
5316
|
+
lines.push(HR_SINGLE);
|
|
5317
|
+
lines.push("FOOTNOTES");
|
|
5318
|
+
lines.push(HR_SINGLE);
|
|
5319
|
+
for (const fn of doc.footnoteDefs) {
|
|
5320
|
+
const text = renderInlinesToText(fn.inlines, meta);
|
|
5321
|
+
lines.push(`[${fn.id}] ${text}`);
|
|
5322
|
+
}
|
|
5323
|
+
lines.push("");
|
|
5324
|
+
}
|
|
5325
|
+
if (resolved.signatures && resolved.signatures.items && resolved.signatures.items.length > 0) {
|
|
5326
|
+
lines.push(HR_SINGLE);
|
|
5327
|
+
lines.push("SIGNATURES & APPROVALS");
|
|
5328
|
+
lines.push(HR_SINGLE);
|
|
5329
|
+
lines.push("");
|
|
5330
|
+
for (const item of resolved.signatures.items) {
|
|
5331
|
+
const title = item.title || "Signatory";
|
|
5332
|
+
const name = item.name ? replaceDocumentTokens(item.name, meta) : "";
|
|
5333
|
+
const role = item.role ? replaceDocumentTokens(item.role, meta) : "";
|
|
5334
|
+
const date = item.date ? replaceDocumentTokens(item.date, meta) : "";
|
|
5335
|
+
lines.push(`[${title}]`);
|
|
5336
|
+
lines.push("____________________________________");
|
|
5337
|
+
if (name) lines.push(`Name: ${name}`);
|
|
5338
|
+
if (role) lines.push(`Role: ${role}`);
|
|
5339
|
+
if (date) lines.push(`Date: ${date}`);
|
|
5340
|
+
lines.push("");
|
|
5341
|
+
}
|
|
5342
|
+
}
|
|
5343
|
+
if (resolved.backCover && resolved.backCover.enabled) {
|
|
5344
|
+
const back = resolved.backCover;
|
|
5345
|
+
const backTitle = (back.title || "THANK YOU").toUpperCase();
|
|
5346
|
+
const backSubtitle = back.subtitle || "";
|
|
5347
|
+
const backCompany = back.company ? replaceDocumentTokens(back.company, meta) : "";
|
|
5348
|
+
const backAddress = back.address ? replaceDocumentTokens(back.address, meta) : "";
|
|
5349
|
+
const backEmail = back.email ? replaceDocumentTokens(back.email, meta) : "";
|
|
5350
|
+
const backPhone = back.phone ? replaceDocumentTokens(back.phone, meta) : "";
|
|
5351
|
+
const backWebsite = back.website ? replaceDocumentTokens(back.website, meta) : "";
|
|
5352
|
+
const backCopyright = back.copyright ? replaceDocumentTokens(back.copyright, meta) : "";
|
|
5353
|
+
lines.push(HR_DOUBLE);
|
|
5354
|
+
lines.push(centerText(backTitle));
|
|
5355
|
+
if (backSubtitle) {
|
|
5356
|
+
lines.push(centerText(backSubtitle));
|
|
5357
|
+
}
|
|
5358
|
+
lines.push(HR_DOUBLE);
|
|
5359
|
+
if (backCompany) lines.push(`Company: ${backCompany}`);
|
|
5360
|
+
if (backAddress) lines.push(`Address: ${backAddress}`);
|
|
5361
|
+
if (backEmail) lines.push(`Email: ${backEmail}`);
|
|
5362
|
+
if (backPhone) lines.push(`Phone: ${backPhone}`);
|
|
5363
|
+
if (backWebsite) lines.push(`Website: ${backWebsite}`);
|
|
5364
|
+
if (back.social && back.social.github) {
|
|
5365
|
+
lines.push(`GitHub: ${back.social.github}`);
|
|
5366
|
+
}
|
|
5367
|
+
if (backCopyright) {
|
|
5368
|
+
lines.push("");
|
|
5369
|
+
lines.push(backCopyright);
|
|
5370
|
+
}
|
|
5371
|
+
lines.push(HR_DOUBLE);
|
|
5372
|
+
lines.push("");
|
|
5373
|
+
}
|
|
5374
|
+
return lines.join("\n").trim() + "\n";
|
|
5375
|
+
}
|
|
5376
|
+
|
|
5377
|
+
// src/core/png/pngBuilder.ts
|
|
5378
|
+
import * as fs6 from "fs";
|
|
5379
|
+
import * as path6 from "path";
|
|
5380
|
+
import * as os3 from "os";
|
|
5381
|
+
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
5382
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
5383
|
+
async function buildPngDocument(doc, config, baseDir) {
|
|
5384
|
+
const htmlContent = await buildHtmlDocument(doc, config, baseDir);
|
|
5385
|
+
const chromePath = findChromeExecutable();
|
|
5386
|
+
if (!chromePath) {
|
|
5387
|
+
throw new Error(
|
|
5388
|
+
"Headless Chrome / Chromium / Edge executable not found for PNG document export. Please install Google Chrome, Chromium, or Microsoft Edge, or set CHROME_PATH environment variable."
|
|
5389
|
+
);
|
|
5390
|
+
}
|
|
5391
|
+
const tmpHtml = path6.join(
|
|
5392
|
+
os3.tmpdir(),
|
|
5393
|
+
`markforge-png-${Date.now()}-${Math.random().toString(36).slice(2)}.html`
|
|
5394
|
+
);
|
|
5395
|
+
const tmpPng = path6.join(
|
|
5396
|
+
os3.tmpdir(),
|
|
5397
|
+
`markforge-png-${Date.now()}-${Math.random().toString(36).slice(2)}.png`
|
|
5398
|
+
);
|
|
5399
|
+
try {
|
|
5400
|
+
fs6.writeFileSync(tmpHtml, htmlContent, "utf-8");
|
|
5401
|
+
const fileUrl = pathToFileURL4(tmpHtml).href;
|
|
5402
|
+
const spawnResult = spawnSync3(
|
|
5403
|
+
chromePath,
|
|
5404
|
+
[
|
|
5405
|
+
"--headless=new",
|
|
5406
|
+
"--disable-gpu",
|
|
5407
|
+
"--no-sandbox",
|
|
5408
|
+
"--disable-setuid-sandbox",
|
|
5409
|
+
"--hide-scrollbars",
|
|
5410
|
+
"--force-device-scale-factor=2",
|
|
5411
|
+
"--window-size=1200,1600",
|
|
5412
|
+
`--screenshot=${tmpPng}`,
|
|
5413
|
+
fileUrl
|
|
5414
|
+
],
|
|
5415
|
+
{ timeout: 3e4, windowsHide: true }
|
|
5416
|
+
);
|
|
5417
|
+
if (spawnResult.error) {
|
|
5418
|
+
throw new Error(`Failed to execute Chromium for PNG export: ${spawnResult.error.message}`);
|
|
5419
|
+
}
|
|
5420
|
+
if (!fs6.existsSync(tmpPng) || fs6.statSync(tmpPng).size === 0) {
|
|
5421
|
+
throw new Error("Chromium PNG export failed to generate output screenshot file.");
|
|
5422
|
+
}
|
|
5423
|
+
return fs6.readFileSync(tmpPng);
|
|
5424
|
+
} finally {
|
|
5425
|
+
try {
|
|
5426
|
+
if (fs6.existsSync(tmpHtml)) fs6.unlinkSync(tmpHtml);
|
|
5427
|
+
if (fs6.existsSync(tmpPng)) fs6.unlinkSync(tmpPng);
|
|
5428
|
+
} catch {
|
|
5429
|
+
}
|
|
5430
|
+
}
|
|
5431
|
+
}
|
|
5432
|
+
|
|
4778
5433
|
// src/core/engine.ts
|
|
4779
5434
|
function formatServerTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
4780
5435
|
const pad = (n) => String(n).padStart(2, "0");
|
|
@@ -4798,20 +5453,20 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
4798
5453
|
let baseDir = process.cwd();
|
|
4799
5454
|
let inputFileName = "document.md";
|
|
4800
5455
|
let isFilePath = false;
|
|
4801
|
-
if (
|
|
5456
|
+
if (fs7.existsSync(inputFilePathOrContent)) {
|
|
4802
5457
|
isFilePath = true;
|
|
4803
|
-
rawMarkdown =
|
|
4804
|
-
baseDir =
|
|
4805
|
-
inputFileName =
|
|
5458
|
+
rawMarkdown = fs7.readFileSync(inputFilePathOrContent, "utf-8");
|
|
5459
|
+
baseDir = path7.dirname(path7.resolve(inputFilePathOrContent));
|
|
5460
|
+
inputFileName = path7.basename(inputFilePathOrContent);
|
|
4806
5461
|
} else {
|
|
4807
5462
|
rawMarkdown = inputFilePathOrContent;
|
|
4808
5463
|
}
|
|
4809
5464
|
onProgress == null ? void 0 : onProgress(`Parsing markdown AST: ${inputFileName}...`);
|
|
4810
5465
|
const parsedDoc = parseMarkdownDocument(rawMarkdown);
|
|
4811
5466
|
const baseName = inputFileName.replace(/\.(md|mdx|markdown)$/i, "");
|
|
4812
|
-
const outputDir = config.outputDir ?
|
|
4813
|
-
if (!
|
|
4814
|
-
|
|
5467
|
+
const outputDir = config.outputDir ? path7.isAbsolute(config.outputDir) ? config.outputDir : path7.resolve(process.cwd(), config.outputDir) : baseDir;
|
|
5468
|
+
if (!fs7.existsSync(outputDir)) {
|
|
5469
|
+
fs7.mkdirSync(outputDir, { recursive: true });
|
|
4815
5470
|
}
|
|
4816
5471
|
const formats = Array.isArray(config.to) ? config.to : [config.to || "docx", "pdf"];
|
|
4817
5472
|
const generatedFiles = [];
|
|
@@ -4821,8 +5476,8 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
4821
5476
|
if (fmt === "docx") {
|
|
4822
5477
|
onProgress == null ? void 0 : onProgress(`Generating DOCX document: ${baseName}.docx...`);
|
|
4823
5478
|
const docxBuffer = await buildDocxDocument(parsedDoc, config, baseDir);
|
|
4824
|
-
const docxPath =
|
|
4825
|
-
|
|
5479
|
+
const docxPath = path7.join(outputDir, `${baseName}.docx`);
|
|
5480
|
+
fs7.writeFileSync(docxPath, docxBuffer);
|
|
4826
5481
|
generatedFiles.push({
|
|
4827
5482
|
format: "docx",
|
|
4828
5483
|
filePath: docxPath,
|
|
@@ -4832,8 +5487,8 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
4832
5487
|
} else if (fmt === "html") {
|
|
4833
5488
|
onProgress == null ? void 0 : onProgress(`Generating HTML document: ${baseName}.html...`);
|
|
4834
5489
|
const htmlString = await buildHtmlDocument(parsedDoc, config, baseDir);
|
|
4835
|
-
const htmlPath =
|
|
4836
|
-
|
|
5490
|
+
const htmlPath = path7.join(outputDir, `${baseName}.html`);
|
|
5491
|
+
fs7.writeFileSync(htmlPath, htmlString, "utf-8");
|
|
4837
5492
|
generatedFiles.push({
|
|
4838
5493
|
format: "html",
|
|
4839
5494
|
filePath: htmlPath,
|
|
@@ -4843,14 +5498,36 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
4843
5498
|
} else if (fmt === "pdf") {
|
|
4844
5499
|
onProgress == null ? void 0 : onProgress(`Generating PDF document: ${baseName}.pdf...`);
|
|
4845
5500
|
const pdfBuffer = await buildPdfDocument(parsedDoc, config, baseDir);
|
|
4846
|
-
const pdfPath =
|
|
4847
|
-
|
|
5501
|
+
const pdfPath = path7.join(outputDir, `${baseName}.pdf`);
|
|
5502
|
+
fs7.writeFileSync(pdfPath, pdfBuffer);
|
|
4848
5503
|
generatedFiles.push({
|
|
4849
5504
|
format: "pdf",
|
|
4850
5505
|
filePath: pdfPath,
|
|
4851
5506
|
fileName: `${baseName}.pdf`,
|
|
4852
5507
|
sizeBytes: pdfBuffer.length
|
|
4853
5508
|
});
|
|
5509
|
+
} else if (fmt === "txt") {
|
|
5510
|
+
onProgress == null ? void 0 : onProgress(`Generating Plain Text document: ${baseName}.txt...`);
|
|
5511
|
+
const textContent = await buildTextDocument(parsedDoc, config, baseDir);
|
|
5512
|
+
const textPath = path7.join(outputDir, `${baseName}.txt`);
|
|
5513
|
+
fs7.writeFileSync(textPath, textContent, "utf-8");
|
|
5514
|
+
generatedFiles.push({
|
|
5515
|
+
format: "txt",
|
|
5516
|
+
filePath: textPath,
|
|
5517
|
+
fileName: `${baseName}.txt`,
|
|
5518
|
+
sizeBytes: Buffer.byteLength(textContent, "utf-8")
|
|
5519
|
+
});
|
|
5520
|
+
} else if (fmt === "png") {
|
|
5521
|
+
onProgress == null ? void 0 : onProgress(`Generating PNG document: ${baseName}.png...`);
|
|
5522
|
+
const pngBuffer = await buildPngDocument(parsedDoc, config, baseDir);
|
|
5523
|
+
const pngPath = path7.join(outputDir, `${baseName}.png`);
|
|
5524
|
+
fs7.writeFileSync(pngPath, pngBuffer);
|
|
5525
|
+
generatedFiles.push({
|
|
5526
|
+
format: "png",
|
|
5527
|
+
filePath: pngPath,
|
|
5528
|
+
fileName: `${baseName}.png`,
|
|
5529
|
+
sizeBytes: pngBuffer.length
|
|
5530
|
+
});
|
|
4854
5531
|
}
|
|
4855
5532
|
} catch (err) {
|
|
4856
5533
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -4869,14 +5546,14 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
4869
5546
|
|
|
4870
5547
|
// src/server/previewServer.ts
|
|
4871
5548
|
import * as http from "http";
|
|
4872
|
-
import * as
|
|
4873
|
-
import * as
|
|
5549
|
+
import * as fs8 from "fs";
|
|
5550
|
+
import * as path8 from "path";
|
|
4874
5551
|
async function startPreviewServer(options) {
|
|
4875
|
-
const absoluteFilePath =
|
|
4876
|
-
if (!
|
|
5552
|
+
const absoluteFilePath = path8.resolve(process.cwd(), options.filePath);
|
|
5553
|
+
if (!fs8.existsSync(absoluteFilePath)) {
|
|
4877
5554
|
throw new Error(`MarkForge preview error: File not found at "${absoluteFilePath}"`);
|
|
4878
5555
|
}
|
|
4879
|
-
const baseDir =
|
|
5556
|
+
const baseDir = path8.dirname(absoluteFilePath);
|
|
4880
5557
|
const { config: fileConfig } = await loadConfig(void 0, baseDir);
|
|
4881
5558
|
const baseConfig = options.config || fileConfig;
|
|
4882
5559
|
const port = options.port || 3e3;
|
|
@@ -4894,9 +5571,9 @@ data: ${Date.now()}
|
|
|
4894
5571
|
});
|
|
4895
5572
|
};
|
|
4896
5573
|
let debounceTimer = null;
|
|
4897
|
-
const watcher =
|
|
5574
|
+
const watcher = fs8.watch(baseDir, { recursive: false }, (_event, filename) => {
|
|
4898
5575
|
if (!filename) return;
|
|
4899
|
-
const changedPath =
|
|
5576
|
+
const changedPath = path8.resolve(baseDir, filename);
|
|
4900
5577
|
if (changedPath === absoluteFilePath || filename.includes("markforge") || filename.endsWith(".css")) {
|
|
4901
5578
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
4902
5579
|
debounceTimer = setTimeout(() => {
|
|
@@ -4923,12 +5600,12 @@ data: ${Date.now()}
|
|
|
4923
5600
|
}
|
|
4924
5601
|
if (url.pathname === "/api/file-content" && req.method === "GET") {
|
|
4925
5602
|
try {
|
|
4926
|
-
const content =
|
|
5603
|
+
const content = fs8.readFileSync(absoluteFilePath, "utf-8");
|
|
4927
5604
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4928
5605
|
res.end(
|
|
4929
5606
|
JSON.stringify({
|
|
4930
5607
|
content,
|
|
4931
|
-
fileName:
|
|
5608
|
+
fileName: path8.basename(absoluteFilePath),
|
|
4932
5609
|
filePath: absoluteFilePath
|
|
4933
5610
|
})
|
|
4934
5611
|
);
|
|
@@ -4948,7 +5625,7 @@ data: ${Date.now()}
|
|
|
4948
5625
|
try {
|
|
4949
5626
|
const parsed = JSON.parse(body);
|
|
4950
5627
|
if (typeof parsed.content === "string") {
|
|
4951
|
-
|
|
5628
|
+
fs8.writeFileSync(absoluteFilePath, parsed.content, "utf-8");
|
|
4952
5629
|
broadcastReload();
|
|
4953
5630
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4954
5631
|
res.end(JSON.stringify({ success: true, savedAt: Date.now() }));
|
|
@@ -4967,11 +5644,11 @@ data: ${Date.now()}
|
|
|
4967
5644
|
if (url.pathname === "/api/export" && (req.method === "GET" || req.method === "POST")) {
|
|
4968
5645
|
const format = url.searchParams.get("format") || "docx";
|
|
4969
5646
|
try {
|
|
4970
|
-
const mdContent =
|
|
5647
|
+
const mdContent = fs8.readFileSync(absoluteFilePath, "utf-8");
|
|
4971
5648
|
const doc = parseMarkdownDocument(mdContent);
|
|
4972
5649
|
const { config: resolvedConfig } = await loadConfig(void 0, baseDir);
|
|
4973
5650
|
const mergedConfig = { ...baseConfig, ...resolvedConfig };
|
|
4974
|
-
const fileBase =
|
|
5651
|
+
const fileBase = path8.basename(absoluteFilePath, path8.extname(absoluteFilePath));
|
|
4975
5652
|
if (format === "docx") {
|
|
4976
5653
|
const buffer = await buildDocxDocument(doc, mergedConfig, baseDir);
|
|
4977
5654
|
res.writeHead(200, {
|
|
@@ -5006,7 +5683,7 @@ data: ${Date.now()}
|
|
|
5006
5683
|
}
|
|
5007
5684
|
if (url.pathname === "/document-content") {
|
|
5008
5685
|
try {
|
|
5009
|
-
const mdContent =
|
|
5686
|
+
const mdContent = fs8.readFileSync(absoluteFilePath, "utf-8");
|
|
5010
5687
|
const doc = parseMarkdownDocument(mdContent);
|
|
5011
5688
|
const { config: resolvedConfig } = await loadConfig(void 0, baseDir);
|
|
5012
5689
|
const html = await buildHtmlDocument(doc, { ...baseConfig, ...resolvedConfig }, baseDir);
|
|
@@ -5039,8 +5716,8 @@ data: ${Date.now()}
|
|
|
5039
5716
|
return;
|
|
5040
5717
|
}
|
|
5041
5718
|
if (url.pathname === "/" || url.pathname === "/index.html") {
|
|
5042
|
-
const fileName =
|
|
5043
|
-
const initialContent =
|
|
5719
|
+
const fileName = path8.basename(absoluteFilePath);
|
|
5720
|
+
const initialContent = fs8.readFileSync(absoluteFilePath, "utf-8");
|
|
5044
5721
|
const appHtml = `<!DOCTYPE html>
|
|
5045
5722
|
<html lang="en">
|
|
5046
5723
|
<head>
|
|
@@ -5744,9 +6421,9 @@ function defineConfig(config) {
|
|
|
5744
6421
|
}
|
|
5745
6422
|
|
|
5746
6423
|
// src/version.ts
|
|
5747
|
-
import * as
|
|
5748
|
-
import * as
|
|
5749
|
-
import { fileURLToPath } from "url";
|
|
6424
|
+
import * as fs9 from "fs";
|
|
6425
|
+
import * as path9 from "path";
|
|
6426
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5750
6427
|
try {
|
|
5751
6428
|
if (typeof globalThis !== "undefined" && (!globalThis.localStorage || typeof globalThis.localStorage.getItem !== "function")) {
|
|
5752
6429
|
Object.defineProperty(globalThis, "localStorage", {
|
|
@@ -5767,32 +6444,33 @@ try {
|
|
|
5767
6444
|
}
|
|
5768
6445
|
} catch {
|
|
5769
6446
|
}
|
|
5770
|
-
var FALLBACK_VERSION = "0.4.0";
|
|
5771
6447
|
function readVersionFromPackageJson(fromDir) {
|
|
5772
6448
|
let currentDir = fromDir;
|
|
5773
|
-
for (let i = 0; i <
|
|
6449
|
+
for (let i = 0; i < 10; i++) {
|
|
5774
6450
|
try {
|
|
5775
|
-
const pkgJsonPath =
|
|
5776
|
-
if (
|
|
5777
|
-
const pkg = JSON.parse(
|
|
6451
|
+
const pkgJsonPath = path9.join(currentDir, "package.json");
|
|
6452
|
+
if (fs9.existsSync(pkgJsonPath)) {
|
|
6453
|
+
const pkg = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
|
|
5778
6454
|
if (pkg.name === "@masumdev/markforge" && pkg.version) {
|
|
5779
6455
|
return pkg.version;
|
|
5780
6456
|
}
|
|
5781
6457
|
}
|
|
5782
6458
|
} catch {
|
|
5783
6459
|
}
|
|
5784
|
-
const parentDir =
|
|
6460
|
+
const parentDir = path9.dirname(currentDir);
|
|
5785
6461
|
if (parentDir === currentDir) break;
|
|
5786
6462
|
currentDir = parentDir;
|
|
5787
6463
|
}
|
|
5788
|
-
|
|
6464
|
+
throw new Error(
|
|
6465
|
+
"Failed to resolve '@masumdev/markforge' package version: package.json was not found or is missing a valid 'version' field."
|
|
6466
|
+
);
|
|
5789
6467
|
}
|
|
5790
6468
|
function getPackageDir() {
|
|
5791
6469
|
if (typeof __dirname !== "undefined") {
|
|
5792
6470
|
return __dirname;
|
|
5793
6471
|
}
|
|
5794
6472
|
try {
|
|
5795
|
-
return
|
|
6473
|
+
return path9.dirname(fileURLToPath2(import.meta.url));
|
|
5796
6474
|
} catch {
|
|
5797
6475
|
return process.cwd();
|
|
5798
6476
|
}
|
|
@@ -5802,6 +6480,8 @@ function getMarkforgeVersion(fromDir = getPackageDir()) {
|
|
|
5802
6480
|
return readVersionFromPackageJson(fromDir);
|
|
5803
6481
|
}
|
|
5804
6482
|
export {
|
|
6483
|
+
BackCoverPreset,
|
|
6484
|
+
CoverPagePreset,
|
|
5805
6485
|
DEFAULT_CONFIG,
|
|
5806
6486
|
KATEX_INLINE_CSS,
|
|
5807
6487
|
MARKFORGE_VERSION,
|
|
@@ -5810,15 +6490,21 @@ export {
|
|
|
5810
6490
|
PAPER_DIMENSIONS_TWIP,
|
|
5811
6491
|
PaperSizeEnum,
|
|
5812
6492
|
SYNTAX_COLORS,
|
|
6493
|
+
SignatureAlign,
|
|
6494
|
+
SignatureStyle,
|
|
5813
6495
|
SyntaxTheme,
|
|
5814
6496
|
THEMES,
|
|
5815
6497
|
THEME_CORPORATE,
|
|
5816
6498
|
THEME_DEFAULT,
|
|
5817
6499
|
Theme,
|
|
5818
6500
|
WatermarkPosition,
|
|
6501
|
+
applyHeadingNumbering,
|
|
5819
6502
|
buildDocxDocument,
|
|
5820
6503
|
buildHtmlDocument,
|
|
5821
6504
|
buildPdfDocument,
|
|
6505
|
+
buildPngDocument,
|
|
6506
|
+
buildTextDocument,
|
|
6507
|
+
buildTextDocument as buildTxtDocument,
|
|
5822
6508
|
compileMarkdown,
|
|
5823
6509
|
defineConfig,
|
|
5824
6510
|
escapeHtml,
|
|
@@ -5847,6 +6533,7 @@ export {
|
|
|
5847
6533
|
renderBackCoverHtml,
|
|
5848
6534
|
renderCoverPageHtml,
|
|
5849
6535
|
renderInlinesToHtml,
|
|
6536
|
+
renderInlinesToText,
|
|
5850
6537
|
renderMathToHtml,
|
|
5851
6538
|
renderMermaidToPng,
|
|
5852
6539
|
renderNodesToHtml,
|