@masumdev/markforge 0.2.3 → 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 +204 -213
- package/dist/{App-DKCNXX3Z.mjs → App-GNRUPFM7.mjs} +900 -324
- package/dist/chunk-IYGPJIK5.mjs +165 -0
- package/dist/cli.mjs +9 -6
- package/dist/index.d.mts +310 -63
- package/dist/index.d.ts +310 -63
- package/dist/index.js +1146 -435
- package/dist/index.mjs +1134 -436
- package/dist/{loadConfig-T4ZV6YY2.mjs → loadConfig-PD6ENMAM.mjs} +1 -1
- package/package.json +1 -1
- package/schema.json +221 -28
- package/dist/chunk-ASXSHC6H.mjs +0 -120
package/dist/index.js
CHANGED
|
@@ -40,10 +40,17 @@ var src_exports = {};
|
|
|
40
40
|
__export(src_exports, {
|
|
41
41
|
DEFAULT_CONFIG: () => DEFAULT_CONFIG,
|
|
42
42
|
MARKFORGE_VERSION: () => MARKFORGE_VERSION,
|
|
43
|
+
Orientation: () => Orientation,
|
|
44
|
+
OutputFormat: () => OutputFormat,
|
|
45
|
+
PAPER_DIMENSIONS_TWIP: () => PAPER_DIMENSIONS_TWIP,
|
|
46
|
+
PaperSizeEnum: () => PaperSizeEnum,
|
|
43
47
|
SYNTAX_COLORS: () => SYNTAX_COLORS,
|
|
48
|
+
SyntaxTheme: () => SyntaxTheme,
|
|
44
49
|
THEMES: () => THEMES,
|
|
45
|
-
|
|
50
|
+
THEME_CORPORATE: () => THEME_CORPORATE,
|
|
46
51
|
THEME_DEFAULT: () => THEME_DEFAULT,
|
|
52
|
+
Theme: () => Theme,
|
|
53
|
+
WatermarkPosition: () => WatermarkPosition,
|
|
47
54
|
buildDocxDocument: () => buildDocxDocument,
|
|
48
55
|
buildHtmlDocument: () => buildHtmlDocument,
|
|
49
56
|
buildPdfDocument: () => buildPdfDocument,
|
|
@@ -52,6 +59,7 @@ __export(src_exports, {
|
|
|
52
59
|
escapeHtml: () => escapeHtml,
|
|
53
60
|
findChromeExecutable: () => findChromeExecutable,
|
|
54
61
|
formatServerTimestamp: () => formatServerTimestamp,
|
|
62
|
+
generateThemeCss: () => generateThemeCss,
|
|
55
63
|
getMarkforgeVersion: () => getMarkforgeVersion,
|
|
56
64
|
getMimeType: () => getMimeType,
|
|
57
65
|
highlightCodeToHtml: () => highlightCodeToHtml,
|
|
@@ -59,11 +67,16 @@ __export(src_exports, {
|
|
|
59
67
|
inlineHtmlImages: () => inlineHtmlImages,
|
|
60
68
|
loadConfig: () => loadConfig,
|
|
61
69
|
markforge: () => compileMarkdown,
|
|
70
|
+
normalizeHeaderFooter: () => normalizeHeaderFooter,
|
|
71
|
+
normalizeHeaderFooterSlot: () => normalizeHeaderFooterSlot,
|
|
72
|
+
normalizeWatermark: () => normalizeWatermark,
|
|
62
73
|
parseInlineSpans: () => parseInlineSpans,
|
|
63
|
-
parseMarginToTwip: () =>
|
|
74
|
+
parseMarginToTwip: () => parseMarginToTwip2,
|
|
64
75
|
parseMarkdownDocument: () => parseMarkdownDocument,
|
|
65
76
|
renderInlinesToHtml: () => renderInlinesToHtml,
|
|
66
77
|
renderMermaidToPng: () => renderMermaidToPng,
|
|
78
|
+
replaceDocumentTokens: () => replaceDocumentTokens,
|
|
79
|
+
resolveDocumentConfig: () => resolveDocumentConfig,
|
|
67
80
|
resolveImage: () => resolveImage,
|
|
68
81
|
slugify: () => slugify,
|
|
69
82
|
tokenizeCodeLine: () => tokenizeCodeLine
|
|
@@ -585,6 +598,51 @@ var SYNTAX_COLORS_LIGHT = {
|
|
|
585
598
|
plain: "24292E"
|
|
586
599
|
// Near-black — identifiers
|
|
587
600
|
};
|
|
601
|
+
var SYNTAX_THEMES = {
|
|
602
|
+
"github-dark": SYNTAX_COLORS,
|
|
603
|
+
"dark": SYNTAX_COLORS,
|
|
604
|
+
"github-light": SYNTAX_COLORS_LIGHT,
|
|
605
|
+
"light": SYNTAX_COLORS_LIGHT,
|
|
606
|
+
"dracula": {
|
|
607
|
+
keyword: "FF79C6",
|
|
608
|
+
string: "F1FA8C",
|
|
609
|
+
comment: "6272A4",
|
|
610
|
+
number: "BD93F9",
|
|
611
|
+
boolean: "BD93F9",
|
|
612
|
+
function: "50FA7B",
|
|
613
|
+
type: "8BE9FD",
|
|
614
|
+
operator: "FF79C6",
|
|
615
|
+
punctuation: "F8F8F2",
|
|
616
|
+
plain: "F8F8F2"
|
|
617
|
+
},
|
|
618
|
+
"monokai": {
|
|
619
|
+
keyword: "F92672",
|
|
620
|
+
string: "E6DB74",
|
|
621
|
+
comment: "75715E",
|
|
622
|
+
number: "AE81FF",
|
|
623
|
+
boolean: "AE81FF",
|
|
624
|
+
function: "A6E22E",
|
|
625
|
+
type: "66D9EF",
|
|
626
|
+
operator: "F92672",
|
|
627
|
+
punctuation: "F8F8F2",
|
|
628
|
+
plain: "F8F8F2"
|
|
629
|
+
},
|
|
630
|
+
"nord": {
|
|
631
|
+
keyword: "81A1C1",
|
|
632
|
+
string: "A3BE8C",
|
|
633
|
+
comment: "616E88",
|
|
634
|
+
number: "B48EAD",
|
|
635
|
+
boolean: "81A1C1",
|
|
636
|
+
function: "88C0D0",
|
|
637
|
+
type: "8FBCBB",
|
|
638
|
+
operator: "81A1C1",
|
|
639
|
+
punctuation: "ECEFF4",
|
|
640
|
+
plain: "D8DEE9"
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
function getSyntaxPalette(themeName = "github-dark") {
|
|
644
|
+
return SYNTAX_THEMES[themeName.toLowerCase()] || SYNTAX_THEMES["github-dark"];
|
|
645
|
+
}
|
|
588
646
|
var JS_KEYWORDS = /* @__PURE__ */ new Set([
|
|
589
647
|
"import",
|
|
590
648
|
"from",
|
|
@@ -728,9 +786,9 @@ var SQL_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
728
786
|
"foreign",
|
|
729
787
|
"references"
|
|
730
788
|
]);
|
|
731
|
-
function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
789
|
+
function tokenizeCodeLine(line, lang = "", theme = "github-dark") {
|
|
732
790
|
var _a;
|
|
733
|
-
const COLORS = theme
|
|
791
|
+
const COLORS = getSyntaxPalette(theme);
|
|
734
792
|
if (!line) {
|
|
735
793
|
return [{ text: " ", type: "plain", colorHex: COLORS.plain }];
|
|
736
794
|
}
|
|
@@ -813,6 +871,10 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
813
871
|
tokens.push({ text: word, type: "keyword", colorHex: COLORS.keyword, bold: true });
|
|
814
872
|
continue;
|
|
815
873
|
}
|
|
874
|
+
if (/^[A-Z][a-zA-Z0-9_$]*$/.test(word)) {
|
|
875
|
+
tokens.push({ text: word, type: "type", colorHex: COLORS.type });
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
816
878
|
let nextNonWs = pos;
|
|
817
879
|
while (nextNonWs < line.length && /\s/.test(line[nextNonWs])) {
|
|
818
880
|
nextNonWs++;
|
|
@@ -821,10 +883,6 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
821
883
|
tokens.push({ text: word, type: "function", colorHex: COLORS.function });
|
|
822
884
|
continue;
|
|
823
885
|
}
|
|
824
|
-
if (/^[A-Z][a-zA-Z0-9_$]*$/.test(word)) {
|
|
825
|
-
tokens.push({ text: word, type: "type", colorHex: COLORS.type });
|
|
826
|
-
continue;
|
|
827
|
-
}
|
|
828
886
|
tokens.push({ text: word, type: "plain", colorHex: COLORS.plain });
|
|
829
887
|
continue;
|
|
830
888
|
}
|
|
@@ -837,10 +895,10 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
837
895
|
}
|
|
838
896
|
return tokens;
|
|
839
897
|
}
|
|
840
|
-
function highlightCodeToHtml(code, lang = "") {
|
|
898
|
+
function highlightCodeToHtml(code, lang = "", theme = "github-dark") {
|
|
841
899
|
const lines = (code || "").split("\n");
|
|
842
900
|
const htmlLines = lines.map((line) => {
|
|
843
|
-
const tokens = tokenizeCodeLine(line, lang);
|
|
901
|
+
const tokens = tokenizeCodeLine(line, lang, theme);
|
|
844
902
|
return tokens.map((t) => {
|
|
845
903
|
const escaped = t.text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
846
904
|
if (t.type === "plain") return escaped;
|
|
@@ -852,21 +910,62 @@ function highlightCodeToHtml(code, lang = "") {
|
|
|
852
910
|
|
|
853
911
|
// src/core/mermaid/mermaidRenderer.ts
|
|
854
912
|
var import_node_child_process2 = require("child_process");
|
|
855
|
-
var
|
|
913
|
+
var fs5 = __toESM(require("fs"));
|
|
856
914
|
var os2 = __toESM(require("os"));
|
|
857
|
-
var
|
|
858
|
-
var
|
|
915
|
+
var path5 = __toESM(require("path"));
|
|
916
|
+
var import_node_url3 = require("url");
|
|
859
917
|
|
|
860
918
|
// src/core/pdf/pdfBuilder.ts
|
|
861
|
-
var
|
|
862
|
-
var
|
|
919
|
+
var fs4 = __toESM(require("fs"));
|
|
920
|
+
var path4 = __toESM(require("path"));
|
|
863
921
|
var os = __toESM(require("os"));
|
|
864
|
-
var
|
|
922
|
+
var import_node_url2 = require("url");
|
|
865
923
|
var import_node_child_process = require("child_process");
|
|
866
924
|
|
|
867
925
|
// src/core/html/htmlBuilder.ts
|
|
868
|
-
var
|
|
869
|
-
var
|
|
926
|
+
var fs3 = __toESM(require("fs"));
|
|
927
|
+
var path3 = __toESM(require("path"));
|
|
928
|
+
|
|
929
|
+
// src/config/types.ts
|
|
930
|
+
var OutputFormat = /* @__PURE__ */ ((OutputFormat2) => {
|
|
931
|
+
OutputFormat2["DOCX"] = "docx";
|
|
932
|
+
OutputFormat2["PDF"] = "pdf";
|
|
933
|
+
OutputFormat2["HTML"] = "html";
|
|
934
|
+
OutputFormat2["PNG"] = "png";
|
|
935
|
+
return OutputFormat2;
|
|
936
|
+
})(OutputFormat || {});
|
|
937
|
+
var Theme = /* @__PURE__ */ ((Theme2) => {
|
|
938
|
+
Theme2["CORPORATE"] = "corporate";
|
|
939
|
+
return Theme2;
|
|
940
|
+
})(Theme || {});
|
|
941
|
+
var Orientation = /* @__PURE__ */ ((Orientation2) => {
|
|
942
|
+
Orientation2["PORTRAIT"] = "portrait";
|
|
943
|
+
Orientation2["LANDSCAPE"] = "landscape";
|
|
944
|
+
return Orientation2;
|
|
945
|
+
})(Orientation || {});
|
|
946
|
+
var PaperSizeEnum = /* @__PURE__ */ ((PaperSizeEnum2) => {
|
|
947
|
+
PaperSizeEnum2["A4"] = "A4";
|
|
948
|
+
PaperSizeEnum2["LETTER"] = "Letter";
|
|
949
|
+
PaperSizeEnum2["LEGAL"] = "Legal";
|
|
950
|
+
PaperSizeEnum2["A3"] = "A3";
|
|
951
|
+
PaperSizeEnum2["A5"] = "A5";
|
|
952
|
+
return PaperSizeEnum2;
|
|
953
|
+
})(PaperSizeEnum || {});
|
|
954
|
+
var SyntaxTheme = /* @__PURE__ */ ((SyntaxTheme2) => {
|
|
955
|
+
SyntaxTheme2["GITHUB_DARK"] = "github-dark";
|
|
956
|
+
SyntaxTheme2["GITHUB_LIGHT"] = "github-light";
|
|
957
|
+
SyntaxTheme2["DRACULA"] = "dracula";
|
|
958
|
+
SyntaxTheme2["MONOKAI"] = "monokai";
|
|
959
|
+
SyntaxTheme2["NORD"] = "nord";
|
|
960
|
+
return SyntaxTheme2;
|
|
961
|
+
})(SyntaxTheme || {});
|
|
962
|
+
var WatermarkPosition = /* @__PURE__ */ ((WatermarkPosition2) => {
|
|
963
|
+
WatermarkPosition2["DIAGONAL"] = "diagonal";
|
|
964
|
+
WatermarkPosition2["CENTER"] = "center";
|
|
965
|
+
WatermarkPosition2["TOP_RIGHT"] = "top-right";
|
|
966
|
+
WatermarkPosition2["BOTTOM_RIGHT"] = "bottom-right";
|
|
967
|
+
return WatermarkPosition2;
|
|
968
|
+
})(WatermarkPosition || {});
|
|
870
969
|
|
|
871
970
|
// src/core/html/htmlThemes.ts
|
|
872
971
|
var THEME_COMPONENTS = `
|
|
@@ -949,7 +1048,7 @@ hr { border: none; border-top: 1px solid var(--mf-border); margin: 2rem 0; }
|
|
|
949
1048
|
pre { overflow: visible; white-space: pre-wrap; word-break: break-all; }
|
|
950
1049
|
}
|
|
951
1050
|
`;
|
|
952
|
-
var
|
|
1051
|
+
var THEME_CORPORATE = `
|
|
953
1052
|
:root {
|
|
954
1053
|
--mf-bg: #ffffff;
|
|
955
1054
|
--mf-text: #0f172a;
|
|
@@ -961,49 +1060,415 @@ var THEME_DEFAULT = `
|
|
|
961
1060
|
--mf-card-bg: #f8fafc;
|
|
962
1061
|
--mf-code-bg: #0f172a;
|
|
963
1062
|
--mf-code-text: #f8fafc;
|
|
964
|
-
--mf-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
1063
|
+
--mf-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
965
1064
|
--mf-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
966
1065
|
}
|
|
967
1066
|
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; }
|
|
968
|
-
.document-container { max-width: 860px; margin: 0 auto; }
|
|
1067
|
+
.document-container { max-width: 860px; margin: 0 auto; position: relative; z-index: 1; }
|
|
969
1068
|
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; }
|
|
970
|
-
h1 { font-size: 2.2rem; border-bottom: 2px solid
|
|
971
|
-
h2 { font-size: 1.6rem; color:
|
|
1069
|
+
h1 { font-size: 2.2rem; border-bottom: 2px solid var(--mf-primary); padding-bottom: 0.5rem; }
|
|
1070
|
+
h2 { font-size: 1.6rem; color: var(--mf-primary-dark); border-bottom: 1px solid #CCFBF1; padding-bottom: 0.4rem; }
|
|
972
1071
|
h3 { font-size: 1.3rem; }
|
|
973
1072
|
h4 { font-size: 1.1rem; }
|
|
974
1073
|
p { margin: 0.8rem 0; }
|
|
975
1074
|
`;
|
|
976
|
-
var
|
|
1075
|
+
var THEME_DEFAULT = THEME_CORPORATE;
|
|
1076
|
+
var THEMES = {
|
|
1077
|
+
corporate: THEME_CORPORATE,
|
|
1078
|
+
default: THEME_CORPORATE
|
|
1079
|
+
};
|
|
1080
|
+
function generateThemeCss(theme) {
|
|
1081
|
+
if (!theme || theme === "corporate" || theme === "default" || theme === "corporate" /* CORPORATE */) {
|
|
1082
|
+
return THEME_CORPORATE;
|
|
1083
|
+
}
|
|
1084
|
+
if (typeof theme === "object") {
|
|
1085
|
+
const bg = theme.backgroundColor || "#ffffff";
|
|
1086
|
+
const text = theme.textColor || "#0f172a";
|
|
1087
|
+
const textMuted = theme.textMuted || "#64748b";
|
|
1088
|
+
const primary = theme.primaryColor || "#33CDCF";
|
|
1089
|
+
const primaryDark = theme.primaryDark || primary;
|
|
1090
|
+
const primaryLight = theme.primaryLight || "#ECFDFD";
|
|
1091
|
+
const border = theme.borderColor || "#e2e8f0";
|
|
1092
|
+
const cardBg = theme.cardBackground || "#f8fafc";
|
|
1093
|
+
const codeBg = theme.codeBackground || "#0f172a";
|
|
1094
|
+
const codeText = theme.codeText || "#f8fafc";
|
|
1095
|
+
const font = theme.fontFamily || "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
|
|
1096
|
+
const fontMono = theme.fontMono || "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace";
|
|
1097
|
+
return `
|
|
977
1098
|
:root {
|
|
978
|
-
--mf-bg:
|
|
979
|
-
--mf-text:
|
|
980
|
-
--mf-text-muted:
|
|
981
|
-
--mf-primary:
|
|
982
|
-
--mf-primary-dark:
|
|
983
|
-
--mf-primary-light:
|
|
984
|
-
--mf-border:
|
|
985
|
-
--mf-card-bg:
|
|
986
|
-
--mf-code-bg:
|
|
987
|
-
--mf-code-text:
|
|
988
|
-
--mf-font-family:
|
|
989
|
-
--mf-font-mono:
|
|
1099
|
+
--mf-bg: ${bg};
|
|
1100
|
+
--mf-text: ${text};
|
|
1101
|
+
--mf-text-muted: ${textMuted};
|
|
1102
|
+
--mf-primary: ${primary};
|
|
1103
|
+
--mf-primary-dark: ${primaryDark};
|
|
1104
|
+
--mf-primary-light: ${primaryLight};
|
|
1105
|
+
--mf-border: ${border};
|
|
1106
|
+
--mf-card-bg: ${cardBg};
|
|
1107
|
+
--mf-code-bg: ${codeBg};
|
|
1108
|
+
--mf-code-text: ${codeText};
|
|
1109
|
+
--mf-font-family: ${font};
|
|
1110
|
+
--mf-font-mono: ${fontMono};
|
|
990
1111
|
}
|
|
991
|
-
body { font-family: var(--mf-font-family); font-size:
|
|
992
|
-
.document-container { max-width:
|
|
993
|
-
h1, h2, h3 { font-
|
|
994
|
-
h1 { font-size: 2rem; border-bottom:
|
|
995
|
-
h2 { font-size: 1.
|
|
996
|
-
h3 { font-size: 1.
|
|
997
|
-
|
|
1112
|
+
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; }
|
|
1113
|
+
.document-container { max-width: 860px; margin: 0 auto; position: relative; z-index: 1; }
|
|
1114
|
+
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; }
|
|
1115
|
+
h1 { font-size: 2.2rem; border-bottom: 2px solid var(--mf-primary); padding-bottom: 0.5rem; }
|
|
1116
|
+
h2 { font-size: 1.6rem; color: var(--mf-primary-dark); border-bottom: 1px solid var(--mf-border); padding-bottom: 0.4rem; }
|
|
1117
|
+
h3 { font-size: 1.3rem; }
|
|
1118
|
+
h4 { font-size: 1.1rem; }
|
|
1119
|
+
p { margin: 0.8rem 0; }
|
|
1120
|
+
${theme.customCss || ""}
|
|
998
1121
|
`;
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1122
|
+
}
|
|
1123
|
+
if (typeof theme === "string" && THEMES[theme]) {
|
|
1124
|
+
return THEMES[theme];
|
|
1125
|
+
}
|
|
1126
|
+
return THEME_CORPORATE;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
// src/config/loadConfig.ts
|
|
1130
|
+
var fs2 = __toESM(require("fs"));
|
|
1131
|
+
var path2 = __toESM(require("path"));
|
|
1132
|
+
var import_node_url = require("url");
|
|
1133
|
+
var YAML = __toESM(require("yaml"));
|
|
1134
|
+
var DEFAULT_CONFIG_FILENAMES = [
|
|
1135
|
+
"markforge.config.json",
|
|
1136
|
+
".markforgerc.json",
|
|
1137
|
+
"markforge.config.yaml",
|
|
1138
|
+
"markforge.config.yml",
|
|
1139
|
+
".markforgerc.yaml",
|
|
1140
|
+
".markforgerc.yml",
|
|
1141
|
+
".markforgerc",
|
|
1142
|
+
"markforge.config.ts",
|
|
1143
|
+
"markforge.config.js",
|
|
1144
|
+
"markforge.config.mjs",
|
|
1145
|
+
"markforge.config.cjs"
|
|
1146
|
+
];
|
|
1147
|
+
var DEFAULT_CONFIG = {
|
|
1148
|
+
to: ["docx", "pdf"],
|
|
1149
|
+
outputDir: void 0,
|
|
1150
|
+
theme: "default",
|
|
1151
|
+
css: void 0,
|
|
1152
|
+
orientation: "portrait",
|
|
1153
|
+
paperSize: "A4",
|
|
1154
|
+
margins: {
|
|
1155
|
+
top: "2.5cm",
|
|
1156
|
+
bottom: "2.5cm",
|
|
1157
|
+
left: "2.5cm",
|
|
1158
|
+
right: "2.5cm"
|
|
1159
|
+
},
|
|
1160
|
+
header: void 0,
|
|
1161
|
+
footer: {
|
|
1162
|
+
right: "Page {page} of {pages}"
|
|
1163
|
+
},
|
|
1164
|
+
toc: false,
|
|
1165
|
+
watermark: void 0,
|
|
1166
|
+
embedImages: true,
|
|
1167
|
+
metadata: void 0,
|
|
1168
|
+
watch: false,
|
|
1169
|
+
serve: false,
|
|
1170
|
+
port: 4e3,
|
|
1171
|
+
open: false,
|
|
1172
|
+
bundleHtml: true,
|
|
1173
|
+
syntaxTheme: "github-dark"
|
|
1174
|
+
};
|
|
1175
|
+
function discoverConfigFile(startDir) {
|
|
1176
|
+
const dirsToCheck = [];
|
|
1177
|
+
let curr = path2.resolve(startDir);
|
|
1178
|
+
while (curr) {
|
|
1179
|
+
dirsToCheck.push(curr);
|
|
1180
|
+
const parent = path2.dirname(curr);
|
|
1181
|
+
if (parent === curr) break;
|
|
1182
|
+
curr = parent;
|
|
1183
|
+
}
|
|
1184
|
+
const cwd = path2.resolve(process.cwd());
|
|
1185
|
+
if (!dirsToCheck.includes(cwd)) {
|
|
1186
|
+
dirsToCheck.push(cwd);
|
|
1187
|
+
}
|
|
1188
|
+
for (const dir of dirsToCheck) {
|
|
1189
|
+
for (const filename of DEFAULT_CONFIG_FILENAMES) {
|
|
1190
|
+
const candidate = path2.join(dir, filename);
|
|
1191
|
+
if (fs2.existsSync(candidate) && fs2.statSync(candidate).isFile()) {
|
|
1192
|
+
return candidate;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
return null;
|
|
1197
|
+
}
|
|
1198
|
+
async function loadConfig(customPath, startDir = process.cwd()) {
|
|
1199
|
+
let resolvedPath = null;
|
|
1200
|
+
if (customPath) {
|
|
1201
|
+
resolvedPath = path2.isAbsolute(customPath) ? customPath : path2.resolve(process.cwd(), customPath);
|
|
1202
|
+
if (!fs2.existsSync(resolvedPath)) {
|
|
1203
|
+
const altPath = path2.resolve(startDir, customPath);
|
|
1204
|
+
if (fs2.existsSync(altPath)) {
|
|
1205
|
+
resolvedPath = altPath;
|
|
1206
|
+
} else {
|
|
1207
|
+
throw new Error(`Configuration file not found: ${resolvedPath}`);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
} else {
|
|
1211
|
+
resolvedPath = discoverConfigFile(startDir);
|
|
1212
|
+
}
|
|
1213
|
+
if (!resolvedPath) {
|
|
1214
|
+
return {
|
|
1215
|
+
config: { ...DEFAULT_CONFIG },
|
|
1216
|
+
configPath: null
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
const ext = path2.extname(resolvedPath).toLowerCase();
|
|
1220
|
+
let userConfig = {};
|
|
1221
|
+
try {
|
|
1222
|
+
if (ext === ".json" || ext === "" || resolvedPath.endsWith(".markforgerc")) {
|
|
1223
|
+
const raw = fs2.readFileSync(resolvedPath, "utf-8").trim();
|
|
1224
|
+
try {
|
|
1225
|
+
userConfig = JSON.parse(raw);
|
|
1226
|
+
} catch {
|
|
1227
|
+
userConfig = YAML.parse(raw) || {};
|
|
1228
|
+
}
|
|
1229
|
+
} else if (ext === ".yaml" || ext === ".yml") {
|
|
1230
|
+
const raw = fs2.readFileSync(resolvedPath, "utf-8");
|
|
1231
|
+
userConfig = YAML.parse(raw) || {};
|
|
1232
|
+
} else if (ext === ".ts" || ext === ".js" || ext === ".mjs" || ext === ".cjs") {
|
|
1233
|
+
try {
|
|
1234
|
+
const fileUrl = `${(0, import_node_url.pathToFileURL)(resolvedPath).href}?t=${Date.now()}`;
|
|
1235
|
+
const mod = await import(fileUrl);
|
|
1236
|
+
const rawExport = mod.default ?? mod.config ?? mod;
|
|
1237
|
+
userConfig = (typeof rawExport === "function" ? await rawExport() : rawExport) || {};
|
|
1238
|
+
} catch (importErr) {
|
|
1239
|
+
try {
|
|
1240
|
+
const mod = require(resolvedPath);
|
|
1241
|
+
const rawExport = mod.default ?? mod.config ?? mod;
|
|
1242
|
+
userConfig = (typeof rawExport === "function" ? await rawExport() : rawExport) || {};
|
|
1243
|
+
} catch {
|
|
1244
|
+
throw importErr;
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
} catch (err) {
|
|
1249
|
+
throw new Error(
|
|
1250
|
+
`Failed to parse configuration file at ${resolvedPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1253
|
+
if (userConfig && typeof userConfig === "object" && "$schema" in userConfig) {
|
|
1254
|
+
delete userConfig.$schema;
|
|
1255
|
+
}
|
|
1256
|
+
const parsedConfig = userConfig;
|
|
1257
|
+
const mergedConfig = {
|
|
1258
|
+
...DEFAULT_CONFIG,
|
|
1259
|
+
...parsedConfig,
|
|
1260
|
+
margins: {
|
|
1261
|
+
...DEFAULT_CONFIG.margins,
|
|
1262
|
+
...parsedConfig.margins || {}
|
|
1263
|
+
},
|
|
1264
|
+
header: parsedConfig.header !== void 0 ? parsedConfig.header : DEFAULT_CONFIG.header,
|
|
1265
|
+
footer: parsedConfig.footer !== void 0 ? parsedConfig.footer : DEFAULT_CONFIG.footer,
|
|
1266
|
+
metadata: {
|
|
1267
|
+
...DEFAULT_CONFIG.metadata || {},
|
|
1268
|
+
...parsedConfig.metadata || {}
|
|
1269
|
+
}
|
|
1270
|
+
};
|
|
1271
|
+
return {
|
|
1272
|
+
config: mergedConfig,
|
|
1273
|
+
configPath: resolvedPath
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// src/config/resolveConfig.ts
|
|
1278
|
+
var PAPER_DIMENSIONS_TWIP = {
|
|
1279
|
+
A4: { width: 11906, height: 16838 },
|
|
1280
|
+
// 210mm x 297mm
|
|
1281
|
+
Letter: { width: 12240, height: 15840 },
|
|
1282
|
+
// 8.5in x 11in
|
|
1283
|
+
Legal: { width: 12240, height: 20160 },
|
|
1284
|
+
// 8.5in x 14in
|
|
1285
|
+
A3: { width: 16838, height: 23811 },
|
|
1286
|
+
// 297mm x 420mm
|
|
1287
|
+
A5: { width: 8390, height: 11906 }
|
|
1288
|
+
// 148mm x 210mm
|
|
1006
1289
|
};
|
|
1290
|
+
function parseMarginToTwip(margin, defaultTwip = 1440) {
|
|
1291
|
+
if (typeof margin === "number") return margin;
|
|
1292
|
+
if (!margin) return defaultTwip;
|
|
1293
|
+
const str = margin.trim().toLowerCase();
|
|
1294
|
+
if (str.endsWith("cm")) {
|
|
1295
|
+
const cm = parseFloat(str);
|
|
1296
|
+
return isNaN(cm) ? defaultTwip : Math.round(cm * 566.929);
|
|
1297
|
+
}
|
|
1298
|
+
if (str.endsWith("mm")) {
|
|
1299
|
+
const mm = parseFloat(str);
|
|
1300
|
+
return isNaN(mm) ? defaultTwip : Math.round(mm * 56.6929);
|
|
1301
|
+
}
|
|
1302
|
+
if (str.endsWith("in") || str.endsWith("inch")) {
|
|
1303
|
+
const inch = parseFloat(str);
|
|
1304
|
+
return isNaN(inch) ? defaultTwip : Math.round(inch * 1440);
|
|
1305
|
+
}
|
|
1306
|
+
if (str.endsWith("pt")) {
|
|
1307
|
+
const pt = parseFloat(str);
|
|
1308
|
+
return isNaN(pt) ? defaultTwip : Math.round(pt * 20);
|
|
1309
|
+
}
|
|
1310
|
+
const val = parseFloat(str);
|
|
1311
|
+
return isNaN(val) ? defaultTwip : Math.round(val);
|
|
1312
|
+
}
|
|
1313
|
+
function formatMarginCss(margin, defaultCss = "2.5cm") {
|
|
1314
|
+
if (margin === void 0 || margin === null) return defaultCss;
|
|
1315
|
+
if (typeof margin === "number") return `${margin}pt`;
|
|
1316
|
+
const str = margin.trim();
|
|
1317
|
+
if (!str) return defaultCss;
|
|
1318
|
+
if (/^[0-9.]+$/.test(str)) return `${str}pt`;
|
|
1319
|
+
return str;
|
|
1320
|
+
}
|
|
1321
|
+
function replaceDocumentTokens(template = "", meta) {
|
|
1322
|
+
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 || "");
|
|
1323
|
+
}
|
|
1324
|
+
function normalizeWatermark(rawWatermark) {
|
|
1325
|
+
if (!rawWatermark) {
|
|
1326
|
+
return void 0;
|
|
1327
|
+
}
|
|
1328
|
+
if (typeof rawWatermark === "string") {
|
|
1329
|
+
const text = rawWatermark.trim();
|
|
1330
|
+
if (!text) return void 0;
|
|
1331
|
+
return {
|
|
1332
|
+
text,
|
|
1333
|
+
color: "#94a3b8",
|
|
1334
|
+
opacity: 0.08,
|
|
1335
|
+
fontSize: 54,
|
|
1336
|
+
rotate: -45,
|
|
1337
|
+
position: "diagonal"
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
if (typeof rawWatermark === "object") {
|
|
1341
|
+
if (!rawWatermark.text || !rawWatermark.text.trim()) return void 0;
|
|
1342
|
+
return {
|
|
1343
|
+
text: rawWatermark.text.trim(),
|
|
1344
|
+
color: rawWatermark.color || "#94a3b8",
|
|
1345
|
+
opacity: typeof rawWatermark.opacity === "number" ? rawWatermark.opacity : 0.08,
|
|
1346
|
+
fontSize: rawWatermark.fontSize || 54,
|
|
1347
|
+
rotate: typeof rawWatermark.rotate === "number" ? rawWatermark.rotate : -45,
|
|
1348
|
+
position: rawWatermark.position || "diagonal"
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
return void 0;
|
|
1352
|
+
}
|
|
1353
|
+
function normalizeHeaderFooterSlot(rawSlot, parent, meta) {
|
|
1354
|
+
if (!rawSlot) return void 0;
|
|
1355
|
+
if (typeof rawSlot === "string") {
|
|
1356
|
+
const text = replaceDocumentTokens(rawSlot, meta).trim();
|
|
1357
|
+
if (!text) return void 0;
|
|
1358
|
+
return {
|
|
1359
|
+
text,
|
|
1360
|
+
color: (parent == null ? void 0 : parent.color) || "#94A3B8",
|
|
1361
|
+
fontSize: (parent == null ? void 0 : parent.size) || 9,
|
|
1362
|
+
fontFamily: (parent == null ? void 0 : parent.font) || "Segoe UI",
|
|
1363
|
+
bold: false,
|
|
1364
|
+
italic: false
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
if (typeof rawSlot === "object") {
|
|
1368
|
+
const text = replaceDocumentTokens(rawSlot.text || "", meta).trim();
|
|
1369
|
+
if (!text) return void 0;
|
|
1370
|
+
return {
|
|
1371
|
+
text,
|
|
1372
|
+
color: rawSlot.color || (parent == null ? void 0 : parent.color) || "#94A3B8",
|
|
1373
|
+
fontSize: rawSlot.fontSize || (parent == null ? void 0 : parent.size) || 9,
|
|
1374
|
+
fontFamily: rawSlot.fontFamily || (parent == null ? void 0 : parent.font) || "Segoe UI",
|
|
1375
|
+
bold: Boolean(rawSlot.bold),
|
|
1376
|
+
italic: Boolean(rawSlot.italic)
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
return void 0;
|
|
1380
|
+
}
|
|
1381
|
+
function normalizeHeaderFooter(raw, meta) {
|
|
1382
|
+
if (!raw) return void 0;
|
|
1383
|
+
const left = normalizeHeaderFooterSlot(raw.left, raw, meta);
|
|
1384
|
+
const center = normalizeHeaderFooterSlot(raw.center, raw, meta);
|
|
1385
|
+
const right = normalizeHeaderFooterSlot(raw.right, raw, meta);
|
|
1386
|
+
if (!left && !center && !right) return void 0;
|
|
1387
|
+
return {
|
|
1388
|
+
left,
|
|
1389
|
+
center,
|
|
1390
|
+
right,
|
|
1391
|
+
font: raw.font || "Segoe UI",
|
|
1392
|
+
size: raw.size || 9,
|
|
1393
|
+
color: raw.color || "#94A3B8",
|
|
1394
|
+
divider: Boolean(raw.divider),
|
|
1395
|
+
dividerColor: raw.dividerColor || "#E2E8F0"
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
function resolveDocumentConfig(frontmatter = {}, userConfig = {}) {
|
|
1399
|
+
const configMeta = userConfig.metadata || {};
|
|
1400
|
+
const mergedMeta = { ...configMeta, ...frontmatter };
|
|
1401
|
+
const title = mergedMeta.title || "MarkForge Document";
|
|
1402
|
+
const subtitle = mergedMeta.subtitle || void 0;
|
|
1403
|
+
const author = Array.isArray(mergedMeta.author) ? mergedMeta.author.join(", ") : mergedMeta.author || void 0;
|
|
1404
|
+
const date = mergedMeta.date || void 0;
|
|
1405
|
+
const version = mergedMeta.version || void 0;
|
|
1406
|
+
const company = mergedMeta.company || void 0;
|
|
1407
|
+
const lang = mergedMeta.lang || "en";
|
|
1408
|
+
const tokenContext = { title, subtitle, author, version, date, company };
|
|
1409
|
+
const theme = mergedMeta.theme || userConfig.theme || DEFAULT_CONFIG.theme;
|
|
1410
|
+
const orientation = mergedMeta.orientation || userConfig.orientation || DEFAULT_CONFIG.orientation;
|
|
1411
|
+
const paperSize = mergedMeta.paperSize || userConfig.paperSize || DEFAULT_CONFIG.paperSize;
|
|
1412
|
+
const baseDim = PAPER_DIMENSIONS_TWIP[paperSize] || PAPER_DIMENSIONS_TWIP.A4;
|
|
1413
|
+
const paperDimensions = orientation === "landscape" ? { widthTwip: baseDim.height, heightTwip: baseDim.width } : { widthTwip: baseDim.width, heightTwip: baseDim.height };
|
|
1414
|
+
const fmMargin = mergedMeta.margins || {};
|
|
1415
|
+
const cfgMargin = userConfig.margins || {};
|
|
1416
|
+
const defMargin = DEFAULT_CONFIG.margins || {};
|
|
1417
|
+
const topRaw = fmMargin.top ?? cfgMargin.top ?? defMargin.top ?? "2.5cm";
|
|
1418
|
+
const bottomRaw = fmMargin.bottom ?? cfgMargin.bottom ?? defMargin.bottom ?? "2.5cm";
|
|
1419
|
+
const leftRaw = fmMargin.left ?? cfgMargin.left ?? defMargin.left ?? "2.5cm";
|
|
1420
|
+
const rightRaw = fmMargin.right ?? cfgMargin.right ?? defMargin.right ?? "2.5cm";
|
|
1421
|
+
const margins = {
|
|
1422
|
+
top: formatMarginCss(topRaw),
|
|
1423
|
+
bottom: formatMarginCss(bottomRaw),
|
|
1424
|
+
left: formatMarginCss(leftRaw),
|
|
1425
|
+
right: formatMarginCss(rightRaw),
|
|
1426
|
+
topTwip: parseMarginToTwip(topRaw),
|
|
1427
|
+
bottomTwip: parseMarginToTwip(bottomRaw),
|
|
1428
|
+
leftTwip: parseMarginToTwip(leftRaw),
|
|
1429
|
+
rightTwip: parseMarginToTwip(rightRaw)
|
|
1430
|
+
};
|
|
1431
|
+
const rawHeader = mergedMeta.header || userConfig.header || DEFAULT_CONFIG.header;
|
|
1432
|
+
const rawFooter = mergedMeta.footer || userConfig.footer || DEFAULT_CONFIG.footer;
|
|
1433
|
+
const header = normalizeHeaderFooter(rawHeader, tokenContext);
|
|
1434
|
+
const footer = normalizeHeaderFooter(rawFooter, tokenContext);
|
|
1435
|
+
const toc = typeof mergedMeta.toc === "boolean" ? mergedMeta.toc : typeof userConfig.toc === "boolean" ? userConfig.toc : DEFAULT_CONFIG.toc;
|
|
1436
|
+
const rawWatermark = mergedMeta.watermark !== void 0 ? mergedMeta.watermark : userConfig.watermark !== void 0 ? userConfig.watermark : DEFAULT_CONFIG.watermark;
|
|
1437
|
+
const watermark = normalizeWatermark(rawWatermark);
|
|
1438
|
+
const cssList = [];
|
|
1439
|
+
const addCss = (item) => {
|
|
1440
|
+
if (!item) return;
|
|
1441
|
+
if (Array.isArray(item)) cssList.push(...item);
|
|
1442
|
+
else cssList.push(item);
|
|
1443
|
+
};
|
|
1444
|
+
addCss(userConfig.css);
|
|
1445
|
+
addCss(mergedMeta.css);
|
|
1446
|
+
const embedImages = typeof userConfig.embedImages === "boolean" ? userConfig.embedImages : DEFAULT_CONFIG.embedImages;
|
|
1447
|
+
const bundleHtml = typeof userConfig.bundleHtml === "boolean" ? userConfig.bundleHtml : DEFAULT_CONFIG.bundleHtml;
|
|
1448
|
+
const syntaxTheme = userConfig.syntaxTheme || DEFAULT_CONFIG.syntaxTheme || "github-dark";
|
|
1449
|
+
return {
|
|
1450
|
+
title,
|
|
1451
|
+
subtitle,
|
|
1452
|
+
author,
|
|
1453
|
+
date,
|
|
1454
|
+
version,
|
|
1455
|
+
company,
|
|
1456
|
+
lang,
|
|
1457
|
+
theme,
|
|
1458
|
+
orientation,
|
|
1459
|
+
paperSize,
|
|
1460
|
+
paperDimensions,
|
|
1461
|
+
margins,
|
|
1462
|
+
header,
|
|
1463
|
+
footer,
|
|
1464
|
+
toc,
|
|
1465
|
+
watermark,
|
|
1466
|
+
css: cssList,
|
|
1467
|
+
embedImages,
|
|
1468
|
+
bundleHtml,
|
|
1469
|
+
syntaxTheme
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1007
1472
|
|
|
1008
1473
|
// src/core/html/htmlBuilder.ts
|
|
1009
1474
|
function escapeHtml(str) {
|
|
@@ -1056,43 +1521,41 @@ async function renderInlinesToHtml(spans = [], baseDir = process.cwd()) {
|
|
|
1056
1521
|
return result;
|
|
1057
1522
|
}
|
|
1058
1523
|
async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
1059
|
-
|
|
1060
|
-
const
|
|
1061
|
-
const themeName = metadata.theme || config.theme || "default";
|
|
1062
|
-
const baseThemeCss = THEMES[themeName] || THEMES.default;
|
|
1524
|
+
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
1525
|
+
const baseThemeCss = generateThemeCss(resolved.theme);
|
|
1063
1526
|
let customCss = "";
|
|
1064
|
-
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
if (fs2.existsSync(fullCssPath)) {
|
|
1069
|
-
customCss += `
|
|
1527
|
+
for (const cssPath of resolved.css) {
|
|
1528
|
+
const fullCssPath = path3.isAbsolute(cssPath) ? cssPath : path3.resolve(baseDir, cssPath);
|
|
1529
|
+
if (fs3.existsSync(fullCssPath)) {
|
|
1530
|
+
customCss += `
|
|
1070
1531
|
/* Custom CSS: ${cssPath} */
|
|
1071
|
-
` +
|
|
1072
|
-
}
|
|
1532
|
+
` + fs3.readFileSync(fullCssPath, "utf-8");
|
|
1073
1533
|
}
|
|
1074
1534
|
}
|
|
1075
1535
|
const inlinedCss = doc.inlinedStyles.join("\n");
|
|
1076
1536
|
let bodyHtml = "";
|
|
1077
|
-
if (
|
|
1537
|
+
if (resolved.title) {
|
|
1078
1538
|
bodyHtml += ` <header class="document-header">
|
|
1079
1539
|
`;
|
|
1080
|
-
bodyHtml += ` <h1 class="document-title">${escapeHtml(
|
|
1540
|
+
bodyHtml += ` <h1 class="document-title">${escapeHtml(resolved.title)}</h1>
|
|
1081
1541
|
`;
|
|
1082
|
-
if (
|
|
1083
|
-
bodyHtml += ` <div class="document-subtitle">${escapeHtml(
|
|
1542
|
+
if (resolved.subtitle) {
|
|
1543
|
+
bodyHtml += ` <div class="document-subtitle">${escapeHtml(resolved.subtitle)}</div>
|
|
1084
1544
|
`;
|
|
1085
1545
|
}
|
|
1086
|
-
if (
|
|
1546
|
+
if (resolved.author || resolved.date || resolved.version) {
|
|
1087
1547
|
bodyHtml += ` <div class="document-meta">
|
|
1088
1548
|
`;
|
|
1089
|
-
if (
|
|
1090
|
-
|
|
1091
|
-
|
|
1549
|
+
if (resolved.author) {
|
|
1550
|
+
bodyHtml += ` <span>Author: ${escapeHtml(resolved.author)}</span>
|
|
1551
|
+
`;
|
|
1552
|
+
}
|
|
1553
|
+
if (resolved.version) {
|
|
1554
|
+
bodyHtml += ` <span>Version: ${escapeHtml(resolved.version)}</span>
|
|
1092
1555
|
`;
|
|
1093
1556
|
}
|
|
1094
|
-
if (
|
|
1095
|
-
bodyHtml += ` <span>Date: ${escapeHtml(
|
|
1557
|
+
if (resolved.date) {
|
|
1558
|
+
bodyHtml += ` <span>Date: ${escapeHtml(resolved.date)}</span>
|
|
1096
1559
|
`;
|
|
1097
1560
|
}
|
|
1098
1561
|
bodyHtml += ` </div>
|
|
@@ -1101,22 +1564,20 @@ async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1101
1564
|
bodyHtml += ` </header>
|
|
1102
1565
|
`;
|
|
1103
1566
|
}
|
|
1104
|
-
if (
|
|
1105
|
-
|
|
1106
|
-
bodyHtml += ` <nav class="table-of-contents">
|
|
1567
|
+
if (resolved.toc && doc.tocEntries.length > 0) {
|
|
1568
|
+
bodyHtml += ` <nav class="table-of-contents">
|
|
1107
1569
|
`;
|
|
1108
|
-
|
|
1570
|
+
bodyHtml += ` <h2>Table of Contents</h2>
|
|
1109
1571
|
<ul>
|
|
1110
1572
|
`;
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1573
|
+
for (const entry of doc.tocEntries) {
|
|
1574
|
+
const indent = " ".repeat(entry.level);
|
|
1575
|
+
bodyHtml += ` ${indent}<li><a href="#${entry.id}">${escapeHtml(entry.text)}</a></li>
|
|
1114
1576
|
`;
|
|
1115
|
-
|
|
1116
|
-
|
|
1577
|
+
}
|
|
1578
|
+
bodyHtml += ` </ul>
|
|
1117
1579
|
</nav>
|
|
1118
1580
|
`;
|
|
1119
|
-
}
|
|
1120
1581
|
}
|
|
1121
1582
|
for (const node of doc.nodes) {
|
|
1122
1583
|
if (node.type === "heading") {
|
|
@@ -1134,7 +1595,7 @@ async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1134
1595
|
if (node.type === "codeBlock") {
|
|
1135
1596
|
const lang = node.language || "";
|
|
1136
1597
|
const langClass = lang ? ` class="language-${escapeHtml(lang)}"` : "";
|
|
1137
|
-
const highlighted = highlightCodeToHtml(node.text || "", lang);
|
|
1598
|
+
const highlighted = highlightCodeToHtml(node.text || "", lang, resolved.syntaxTheme);
|
|
1138
1599
|
bodyHtml += ` <pre><code${langClass}>${highlighted}</code></pre>
|
|
1139
1600
|
`;
|
|
1140
1601
|
continue;
|
|
@@ -1178,15 +1639,12 @@ ${escapeHtml(node.text || "")}
|
|
|
1178
1639
|
for (const row of node.children) {
|
|
1179
1640
|
bodyHtml += ` <tr>
|
|
1180
1641
|
`;
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
const cellInner = await renderInlinesToHtml(cell.inlines, baseDir);
|
|
1187
|
-
bodyHtml += ` <${tag}${align}>${cellInner}</${tag}>
|
|
1642
|
+
for (const cell of row.children || []) {
|
|
1643
|
+
const tag = cell.isHeader ? "th" : "td";
|
|
1644
|
+
const align = cell.align ? ` align="${cell.align}"` : "";
|
|
1645
|
+
const inner = await renderInlinesToHtml(cell.inlines, baseDir);
|
|
1646
|
+
bodyHtml += ` <${tag}${align}>${inner}</${tag}>
|
|
1188
1647
|
`;
|
|
1189
|
-
}
|
|
1190
1648
|
}
|
|
1191
1649
|
bodyHtml += ` </tr>
|
|
1192
1650
|
`;
|
|
@@ -1200,57 +1658,52 @@ ${escapeHtml(node.text || "")}
|
|
|
1200
1658
|
bodyHtml += ` <${tag}>
|
|
1201
1659
|
`;
|
|
1202
1660
|
for (const item of node.children) {
|
|
1203
|
-
const
|
|
1204
|
-
|
|
1205
|
-
if (item.checked !== void 0) {
|
|
1206
|
-
prefix = `<input type="checkbox" disabled ${item.checked ? "checked" : ""}/> `;
|
|
1207
|
-
}
|
|
1208
|
-
bodyHtml += ` <li>${prefix}${itemInner}</li>
|
|
1661
|
+
const inner = await renderInlinesToHtml(item.inlines, baseDir);
|
|
1662
|
+
bodyHtml += ` <li>${inner}</li>
|
|
1209
1663
|
`;
|
|
1210
1664
|
}
|
|
1211
1665
|
bodyHtml += ` </${tag}>
|
|
1212
1666
|
`;
|
|
1213
1667
|
continue;
|
|
1214
1668
|
}
|
|
1215
|
-
if (node.type === "
|
|
1216
|
-
bodyHtml += `
|
|
1669
|
+
if (node.type === "thematicBreak") {
|
|
1670
|
+
bodyHtml += ` <hr />
|
|
1217
1671
|
`;
|
|
1218
1672
|
continue;
|
|
1219
1673
|
}
|
|
1220
|
-
if (node.type === "
|
|
1221
|
-
bodyHtml += `
|
|
1674
|
+
if (node.type === "htmlBlock") {
|
|
1675
|
+
bodyHtml += ` ${node.text}
|
|
1222
1676
|
`;
|
|
1223
1677
|
continue;
|
|
1224
1678
|
}
|
|
1225
1679
|
}
|
|
1226
|
-
const wmConfig = config.watermark ?? metadata.watermark;
|
|
1227
|
-
let watermarkHtml = "";
|
|
1228
1680
|
let watermarkCss = "";
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
const
|
|
1232
|
-
const rotate = typeof wmConfig === "object" && wmConfig.rotate !== void 0 ? wmConfig.rotate : -45;
|
|
1233
|
-
const color = typeof wmConfig === "object" && wmConfig.color ? wmConfig.color : "#94A3B8";
|
|
1234
|
-
const fontSize = typeof wmConfig === "object" && wmConfig.fontSize ? `${wmConfig.fontSize}pt` : "52pt";
|
|
1681
|
+
let watermarkHtml = "";
|
|
1682
|
+
if (resolved.watermark) {
|
|
1683
|
+
const wm = resolved.watermark;
|
|
1235
1684
|
watermarkCss = `
|
|
1236
1685
|
.document-watermark {
|
|
1237
1686
|
position: fixed;
|
|
1238
1687
|
top: 50%;
|
|
1239
1688
|
left: 50%;
|
|
1240
|
-
transform: translate(-50%, -50%) rotate(${rotate}deg);
|
|
1241
|
-
font-size: ${fontSize};
|
|
1242
|
-
font-weight:
|
|
1243
|
-
color: ${color};
|
|
1244
|
-
opacity: ${opacity};
|
|
1689
|
+
transform: translate(-50%, -50%) rotate(${wm.rotate}deg);
|
|
1690
|
+
font-size: ${wm.fontSize}pt;
|
|
1691
|
+
font-weight: 900;
|
|
1692
|
+
color: ${wm.color};
|
|
1693
|
+
opacity: ${wm.opacity};
|
|
1245
1694
|
pointer-events: none;
|
|
1695
|
+
z-index: 0;
|
|
1246
1696
|
user-select: none;
|
|
1247
|
-
z-index: 9999;
|
|
1248
1697
|
text-transform: uppercase;
|
|
1249
1698
|
letter-spacing: 0.15em;
|
|
1250
1699
|
white-space: nowrap;
|
|
1251
1700
|
}
|
|
1701
|
+
.document-container {
|
|
1702
|
+
position: relative;
|
|
1703
|
+
z-index: 1;
|
|
1704
|
+
}
|
|
1252
1705
|
`;
|
|
1253
|
-
watermarkHtml = ` <div class="document-watermark">${escapeHtml(
|
|
1706
|
+
watermarkHtml = ` <div class="document-watermark">${escapeHtml(wm.text)}</div>
|
|
1254
1707
|
`;
|
|
1255
1708
|
}
|
|
1256
1709
|
const hasMermaid = doc.nodes.some((n) => n.type === "mermaid");
|
|
@@ -1269,13 +1722,12 @@ ${escapeHtml(node.text || "")}
|
|
|
1269
1722
|
}
|
|
1270
1723
|
});
|
|
1271
1724
|
</script>` : "";
|
|
1272
|
-
const documentTitle = metadata.title || "MarkForge Document";
|
|
1273
1725
|
return `<!DOCTYPE html>
|
|
1274
|
-
<html lang="${
|
|
1726
|
+
<html lang="${resolved.lang}">
|
|
1275
1727
|
<head>
|
|
1276
1728
|
<meta charset="UTF-8">
|
|
1277
1729
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1278
|
-
<title>${escapeHtml(
|
|
1730
|
+
<title>${escapeHtml(resolved.title)}</title>
|
|
1279
1731
|
<style>
|
|
1280
1732
|
${THEME_COMPONENTS}
|
|
1281
1733
|
${baseThemeCss}
|
|
@@ -1294,10 +1746,10 @@ ${bodyHtml} </div>
|
|
|
1294
1746
|
|
|
1295
1747
|
// src/core/pdf/pdfBuilder.ts
|
|
1296
1748
|
function findChromeExecutable() {
|
|
1297
|
-
if (process.env.CHROME_PATH &&
|
|
1749
|
+
if (process.env.CHROME_PATH && fs4.existsSync(process.env.CHROME_PATH)) {
|
|
1298
1750
|
return process.env.CHROME_PATH;
|
|
1299
1751
|
}
|
|
1300
|
-
if (process.env.PUPPETEER_EXECUTABLE_PATH &&
|
|
1752
|
+
if (process.env.PUPPETEER_EXECUTABLE_PATH && fs4.existsSync(process.env.PUPPETEER_EXECUTABLE_PATH)) {
|
|
1301
1753
|
return process.env.PUPPETEER_EXECUTABLE_PATH;
|
|
1302
1754
|
}
|
|
1303
1755
|
const isWin = process.platform === "win32";
|
|
@@ -1319,14 +1771,14 @@ function findChromeExecutable() {
|
|
|
1319
1771
|
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
1320
1772
|
"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
|
|
1321
1773
|
"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
|
|
1774
|
+
// Windows — Microsoft Edge (Native Windows 10/11 browser, enterprise whitelist friendly)
|
|
1775
|
+
`${winProgramFiles}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1776
|
+
`${winProgramFilesX86}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1777
|
+
`${winLocalAppData}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1322
1778
|
// Windows — Google Chrome
|
|
1323
1779
|
`${winProgramFiles}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1324
1780
|
`${winProgramFilesX86}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1325
1781
|
`${winLocalAppData}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1326
|
-
// Windows — Microsoft Edge (ships with Windows 10/11)
|
|
1327
|
-
`${winProgramFiles}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1328
|
-
`${winProgramFilesX86}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1329
|
-
`${winLocalAppData}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1330
1782
|
// Windows — Brave Browser
|
|
1331
1783
|
`${winProgramFiles}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
1332
1784
|
`${winProgramFilesX86}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
@@ -1336,7 +1788,7 @@ function findChromeExecutable() {
|
|
|
1336
1788
|
].filter(Boolean);
|
|
1337
1789
|
for (const candidate of candidates) {
|
|
1338
1790
|
try {
|
|
1339
|
-
if (
|
|
1791
|
+
if (fs4.existsSync(candidate)) {
|
|
1340
1792
|
return candidate;
|
|
1341
1793
|
}
|
|
1342
1794
|
} catch {
|
|
@@ -1349,7 +1801,7 @@ function findChromeExecutable() {
|
|
|
1349
1801
|
const res = (0, import_node_child_process.spawnSync)(cmd, [name], { encoding: "utf-8" });
|
|
1350
1802
|
if (res.status === 0 && res.stdout.trim()) {
|
|
1351
1803
|
const binPath = res.stdout.split(/\r?\n/)[0].trim();
|
|
1352
|
-
if (
|
|
1804
|
+
if (fs4.existsSync(binPath)) return binPath;
|
|
1353
1805
|
}
|
|
1354
1806
|
}
|
|
1355
1807
|
} catch {
|
|
@@ -1357,22 +1809,50 @@ function findChromeExecutable() {
|
|
|
1357
1809
|
return null;
|
|
1358
1810
|
}
|
|
1359
1811
|
function injectPagedMediaStyles(html, config, metadata) {
|
|
1360
|
-
var _a, _b, _c, _d;
|
|
1361
|
-
const
|
|
1362
|
-
const
|
|
1363
|
-
const
|
|
1364
|
-
const
|
|
1365
|
-
const
|
|
1366
|
-
const
|
|
1367
|
-
const
|
|
1368
|
-
const
|
|
1369
|
-
const
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1812
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1813
|
+
const resolved = resolveDocumentConfig(metadata || {}, config);
|
|
1814
|
+
const size = resolved.paperSize;
|
|
1815
|
+
const orientation = resolved.orientation;
|
|
1816
|
+
const top = resolved.margins.top;
|
|
1817
|
+
const bottom = resolved.margins.bottom;
|
|
1818
|
+
const left = resolved.margins.left;
|
|
1819
|
+
const right = resolved.margins.right;
|
|
1820
|
+
const esc = (s) => s.replace(/"/g, '\\"').replace(/\\/g, "\\\\");
|
|
1821
|
+
const buildZoneCss = (pos, zone, isPageCounter = false) => {
|
|
1822
|
+
if (!zone && !isPageCounter) return "";
|
|
1823
|
+
const color = (zone == null ? void 0 : zone.color) || "#94a3b8";
|
|
1824
|
+
const fontSize = (zone == null ? void 0 : zone.fontSize) ? `${zone.fontSize}pt` : "9pt";
|
|
1825
|
+
const fontFamily = (zone == null ? void 0 : zone.fontFamily) ? `font-family: ${zone.fontFamily};` : "";
|
|
1826
|
+
const fontWeight = (zone == null ? void 0 : zone.bold) ? "font-weight: bold;" : "";
|
|
1827
|
+
const fontStyle = (zone == null ? void 0 : zone.italic) ? "font-style: italic;" : "";
|
|
1828
|
+
let content = "";
|
|
1829
|
+
if (isPageCounter) {
|
|
1830
|
+
if ((zone == null ? void 0 : zone.text) && (zone.text.includes("{page}") || zone.text.includes("{pages}"))) {
|
|
1831
|
+
const parts = zone.text.split(/(\{page\}|\{pages\})/gi);
|
|
1832
|
+
const cssParts = parts.map((part) => {
|
|
1833
|
+
if (part.toLowerCase() === "{page}") return "counter(page)";
|
|
1834
|
+
if (part.toLowerCase() === "{pages}") return "counter(pages)";
|
|
1835
|
+
return `"${esc(part)}"`;
|
|
1836
|
+
});
|
|
1837
|
+
content = cssParts.join(" ");
|
|
1838
|
+
} else if (zone == null ? void 0 : zone.text) {
|
|
1839
|
+
content = `"${esc(zone.text)}"`;
|
|
1840
|
+
} else {
|
|
1841
|
+
content = `"Page " counter(page) " of " counter(pages)`;
|
|
1842
|
+
}
|
|
1843
|
+
} else if (zone == null ? void 0 : zone.text) {
|
|
1844
|
+
content = `"${esc(zone.text)}"`;
|
|
1845
|
+
}
|
|
1846
|
+
if (!content) return "";
|
|
1847
|
+
return `@${pos} {
|
|
1848
|
+
content: ${content};
|
|
1849
|
+
font-size: ${fontSize};
|
|
1850
|
+
color: ${color};
|
|
1851
|
+
${fontFamily}
|
|
1852
|
+
${fontWeight}
|
|
1853
|
+
${fontStyle}
|
|
1854
|
+
}`;
|
|
1855
|
+
};
|
|
1376
1856
|
const pagedCss = `
|
|
1377
1857
|
@page {
|
|
1378
1858
|
size: ${size} ${orientation};
|
|
@@ -1380,15 +1860,12 @@ function injectPagedMediaStyles(html, config, metadata) {
|
|
|
1380
1860
|
margin-bottom: ${bottom};
|
|
1381
1861
|
margin-left: ${left};
|
|
1382
1862
|
margin-right: ${right};
|
|
1383
|
-
${
|
|
1384
|
-
${
|
|
1385
|
-
${
|
|
1386
|
-
${
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
font-size: 9pt;
|
|
1390
|
-
color: #94a3b8;
|
|
1391
|
-
}
|
|
1863
|
+
${buildZoneCss("top-left", (_a = resolved.header) == null ? void 0 : _a.left)}
|
|
1864
|
+
${buildZoneCss("top-center", (_b = resolved.header) == null ? void 0 : _b.center)}
|
|
1865
|
+
${buildZoneCss("top-right", (_c = resolved.header) == null ? void 0 : _c.right)}
|
|
1866
|
+
${buildZoneCss("bottom-left", (_d = resolved.footer) == null ? void 0 : _d.left)}
|
|
1867
|
+
${buildZoneCss("bottom-center", (_e = resolved.footer) == null ? void 0 : _e.center)}
|
|
1868
|
+
${buildZoneCss("bottom-right", (_f = resolved.footer) == null ? void 0 : _f.right, true)}
|
|
1392
1869
|
}
|
|
1393
1870
|
@media print {
|
|
1394
1871
|
body { padding: 0; }
|
|
@@ -1445,56 +1922,72 @@ async function buildPdfDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1445
1922
|
if (chromePath) {
|
|
1446
1923
|
const tmpId = Math.random().toString(36).substring(2, 9);
|
|
1447
1924
|
const tmpDir = os.tmpdir();
|
|
1448
|
-
const tmpHtml =
|
|
1449
|
-
const tmpPdf =
|
|
1925
|
+
const tmpHtml = path4.join(tmpDir, `markforge_${tmpId}.html`);
|
|
1926
|
+
const tmpPdf = path4.join(tmpDir, `markforge_${tmpId}.pdf`);
|
|
1927
|
+
const tmpProfile = path4.join(tmpDir, `markforge_prof_${tmpId}`);
|
|
1928
|
+
const isolatedFlags = [
|
|
1929
|
+
`--user-data-dir=${tmpProfile}`,
|
|
1930
|
+
"--no-first-run",
|
|
1931
|
+
"--no-default-browser-check",
|
|
1932
|
+
"--disable-sync",
|
|
1933
|
+
"--disable-background-networking",
|
|
1934
|
+
"--disable-component-update",
|
|
1935
|
+
"--disable-default-apps",
|
|
1936
|
+
"--disable-extensions",
|
|
1937
|
+
"--disable-domain-reliability",
|
|
1938
|
+
"--disable-client-side-phishing-detection",
|
|
1939
|
+
"--disable-breakpad",
|
|
1940
|
+
"--disable-component-extensions-with-background-pages",
|
|
1941
|
+
"--disable-features=Translate,OptimizationHints,MediaRouter,DialMediaRouteProvider,CalculatedNewTabPage,ChromeWhatsNewUI,PrivacySandboxSettings4",
|
|
1942
|
+
"--password-store=basic",
|
|
1943
|
+
"--use-mock-keychain",
|
|
1944
|
+
"--mute-audio",
|
|
1945
|
+
"--no-service-autorun",
|
|
1946
|
+
"--disable-gpu",
|
|
1947
|
+
"--no-sandbox",
|
|
1948
|
+
"--disable-setuid-sandbox",
|
|
1949
|
+
"--allow-file-access-from-files",
|
|
1950
|
+
"--disable-web-security",
|
|
1951
|
+
"--force-color-profile=srgb",
|
|
1952
|
+
"--no-pdf-header-footer"
|
|
1953
|
+
];
|
|
1450
1954
|
try {
|
|
1451
|
-
|
|
1452
|
-
const fileUrl = (0,
|
|
1955
|
+
fs4.writeFileSync(tmpHtml, pagedHtml, "utf-8");
|
|
1956
|
+
const fileUrl = (0, import_node_url2.pathToFileURL)(tmpHtml).href;
|
|
1453
1957
|
let res = (0, import_node_child_process.spawnSync)(
|
|
1454
1958
|
chromePath,
|
|
1455
1959
|
[
|
|
1456
1960
|
"--headless=new",
|
|
1457
|
-
|
|
1458
|
-
"--no-sandbox",
|
|
1459
|
-
"--disable-setuid-sandbox",
|
|
1460
|
-
"--allow-file-access-from-files",
|
|
1461
|
-
"--disable-web-security",
|
|
1462
|
-
"--force-color-profile=srgb",
|
|
1961
|
+
...isolatedFlags,
|
|
1463
1962
|
"--run-all-compositor-stages-before-draw",
|
|
1464
1963
|
"--virtual-time-budget=8000",
|
|
1465
|
-
"--no-pdf-header-footer",
|
|
1466
1964
|
`--print-to-pdf=${tmpPdf}`,
|
|
1467
1965
|
fileUrl
|
|
1468
1966
|
],
|
|
1469
1967
|
{ timeout: 3e4 }
|
|
1470
1968
|
);
|
|
1471
|
-
if ((res.status !== 0 || !
|
|
1969
|
+
if ((res.status !== 0 || !fs4.existsSync(tmpPdf)) && chromePath) {
|
|
1472
1970
|
res = (0, import_node_child_process.spawnSync)(
|
|
1473
1971
|
chromePath,
|
|
1474
1972
|
[
|
|
1475
1973
|
"--headless",
|
|
1476
|
-
|
|
1477
|
-
"--no-sandbox",
|
|
1478
|
-
"--disable-setuid-sandbox",
|
|
1479
|
-
"--allow-file-access-from-files",
|
|
1480
|
-
"--disable-web-security",
|
|
1481
|
-
"--force-color-profile=srgb",
|
|
1482
|
-
"--no-pdf-header-footer",
|
|
1974
|
+
...isolatedFlags,
|
|
1483
1975
|
`--print-to-pdf=${tmpPdf}`,
|
|
1484
1976
|
fileUrl
|
|
1485
1977
|
],
|
|
1486
1978
|
{ timeout: 3e4 }
|
|
1487
1979
|
);
|
|
1488
1980
|
}
|
|
1489
|
-
if (
|
|
1490
|
-
const pdfBuffer =
|
|
1981
|
+
if (fs4.existsSync(tmpPdf) && fs4.statSync(tmpPdf).size > 0) {
|
|
1982
|
+
const pdfBuffer = fs4.readFileSync(tmpPdf);
|
|
1491
1983
|
return pdfBuffer;
|
|
1492
1984
|
}
|
|
1493
1985
|
} catch {
|
|
1494
1986
|
} finally {
|
|
1495
1987
|
try {
|
|
1496
|
-
if (
|
|
1497
|
-
if (
|
|
1988
|
+
if (fs4.existsSync(tmpHtml)) fs4.unlinkSync(tmpHtml);
|
|
1989
|
+
if (fs4.existsSync(tmpPdf)) fs4.unlinkSync(tmpPdf);
|
|
1990
|
+
if (fs4.existsSync(tmpProfile)) fs4.rmSync(tmpProfile, { recursive: true, force: true });
|
|
1498
1991
|
} catch {
|
|
1499
1992
|
}
|
|
1500
1993
|
}
|
|
@@ -1510,8 +2003,8 @@ async function renderMermaidToPng(mermaidCode, _baseDir = process.cwd()) {
|
|
|
1510
2003
|
}
|
|
1511
2004
|
const tmpId = Math.random().toString(36).substring(2, 9);
|
|
1512
2005
|
const tmpDir = os2.tmpdir();
|
|
1513
|
-
const tmpHtml =
|
|
1514
|
-
const tmpScreenshot =
|
|
2006
|
+
const tmpHtml = path5.join(tmpDir, `mermaid_${tmpId}.html`);
|
|
2007
|
+
const tmpScreenshot = path5.join(tmpDir, `mermaid_${tmpId}.png`);
|
|
1515
2008
|
const htmlContent = `<!DOCTYPE html>
|
|
1516
2009
|
<html>
|
|
1517
2010
|
<head>
|
|
@@ -1550,8 +2043,8 @@ ${mermaidCode}
|
|
|
1550
2043
|
</body>
|
|
1551
2044
|
</html>`;
|
|
1552
2045
|
try {
|
|
1553
|
-
|
|
1554
|
-
const fileUrl = (0,
|
|
2046
|
+
fs5.writeFileSync(tmpHtml, htmlContent, "utf-8");
|
|
2047
|
+
const fileUrl = (0, import_node_url3.pathToFileURL)(tmpHtml).href;
|
|
1555
2048
|
const res = (0, import_node_child_process2.spawnSync)(
|
|
1556
2049
|
chromePath,
|
|
1557
2050
|
[
|
|
@@ -1569,15 +2062,15 @@ ${mermaidCode}
|
|
|
1569
2062
|
],
|
|
1570
2063
|
{ timeout: 15e3 }
|
|
1571
2064
|
);
|
|
1572
|
-
if (res.status === 0 &&
|
|
1573
|
-
const buffer =
|
|
2065
|
+
if (res.status === 0 && fs5.existsSync(tmpScreenshot)) {
|
|
2066
|
+
const buffer = fs5.readFileSync(tmpScreenshot);
|
|
1574
2067
|
return buffer;
|
|
1575
2068
|
}
|
|
1576
2069
|
} catch {
|
|
1577
2070
|
} finally {
|
|
1578
2071
|
try {
|
|
1579
|
-
if (
|
|
1580
|
-
if (
|
|
2072
|
+
if (fs5.existsSync(tmpHtml)) fs5.unlinkSync(tmpHtml);
|
|
2073
|
+
if (fs5.existsSync(tmpScreenshot)) fs5.unlinkSync(tmpScreenshot);
|
|
1581
2074
|
} catch {
|
|
1582
2075
|
}
|
|
1583
2076
|
}
|
|
@@ -1585,7 +2078,7 @@ ${mermaidCode}
|
|
|
1585
2078
|
}
|
|
1586
2079
|
|
|
1587
2080
|
// src/core/docx/docxBuilder.ts
|
|
1588
|
-
function
|
|
2081
|
+
function parseMarginToTwip2(margin, defaultTwip = 1440) {
|
|
1589
2082
|
if (typeof margin === "number") return margin;
|
|
1590
2083
|
if (!margin) return defaultTwip;
|
|
1591
2084
|
const str = margin.trim().toLowerCase();
|
|
@@ -1608,7 +2101,7 @@ function parseMarginToTwip(margin, defaultTwip = 1440) {
|
|
|
1608
2101
|
const val = parseFloat(str);
|
|
1609
2102
|
return isNaN(val) ? defaultTwip : Math.round(val);
|
|
1610
2103
|
}
|
|
1611
|
-
async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
2104
|
+
async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd(), options = {}) {
|
|
1612
2105
|
const runs = [];
|
|
1613
2106
|
for (const span of spans) {
|
|
1614
2107
|
if (span.type === "image" && span.url) {
|
|
@@ -1638,7 +2131,10 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1638
2131
|
new import_docx.TextRun({
|
|
1639
2132
|
text: span.content,
|
|
1640
2133
|
style: "Hyperlink",
|
|
1641
|
-
color: "
|
|
2134
|
+
color: "009DA0",
|
|
2135
|
+
font: options.font,
|
|
2136
|
+
size: options.size,
|
|
2137
|
+
bold: options.bold,
|
|
1642
2138
|
underline: {}
|
|
1643
2139
|
})
|
|
1644
2140
|
],
|
|
@@ -1651,7 +2147,11 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1651
2147
|
runs.push(
|
|
1652
2148
|
new import_docx.TextRun({
|
|
1653
2149
|
text: span.content,
|
|
1654
|
-
bold: true
|
|
2150
|
+
bold: true,
|
|
2151
|
+
font: options.font,
|
|
2152
|
+
size: options.size,
|
|
2153
|
+
color: options.color,
|
|
2154
|
+
italics: options.italics
|
|
1655
2155
|
})
|
|
1656
2156
|
);
|
|
1657
2157
|
continue;
|
|
@@ -1660,7 +2160,11 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1660
2160
|
runs.push(
|
|
1661
2161
|
new import_docx.TextRun({
|
|
1662
2162
|
text: span.content,
|
|
1663
|
-
italics: true
|
|
2163
|
+
italics: true,
|
|
2164
|
+
font: options.font,
|
|
2165
|
+
size: options.size,
|
|
2166
|
+
color: options.color,
|
|
2167
|
+
bold: options.bold
|
|
1664
2168
|
})
|
|
1665
2169
|
);
|
|
1666
2170
|
continue;
|
|
@@ -1669,7 +2173,10 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1669
2173
|
runs.push(
|
|
1670
2174
|
new import_docx.TextRun({
|
|
1671
2175
|
text: span.content,
|
|
1672
|
-
strike: true
|
|
2176
|
+
strike: true,
|
|
2177
|
+
font: options.font,
|
|
2178
|
+
size: options.size,
|
|
2179
|
+
color: options.color
|
|
1673
2180
|
})
|
|
1674
2181
|
);
|
|
1675
2182
|
continue;
|
|
@@ -1677,22 +2184,23 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1677
2184
|
if (span.type === "code") {
|
|
1678
2185
|
runs.push(
|
|
1679
2186
|
new import_docx.TextRun({
|
|
1680
|
-
text:
|
|
2187
|
+
text: span.content,
|
|
1681
2188
|
font: "Consolas",
|
|
2189
|
+
size: options.size ? options.size - 2 : 19,
|
|
2190
|
+
color: "0F172A",
|
|
1682
2191
|
shading: {
|
|
1683
2192
|
type: import_docx.ShadingType.CLEAR,
|
|
1684
|
-
fill: "F1F5F9"
|
|
1685
|
-
color: "0F172A"
|
|
2193
|
+
fill: "F1F5F9"
|
|
1686
2194
|
}
|
|
1687
2195
|
})
|
|
1688
2196
|
);
|
|
1689
2197
|
continue;
|
|
1690
2198
|
}
|
|
1691
2199
|
if (span.type === "htmlInline") {
|
|
1692
|
-
let colorHex;
|
|
2200
|
+
let colorHex = options.color;
|
|
1693
2201
|
let bgHex;
|
|
1694
|
-
let isBold =
|
|
1695
|
-
let isItalic =
|
|
2202
|
+
let isBold = !!options.bold;
|
|
2203
|
+
let isItalic = !!options.italics;
|
|
1696
2204
|
if (span.style) {
|
|
1697
2205
|
if (span.style.color) {
|
|
1698
2206
|
colorHex = span.style.color.replace("#", "").trim();
|
|
@@ -1708,13 +2216,9 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1708
2216
|
}
|
|
1709
2217
|
}
|
|
1710
2218
|
if (span.children && span.children.length > 0) {
|
|
1711
|
-
const childRuns = await convertInlinesToTextRuns(span.children, baseDir);
|
|
2219
|
+
const childRuns = await convertInlinesToTextRuns(span.children, baseDir, options);
|
|
1712
2220
|
for (const child of childRuns) {
|
|
1713
|
-
|
|
1714
|
-
runs.push(child);
|
|
1715
|
-
} else {
|
|
1716
|
-
runs.push(child);
|
|
1717
|
-
}
|
|
2221
|
+
runs.push(child);
|
|
1718
2222
|
}
|
|
1719
2223
|
continue;
|
|
1720
2224
|
}
|
|
@@ -1724,6 +2228,8 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1724
2228
|
color: colorHex,
|
|
1725
2229
|
bold: isBold,
|
|
1726
2230
|
italics: isItalic,
|
|
2231
|
+
font: options.font,
|
|
2232
|
+
size: options.size,
|
|
1727
2233
|
shading: bgHex ? { type: import_docx.ShadingType.CLEAR, fill: bgHex } : void 0
|
|
1728
2234
|
})
|
|
1729
2235
|
);
|
|
@@ -1731,91 +2237,239 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1731
2237
|
}
|
|
1732
2238
|
runs.push(
|
|
1733
2239
|
new import_docx.TextRun({
|
|
1734
|
-
text: span.content
|
|
2240
|
+
text: span.content,
|
|
2241
|
+
font: options.font,
|
|
2242
|
+
size: options.size,
|
|
2243
|
+
color: options.color,
|
|
2244
|
+
bold: options.bold,
|
|
2245
|
+
italics: options.italics
|
|
1735
2246
|
})
|
|
1736
2247
|
);
|
|
1737
2248
|
}
|
|
1738
2249
|
return runs;
|
|
1739
2250
|
}
|
|
1740
2251
|
async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
1741
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
1742
|
-
const
|
|
2252
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
2253
|
+
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
1743
2254
|
const docElements = [];
|
|
1744
|
-
|
|
2255
|
+
const themeProps = typeof resolved.theme === "object" ? resolved.theme : {};
|
|
2256
|
+
const primaryHex = (themeProps.primaryColor || "#33CDCF").replace("#", "");
|
|
2257
|
+
const primaryDarkHex = (themeProps.primaryDark || "#009DA0").replace("#", "");
|
|
2258
|
+
const textHex = (themeProps.textColor || "#0F172A").replace("#", "");
|
|
2259
|
+
const textMutedHex = (themeProps.textMuted || "#64748B").replace("#", "");
|
|
2260
|
+
const borderHex = (themeProps.borderColor || "#E2E8F0").replace("#", "");
|
|
2261
|
+
const cardBgHex = (themeProps.cardBackground || "#F8FAFC").replace("#", "");
|
|
2262
|
+
const defaultFont = themeProps.fontFamily ? themeProps.fontFamily.split(",")[0].replace(/['"]/g, "").trim() : "Segoe UI";
|
|
2263
|
+
if (resolved.title) {
|
|
1745
2264
|
docElements.push(
|
|
1746
2265
|
new import_docx.Paragraph({
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
2266
|
+
children: [
|
|
2267
|
+
new import_docx.TextRun({
|
|
2268
|
+
text: resolved.title,
|
|
2269
|
+
bold: true,
|
|
2270
|
+
size: 44,
|
|
2271
|
+
// 22pt
|
|
2272
|
+
color: textHex,
|
|
2273
|
+
font: defaultFont
|
|
2274
|
+
})
|
|
2275
|
+
],
|
|
2276
|
+
spacing: { before: 120, after: 80 }
|
|
1750
2277
|
})
|
|
1751
2278
|
);
|
|
1752
|
-
if (
|
|
2279
|
+
if (resolved.subtitle) {
|
|
1753
2280
|
docElements.push(
|
|
1754
2281
|
new import_docx.Paragraph({
|
|
1755
2282
|
children: [
|
|
1756
2283
|
new import_docx.TextRun({
|
|
1757
|
-
text:
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
size: 24
|
|
2284
|
+
text: resolved.subtitle,
|
|
2285
|
+
color: textMutedHex,
|
|
2286
|
+
size: 24,
|
|
1761
2287
|
// 12pt
|
|
2288
|
+
font: defaultFont
|
|
1762
2289
|
})
|
|
1763
2290
|
],
|
|
1764
|
-
spacing: { after:
|
|
2291
|
+
spacing: { before: 60, after: 120 }
|
|
1765
2292
|
})
|
|
1766
2293
|
);
|
|
1767
2294
|
}
|
|
1768
|
-
if (
|
|
2295
|
+
if (resolved.author || resolved.date || resolved.version || resolved.company) {
|
|
1769
2296
|
const metaParts = [];
|
|
1770
|
-
if (
|
|
1771
|
-
if (
|
|
2297
|
+
if (resolved.author) metaParts.push(`Author: ${resolved.author}`);
|
|
2298
|
+
if (resolved.version) metaParts.push(`Version: ${resolved.version}`);
|
|
2299
|
+
if (resolved.date) metaParts.push(`Date: ${resolved.date}`);
|
|
1772
2300
|
docElements.push(
|
|
1773
2301
|
new import_docx.Paragraph({
|
|
1774
2302
|
children: [
|
|
1775
2303
|
new import_docx.TextRun({
|
|
1776
|
-
text: metaParts.join("
|
|
1777
|
-
color:
|
|
1778
|
-
size:
|
|
1779
|
-
//
|
|
2304
|
+
text: metaParts.join(" "),
|
|
2305
|
+
color: textMutedHex,
|
|
2306
|
+
size: 18,
|
|
2307
|
+
// 9pt
|
|
2308
|
+
font: defaultFont
|
|
1780
2309
|
})
|
|
1781
2310
|
],
|
|
1782
|
-
spacing: { after:
|
|
2311
|
+
spacing: { before: 40, after: 240 },
|
|
1783
2312
|
border: {
|
|
1784
2313
|
bottom: {
|
|
1785
|
-
color:
|
|
1786
|
-
space:
|
|
2314
|
+
color: borderHex,
|
|
2315
|
+
space: 12,
|
|
1787
2316
|
style: import_docx.BorderStyle.SINGLE,
|
|
1788
|
-
size:
|
|
2317
|
+
size: 4
|
|
1789
2318
|
}
|
|
1790
2319
|
}
|
|
1791
2320
|
})
|
|
1792
2321
|
);
|
|
1793
2322
|
}
|
|
1794
2323
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
if (node.level === 5) headingLevel = import_docx.HeadingLevel.HEADING_5;
|
|
1802
|
-
if (node.level === 6) headingLevel = import_docx.HeadingLevel.HEADING_6;
|
|
1803
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir);
|
|
1804
|
-
docElements.push(
|
|
2324
|
+
if (resolved.toc) {
|
|
2325
|
+
const headingNodes = doc.nodes.filter(
|
|
2326
|
+
(n) => n.type === "heading" && typeof n.level === "number" && n.level >= 1 && n.level <= 3
|
|
2327
|
+
);
|
|
2328
|
+
if (headingNodes.length > 0) {
|
|
2329
|
+
const tocParagraphs = [
|
|
1805
2330
|
new import_docx.Paragraph({
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
2331
|
+
children: [
|
|
2332
|
+
new import_docx.TextRun({
|
|
2333
|
+
text: "TABLE OF CONTENTS",
|
|
2334
|
+
bold: true,
|
|
2335
|
+
size: 18,
|
|
2336
|
+
// 9pt
|
|
2337
|
+
color: textMutedHex,
|
|
2338
|
+
font: defaultFont
|
|
2339
|
+
})
|
|
2340
|
+
],
|
|
2341
|
+
spacing: { after: 120 },
|
|
2342
|
+
border: {
|
|
2343
|
+
bottom: {
|
|
2344
|
+
color: borderHex,
|
|
2345
|
+
space: 6,
|
|
2346
|
+
style: import_docx.BorderStyle.SINGLE,
|
|
2347
|
+
size: 4
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
1809
2350
|
})
|
|
1810
|
-
|
|
2351
|
+
];
|
|
2352
|
+
for (const h of headingNodes) {
|
|
2353
|
+
const indentLeft = (h.level - 1) * 240;
|
|
2354
|
+
tocParagraphs.push(
|
|
2355
|
+
new import_docx.Paragraph({
|
|
2356
|
+
indent: { left: indentLeft },
|
|
2357
|
+
children: [
|
|
2358
|
+
new import_docx.TextRun({
|
|
2359
|
+
text: h.text,
|
|
2360
|
+
bold: h.level === 1,
|
|
2361
|
+
color: primaryDarkHex,
|
|
2362
|
+
size: h.level === 1 ? 21 : 20,
|
|
2363
|
+
font: defaultFont
|
|
2364
|
+
})
|
|
2365
|
+
],
|
|
2366
|
+
spacing: { before: 20, after: 20 }
|
|
2367
|
+
})
|
|
2368
|
+
);
|
|
2369
|
+
}
|
|
2370
|
+
const tocCard = new import_docx.Table({
|
|
2371
|
+
width: { size: 100, type: import_docx.WidthType.PERCENTAGE },
|
|
2372
|
+
columnWidths: [9e3],
|
|
2373
|
+
rows: [
|
|
2374
|
+
new import_docx.TableRow({
|
|
2375
|
+
children: [
|
|
2376
|
+
new import_docx.TableCell({
|
|
2377
|
+
width: { size: 9e3, type: import_docx.WidthType.DXA },
|
|
2378
|
+
shading: { fill: cardBgHex, type: import_docx.ShadingType.CLEAR },
|
|
2379
|
+
margins: { top: 140, bottom: 140, left: 180, right: 180 },
|
|
2380
|
+
borders: {
|
|
2381
|
+
top: { style: import_docx.BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2382
|
+
bottom: { style: import_docx.BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2383
|
+
left: { style: import_docx.BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2384
|
+
right: { style: import_docx.BorderStyle.SINGLE, size: 4, color: borderHex }
|
|
2385
|
+
},
|
|
2386
|
+
children: tocParagraphs
|
|
2387
|
+
})
|
|
2388
|
+
]
|
|
2389
|
+
})
|
|
2390
|
+
]
|
|
2391
|
+
});
|
|
2392
|
+
docElements.push(tocCard);
|
|
2393
|
+
docElements.push(new import_docx.Paragraph({ spacing: { after: 200 } }));
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
for (const node of doc.nodes) {
|
|
2397
|
+
if (node.type === "heading") {
|
|
2398
|
+
if (node.level === 1) {
|
|
2399
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2400
|
+
font: defaultFont,
|
|
2401
|
+
size: 34,
|
|
2402
|
+
// 17pt
|
|
2403
|
+
color: textHex,
|
|
2404
|
+
bold: true
|
|
2405
|
+
});
|
|
2406
|
+
docElements.push(
|
|
2407
|
+
new import_docx.Paragraph({
|
|
2408
|
+
heading: import_docx.HeadingLevel.HEADING_1,
|
|
2409
|
+
children: runs,
|
|
2410
|
+
spacing: { before: 360, after: 140 },
|
|
2411
|
+
border: {
|
|
2412
|
+
bottom: {
|
|
2413
|
+
color: primaryHex,
|
|
2414
|
+
space: 6,
|
|
2415
|
+
style: import_docx.BorderStyle.SINGLE,
|
|
2416
|
+
size: 16
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
})
|
|
2420
|
+
);
|
|
2421
|
+
} else if (node.level === 2) {
|
|
2422
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2423
|
+
font: defaultFont,
|
|
2424
|
+
size: 26,
|
|
2425
|
+
// 13pt
|
|
2426
|
+
color: primaryDarkHex,
|
|
2427
|
+
bold: true
|
|
2428
|
+
});
|
|
2429
|
+
docElements.push(
|
|
2430
|
+
new import_docx.Paragraph({
|
|
2431
|
+
heading: import_docx.HeadingLevel.HEADING_2,
|
|
2432
|
+
children: runs,
|
|
2433
|
+
spacing: { before: 280, after: 100 },
|
|
2434
|
+
border: {
|
|
2435
|
+
bottom: {
|
|
2436
|
+
color: borderHex,
|
|
2437
|
+
space: 4,
|
|
2438
|
+
style: import_docx.BorderStyle.SINGLE,
|
|
2439
|
+
size: 4
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
})
|
|
2443
|
+
);
|
|
2444
|
+
} else {
|
|
2445
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2446
|
+
font: defaultFont,
|
|
2447
|
+
size: 22,
|
|
2448
|
+
// 11pt
|
|
2449
|
+
color: textHex,
|
|
2450
|
+
bold: true
|
|
2451
|
+
});
|
|
2452
|
+
docElements.push(
|
|
2453
|
+
new import_docx.Paragraph({
|
|
2454
|
+
heading: node.level === 3 ? import_docx.HeadingLevel.HEADING_3 : import_docx.HeadingLevel.HEADING_4,
|
|
2455
|
+
children: runs,
|
|
2456
|
+
spacing: { before: 200, after: 80 }
|
|
2457
|
+
})
|
|
2458
|
+
);
|
|
2459
|
+
}
|
|
1811
2460
|
continue;
|
|
1812
2461
|
}
|
|
1813
2462
|
if (node.type === "paragraph") {
|
|
1814
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
2463
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2464
|
+
font: defaultFont,
|
|
2465
|
+
size: 22,
|
|
2466
|
+
// 11pt
|
|
2467
|
+
color: "334155"
|
|
2468
|
+
});
|
|
1815
2469
|
docElements.push(
|
|
1816
2470
|
new import_docx.Paragraph({
|
|
1817
2471
|
children: runs,
|
|
1818
|
-
spacing: { before:
|
|
2472
|
+
spacing: { before: 40, after: 140, line: 280 }
|
|
1819
2473
|
})
|
|
1820
2474
|
);
|
|
1821
2475
|
continue;
|
|
@@ -1887,7 +2541,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1887
2541
|
bgFill = "F5F3FF";
|
|
1888
2542
|
title = "IMPORTANT";
|
|
1889
2543
|
}
|
|
1890
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
2544
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2545
|
+
font: defaultFont,
|
|
2546
|
+
size: 21,
|
|
2547
|
+
color: "334155"
|
|
2548
|
+
});
|
|
1891
2549
|
const calloutTable = new import_docx.Table({
|
|
1892
2550
|
width: { size: 100, type: import_docx.WidthType.PERCENTAGE },
|
|
1893
2551
|
columnWidths: [9e3],
|
|
@@ -1902,7 +2560,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1902
2560
|
top: { style: import_docx.BorderStyle.NONE },
|
|
1903
2561
|
bottom: { style: import_docx.BorderStyle.NONE },
|
|
1904
2562
|
right: { style: import_docx.BorderStyle.NONE },
|
|
1905
|
-
left: { style: import_docx.BorderStyle.SINGLE, size:
|
|
2563
|
+
left: { style: import_docx.BorderStyle.SINGLE, size: 20, color: borderColor }
|
|
1906
2564
|
},
|
|
1907
2565
|
children: [
|
|
1908
2566
|
new import_docx.Paragraph({
|
|
@@ -1911,13 +2569,15 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1911
2569
|
text: `[${title}]`,
|
|
1912
2570
|
bold: true,
|
|
1913
2571
|
color: borderColor,
|
|
2572
|
+
font: defaultFont,
|
|
1914
2573
|
size: 20
|
|
1915
2574
|
})
|
|
1916
2575
|
],
|
|
1917
|
-
spacing: { after:
|
|
2576
|
+
spacing: { after: 40 }
|
|
1918
2577
|
}),
|
|
1919
2578
|
new import_docx.Paragraph({
|
|
1920
|
-
children: runs
|
|
2579
|
+
children: runs,
|
|
2580
|
+
spacing: { line: 270 }
|
|
1921
2581
|
})
|
|
1922
2582
|
]
|
|
1923
2583
|
})
|
|
@@ -1935,17 +2595,27 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1935
2595
|
if (lines.length > 0) {
|
|
1936
2596
|
for (const lineText of lines) {
|
|
1937
2597
|
const spans = parseInlineSpans(lineText.replace(/^>\s?/, "").trim());
|
|
1938
|
-
const lineRuns = await convertInlinesToTextRuns(spans, baseDir
|
|
2598
|
+
const lineRuns = await convertInlinesToTextRuns(spans, baseDir, {
|
|
2599
|
+
font: defaultFont,
|
|
2600
|
+
size: 21,
|
|
2601
|
+
color: "475569",
|
|
2602
|
+
italics: true
|
|
2603
|
+
});
|
|
1939
2604
|
quoteParagraphs.push(
|
|
1940
2605
|
new import_docx.Paragraph({
|
|
1941
2606
|
children: lineRuns,
|
|
1942
|
-
spacing: { before:
|
|
2607
|
+
spacing: { before: 20, after: 20, line: 260 }
|
|
1943
2608
|
})
|
|
1944
2609
|
);
|
|
1945
2610
|
}
|
|
1946
2611
|
} else {
|
|
1947
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
1948
|
-
|
|
2612
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2613
|
+
font: defaultFont,
|
|
2614
|
+
size: 21,
|
|
2615
|
+
color: "475569",
|
|
2616
|
+
italics: true
|
|
2617
|
+
});
|
|
2618
|
+
quoteParagraphs.push(new import_docx.Paragraph({ children: runs, spacing: { line: 260 } }));
|
|
1949
2619
|
}
|
|
1950
2620
|
const quoteTable = new import_docx.Table({
|
|
1951
2621
|
width: { size: 100, type: import_docx.WidthType.PERCENTAGE },
|
|
@@ -1961,7 +2631,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1961
2631
|
top: { style: import_docx.BorderStyle.NONE },
|
|
1962
2632
|
bottom: { style: import_docx.BorderStyle.NONE },
|
|
1963
2633
|
right: { style: import_docx.BorderStyle.NONE },
|
|
1964
|
-
left: { style: import_docx.BorderStyle.SINGLE, size:
|
|
2634
|
+
left: { style: import_docx.BorderStyle.SINGLE, size: 16, color: primaryHex }
|
|
1965
2635
|
},
|
|
1966
2636
|
children: quoteParagraphs
|
|
1967
2637
|
})
|
|
@@ -1996,7 +2666,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1996
2666
|
docElements.push(
|
|
1997
2667
|
new import_docx.Paragraph({
|
|
1998
2668
|
children: [
|
|
1999
|
-
new import_docx.TextRun({ text: "[Mermaid Diagram: " + (node.text || "").slice(0, 40) + "...]", bold: true, color:
|
|
2669
|
+
new import_docx.TextRun({ text: "[Mermaid Diagram: " + (node.text || "").slice(0, 40) + "...]", bold: true, color: primaryHex })
|
|
2000
2670
|
],
|
|
2001
2671
|
spacing: { before: 60, after: 60 }
|
|
2002
2672
|
})
|
|
@@ -2008,8 +2678,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2008
2678
|
const tableRows = [];
|
|
2009
2679
|
const numCols = ((_b = (_a = node.children[0]) == null ? void 0 : _a.children) == null ? void 0 : _b.length) || 1;
|
|
2010
2680
|
const colWidth = Math.floor(9e3 / numCols);
|
|
2011
|
-
for (
|
|
2681
|
+
for (let rowIdx = 0; rowIdx < node.children.length; rowIdx++) {
|
|
2682
|
+
const rowNode = node.children[rowIdx];
|
|
2012
2683
|
const cells = [];
|
|
2684
|
+
const isHeader = rowNode.isHeader;
|
|
2685
|
+
const rowBg = isHeader ? "F1F5F9" : rowIdx % 2 === 0 ? "FFFFFF" : "F8FAFC";
|
|
2013
2686
|
if (rowNode.children) {
|
|
2014
2687
|
for (let colIdx = 0; colIdx < rowNode.children.length; colIdx++) {
|
|
2015
2688
|
const cellNode = rowNode.children[colIdx];
|
|
@@ -2017,22 +2690,27 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2017
2690
|
let alignment = import_docx.AlignmentType.LEFT;
|
|
2018
2691
|
if (align === "center") alignment = import_docx.AlignmentType.CENTER;
|
|
2019
2692
|
if (align === "right") alignment = import_docx.AlignmentType.RIGHT;
|
|
2020
|
-
const runs = await convertInlinesToTextRuns(cellNode.inlines, baseDir
|
|
2693
|
+
const runs = await convertInlinesToTextRuns(cellNode.inlines, baseDir, {
|
|
2694
|
+
font: defaultFont,
|
|
2695
|
+
size: 20,
|
|
2696
|
+
color: isHeader ? "0F172A" : "334155",
|
|
2697
|
+
bold: isHeader
|
|
2698
|
+
});
|
|
2021
2699
|
cells.push(
|
|
2022
2700
|
new import_docx.TableCell({
|
|
2023
2701
|
width: { size: colWidth, type: import_docx.WidthType.DXA },
|
|
2024
|
-
shading:
|
|
2025
|
-
margins: { top: 100, bottom: 100, left:
|
|
2702
|
+
shading: { fill: rowBg, type: import_docx.ShadingType.CLEAR },
|
|
2703
|
+
margins: { top: 100, bottom: 100, left: 140, right: 140 },
|
|
2026
2704
|
borders: {
|
|
2027
|
-
top: { style: import_docx.BorderStyle.SINGLE, size: 4, color: "
|
|
2028
|
-
bottom: { style: import_docx.BorderStyle.SINGLE, size: 4, color: "CBD5E1" },
|
|
2029
|
-
left: { style: import_docx.BorderStyle.SINGLE, size: 4, color: "
|
|
2030
|
-
right: { style: import_docx.BorderStyle.SINGLE, size: 4, color: "
|
|
2705
|
+
top: { style: import_docx.BorderStyle.SINGLE, size: 4, color: "E2E8F0" },
|
|
2706
|
+
bottom: { style: import_docx.BorderStyle.SINGLE, size: isHeader ? 8 : 4, color: isHeader ? "CBD5E1" : "E2E8F0" },
|
|
2707
|
+
left: { style: import_docx.BorderStyle.SINGLE, size: 4, color: "E2E8F0" },
|
|
2708
|
+
right: { style: import_docx.BorderStyle.SINGLE, size: 4, color: "E2E8F0" }
|
|
2031
2709
|
},
|
|
2032
2710
|
children: [
|
|
2033
2711
|
new import_docx.Paragraph({
|
|
2034
2712
|
alignment,
|
|
2035
|
-
children:
|
|
2713
|
+
children: runs
|
|
2036
2714
|
})
|
|
2037
2715
|
]
|
|
2038
2716
|
})
|
|
@@ -2041,7 +2719,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2041
2719
|
}
|
|
2042
2720
|
tableRows.push(
|
|
2043
2721
|
new import_docx.TableRow({
|
|
2044
|
-
tableHeader:
|
|
2722
|
+
tableHeader: isHeader,
|
|
2045
2723
|
children: cells
|
|
2046
2724
|
})
|
|
2047
2725
|
);
|
|
@@ -2057,7 +2735,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2057
2735
|
}
|
|
2058
2736
|
if (node.type === "list" && node.children) {
|
|
2059
2737
|
for (const item of node.children) {
|
|
2060
|
-
const runs = await convertInlinesToTextRuns(item.inlines, baseDir
|
|
2738
|
+
const runs = await convertInlinesToTextRuns(item.inlines, baseDir, {
|
|
2739
|
+
font: defaultFont,
|
|
2740
|
+
size: 21,
|
|
2741
|
+
color: "334155"
|
|
2742
|
+
});
|
|
2061
2743
|
let prefix = "";
|
|
2062
2744
|
if (item.checked !== void 0) {
|
|
2063
2745
|
prefix = item.checked ? "[X] " : "[ ] ";
|
|
@@ -2069,7 +2751,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2069
2751
|
...prefix ? [new import_docx.TextRun({ text: prefix, bold: true, font: "Consolas" })] : [],
|
|
2070
2752
|
...runs
|
|
2071
2753
|
],
|
|
2072
|
-
spacing: { before:
|
|
2754
|
+
spacing: { before: 20, after: 20, line: 260 }
|
|
2073
2755
|
})
|
|
2074
2756
|
);
|
|
2075
2757
|
}
|
|
@@ -2144,88 +2826,205 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2144
2826
|
continue;
|
|
2145
2827
|
}
|
|
2146
2828
|
}
|
|
2147
|
-
const
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
const
|
|
2829
|
+
const contentWidthTwip = Math.max(
|
|
2830
|
+
1e3,
|
|
2831
|
+
resolved.paperDimensions.widthTwip - resolved.margins.leftTwip - resolved.margins.rightTwip
|
|
2832
|
+
);
|
|
2833
|
+
const centerPos = Math.round(contentWidthTwip / 2);
|
|
2834
|
+
const rightPos = contentWidthTwip;
|
|
2835
|
+
const headerRuns = [];
|
|
2836
|
+
if ((_d = resolved.header) == null ? void 0 : _d.left) {
|
|
2837
|
+
headerRuns.push(
|
|
2838
|
+
new import_docx.TextRun({
|
|
2839
|
+
text: resolved.header.left.text,
|
|
2840
|
+
color: resolved.header.left.color.replace("#", ""),
|
|
2841
|
+
size: (resolved.header.left.fontSize || 9) * 2,
|
|
2842
|
+
font: resolved.header.left.fontFamily || defaultFont,
|
|
2843
|
+
bold: resolved.header.left.bold,
|
|
2844
|
+
italics: resolved.header.left.italic
|
|
2845
|
+
})
|
|
2846
|
+
);
|
|
2847
|
+
}
|
|
2848
|
+
headerRuns.push(new import_docx.TextRun({ text: " " }));
|
|
2849
|
+
if ((_e = resolved.header) == null ? void 0 : _e.center) {
|
|
2850
|
+
headerRuns.push(
|
|
2851
|
+
new import_docx.TextRun({
|
|
2852
|
+
text: resolved.header.center.text,
|
|
2853
|
+
color: resolved.header.center.color.replace("#", ""),
|
|
2854
|
+
size: (resolved.header.center.fontSize || 9) * 2,
|
|
2855
|
+
font: resolved.header.center.fontFamily || defaultFont,
|
|
2856
|
+
bold: resolved.header.center.bold,
|
|
2857
|
+
italics: resolved.header.center.italic
|
|
2858
|
+
})
|
|
2859
|
+
);
|
|
2860
|
+
}
|
|
2861
|
+
headerRuns.push(new import_docx.TextRun({ text: " " }));
|
|
2862
|
+
if ((_f = resolved.header) == null ? void 0 : _f.right) {
|
|
2863
|
+
headerRuns.push(
|
|
2864
|
+
new import_docx.TextRun({
|
|
2865
|
+
text: resolved.header.right.text,
|
|
2866
|
+
color: resolved.header.right.color.replace("#", ""),
|
|
2867
|
+
size: (resolved.header.right.fontSize || 9) * 2,
|
|
2868
|
+
font: resolved.header.right.fontFamily || defaultFont,
|
|
2869
|
+
bold: resolved.header.right.bold,
|
|
2870
|
+
italics: resolved.header.right.italic
|
|
2871
|
+
})
|
|
2872
|
+
);
|
|
2873
|
+
}
|
|
2874
|
+
const docHeader = resolved.header ? new import_docx.Header({
|
|
2154
2875
|
children: [
|
|
2155
2876
|
new import_docx.Paragraph({
|
|
2156
|
-
tabStops:
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2877
|
+
tabStops: [
|
|
2878
|
+
{
|
|
2879
|
+
type: import_docx.TabStopType.CENTER,
|
|
2880
|
+
position: centerPos
|
|
2881
|
+
},
|
|
2882
|
+
{
|
|
2883
|
+
type: import_docx.TabStopType.RIGHT,
|
|
2884
|
+
position: rightPos
|
|
2885
|
+
}
|
|
2886
|
+
],
|
|
2887
|
+
border: resolved.header.divider ? {
|
|
2888
|
+
bottom: {
|
|
2889
|
+
style: import_docx.BorderStyle.SINGLE,
|
|
2890
|
+
size: 4,
|
|
2891
|
+
space: 6,
|
|
2892
|
+
color: (resolved.header.dividerColor || "#CBD5E1").replace("#", "")
|
|
2893
|
+
}
|
|
2894
|
+
} : void 0,
|
|
2895
|
+
children: headerRuns,
|
|
2896
|
+
spacing: { after: 120 }
|
|
2897
|
+
})
|
|
2898
|
+
]
|
|
2899
|
+
}) : void 0;
|
|
2900
|
+
const footerRuns = [];
|
|
2901
|
+
if ((_g = resolved.footer) == null ? void 0 : _g.left) {
|
|
2902
|
+
footerRuns.push(
|
|
2903
|
+
new import_docx.TextRun({
|
|
2904
|
+
text: resolved.footer.left.text,
|
|
2905
|
+
color: resolved.footer.left.color.replace("#", ""),
|
|
2906
|
+
size: (resolved.footer.left.fontSize || 9) * 2,
|
|
2907
|
+
font: resolved.footer.left.fontFamily || defaultFont,
|
|
2908
|
+
bold: resolved.footer.left.bold,
|
|
2909
|
+
italics: resolved.footer.left.italic
|
|
2910
|
+
})
|
|
2911
|
+
);
|
|
2912
|
+
}
|
|
2913
|
+
footerRuns.push(new import_docx.TextRun({ text: " " }));
|
|
2914
|
+
if ((_h = resolved.footer) == null ? void 0 : _h.center) {
|
|
2915
|
+
footerRuns.push(
|
|
2916
|
+
new import_docx.TextRun({
|
|
2917
|
+
text: resolved.footer.center.text,
|
|
2918
|
+
color: resolved.footer.center.color.replace("#", ""),
|
|
2919
|
+
size: (resolved.footer.center.fontSize || 9) * 2,
|
|
2920
|
+
font: resolved.footer.center.fontFamily || defaultFont,
|
|
2921
|
+
bold: resolved.footer.center.bold,
|
|
2922
|
+
italics: resolved.footer.center.italic
|
|
2923
|
+
})
|
|
2924
|
+
);
|
|
2925
|
+
}
|
|
2926
|
+
footerRuns.push(new import_docx.TextRun({ text: " " }));
|
|
2927
|
+
if ((_i = resolved.footer) == null ? void 0 : _i.right) {
|
|
2928
|
+
const rZone = resolved.footer.right;
|
|
2929
|
+
const rColor = rZone.color.replace("#", "");
|
|
2930
|
+
const rSize = (rZone.fontSize || 9) * 2;
|
|
2931
|
+
const rFont = rZone.fontFamily || defaultFont;
|
|
2932
|
+
const rBold = rZone.bold;
|
|
2933
|
+
const rItalics = rZone.italic;
|
|
2934
|
+
if (rZone.text.includes("{page}") || rZone.text.includes("{pages}")) {
|
|
2935
|
+
const parts = rZone.text.split(/(\{page\}|\{pages\})/gi);
|
|
2936
|
+
for (const part of parts) {
|
|
2937
|
+
if (part.toLowerCase() === "{page}") {
|
|
2938
|
+
footerRuns.push(
|
|
2160
2939
|
new import_docx.TextRun({
|
|
2161
|
-
|
|
2162
|
-
color:
|
|
2163
|
-
size:
|
|
2940
|
+
children: [import_docx.PageNumber.CURRENT],
|
|
2941
|
+
color: rColor,
|
|
2942
|
+
size: rSize,
|
|
2943
|
+
font: rFont,
|
|
2944
|
+
bold: rBold,
|
|
2945
|
+
italics: rItalics
|
|
2164
2946
|
})
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
new import_docx.TextRun({ text: " ", color: "94A3B8", size: 18 }),
|
|
2947
|
+
);
|
|
2948
|
+
} else if (part.toLowerCase() === "{pages}") {
|
|
2949
|
+
footerRuns.push(
|
|
2169
2950
|
new import_docx.TextRun({
|
|
2170
|
-
|
|
2171
|
-
color:
|
|
2172
|
-
size:
|
|
2951
|
+
children: [import_docx.PageNumber.TOTAL_PAGES],
|
|
2952
|
+
color: rColor,
|
|
2953
|
+
size: rSize,
|
|
2954
|
+
font: rFont,
|
|
2955
|
+
bold: rBold,
|
|
2956
|
+
italics: rItalics
|
|
2173
2957
|
})
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
new import_docx.TextRun({
|
|
2178
|
-
text: headerObj.left || headerObj.center ? " " : "",
|
|
2179
|
-
color: "94A3B8",
|
|
2180
|
-
size: 18
|
|
2181
|
-
}),
|
|
2958
|
+
);
|
|
2959
|
+
} else if (part) {
|
|
2960
|
+
footerRuns.push(
|
|
2182
2961
|
new import_docx.TextRun({
|
|
2183
|
-
text:
|
|
2184
|
-
color:
|
|
2185
|
-
size:
|
|
2962
|
+
text: part,
|
|
2963
|
+
color: rColor,
|
|
2964
|
+
size: rSize,
|
|
2965
|
+
font: rFont,
|
|
2966
|
+
bold: rBold,
|
|
2967
|
+
italics: rItalics
|
|
2186
2968
|
})
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
} else {
|
|
2973
|
+
footerRuns.push(
|
|
2974
|
+
new import_docx.TextRun({
|
|
2975
|
+
text: rZone.text,
|
|
2976
|
+
color: rColor,
|
|
2977
|
+
size: rSize,
|
|
2978
|
+
font: rFont,
|
|
2979
|
+
bold: rBold,
|
|
2980
|
+
italics: rItalics
|
|
2981
|
+
})
|
|
2982
|
+
);
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
const docFooter = resolved.footer ? new import_docx.Footer({
|
|
2193
2986
|
children: [
|
|
2194
2987
|
new import_docx.Paragraph({
|
|
2195
|
-
tabStops:
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2988
|
+
tabStops: [
|
|
2989
|
+
{
|
|
2990
|
+
type: import_docx.TabStopType.CENTER,
|
|
2991
|
+
position: centerPos
|
|
2992
|
+
},
|
|
2993
|
+
{
|
|
2994
|
+
type: import_docx.TabStopType.RIGHT,
|
|
2995
|
+
position: rightPos
|
|
2996
|
+
}
|
|
2997
|
+
],
|
|
2998
|
+
border: resolved.footer.divider ? {
|
|
2999
|
+
top: {
|
|
3000
|
+
style: import_docx.BorderStyle.SINGLE,
|
|
3001
|
+
size: 4,
|
|
3002
|
+
space: 6,
|
|
3003
|
+
color: (resolved.footer.dividerColor || "#CBD5E1").replace("#", "")
|
|
3004
|
+
}
|
|
3005
|
+
} : void 0,
|
|
3006
|
+
children: footerRuns,
|
|
3007
|
+
spacing: { before: 120 }
|
|
2212
3008
|
})
|
|
2213
3009
|
]
|
|
2214
3010
|
}) : void 0;
|
|
2215
|
-
const
|
|
2216
|
-
const bottomMargin = parseMarginToTwip(((_f = metadata.margins) == null ? void 0 : _f.bottom) || ((_g = config.margins) == null ? void 0 : _g.bottom), 1440);
|
|
2217
|
-
const leftMargin = parseMarginToTwip(((_h = metadata.margins) == null ? void 0 : _h.left) || ((_i = config.margins) == null ? void 0 : _i.left), 1440);
|
|
2218
|
-
const rightMargin = parseMarginToTwip(((_j = metadata.margins) == null ? void 0 : _j.right) || ((_k = config.margins) == null ? void 0 : _k.right), 1440);
|
|
2219
|
-
const isLandscape = (metadata.orientation || config.orientation) === "landscape";
|
|
3011
|
+
const isLandscape = resolved.orientation === "landscape";
|
|
2220
3012
|
const document = new import_docx.Document({
|
|
2221
3013
|
styles: {
|
|
2222
3014
|
default: {
|
|
2223
3015
|
document: {
|
|
2224
3016
|
run: {
|
|
2225
|
-
font:
|
|
2226
|
-
size:
|
|
2227
|
-
//
|
|
2228
|
-
color:
|
|
3017
|
+
font: defaultFont,
|
|
3018
|
+
size: 21,
|
|
3019
|
+
// 10.5pt
|
|
3020
|
+
color: textHex
|
|
3021
|
+
},
|
|
3022
|
+
paragraph: {
|
|
3023
|
+
spacing: {
|
|
3024
|
+
line: 276,
|
|
3025
|
+
// 1.15 line spacing
|
|
3026
|
+
after: 140
|
|
3027
|
+
}
|
|
2229
3028
|
}
|
|
2230
3029
|
}
|
|
2231
3030
|
}
|
|
@@ -2235,13 +3034,15 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2235
3034
|
properties: {
|
|
2236
3035
|
page: {
|
|
2237
3036
|
size: {
|
|
3037
|
+
width: resolved.paperDimensions.widthTwip,
|
|
3038
|
+
height: resolved.paperDimensions.heightTwip,
|
|
2238
3039
|
orientation: isLandscape ? import_docx.PageOrientation.LANDSCAPE : import_docx.PageOrientation.PORTRAIT
|
|
2239
3040
|
},
|
|
2240
3041
|
margin: {
|
|
2241
|
-
top:
|
|
2242
|
-
bottom:
|
|
2243
|
-
left:
|
|
2244
|
-
right:
|
|
3042
|
+
top: resolved.margins.topTwip,
|
|
3043
|
+
bottom: resolved.margins.bottomTwip,
|
|
3044
|
+
left: resolved.margins.leftTwip,
|
|
3045
|
+
right: resolved.margins.rightTwip,
|
|
2245
3046
|
header: 720,
|
|
2246
3047
|
footer: 720
|
|
2247
3048
|
}
|
|
@@ -2256,109 +3057,6 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2256
3057
|
return await import_docx.Packer.toBuffer(document);
|
|
2257
3058
|
}
|
|
2258
3059
|
|
|
2259
|
-
// src/config/loadConfig.ts
|
|
2260
|
-
var fs5 = __toESM(require("fs"));
|
|
2261
|
-
var path5 = __toESM(require("path"));
|
|
2262
|
-
var import_node_url3 = require("url");
|
|
2263
|
-
var YAML = __toESM(require("yaml"));
|
|
2264
|
-
var DEFAULT_CONFIG_FILENAMES = [
|
|
2265
|
-
"markforge.config.json",
|
|
2266
|
-
".markforgerc.json",
|
|
2267
|
-
"markforge.config.yaml",
|
|
2268
|
-
"markforge.config.yml",
|
|
2269
|
-
".markforgerc.yaml",
|
|
2270
|
-
".markforgerc.yml",
|
|
2271
|
-
".markforgerc",
|
|
2272
|
-
"markforge.config.ts",
|
|
2273
|
-
"markforge.config.js",
|
|
2274
|
-
"markforge.config.mjs",
|
|
2275
|
-
"markforge.config.cjs"
|
|
2276
|
-
];
|
|
2277
|
-
var DEFAULT_CONFIG = {
|
|
2278
|
-
to: ["docx", "pdf"],
|
|
2279
|
-
outputDir: void 0,
|
|
2280
|
-
theme: "default",
|
|
2281
|
-
css: void 0,
|
|
2282
|
-
orientation: "portrait",
|
|
2283
|
-
paperSize: "A4",
|
|
2284
|
-
margins: {
|
|
2285
|
-
top: "2.5cm",
|
|
2286
|
-
bottom: "2.5cm",
|
|
2287
|
-
left: "2.5cm",
|
|
2288
|
-
right: "2.5cm"
|
|
2289
|
-
},
|
|
2290
|
-
header: void 0,
|
|
2291
|
-
footer: {
|
|
2292
|
-
right: "Page {page} of {pages}"
|
|
2293
|
-
},
|
|
2294
|
-
toc: false,
|
|
2295
|
-
watermark: void 0,
|
|
2296
|
-
embedImages: true,
|
|
2297
|
-
metadata: void 0,
|
|
2298
|
-
watch: false,
|
|
2299
|
-
serve: false,
|
|
2300
|
-
port: 4e3,
|
|
2301
|
-
open: false,
|
|
2302
|
-
bundleHtml: true,
|
|
2303
|
-
syntaxTheme: "github-dark"
|
|
2304
|
-
};
|
|
2305
|
-
async function loadConfig(customPath, cwd = process.cwd()) {
|
|
2306
|
-
let resolvedPath = null;
|
|
2307
|
-
if (customPath) {
|
|
2308
|
-
resolvedPath = path5.isAbsolute(customPath) ? customPath : path5.resolve(cwd, customPath);
|
|
2309
|
-
if (!fs5.existsSync(resolvedPath)) {
|
|
2310
|
-
throw new Error(`Configuration file not found: ${resolvedPath}`);
|
|
2311
|
-
}
|
|
2312
|
-
} else {
|
|
2313
|
-
for (const filename of DEFAULT_CONFIG_FILENAMES) {
|
|
2314
|
-
const candidate = path5.resolve(cwd, filename);
|
|
2315
|
-
if (fs5.existsSync(candidate)) {
|
|
2316
|
-
resolvedPath = candidate;
|
|
2317
|
-
break;
|
|
2318
|
-
}
|
|
2319
|
-
}
|
|
2320
|
-
}
|
|
2321
|
-
if (!resolvedPath) {
|
|
2322
|
-
return {
|
|
2323
|
-
config: { ...DEFAULT_CONFIG },
|
|
2324
|
-
configPath: null
|
|
2325
|
-
};
|
|
2326
|
-
}
|
|
2327
|
-
const ext = path5.extname(resolvedPath).toLowerCase();
|
|
2328
|
-
let userConfig = {};
|
|
2329
|
-
if (ext === ".json" || resolvedPath.endsWith(".markforgerc")) {
|
|
2330
|
-
const raw = fs5.readFileSync(resolvedPath, "utf-8");
|
|
2331
|
-
userConfig = JSON.parse(raw);
|
|
2332
|
-
} else if (ext === ".yaml" || ext === ".yml") {
|
|
2333
|
-
const raw = fs5.readFileSync(resolvedPath, "utf-8");
|
|
2334
|
-
userConfig = YAML.parse(raw);
|
|
2335
|
-
} else if (ext === ".ts" || ext === ".js" || ext === ".mjs" || ext === ".cjs") {
|
|
2336
|
-
try {
|
|
2337
|
-
const fileUrl = (0, import_node_url3.pathToFileURL)(resolvedPath).href;
|
|
2338
|
-
const mod = await import(fileUrl);
|
|
2339
|
-
userConfig = mod.default || mod;
|
|
2340
|
-
} catch {
|
|
2341
|
-
const required = require(resolvedPath);
|
|
2342
|
-
userConfig = required.default || required;
|
|
2343
|
-
}
|
|
2344
|
-
}
|
|
2345
|
-
const mergedConfig = {
|
|
2346
|
-
...DEFAULT_CONFIG,
|
|
2347
|
-
...userConfig,
|
|
2348
|
-
margins: {
|
|
2349
|
-
...DEFAULT_CONFIG.margins,
|
|
2350
|
-
...userConfig.margins
|
|
2351
|
-
},
|
|
2352
|
-
header: userConfig.header || DEFAULT_CONFIG.header,
|
|
2353
|
-
footer: userConfig.footer || DEFAULT_CONFIG.footer,
|
|
2354
|
-
metadata: userConfig.metadata
|
|
2355
|
-
};
|
|
2356
|
-
return {
|
|
2357
|
-
config: mergedConfig,
|
|
2358
|
-
configPath: resolvedPath
|
|
2359
|
-
};
|
|
2360
|
-
}
|
|
2361
|
-
|
|
2362
3060
|
// src/core/engine.ts
|
|
2363
3061
|
function formatServerTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
2364
3062
|
const pad = (n) => String(n).padStart(2, "0");
|
|
@@ -2519,10 +3217,17 @@ function getMarkforgeVersion(fromDir = getPackageDir()) {
|
|
|
2519
3217
|
0 && (module.exports = {
|
|
2520
3218
|
DEFAULT_CONFIG,
|
|
2521
3219
|
MARKFORGE_VERSION,
|
|
3220
|
+
Orientation,
|
|
3221
|
+
OutputFormat,
|
|
3222
|
+
PAPER_DIMENSIONS_TWIP,
|
|
3223
|
+
PaperSizeEnum,
|
|
2522
3224
|
SYNTAX_COLORS,
|
|
3225
|
+
SyntaxTheme,
|
|
2523
3226
|
THEMES,
|
|
2524
|
-
|
|
3227
|
+
THEME_CORPORATE,
|
|
2525
3228
|
THEME_DEFAULT,
|
|
3229
|
+
Theme,
|
|
3230
|
+
WatermarkPosition,
|
|
2526
3231
|
buildDocxDocument,
|
|
2527
3232
|
buildHtmlDocument,
|
|
2528
3233
|
buildPdfDocument,
|
|
@@ -2531,6 +3236,7 @@ function getMarkforgeVersion(fromDir = getPackageDir()) {
|
|
|
2531
3236
|
escapeHtml,
|
|
2532
3237
|
findChromeExecutable,
|
|
2533
3238
|
formatServerTimestamp,
|
|
3239
|
+
generateThemeCss,
|
|
2534
3240
|
getMarkforgeVersion,
|
|
2535
3241
|
getMimeType,
|
|
2536
3242
|
highlightCodeToHtml,
|
|
@@ -2538,11 +3244,16 @@ function getMarkforgeVersion(fromDir = getPackageDir()) {
|
|
|
2538
3244
|
inlineHtmlImages,
|
|
2539
3245
|
loadConfig,
|
|
2540
3246
|
markforge,
|
|
3247
|
+
normalizeHeaderFooter,
|
|
3248
|
+
normalizeHeaderFooterSlot,
|
|
3249
|
+
normalizeWatermark,
|
|
2541
3250
|
parseInlineSpans,
|
|
2542
3251
|
parseMarginToTwip,
|
|
2543
3252
|
parseMarkdownDocument,
|
|
2544
3253
|
renderInlinesToHtml,
|
|
2545
3254
|
renderMermaidToPng,
|
|
3255
|
+
replaceDocumentTokens,
|
|
3256
|
+
resolveDocumentConfig,
|
|
2546
3257
|
resolveImage,
|
|
2547
3258
|
slugify,
|
|
2548
3259
|
tokenizeCodeLine
|