@masumdev/markforge 0.4.1 → 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/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 fs6 from "fs";
18
- import * as path6 from "path";
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";
@@ -591,12 +591,14 @@ import {
591
591
  ExternalHyperlink,
592
592
  TabStopType,
593
593
  PageBreak,
594
- NumberFormat
594
+ NumberFormat,
595
+ SectionType
595
596
  } from "docx";
596
597
 
597
598
  // src/core/imageResolver.ts
598
599
  import * as fs from "fs";
599
600
  import * as path from "path";
601
+ import { fileURLToPath } from "url";
600
602
  var memoryImageCache = /* @__PURE__ */ new Map();
601
603
  function getMimeType(filePathOrUrl) {
602
604
  const clean = filePathOrUrl.split("?")[0].toLowerCase();
@@ -653,9 +655,19 @@ async function resolveImage(src, baseDir = process.cwd()) {
653
655
  memoryImageCache.set(cacheKey, resolved2);
654
656
  return resolved2;
655
657
  }
656
- let localPath = path.isAbsolute(src) ? src : path.resolve(baseDir, src);
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
+ }
657
669
  if (!fs.existsSync(localPath)) {
658
- const cwdPath = path.resolve(process.cwd(), src);
670
+ const cwdPath = path.resolve(process.cwd(), src.startsWith("file://") ? localPath : src);
659
671
  if (fs.existsSync(cwdPath)) {
660
672
  localPath = cwdPath;
661
673
  } else {
@@ -1078,6 +1090,7 @@ var OutputFormat = /* @__PURE__ */ ((OutputFormat2) => {
1078
1090
  OutputFormat2["PDF"] = "pdf";
1079
1091
  OutputFormat2["HTML"] = "html";
1080
1092
  OutputFormat2["PNG"] = "png";
1093
+ OutputFormat2["TXT"] = "txt";
1081
1094
  return OutputFormat2;
1082
1095
  })(OutputFormat || {});
1083
1096
  var Theme = /* @__PURE__ */ ((Theme2) => {
@@ -1112,6 +1125,33 @@ var WatermarkPosition = /* @__PURE__ */ ((WatermarkPosition2) => {
1112
1125
  WatermarkPosition2["BOTTOM_RIGHT"] = "bottom-right";
1113
1126
  return WatermarkPosition2;
1114
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 || {});
1115
1155
 
1116
1156
  // src/core/html/htmlThemes.ts
1117
1157
  var THEME_COMPONENTS = `
@@ -2426,7 +2466,7 @@ async function renderBackCoverHtml(backCover, baseDir = process.cwd()) {
2426
2466
  `;
2427
2467
  return { html, css };
2428
2468
  }
2429
- async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
2469
+ async function buildHtmlDocument(doc, config = {}, baseDir = process.cwd()) {
2430
2470
  var _a, _b;
2431
2471
  const resolved = resolveDocumentConfig(doc.metadata, config);
2432
2472
  const baseThemeCss = generateThemeCss(resolved.theme);
@@ -2777,8 +2817,11 @@ function escapeXml(str) {
2777
2817
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
2778
2818
  }
2779
2819
  function generateWatermarkPngBuffer(chromePath, wm) {
2780
- const tmpHtml = path4.join(os.tmpdir(), `markforge-wm-${Date.now()}-${Math.random().toString(36).slice(2)}.html`);
2781
- const tmpPng = path4.join(os.tmpdir(), `markforge-wm-${Date.now()}-${Math.random().toString(36).slice(2)}.png`);
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}`);
2782
2825
  try {
2783
2826
  const text = escapeXml(wm.text.toUpperCase());
2784
2827
  const fontSize = (wm.fontSize || 52) * 1.5;
@@ -2829,6 +2872,9 @@ function generateWatermarkPngBuffer(chromePath, wm) {
2829
2872
  chromePath,
2830
2873
  [
2831
2874
  "--headless=new",
2875
+ `--user-data-dir=${tmpProfile}`,
2876
+ "--no-first-run",
2877
+ "--no-default-browser-check",
2832
2878
  "--disable-gpu",
2833
2879
  "--disable-sync",
2834
2880
  "--disable-extensions",
@@ -2850,6 +2896,7 @@ function generateWatermarkPngBuffer(chromePath, wm) {
2850
2896
  try {
2851
2897
  if (fs4.existsSync(tmpHtml)) fs4.unlinkSync(tmpHtml);
2852
2898
  if (fs4.existsSync(tmpPng)) fs4.unlinkSync(tmpPng);
2899
+ if (fs4.existsSync(tmpProfile)) fs4.rmSync(tmpProfile, { recursive: true, force: true });
2853
2900
  } catch {
2854
2901
  }
2855
2902
  }
@@ -2865,6 +2912,8 @@ function findChromeExecutable() {
2865
2912
  const winLocalAppData = process.env.LOCALAPPDATA ?? "";
2866
2913
  const winProgramFiles = process.env.PROGRAMFILES ?? "C:\\Program Files";
2867
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 ?? "";
2868
2917
  const candidates = [
2869
2918
  // Linux
2870
2919
  "/usr/bin/google-chrome",
@@ -2883,17 +2932,34 @@ function findChromeExecutable() {
2883
2932
  // Windows — Microsoft Edge (Native Windows 10/11 browser, enterprise whitelist friendly)
2884
2933
  `${winProgramFiles}\\Microsoft\\Edge\\Application\\msedge.exe`,
2885
2934
  `${winProgramFilesX86}\\Microsoft\\Edge\\Application\\msedge.exe`,
2935
+ `${winProgramW6432}\\Microsoft\\Edge\\Application\\msedge.exe`,
2886
2936
  `${winLocalAppData}\\Microsoft\\Edge\\Application\\msedge.exe`,
2887
- // Windows — Google Chrome
2937
+ `${winLocalAppData}\\Microsoft\\Edge Dev\\Application\\msedge.exe`,
2938
+ `${winLocalAppData}\\Microsoft\\Edge Beta\\Application\\msedge.exe`,
2939
+ // Windows — Google Chrome & Chrome SxS (Canary)
2888
2940
  `${winProgramFiles}\\Google\\Chrome\\Application\\chrome.exe`,
2889
2941
  `${winProgramFilesX86}\\Google\\Chrome\\Application\\chrome.exe`,
2942
+ `${winProgramW6432}\\Google\\Chrome\\Application\\chrome.exe`,
2890
2943
  `${winLocalAppData}\\Google\\Chrome\\Application\\chrome.exe`,
2944
+ `${winLocalAppData}\\Google\\Chrome SxS\\Application\\chrome.exe`,
2891
2945
  // Windows — Brave Browser
2892
2946
  `${winProgramFiles}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
2893
2947
  `${winProgramFilesX86}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
2948
+ `${winProgramW6432}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
2894
2949
  `${winLocalAppData}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
2895
2950
  // Windows — Chromium
2896
- `${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"
2897
2963
  ].filter(Boolean);
2898
2964
  for (const candidate of candidates) {
2899
2965
  try {
@@ -2904,13 +2970,15 @@ function findChromeExecutable() {
2904
2970
  }
2905
2971
  }
2906
2972
  try {
2907
- const cmd = isWin ? "where" : "which";
2908
- 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"];
2909
2975
  for (const name of names) {
2910
- const res = spawnSync(cmd, [name], { encoding: "utf-8" });
2976
+ const res = spawnSync(cmd, [name], { encoding: "utf-8", windowsHide: true });
2911
2977
  if (res.status === 0 && res.stdout.trim()) {
2912
- const binPath = res.stdout.split(/\r?\n/)[0].trim();
2913
- if (fs4.existsSync(binPath)) return binPath;
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
+ }
2914
2982
  }
2915
2983
  }
2916
2984
  } catch {
@@ -3244,6 +3312,8 @@ async function renderMermaidToPng(mermaidCode, _baseDir = process.cwd()) {
3244
3312
  const tmpDir = os2.tmpdir();
3245
3313
  const tmpHtml = path5.join(tmpDir, `mermaid_${tmpId}.html`);
3246
3314
  const tmpScreenshot = path5.join(tmpDir, `mermaid_${tmpId}.png`);
3315
+ const tmpProfile = path5.join(tmpDir, `mermaid_prof_${tmpId}`);
3316
+ const isWin = process.platform === "win32";
3247
3317
  const htmlContent = `<!DOCTYPE html>
3248
3318
  <html>
3249
3319
  <head>
@@ -3287,10 +3357,14 @@ ${mermaidCode}
3287
3357
  const res = spawnSync2(
3288
3358
  chromePath,
3289
3359
  [
3290
- "--headless",
3360
+ "--headless=new",
3361
+ `--user-data-dir=${tmpProfile}`,
3362
+ "--no-first-run",
3363
+ "--no-default-browser-check",
3291
3364
  "--disable-gpu",
3292
- "--no-sandbox",
3293
- "--disable-setuid-sandbox",
3365
+ "--disable-sync",
3366
+ "--disable-extensions",
3367
+ ...isWin ? [] : ["--no-sandbox", "--disable-setuid-sandbox"],
3294
3368
  "--allow-file-access-from-files",
3295
3369
  "--disable-web-security",
3296
3370
  "--disable-software-rasterizer",
@@ -3299,7 +3373,7 @@ ${mermaidCode}
3299
3373
  `--screenshot=${tmpScreenshot}`,
3300
3374
  fileUrl
3301
3375
  ],
3302
- { timeout: 15e3 }
3376
+ { timeout: 15e3, windowsHide: true }
3303
3377
  );
3304
3378
  if (res.status === 0 && fs5.existsSync(tmpScreenshot)) {
3305
3379
  const buffer = fs5.readFileSync(tmpScreenshot);
@@ -3310,6 +3384,7 @@ ${mermaidCode}
3310
3384
  try {
3311
3385
  if (fs5.existsSync(tmpHtml)) fs5.unlinkSync(tmpHtml);
3312
3386
  if (fs5.existsSync(tmpScreenshot)) fs5.unlinkSync(tmpScreenshot);
3387
+ if (fs5.existsSync(tmpProfile)) fs5.rmSync(tmpProfile, { recursive: true, force: true });
3313
3388
  } catch {
3314
3389
  }
3315
3390
  }
@@ -4451,6 +4526,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
4451
4526
  );
4452
4527
  docSections.push({
4453
4528
  properties: {
4529
+ type: SectionType.NEXT_PAGE,
4454
4530
  page: {
4455
4531
  size: {
4456
4532
  width: resolved.paperDimensions.widthTwip,
@@ -4465,13 +4541,14 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
4465
4541
  }
4466
4542
  }
4467
4543
  },
4468
- headers: void 0,
4469
- footers: void 0,
4544
+ headers: { default: new Header({ children: [] }) },
4545
+ footers: { default: new Footer({ children: [] }) },
4470
4546
  children: coverElements
4471
4547
  });
4472
4548
  }
4473
4549
  docSections.push({
4474
4550
  properties: {
4551
+ type: SectionType.NEXT_PAGE,
4475
4552
  page: {
4476
4553
  pageNumbers: {
4477
4554
  start: 1,
@@ -4492,8 +4569,8 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
4492
4569
  }
4493
4570
  }
4494
4571
  },
4495
- headers: docHeader ? { default: docHeader } : void 0,
4496
- footers: docFooter ? { default: docFooter } : void 0,
4572
+ headers: docHeader ? { default: docHeader } : { default: new Header({ children: [] }) },
4573
+ footers: docFooter ? { default: docFooter } : { default: new Footer({ children: [] }) },
4497
4574
  children: docElements
4498
4575
  });
4499
4576
  if (resolved.backCover && resolved.backCover.enabled) {
@@ -4508,6 +4585,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
4508
4585
  );
4509
4586
  docSections.push({
4510
4587
  properties: {
4588
+ type: SectionType.NEXT_PAGE,
4511
4589
  page: {
4512
4590
  size: {
4513
4591
  width: resolved.paperDimensions.widthTwip,
@@ -4522,8 +4600,8 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
4522
4600
  }
4523
4601
  }
4524
4602
  },
4525
- headers: void 0,
4526
- footers: void 0,
4603
+ headers: { default: new Header({ children: [] }) },
4604
+ footers: { default: new Footer({ children: [] }) },
4527
4605
  children: backElements
4528
4606
  });
4529
4607
  }
@@ -4926,6 +5004,432 @@ function createEmptyDocxCell(widthDxa) {
4926
5004
  });
4927
5005
  }
4928
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
+
4929
5433
  // src/core/engine.ts
4930
5434
  function formatServerTimestamp(date = /* @__PURE__ */ new Date()) {
4931
5435
  const pad = (n) => String(n).padStart(2, "0");
@@ -4949,20 +5453,20 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
4949
5453
  let baseDir = process.cwd();
4950
5454
  let inputFileName = "document.md";
4951
5455
  let isFilePath = false;
4952
- if (fs6.existsSync(inputFilePathOrContent)) {
5456
+ if (fs7.existsSync(inputFilePathOrContent)) {
4953
5457
  isFilePath = true;
4954
- rawMarkdown = fs6.readFileSync(inputFilePathOrContent, "utf-8");
4955
- baseDir = path6.dirname(path6.resolve(inputFilePathOrContent));
4956
- inputFileName = path6.basename(inputFilePathOrContent);
5458
+ rawMarkdown = fs7.readFileSync(inputFilePathOrContent, "utf-8");
5459
+ baseDir = path7.dirname(path7.resolve(inputFilePathOrContent));
5460
+ inputFileName = path7.basename(inputFilePathOrContent);
4957
5461
  } else {
4958
5462
  rawMarkdown = inputFilePathOrContent;
4959
5463
  }
4960
5464
  onProgress == null ? void 0 : onProgress(`Parsing markdown AST: ${inputFileName}...`);
4961
5465
  const parsedDoc = parseMarkdownDocument(rawMarkdown);
4962
5466
  const baseName = inputFileName.replace(/\.(md|mdx|markdown)$/i, "");
4963
- const outputDir = config.outputDir ? path6.isAbsolute(config.outputDir) ? config.outputDir : path6.resolve(process.cwd(), config.outputDir) : baseDir;
4964
- if (!fs6.existsSync(outputDir)) {
4965
- fs6.mkdirSync(outputDir, { recursive: true });
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 });
4966
5470
  }
4967
5471
  const formats = Array.isArray(config.to) ? config.to : [config.to || "docx", "pdf"];
4968
5472
  const generatedFiles = [];
@@ -4972,8 +5476,8 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
4972
5476
  if (fmt === "docx") {
4973
5477
  onProgress == null ? void 0 : onProgress(`Generating DOCX document: ${baseName}.docx...`);
4974
5478
  const docxBuffer = await buildDocxDocument(parsedDoc, config, baseDir);
4975
- const docxPath = path6.join(outputDir, `${baseName}.docx`);
4976
- fs6.writeFileSync(docxPath, docxBuffer);
5479
+ const docxPath = path7.join(outputDir, `${baseName}.docx`);
5480
+ fs7.writeFileSync(docxPath, docxBuffer);
4977
5481
  generatedFiles.push({
4978
5482
  format: "docx",
4979
5483
  filePath: docxPath,
@@ -4983,8 +5487,8 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
4983
5487
  } else if (fmt === "html") {
4984
5488
  onProgress == null ? void 0 : onProgress(`Generating HTML document: ${baseName}.html...`);
4985
5489
  const htmlString = await buildHtmlDocument(parsedDoc, config, baseDir);
4986
- const htmlPath = path6.join(outputDir, `${baseName}.html`);
4987
- fs6.writeFileSync(htmlPath, htmlString, "utf-8");
5490
+ const htmlPath = path7.join(outputDir, `${baseName}.html`);
5491
+ fs7.writeFileSync(htmlPath, htmlString, "utf-8");
4988
5492
  generatedFiles.push({
4989
5493
  format: "html",
4990
5494
  filePath: htmlPath,
@@ -4994,14 +5498,36 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
4994
5498
  } else if (fmt === "pdf") {
4995
5499
  onProgress == null ? void 0 : onProgress(`Generating PDF document: ${baseName}.pdf...`);
4996
5500
  const pdfBuffer = await buildPdfDocument(parsedDoc, config, baseDir);
4997
- const pdfPath = path6.join(outputDir, `${baseName}.pdf`);
4998
- fs6.writeFileSync(pdfPath, pdfBuffer);
5501
+ const pdfPath = path7.join(outputDir, `${baseName}.pdf`);
5502
+ fs7.writeFileSync(pdfPath, pdfBuffer);
4999
5503
  generatedFiles.push({
5000
5504
  format: "pdf",
5001
5505
  filePath: pdfPath,
5002
5506
  fileName: `${baseName}.pdf`,
5003
5507
  sizeBytes: pdfBuffer.length
5004
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
+ });
5005
5531
  }
5006
5532
  } catch (err) {
5007
5533
  const errMsg = err instanceof Error ? err.message : String(err);
@@ -5020,14 +5546,14 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
5020
5546
 
5021
5547
  // src/server/previewServer.ts
5022
5548
  import * as http from "http";
5023
- import * as fs7 from "fs";
5024
- import * as path7 from "path";
5549
+ import * as fs8 from "fs";
5550
+ import * as path8 from "path";
5025
5551
  async function startPreviewServer(options) {
5026
- const absoluteFilePath = path7.resolve(process.cwd(), options.filePath);
5027
- if (!fs7.existsSync(absoluteFilePath)) {
5552
+ const absoluteFilePath = path8.resolve(process.cwd(), options.filePath);
5553
+ if (!fs8.existsSync(absoluteFilePath)) {
5028
5554
  throw new Error(`MarkForge preview error: File not found at "${absoluteFilePath}"`);
5029
5555
  }
5030
- const baseDir = path7.dirname(absoluteFilePath);
5556
+ const baseDir = path8.dirname(absoluteFilePath);
5031
5557
  const { config: fileConfig } = await loadConfig(void 0, baseDir);
5032
5558
  const baseConfig = options.config || fileConfig;
5033
5559
  const port = options.port || 3e3;
@@ -5045,9 +5571,9 @@ data: ${Date.now()}
5045
5571
  });
5046
5572
  };
5047
5573
  let debounceTimer = null;
5048
- const watcher = fs7.watch(baseDir, { recursive: false }, (_event, filename) => {
5574
+ const watcher = fs8.watch(baseDir, { recursive: false }, (_event, filename) => {
5049
5575
  if (!filename) return;
5050
- const changedPath = path7.resolve(baseDir, filename);
5576
+ const changedPath = path8.resolve(baseDir, filename);
5051
5577
  if (changedPath === absoluteFilePath || filename.includes("markforge") || filename.endsWith(".css")) {
5052
5578
  if (debounceTimer) clearTimeout(debounceTimer);
5053
5579
  debounceTimer = setTimeout(() => {
@@ -5074,12 +5600,12 @@ data: ${Date.now()}
5074
5600
  }
5075
5601
  if (url.pathname === "/api/file-content" && req.method === "GET") {
5076
5602
  try {
5077
- const content = fs7.readFileSync(absoluteFilePath, "utf-8");
5603
+ const content = fs8.readFileSync(absoluteFilePath, "utf-8");
5078
5604
  res.writeHead(200, { "Content-Type": "application/json" });
5079
5605
  res.end(
5080
5606
  JSON.stringify({
5081
5607
  content,
5082
- fileName: path7.basename(absoluteFilePath),
5608
+ fileName: path8.basename(absoluteFilePath),
5083
5609
  filePath: absoluteFilePath
5084
5610
  })
5085
5611
  );
@@ -5099,7 +5625,7 @@ data: ${Date.now()}
5099
5625
  try {
5100
5626
  const parsed = JSON.parse(body);
5101
5627
  if (typeof parsed.content === "string") {
5102
- fs7.writeFileSync(absoluteFilePath, parsed.content, "utf-8");
5628
+ fs8.writeFileSync(absoluteFilePath, parsed.content, "utf-8");
5103
5629
  broadcastReload();
5104
5630
  res.writeHead(200, { "Content-Type": "application/json" });
5105
5631
  res.end(JSON.stringify({ success: true, savedAt: Date.now() }));
@@ -5118,11 +5644,11 @@ data: ${Date.now()}
5118
5644
  if (url.pathname === "/api/export" && (req.method === "GET" || req.method === "POST")) {
5119
5645
  const format = url.searchParams.get("format") || "docx";
5120
5646
  try {
5121
- const mdContent = fs7.readFileSync(absoluteFilePath, "utf-8");
5647
+ const mdContent = fs8.readFileSync(absoluteFilePath, "utf-8");
5122
5648
  const doc = parseMarkdownDocument(mdContent);
5123
5649
  const { config: resolvedConfig } = await loadConfig(void 0, baseDir);
5124
5650
  const mergedConfig = { ...baseConfig, ...resolvedConfig };
5125
- const fileBase = path7.basename(absoluteFilePath, path7.extname(absoluteFilePath));
5651
+ const fileBase = path8.basename(absoluteFilePath, path8.extname(absoluteFilePath));
5126
5652
  if (format === "docx") {
5127
5653
  const buffer = await buildDocxDocument(doc, mergedConfig, baseDir);
5128
5654
  res.writeHead(200, {
@@ -5157,7 +5683,7 @@ data: ${Date.now()}
5157
5683
  }
5158
5684
  if (url.pathname === "/document-content") {
5159
5685
  try {
5160
- const mdContent = fs7.readFileSync(absoluteFilePath, "utf-8");
5686
+ const mdContent = fs8.readFileSync(absoluteFilePath, "utf-8");
5161
5687
  const doc = parseMarkdownDocument(mdContent);
5162
5688
  const { config: resolvedConfig } = await loadConfig(void 0, baseDir);
5163
5689
  const html = await buildHtmlDocument(doc, { ...baseConfig, ...resolvedConfig }, baseDir);
@@ -5190,8 +5716,8 @@ data: ${Date.now()}
5190
5716
  return;
5191
5717
  }
5192
5718
  if (url.pathname === "/" || url.pathname === "/index.html") {
5193
- const fileName = path7.basename(absoluteFilePath);
5194
- const initialContent = fs7.readFileSync(absoluteFilePath, "utf-8");
5719
+ const fileName = path8.basename(absoluteFilePath);
5720
+ const initialContent = fs8.readFileSync(absoluteFilePath, "utf-8");
5195
5721
  const appHtml = `<!DOCTYPE html>
5196
5722
  <html lang="en">
5197
5723
  <head>
@@ -5895,9 +6421,9 @@ function defineConfig(config) {
5895
6421
  }
5896
6422
 
5897
6423
  // src/version.ts
5898
- import * as fs8 from "fs";
5899
- import * as path8 from "path";
5900
- import { fileURLToPath } from "url";
6424
+ import * as fs9 from "fs";
6425
+ import * as path9 from "path";
6426
+ import { fileURLToPath as fileURLToPath2 } from "url";
5901
6427
  try {
5902
6428
  if (typeof globalThis !== "undefined" && (!globalThis.localStorage || typeof globalThis.localStorage.getItem !== "function")) {
5903
6429
  Object.defineProperty(globalThis, "localStorage", {
@@ -5922,16 +6448,16 @@ function readVersionFromPackageJson(fromDir) {
5922
6448
  let currentDir = fromDir;
5923
6449
  for (let i = 0; i < 10; i++) {
5924
6450
  try {
5925
- const pkgJsonPath = path8.join(currentDir, "package.json");
5926
- if (fs8.existsSync(pkgJsonPath)) {
5927
- const pkg = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
6451
+ const pkgJsonPath = path9.join(currentDir, "package.json");
6452
+ if (fs9.existsSync(pkgJsonPath)) {
6453
+ const pkg = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
5928
6454
  if (pkg.name === "@masumdev/markforge" && pkg.version) {
5929
6455
  return pkg.version;
5930
6456
  }
5931
6457
  }
5932
6458
  } catch {
5933
6459
  }
5934
- const parentDir = path8.dirname(currentDir);
6460
+ const parentDir = path9.dirname(currentDir);
5935
6461
  if (parentDir === currentDir) break;
5936
6462
  currentDir = parentDir;
5937
6463
  }
@@ -5944,7 +6470,7 @@ function getPackageDir() {
5944
6470
  return __dirname;
5945
6471
  }
5946
6472
  try {
5947
- return path8.dirname(fileURLToPath(import.meta.url));
6473
+ return path9.dirname(fileURLToPath2(import.meta.url));
5948
6474
  } catch {
5949
6475
  return process.cwd();
5950
6476
  }
@@ -5954,6 +6480,8 @@ function getMarkforgeVersion(fromDir = getPackageDir()) {
5954
6480
  return readVersionFromPackageJson(fromDir);
5955
6481
  }
5956
6482
  export {
6483
+ BackCoverPreset,
6484
+ CoverPagePreset,
5957
6485
  DEFAULT_CONFIG,
5958
6486
  KATEX_INLINE_CSS,
5959
6487
  MARKFORGE_VERSION,
@@ -5962,6 +6490,8 @@ export {
5962
6490
  PAPER_DIMENSIONS_TWIP,
5963
6491
  PaperSizeEnum,
5964
6492
  SYNTAX_COLORS,
6493
+ SignatureAlign,
6494
+ SignatureStyle,
5965
6495
  SyntaxTheme,
5966
6496
  THEMES,
5967
6497
  THEME_CORPORATE,
@@ -5972,6 +6502,9 @@ export {
5972
6502
  buildDocxDocument,
5973
6503
  buildHtmlDocument,
5974
6504
  buildPdfDocument,
6505
+ buildPngDocument,
6506
+ buildTextDocument,
6507
+ buildTextDocument as buildTxtDocument,
5975
6508
  compileMarkdown,
5976
6509
  defineConfig,
5977
6510
  escapeHtml,
@@ -6000,6 +6533,7 @@ export {
6000
6533
  renderBackCoverHtml,
6001
6534
  renderCoverPageHtml,
6002
6535
  renderInlinesToHtml,
6536
+ renderInlinesToText,
6003
6537
  renderMathToHtml,
6004
6538
  renderMermaidToPng,
6005
6539
  renderNodesToHtml,