@masumdev/markforge 0.2.4 → 0.2.5
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 +203 -302
- package/dist/{App-IJVCGBJM.mjs → App-GNRUPFM7.mjs} +899 -323
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +309 -62
- package/dist/index.d.ts +309 -62
- package/dist/index.js +1149 -483
- package/dist/index.mjs +1137 -484
- package/package.json +1 -1
- package/schema.json +198 -36
package/dist/index.mjs
CHANGED
|
@@ -550,6 +550,51 @@ var SYNTAX_COLORS_LIGHT = {
|
|
|
550
550
|
plain: "24292E"
|
|
551
551
|
// Near-black — identifiers
|
|
552
552
|
};
|
|
553
|
+
var SYNTAX_THEMES = {
|
|
554
|
+
"github-dark": SYNTAX_COLORS,
|
|
555
|
+
"dark": SYNTAX_COLORS,
|
|
556
|
+
"github-light": SYNTAX_COLORS_LIGHT,
|
|
557
|
+
"light": SYNTAX_COLORS_LIGHT,
|
|
558
|
+
"dracula": {
|
|
559
|
+
keyword: "FF79C6",
|
|
560
|
+
string: "F1FA8C",
|
|
561
|
+
comment: "6272A4",
|
|
562
|
+
number: "BD93F9",
|
|
563
|
+
boolean: "BD93F9",
|
|
564
|
+
function: "50FA7B",
|
|
565
|
+
type: "8BE9FD",
|
|
566
|
+
operator: "FF79C6",
|
|
567
|
+
punctuation: "F8F8F2",
|
|
568
|
+
plain: "F8F8F2"
|
|
569
|
+
},
|
|
570
|
+
"monokai": {
|
|
571
|
+
keyword: "F92672",
|
|
572
|
+
string: "E6DB74",
|
|
573
|
+
comment: "75715E",
|
|
574
|
+
number: "AE81FF",
|
|
575
|
+
boolean: "AE81FF",
|
|
576
|
+
function: "A6E22E",
|
|
577
|
+
type: "66D9EF",
|
|
578
|
+
operator: "F92672",
|
|
579
|
+
punctuation: "F8F8F2",
|
|
580
|
+
plain: "F8F8F2"
|
|
581
|
+
},
|
|
582
|
+
"nord": {
|
|
583
|
+
keyword: "81A1C1",
|
|
584
|
+
string: "A3BE8C",
|
|
585
|
+
comment: "616E88",
|
|
586
|
+
number: "B48EAD",
|
|
587
|
+
boolean: "81A1C1",
|
|
588
|
+
function: "88C0D0",
|
|
589
|
+
type: "8FBCBB",
|
|
590
|
+
operator: "81A1C1",
|
|
591
|
+
punctuation: "ECEFF4",
|
|
592
|
+
plain: "D8DEE9"
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
function getSyntaxPalette(themeName = "github-dark") {
|
|
596
|
+
return SYNTAX_THEMES[themeName.toLowerCase()] || SYNTAX_THEMES["github-dark"];
|
|
597
|
+
}
|
|
553
598
|
var JS_KEYWORDS = /* @__PURE__ */ new Set([
|
|
554
599
|
"import",
|
|
555
600
|
"from",
|
|
@@ -693,9 +738,9 @@ var SQL_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
693
738
|
"foreign",
|
|
694
739
|
"references"
|
|
695
740
|
]);
|
|
696
|
-
function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
741
|
+
function tokenizeCodeLine(line, lang = "", theme = "github-dark") {
|
|
697
742
|
var _a;
|
|
698
|
-
const COLORS = theme
|
|
743
|
+
const COLORS = getSyntaxPalette(theme);
|
|
699
744
|
if (!line) {
|
|
700
745
|
return [{ text: " ", type: "plain", colorHex: COLORS.plain }];
|
|
701
746
|
}
|
|
@@ -778,6 +823,10 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
778
823
|
tokens.push({ text: word, type: "keyword", colorHex: COLORS.keyword, bold: true });
|
|
779
824
|
continue;
|
|
780
825
|
}
|
|
826
|
+
if (/^[A-Z][a-zA-Z0-9_$]*$/.test(word)) {
|
|
827
|
+
tokens.push({ text: word, type: "type", colorHex: COLORS.type });
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
781
830
|
let nextNonWs = pos;
|
|
782
831
|
while (nextNonWs < line.length && /\s/.test(line[nextNonWs])) {
|
|
783
832
|
nextNonWs++;
|
|
@@ -786,10 +835,6 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
786
835
|
tokens.push({ text: word, type: "function", colorHex: COLORS.function });
|
|
787
836
|
continue;
|
|
788
837
|
}
|
|
789
|
-
if (/^[A-Z][a-zA-Z0-9_$]*$/.test(word)) {
|
|
790
|
-
tokens.push({ text: word, type: "type", colorHex: COLORS.type });
|
|
791
|
-
continue;
|
|
792
|
-
}
|
|
793
838
|
tokens.push({ text: word, type: "plain", colorHex: COLORS.plain });
|
|
794
839
|
continue;
|
|
795
840
|
}
|
|
@@ -802,10 +847,10 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
802
847
|
}
|
|
803
848
|
return tokens;
|
|
804
849
|
}
|
|
805
|
-
function highlightCodeToHtml(code, lang = "") {
|
|
850
|
+
function highlightCodeToHtml(code, lang = "", theme = "github-dark") {
|
|
806
851
|
const lines = (code || "").split("\n");
|
|
807
852
|
const htmlLines = lines.map((line) => {
|
|
808
|
-
const tokens = tokenizeCodeLine(line, lang);
|
|
853
|
+
const tokens = tokenizeCodeLine(line, lang, theme);
|
|
809
854
|
return tokens.map((t) => {
|
|
810
855
|
const escaped = t.text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
811
856
|
if (t.type === "plain") return escaped;
|
|
@@ -817,21 +862,62 @@ function highlightCodeToHtml(code, lang = "") {
|
|
|
817
862
|
|
|
818
863
|
// src/core/mermaid/mermaidRenderer.ts
|
|
819
864
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
820
|
-
import * as
|
|
865
|
+
import * as fs5 from "fs";
|
|
821
866
|
import * as os2 from "os";
|
|
822
|
-
import * as
|
|
823
|
-
import { pathToFileURL as
|
|
867
|
+
import * as path5 from "path";
|
|
868
|
+
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
824
869
|
|
|
825
870
|
// src/core/pdf/pdfBuilder.ts
|
|
826
|
-
import * as
|
|
827
|
-
import * as
|
|
871
|
+
import * as fs4 from "fs";
|
|
872
|
+
import * as path4 from "path";
|
|
828
873
|
import * as os from "os";
|
|
829
|
-
import { pathToFileURL } from "url";
|
|
874
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
830
875
|
import { spawnSync } from "child_process";
|
|
831
876
|
|
|
832
877
|
// src/core/html/htmlBuilder.ts
|
|
833
|
-
import * as
|
|
834
|
-
import * as
|
|
878
|
+
import * as fs3 from "fs";
|
|
879
|
+
import * as path3 from "path";
|
|
880
|
+
|
|
881
|
+
// src/config/types.ts
|
|
882
|
+
var OutputFormat = /* @__PURE__ */ ((OutputFormat2) => {
|
|
883
|
+
OutputFormat2["DOCX"] = "docx";
|
|
884
|
+
OutputFormat2["PDF"] = "pdf";
|
|
885
|
+
OutputFormat2["HTML"] = "html";
|
|
886
|
+
OutputFormat2["PNG"] = "png";
|
|
887
|
+
return OutputFormat2;
|
|
888
|
+
})(OutputFormat || {});
|
|
889
|
+
var Theme = /* @__PURE__ */ ((Theme2) => {
|
|
890
|
+
Theme2["CORPORATE"] = "corporate";
|
|
891
|
+
return Theme2;
|
|
892
|
+
})(Theme || {});
|
|
893
|
+
var Orientation = /* @__PURE__ */ ((Orientation2) => {
|
|
894
|
+
Orientation2["PORTRAIT"] = "portrait";
|
|
895
|
+
Orientation2["LANDSCAPE"] = "landscape";
|
|
896
|
+
return Orientation2;
|
|
897
|
+
})(Orientation || {});
|
|
898
|
+
var PaperSizeEnum = /* @__PURE__ */ ((PaperSizeEnum2) => {
|
|
899
|
+
PaperSizeEnum2["A4"] = "A4";
|
|
900
|
+
PaperSizeEnum2["LETTER"] = "Letter";
|
|
901
|
+
PaperSizeEnum2["LEGAL"] = "Legal";
|
|
902
|
+
PaperSizeEnum2["A3"] = "A3";
|
|
903
|
+
PaperSizeEnum2["A5"] = "A5";
|
|
904
|
+
return PaperSizeEnum2;
|
|
905
|
+
})(PaperSizeEnum || {});
|
|
906
|
+
var SyntaxTheme = /* @__PURE__ */ ((SyntaxTheme2) => {
|
|
907
|
+
SyntaxTheme2["GITHUB_DARK"] = "github-dark";
|
|
908
|
+
SyntaxTheme2["GITHUB_LIGHT"] = "github-light";
|
|
909
|
+
SyntaxTheme2["DRACULA"] = "dracula";
|
|
910
|
+
SyntaxTheme2["MONOKAI"] = "monokai";
|
|
911
|
+
SyntaxTheme2["NORD"] = "nord";
|
|
912
|
+
return SyntaxTheme2;
|
|
913
|
+
})(SyntaxTheme || {});
|
|
914
|
+
var WatermarkPosition = /* @__PURE__ */ ((WatermarkPosition2) => {
|
|
915
|
+
WatermarkPosition2["DIAGONAL"] = "diagonal";
|
|
916
|
+
WatermarkPosition2["CENTER"] = "center";
|
|
917
|
+
WatermarkPosition2["TOP_RIGHT"] = "top-right";
|
|
918
|
+
WatermarkPosition2["BOTTOM_RIGHT"] = "bottom-right";
|
|
919
|
+
return WatermarkPosition2;
|
|
920
|
+
})(WatermarkPosition || {});
|
|
835
921
|
|
|
836
922
|
// src/core/html/htmlThemes.ts
|
|
837
923
|
var THEME_COMPONENTS = `
|
|
@@ -914,7 +1000,7 @@ hr { border: none; border-top: 1px solid var(--mf-border); margin: 2rem 0; }
|
|
|
914
1000
|
pre { overflow: visible; white-space: pre-wrap; word-break: break-all; }
|
|
915
1001
|
}
|
|
916
1002
|
`;
|
|
917
|
-
var
|
|
1003
|
+
var THEME_CORPORATE = `
|
|
918
1004
|
:root {
|
|
919
1005
|
--mf-bg: #ffffff;
|
|
920
1006
|
--mf-text: #0f172a;
|
|
@@ -926,49 +1012,415 @@ var THEME_DEFAULT = `
|
|
|
926
1012
|
--mf-card-bg: #f8fafc;
|
|
927
1013
|
--mf-code-bg: #0f172a;
|
|
928
1014
|
--mf-code-text: #f8fafc;
|
|
929
|
-
--mf-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
1015
|
+
--mf-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
930
1016
|
--mf-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
931
1017
|
}
|
|
932
1018
|
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; }
|
|
933
|
-
.document-container { max-width: 860px; margin: 0 auto; }
|
|
1019
|
+
.document-container { max-width: 860px; margin: 0 auto; position: relative; z-index: 1; }
|
|
934
1020
|
h1, h2, h3, h4, h5, h6 { color: var(--mf-text); font-weight: 700; margin-top: 1.8rem; margin-bottom: 0.8rem; line-height: 1.25; }
|
|
935
|
-
h1 { font-size: 2.2rem; border-bottom: 2px solid
|
|
936
|
-
h2 { font-size: 1.6rem; color:
|
|
1021
|
+
h1 { font-size: 2.2rem; border-bottom: 2px solid var(--mf-primary); padding-bottom: 0.5rem; }
|
|
1022
|
+
h2 { font-size: 1.6rem; color: var(--mf-primary-dark); border-bottom: 1px solid #CCFBF1; padding-bottom: 0.4rem; }
|
|
937
1023
|
h3 { font-size: 1.3rem; }
|
|
938
1024
|
h4 { font-size: 1.1rem; }
|
|
939
1025
|
p { margin: 0.8rem 0; }
|
|
940
1026
|
`;
|
|
941
|
-
var
|
|
1027
|
+
var THEME_DEFAULT = THEME_CORPORATE;
|
|
1028
|
+
var THEMES = {
|
|
1029
|
+
corporate: THEME_CORPORATE,
|
|
1030
|
+
default: THEME_CORPORATE
|
|
1031
|
+
};
|
|
1032
|
+
function generateThemeCss(theme) {
|
|
1033
|
+
if (!theme || theme === "corporate" || theme === "default" || theme === "corporate" /* CORPORATE */) {
|
|
1034
|
+
return THEME_CORPORATE;
|
|
1035
|
+
}
|
|
1036
|
+
if (typeof theme === "object") {
|
|
1037
|
+
const bg = theme.backgroundColor || "#ffffff";
|
|
1038
|
+
const text = theme.textColor || "#0f172a";
|
|
1039
|
+
const textMuted = theme.textMuted || "#64748b";
|
|
1040
|
+
const primary = theme.primaryColor || "#33CDCF";
|
|
1041
|
+
const primaryDark = theme.primaryDark || primary;
|
|
1042
|
+
const primaryLight = theme.primaryLight || "#ECFDFD";
|
|
1043
|
+
const border = theme.borderColor || "#e2e8f0";
|
|
1044
|
+
const cardBg = theme.cardBackground || "#f8fafc";
|
|
1045
|
+
const codeBg = theme.codeBackground || "#0f172a";
|
|
1046
|
+
const codeText = theme.codeText || "#f8fafc";
|
|
1047
|
+
const font = theme.fontFamily || "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
|
|
1048
|
+
const fontMono = theme.fontMono || "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace";
|
|
1049
|
+
return `
|
|
942
1050
|
:root {
|
|
943
|
-
--mf-bg:
|
|
944
|
-
--mf-text:
|
|
945
|
-
--mf-text-muted:
|
|
946
|
-
--mf-primary:
|
|
947
|
-
--mf-primary-dark:
|
|
948
|
-
--mf-primary-light:
|
|
949
|
-
--mf-border:
|
|
950
|
-
--mf-card-bg:
|
|
951
|
-
--mf-code-bg:
|
|
952
|
-
--mf-code-text:
|
|
953
|
-
--mf-font-family:
|
|
954
|
-
--mf-font-mono:
|
|
1051
|
+
--mf-bg: ${bg};
|
|
1052
|
+
--mf-text: ${text};
|
|
1053
|
+
--mf-text-muted: ${textMuted};
|
|
1054
|
+
--mf-primary: ${primary};
|
|
1055
|
+
--mf-primary-dark: ${primaryDark};
|
|
1056
|
+
--mf-primary-light: ${primaryLight};
|
|
1057
|
+
--mf-border: ${border};
|
|
1058
|
+
--mf-card-bg: ${cardBg};
|
|
1059
|
+
--mf-code-bg: ${codeBg};
|
|
1060
|
+
--mf-code-text: ${codeText};
|
|
1061
|
+
--mf-font-family: ${font};
|
|
1062
|
+
--mf-font-mono: ${fontMono};
|
|
955
1063
|
}
|
|
956
|
-
body { font-family: var(--mf-font-family); font-size:
|
|
957
|
-
.document-container { max-width:
|
|
958
|
-
h1, h2, h3 { font-
|
|
959
|
-
h1 { font-size: 2rem; border-bottom:
|
|
960
|
-
h2 { font-size: 1.
|
|
961
|
-
h3 { font-size: 1.
|
|
962
|
-
|
|
1064
|
+
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; }
|
|
1065
|
+
.document-container { max-width: 860px; margin: 0 auto; position: relative; z-index: 1; }
|
|
1066
|
+
h1, h2, h3, h4, h5, h6 { color: var(--mf-text); font-weight: 700; margin-top: 1.8rem; margin-bottom: 0.8rem; line-height: 1.25; }
|
|
1067
|
+
h1 { font-size: 2.2rem; border-bottom: 2px solid var(--mf-primary); padding-bottom: 0.5rem; }
|
|
1068
|
+
h2 { font-size: 1.6rem; color: var(--mf-primary-dark); border-bottom: 1px solid var(--mf-border); padding-bottom: 0.4rem; }
|
|
1069
|
+
h3 { font-size: 1.3rem; }
|
|
1070
|
+
h4 { font-size: 1.1rem; }
|
|
1071
|
+
p { margin: 0.8rem 0; }
|
|
1072
|
+
${theme.customCss || ""}
|
|
963
1073
|
`;
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1074
|
+
}
|
|
1075
|
+
if (typeof theme === "string" && THEMES[theme]) {
|
|
1076
|
+
return THEMES[theme];
|
|
1077
|
+
}
|
|
1078
|
+
return THEME_CORPORATE;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// src/config/loadConfig.ts
|
|
1082
|
+
import * as fs2 from "fs";
|
|
1083
|
+
import * as path2 from "path";
|
|
1084
|
+
import { pathToFileURL } from "url";
|
|
1085
|
+
import * as YAML from "yaml";
|
|
1086
|
+
var DEFAULT_CONFIG_FILENAMES = [
|
|
1087
|
+
"markforge.config.json",
|
|
1088
|
+
".markforgerc.json",
|
|
1089
|
+
"markforge.config.yaml",
|
|
1090
|
+
"markforge.config.yml",
|
|
1091
|
+
".markforgerc.yaml",
|
|
1092
|
+
".markforgerc.yml",
|
|
1093
|
+
".markforgerc",
|
|
1094
|
+
"markforge.config.ts",
|
|
1095
|
+
"markforge.config.js",
|
|
1096
|
+
"markforge.config.mjs",
|
|
1097
|
+
"markforge.config.cjs"
|
|
1098
|
+
];
|
|
1099
|
+
var DEFAULT_CONFIG = {
|
|
1100
|
+
to: ["docx", "pdf"],
|
|
1101
|
+
outputDir: void 0,
|
|
1102
|
+
theme: "default",
|
|
1103
|
+
css: void 0,
|
|
1104
|
+
orientation: "portrait",
|
|
1105
|
+
paperSize: "A4",
|
|
1106
|
+
margins: {
|
|
1107
|
+
top: "2.5cm",
|
|
1108
|
+
bottom: "2.5cm",
|
|
1109
|
+
left: "2.5cm",
|
|
1110
|
+
right: "2.5cm"
|
|
1111
|
+
},
|
|
1112
|
+
header: void 0,
|
|
1113
|
+
footer: {
|
|
1114
|
+
right: "Page {page} of {pages}"
|
|
1115
|
+
},
|
|
1116
|
+
toc: false,
|
|
1117
|
+
watermark: void 0,
|
|
1118
|
+
embedImages: true,
|
|
1119
|
+
metadata: void 0,
|
|
1120
|
+
watch: false,
|
|
1121
|
+
serve: false,
|
|
1122
|
+
port: 4e3,
|
|
1123
|
+
open: false,
|
|
1124
|
+
bundleHtml: true,
|
|
1125
|
+
syntaxTheme: "github-dark"
|
|
1126
|
+
};
|
|
1127
|
+
function discoverConfigFile(startDir) {
|
|
1128
|
+
const dirsToCheck = [];
|
|
1129
|
+
let curr = path2.resolve(startDir);
|
|
1130
|
+
while (curr) {
|
|
1131
|
+
dirsToCheck.push(curr);
|
|
1132
|
+
const parent = path2.dirname(curr);
|
|
1133
|
+
if (parent === curr) break;
|
|
1134
|
+
curr = parent;
|
|
1135
|
+
}
|
|
1136
|
+
const cwd = path2.resolve(process.cwd());
|
|
1137
|
+
if (!dirsToCheck.includes(cwd)) {
|
|
1138
|
+
dirsToCheck.push(cwd);
|
|
1139
|
+
}
|
|
1140
|
+
for (const dir of dirsToCheck) {
|
|
1141
|
+
for (const filename of DEFAULT_CONFIG_FILENAMES) {
|
|
1142
|
+
const candidate = path2.join(dir, filename);
|
|
1143
|
+
if (fs2.existsSync(candidate) && fs2.statSync(candidate).isFile()) {
|
|
1144
|
+
return candidate;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
return null;
|
|
1149
|
+
}
|
|
1150
|
+
async function loadConfig(customPath, startDir = process.cwd()) {
|
|
1151
|
+
let resolvedPath = null;
|
|
1152
|
+
if (customPath) {
|
|
1153
|
+
resolvedPath = path2.isAbsolute(customPath) ? customPath : path2.resolve(process.cwd(), customPath);
|
|
1154
|
+
if (!fs2.existsSync(resolvedPath)) {
|
|
1155
|
+
const altPath = path2.resolve(startDir, customPath);
|
|
1156
|
+
if (fs2.existsSync(altPath)) {
|
|
1157
|
+
resolvedPath = altPath;
|
|
1158
|
+
} else {
|
|
1159
|
+
throw new Error(`Configuration file not found: ${resolvedPath}`);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
} else {
|
|
1163
|
+
resolvedPath = discoverConfigFile(startDir);
|
|
1164
|
+
}
|
|
1165
|
+
if (!resolvedPath) {
|
|
1166
|
+
return {
|
|
1167
|
+
config: { ...DEFAULT_CONFIG },
|
|
1168
|
+
configPath: null
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
const ext = path2.extname(resolvedPath).toLowerCase();
|
|
1172
|
+
let userConfig = {};
|
|
1173
|
+
try {
|
|
1174
|
+
if (ext === ".json" || ext === "" || resolvedPath.endsWith(".markforgerc")) {
|
|
1175
|
+
const raw = fs2.readFileSync(resolvedPath, "utf-8").trim();
|
|
1176
|
+
try {
|
|
1177
|
+
userConfig = JSON.parse(raw);
|
|
1178
|
+
} catch {
|
|
1179
|
+
userConfig = YAML.parse(raw) || {};
|
|
1180
|
+
}
|
|
1181
|
+
} else if (ext === ".yaml" || ext === ".yml") {
|
|
1182
|
+
const raw = fs2.readFileSync(resolvedPath, "utf-8");
|
|
1183
|
+
userConfig = YAML.parse(raw) || {};
|
|
1184
|
+
} else if (ext === ".ts" || ext === ".js" || ext === ".mjs" || ext === ".cjs") {
|
|
1185
|
+
try {
|
|
1186
|
+
const fileUrl = `${pathToFileURL(resolvedPath).href}?t=${Date.now()}`;
|
|
1187
|
+
const mod = await import(fileUrl);
|
|
1188
|
+
const rawExport = mod.default ?? mod.config ?? mod;
|
|
1189
|
+
userConfig = (typeof rawExport === "function" ? await rawExport() : rawExport) || {};
|
|
1190
|
+
} catch (importErr) {
|
|
1191
|
+
try {
|
|
1192
|
+
const mod = __require(resolvedPath);
|
|
1193
|
+
const rawExport = mod.default ?? mod.config ?? mod;
|
|
1194
|
+
userConfig = (typeof rawExport === "function" ? await rawExport() : rawExport) || {};
|
|
1195
|
+
} catch {
|
|
1196
|
+
throw importErr;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
} catch (err) {
|
|
1201
|
+
throw new Error(
|
|
1202
|
+
`Failed to parse configuration file at ${resolvedPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
if (userConfig && typeof userConfig === "object" && "$schema" in userConfig) {
|
|
1206
|
+
delete userConfig.$schema;
|
|
1207
|
+
}
|
|
1208
|
+
const parsedConfig = userConfig;
|
|
1209
|
+
const mergedConfig = {
|
|
1210
|
+
...DEFAULT_CONFIG,
|
|
1211
|
+
...parsedConfig,
|
|
1212
|
+
margins: {
|
|
1213
|
+
...DEFAULT_CONFIG.margins,
|
|
1214
|
+
...parsedConfig.margins || {}
|
|
1215
|
+
},
|
|
1216
|
+
header: parsedConfig.header !== void 0 ? parsedConfig.header : DEFAULT_CONFIG.header,
|
|
1217
|
+
footer: parsedConfig.footer !== void 0 ? parsedConfig.footer : DEFAULT_CONFIG.footer,
|
|
1218
|
+
metadata: {
|
|
1219
|
+
...DEFAULT_CONFIG.metadata || {},
|
|
1220
|
+
...parsedConfig.metadata || {}
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
return {
|
|
1224
|
+
config: mergedConfig,
|
|
1225
|
+
configPath: resolvedPath
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
// src/config/resolveConfig.ts
|
|
1230
|
+
var PAPER_DIMENSIONS_TWIP = {
|
|
1231
|
+
A4: { width: 11906, height: 16838 },
|
|
1232
|
+
// 210mm x 297mm
|
|
1233
|
+
Letter: { width: 12240, height: 15840 },
|
|
1234
|
+
// 8.5in x 11in
|
|
1235
|
+
Legal: { width: 12240, height: 20160 },
|
|
1236
|
+
// 8.5in x 14in
|
|
1237
|
+
A3: { width: 16838, height: 23811 },
|
|
1238
|
+
// 297mm x 420mm
|
|
1239
|
+
A5: { width: 8390, height: 11906 }
|
|
1240
|
+
// 148mm x 210mm
|
|
971
1241
|
};
|
|
1242
|
+
function parseMarginToTwip(margin, defaultTwip = 1440) {
|
|
1243
|
+
if (typeof margin === "number") return margin;
|
|
1244
|
+
if (!margin) return defaultTwip;
|
|
1245
|
+
const str = margin.trim().toLowerCase();
|
|
1246
|
+
if (str.endsWith("cm")) {
|
|
1247
|
+
const cm = parseFloat(str);
|
|
1248
|
+
return isNaN(cm) ? defaultTwip : Math.round(cm * 566.929);
|
|
1249
|
+
}
|
|
1250
|
+
if (str.endsWith("mm")) {
|
|
1251
|
+
const mm = parseFloat(str);
|
|
1252
|
+
return isNaN(mm) ? defaultTwip : Math.round(mm * 56.6929);
|
|
1253
|
+
}
|
|
1254
|
+
if (str.endsWith("in") || str.endsWith("inch")) {
|
|
1255
|
+
const inch = parseFloat(str);
|
|
1256
|
+
return isNaN(inch) ? defaultTwip : Math.round(inch * 1440);
|
|
1257
|
+
}
|
|
1258
|
+
if (str.endsWith("pt")) {
|
|
1259
|
+
const pt = parseFloat(str);
|
|
1260
|
+
return isNaN(pt) ? defaultTwip : Math.round(pt * 20);
|
|
1261
|
+
}
|
|
1262
|
+
const val = parseFloat(str);
|
|
1263
|
+
return isNaN(val) ? defaultTwip : Math.round(val);
|
|
1264
|
+
}
|
|
1265
|
+
function formatMarginCss(margin, defaultCss = "2.5cm") {
|
|
1266
|
+
if (margin === void 0 || margin === null) return defaultCss;
|
|
1267
|
+
if (typeof margin === "number") return `${margin}pt`;
|
|
1268
|
+
const str = margin.trim();
|
|
1269
|
+
if (!str) return defaultCss;
|
|
1270
|
+
if (/^[0-9.]+$/.test(str)) return `${str}pt`;
|
|
1271
|
+
return str;
|
|
1272
|
+
}
|
|
1273
|
+
function replaceDocumentTokens(template = "", meta) {
|
|
1274
|
+
return template.replace(/\{title\}/gi, meta.title || "").replace(/\{subtitle\}/gi, meta.subtitle || "").replace(/\{author\}/gi, meta.author || "").replace(/\{version\}/gi, meta.version || "").replace(/\{date\}/gi, meta.date || "").replace(/\{company\}/gi, meta.company || "");
|
|
1275
|
+
}
|
|
1276
|
+
function normalizeWatermark(rawWatermark) {
|
|
1277
|
+
if (!rawWatermark) {
|
|
1278
|
+
return void 0;
|
|
1279
|
+
}
|
|
1280
|
+
if (typeof rawWatermark === "string") {
|
|
1281
|
+
const text = rawWatermark.trim();
|
|
1282
|
+
if (!text) return void 0;
|
|
1283
|
+
return {
|
|
1284
|
+
text,
|
|
1285
|
+
color: "#94a3b8",
|
|
1286
|
+
opacity: 0.08,
|
|
1287
|
+
fontSize: 54,
|
|
1288
|
+
rotate: -45,
|
|
1289
|
+
position: "diagonal"
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
if (typeof rawWatermark === "object") {
|
|
1293
|
+
if (!rawWatermark.text || !rawWatermark.text.trim()) return void 0;
|
|
1294
|
+
return {
|
|
1295
|
+
text: rawWatermark.text.trim(),
|
|
1296
|
+
color: rawWatermark.color || "#94a3b8",
|
|
1297
|
+
opacity: typeof rawWatermark.opacity === "number" ? rawWatermark.opacity : 0.08,
|
|
1298
|
+
fontSize: rawWatermark.fontSize || 54,
|
|
1299
|
+
rotate: typeof rawWatermark.rotate === "number" ? rawWatermark.rotate : -45,
|
|
1300
|
+
position: rawWatermark.position || "diagonal"
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
return void 0;
|
|
1304
|
+
}
|
|
1305
|
+
function normalizeHeaderFooterSlot(rawSlot, parent, meta) {
|
|
1306
|
+
if (!rawSlot) return void 0;
|
|
1307
|
+
if (typeof rawSlot === "string") {
|
|
1308
|
+
const text = replaceDocumentTokens(rawSlot, meta).trim();
|
|
1309
|
+
if (!text) return void 0;
|
|
1310
|
+
return {
|
|
1311
|
+
text,
|
|
1312
|
+
color: (parent == null ? void 0 : parent.color) || "#94A3B8",
|
|
1313
|
+
fontSize: (parent == null ? void 0 : parent.size) || 9,
|
|
1314
|
+
fontFamily: (parent == null ? void 0 : parent.font) || "Segoe UI",
|
|
1315
|
+
bold: false,
|
|
1316
|
+
italic: false
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
if (typeof rawSlot === "object") {
|
|
1320
|
+
const text = replaceDocumentTokens(rawSlot.text || "", meta).trim();
|
|
1321
|
+
if (!text) return void 0;
|
|
1322
|
+
return {
|
|
1323
|
+
text,
|
|
1324
|
+
color: rawSlot.color || (parent == null ? void 0 : parent.color) || "#94A3B8",
|
|
1325
|
+
fontSize: rawSlot.fontSize || (parent == null ? void 0 : parent.size) || 9,
|
|
1326
|
+
fontFamily: rawSlot.fontFamily || (parent == null ? void 0 : parent.font) || "Segoe UI",
|
|
1327
|
+
bold: Boolean(rawSlot.bold),
|
|
1328
|
+
italic: Boolean(rawSlot.italic)
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
return void 0;
|
|
1332
|
+
}
|
|
1333
|
+
function normalizeHeaderFooter(raw, meta) {
|
|
1334
|
+
if (!raw) return void 0;
|
|
1335
|
+
const left = normalizeHeaderFooterSlot(raw.left, raw, meta);
|
|
1336
|
+
const center = normalizeHeaderFooterSlot(raw.center, raw, meta);
|
|
1337
|
+
const right = normalizeHeaderFooterSlot(raw.right, raw, meta);
|
|
1338
|
+
if (!left && !center && !right) return void 0;
|
|
1339
|
+
return {
|
|
1340
|
+
left,
|
|
1341
|
+
center,
|
|
1342
|
+
right,
|
|
1343
|
+
font: raw.font || "Segoe UI",
|
|
1344
|
+
size: raw.size || 9,
|
|
1345
|
+
color: raw.color || "#94A3B8",
|
|
1346
|
+
divider: Boolean(raw.divider),
|
|
1347
|
+
dividerColor: raw.dividerColor || "#E2E8F0"
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
function resolveDocumentConfig(frontmatter = {}, userConfig = {}) {
|
|
1351
|
+
const configMeta = userConfig.metadata || {};
|
|
1352
|
+
const mergedMeta = { ...configMeta, ...frontmatter };
|
|
1353
|
+
const title = mergedMeta.title || "MarkForge Document";
|
|
1354
|
+
const subtitle = mergedMeta.subtitle || void 0;
|
|
1355
|
+
const author = Array.isArray(mergedMeta.author) ? mergedMeta.author.join(", ") : mergedMeta.author || void 0;
|
|
1356
|
+
const date = mergedMeta.date || void 0;
|
|
1357
|
+
const version = mergedMeta.version || void 0;
|
|
1358
|
+
const company = mergedMeta.company || void 0;
|
|
1359
|
+
const lang = mergedMeta.lang || "en";
|
|
1360
|
+
const tokenContext = { title, subtitle, author, version, date, company };
|
|
1361
|
+
const theme = mergedMeta.theme || userConfig.theme || DEFAULT_CONFIG.theme;
|
|
1362
|
+
const orientation = mergedMeta.orientation || userConfig.orientation || DEFAULT_CONFIG.orientation;
|
|
1363
|
+
const paperSize = mergedMeta.paperSize || userConfig.paperSize || DEFAULT_CONFIG.paperSize;
|
|
1364
|
+
const baseDim = PAPER_DIMENSIONS_TWIP[paperSize] || PAPER_DIMENSIONS_TWIP.A4;
|
|
1365
|
+
const paperDimensions = orientation === "landscape" ? { widthTwip: baseDim.height, heightTwip: baseDim.width } : { widthTwip: baseDim.width, heightTwip: baseDim.height };
|
|
1366
|
+
const fmMargin = mergedMeta.margins || {};
|
|
1367
|
+
const cfgMargin = userConfig.margins || {};
|
|
1368
|
+
const defMargin = DEFAULT_CONFIG.margins || {};
|
|
1369
|
+
const topRaw = fmMargin.top ?? cfgMargin.top ?? defMargin.top ?? "2.5cm";
|
|
1370
|
+
const bottomRaw = fmMargin.bottom ?? cfgMargin.bottom ?? defMargin.bottom ?? "2.5cm";
|
|
1371
|
+
const leftRaw = fmMargin.left ?? cfgMargin.left ?? defMargin.left ?? "2.5cm";
|
|
1372
|
+
const rightRaw = fmMargin.right ?? cfgMargin.right ?? defMargin.right ?? "2.5cm";
|
|
1373
|
+
const margins = {
|
|
1374
|
+
top: formatMarginCss(topRaw),
|
|
1375
|
+
bottom: formatMarginCss(bottomRaw),
|
|
1376
|
+
left: formatMarginCss(leftRaw),
|
|
1377
|
+
right: formatMarginCss(rightRaw),
|
|
1378
|
+
topTwip: parseMarginToTwip(topRaw),
|
|
1379
|
+
bottomTwip: parseMarginToTwip(bottomRaw),
|
|
1380
|
+
leftTwip: parseMarginToTwip(leftRaw),
|
|
1381
|
+
rightTwip: parseMarginToTwip(rightRaw)
|
|
1382
|
+
};
|
|
1383
|
+
const rawHeader = mergedMeta.header || userConfig.header || DEFAULT_CONFIG.header;
|
|
1384
|
+
const rawFooter = mergedMeta.footer || userConfig.footer || DEFAULT_CONFIG.footer;
|
|
1385
|
+
const header = normalizeHeaderFooter(rawHeader, tokenContext);
|
|
1386
|
+
const footer = normalizeHeaderFooter(rawFooter, tokenContext);
|
|
1387
|
+
const toc = typeof mergedMeta.toc === "boolean" ? mergedMeta.toc : typeof userConfig.toc === "boolean" ? userConfig.toc : DEFAULT_CONFIG.toc;
|
|
1388
|
+
const rawWatermark = mergedMeta.watermark !== void 0 ? mergedMeta.watermark : userConfig.watermark !== void 0 ? userConfig.watermark : DEFAULT_CONFIG.watermark;
|
|
1389
|
+
const watermark = normalizeWatermark(rawWatermark);
|
|
1390
|
+
const cssList = [];
|
|
1391
|
+
const addCss = (item) => {
|
|
1392
|
+
if (!item) return;
|
|
1393
|
+
if (Array.isArray(item)) cssList.push(...item);
|
|
1394
|
+
else cssList.push(item);
|
|
1395
|
+
};
|
|
1396
|
+
addCss(userConfig.css);
|
|
1397
|
+
addCss(mergedMeta.css);
|
|
1398
|
+
const embedImages = typeof userConfig.embedImages === "boolean" ? userConfig.embedImages : DEFAULT_CONFIG.embedImages;
|
|
1399
|
+
const bundleHtml = typeof userConfig.bundleHtml === "boolean" ? userConfig.bundleHtml : DEFAULT_CONFIG.bundleHtml;
|
|
1400
|
+
const syntaxTheme = userConfig.syntaxTheme || DEFAULT_CONFIG.syntaxTheme || "github-dark";
|
|
1401
|
+
return {
|
|
1402
|
+
title,
|
|
1403
|
+
subtitle,
|
|
1404
|
+
author,
|
|
1405
|
+
date,
|
|
1406
|
+
version,
|
|
1407
|
+
company,
|
|
1408
|
+
lang,
|
|
1409
|
+
theme,
|
|
1410
|
+
orientation,
|
|
1411
|
+
paperSize,
|
|
1412
|
+
paperDimensions,
|
|
1413
|
+
margins,
|
|
1414
|
+
header,
|
|
1415
|
+
footer,
|
|
1416
|
+
toc,
|
|
1417
|
+
watermark,
|
|
1418
|
+
css: cssList,
|
|
1419
|
+
embedImages,
|
|
1420
|
+
bundleHtml,
|
|
1421
|
+
syntaxTheme
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
972
1424
|
|
|
973
1425
|
// src/core/html/htmlBuilder.ts
|
|
974
1426
|
function escapeHtml(str) {
|
|
@@ -1021,43 +1473,41 @@ async function renderInlinesToHtml(spans = [], baseDir = process.cwd()) {
|
|
|
1021
1473
|
return result;
|
|
1022
1474
|
}
|
|
1023
1475
|
async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
1024
|
-
|
|
1025
|
-
const
|
|
1026
|
-
const themeName = metadata.theme || config.theme || "default";
|
|
1027
|
-
const baseThemeCss = THEMES[themeName] || THEMES.default;
|
|
1476
|
+
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
1477
|
+
const baseThemeCss = generateThemeCss(resolved.theme);
|
|
1028
1478
|
let customCss = "";
|
|
1029
|
-
|
|
1030
|
-
const
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
if (fs2.existsSync(fullCssPath)) {
|
|
1034
|
-
customCss += `
|
|
1479
|
+
for (const cssPath of resolved.css) {
|
|
1480
|
+
const fullCssPath = path3.isAbsolute(cssPath) ? cssPath : path3.resolve(baseDir, cssPath);
|
|
1481
|
+
if (fs3.existsSync(fullCssPath)) {
|
|
1482
|
+
customCss += `
|
|
1035
1483
|
/* Custom CSS: ${cssPath} */
|
|
1036
|
-
` +
|
|
1037
|
-
}
|
|
1484
|
+
` + fs3.readFileSync(fullCssPath, "utf-8");
|
|
1038
1485
|
}
|
|
1039
1486
|
}
|
|
1040
1487
|
const inlinedCss = doc.inlinedStyles.join("\n");
|
|
1041
1488
|
let bodyHtml = "";
|
|
1042
|
-
if (
|
|
1489
|
+
if (resolved.title) {
|
|
1043
1490
|
bodyHtml += ` <header class="document-header">
|
|
1044
1491
|
`;
|
|
1045
|
-
bodyHtml += ` <h1 class="document-title">${escapeHtml(
|
|
1492
|
+
bodyHtml += ` <h1 class="document-title">${escapeHtml(resolved.title)}</h1>
|
|
1046
1493
|
`;
|
|
1047
|
-
if (
|
|
1048
|
-
bodyHtml += ` <div class="document-subtitle">${escapeHtml(
|
|
1494
|
+
if (resolved.subtitle) {
|
|
1495
|
+
bodyHtml += ` <div class="document-subtitle">${escapeHtml(resolved.subtitle)}</div>
|
|
1049
1496
|
`;
|
|
1050
1497
|
}
|
|
1051
|
-
if (
|
|
1498
|
+
if (resolved.author || resolved.date || resolved.version) {
|
|
1052
1499
|
bodyHtml += ` <div class="document-meta">
|
|
1053
1500
|
`;
|
|
1054
|
-
if (
|
|
1055
|
-
|
|
1056
|
-
|
|
1501
|
+
if (resolved.author) {
|
|
1502
|
+
bodyHtml += ` <span>Author: ${escapeHtml(resolved.author)}</span>
|
|
1503
|
+
`;
|
|
1504
|
+
}
|
|
1505
|
+
if (resolved.version) {
|
|
1506
|
+
bodyHtml += ` <span>Version: ${escapeHtml(resolved.version)}</span>
|
|
1057
1507
|
`;
|
|
1058
1508
|
}
|
|
1059
|
-
if (
|
|
1060
|
-
bodyHtml += ` <span>Date: ${escapeHtml(
|
|
1509
|
+
if (resolved.date) {
|
|
1510
|
+
bodyHtml += ` <span>Date: ${escapeHtml(resolved.date)}</span>
|
|
1061
1511
|
`;
|
|
1062
1512
|
}
|
|
1063
1513
|
bodyHtml += ` </div>
|
|
@@ -1066,22 +1516,20 @@ async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1066
1516
|
bodyHtml += ` </header>
|
|
1067
1517
|
`;
|
|
1068
1518
|
}
|
|
1069
|
-
if (
|
|
1070
|
-
|
|
1071
|
-
bodyHtml += ` <nav class="table-of-contents">
|
|
1519
|
+
if (resolved.toc && doc.tocEntries.length > 0) {
|
|
1520
|
+
bodyHtml += ` <nav class="table-of-contents">
|
|
1072
1521
|
`;
|
|
1073
|
-
|
|
1522
|
+
bodyHtml += ` <h2>Table of Contents</h2>
|
|
1074
1523
|
<ul>
|
|
1075
1524
|
`;
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1525
|
+
for (const entry of doc.tocEntries) {
|
|
1526
|
+
const indent = " ".repeat(entry.level);
|
|
1527
|
+
bodyHtml += ` ${indent}<li><a href="#${entry.id}">${escapeHtml(entry.text)}</a></li>
|
|
1079
1528
|
`;
|
|
1080
|
-
|
|
1081
|
-
|
|
1529
|
+
}
|
|
1530
|
+
bodyHtml += ` </ul>
|
|
1082
1531
|
</nav>
|
|
1083
1532
|
`;
|
|
1084
|
-
}
|
|
1085
1533
|
}
|
|
1086
1534
|
for (const node of doc.nodes) {
|
|
1087
1535
|
if (node.type === "heading") {
|
|
@@ -1099,7 +1547,7 @@ async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1099
1547
|
if (node.type === "codeBlock") {
|
|
1100
1548
|
const lang = node.language || "";
|
|
1101
1549
|
const langClass = lang ? ` class="language-${escapeHtml(lang)}"` : "";
|
|
1102
|
-
const highlighted = highlightCodeToHtml(node.text || "", lang);
|
|
1550
|
+
const highlighted = highlightCodeToHtml(node.text || "", lang, resolved.syntaxTheme);
|
|
1103
1551
|
bodyHtml += ` <pre><code${langClass}>${highlighted}</code></pre>
|
|
1104
1552
|
`;
|
|
1105
1553
|
continue;
|
|
@@ -1143,15 +1591,12 @@ ${escapeHtml(node.text || "")}
|
|
|
1143
1591
|
for (const row of node.children) {
|
|
1144
1592
|
bodyHtml += ` <tr>
|
|
1145
1593
|
`;
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
const cellInner = await renderInlinesToHtml(cell.inlines, baseDir);
|
|
1152
|
-
bodyHtml += ` <${tag}${align}>${cellInner}</${tag}>
|
|
1594
|
+
for (const cell of row.children || []) {
|
|
1595
|
+
const tag = cell.isHeader ? "th" : "td";
|
|
1596
|
+
const align = cell.align ? ` align="${cell.align}"` : "";
|
|
1597
|
+
const inner = await renderInlinesToHtml(cell.inlines, baseDir);
|
|
1598
|
+
bodyHtml += ` <${tag}${align}>${inner}</${tag}>
|
|
1153
1599
|
`;
|
|
1154
|
-
}
|
|
1155
1600
|
}
|
|
1156
1601
|
bodyHtml += ` </tr>
|
|
1157
1602
|
`;
|
|
@@ -1165,57 +1610,52 @@ ${escapeHtml(node.text || "")}
|
|
|
1165
1610
|
bodyHtml += ` <${tag}>
|
|
1166
1611
|
`;
|
|
1167
1612
|
for (const item of node.children) {
|
|
1168
|
-
const
|
|
1169
|
-
|
|
1170
|
-
if (item.checked !== void 0) {
|
|
1171
|
-
prefix = `<input type="checkbox" disabled ${item.checked ? "checked" : ""}/> `;
|
|
1172
|
-
}
|
|
1173
|
-
bodyHtml += ` <li>${prefix}${itemInner}</li>
|
|
1613
|
+
const inner = await renderInlinesToHtml(item.inlines, baseDir);
|
|
1614
|
+
bodyHtml += ` <li>${inner}</li>
|
|
1174
1615
|
`;
|
|
1175
1616
|
}
|
|
1176
1617
|
bodyHtml += ` </${tag}>
|
|
1177
1618
|
`;
|
|
1178
1619
|
continue;
|
|
1179
1620
|
}
|
|
1180
|
-
if (node.type === "
|
|
1181
|
-
bodyHtml += `
|
|
1621
|
+
if (node.type === "thematicBreak") {
|
|
1622
|
+
bodyHtml += ` <hr />
|
|
1182
1623
|
`;
|
|
1183
1624
|
continue;
|
|
1184
1625
|
}
|
|
1185
|
-
if (node.type === "
|
|
1186
|
-
bodyHtml += `
|
|
1626
|
+
if (node.type === "htmlBlock") {
|
|
1627
|
+
bodyHtml += ` ${node.text}
|
|
1187
1628
|
`;
|
|
1188
1629
|
continue;
|
|
1189
1630
|
}
|
|
1190
1631
|
}
|
|
1191
|
-
const wmConfig = config.watermark ?? metadata.watermark;
|
|
1192
|
-
let watermarkHtml = "";
|
|
1193
1632
|
let watermarkCss = "";
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
const
|
|
1197
|
-
const rotate = typeof wmConfig === "object" && wmConfig.rotate !== void 0 ? wmConfig.rotate : -45;
|
|
1198
|
-
const color = typeof wmConfig === "object" && wmConfig.color ? wmConfig.color : "#94A3B8";
|
|
1199
|
-
const fontSize = typeof wmConfig === "object" && wmConfig.fontSize ? `${wmConfig.fontSize}pt` : "52pt";
|
|
1633
|
+
let watermarkHtml = "";
|
|
1634
|
+
if (resolved.watermark) {
|
|
1635
|
+
const wm = resolved.watermark;
|
|
1200
1636
|
watermarkCss = `
|
|
1201
1637
|
.document-watermark {
|
|
1202
1638
|
position: fixed;
|
|
1203
1639
|
top: 50%;
|
|
1204
1640
|
left: 50%;
|
|
1205
|
-
transform: translate(-50%, -50%) rotate(${rotate}deg);
|
|
1206
|
-
font-size: ${fontSize};
|
|
1207
|
-
font-weight:
|
|
1208
|
-
color: ${color};
|
|
1209
|
-
opacity: ${opacity};
|
|
1641
|
+
transform: translate(-50%, -50%) rotate(${wm.rotate}deg);
|
|
1642
|
+
font-size: ${wm.fontSize}pt;
|
|
1643
|
+
font-weight: 900;
|
|
1644
|
+
color: ${wm.color};
|
|
1645
|
+
opacity: ${wm.opacity};
|
|
1210
1646
|
pointer-events: none;
|
|
1647
|
+
z-index: 0;
|
|
1211
1648
|
user-select: none;
|
|
1212
|
-
z-index: 9999;
|
|
1213
1649
|
text-transform: uppercase;
|
|
1214
1650
|
letter-spacing: 0.15em;
|
|
1215
1651
|
white-space: nowrap;
|
|
1216
1652
|
}
|
|
1653
|
+
.document-container {
|
|
1654
|
+
position: relative;
|
|
1655
|
+
z-index: 1;
|
|
1656
|
+
}
|
|
1217
1657
|
`;
|
|
1218
|
-
watermarkHtml = ` <div class="document-watermark">${escapeHtml(
|
|
1658
|
+
watermarkHtml = ` <div class="document-watermark">${escapeHtml(wm.text)}</div>
|
|
1219
1659
|
`;
|
|
1220
1660
|
}
|
|
1221
1661
|
const hasMermaid = doc.nodes.some((n) => n.type === "mermaid");
|
|
@@ -1234,13 +1674,12 @@ ${escapeHtml(node.text || "")}
|
|
|
1234
1674
|
}
|
|
1235
1675
|
});
|
|
1236
1676
|
</script>` : "";
|
|
1237
|
-
const documentTitle = metadata.title || "MarkForge Document";
|
|
1238
1677
|
return `<!DOCTYPE html>
|
|
1239
|
-
<html lang="${
|
|
1678
|
+
<html lang="${resolved.lang}">
|
|
1240
1679
|
<head>
|
|
1241
1680
|
<meta charset="UTF-8">
|
|
1242
1681
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1243
|
-
<title>${escapeHtml(
|
|
1682
|
+
<title>${escapeHtml(resolved.title)}</title>
|
|
1244
1683
|
<style>
|
|
1245
1684
|
${THEME_COMPONENTS}
|
|
1246
1685
|
${baseThemeCss}
|
|
@@ -1259,10 +1698,10 @@ ${bodyHtml} </div>
|
|
|
1259
1698
|
|
|
1260
1699
|
// src/core/pdf/pdfBuilder.ts
|
|
1261
1700
|
function findChromeExecutable() {
|
|
1262
|
-
if (process.env.CHROME_PATH &&
|
|
1701
|
+
if (process.env.CHROME_PATH && fs4.existsSync(process.env.CHROME_PATH)) {
|
|
1263
1702
|
return process.env.CHROME_PATH;
|
|
1264
1703
|
}
|
|
1265
|
-
if (process.env.PUPPETEER_EXECUTABLE_PATH &&
|
|
1704
|
+
if (process.env.PUPPETEER_EXECUTABLE_PATH && fs4.existsSync(process.env.PUPPETEER_EXECUTABLE_PATH)) {
|
|
1266
1705
|
return process.env.PUPPETEER_EXECUTABLE_PATH;
|
|
1267
1706
|
}
|
|
1268
1707
|
const isWin = process.platform === "win32";
|
|
@@ -1284,14 +1723,14 @@ function findChromeExecutable() {
|
|
|
1284
1723
|
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
1285
1724
|
"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
|
|
1286
1725
|
"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
|
|
1726
|
+
// Windows — Microsoft Edge (Native Windows 10/11 browser, enterprise whitelist friendly)
|
|
1727
|
+
`${winProgramFiles}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1728
|
+
`${winProgramFilesX86}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1729
|
+
`${winLocalAppData}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1287
1730
|
// Windows — Google Chrome
|
|
1288
1731
|
`${winProgramFiles}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1289
1732
|
`${winProgramFilesX86}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1290
1733
|
`${winLocalAppData}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1291
|
-
// Windows — Microsoft Edge (ships with Windows 10/11)
|
|
1292
|
-
`${winProgramFiles}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1293
|
-
`${winProgramFilesX86}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1294
|
-
`${winLocalAppData}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1295
1734
|
// Windows — Brave Browser
|
|
1296
1735
|
`${winProgramFiles}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
1297
1736
|
`${winProgramFilesX86}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
@@ -1301,7 +1740,7 @@ function findChromeExecutable() {
|
|
|
1301
1740
|
].filter(Boolean);
|
|
1302
1741
|
for (const candidate of candidates) {
|
|
1303
1742
|
try {
|
|
1304
|
-
if (
|
|
1743
|
+
if (fs4.existsSync(candidate)) {
|
|
1305
1744
|
return candidate;
|
|
1306
1745
|
}
|
|
1307
1746
|
} catch {
|
|
@@ -1314,7 +1753,7 @@ function findChromeExecutable() {
|
|
|
1314
1753
|
const res = spawnSync(cmd, [name], { encoding: "utf-8" });
|
|
1315
1754
|
if (res.status === 0 && res.stdout.trim()) {
|
|
1316
1755
|
const binPath = res.stdout.split(/\r?\n/)[0].trim();
|
|
1317
|
-
if (
|
|
1756
|
+
if (fs4.existsSync(binPath)) return binPath;
|
|
1318
1757
|
}
|
|
1319
1758
|
}
|
|
1320
1759
|
} catch {
|
|
@@ -1322,38 +1761,63 @@ function findChromeExecutable() {
|
|
|
1322
1761
|
return null;
|
|
1323
1762
|
}
|
|
1324
1763
|
function injectPagedMediaStyles(html, config, metadata) {
|
|
1325
|
-
var _a, _b, _c, _d;
|
|
1326
|
-
const
|
|
1327
|
-
const
|
|
1328
|
-
const
|
|
1329
|
-
const
|
|
1330
|
-
const
|
|
1331
|
-
const
|
|
1332
|
-
const
|
|
1333
|
-
const
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1764
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1765
|
+
const resolved = resolveDocumentConfig(metadata || {}, config);
|
|
1766
|
+
const size = resolved.paperSize;
|
|
1767
|
+
const orientation = resolved.orientation;
|
|
1768
|
+
const top = resolved.margins.top;
|
|
1769
|
+
const bottom = resolved.margins.bottom;
|
|
1770
|
+
const left = resolved.margins.left;
|
|
1771
|
+
const right = resolved.margins.right;
|
|
1772
|
+
const esc = (s) => s.replace(/"/g, '\\"').replace(/\\/g, "\\\\");
|
|
1773
|
+
const buildZoneCss = (pos, zone, isPageCounter = false) => {
|
|
1774
|
+
if (!zone && !isPageCounter) return "";
|
|
1775
|
+
const color = (zone == null ? void 0 : zone.color) || "#94a3b8";
|
|
1776
|
+
const fontSize = (zone == null ? void 0 : zone.fontSize) ? `${zone.fontSize}pt` : "9pt";
|
|
1777
|
+
const fontFamily = (zone == null ? void 0 : zone.fontFamily) ? `font-family: ${zone.fontFamily};` : "";
|
|
1778
|
+
const fontWeight = (zone == null ? void 0 : zone.bold) ? "font-weight: bold;" : "";
|
|
1779
|
+
const fontStyle = (zone == null ? void 0 : zone.italic) ? "font-style: italic;" : "";
|
|
1780
|
+
let content = "";
|
|
1781
|
+
if (isPageCounter) {
|
|
1782
|
+
if ((zone == null ? void 0 : zone.text) && (zone.text.includes("{page}") || zone.text.includes("{pages}"))) {
|
|
1783
|
+
const parts = zone.text.split(/(\{page\}|\{pages\})/gi);
|
|
1784
|
+
const cssParts = parts.map((part) => {
|
|
1785
|
+
if (part.toLowerCase() === "{page}") return "counter(page)";
|
|
1786
|
+
if (part.toLowerCase() === "{pages}") return "counter(pages)";
|
|
1787
|
+
return `"${esc(part)}"`;
|
|
1788
|
+
});
|
|
1789
|
+
content = cssParts.join(" ");
|
|
1790
|
+
} else if (zone == null ? void 0 : zone.text) {
|
|
1791
|
+
content = `"${esc(zone.text)}"`;
|
|
1792
|
+
} else {
|
|
1793
|
+
content = `"Page " counter(page) " of " counter(pages)`;
|
|
1794
|
+
}
|
|
1795
|
+
} else if (zone == null ? void 0 : zone.text) {
|
|
1796
|
+
content = `"${esc(zone.text)}"`;
|
|
1797
|
+
}
|
|
1798
|
+
if (!content) return "";
|
|
1799
|
+
return `@${pos} {
|
|
1800
|
+
content: ${content};
|
|
1801
|
+
font-size: ${fontSize};
|
|
1802
|
+
color: ${color};
|
|
1803
|
+
${fontFamily}
|
|
1804
|
+
${fontWeight}
|
|
1805
|
+
${fontStyle}
|
|
1806
|
+
}`;
|
|
1807
|
+
};
|
|
1808
|
+
const pagedCss = `
|
|
1809
|
+
@page {
|
|
1810
|
+
size: ${size} ${orientation};
|
|
1344
1811
|
margin-top: ${top};
|
|
1345
1812
|
margin-bottom: ${bottom};
|
|
1346
1813
|
margin-left: ${left};
|
|
1347
1814
|
margin-right: ${right};
|
|
1348
|
-
${
|
|
1349
|
-
${
|
|
1350
|
-
${
|
|
1351
|
-
${
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
font-size: 9pt;
|
|
1355
|
-
color: #94a3b8;
|
|
1356
|
-
}
|
|
1815
|
+
${buildZoneCss("top-left", (_a = resolved.header) == null ? void 0 : _a.left)}
|
|
1816
|
+
${buildZoneCss("top-center", (_b = resolved.header) == null ? void 0 : _b.center)}
|
|
1817
|
+
${buildZoneCss("top-right", (_c = resolved.header) == null ? void 0 : _c.right)}
|
|
1818
|
+
${buildZoneCss("bottom-left", (_d = resolved.footer) == null ? void 0 : _d.left)}
|
|
1819
|
+
${buildZoneCss("bottom-center", (_e = resolved.footer) == null ? void 0 : _e.center)}
|
|
1820
|
+
${buildZoneCss("bottom-right", (_f = resolved.footer) == null ? void 0 : _f.right, true)}
|
|
1357
1821
|
}
|
|
1358
1822
|
@media print {
|
|
1359
1823
|
body { padding: 0; }
|
|
@@ -1410,56 +1874,72 @@ async function buildPdfDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1410
1874
|
if (chromePath) {
|
|
1411
1875
|
const tmpId = Math.random().toString(36).substring(2, 9);
|
|
1412
1876
|
const tmpDir = os.tmpdir();
|
|
1413
|
-
const tmpHtml =
|
|
1414
|
-
const tmpPdf =
|
|
1877
|
+
const tmpHtml = path4.join(tmpDir, `markforge_${tmpId}.html`);
|
|
1878
|
+
const tmpPdf = path4.join(tmpDir, `markforge_${tmpId}.pdf`);
|
|
1879
|
+
const tmpProfile = path4.join(tmpDir, `markforge_prof_${tmpId}`);
|
|
1880
|
+
const isolatedFlags = [
|
|
1881
|
+
`--user-data-dir=${tmpProfile}`,
|
|
1882
|
+
"--no-first-run",
|
|
1883
|
+
"--no-default-browser-check",
|
|
1884
|
+
"--disable-sync",
|
|
1885
|
+
"--disable-background-networking",
|
|
1886
|
+
"--disable-component-update",
|
|
1887
|
+
"--disable-default-apps",
|
|
1888
|
+
"--disable-extensions",
|
|
1889
|
+
"--disable-domain-reliability",
|
|
1890
|
+
"--disable-client-side-phishing-detection",
|
|
1891
|
+
"--disable-breakpad",
|
|
1892
|
+
"--disable-component-extensions-with-background-pages",
|
|
1893
|
+
"--disable-features=Translate,OptimizationHints,MediaRouter,DialMediaRouteProvider,CalculatedNewTabPage,ChromeWhatsNewUI,PrivacySandboxSettings4",
|
|
1894
|
+
"--password-store=basic",
|
|
1895
|
+
"--use-mock-keychain",
|
|
1896
|
+
"--mute-audio",
|
|
1897
|
+
"--no-service-autorun",
|
|
1898
|
+
"--disable-gpu",
|
|
1899
|
+
"--no-sandbox",
|
|
1900
|
+
"--disable-setuid-sandbox",
|
|
1901
|
+
"--allow-file-access-from-files",
|
|
1902
|
+
"--disable-web-security",
|
|
1903
|
+
"--force-color-profile=srgb",
|
|
1904
|
+
"--no-pdf-header-footer"
|
|
1905
|
+
];
|
|
1415
1906
|
try {
|
|
1416
|
-
|
|
1417
|
-
const fileUrl =
|
|
1907
|
+
fs4.writeFileSync(tmpHtml, pagedHtml, "utf-8");
|
|
1908
|
+
const fileUrl = pathToFileURL2(tmpHtml).href;
|
|
1418
1909
|
let res = spawnSync(
|
|
1419
1910
|
chromePath,
|
|
1420
1911
|
[
|
|
1421
1912
|
"--headless=new",
|
|
1422
|
-
|
|
1423
|
-
"--no-sandbox",
|
|
1424
|
-
"--disable-setuid-sandbox",
|
|
1425
|
-
"--allow-file-access-from-files",
|
|
1426
|
-
"--disable-web-security",
|
|
1427
|
-
"--force-color-profile=srgb",
|
|
1913
|
+
...isolatedFlags,
|
|
1428
1914
|
"--run-all-compositor-stages-before-draw",
|
|
1429
1915
|
"--virtual-time-budget=8000",
|
|
1430
|
-
"--no-pdf-header-footer",
|
|
1431
1916
|
`--print-to-pdf=${tmpPdf}`,
|
|
1432
1917
|
fileUrl
|
|
1433
1918
|
],
|
|
1434
1919
|
{ timeout: 3e4 }
|
|
1435
1920
|
);
|
|
1436
|
-
if ((res.status !== 0 || !
|
|
1921
|
+
if ((res.status !== 0 || !fs4.existsSync(tmpPdf)) && chromePath) {
|
|
1437
1922
|
res = spawnSync(
|
|
1438
1923
|
chromePath,
|
|
1439
1924
|
[
|
|
1440
1925
|
"--headless",
|
|
1441
|
-
|
|
1442
|
-
"--no-sandbox",
|
|
1443
|
-
"--disable-setuid-sandbox",
|
|
1444
|
-
"--allow-file-access-from-files",
|
|
1445
|
-
"--disable-web-security",
|
|
1446
|
-
"--force-color-profile=srgb",
|
|
1447
|
-
"--no-pdf-header-footer",
|
|
1926
|
+
...isolatedFlags,
|
|
1448
1927
|
`--print-to-pdf=${tmpPdf}`,
|
|
1449
1928
|
fileUrl
|
|
1450
1929
|
],
|
|
1451
1930
|
{ timeout: 3e4 }
|
|
1452
1931
|
);
|
|
1453
1932
|
}
|
|
1454
|
-
if (
|
|
1455
|
-
const pdfBuffer =
|
|
1933
|
+
if (fs4.existsSync(tmpPdf) && fs4.statSync(tmpPdf).size > 0) {
|
|
1934
|
+
const pdfBuffer = fs4.readFileSync(tmpPdf);
|
|
1456
1935
|
return pdfBuffer;
|
|
1457
1936
|
}
|
|
1458
1937
|
} catch {
|
|
1459
1938
|
} finally {
|
|
1460
1939
|
try {
|
|
1461
|
-
if (
|
|
1462
|
-
if (
|
|
1940
|
+
if (fs4.existsSync(tmpHtml)) fs4.unlinkSync(tmpHtml);
|
|
1941
|
+
if (fs4.existsSync(tmpPdf)) fs4.unlinkSync(tmpPdf);
|
|
1942
|
+
if (fs4.existsSync(tmpProfile)) fs4.rmSync(tmpProfile, { recursive: true, force: true });
|
|
1463
1943
|
} catch {
|
|
1464
1944
|
}
|
|
1465
1945
|
}
|
|
@@ -1475,8 +1955,8 @@ async function renderMermaidToPng(mermaidCode, _baseDir = process.cwd()) {
|
|
|
1475
1955
|
}
|
|
1476
1956
|
const tmpId = Math.random().toString(36).substring(2, 9);
|
|
1477
1957
|
const tmpDir = os2.tmpdir();
|
|
1478
|
-
const tmpHtml =
|
|
1479
|
-
const tmpScreenshot =
|
|
1958
|
+
const tmpHtml = path5.join(tmpDir, `mermaid_${tmpId}.html`);
|
|
1959
|
+
const tmpScreenshot = path5.join(tmpDir, `mermaid_${tmpId}.png`);
|
|
1480
1960
|
const htmlContent = `<!DOCTYPE html>
|
|
1481
1961
|
<html>
|
|
1482
1962
|
<head>
|
|
@@ -1515,8 +1995,8 @@ ${mermaidCode}
|
|
|
1515
1995
|
</body>
|
|
1516
1996
|
</html>`;
|
|
1517
1997
|
try {
|
|
1518
|
-
|
|
1519
|
-
const fileUrl =
|
|
1998
|
+
fs5.writeFileSync(tmpHtml, htmlContent, "utf-8");
|
|
1999
|
+
const fileUrl = pathToFileURL3(tmpHtml).href;
|
|
1520
2000
|
const res = spawnSync2(
|
|
1521
2001
|
chromePath,
|
|
1522
2002
|
[
|
|
@@ -1534,15 +2014,15 @@ ${mermaidCode}
|
|
|
1534
2014
|
],
|
|
1535
2015
|
{ timeout: 15e3 }
|
|
1536
2016
|
);
|
|
1537
|
-
if (res.status === 0 &&
|
|
1538
|
-
const buffer =
|
|
2017
|
+
if (res.status === 0 && fs5.existsSync(tmpScreenshot)) {
|
|
2018
|
+
const buffer = fs5.readFileSync(tmpScreenshot);
|
|
1539
2019
|
return buffer;
|
|
1540
2020
|
}
|
|
1541
2021
|
} catch {
|
|
1542
2022
|
} finally {
|
|
1543
2023
|
try {
|
|
1544
|
-
if (
|
|
1545
|
-
if (
|
|
2024
|
+
if (fs5.existsSync(tmpHtml)) fs5.unlinkSync(tmpHtml);
|
|
2025
|
+
if (fs5.existsSync(tmpScreenshot)) fs5.unlinkSync(tmpScreenshot);
|
|
1546
2026
|
} catch {
|
|
1547
2027
|
}
|
|
1548
2028
|
}
|
|
@@ -1550,7 +2030,7 @@ ${mermaidCode}
|
|
|
1550
2030
|
}
|
|
1551
2031
|
|
|
1552
2032
|
// src/core/docx/docxBuilder.ts
|
|
1553
|
-
function
|
|
2033
|
+
function parseMarginToTwip2(margin, defaultTwip = 1440) {
|
|
1554
2034
|
if (typeof margin === "number") return margin;
|
|
1555
2035
|
if (!margin) return defaultTwip;
|
|
1556
2036
|
const str = margin.trim().toLowerCase();
|
|
@@ -1573,7 +2053,7 @@ function parseMarginToTwip(margin, defaultTwip = 1440) {
|
|
|
1573
2053
|
const val = parseFloat(str);
|
|
1574
2054
|
return isNaN(val) ? defaultTwip : Math.round(val);
|
|
1575
2055
|
}
|
|
1576
|
-
async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
2056
|
+
async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd(), options = {}) {
|
|
1577
2057
|
const runs = [];
|
|
1578
2058
|
for (const span of spans) {
|
|
1579
2059
|
if (span.type === "image" && span.url) {
|
|
@@ -1603,7 +2083,10 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1603
2083
|
new TextRun({
|
|
1604
2084
|
text: span.content,
|
|
1605
2085
|
style: "Hyperlink",
|
|
1606
|
-
color: "
|
|
2086
|
+
color: "009DA0",
|
|
2087
|
+
font: options.font,
|
|
2088
|
+
size: options.size,
|
|
2089
|
+
bold: options.bold,
|
|
1607
2090
|
underline: {}
|
|
1608
2091
|
})
|
|
1609
2092
|
],
|
|
@@ -1616,7 +2099,11 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1616
2099
|
runs.push(
|
|
1617
2100
|
new TextRun({
|
|
1618
2101
|
text: span.content,
|
|
1619
|
-
bold: true
|
|
2102
|
+
bold: true,
|
|
2103
|
+
font: options.font,
|
|
2104
|
+
size: options.size,
|
|
2105
|
+
color: options.color,
|
|
2106
|
+
italics: options.italics
|
|
1620
2107
|
})
|
|
1621
2108
|
);
|
|
1622
2109
|
continue;
|
|
@@ -1625,7 +2112,11 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1625
2112
|
runs.push(
|
|
1626
2113
|
new TextRun({
|
|
1627
2114
|
text: span.content,
|
|
1628
|
-
italics: true
|
|
2115
|
+
italics: true,
|
|
2116
|
+
font: options.font,
|
|
2117
|
+
size: options.size,
|
|
2118
|
+
color: options.color,
|
|
2119
|
+
bold: options.bold
|
|
1629
2120
|
})
|
|
1630
2121
|
);
|
|
1631
2122
|
continue;
|
|
@@ -1634,7 +2125,10 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1634
2125
|
runs.push(
|
|
1635
2126
|
new TextRun({
|
|
1636
2127
|
text: span.content,
|
|
1637
|
-
strike: true
|
|
2128
|
+
strike: true,
|
|
2129
|
+
font: options.font,
|
|
2130
|
+
size: options.size,
|
|
2131
|
+
color: options.color
|
|
1638
2132
|
})
|
|
1639
2133
|
);
|
|
1640
2134
|
continue;
|
|
@@ -1642,22 +2136,23 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1642
2136
|
if (span.type === "code") {
|
|
1643
2137
|
runs.push(
|
|
1644
2138
|
new TextRun({
|
|
1645
|
-
text:
|
|
2139
|
+
text: span.content,
|
|
1646
2140
|
font: "Consolas",
|
|
2141
|
+
size: options.size ? options.size - 2 : 19,
|
|
2142
|
+
color: "0F172A",
|
|
1647
2143
|
shading: {
|
|
1648
2144
|
type: ShadingType.CLEAR,
|
|
1649
|
-
fill: "F1F5F9"
|
|
1650
|
-
color: "0F172A"
|
|
2145
|
+
fill: "F1F5F9"
|
|
1651
2146
|
}
|
|
1652
2147
|
})
|
|
1653
2148
|
);
|
|
1654
2149
|
continue;
|
|
1655
2150
|
}
|
|
1656
2151
|
if (span.type === "htmlInline") {
|
|
1657
|
-
let colorHex;
|
|
2152
|
+
let colorHex = options.color;
|
|
1658
2153
|
let bgHex;
|
|
1659
|
-
let isBold =
|
|
1660
|
-
let isItalic =
|
|
2154
|
+
let isBold = !!options.bold;
|
|
2155
|
+
let isItalic = !!options.italics;
|
|
1661
2156
|
if (span.style) {
|
|
1662
2157
|
if (span.style.color) {
|
|
1663
2158
|
colorHex = span.style.color.replace("#", "").trim();
|
|
@@ -1673,13 +2168,9 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1673
2168
|
}
|
|
1674
2169
|
}
|
|
1675
2170
|
if (span.children && span.children.length > 0) {
|
|
1676
|
-
const childRuns = await convertInlinesToTextRuns(span.children, baseDir);
|
|
2171
|
+
const childRuns = await convertInlinesToTextRuns(span.children, baseDir, options);
|
|
1677
2172
|
for (const child of childRuns) {
|
|
1678
|
-
|
|
1679
|
-
runs.push(child);
|
|
1680
|
-
} else {
|
|
1681
|
-
runs.push(child);
|
|
1682
|
-
}
|
|
2173
|
+
runs.push(child);
|
|
1683
2174
|
}
|
|
1684
2175
|
continue;
|
|
1685
2176
|
}
|
|
@@ -1689,6 +2180,8 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1689
2180
|
color: colorHex,
|
|
1690
2181
|
bold: isBold,
|
|
1691
2182
|
italics: isItalic,
|
|
2183
|
+
font: options.font,
|
|
2184
|
+
size: options.size,
|
|
1692
2185
|
shading: bgHex ? { type: ShadingType.CLEAR, fill: bgHex } : void 0
|
|
1693
2186
|
})
|
|
1694
2187
|
);
|
|
@@ -1696,91 +2189,239 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1696
2189
|
}
|
|
1697
2190
|
runs.push(
|
|
1698
2191
|
new TextRun({
|
|
1699
|
-
text: span.content
|
|
2192
|
+
text: span.content,
|
|
2193
|
+
font: options.font,
|
|
2194
|
+
size: options.size,
|
|
2195
|
+
color: options.color,
|
|
2196
|
+
bold: options.bold,
|
|
2197
|
+
italics: options.italics
|
|
1700
2198
|
})
|
|
1701
2199
|
);
|
|
1702
2200
|
}
|
|
1703
2201
|
return runs;
|
|
1704
2202
|
}
|
|
1705
2203
|
async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
1706
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
1707
|
-
const
|
|
2204
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
2205
|
+
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
1708
2206
|
const docElements = [];
|
|
1709
|
-
|
|
2207
|
+
const themeProps = typeof resolved.theme === "object" ? resolved.theme : {};
|
|
2208
|
+
const primaryHex = (themeProps.primaryColor || "#33CDCF").replace("#", "");
|
|
2209
|
+
const primaryDarkHex = (themeProps.primaryDark || "#009DA0").replace("#", "");
|
|
2210
|
+
const textHex = (themeProps.textColor || "#0F172A").replace("#", "");
|
|
2211
|
+
const textMutedHex = (themeProps.textMuted || "#64748B").replace("#", "");
|
|
2212
|
+
const borderHex = (themeProps.borderColor || "#E2E8F0").replace("#", "");
|
|
2213
|
+
const cardBgHex = (themeProps.cardBackground || "#F8FAFC").replace("#", "");
|
|
2214
|
+
const defaultFont = themeProps.fontFamily ? themeProps.fontFamily.split(",")[0].replace(/['"]/g, "").trim() : "Segoe UI";
|
|
2215
|
+
if (resolved.title) {
|
|
1710
2216
|
docElements.push(
|
|
1711
2217
|
new Paragraph({
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
2218
|
+
children: [
|
|
2219
|
+
new TextRun({
|
|
2220
|
+
text: resolved.title,
|
|
2221
|
+
bold: true,
|
|
2222
|
+
size: 44,
|
|
2223
|
+
// 22pt
|
|
2224
|
+
color: textHex,
|
|
2225
|
+
font: defaultFont
|
|
2226
|
+
})
|
|
2227
|
+
],
|
|
2228
|
+
spacing: { before: 120, after: 80 }
|
|
1715
2229
|
})
|
|
1716
2230
|
);
|
|
1717
|
-
if (
|
|
2231
|
+
if (resolved.subtitle) {
|
|
1718
2232
|
docElements.push(
|
|
1719
2233
|
new Paragraph({
|
|
1720
2234
|
children: [
|
|
1721
2235
|
new TextRun({
|
|
1722
|
-
text:
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
size: 24
|
|
2236
|
+
text: resolved.subtitle,
|
|
2237
|
+
color: textMutedHex,
|
|
2238
|
+
size: 24,
|
|
1726
2239
|
// 12pt
|
|
2240
|
+
font: defaultFont
|
|
1727
2241
|
})
|
|
1728
2242
|
],
|
|
1729
|
-
spacing: { after:
|
|
2243
|
+
spacing: { before: 60, after: 120 }
|
|
1730
2244
|
})
|
|
1731
2245
|
);
|
|
1732
2246
|
}
|
|
1733
|
-
if (
|
|
2247
|
+
if (resolved.author || resolved.date || resolved.version || resolved.company) {
|
|
1734
2248
|
const metaParts = [];
|
|
1735
|
-
if (
|
|
1736
|
-
if (
|
|
2249
|
+
if (resolved.author) metaParts.push(`Author: ${resolved.author}`);
|
|
2250
|
+
if (resolved.version) metaParts.push(`Version: ${resolved.version}`);
|
|
2251
|
+
if (resolved.date) metaParts.push(`Date: ${resolved.date}`);
|
|
1737
2252
|
docElements.push(
|
|
1738
2253
|
new Paragraph({
|
|
1739
2254
|
children: [
|
|
1740
2255
|
new TextRun({
|
|
1741
|
-
text: metaParts.join("
|
|
1742
|
-
color:
|
|
1743
|
-
size:
|
|
1744
|
-
//
|
|
2256
|
+
text: metaParts.join(" "),
|
|
2257
|
+
color: textMutedHex,
|
|
2258
|
+
size: 18,
|
|
2259
|
+
// 9pt
|
|
2260
|
+
font: defaultFont
|
|
1745
2261
|
})
|
|
1746
2262
|
],
|
|
1747
|
-
spacing: { after:
|
|
2263
|
+
spacing: { before: 40, after: 240 },
|
|
1748
2264
|
border: {
|
|
1749
2265
|
bottom: {
|
|
1750
|
-
color:
|
|
1751
|
-
space:
|
|
2266
|
+
color: borderHex,
|
|
2267
|
+
space: 12,
|
|
1752
2268
|
style: BorderStyle.SINGLE,
|
|
1753
|
-
size:
|
|
2269
|
+
size: 4
|
|
1754
2270
|
}
|
|
1755
2271
|
}
|
|
1756
2272
|
})
|
|
1757
2273
|
);
|
|
1758
2274
|
}
|
|
1759
2275
|
}
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
if (node.level === 5) headingLevel = HeadingLevel.HEADING_5;
|
|
1767
|
-
if (node.level === 6) headingLevel = HeadingLevel.HEADING_6;
|
|
1768
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir);
|
|
1769
|
-
docElements.push(
|
|
2276
|
+
if (resolved.toc) {
|
|
2277
|
+
const headingNodes = doc.nodes.filter(
|
|
2278
|
+
(n) => n.type === "heading" && typeof n.level === "number" && n.level >= 1 && n.level <= 3
|
|
2279
|
+
);
|
|
2280
|
+
if (headingNodes.length > 0) {
|
|
2281
|
+
const tocParagraphs = [
|
|
1770
2282
|
new Paragraph({
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
2283
|
+
children: [
|
|
2284
|
+
new TextRun({
|
|
2285
|
+
text: "TABLE OF CONTENTS",
|
|
2286
|
+
bold: true,
|
|
2287
|
+
size: 18,
|
|
2288
|
+
// 9pt
|
|
2289
|
+
color: textMutedHex,
|
|
2290
|
+
font: defaultFont
|
|
2291
|
+
})
|
|
2292
|
+
],
|
|
2293
|
+
spacing: { after: 120 },
|
|
2294
|
+
border: {
|
|
2295
|
+
bottom: {
|
|
2296
|
+
color: borderHex,
|
|
2297
|
+
space: 6,
|
|
2298
|
+
style: BorderStyle.SINGLE,
|
|
2299
|
+
size: 4
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
1774
2302
|
})
|
|
1775
|
-
|
|
2303
|
+
];
|
|
2304
|
+
for (const h of headingNodes) {
|
|
2305
|
+
const indentLeft = (h.level - 1) * 240;
|
|
2306
|
+
tocParagraphs.push(
|
|
2307
|
+
new Paragraph({
|
|
2308
|
+
indent: { left: indentLeft },
|
|
2309
|
+
children: [
|
|
2310
|
+
new TextRun({
|
|
2311
|
+
text: h.text,
|
|
2312
|
+
bold: h.level === 1,
|
|
2313
|
+
color: primaryDarkHex,
|
|
2314
|
+
size: h.level === 1 ? 21 : 20,
|
|
2315
|
+
font: defaultFont
|
|
2316
|
+
})
|
|
2317
|
+
],
|
|
2318
|
+
spacing: { before: 20, after: 20 }
|
|
2319
|
+
})
|
|
2320
|
+
);
|
|
2321
|
+
}
|
|
2322
|
+
const tocCard = new Table({
|
|
2323
|
+
width: { size: 100, type: WidthType.PERCENTAGE },
|
|
2324
|
+
columnWidths: [9e3],
|
|
2325
|
+
rows: [
|
|
2326
|
+
new TableRow({
|
|
2327
|
+
children: [
|
|
2328
|
+
new TableCell({
|
|
2329
|
+
width: { size: 9e3, type: WidthType.DXA },
|
|
2330
|
+
shading: { fill: cardBgHex, type: ShadingType.CLEAR },
|
|
2331
|
+
margins: { top: 140, bottom: 140, left: 180, right: 180 },
|
|
2332
|
+
borders: {
|
|
2333
|
+
top: { style: BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2334
|
+
bottom: { style: BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2335
|
+
left: { style: BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2336
|
+
right: { style: BorderStyle.SINGLE, size: 4, color: borderHex }
|
|
2337
|
+
},
|
|
2338
|
+
children: tocParagraphs
|
|
2339
|
+
})
|
|
2340
|
+
]
|
|
2341
|
+
})
|
|
2342
|
+
]
|
|
2343
|
+
});
|
|
2344
|
+
docElements.push(tocCard);
|
|
2345
|
+
docElements.push(new Paragraph({ spacing: { after: 200 } }));
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
for (const node of doc.nodes) {
|
|
2349
|
+
if (node.type === "heading") {
|
|
2350
|
+
if (node.level === 1) {
|
|
2351
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2352
|
+
font: defaultFont,
|
|
2353
|
+
size: 34,
|
|
2354
|
+
// 17pt
|
|
2355
|
+
color: textHex,
|
|
2356
|
+
bold: true
|
|
2357
|
+
});
|
|
2358
|
+
docElements.push(
|
|
2359
|
+
new Paragraph({
|
|
2360
|
+
heading: HeadingLevel.HEADING_1,
|
|
2361
|
+
children: runs,
|
|
2362
|
+
spacing: { before: 360, after: 140 },
|
|
2363
|
+
border: {
|
|
2364
|
+
bottom: {
|
|
2365
|
+
color: primaryHex,
|
|
2366
|
+
space: 6,
|
|
2367
|
+
style: BorderStyle.SINGLE,
|
|
2368
|
+
size: 16
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
})
|
|
2372
|
+
);
|
|
2373
|
+
} else if (node.level === 2) {
|
|
2374
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2375
|
+
font: defaultFont,
|
|
2376
|
+
size: 26,
|
|
2377
|
+
// 13pt
|
|
2378
|
+
color: primaryDarkHex,
|
|
2379
|
+
bold: true
|
|
2380
|
+
});
|
|
2381
|
+
docElements.push(
|
|
2382
|
+
new Paragraph({
|
|
2383
|
+
heading: HeadingLevel.HEADING_2,
|
|
2384
|
+
children: runs,
|
|
2385
|
+
spacing: { before: 280, after: 100 },
|
|
2386
|
+
border: {
|
|
2387
|
+
bottom: {
|
|
2388
|
+
color: borderHex,
|
|
2389
|
+
space: 4,
|
|
2390
|
+
style: BorderStyle.SINGLE,
|
|
2391
|
+
size: 4
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
})
|
|
2395
|
+
);
|
|
2396
|
+
} else {
|
|
2397
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2398
|
+
font: defaultFont,
|
|
2399
|
+
size: 22,
|
|
2400
|
+
// 11pt
|
|
2401
|
+
color: textHex,
|
|
2402
|
+
bold: true
|
|
2403
|
+
});
|
|
2404
|
+
docElements.push(
|
|
2405
|
+
new Paragraph({
|
|
2406
|
+
heading: node.level === 3 ? HeadingLevel.HEADING_3 : HeadingLevel.HEADING_4,
|
|
2407
|
+
children: runs,
|
|
2408
|
+
spacing: { before: 200, after: 80 }
|
|
2409
|
+
})
|
|
2410
|
+
);
|
|
2411
|
+
}
|
|
1776
2412
|
continue;
|
|
1777
2413
|
}
|
|
1778
2414
|
if (node.type === "paragraph") {
|
|
1779
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
2415
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2416
|
+
font: defaultFont,
|
|
2417
|
+
size: 22,
|
|
2418
|
+
// 11pt
|
|
2419
|
+
color: "334155"
|
|
2420
|
+
});
|
|
1780
2421
|
docElements.push(
|
|
1781
2422
|
new Paragraph({
|
|
1782
2423
|
children: runs,
|
|
1783
|
-
spacing: { before:
|
|
2424
|
+
spacing: { before: 40, after: 140, line: 280 }
|
|
1784
2425
|
})
|
|
1785
2426
|
);
|
|
1786
2427
|
continue;
|
|
@@ -1852,7 +2493,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1852
2493
|
bgFill = "F5F3FF";
|
|
1853
2494
|
title = "IMPORTANT";
|
|
1854
2495
|
}
|
|
1855
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
2496
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2497
|
+
font: defaultFont,
|
|
2498
|
+
size: 21,
|
|
2499
|
+
color: "334155"
|
|
2500
|
+
});
|
|
1856
2501
|
const calloutTable = new Table({
|
|
1857
2502
|
width: { size: 100, type: WidthType.PERCENTAGE },
|
|
1858
2503
|
columnWidths: [9e3],
|
|
@@ -1867,7 +2512,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1867
2512
|
top: { style: BorderStyle.NONE },
|
|
1868
2513
|
bottom: { style: BorderStyle.NONE },
|
|
1869
2514
|
right: { style: BorderStyle.NONE },
|
|
1870
|
-
left: { style: BorderStyle.SINGLE, size:
|
|
2515
|
+
left: { style: BorderStyle.SINGLE, size: 20, color: borderColor }
|
|
1871
2516
|
},
|
|
1872
2517
|
children: [
|
|
1873
2518
|
new Paragraph({
|
|
@@ -1876,13 +2521,15 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1876
2521
|
text: `[${title}]`,
|
|
1877
2522
|
bold: true,
|
|
1878
2523
|
color: borderColor,
|
|
2524
|
+
font: defaultFont,
|
|
1879
2525
|
size: 20
|
|
1880
2526
|
})
|
|
1881
2527
|
],
|
|
1882
|
-
spacing: { after:
|
|
2528
|
+
spacing: { after: 40 }
|
|
1883
2529
|
}),
|
|
1884
2530
|
new Paragraph({
|
|
1885
|
-
children: runs
|
|
2531
|
+
children: runs,
|
|
2532
|
+
spacing: { line: 270 }
|
|
1886
2533
|
})
|
|
1887
2534
|
]
|
|
1888
2535
|
})
|
|
@@ -1900,17 +2547,27 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1900
2547
|
if (lines.length > 0) {
|
|
1901
2548
|
for (const lineText of lines) {
|
|
1902
2549
|
const spans = parseInlineSpans(lineText.replace(/^>\s?/, "").trim());
|
|
1903
|
-
const lineRuns = await convertInlinesToTextRuns(spans, baseDir
|
|
2550
|
+
const lineRuns = await convertInlinesToTextRuns(spans, baseDir, {
|
|
2551
|
+
font: defaultFont,
|
|
2552
|
+
size: 21,
|
|
2553
|
+
color: "475569",
|
|
2554
|
+
italics: true
|
|
2555
|
+
});
|
|
1904
2556
|
quoteParagraphs.push(
|
|
1905
2557
|
new Paragraph({
|
|
1906
2558
|
children: lineRuns,
|
|
1907
|
-
spacing: { before:
|
|
2559
|
+
spacing: { before: 20, after: 20, line: 260 }
|
|
1908
2560
|
})
|
|
1909
2561
|
);
|
|
1910
2562
|
}
|
|
1911
2563
|
} else {
|
|
1912
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
1913
|
-
|
|
2564
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2565
|
+
font: defaultFont,
|
|
2566
|
+
size: 21,
|
|
2567
|
+
color: "475569",
|
|
2568
|
+
italics: true
|
|
2569
|
+
});
|
|
2570
|
+
quoteParagraphs.push(new Paragraph({ children: runs, spacing: { line: 260 } }));
|
|
1914
2571
|
}
|
|
1915
2572
|
const quoteTable = new Table({
|
|
1916
2573
|
width: { size: 100, type: WidthType.PERCENTAGE },
|
|
@@ -1926,7 +2583,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1926
2583
|
top: { style: BorderStyle.NONE },
|
|
1927
2584
|
bottom: { style: BorderStyle.NONE },
|
|
1928
2585
|
right: { style: BorderStyle.NONE },
|
|
1929
|
-
left: { style: BorderStyle.SINGLE, size:
|
|
2586
|
+
left: { style: BorderStyle.SINGLE, size: 16, color: primaryHex }
|
|
1930
2587
|
},
|
|
1931
2588
|
children: quoteParagraphs
|
|
1932
2589
|
})
|
|
@@ -1961,7 +2618,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1961
2618
|
docElements.push(
|
|
1962
2619
|
new Paragraph({
|
|
1963
2620
|
children: [
|
|
1964
|
-
new TextRun({ text: "[Mermaid Diagram: " + (node.text || "").slice(0, 40) + "...]", bold: true, color:
|
|
2621
|
+
new TextRun({ text: "[Mermaid Diagram: " + (node.text || "").slice(0, 40) + "...]", bold: true, color: primaryHex })
|
|
1965
2622
|
],
|
|
1966
2623
|
spacing: { before: 60, after: 60 }
|
|
1967
2624
|
})
|
|
@@ -1973,8 +2630,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1973
2630
|
const tableRows = [];
|
|
1974
2631
|
const numCols = ((_b = (_a = node.children[0]) == null ? void 0 : _a.children) == null ? void 0 : _b.length) || 1;
|
|
1975
2632
|
const colWidth = Math.floor(9e3 / numCols);
|
|
1976
|
-
for (
|
|
2633
|
+
for (let rowIdx = 0; rowIdx < node.children.length; rowIdx++) {
|
|
2634
|
+
const rowNode = node.children[rowIdx];
|
|
1977
2635
|
const cells = [];
|
|
2636
|
+
const isHeader = rowNode.isHeader;
|
|
2637
|
+
const rowBg = isHeader ? "F1F5F9" : rowIdx % 2 === 0 ? "FFFFFF" : "F8FAFC";
|
|
1978
2638
|
if (rowNode.children) {
|
|
1979
2639
|
for (let colIdx = 0; colIdx < rowNode.children.length; colIdx++) {
|
|
1980
2640
|
const cellNode = rowNode.children[colIdx];
|
|
@@ -1982,22 +2642,27 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1982
2642
|
let alignment = AlignmentType.LEFT;
|
|
1983
2643
|
if (align === "center") alignment = AlignmentType.CENTER;
|
|
1984
2644
|
if (align === "right") alignment = AlignmentType.RIGHT;
|
|
1985
|
-
const runs = await convertInlinesToTextRuns(cellNode.inlines, baseDir
|
|
2645
|
+
const runs = await convertInlinesToTextRuns(cellNode.inlines, baseDir, {
|
|
2646
|
+
font: defaultFont,
|
|
2647
|
+
size: 20,
|
|
2648
|
+
color: isHeader ? "0F172A" : "334155",
|
|
2649
|
+
bold: isHeader
|
|
2650
|
+
});
|
|
1986
2651
|
cells.push(
|
|
1987
2652
|
new TableCell({
|
|
1988
2653
|
width: { size: colWidth, type: WidthType.DXA },
|
|
1989
|
-
shading:
|
|
1990
|
-
margins: { top: 100, bottom: 100, left:
|
|
2654
|
+
shading: { fill: rowBg, type: ShadingType.CLEAR },
|
|
2655
|
+
margins: { top: 100, bottom: 100, left: 140, right: 140 },
|
|
1991
2656
|
borders: {
|
|
1992
|
-
top: { style: BorderStyle.SINGLE, size: 4, color: "
|
|
1993
|
-
bottom: { style: BorderStyle.SINGLE, size: 4, color: "CBD5E1" },
|
|
1994
|
-
left: { style: BorderStyle.SINGLE, size: 4, color: "
|
|
1995
|
-
right: { style: BorderStyle.SINGLE, size: 4, color: "
|
|
2657
|
+
top: { style: BorderStyle.SINGLE, size: 4, color: "E2E8F0" },
|
|
2658
|
+
bottom: { style: BorderStyle.SINGLE, size: isHeader ? 8 : 4, color: isHeader ? "CBD5E1" : "E2E8F0" },
|
|
2659
|
+
left: { style: BorderStyle.SINGLE, size: 4, color: "E2E8F0" },
|
|
2660
|
+
right: { style: BorderStyle.SINGLE, size: 4, color: "E2E8F0" }
|
|
1996
2661
|
},
|
|
1997
2662
|
children: [
|
|
1998
2663
|
new Paragraph({
|
|
1999
2664
|
alignment,
|
|
2000
|
-
children:
|
|
2665
|
+
children: runs
|
|
2001
2666
|
})
|
|
2002
2667
|
]
|
|
2003
2668
|
})
|
|
@@ -2006,7 +2671,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2006
2671
|
}
|
|
2007
2672
|
tableRows.push(
|
|
2008
2673
|
new TableRow({
|
|
2009
|
-
tableHeader:
|
|
2674
|
+
tableHeader: isHeader,
|
|
2010
2675
|
children: cells
|
|
2011
2676
|
})
|
|
2012
2677
|
);
|
|
@@ -2022,7 +2687,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2022
2687
|
}
|
|
2023
2688
|
if (node.type === "list" && node.children) {
|
|
2024
2689
|
for (const item of node.children) {
|
|
2025
|
-
const runs = await convertInlinesToTextRuns(item.inlines, baseDir
|
|
2690
|
+
const runs = await convertInlinesToTextRuns(item.inlines, baseDir, {
|
|
2691
|
+
font: defaultFont,
|
|
2692
|
+
size: 21,
|
|
2693
|
+
color: "334155"
|
|
2694
|
+
});
|
|
2026
2695
|
let prefix = "";
|
|
2027
2696
|
if (item.checked !== void 0) {
|
|
2028
2697
|
prefix = item.checked ? "[X] " : "[ ] ";
|
|
@@ -2034,7 +2703,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2034
2703
|
...prefix ? [new TextRun({ text: prefix, bold: true, font: "Consolas" })] : [],
|
|
2035
2704
|
...runs
|
|
2036
2705
|
],
|
|
2037
|
-
spacing: { before:
|
|
2706
|
+
spacing: { before: 20, after: 20, line: 260 }
|
|
2038
2707
|
})
|
|
2039
2708
|
);
|
|
2040
2709
|
}
|
|
@@ -2109,88 +2778,205 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2109
2778
|
continue;
|
|
2110
2779
|
}
|
|
2111
2780
|
}
|
|
2112
|
-
const
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
const
|
|
2781
|
+
const contentWidthTwip = Math.max(
|
|
2782
|
+
1e3,
|
|
2783
|
+
resolved.paperDimensions.widthTwip - resolved.margins.leftTwip - resolved.margins.rightTwip
|
|
2784
|
+
);
|
|
2785
|
+
const centerPos = Math.round(contentWidthTwip / 2);
|
|
2786
|
+
const rightPos = contentWidthTwip;
|
|
2787
|
+
const headerRuns = [];
|
|
2788
|
+
if ((_d = resolved.header) == null ? void 0 : _d.left) {
|
|
2789
|
+
headerRuns.push(
|
|
2790
|
+
new TextRun({
|
|
2791
|
+
text: resolved.header.left.text,
|
|
2792
|
+
color: resolved.header.left.color.replace("#", ""),
|
|
2793
|
+
size: (resolved.header.left.fontSize || 9) * 2,
|
|
2794
|
+
font: resolved.header.left.fontFamily || defaultFont,
|
|
2795
|
+
bold: resolved.header.left.bold,
|
|
2796
|
+
italics: resolved.header.left.italic
|
|
2797
|
+
})
|
|
2798
|
+
);
|
|
2799
|
+
}
|
|
2800
|
+
headerRuns.push(new TextRun({ text: " " }));
|
|
2801
|
+
if ((_e = resolved.header) == null ? void 0 : _e.center) {
|
|
2802
|
+
headerRuns.push(
|
|
2803
|
+
new TextRun({
|
|
2804
|
+
text: resolved.header.center.text,
|
|
2805
|
+
color: resolved.header.center.color.replace("#", ""),
|
|
2806
|
+
size: (resolved.header.center.fontSize || 9) * 2,
|
|
2807
|
+
font: resolved.header.center.fontFamily || defaultFont,
|
|
2808
|
+
bold: resolved.header.center.bold,
|
|
2809
|
+
italics: resolved.header.center.italic
|
|
2810
|
+
})
|
|
2811
|
+
);
|
|
2812
|
+
}
|
|
2813
|
+
headerRuns.push(new TextRun({ text: " " }));
|
|
2814
|
+
if ((_f = resolved.header) == null ? void 0 : _f.right) {
|
|
2815
|
+
headerRuns.push(
|
|
2816
|
+
new TextRun({
|
|
2817
|
+
text: resolved.header.right.text,
|
|
2818
|
+
color: resolved.header.right.color.replace("#", ""),
|
|
2819
|
+
size: (resolved.header.right.fontSize || 9) * 2,
|
|
2820
|
+
font: resolved.header.right.fontFamily || defaultFont,
|
|
2821
|
+
bold: resolved.header.right.bold,
|
|
2822
|
+
italics: resolved.header.right.italic
|
|
2823
|
+
})
|
|
2824
|
+
);
|
|
2825
|
+
}
|
|
2826
|
+
const docHeader = resolved.header ? new Header({
|
|
2119
2827
|
children: [
|
|
2120
2828
|
new Paragraph({
|
|
2121
|
-
tabStops:
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2829
|
+
tabStops: [
|
|
2830
|
+
{
|
|
2831
|
+
type: TabStopType.CENTER,
|
|
2832
|
+
position: centerPos
|
|
2833
|
+
},
|
|
2834
|
+
{
|
|
2835
|
+
type: TabStopType.RIGHT,
|
|
2836
|
+
position: rightPos
|
|
2837
|
+
}
|
|
2838
|
+
],
|
|
2839
|
+
border: resolved.header.divider ? {
|
|
2840
|
+
bottom: {
|
|
2841
|
+
style: BorderStyle.SINGLE,
|
|
2842
|
+
size: 4,
|
|
2843
|
+
space: 6,
|
|
2844
|
+
color: (resolved.header.dividerColor || "#CBD5E1").replace("#", "")
|
|
2845
|
+
}
|
|
2846
|
+
} : void 0,
|
|
2847
|
+
children: headerRuns,
|
|
2848
|
+
spacing: { after: 120 }
|
|
2849
|
+
})
|
|
2850
|
+
]
|
|
2851
|
+
}) : void 0;
|
|
2852
|
+
const footerRuns = [];
|
|
2853
|
+
if ((_g = resolved.footer) == null ? void 0 : _g.left) {
|
|
2854
|
+
footerRuns.push(
|
|
2855
|
+
new TextRun({
|
|
2856
|
+
text: resolved.footer.left.text,
|
|
2857
|
+
color: resolved.footer.left.color.replace("#", ""),
|
|
2858
|
+
size: (resolved.footer.left.fontSize || 9) * 2,
|
|
2859
|
+
font: resolved.footer.left.fontFamily || defaultFont,
|
|
2860
|
+
bold: resolved.footer.left.bold,
|
|
2861
|
+
italics: resolved.footer.left.italic
|
|
2862
|
+
})
|
|
2863
|
+
);
|
|
2864
|
+
}
|
|
2865
|
+
footerRuns.push(new TextRun({ text: " " }));
|
|
2866
|
+
if ((_h = resolved.footer) == null ? void 0 : _h.center) {
|
|
2867
|
+
footerRuns.push(
|
|
2868
|
+
new TextRun({
|
|
2869
|
+
text: resolved.footer.center.text,
|
|
2870
|
+
color: resolved.footer.center.color.replace("#", ""),
|
|
2871
|
+
size: (resolved.footer.center.fontSize || 9) * 2,
|
|
2872
|
+
font: resolved.footer.center.fontFamily || defaultFont,
|
|
2873
|
+
bold: resolved.footer.center.bold,
|
|
2874
|
+
italics: resolved.footer.center.italic
|
|
2875
|
+
})
|
|
2876
|
+
);
|
|
2877
|
+
}
|
|
2878
|
+
footerRuns.push(new TextRun({ text: " " }));
|
|
2879
|
+
if ((_i = resolved.footer) == null ? void 0 : _i.right) {
|
|
2880
|
+
const rZone = resolved.footer.right;
|
|
2881
|
+
const rColor = rZone.color.replace("#", "");
|
|
2882
|
+
const rSize = (rZone.fontSize || 9) * 2;
|
|
2883
|
+
const rFont = rZone.fontFamily || defaultFont;
|
|
2884
|
+
const rBold = rZone.bold;
|
|
2885
|
+
const rItalics = rZone.italic;
|
|
2886
|
+
if (rZone.text.includes("{page}") || rZone.text.includes("{pages}")) {
|
|
2887
|
+
const parts = rZone.text.split(/(\{page\}|\{pages\})/gi);
|
|
2888
|
+
for (const part of parts) {
|
|
2889
|
+
if (part.toLowerCase() === "{page}") {
|
|
2890
|
+
footerRuns.push(
|
|
2125
2891
|
new TextRun({
|
|
2126
|
-
|
|
2127
|
-
color:
|
|
2128
|
-
size:
|
|
2892
|
+
children: [PageNumber.CURRENT],
|
|
2893
|
+
color: rColor,
|
|
2894
|
+
size: rSize,
|
|
2895
|
+
font: rFont,
|
|
2896
|
+
bold: rBold,
|
|
2897
|
+
italics: rItalics
|
|
2129
2898
|
})
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
new TextRun({ text: " ", color: "94A3B8", size: 18 }),
|
|
2899
|
+
);
|
|
2900
|
+
} else if (part.toLowerCase() === "{pages}") {
|
|
2901
|
+
footerRuns.push(
|
|
2134
2902
|
new TextRun({
|
|
2135
|
-
|
|
2136
|
-
color:
|
|
2137
|
-
size:
|
|
2903
|
+
children: [PageNumber.TOTAL_PAGES],
|
|
2904
|
+
color: rColor,
|
|
2905
|
+
size: rSize,
|
|
2906
|
+
font: rFont,
|
|
2907
|
+
bold: rBold,
|
|
2908
|
+
italics: rItalics
|
|
2138
2909
|
})
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
new TextRun({
|
|
2143
|
-
text: headerObj.left || headerObj.center ? " " : "",
|
|
2144
|
-
color: "94A3B8",
|
|
2145
|
-
size: 18
|
|
2146
|
-
}),
|
|
2910
|
+
);
|
|
2911
|
+
} else if (part) {
|
|
2912
|
+
footerRuns.push(
|
|
2147
2913
|
new TextRun({
|
|
2148
|
-
text:
|
|
2149
|
-
color:
|
|
2150
|
-
size:
|
|
2914
|
+
text: part,
|
|
2915
|
+
color: rColor,
|
|
2916
|
+
size: rSize,
|
|
2917
|
+
font: rFont,
|
|
2918
|
+
bold: rBold,
|
|
2919
|
+
italics: rItalics
|
|
2151
2920
|
})
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2921
|
+
);
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
} else {
|
|
2925
|
+
footerRuns.push(
|
|
2926
|
+
new TextRun({
|
|
2927
|
+
text: rZone.text,
|
|
2928
|
+
color: rColor,
|
|
2929
|
+
size: rSize,
|
|
2930
|
+
font: rFont,
|
|
2931
|
+
bold: rBold,
|
|
2932
|
+
italics: rItalics
|
|
2933
|
+
})
|
|
2934
|
+
);
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
const docFooter = resolved.footer ? new Footer({
|
|
2158
2938
|
children: [
|
|
2159
2939
|
new Paragraph({
|
|
2160
|
-
tabStops:
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2940
|
+
tabStops: [
|
|
2941
|
+
{
|
|
2942
|
+
type: TabStopType.CENTER,
|
|
2943
|
+
position: centerPos
|
|
2944
|
+
},
|
|
2945
|
+
{
|
|
2946
|
+
type: TabStopType.RIGHT,
|
|
2947
|
+
position: rightPos
|
|
2948
|
+
}
|
|
2949
|
+
],
|
|
2950
|
+
border: resolved.footer.divider ? {
|
|
2951
|
+
top: {
|
|
2952
|
+
style: BorderStyle.SINGLE,
|
|
2953
|
+
size: 4,
|
|
2954
|
+
space: 6,
|
|
2955
|
+
color: (resolved.footer.dividerColor || "#CBD5E1").replace("#", "")
|
|
2956
|
+
}
|
|
2957
|
+
} : void 0,
|
|
2958
|
+
children: footerRuns,
|
|
2959
|
+
spacing: { before: 120 }
|
|
2177
2960
|
})
|
|
2178
2961
|
]
|
|
2179
2962
|
}) : void 0;
|
|
2180
|
-
const
|
|
2181
|
-
const bottomMargin = parseMarginToTwip(((_f = metadata.margins) == null ? void 0 : _f.bottom) || ((_g = config.margins) == null ? void 0 : _g.bottom), 1440);
|
|
2182
|
-
const leftMargin = parseMarginToTwip(((_h = metadata.margins) == null ? void 0 : _h.left) || ((_i = config.margins) == null ? void 0 : _i.left), 1440);
|
|
2183
|
-
const rightMargin = parseMarginToTwip(((_j = metadata.margins) == null ? void 0 : _j.right) || ((_k = config.margins) == null ? void 0 : _k.right), 1440);
|
|
2184
|
-
const isLandscape = (metadata.orientation || config.orientation) === "landscape";
|
|
2963
|
+
const isLandscape = resolved.orientation === "landscape";
|
|
2185
2964
|
const document = new Document({
|
|
2186
2965
|
styles: {
|
|
2187
2966
|
default: {
|
|
2188
2967
|
document: {
|
|
2189
2968
|
run: {
|
|
2190
|
-
font:
|
|
2191
|
-
size:
|
|
2192
|
-
//
|
|
2193
|
-
color:
|
|
2969
|
+
font: defaultFont,
|
|
2970
|
+
size: 21,
|
|
2971
|
+
// 10.5pt
|
|
2972
|
+
color: textHex
|
|
2973
|
+
},
|
|
2974
|
+
paragraph: {
|
|
2975
|
+
spacing: {
|
|
2976
|
+
line: 276,
|
|
2977
|
+
// 1.15 line spacing
|
|
2978
|
+
after: 140
|
|
2979
|
+
}
|
|
2194
2980
|
}
|
|
2195
2981
|
}
|
|
2196
2982
|
}
|
|
@@ -2200,13 +2986,15 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2200
2986
|
properties: {
|
|
2201
2987
|
page: {
|
|
2202
2988
|
size: {
|
|
2989
|
+
width: resolved.paperDimensions.widthTwip,
|
|
2990
|
+
height: resolved.paperDimensions.heightTwip,
|
|
2203
2991
|
orientation: isLandscape ? PageOrientation.LANDSCAPE : PageOrientation.PORTRAIT
|
|
2204
2992
|
},
|
|
2205
2993
|
margin: {
|
|
2206
|
-
top:
|
|
2207
|
-
bottom:
|
|
2208
|
-
left:
|
|
2209
|
-
right:
|
|
2994
|
+
top: resolved.margins.topTwip,
|
|
2995
|
+
bottom: resolved.margins.bottomTwip,
|
|
2996
|
+
left: resolved.margins.leftTwip,
|
|
2997
|
+
right: resolved.margins.rightTwip,
|
|
2210
2998
|
header: 720,
|
|
2211
2999
|
footer: 720
|
|
2212
3000
|
}
|
|
@@ -2221,154 +3009,6 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2221
3009
|
return await Packer.toBuffer(document);
|
|
2222
3010
|
}
|
|
2223
3011
|
|
|
2224
|
-
// src/config/loadConfig.ts
|
|
2225
|
-
import * as fs5 from "fs";
|
|
2226
|
-
import * as path5 from "path";
|
|
2227
|
-
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
2228
|
-
import * as YAML from "yaml";
|
|
2229
|
-
var DEFAULT_CONFIG_FILENAMES = [
|
|
2230
|
-
"markforge.config.json",
|
|
2231
|
-
".markforgerc.json",
|
|
2232
|
-
"markforge.config.yaml",
|
|
2233
|
-
"markforge.config.yml",
|
|
2234
|
-
".markforgerc.yaml",
|
|
2235
|
-
".markforgerc.yml",
|
|
2236
|
-
".markforgerc",
|
|
2237
|
-
"markforge.config.ts",
|
|
2238
|
-
"markforge.config.js",
|
|
2239
|
-
"markforge.config.mjs",
|
|
2240
|
-
"markforge.config.cjs"
|
|
2241
|
-
];
|
|
2242
|
-
var DEFAULT_CONFIG = {
|
|
2243
|
-
to: ["docx", "pdf"],
|
|
2244
|
-
outputDir: void 0,
|
|
2245
|
-
theme: "default",
|
|
2246
|
-
css: void 0,
|
|
2247
|
-
orientation: "portrait",
|
|
2248
|
-
paperSize: "A4",
|
|
2249
|
-
margins: {
|
|
2250
|
-
top: "2.5cm",
|
|
2251
|
-
bottom: "2.5cm",
|
|
2252
|
-
left: "2.5cm",
|
|
2253
|
-
right: "2.5cm"
|
|
2254
|
-
},
|
|
2255
|
-
header: void 0,
|
|
2256
|
-
footer: {
|
|
2257
|
-
right: "Page {page} of {pages}"
|
|
2258
|
-
},
|
|
2259
|
-
toc: false,
|
|
2260
|
-
watermark: void 0,
|
|
2261
|
-
embedImages: true,
|
|
2262
|
-
metadata: void 0,
|
|
2263
|
-
watch: false,
|
|
2264
|
-
serve: false,
|
|
2265
|
-
port: 4e3,
|
|
2266
|
-
open: false,
|
|
2267
|
-
bundleHtml: true,
|
|
2268
|
-
syntaxTheme: "github-dark"
|
|
2269
|
-
};
|
|
2270
|
-
function discoverConfigFile(startDir) {
|
|
2271
|
-
const dirsToCheck = [];
|
|
2272
|
-
let curr = path5.resolve(startDir);
|
|
2273
|
-
while (curr) {
|
|
2274
|
-
dirsToCheck.push(curr);
|
|
2275
|
-
const parent = path5.dirname(curr);
|
|
2276
|
-
if (parent === curr) break;
|
|
2277
|
-
curr = parent;
|
|
2278
|
-
}
|
|
2279
|
-
const cwd = path5.resolve(process.cwd());
|
|
2280
|
-
if (!dirsToCheck.includes(cwd)) {
|
|
2281
|
-
dirsToCheck.push(cwd);
|
|
2282
|
-
}
|
|
2283
|
-
for (const dir of dirsToCheck) {
|
|
2284
|
-
for (const filename of DEFAULT_CONFIG_FILENAMES) {
|
|
2285
|
-
const candidate = path5.join(dir, filename);
|
|
2286
|
-
if (fs5.existsSync(candidate) && fs5.statSync(candidate).isFile()) {
|
|
2287
|
-
return candidate;
|
|
2288
|
-
}
|
|
2289
|
-
}
|
|
2290
|
-
}
|
|
2291
|
-
return null;
|
|
2292
|
-
}
|
|
2293
|
-
async function loadConfig(customPath, startDir = process.cwd()) {
|
|
2294
|
-
let resolvedPath = null;
|
|
2295
|
-
if (customPath) {
|
|
2296
|
-
resolvedPath = path5.isAbsolute(customPath) ? customPath : path5.resolve(process.cwd(), customPath);
|
|
2297
|
-
if (!fs5.existsSync(resolvedPath)) {
|
|
2298
|
-
const altPath = path5.resolve(startDir, customPath);
|
|
2299
|
-
if (fs5.existsSync(altPath)) {
|
|
2300
|
-
resolvedPath = altPath;
|
|
2301
|
-
} else {
|
|
2302
|
-
throw new Error(`Configuration file not found: ${resolvedPath}`);
|
|
2303
|
-
}
|
|
2304
|
-
}
|
|
2305
|
-
} else {
|
|
2306
|
-
resolvedPath = discoverConfigFile(startDir);
|
|
2307
|
-
}
|
|
2308
|
-
if (!resolvedPath) {
|
|
2309
|
-
return {
|
|
2310
|
-
config: { ...DEFAULT_CONFIG },
|
|
2311
|
-
configPath: null
|
|
2312
|
-
};
|
|
2313
|
-
}
|
|
2314
|
-
const ext = path5.extname(resolvedPath).toLowerCase();
|
|
2315
|
-
let userConfig = {};
|
|
2316
|
-
try {
|
|
2317
|
-
if (ext === ".json" || ext === "" || resolvedPath.endsWith(".markforgerc")) {
|
|
2318
|
-
const raw = fs5.readFileSync(resolvedPath, "utf-8").trim();
|
|
2319
|
-
try {
|
|
2320
|
-
userConfig = JSON.parse(raw);
|
|
2321
|
-
} catch {
|
|
2322
|
-
userConfig = YAML.parse(raw) || {};
|
|
2323
|
-
}
|
|
2324
|
-
} else if (ext === ".yaml" || ext === ".yml") {
|
|
2325
|
-
const raw = fs5.readFileSync(resolvedPath, "utf-8");
|
|
2326
|
-
userConfig = YAML.parse(raw) || {};
|
|
2327
|
-
} else if (ext === ".ts" || ext === ".js" || ext === ".mjs" || ext === ".cjs") {
|
|
2328
|
-
try {
|
|
2329
|
-
const fileUrl = `${pathToFileURL3(resolvedPath).href}?t=${Date.now()}`;
|
|
2330
|
-
const mod = await import(fileUrl);
|
|
2331
|
-
const rawExport = mod.default ?? mod.config ?? mod;
|
|
2332
|
-
userConfig = (typeof rawExport === "function" ? await rawExport() : rawExport) || {};
|
|
2333
|
-
} catch (importErr) {
|
|
2334
|
-
try {
|
|
2335
|
-
const mod = __require(resolvedPath);
|
|
2336
|
-
const rawExport = mod.default ?? mod.config ?? mod;
|
|
2337
|
-
userConfig = (typeof rawExport === "function" ? await rawExport() : rawExport) || {};
|
|
2338
|
-
} catch {
|
|
2339
|
-
throw importErr;
|
|
2340
|
-
}
|
|
2341
|
-
}
|
|
2342
|
-
}
|
|
2343
|
-
} catch (err) {
|
|
2344
|
-
throw new Error(
|
|
2345
|
-
`Failed to parse configuration file at ${resolvedPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
2346
|
-
);
|
|
2347
|
-
}
|
|
2348
|
-
if (userConfig && typeof userConfig === "object" && "$schema" in userConfig) {
|
|
2349
|
-
delete userConfig.$schema;
|
|
2350
|
-
}
|
|
2351
|
-
const parsedConfig = userConfig;
|
|
2352
|
-
const mergedConfig = {
|
|
2353
|
-
...DEFAULT_CONFIG,
|
|
2354
|
-
...parsedConfig,
|
|
2355
|
-
margins: {
|
|
2356
|
-
...DEFAULT_CONFIG.margins,
|
|
2357
|
-
...parsedConfig.margins || {}
|
|
2358
|
-
},
|
|
2359
|
-
header: parsedConfig.header !== void 0 ? parsedConfig.header : DEFAULT_CONFIG.header,
|
|
2360
|
-
footer: parsedConfig.footer !== void 0 ? parsedConfig.footer : DEFAULT_CONFIG.footer,
|
|
2361
|
-
metadata: {
|
|
2362
|
-
...DEFAULT_CONFIG.metadata || {},
|
|
2363
|
-
...parsedConfig.metadata || {}
|
|
2364
|
-
}
|
|
2365
|
-
};
|
|
2366
|
-
return {
|
|
2367
|
-
config: mergedConfig,
|
|
2368
|
-
configPath: resolvedPath
|
|
2369
|
-
};
|
|
2370
|
-
}
|
|
2371
|
-
|
|
2372
3012
|
// src/core/engine.ts
|
|
2373
3013
|
function formatServerTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
2374
3014
|
const pad = (n) => String(n).padStart(2, "0");
|
|
@@ -2469,7 +3109,7 @@ function defineConfig(config) {
|
|
|
2469
3109
|
// src/version.ts
|
|
2470
3110
|
import * as fs7 from "fs";
|
|
2471
3111
|
import * as path7 from "path";
|
|
2472
|
-
import { fileURLToPath
|
|
3112
|
+
import { fileURLToPath } from "url";
|
|
2473
3113
|
try {
|
|
2474
3114
|
if (typeof globalThis !== "undefined" && (!globalThis.localStorage || typeof globalThis.localStorage.getItem !== "function")) {
|
|
2475
3115
|
Object.defineProperty(globalThis, "localStorage", {
|
|
@@ -2515,7 +3155,7 @@ function getPackageDir() {
|
|
|
2515
3155
|
return __dirname;
|
|
2516
3156
|
}
|
|
2517
3157
|
try {
|
|
2518
|
-
return path7.dirname(
|
|
3158
|
+
return path7.dirname(fileURLToPath(import.meta.url));
|
|
2519
3159
|
} catch {
|
|
2520
3160
|
return process.cwd();
|
|
2521
3161
|
}
|
|
@@ -2527,10 +3167,17 @@ function getMarkforgeVersion(fromDir = getPackageDir()) {
|
|
|
2527
3167
|
export {
|
|
2528
3168
|
DEFAULT_CONFIG,
|
|
2529
3169
|
MARKFORGE_VERSION,
|
|
3170
|
+
Orientation,
|
|
3171
|
+
OutputFormat,
|
|
3172
|
+
PAPER_DIMENSIONS_TWIP,
|
|
3173
|
+
PaperSizeEnum,
|
|
2530
3174
|
SYNTAX_COLORS,
|
|
3175
|
+
SyntaxTheme,
|
|
2531
3176
|
THEMES,
|
|
2532
|
-
|
|
3177
|
+
THEME_CORPORATE,
|
|
2533
3178
|
THEME_DEFAULT,
|
|
3179
|
+
Theme,
|
|
3180
|
+
WatermarkPosition,
|
|
2534
3181
|
buildDocxDocument,
|
|
2535
3182
|
buildHtmlDocument,
|
|
2536
3183
|
buildPdfDocument,
|
|
@@ -2539,6 +3186,7 @@ export {
|
|
|
2539
3186
|
escapeHtml,
|
|
2540
3187
|
findChromeExecutable,
|
|
2541
3188
|
formatServerTimestamp,
|
|
3189
|
+
generateThemeCss,
|
|
2542
3190
|
getMarkforgeVersion,
|
|
2543
3191
|
getMimeType,
|
|
2544
3192
|
highlightCodeToHtml,
|
|
@@ -2546,11 +3194,16 @@ export {
|
|
|
2546
3194
|
inlineHtmlImages,
|
|
2547
3195
|
loadConfig,
|
|
2548
3196
|
compileMarkdown as markforge,
|
|
3197
|
+
normalizeHeaderFooter,
|
|
3198
|
+
normalizeHeaderFooterSlot,
|
|
3199
|
+
normalizeWatermark,
|
|
2549
3200
|
parseInlineSpans,
|
|
2550
|
-
parseMarginToTwip,
|
|
3201
|
+
parseMarginToTwip2 as parseMarginToTwip,
|
|
2551
3202
|
parseMarkdownDocument,
|
|
2552
3203
|
renderInlinesToHtml,
|
|
2553
3204
|
renderMermaidToPng,
|
|
3205
|
+
replaceDocumentTokens,
|
|
3206
|
+
resolveDocumentConfig,
|
|
2554
3207
|
resolveImage,
|
|
2555
3208
|
slugify,
|
|
2556
3209
|
tokenizeCodeLine
|