@masumdev/markforge 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +229 -298
- package/dist/{App-IJVCGBJM.mjs → App-AM2CWXHJ.mjs} +1413 -378
- package/dist/{chunk-NGC2ZAWZ.mjs → chunk-HKB4CSPZ.mjs} +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/index.d.mts +409 -59
- package/dist/index.d.ts +409 -59
- package/dist/index.js +1533 -479
- package/dist/index.mjs +1520 -480
- package/package.json +1 -1
- package/schema.json +198 -36
|
@@ -9,7 +9,7 @@ try {
|
|
|
9
9
|
} catch {}
|
|
10
10
|
import {
|
|
11
11
|
MARKFORGE_VERSION
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HKB4CSPZ.mjs";
|
|
13
13
|
import {
|
|
14
14
|
DEFAULT_CONFIG
|
|
15
15
|
} from "./chunk-IYGPJIK5.mjs";
|
|
@@ -20,32 +20,71 @@ import { useState, useEffect } from "react";
|
|
|
20
20
|
import { Box as Box4 } from "ink";
|
|
21
21
|
|
|
22
22
|
// src/ui/Header.tsx
|
|
23
|
+
import * as path from "path";
|
|
23
24
|
import { Box, Text } from "ink";
|
|
24
25
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
25
|
-
|
|
26
|
+
function formatDisplayPath(p) {
|
|
27
|
+
if (!p) return "";
|
|
28
|
+
try {
|
|
29
|
+
const rel = path.relative(process.cwd(), p);
|
|
30
|
+
return rel && !rel.startsWith("..") && rel.length < p.length ? `./${rel}` : p;
|
|
31
|
+
} catch {
|
|
32
|
+
return p;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
var Header = ({
|
|
36
|
+
inputFile,
|
|
37
|
+
theme = "corporate",
|
|
38
|
+
targetFormats = ["docx", "pdf"]
|
|
39
|
+
}) => {
|
|
40
|
+
const themeLabel = typeof theme === "object" ? "Custom (ThemeProps)" : String(theme || "corporate");
|
|
26
41
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: /* @__PURE__ */ jsxs(
|
|
27
42
|
Box,
|
|
28
43
|
{
|
|
29
44
|
borderStyle: "round",
|
|
30
45
|
borderColor: "cyan",
|
|
31
46
|
paddingX: 2,
|
|
32
|
-
paddingY:
|
|
47
|
+
paddingY: 1,
|
|
33
48
|
flexDirection: "column",
|
|
34
49
|
children: [
|
|
35
|
-
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
|
|
36
|
-
/* @__PURE__ */
|
|
37
|
-
|
|
50
|
+
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", alignItems: "center", children: [
|
|
51
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
52
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "MARKFORGE" }),
|
|
53
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: " | Document Publishing Engine" })
|
|
54
|
+
] }),
|
|
55
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "black", backgroundColor: "cyan", bold: true, children: [
|
|
56
|
+
" ",
|
|
38
57
|
"v",
|
|
39
|
-
MARKFORGE_VERSION
|
|
40
|
-
|
|
58
|
+
MARKFORGE_VERSION,
|
|
59
|
+
" "
|
|
60
|
+
] }) })
|
|
41
61
|
] }),
|
|
42
|
-
|
|
43
|
-
/* @__PURE__ */
|
|
44
|
-
|
|
62
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
63
|
+
inputFile && /* @__PURE__ */ jsxs(Box, { children: [
|
|
64
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Source: " }),
|
|
65
|
+
/* @__PURE__ */ jsx(Text, { color: "white", bold: true, children: formatDisplayPath(inputFile) })
|
|
66
|
+
] }),
|
|
67
|
+
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", marginTop: 0, children: [
|
|
68
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
69
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Theme: " }),
|
|
70
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: themeLabel })
|
|
71
|
+
] }),
|
|
72
|
+
targetFormats && targetFormats.length > 0 && /* @__PURE__ */ jsxs(Box, { children: [
|
|
73
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Targets: " }),
|
|
74
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: targetFormats.map((f) => f.toUpperCase()).join(", ") })
|
|
75
|
+
] })
|
|
76
|
+
] })
|
|
45
77
|
] }),
|
|
46
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
47
|
-
/* @__PURE__ */
|
|
48
|
-
|
|
78
|
+
/* @__PURE__ */ jsxs(Box, { marginTop: 1, justifyContent: "space-between", children: [
|
|
79
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
80
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Author: " }),
|
|
81
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "Ma'sum" }),
|
|
82
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: " (@masumrpg)" })
|
|
83
|
+
] }),
|
|
84
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
85
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "GitHub: " }),
|
|
86
|
+
/* @__PURE__ */ jsx(Text, { color: "blue", underline: true, children: "https://github.com/masumrpg" })
|
|
87
|
+
] })
|
|
49
88
|
] })
|
|
50
89
|
]
|
|
51
90
|
}
|
|
@@ -68,6 +107,7 @@ var LiveProgress = ({ status, isCompiling }) => {
|
|
|
68
107
|
};
|
|
69
108
|
|
|
70
109
|
// src/ui/SummaryTable.tsx
|
|
110
|
+
import * as path2 from "path";
|
|
71
111
|
import { Box as Box3, Text as Text3 } from "ink";
|
|
72
112
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
73
113
|
function formatBytes(bytes) {
|
|
@@ -77,6 +117,15 @@ function formatBytes(bytes) {
|
|
|
77
117
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
78
118
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
|
79
119
|
}
|
|
120
|
+
function formatDisplayPath2(p) {
|
|
121
|
+
if (!p) return "";
|
|
122
|
+
try {
|
|
123
|
+
const rel = path2.relative(process.cwd(), p);
|
|
124
|
+
return rel && !rel.startsWith("..") && rel.length < p.length ? `./${rel}` : p;
|
|
125
|
+
} catch {
|
|
126
|
+
return p;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
80
129
|
var SummaryTable = ({ result }) => {
|
|
81
130
|
if (!result) return null;
|
|
82
131
|
const hasErrors = result.errors.length > 0;
|
|
@@ -89,33 +138,39 @@ var SummaryTable = ({ result }) => {
|
|
|
89
138
|
paddingY: 1,
|
|
90
139
|
flexDirection: "column",
|
|
91
140
|
children: [
|
|
92
|
-
/* @__PURE__ */ jsxs3(Box3, { justifyContent: "space-between", children: [
|
|
93
|
-
/* @__PURE__ */ jsx3(Text3, { bold: true, color: hasErrors ? "red" : "green", children: hasErrors ? "[COMPILATION
|
|
94
|
-
/* @__PURE__ */ jsxs3(
|
|
95
|
-
|
|
96
|
-
"
|
|
141
|
+
/* @__PURE__ */ jsxs3(Box3, { justifyContent: "space-between", alignItems: "center", children: [
|
|
142
|
+
/* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: hasErrors ? "red" : "green", children: hasErrors ? "[COMPILATION FAILED]" : "[COMPILATION SUCCESSFUL]" }) }),
|
|
143
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
144
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Duration: " }),
|
|
145
|
+
/* @__PURE__ */ jsxs3(Text3, { color: "yellow", bold: true, children: [
|
|
146
|
+
result.durationMs,
|
|
147
|
+
"ms"
|
|
148
|
+
] })
|
|
97
149
|
] })
|
|
98
150
|
] }),
|
|
99
|
-
/* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
|
|
151
|
+
result.files.length > 0 && /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
|
|
100
152
|
/* @__PURE__ */ jsxs3(Text3, { bold: true, color: "white", children: [
|
|
101
|
-
"
|
|
153
|
+
"Generated Documents (",
|
|
102
154
|
result.files.length,
|
|
103
155
|
"):"
|
|
104
156
|
] }),
|
|
105
|
-
result.files.map((f, i) =>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
157
|
+
result.files.map((f, i) => {
|
|
158
|
+
const formatColor = f.format === "docx" ? "blue" : f.format === "pdf" ? "red" : "yellow";
|
|
159
|
+
const paddedBadge = `[${f.format.toUpperCase()}]`.padEnd(7, " ");
|
|
160
|
+
return /* @__PURE__ */ jsxs3(Box3, { marginTop: 0, flexDirection: "column", marginLeft: 1, children: [
|
|
161
|
+
/* @__PURE__ */ jsxs3(Box3, { justifyContent: "space-between", alignItems: "center", children: [
|
|
162
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
163
|
+
/* @__PURE__ */ jsx3(Text3, { color: formatColor, bold: true, children: paddedBadge }),
|
|
164
|
+
/* @__PURE__ */ jsx3(Text3, { color: "white", bold: true, children: f.fileName })
|
|
165
|
+
] }),
|
|
166
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: formatBytes(f.sizeBytes) })
|
|
111
167
|
] }),
|
|
112
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
] }, i))
|
|
168
|
+
/* @__PURE__ */ jsx3(Box3, { marginLeft: 2, children: /* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
169
|
+
"\u2514\u2500 ",
|
|
170
|
+
formatDisplayPath2(f.filePath)
|
|
171
|
+
] }) })
|
|
172
|
+
] }, i);
|
|
173
|
+
})
|
|
119
174
|
] }),
|
|
120
175
|
hasErrors && /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
|
|
121
176
|
/* @__PURE__ */ jsx3(Text3, { bold: true, color: "red", children: "Errors:" }),
|
|
@@ -123,6 +178,17 @@ var SummaryTable = ({ result }) => {
|
|
|
123
178
|
"- ",
|
|
124
179
|
err
|
|
125
180
|
] }) }, i))
|
|
181
|
+
] }),
|
|
182
|
+
/* @__PURE__ */ jsxs3(Box3, { marginTop: 1, justifyContent: "space-between", alignItems: "center", children: [
|
|
183
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
184
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Author: " }),
|
|
185
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: "Ma'sum" }),
|
|
186
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: " (@masumrpg)" })
|
|
187
|
+
] }),
|
|
188
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
189
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "GitHub: " }),
|
|
190
|
+
/* @__PURE__ */ jsx3(Text3, { color: "blue", underline: true, children: "https://github.com/masumrpg" })
|
|
191
|
+
] })
|
|
126
192
|
] })
|
|
127
193
|
]
|
|
128
194
|
}
|
|
@@ -131,7 +197,7 @@ var SummaryTable = ({ result }) => {
|
|
|
131
197
|
|
|
132
198
|
// src/core/engine.ts
|
|
133
199
|
import * as fs5 from "fs";
|
|
134
|
-
import * as
|
|
200
|
+
import * as path7 from "path";
|
|
135
201
|
|
|
136
202
|
// src/core/parser.ts
|
|
137
203
|
import matter from "gray-matter";
|
|
@@ -525,7 +591,7 @@ import {
|
|
|
525
591
|
|
|
526
592
|
// src/core/imageResolver.ts
|
|
527
593
|
import * as fs from "fs";
|
|
528
|
-
import * as
|
|
594
|
+
import * as path3 from "path";
|
|
529
595
|
var memoryImageCache = /* @__PURE__ */ new Map();
|
|
530
596
|
function getMimeType(filePathOrUrl) {
|
|
531
597
|
const clean = filePathOrUrl.split("?")[0].toLowerCase();
|
|
@@ -582,7 +648,7 @@ async function resolveImage(src, baseDir = process.cwd()) {
|
|
|
582
648
|
memoryImageCache.set(cacheKey, resolved2);
|
|
583
649
|
return resolved2;
|
|
584
650
|
}
|
|
585
|
-
const localPath =
|
|
651
|
+
const localPath = path3.isAbsolute(src) ? src : path3.resolve(baseDir, src);
|
|
586
652
|
if (!fs.existsSync(localPath)) {
|
|
587
653
|
return null;
|
|
588
654
|
}
|
|
@@ -649,6 +715,51 @@ var SYNTAX_COLORS_LIGHT = {
|
|
|
649
715
|
plain: "24292E"
|
|
650
716
|
// Near-black — identifiers
|
|
651
717
|
};
|
|
718
|
+
var SYNTAX_THEMES = {
|
|
719
|
+
"github-dark": SYNTAX_COLORS,
|
|
720
|
+
"dark": SYNTAX_COLORS,
|
|
721
|
+
"github-light": SYNTAX_COLORS_LIGHT,
|
|
722
|
+
"light": SYNTAX_COLORS_LIGHT,
|
|
723
|
+
"dracula": {
|
|
724
|
+
keyword: "FF79C6",
|
|
725
|
+
string: "F1FA8C",
|
|
726
|
+
comment: "6272A4",
|
|
727
|
+
number: "BD93F9",
|
|
728
|
+
boolean: "BD93F9",
|
|
729
|
+
function: "50FA7B",
|
|
730
|
+
type: "8BE9FD",
|
|
731
|
+
operator: "FF79C6",
|
|
732
|
+
punctuation: "F8F8F2",
|
|
733
|
+
plain: "F8F8F2"
|
|
734
|
+
},
|
|
735
|
+
"monokai": {
|
|
736
|
+
keyword: "F92672",
|
|
737
|
+
string: "E6DB74",
|
|
738
|
+
comment: "75715E",
|
|
739
|
+
number: "AE81FF",
|
|
740
|
+
boolean: "AE81FF",
|
|
741
|
+
function: "A6E22E",
|
|
742
|
+
type: "66D9EF",
|
|
743
|
+
operator: "F92672",
|
|
744
|
+
punctuation: "F8F8F2",
|
|
745
|
+
plain: "F8F8F2"
|
|
746
|
+
},
|
|
747
|
+
"nord": {
|
|
748
|
+
keyword: "81A1C1",
|
|
749
|
+
string: "A3BE8C",
|
|
750
|
+
comment: "616E88",
|
|
751
|
+
number: "B48EAD",
|
|
752
|
+
boolean: "81A1C1",
|
|
753
|
+
function: "88C0D0",
|
|
754
|
+
type: "8FBCBB",
|
|
755
|
+
operator: "81A1C1",
|
|
756
|
+
punctuation: "ECEFF4",
|
|
757
|
+
plain: "D8DEE9"
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
function getSyntaxPalette(themeName = "github-dark") {
|
|
761
|
+
return SYNTAX_THEMES[themeName.toLowerCase()] || SYNTAX_THEMES["github-dark"];
|
|
762
|
+
}
|
|
652
763
|
var JS_KEYWORDS = /* @__PURE__ */ new Set([
|
|
653
764
|
"import",
|
|
654
765
|
"from",
|
|
@@ -792,9 +903,9 @@ var SQL_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
792
903
|
"foreign",
|
|
793
904
|
"references"
|
|
794
905
|
]);
|
|
795
|
-
function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
906
|
+
function tokenizeCodeLine(line, lang = "", theme = "github-dark") {
|
|
796
907
|
var _a;
|
|
797
|
-
const COLORS = theme
|
|
908
|
+
const COLORS = getSyntaxPalette(theme);
|
|
798
909
|
if (!line) {
|
|
799
910
|
return [{ text: " ", type: "plain", colorHex: COLORS.plain }];
|
|
800
911
|
}
|
|
@@ -877,6 +988,10 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
877
988
|
tokens.push({ text: word, type: "keyword", colorHex: COLORS.keyword, bold: true });
|
|
878
989
|
continue;
|
|
879
990
|
}
|
|
991
|
+
if (/^[A-Z][a-zA-Z0-9_$]*$/.test(word)) {
|
|
992
|
+
tokens.push({ text: word, type: "type", colorHex: COLORS.type });
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
880
995
|
let nextNonWs = pos;
|
|
881
996
|
while (nextNonWs < line.length && /\s/.test(line[nextNonWs])) {
|
|
882
997
|
nextNonWs++;
|
|
@@ -885,10 +1000,6 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
885
1000
|
tokens.push({ text: word, type: "function", colorHex: COLORS.function });
|
|
886
1001
|
continue;
|
|
887
1002
|
}
|
|
888
|
-
if (/^[A-Z][a-zA-Z0-9_$]*$/.test(word)) {
|
|
889
|
-
tokens.push({ text: word, type: "type", colorHex: COLORS.type });
|
|
890
|
-
continue;
|
|
891
|
-
}
|
|
892
1003
|
tokens.push({ text: word, type: "plain", colorHex: COLORS.plain });
|
|
893
1004
|
continue;
|
|
894
1005
|
}
|
|
@@ -901,10 +1012,10 @@ function tokenizeCodeLine(line, lang = "", theme = "dark") {
|
|
|
901
1012
|
}
|
|
902
1013
|
return tokens;
|
|
903
1014
|
}
|
|
904
|
-
function highlightCodeToHtml(code, lang = "") {
|
|
1015
|
+
function highlightCodeToHtml(code, lang = "", theme = "github-dark") {
|
|
905
1016
|
const lines = (code || "").split("\n");
|
|
906
1017
|
const htmlLines = lines.map((line) => {
|
|
907
|
-
const tokens = tokenizeCodeLine(line, lang);
|
|
1018
|
+
const tokens = tokenizeCodeLine(line, lang, theme);
|
|
908
1019
|
return tokens.map((t) => {
|
|
909
1020
|
const escaped = t.text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
910
1021
|
if (t.type === "plain") return escaped;
|
|
@@ -918,19 +1029,19 @@ function highlightCodeToHtml(code, lang = "") {
|
|
|
918
1029
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
919
1030
|
import * as fs4 from "fs";
|
|
920
1031
|
import * as os2 from "os";
|
|
921
|
-
import * as
|
|
1032
|
+
import * as path6 from "path";
|
|
922
1033
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
923
1034
|
|
|
924
1035
|
// src/core/pdf/pdfBuilder.ts
|
|
925
1036
|
import * as fs3 from "fs";
|
|
926
|
-
import * as
|
|
1037
|
+
import * as path5 from "path";
|
|
927
1038
|
import * as os from "os";
|
|
928
1039
|
import { pathToFileURL } from "url";
|
|
929
1040
|
import { spawnSync } from "child_process";
|
|
930
1041
|
|
|
931
1042
|
// src/core/html/htmlBuilder.ts
|
|
932
1043
|
import * as fs2 from "fs";
|
|
933
|
-
import * as
|
|
1044
|
+
import * as path4 from "path";
|
|
934
1045
|
|
|
935
1046
|
// src/core/html/htmlThemes.ts
|
|
936
1047
|
var THEME_COMPONENTS = `
|
|
@@ -1013,7 +1124,7 @@ hr { border: none; border-top: 1px solid var(--mf-border); margin: 2rem 0; }
|
|
|
1013
1124
|
pre { overflow: visible; white-space: pre-wrap; word-break: break-all; }
|
|
1014
1125
|
}
|
|
1015
1126
|
`;
|
|
1016
|
-
var
|
|
1127
|
+
var THEME_CORPORATE = `
|
|
1017
1128
|
:root {
|
|
1018
1129
|
--mf-bg: #ffffff;
|
|
1019
1130
|
--mf-text: #0f172a;
|
|
@@ -1025,49 +1136,330 @@ var THEME_DEFAULT = `
|
|
|
1025
1136
|
--mf-card-bg: #f8fafc;
|
|
1026
1137
|
--mf-code-bg: #0f172a;
|
|
1027
1138
|
--mf-code-text: #f8fafc;
|
|
1028
|
-
--mf-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
1139
|
+
--mf-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
1029
1140
|
--mf-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
1030
1141
|
}
|
|
1031
1142
|
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; }
|
|
1032
|
-
.document-container { max-width: 860px; margin: 0 auto; }
|
|
1143
|
+
.document-container { max-width: 860px; margin: 0 auto; position: relative; z-index: 1; }
|
|
1033
1144
|
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; }
|
|
1034
|
-
h1 { font-size: 2.2rem; border-bottom: 2px solid
|
|
1035
|
-
h2 { font-size: 1.6rem; color:
|
|
1145
|
+
h1 { font-size: 2.2rem; border-bottom: 2px solid var(--mf-primary); padding-bottom: 0.5rem; }
|
|
1146
|
+
h2 { font-size: 1.6rem; color: var(--mf-primary-dark); border-bottom: 1px solid #CCFBF1; padding-bottom: 0.4rem; }
|
|
1036
1147
|
h3 { font-size: 1.3rem; }
|
|
1037
1148
|
h4 { font-size: 1.1rem; }
|
|
1038
1149
|
p { margin: 0.8rem 0; }
|
|
1039
1150
|
`;
|
|
1040
|
-
var
|
|
1151
|
+
var THEMES = {
|
|
1152
|
+
corporate: THEME_CORPORATE,
|
|
1153
|
+
default: THEME_CORPORATE
|
|
1154
|
+
};
|
|
1155
|
+
function generateThemeCss(theme) {
|
|
1156
|
+
if (!theme || theme === "corporate" || theme === "default" || theme === "corporate" /* CORPORATE */) {
|
|
1157
|
+
return THEME_CORPORATE;
|
|
1158
|
+
}
|
|
1159
|
+
if (typeof theme === "object") {
|
|
1160
|
+
const bg = theme.backgroundColor || "#ffffff";
|
|
1161
|
+
const text = theme.textColor || "#0f172a";
|
|
1162
|
+
const textMuted = theme.textMuted || "#64748b";
|
|
1163
|
+
const primary = theme.primaryColor || "#33CDCF";
|
|
1164
|
+
const primaryDark = theme.primaryDark || primary;
|
|
1165
|
+
const primaryLight = theme.primaryLight || "#ECFDFD";
|
|
1166
|
+
const border = theme.borderColor || "#e2e8f0";
|
|
1167
|
+
const cardBg = theme.cardBackground || "#f8fafc";
|
|
1168
|
+
const codeBg = theme.codeBackground || "#0f172a";
|
|
1169
|
+
const codeText = theme.codeText || "#f8fafc";
|
|
1170
|
+
const font = theme.fontFamily || "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
|
|
1171
|
+
const fontMono = theme.fontMono || "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace";
|
|
1172
|
+
return `
|
|
1041
1173
|
:root {
|
|
1042
|
-
--mf-bg:
|
|
1043
|
-
--mf-text:
|
|
1044
|
-
--mf-text-muted:
|
|
1045
|
-
--mf-primary:
|
|
1046
|
-
--mf-primary-dark:
|
|
1047
|
-
--mf-primary-light:
|
|
1048
|
-
--mf-border:
|
|
1049
|
-
--mf-card-bg:
|
|
1050
|
-
--mf-code-bg:
|
|
1051
|
-
--mf-code-text:
|
|
1052
|
-
--mf-font-family:
|
|
1053
|
-
--mf-font-mono:
|
|
1174
|
+
--mf-bg: ${bg};
|
|
1175
|
+
--mf-text: ${text};
|
|
1176
|
+
--mf-text-muted: ${textMuted};
|
|
1177
|
+
--mf-primary: ${primary};
|
|
1178
|
+
--mf-primary-dark: ${primaryDark};
|
|
1179
|
+
--mf-primary-light: ${primaryLight};
|
|
1180
|
+
--mf-border: ${border};
|
|
1181
|
+
--mf-card-bg: ${cardBg};
|
|
1182
|
+
--mf-code-bg: ${codeBg};
|
|
1183
|
+
--mf-code-text: ${codeText};
|
|
1184
|
+
--mf-font-family: ${font};
|
|
1185
|
+
--mf-font-mono: ${fontMono};
|
|
1054
1186
|
}
|
|
1055
|
-
body { font-family: var(--mf-font-family); font-size:
|
|
1056
|
-
.document-container { max-width:
|
|
1057
|
-
h1, h2, h3 { font-
|
|
1058
|
-
h1 { font-size: 2rem; border-bottom:
|
|
1059
|
-
h2 { font-size: 1.
|
|
1060
|
-
h3 { font-size: 1.
|
|
1061
|
-
|
|
1187
|
+
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; }
|
|
1188
|
+
.document-container { max-width: 860px; margin: 0 auto; position: relative; z-index: 1; }
|
|
1189
|
+
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; }
|
|
1190
|
+
h1 { font-size: 2.2rem; border-bottom: 2px solid var(--mf-primary); padding-bottom: 0.5rem; }
|
|
1191
|
+
h2 { font-size: 1.6rem; color: var(--mf-primary-dark); border-bottom: 1px solid var(--mf-border); padding-bottom: 0.4rem; }
|
|
1192
|
+
h3 { font-size: 1.3rem; }
|
|
1193
|
+
h4 { font-size: 1.1rem; }
|
|
1194
|
+
p { margin: 0.8rem 0; }
|
|
1195
|
+
${theme.customCss || ""}
|
|
1062
1196
|
`;
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1197
|
+
}
|
|
1198
|
+
if (typeof theme === "string" && THEMES[theme]) {
|
|
1199
|
+
return THEMES[theme];
|
|
1200
|
+
}
|
|
1201
|
+
return THEME_CORPORATE;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// src/config/resolveConfig.ts
|
|
1205
|
+
var PAPER_DIMENSIONS_TWIP = {
|
|
1206
|
+
A4: { width: 11906, height: 16838 },
|
|
1207
|
+
// 210mm x 297mm
|
|
1208
|
+
Letter: { width: 12240, height: 15840 },
|
|
1209
|
+
// 8.5in x 11in
|
|
1210
|
+
Legal: { width: 12240, height: 20160 },
|
|
1211
|
+
// 8.5in x 14in
|
|
1212
|
+
A3: { width: 16838, height: 23811 },
|
|
1213
|
+
// 297mm x 420mm
|
|
1214
|
+
A5: { width: 8390, height: 11906 }
|
|
1215
|
+
// 148mm x 210mm
|
|
1070
1216
|
};
|
|
1217
|
+
function parseMarginToTwip(margin, defaultTwip = 1440) {
|
|
1218
|
+
if (typeof margin === "number") return margin;
|
|
1219
|
+
if (!margin) return defaultTwip;
|
|
1220
|
+
const str = margin.trim().toLowerCase();
|
|
1221
|
+
if (str.endsWith("cm")) {
|
|
1222
|
+
const cm = parseFloat(str);
|
|
1223
|
+
return isNaN(cm) ? defaultTwip : Math.round(cm * 566.929);
|
|
1224
|
+
}
|
|
1225
|
+
if (str.endsWith("mm")) {
|
|
1226
|
+
const mm = parseFloat(str);
|
|
1227
|
+
return isNaN(mm) ? defaultTwip : Math.round(mm * 56.6929);
|
|
1228
|
+
}
|
|
1229
|
+
if (str.endsWith("in") || str.endsWith("inch")) {
|
|
1230
|
+
const inch = parseFloat(str);
|
|
1231
|
+
return isNaN(inch) ? defaultTwip : Math.round(inch * 1440);
|
|
1232
|
+
}
|
|
1233
|
+
if (str.endsWith("pt")) {
|
|
1234
|
+
const pt = parseFloat(str);
|
|
1235
|
+
return isNaN(pt) ? defaultTwip : Math.round(pt * 20);
|
|
1236
|
+
}
|
|
1237
|
+
const val = parseFloat(str);
|
|
1238
|
+
return isNaN(val) ? defaultTwip : Math.round(val);
|
|
1239
|
+
}
|
|
1240
|
+
function formatMarginCss(margin, defaultCss = "2.5cm") {
|
|
1241
|
+
if (margin === void 0 || margin === null) return defaultCss;
|
|
1242
|
+
if (typeof margin === "number") return `${margin}pt`;
|
|
1243
|
+
const str = margin.trim();
|
|
1244
|
+
if (!str) return defaultCss;
|
|
1245
|
+
if (/^[0-9.]+$/.test(str)) return `${str}pt`;
|
|
1246
|
+
return str;
|
|
1247
|
+
}
|
|
1248
|
+
function replaceDocumentTokens(template = "", meta) {
|
|
1249
|
+
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 || "");
|
|
1250
|
+
}
|
|
1251
|
+
function normalizeWatermark(rawWatermark) {
|
|
1252
|
+
if (!rawWatermark) {
|
|
1253
|
+
return void 0;
|
|
1254
|
+
}
|
|
1255
|
+
if (typeof rawWatermark === "string") {
|
|
1256
|
+
const text = rawWatermark.trim();
|
|
1257
|
+
if (!text) return void 0;
|
|
1258
|
+
return {
|
|
1259
|
+
text,
|
|
1260
|
+
color: "#94a3b8",
|
|
1261
|
+
opacity: 0.08,
|
|
1262
|
+
fontSize: 54,
|
|
1263
|
+
rotate: -45,
|
|
1264
|
+
position: "diagonal"
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
if (typeof rawWatermark === "object") {
|
|
1268
|
+
if (!rawWatermark.text || !rawWatermark.text.trim()) return void 0;
|
|
1269
|
+
return {
|
|
1270
|
+
text: rawWatermark.text.trim(),
|
|
1271
|
+
color: rawWatermark.color || "#94a3b8",
|
|
1272
|
+
opacity: typeof rawWatermark.opacity === "number" ? rawWatermark.opacity : 0.08,
|
|
1273
|
+
fontSize: rawWatermark.fontSize || 54,
|
|
1274
|
+
rotate: typeof rawWatermark.rotate === "number" ? rawWatermark.rotate : -45,
|
|
1275
|
+
position: rawWatermark.position || "diagonal"
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
return void 0;
|
|
1279
|
+
}
|
|
1280
|
+
function normalizeHeaderFooterSlot(rawSlot, parent, meta) {
|
|
1281
|
+
if (!rawSlot) return void 0;
|
|
1282
|
+
if (typeof rawSlot === "string") {
|
|
1283
|
+
const text = replaceDocumentTokens(rawSlot, meta).trim();
|
|
1284
|
+
if (!text) return void 0;
|
|
1285
|
+
return {
|
|
1286
|
+
text,
|
|
1287
|
+
color: (parent == null ? void 0 : parent.color) || "#94A3B8",
|
|
1288
|
+
fontSize: (parent == null ? void 0 : parent.size) || 9,
|
|
1289
|
+
fontFamily: (parent == null ? void 0 : parent.font) || "Segoe UI",
|
|
1290
|
+
bold: false,
|
|
1291
|
+
italic: false
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
if (typeof rawSlot === "object") {
|
|
1295
|
+
const text = replaceDocumentTokens(rawSlot.text || "", meta).trim();
|
|
1296
|
+
if (!text) return void 0;
|
|
1297
|
+
return {
|
|
1298
|
+
text,
|
|
1299
|
+
color: rawSlot.color || (parent == null ? void 0 : parent.color) || "#94A3B8",
|
|
1300
|
+
fontSize: rawSlot.fontSize || (parent == null ? void 0 : parent.size) || 9,
|
|
1301
|
+
fontFamily: rawSlot.fontFamily || (parent == null ? void 0 : parent.font) || "Segoe UI",
|
|
1302
|
+
bold: Boolean(rawSlot.bold),
|
|
1303
|
+
italic: Boolean(rawSlot.italic)
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
return void 0;
|
|
1307
|
+
}
|
|
1308
|
+
function normalizeHeaderFooter(raw, meta) {
|
|
1309
|
+
if (!raw) return void 0;
|
|
1310
|
+
const left = normalizeHeaderFooterSlot(raw.left, raw, meta);
|
|
1311
|
+
const center = normalizeHeaderFooterSlot(raw.center, raw, meta);
|
|
1312
|
+
const right = normalizeHeaderFooterSlot(raw.right, raw, meta);
|
|
1313
|
+
if (!left && !center && !right) return void 0;
|
|
1314
|
+
return {
|
|
1315
|
+
left,
|
|
1316
|
+
center,
|
|
1317
|
+
right,
|
|
1318
|
+
font: raw.font || "Segoe UI",
|
|
1319
|
+
size: raw.size || 9,
|
|
1320
|
+
color: raw.color || "#94A3B8",
|
|
1321
|
+
divider: Boolean(raw.divider),
|
|
1322
|
+
dividerColor: raw.dividerColor || "#E2E8F0"
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
function normalizeSignatures(raw, meta = {}) {
|
|
1326
|
+
if (!raw) return void 0;
|
|
1327
|
+
let rawItems = [];
|
|
1328
|
+
let rawConfig = {};
|
|
1329
|
+
if (Array.isArray(raw)) {
|
|
1330
|
+
rawItems = raw;
|
|
1331
|
+
} else if (typeof raw === "object" && Array.isArray(raw.items)) {
|
|
1332
|
+
rawItems = raw.items;
|
|
1333
|
+
rawConfig = raw;
|
|
1334
|
+
}
|
|
1335
|
+
if (rawItems.length === 0) return void 0;
|
|
1336
|
+
const cappedItems = rawItems.slice(0, 4);
|
|
1337
|
+
const items = cappedItems.map((item) => {
|
|
1338
|
+
const tokenCtx = meta;
|
|
1339
|
+
const rawName = typeof item.name === "string" ? item.name : "";
|
|
1340
|
+
const name = replaceDocumentTokens(rawName, tokenCtx).trim();
|
|
1341
|
+
const title = item.title ? replaceDocumentTokens(item.title, tokenCtx).trim() : void 0;
|
|
1342
|
+
const role = item.role ? replaceDocumentTokens(item.role, tokenCtx).trim() : void 0;
|
|
1343
|
+
let dateStr;
|
|
1344
|
+
if (typeof item.date === "string") {
|
|
1345
|
+
dateStr = replaceDocumentTokens(item.date, tokenCtx).trim();
|
|
1346
|
+
} else if (item.date === true) {
|
|
1347
|
+
dateStr = meta.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1348
|
+
}
|
|
1349
|
+
let signatureHeight = 60;
|
|
1350
|
+
if (typeof item.signatureHeight === "number") {
|
|
1351
|
+
signatureHeight = item.signatureHeight;
|
|
1352
|
+
} else if (typeof item.signatureHeight === "string") {
|
|
1353
|
+
const parsed = parseFloat(item.signatureHeight);
|
|
1354
|
+
if (!isNaN(parsed)) signatureHeight = parsed;
|
|
1355
|
+
}
|
|
1356
|
+
return {
|
|
1357
|
+
title,
|
|
1358
|
+
name: name || "Authorized Signatory",
|
|
1359
|
+
role,
|
|
1360
|
+
date: dateStr,
|
|
1361
|
+
image: item.image,
|
|
1362
|
+
signatureHeight
|
|
1363
|
+
};
|
|
1364
|
+
});
|
|
1365
|
+
const align = rawConfig.align || (items.length === 1 ? "right" : "space-between");
|
|
1366
|
+
const style = rawConfig.style || "line";
|
|
1367
|
+
const borderColor = rawConfig.borderColor || "#CBD5E1";
|
|
1368
|
+
const titleColor = rawConfig.titleColor || "#64748B";
|
|
1369
|
+
const nameColor = rawConfig.nameColor || "#0F172A";
|
|
1370
|
+
const roleColor = rawConfig.roleColor || "#64748B";
|
|
1371
|
+
const spacingBeforeRaw = rawConfig.spacingBefore ?? "2.5rem";
|
|
1372
|
+
const spacingBefore = formatMarginCss(spacingBeforeRaw, "2.5rem");
|
|
1373
|
+
const spacingBeforeTwip = parseMarginToTwip(spacingBeforeRaw, 600);
|
|
1374
|
+
return {
|
|
1375
|
+
items,
|
|
1376
|
+
align,
|
|
1377
|
+
style,
|
|
1378
|
+
borderColor,
|
|
1379
|
+
titleColor,
|
|
1380
|
+
nameColor,
|
|
1381
|
+
roleColor,
|
|
1382
|
+
spacingBefore,
|
|
1383
|
+
spacingBeforeTwip
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1386
|
+
function resolveDocumentConfig(frontmatter = {}, userConfig = {}) {
|
|
1387
|
+
const configMeta = userConfig.metadata || {};
|
|
1388
|
+
const mergedMeta = { ...configMeta, ...frontmatter };
|
|
1389
|
+
const title = mergedMeta.title || "MarkForge Document";
|
|
1390
|
+
const subtitle = mergedMeta.subtitle || void 0;
|
|
1391
|
+
const author = Array.isArray(mergedMeta.author) ? mergedMeta.author.join(", ") : mergedMeta.author || void 0;
|
|
1392
|
+
const date = mergedMeta.date || void 0;
|
|
1393
|
+
const version = mergedMeta.version || void 0;
|
|
1394
|
+
const company = mergedMeta.company || void 0;
|
|
1395
|
+
const lang = mergedMeta.lang || "en";
|
|
1396
|
+
const tokenContext = { title, subtitle, author, version, date, company };
|
|
1397
|
+
const theme = mergedMeta.theme || userConfig.theme || DEFAULT_CONFIG.theme;
|
|
1398
|
+
const orientation = mergedMeta.orientation || userConfig.orientation || DEFAULT_CONFIG.orientation;
|
|
1399
|
+
const paperSize = mergedMeta.paperSize || userConfig.paperSize || DEFAULT_CONFIG.paperSize;
|
|
1400
|
+
const baseDim = PAPER_DIMENSIONS_TWIP[paperSize] || PAPER_DIMENSIONS_TWIP.A4;
|
|
1401
|
+
const paperDimensions = orientation === "landscape" ? { widthTwip: baseDim.height, heightTwip: baseDim.width } : { widthTwip: baseDim.width, heightTwip: baseDim.height };
|
|
1402
|
+
const fmMargin = mergedMeta.margins || {};
|
|
1403
|
+
const cfgMargin = userConfig.margins || {};
|
|
1404
|
+
const defMargin = DEFAULT_CONFIG.margins || {};
|
|
1405
|
+
const topRaw = fmMargin.top ?? cfgMargin.top ?? defMargin.top ?? "2.5cm";
|
|
1406
|
+
const bottomRaw = fmMargin.bottom ?? cfgMargin.bottom ?? defMargin.bottom ?? "2.5cm";
|
|
1407
|
+
const leftRaw = fmMargin.left ?? cfgMargin.left ?? defMargin.left ?? "2.5cm";
|
|
1408
|
+
const rightRaw = fmMargin.right ?? cfgMargin.right ?? defMargin.right ?? "2.5cm";
|
|
1409
|
+
const margins = {
|
|
1410
|
+
top: formatMarginCss(topRaw),
|
|
1411
|
+
bottom: formatMarginCss(bottomRaw),
|
|
1412
|
+
left: formatMarginCss(leftRaw),
|
|
1413
|
+
right: formatMarginCss(rightRaw),
|
|
1414
|
+
topTwip: parseMarginToTwip(topRaw),
|
|
1415
|
+
bottomTwip: parseMarginToTwip(bottomRaw),
|
|
1416
|
+
leftTwip: parseMarginToTwip(leftRaw),
|
|
1417
|
+
rightTwip: parseMarginToTwip(rightRaw)
|
|
1418
|
+
};
|
|
1419
|
+
const rawHeader = mergedMeta.header || userConfig.header || DEFAULT_CONFIG.header;
|
|
1420
|
+
const rawFooter = mergedMeta.footer || userConfig.footer || DEFAULT_CONFIG.footer;
|
|
1421
|
+
const header = normalizeHeaderFooter(rawHeader, tokenContext);
|
|
1422
|
+
const footer = normalizeHeaderFooter(rawFooter, tokenContext);
|
|
1423
|
+
const toc = typeof mergedMeta.toc === "boolean" ? mergedMeta.toc : typeof userConfig.toc === "boolean" ? userConfig.toc : DEFAULT_CONFIG.toc;
|
|
1424
|
+
const rawWatermark = mergedMeta.watermark !== void 0 ? mergedMeta.watermark : userConfig.watermark !== void 0 ? userConfig.watermark : DEFAULT_CONFIG.watermark;
|
|
1425
|
+
const watermark = normalizeWatermark(rawWatermark);
|
|
1426
|
+
const rawSignatures = mergedMeta.signatures || userConfig.signatures;
|
|
1427
|
+
const signatures = normalizeSignatures(rawSignatures, tokenContext);
|
|
1428
|
+
const cssList = [];
|
|
1429
|
+
const addCss = (item) => {
|
|
1430
|
+
if (!item) return;
|
|
1431
|
+
if (Array.isArray(item)) cssList.push(...item);
|
|
1432
|
+
else cssList.push(item);
|
|
1433
|
+
};
|
|
1434
|
+
addCss(userConfig.css);
|
|
1435
|
+
addCss(mergedMeta.css);
|
|
1436
|
+
const embedImages = typeof userConfig.embedImages === "boolean" ? userConfig.embedImages : DEFAULT_CONFIG.embedImages;
|
|
1437
|
+
const bundleHtml = typeof userConfig.bundleHtml === "boolean" ? userConfig.bundleHtml : DEFAULT_CONFIG.bundleHtml;
|
|
1438
|
+
const syntaxTheme = userConfig.syntaxTheme || DEFAULT_CONFIG.syntaxTheme || "github-dark";
|
|
1439
|
+
return {
|
|
1440
|
+
title,
|
|
1441
|
+
subtitle,
|
|
1442
|
+
author,
|
|
1443
|
+
date,
|
|
1444
|
+
version,
|
|
1445
|
+
company,
|
|
1446
|
+
lang,
|
|
1447
|
+
theme,
|
|
1448
|
+
orientation,
|
|
1449
|
+
paperSize,
|
|
1450
|
+
paperDimensions,
|
|
1451
|
+
margins,
|
|
1452
|
+
header,
|
|
1453
|
+
footer,
|
|
1454
|
+
toc,
|
|
1455
|
+
signatures,
|
|
1456
|
+
watermark,
|
|
1457
|
+
css: cssList,
|
|
1458
|
+
embedImages,
|
|
1459
|
+
bundleHtml,
|
|
1460
|
+
syntaxTheme
|
|
1461
|
+
};
|
|
1462
|
+
}
|
|
1071
1463
|
|
|
1072
1464
|
// src/core/html/htmlBuilder.ts
|
|
1073
1465
|
function escapeHtml(str) {
|
|
@@ -1120,43 +1512,41 @@ async function renderInlinesToHtml(spans = [], baseDir = process.cwd()) {
|
|
|
1120
1512
|
return result;
|
|
1121
1513
|
}
|
|
1122
1514
|
async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
1123
|
-
|
|
1124
|
-
const
|
|
1125
|
-
const themeName = metadata.theme || config.theme || "default";
|
|
1126
|
-
const baseThemeCss = THEMES[themeName] || THEMES.default;
|
|
1515
|
+
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
1516
|
+
const baseThemeCss = generateThemeCss(resolved.theme);
|
|
1127
1517
|
let customCss = "";
|
|
1128
|
-
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
if (fs2.existsSync(fullCssPath)) {
|
|
1133
|
-
customCss += `
|
|
1518
|
+
for (const cssPath of resolved.css) {
|
|
1519
|
+
const fullCssPath = path4.isAbsolute(cssPath) ? cssPath : path4.resolve(baseDir, cssPath);
|
|
1520
|
+
if (fs2.existsSync(fullCssPath)) {
|
|
1521
|
+
customCss += `
|
|
1134
1522
|
/* Custom CSS: ${cssPath} */
|
|
1135
1523
|
` + fs2.readFileSync(fullCssPath, "utf-8");
|
|
1136
|
-
}
|
|
1137
1524
|
}
|
|
1138
1525
|
}
|
|
1139
1526
|
const inlinedCss = doc.inlinedStyles.join("\n");
|
|
1140
1527
|
let bodyHtml = "";
|
|
1141
|
-
if (
|
|
1528
|
+
if (resolved.title) {
|
|
1142
1529
|
bodyHtml += ` <header class="document-header">
|
|
1143
1530
|
`;
|
|
1144
|
-
bodyHtml += ` <h1 class="document-title">${escapeHtml(
|
|
1531
|
+
bodyHtml += ` <h1 class="document-title">${escapeHtml(resolved.title)}</h1>
|
|
1145
1532
|
`;
|
|
1146
|
-
if (
|
|
1147
|
-
bodyHtml += ` <div class="document-subtitle">${escapeHtml(
|
|
1533
|
+
if (resolved.subtitle) {
|
|
1534
|
+
bodyHtml += ` <div class="document-subtitle">${escapeHtml(resolved.subtitle)}</div>
|
|
1148
1535
|
`;
|
|
1149
1536
|
}
|
|
1150
|
-
if (
|
|
1537
|
+
if (resolved.author || resolved.date || resolved.version) {
|
|
1151
1538
|
bodyHtml += ` <div class="document-meta">
|
|
1152
1539
|
`;
|
|
1153
|
-
if (
|
|
1154
|
-
|
|
1155
|
-
bodyHtml += ` <span>Author: ${escapeHtml(authors)}</span>
|
|
1540
|
+
if (resolved.author) {
|
|
1541
|
+
bodyHtml += ` <span>Author: ${escapeHtml(resolved.author)}</span>
|
|
1156
1542
|
`;
|
|
1157
1543
|
}
|
|
1158
|
-
if (
|
|
1159
|
-
bodyHtml += ` <span>
|
|
1544
|
+
if (resolved.version) {
|
|
1545
|
+
bodyHtml += ` <span>Version: ${escapeHtml(resolved.version)}</span>
|
|
1546
|
+
`;
|
|
1547
|
+
}
|
|
1548
|
+
if (resolved.date) {
|
|
1549
|
+
bodyHtml += ` <span>Date: ${escapeHtml(resolved.date)}</span>
|
|
1160
1550
|
`;
|
|
1161
1551
|
}
|
|
1162
1552
|
bodyHtml += ` </div>
|
|
@@ -1165,22 +1555,20 @@ async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1165
1555
|
bodyHtml += ` </header>
|
|
1166
1556
|
`;
|
|
1167
1557
|
}
|
|
1168
|
-
if (
|
|
1169
|
-
|
|
1170
|
-
bodyHtml += ` <nav class="table-of-contents">
|
|
1558
|
+
if (resolved.toc && doc.tocEntries.length > 0) {
|
|
1559
|
+
bodyHtml += ` <nav class="table-of-contents">
|
|
1171
1560
|
`;
|
|
1172
|
-
|
|
1561
|
+
bodyHtml += ` <h2>Table of Contents</h2>
|
|
1173
1562
|
<ul>
|
|
1174
1563
|
`;
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1564
|
+
for (const entry of doc.tocEntries) {
|
|
1565
|
+
const indent = " ".repeat(entry.level);
|
|
1566
|
+
bodyHtml += ` ${indent}<li><a href="#${entry.id}">${escapeHtml(entry.text)}</a></li>
|
|
1178
1567
|
`;
|
|
1179
|
-
|
|
1180
|
-
|
|
1568
|
+
}
|
|
1569
|
+
bodyHtml += ` </ul>
|
|
1181
1570
|
</nav>
|
|
1182
1571
|
`;
|
|
1183
|
-
}
|
|
1184
1572
|
}
|
|
1185
1573
|
for (const node of doc.nodes) {
|
|
1186
1574
|
if (node.type === "heading") {
|
|
@@ -1198,7 +1586,7 @@ async function buildHtmlDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1198
1586
|
if (node.type === "codeBlock") {
|
|
1199
1587
|
const lang = node.language || "";
|
|
1200
1588
|
const langClass = lang ? ` class="language-${escapeHtml(lang)}"` : "";
|
|
1201
|
-
const highlighted = highlightCodeToHtml(node.text || "", lang);
|
|
1589
|
+
const highlighted = highlightCodeToHtml(node.text || "", lang, resolved.syntaxTheme);
|
|
1202
1590
|
bodyHtml += ` <pre><code${langClass}>${highlighted}</code></pre>
|
|
1203
1591
|
`;
|
|
1204
1592
|
continue;
|
|
@@ -1242,15 +1630,12 @@ ${escapeHtml(node.text || "")}
|
|
|
1242
1630
|
for (const row of node.children) {
|
|
1243
1631
|
bodyHtml += ` <tr>
|
|
1244
1632
|
`;
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
const cellInner = await renderInlinesToHtml(cell.inlines, baseDir);
|
|
1251
|
-
bodyHtml += ` <${tag}${align}>${cellInner}</${tag}>
|
|
1633
|
+
for (const cell of row.children || []) {
|
|
1634
|
+
const tag = cell.isHeader ? "th" : "td";
|
|
1635
|
+
const align = cell.align ? ` align="${cell.align}"` : "";
|
|
1636
|
+
const inner = await renderInlinesToHtml(cell.inlines, baseDir);
|
|
1637
|
+
bodyHtml += ` <${tag}${align}>${inner}</${tag}>
|
|
1252
1638
|
`;
|
|
1253
|
-
}
|
|
1254
1639
|
}
|
|
1255
1640
|
bodyHtml += ` </tr>
|
|
1256
1641
|
`;
|
|
@@ -1264,57 +1649,186 @@ ${escapeHtml(node.text || "")}
|
|
|
1264
1649
|
bodyHtml += ` <${tag}>
|
|
1265
1650
|
`;
|
|
1266
1651
|
for (const item of node.children) {
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1269
|
-
if (item.checked !== void 0) {
|
|
1270
|
-
prefix = `<input type="checkbox" disabled ${item.checked ? "checked" : ""}/> `;
|
|
1271
|
-
}
|
|
1272
|
-
bodyHtml += ` <li>${prefix}${itemInner}</li>
|
|
1652
|
+
const inner = await renderInlinesToHtml(item.inlines, baseDir);
|
|
1653
|
+
bodyHtml += ` <li>${inner}</li>
|
|
1273
1654
|
`;
|
|
1274
1655
|
}
|
|
1275
1656
|
bodyHtml += ` </${tag}>
|
|
1276
1657
|
`;
|
|
1277
1658
|
continue;
|
|
1278
1659
|
}
|
|
1279
|
-
if (node.type === "
|
|
1280
|
-
bodyHtml += `
|
|
1660
|
+
if (node.type === "thematicBreak") {
|
|
1661
|
+
bodyHtml += ` <hr />
|
|
1281
1662
|
`;
|
|
1282
1663
|
continue;
|
|
1283
1664
|
}
|
|
1284
|
-
if (node.type === "
|
|
1285
|
-
bodyHtml += `
|
|
1665
|
+
if (node.type === "htmlBlock") {
|
|
1666
|
+
bodyHtml += ` ${node.text}
|
|
1286
1667
|
`;
|
|
1287
1668
|
continue;
|
|
1288
1669
|
}
|
|
1289
1670
|
}
|
|
1290
|
-
const wmConfig = config.watermark ?? metadata.watermark;
|
|
1291
|
-
let watermarkHtml = "";
|
|
1292
1671
|
let watermarkCss = "";
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
const
|
|
1296
|
-
const rotate = typeof wmConfig === "object" && wmConfig.rotate !== void 0 ? wmConfig.rotate : -45;
|
|
1297
|
-
const color = typeof wmConfig === "object" && wmConfig.color ? wmConfig.color : "#94A3B8";
|
|
1298
|
-
const fontSize = typeof wmConfig === "object" && wmConfig.fontSize ? `${wmConfig.fontSize}pt` : "52pt";
|
|
1672
|
+
let watermarkHtml = "";
|
|
1673
|
+
if (resolved.watermark) {
|
|
1674
|
+
const wm = resolved.watermark;
|
|
1299
1675
|
watermarkCss = `
|
|
1300
1676
|
.document-watermark {
|
|
1301
1677
|
position: fixed;
|
|
1302
|
-
top:
|
|
1303
|
-
left:
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
font-weight: 800;
|
|
1307
|
-
color: ${color};
|
|
1308
|
-
opacity: ${opacity};
|
|
1678
|
+
top: 0;
|
|
1679
|
+
left: 0;
|
|
1680
|
+
width: 100vw;
|
|
1681
|
+
height: 100vh;
|
|
1309
1682
|
pointer-events: none;
|
|
1683
|
+
z-index: 0;
|
|
1310
1684
|
user-select: none;
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1685
|
+
-webkit-user-select: none;
|
|
1686
|
+
}
|
|
1687
|
+
.document-container {
|
|
1688
|
+
position: relative;
|
|
1689
|
+
z-index: 1;
|
|
1690
|
+
}
|
|
1691
|
+
@media print {
|
|
1692
|
+
.document-watermark {
|
|
1693
|
+
position: fixed;
|
|
1694
|
+
top: 0;
|
|
1695
|
+
left: 0;
|
|
1696
|
+
width: 100vw;
|
|
1697
|
+
height: 100vh;
|
|
1698
|
+
-webkit-print-color-adjust: exact;
|
|
1699
|
+
print-color-adjust: exact;
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
`;
|
|
1703
|
+
watermarkHtml = ` <div id="markforge-watermark" class="document-watermark" aria-hidden="true"></div>
|
|
1704
|
+
<script>
|
|
1705
|
+
(function() {
|
|
1706
|
+
try {
|
|
1707
|
+
var canvas = document.createElement('canvas');
|
|
1708
|
+
var dpr = 3;
|
|
1709
|
+
var width = 800;
|
|
1710
|
+
var height = 1100;
|
|
1711
|
+
canvas.width = Math.round(width * dpr);
|
|
1712
|
+
canvas.height = Math.round(height * dpr);
|
|
1713
|
+
var ctx = canvas.getContext('2d');
|
|
1714
|
+
if (ctx) {
|
|
1715
|
+
ctx.scale(dpr, dpr);
|
|
1716
|
+
ctx.translate(width / 2, height / 2);
|
|
1717
|
+
ctx.rotate((${wm.rotate} * Math.PI) / 180);
|
|
1718
|
+
ctx.textAlign = 'center';
|
|
1719
|
+
ctx.textBaseline = 'middle';
|
|
1720
|
+
ctx.font = '900 ${wm.fontSize * 1.5}px system-ui, -apple-system, sans-serif';
|
|
1721
|
+
ctx.fillStyle = '${wm.color}';
|
|
1722
|
+
ctx.globalAlpha = ${wm.opacity};
|
|
1723
|
+
try { ctx.letterSpacing = '0.15em'; } catch(e) {}
|
|
1724
|
+
ctx.fillText(${JSON.stringify(wm.text.toUpperCase())}, 0, 0);
|
|
1725
|
+
var dataUrl = canvas.toDataURL('image/png');
|
|
1726
|
+
var wmEl = document.getElementById('markforge-watermark');
|
|
1727
|
+
if (wmEl) {
|
|
1728
|
+
wmEl.style.backgroundImage = 'url("' + dataUrl + '")';
|
|
1729
|
+
wmEl.style.backgroundRepeat = 'no-repeat';
|
|
1730
|
+
wmEl.style.backgroundPosition = 'center center';
|
|
1731
|
+
wmEl.style.backgroundSize = 'contain';
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
} catch(err) {}
|
|
1735
|
+
})();
|
|
1736
|
+
</script>
|
|
1737
|
+
`;
|
|
1738
|
+
}
|
|
1739
|
+
let signaturesHtml = "";
|
|
1740
|
+
let signaturesCss = "";
|
|
1741
|
+
if (resolved.signatures && resolved.signatures.items.length > 0) {
|
|
1742
|
+
const sig = resolved.signatures;
|
|
1743
|
+
const numItems = sig.items.length;
|
|
1744
|
+
let justifyCss = "flex-end";
|
|
1745
|
+
if (sig.align === "left") justifyCss = "flex-start";
|
|
1746
|
+
else if (sig.align === "center") justifyCss = "center";
|
|
1747
|
+
else if (sig.align === "space-between") justifyCss = "space-between";
|
|
1748
|
+
signaturesCss = `
|
|
1749
|
+
.markforge-signatures {
|
|
1750
|
+
margin-top: ${sig.spacingBefore};
|
|
1751
|
+
display: grid;
|
|
1752
|
+
grid-template-columns: ${numItems === 1 ? sig.align === "left" ? "minmax(200px, 280px) 1fr" : sig.align === "center" ? "1fr minmax(200px, 280px) 1fr" : "1fr minmax(200px, 280px)" : `repeat(${numItems}, minmax(0, 1fr))`};
|
|
1753
|
+
gap: 2rem;
|
|
1754
|
+
page-break-inside: avoid;
|
|
1755
|
+
break-inside: avoid;
|
|
1756
|
+
}
|
|
1757
|
+
.markforge-signature-card {
|
|
1758
|
+
${numItems === 1 && sig.align === "center" ? "grid-column: 2;" : ""}
|
|
1759
|
+
${numItems === 1 && sig.align === "right" ? "grid-column: 2;" : ""}
|
|
1760
|
+
display: flex;
|
|
1761
|
+
flex-direction: column;
|
|
1762
|
+
${sig.style === "box" ? `border: 1px solid ${sig.borderColor}; border-radius: 6px; padding: 14px 18px; background-color: var(--mf-card-bg, #F8FAFC);` : ""}
|
|
1763
|
+
}
|
|
1764
|
+
.markforge-sig-title {
|
|
1765
|
+
font-size: 0.85rem;
|
|
1766
|
+
color: ${sig.titleColor};
|
|
1767
|
+
font-weight: 600;
|
|
1768
|
+
margin-bottom: 6px;
|
|
1769
|
+
}
|
|
1770
|
+
.markforge-sig-space {
|
|
1771
|
+
height: var(--sig-height, 60px);
|
|
1772
|
+
display: flex;
|
|
1773
|
+
align-items: center;
|
|
1774
|
+
justify-content: center;
|
|
1775
|
+
margin-bottom: 6px;
|
|
1776
|
+
}
|
|
1777
|
+
.markforge-sig-space img {
|
|
1778
|
+
max-height: 100%;
|
|
1779
|
+
max-width: 100%;
|
|
1780
|
+
object-fit: contain;
|
|
1781
|
+
}
|
|
1782
|
+
.markforge-sig-line {
|
|
1783
|
+
${sig.style === "line" ? `border-bottom: 1.5px solid ${sig.borderColor}; margin-bottom: 8px;` : ""}
|
|
1784
|
+
}
|
|
1785
|
+
.markforge-sig-name {
|
|
1786
|
+
font-size: 0.95rem;
|
|
1787
|
+
font-weight: 700;
|
|
1788
|
+
color: ${sig.nameColor};
|
|
1789
|
+
}
|
|
1790
|
+
.markforge-sig-role {
|
|
1791
|
+
font-size: 0.82rem;
|
|
1792
|
+
color: ${sig.roleColor};
|
|
1793
|
+
margin-top: 2px;
|
|
1794
|
+
}
|
|
1795
|
+
.markforge-sig-date {
|
|
1796
|
+
font-size: 0.78rem;
|
|
1797
|
+
color: ${sig.roleColor};
|
|
1798
|
+
margin-top: 2px;
|
|
1799
|
+
}
|
|
1800
|
+
@media print {
|
|
1801
|
+
.markforge-signatures {
|
|
1802
|
+
page-break-inside: avoid;
|
|
1803
|
+
break-inside: avoid;
|
|
1804
|
+
}
|
|
1315
1805
|
}
|
|
1316
1806
|
`;
|
|
1317
|
-
|
|
1807
|
+
const itemCards = sig.items.map((item) => {
|
|
1808
|
+
const titleHtml = item.title ? `<div class="markforge-sig-title">${escapeHtml(item.title)}</div>` : "";
|
|
1809
|
+
let signSpaceHtml = "";
|
|
1810
|
+
if (item.image) {
|
|
1811
|
+
signSpaceHtml = `<div class="markforge-sig-space" style="--sig-height: ${item.signatureHeight}px;"><img src="${escapeHtml(item.image)}" alt="Signature" /></div>`;
|
|
1812
|
+
} else {
|
|
1813
|
+
signSpaceHtml = `<div class="markforge-sig-space" style="--sig-height: ${item.signatureHeight}px;"></div>`;
|
|
1814
|
+
}
|
|
1815
|
+
const lineHtml = sig.style === "line" ? `<div class="markforge-sig-line"></div>` : "";
|
|
1816
|
+
const nameHtml = `<div class="markforge-sig-name">${escapeHtml(item.name)}</div>`;
|
|
1817
|
+
const roleHtml = item.role ? `<div class="markforge-sig-role">${escapeHtml(item.role)}</div>` : "";
|
|
1818
|
+
const dateHtml = item.date ? `<div class="markforge-sig-date">Date: ${escapeHtml(item.date)}</div>` : "";
|
|
1819
|
+
return ` <div class="markforge-signature-card">
|
|
1820
|
+
${titleHtml}
|
|
1821
|
+
${signSpaceHtml}
|
|
1822
|
+
${lineHtml}
|
|
1823
|
+
${nameHtml}
|
|
1824
|
+
${roleHtml}
|
|
1825
|
+
${dateHtml}
|
|
1826
|
+
</div>`;
|
|
1827
|
+
}).join("\n");
|
|
1828
|
+
signaturesHtml = `
|
|
1829
|
+
<div class="markforge-signatures">
|
|
1830
|
+
${itemCards}
|
|
1831
|
+
</div>
|
|
1318
1832
|
`;
|
|
1319
1833
|
}
|
|
1320
1834
|
const hasMermaid = doc.nodes.some((n) => n.type === "mermaid");
|
|
@@ -1333,24 +1847,24 @@ ${escapeHtml(node.text || "")}
|
|
|
1333
1847
|
}
|
|
1334
1848
|
});
|
|
1335
1849
|
</script>` : "";
|
|
1336
|
-
const documentTitle = metadata.title || "MarkForge Document";
|
|
1337
1850
|
return `<!DOCTYPE html>
|
|
1338
|
-
<html lang="${
|
|
1851
|
+
<html lang="${resolved.lang}">
|
|
1339
1852
|
<head>
|
|
1340
1853
|
<meta charset="UTF-8">
|
|
1341
1854
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1342
|
-
<title>${escapeHtml(
|
|
1855
|
+
<title>${escapeHtml(resolved.title)}</title>
|
|
1343
1856
|
<style>
|
|
1344
1857
|
${THEME_COMPONENTS}
|
|
1345
1858
|
${baseThemeCss}
|
|
1346
1859
|
${customCss}
|
|
1347
1860
|
${inlinedCss}
|
|
1348
1861
|
${watermarkCss}
|
|
1862
|
+
${signaturesCss}
|
|
1349
1863
|
</style>
|
|
1350
1864
|
</head>
|
|
1351
1865
|
<body>
|
|
1352
1866
|
${watermarkHtml} <div class="document-container">
|
|
1353
|
-
${bodyHtml} </div>
|
|
1867
|
+
${bodyHtml}${signaturesHtml} </div>
|
|
1354
1868
|
${mermaidScript}
|
|
1355
1869
|
</body>
|
|
1356
1870
|
</html>`;
|
|
@@ -1383,14 +1897,14 @@ function findChromeExecutable() {
|
|
|
1383
1897
|
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
1384
1898
|
"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
|
|
1385
1899
|
"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
|
|
1900
|
+
// Windows — Microsoft Edge (Native Windows 10/11 browser, enterprise whitelist friendly)
|
|
1901
|
+
`${winProgramFiles}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1902
|
+
`${winProgramFilesX86}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1903
|
+
`${winLocalAppData}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1386
1904
|
// Windows — Google Chrome
|
|
1387
1905
|
`${winProgramFiles}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1388
1906
|
`${winProgramFilesX86}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1389
1907
|
`${winLocalAppData}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
1390
|
-
// Windows — Microsoft Edge (ships with Windows 10/11)
|
|
1391
|
-
`${winProgramFiles}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1392
|
-
`${winProgramFilesX86}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1393
|
-
`${winLocalAppData}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
1394
1908
|
// Windows — Brave Browser
|
|
1395
1909
|
`${winProgramFiles}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
1396
1910
|
`${winProgramFilesX86}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
@@ -1421,22 +1935,50 @@ function findChromeExecutable() {
|
|
|
1421
1935
|
return null;
|
|
1422
1936
|
}
|
|
1423
1937
|
function injectPagedMediaStyles(html, config, metadata) {
|
|
1424
|
-
var _a, _b, _c, _d;
|
|
1425
|
-
const
|
|
1426
|
-
const
|
|
1427
|
-
const
|
|
1428
|
-
const
|
|
1429
|
-
const
|
|
1430
|
-
const
|
|
1431
|
-
const
|
|
1432
|
-
const
|
|
1433
|
-
const
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1938
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1939
|
+
const resolved = resolveDocumentConfig(metadata || {}, config);
|
|
1940
|
+
const size = resolved.paperSize;
|
|
1941
|
+
const orientation = resolved.orientation;
|
|
1942
|
+
const top = resolved.margins.top;
|
|
1943
|
+
const bottom = resolved.margins.bottom;
|
|
1944
|
+
const left = resolved.margins.left;
|
|
1945
|
+
const right = resolved.margins.right;
|
|
1946
|
+
const esc = (s) => s.replace(/"/g, '\\"').replace(/\\/g, "\\\\");
|
|
1947
|
+
const buildZoneCss = (pos, zone, isPageCounter = false) => {
|
|
1948
|
+
if (!zone && !isPageCounter) return "";
|
|
1949
|
+
const color = (zone == null ? void 0 : zone.color) || "#94a3b8";
|
|
1950
|
+
const fontSize = (zone == null ? void 0 : zone.fontSize) ? `${zone.fontSize}pt` : "9pt";
|
|
1951
|
+
const fontFamily = (zone == null ? void 0 : zone.fontFamily) ? `font-family: ${zone.fontFamily};` : "";
|
|
1952
|
+
const fontWeight = (zone == null ? void 0 : zone.bold) ? "font-weight: bold;" : "";
|
|
1953
|
+
const fontStyle = (zone == null ? void 0 : zone.italic) ? "font-style: italic;" : "";
|
|
1954
|
+
let content = "";
|
|
1955
|
+
if (isPageCounter) {
|
|
1956
|
+
if ((zone == null ? void 0 : zone.text) && (zone.text.includes("{page}") || zone.text.includes("{pages}"))) {
|
|
1957
|
+
const parts = zone.text.split(/(\{page\}|\{pages\})/gi);
|
|
1958
|
+
const cssParts = parts.map((part) => {
|
|
1959
|
+
if (part.toLowerCase() === "{page}") return "counter(page)";
|
|
1960
|
+
if (part.toLowerCase() === "{pages}") return "counter(pages)";
|
|
1961
|
+
return `"${esc(part)}"`;
|
|
1962
|
+
});
|
|
1963
|
+
content = cssParts.join(" ");
|
|
1964
|
+
} else if (zone == null ? void 0 : zone.text) {
|
|
1965
|
+
content = `"${esc(zone.text)}"`;
|
|
1966
|
+
} else {
|
|
1967
|
+
content = `"Page " counter(page) " of " counter(pages)`;
|
|
1968
|
+
}
|
|
1969
|
+
} else if (zone == null ? void 0 : zone.text) {
|
|
1970
|
+
content = `"${esc(zone.text)}"`;
|
|
1971
|
+
}
|
|
1972
|
+
if (!content) return "";
|
|
1973
|
+
return `@${pos} {
|
|
1974
|
+
content: ${content};
|
|
1975
|
+
font-size: ${fontSize};
|
|
1976
|
+
color: ${color};
|
|
1977
|
+
${fontFamily}
|
|
1978
|
+
${fontWeight}
|
|
1979
|
+
${fontStyle}
|
|
1980
|
+
}`;
|
|
1981
|
+
};
|
|
1440
1982
|
const pagedCss = `
|
|
1441
1983
|
@page {
|
|
1442
1984
|
size: ${size} ${orientation};
|
|
@@ -1444,15 +1986,12 @@ function injectPagedMediaStyles(html, config, metadata) {
|
|
|
1444
1986
|
margin-bottom: ${bottom};
|
|
1445
1987
|
margin-left: ${left};
|
|
1446
1988
|
margin-right: ${right};
|
|
1447
|
-
${
|
|
1448
|
-
${
|
|
1449
|
-
${
|
|
1450
|
-
${
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
font-size: 9pt;
|
|
1454
|
-
color: #94a3b8;
|
|
1455
|
-
}
|
|
1989
|
+
${buildZoneCss("top-left", (_a = resolved.header) == null ? void 0 : _a.left)}
|
|
1990
|
+
${buildZoneCss("top-center", (_b = resolved.header) == null ? void 0 : _b.center)}
|
|
1991
|
+
${buildZoneCss("top-right", (_c = resolved.header) == null ? void 0 : _c.right)}
|
|
1992
|
+
${buildZoneCss("bottom-left", (_d = resolved.footer) == null ? void 0 : _d.left)}
|
|
1993
|
+
${buildZoneCss("bottom-center", (_e = resolved.footer) == null ? void 0 : _e.center)}
|
|
1994
|
+
${buildZoneCss("bottom-right", (_f = resolved.footer) == null ? void 0 : _f.right, true)}
|
|
1456
1995
|
}
|
|
1457
1996
|
@media print {
|
|
1458
1997
|
body { padding: 0; }
|
|
@@ -1509,8 +2048,35 @@ async function buildPdfDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1509
2048
|
if (chromePath) {
|
|
1510
2049
|
const tmpId = Math.random().toString(36).substring(2, 9);
|
|
1511
2050
|
const tmpDir = os.tmpdir();
|
|
1512
|
-
const tmpHtml =
|
|
1513
|
-
const tmpPdf =
|
|
2051
|
+
const tmpHtml = path5.join(tmpDir, `markforge_${tmpId}.html`);
|
|
2052
|
+
const tmpPdf = path5.join(tmpDir, `markforge_${tmpId}.pdf`);
|
|
2053
|
+
const tmpProfile = path5.join(tmpDir, `markforge_prof_${tmpId}`);
|
|
2054
|
+
const isolatedFlags = [
|
|
2055
|
+
`--user-data-dir=${tmpProfile}`,
|
|
2056
|
+
"--no-first-run",
|
|
2057
|
+
"--no-default-browser-check",
|
|
2058
|
+
"--disable-sync",
|
|
2059
|
+
"--disable-background-networking",
|
|
2060
|
+
"--disable-component-update",
|
|
2061
|
+
"--disable-default-apps",
|
|
2062
|
+
"--disable-extensions",
|
|
2063
|
+
"--disable-domain-reliability",
|
|
2064
|
+
"--disable-client-side-phishing-detection",
|
|
2065
|
+
"--disable-breakpad",
|
|
2066
|
+
"--disable-component-extensions-with-background-pages",
|
|
2067
|
+
"--disable-features=Translate,OptimizationHints,MediaRouter,DialMediaRouteProvider,CalculatedNewTabPage,ChromeWhatsNewUI,PrivacySandboxSettings4",
|
|
2068
|
+
"--password-store=basic",
|
|
2069
|
+
"--use-mock-keychain",
|
|
2070
|
+
"--mute-audio",
|
|
2071
|
+
"--no-service-autorun",
|
|
2072
|
+
"--disable-gpu",
|
|
2073
|
+
"--no-sandbox",
|
|
2074
|
+
"--disable-setuid-sandbox",
|
|
2075
|
+
"--allow-file-access-from-files",
|
|
2076
|
+
"--disable-web-security",
|
|
2077
|
+
"--force-color-profile=srgb",
|
|
2078
|
+
"--no-pdf-header-footer"
|
|
2079
|
+
];
|
|
1514
2080
|
try {
|
|
1515
2081
|
fs3.writeFileSync(tmpHtml, pagedHtml, "utf-8");
|
|
1516
2082
|
const fileUrl = pathToFileURL(tmpHtml).href;
|
|
@@ -1518,15 +2084,9 @@ async function buildPdfDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1518
2084
|
chromePath,
|
|
1519
2085
|
[
|
|
1520
2086
|
"--headless=new",
|
|
1521
|
-
|
|
1522
|
-
"--no-sandbox",
|
|
1523
|
-
"--disable-setuid-sandbox",
|
|
1524
|
-
"--allow-file-access-from-files",
|
|
1525
|
-
"--disable-web-security",
|
|
1526
|
-
"--force-color-profile=srgb",
|
|
2087
|
+
...isolatedFlags,
|
|
1527
2088
|
"--run-all-compositor-stages-before-draw",
|
|
1528
2089
|
"--virtual-time-budget=8000",
|
|
1529
|
-
"--no-pdf-header-footer",
|
|
1530
2090
|
`--print-to-pdf=${tmpPdf}`,
|
|
1531
2091
|
fileUrl
|
|
1532
2092
|
],
|
|
@@ -1537,13 +2097,7 @@ async function buildPdfDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1537
2097
|
chromePath,
|
|
1538
2098
|
[
|
|
1539
2099
|
"--headless",
|
|
1540
|
-
|
|
1541
|
-
"--no-sandbox",
|
|
1542
|
-
"--disable-setuid-sandbox",
|
|
1543
|
-
"--allow-file-access-from-files",
|
|
1544
|
-
"--disable-web-security",
|
|
1545
|
-
"--force-color-profile=srgb",
|
|
1546
|
-
"--no-pdf-header-footer",
|
|
2100
|
+
...isolatedFlags,
|
|
1547
2101
|
`--print-to-pdf=${tmpPdf}`,
|
|
1548
2102
|
fileUrl
|
|
1549
2103
|
],
|
|
@@ -1559,6 +2113,7 @@ async function buildPdfDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1559
2113
|
try {
|
|
1560
2114
|
if (fs3.existsSync(tmpHtml)) fs3.unlinkSync(tmpHtml);
|
|
1561
2115
|
if (fs3.existsSync(tmpPdf)) fs3.unlinkSync(tmpPdf);
|
|
2116
|
+
if (fs3.existsSync(tmpProfile)) fs3.rmSync(tmpProfile, { recursive: true, force: true });
|
|
1562
2117
|
} catch {
|
|
1563
2118
|
}
|
|
1564
2119
|
}
|
|
@@ -1574,8 +2129,8 @@ async function renderMermaidToPng(mermaidCode, _baseDir = process.cwd()) {
|
|
|
1574
2129
|
}
|
|
1575
2130
|
const tmpId = Math.random().toString(36).substring(2, 9);
|
|
1576
2131
|
const tmpDir = os2.tmpdir();
|
|
1577
|
-
const tmpHtml =
|
|
1578
|
-
const tmpScreenshot =
|
|
2132
|
+
const tmpHtml = path6.join(tmpDir, `mermaid_${tmpId}.html`);
|
|
2133
|
+
const tmpScreenshot = path6.join(tmpDir, `mermaid_${tmpId}.png`);
|
|
1579
2134
|
const htmlContent = `<!DOCTYPE html>
|
|
1580
2135
|
<html>
|
|
1581
2136
|
<head>
|
|
@@ -1649,30 +2204,7 @@ ${mermaidCode}
|
|
|
1649
2204
|
}
|
|
1650
2205
|
|
|
1651
2206
|
// src/core/docx/docxBuilder.ts
|
|
1652
|
-
function
|
|
1653
|
-
if (typeof margin === "number") return margin;
|
|
1654
|
-
if (!margin) return defaultTwip;
|
|
1655
|
-
const str = margin.trim().toLowerCase();
|
|
1656
|
-
if (str.endsWith("cm")) {
|
|
1657
|
-
const cm = parseFloat(str);
|
|
1658
|
-
return Math.round(convertMillimetersToTwip(cm * 10));
|
|
1659
|
-
}
|
|
1660
|
-
if (str.endsWith("mm")) {
|
|
1661
|
-
const mm = parseFloat(str);
|
|
1662
|
-
return Math.round(convertMillimetersToTwip(mm));
|
|
1663
|
-
}
|
|
1664
|
-
if (str.endsWith("in") || str.endsWith("inch")) {
|
|
1665
|
-
const inch = parseFloat(str);
|
|
1666
|
-
return Math.round(convertInchesToTwip(inch));
|
|
1667
|
-
}
|
|
1668
|
-
if (str.endsWith("pt")) {
|
|
1669
|
-
const pt = parseFloat(str);
|
|
1670
|
-
return Math.round(pt * 20);
|
|
1671
|
-
}
|
|
1672
|
-
const val = parseFloat(str);
|
|
1673
|
-
return isNaN(val) ? defaultTwip : Math.round(val);
|
|
1674
|
-
}
|
|
1675
|
-
async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
2207
|
+
async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd(), options = {}) {
|
|
1676
2208
|
const runs = [];
|
|
1677
2209
|
for (const span of spans) {
|
|
1678
2210
|
if (span.type === "image" && span.url) {
|
|
@@ -1702,7 +2234,10 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1702
2234
|
new TextRun({
|
|
1703
2235
|
text: span.content,
|
|
1704
2236
|
style: "Hyperlink",
|
|
1705
|
-
color: "
|
|
2237
|
+
color: "009DA0",
|
|
2238
|
+
font: options.font,
|
|
2239
|
+
size: options.size,
|
|
2240
|
+
bold: options.bold,
|
|
1706
2241
|
underline: {}
|
|
1707
2242
|
})
|
|
1708
2243
|
],
|
|
@@ -1715,7 +2250,11 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1715
2250
|
runs.push(
|
|
1716
2251
|
new TextRun({
|
|
1717
2252
|
text: span.content,
|
|
1718
|
-
bold: true
|
|
2253
|
+
bold: true,
|
|
2254
|
+
font: options.font,
|
|
2255
|
+
size: options.size,
|
|
2256
|
+
color: options.color,
|
|
2257
|
+
italics: options.italics
|
|
1719
2258
|
})
|
|
1720
2259
|
);
|
|
1721
2260
|
continue;
|
|
@@ -1724,7 +2263,11 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1724
2263
|
runs.push(
|
|
1725
2264
|
new TextRun({
|
|
1726
2265
|
text: span.content,
|
|
1727
|
-
italics: true
|
|
2266
|
+
italics: true,
|
|
2267
|
+
font: options.font,
|
|
2268
|
+
size: options.size,
|
|
2269
|
+
color: options.color,
|
|
2270
|
+
bold: options.bold
|
|
1728
2271
|
})
|
|
1729
2272
|
);
|
|
1730
2273
|
continue;
|
|
@@ -1733,7 +2276,10 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1733
2276
|
runs.push(
|
|
1734
2277
|
new TextRun({
|
|
1735
2278
|
text: span.content,
|
|
1736
|
-
strike: true
|
|
2279
|
+
strike: true,
|
|
2280
|
+
font: options.font,
|
|
2281
|
+
size: options.size,
|
|
2282
|
+
color: options.color
|
|
1737
2283
|
})
|
|
1738
2284
|
);
|
|
1739
2285
|
continue;
|
|
@@ -1741,22 +2287,23 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1741
2287
|
if (span.type === "code") {
|
|
1742
2288
|
runs.push(
|
|
1743
2289
|
new TextRun({
|
|
1744
|
-
text:
|
|
2290
|
+
text: span.content,
|
|
1745
2291
|
font: "Consolas",
|
|
2292
|
+
size: options.size ? options.size - 2 : 19,
|
|
2293
|
+
color: "0F172A",
|
|
1746
2294
|
shading: {
|
|
1747
2295
|
type: ShadingType.CLEAR,
|
|
1748
|
-
fill: "F1F5F9"
|
|
1749
|
-
color: "0F172A"
|
|
2296
|
+
fill: "F1F5F9"
|
|
1750
2297
|
}
|
|
1751
2298
|
})
|
|
1752
2299
|
);
|
|
1753
2300
|
continue;
|
|
1754
2301
|
}
|
|
1755
2302
|
if (span.type === "htmlInline") {
|
|
1756
|
-
let colorHex;
|
|
2303
|
+
let colorHex = options.color;
|
|
1757
2304
|
let bgHex;
|
|
1758
|
-
let isBold =
|
|
1759
|
-
let isItalic =
|
|
2305
|
+
let isBold = !!options.bold;
|
|
2306
|
+
let isItalic = !!options.italics;
|
|
1760
2307
|
if (span.style) {
|
|
1761
2308
|
if (span.style.color) {
|
|
1762
2309
|
colorHex = span.style.color.replace("#", "").trim();
|
|
@@ -1772,13 +2319,9 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1772
2319
|
}
|
|
1773
2320
|
}
|
|
1774
2321
|
if (span.children && span.children.length > 0) {
|
|
1775
|
-
const childRuns = await convertInlinesToTextRuns(span.children, baseDir);
|
|
2322
|
+
const childRuns = await convertInlinesToTextRuns(span.children, baseDir, options);
|
|
1776
2323
|
for (const child of childRuns) {
|
|
1777
|
-
|
|
1778
|
-
runs.push(child);
|
|
1779
|
-
} else {
|
|
1780
|
-
runs.push(child);
|
|
1781
|
-
}
|
|
2324
|
+
runs.push(child);
|
|
1782
2325
|
}
|
|
1783
2326
|
continue;
|
|
1784
2327
|
}
|
|
@@ -1788,6 +2331,8 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1788
2331
|
color: colorHex,
|
|
1789
2332
|
bold: isBold,
|
|
1790
2333
|
italics: isItalic,
|
|
2334
|
+
font: options.font,
|
|
2335
|
+
size: options.size,
|
|
1791
2336
|
shading: bgHex ? { type: ShadingType.CLEAR, fill: bgHex } : void 0
|
|
1792
2337
|
})
|
|
1793
2338
|
);
|
|
@@ -1795,91 +2340,239 @@ async function convertInlinesToTextRuns(spans = [], baseDir = process.cwd()) {
|
|
|
1795
2340
|
}
|
|
1796
2341
|
runs.push(
|
|
1797
2342
|
new TextRun({
|
|
1798
|
-
text: span.content
|
|
2343
|
+
text: span.content,
|
|
2344
|
+
font: options.font,
|
|
2345
|
+
size: options.size,
|
|
2346
|
+
color: options.color,
|
|
2347
|
+
bold: options.bold,
|
|
2348
|
+
italics: options.italics
|
|
1799
2349
|
})
|
|
1800
2350
|
);
|
|
1801
2351
|
}
|
|
1802
2352
|
return runs;
|
|
1803
2353
|
}
|
|
1804
2354
|
async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
1805
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
1806
|
-
const
|
|
2355
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
2356
|
+
const resolved = resolveDocumentConfig(doc.metadata, config);
|
|
1807
2357
|
const docElements = [];
|
|
1808
|
-
|
|
2358
|
+
const themeProps = typeof resolved.theme === "object" ? resolved.theme : {};
|
|
2359
|
+
const primaryHex = (themeProps.primaryColor || "#33CDCF").replace("#", "");
|
|
2360
|
+
const primaryDarkHex = (themeProps.primaryDark || "#009DA0").replace("#", "");
|
|
2361
|
+
const textHex = (themeProps.textColor || "#0F172A").replace("#", "");
|
|
2362
|
+
const textMutedHex = (themeProps.textMuted || "#64748B").replace("#", "");
|
|
2363
|
+
const borderHex = (themeProps.borderColor || "#E2E8F0").replace("#", "");
|
|
2364
|
+
const cardBgHex = (themeProps.cardBackground || "#F8FAFC").replace("#", "");
|
|
2365
|
+
const defaultFont = themeProps.fontFamily ? themeProps.fontFamily.split(",")[0].replace(/['"]/g, "").trim() : "Segoe UI";
|
|
2366
|
+
if (resolved.title) {
|
|
1809
2367
|
docElements.push(
|
|
1810
2368
|
new Paragraph({
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
2369
|
+
children: [
|
|
2370
|
+
new TextRun({
|
|
2371
|
+
text: resolved.title,
|
|
2372
|
+
bold: true,
|
|
2373
|
+
size: 44,
|
|
2374
|
+
// 22pt
|
|
2375
|
+
color: textHex,
|
|
2376
|
+
font: defaultFont
|
|
2377
|
+
})
|
|
2378
|
+
],
|
|
2379
|
+
spacing: { before: 120, after: 80 }
|
|
1814
2380
|
})
|
|
1815
2381
|
);
|
|
1816
|
-
if (
|
|
2382
|
+
if (resolved.subtitle) {
|
|
1817
2383
|
docElements.push(
|
|
1818
2384
|
new Paragraph({
|
|
1819
2385
|
children: [
|
|
1820
2386
|
new TextRun({
|
|
1821
|
-
text:
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
size: 24
|
|
2387
|
+
text: resolved.subtitle,
|
|
2388
|
+
color: textMutedHex,
|
|
2389
|
+
size: 24,
|
|
1825
2390
|
// 12pt
|
|
2391
|
+
font: defaultFont
|
|
1826
2392
|
})
|
|
1827
2393
|
],
|
|
1828
|
-
spacing: { after:
|
|
2394
|
+
spacing: { before: 60, after: 120 }
|
|
1829
2395
|
})
|
|
1830
2396
|
);
|
|
1831
2397
|
}
|
|
1832
|
-
if (
|
|
2398
|
+
if (resolved.author || resolved.date || resolved.version || resolved.company) {
|
|
1833
2399
|
const metaParts = [];
|
|
1834
|
-
if (
|
|
1835
|
-
if (
|
|
2400
|
+
if (resolved.author) metaParts.push(`Author: ${resolved.author}`);
|
|
2401
|
+
if (resolved.version) metaParts.push(`Version: ${resolved.version}`);
|
|
2402
|
+
if (resolved.date) metaParts.push(`Date: ${resolved.date}`);
|
|
1836
2403
|
docElements.push(
|
|
1837
2404
|
new Paragraph({
|
|
1838
2405
|
children: [
|
|
1839
2406
|
new TextRun({
|
|
1840
|
-
text: metaParts.join("
|
|
1841
|
-
color:
|
|
1842
|
-
size:
|
|
1843
|
-
//
|
|
2407
|
+
text: metaParts.join(" "),
|
|
2408
|
+
color: textMutedHex,
|
|
2409
|
+
size: 18,
|
|
2410
|
+
// 9pt
|
|
2411
|
+
font: defaultFont
|
|
1844
2412
|
})
|
|
1845
2413
|
],
|
|
1846
|
-
spacing: { after:
|
|
2414
|
+
spacing: { before: 40, after: 240 },
|
|
1847
2415
|
border: {
|
|
1848
2416
|
bottom: {
|
|
1849
|
-
color:
|
|
1850
|
-
space:
|
|
2417
|
+
color: borderHex,
|
|
2418
|
+
space: 12,
|
|
1851
2419
|
style: BorderStyle.SINGLE,
|
|
1852
|
-
size:
|
|
2420
|
+
size: 4
|
|
1853
2421
|
}
|
|
1854
2422
|
}
|
|
1855
2423
|
})
|
|
1856
2424
|
);
|
|
1857
2425
|
}
|
|
1858
2426
|
}
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
if (node.level === 5) headingLevel = HeadingLevel.HEADING_5;
|
|
1866
|
-
if (node.level === 6) headingLevel = HeadingLevel.HEADING_6;
|
|
1867
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir);
|
|
1868
|
-
docElements.push(
|
|
2427
|
+
if (resolved.toc) {
|
|
2428
|
+
const headingNodes = doc.nodes.filter(
|
|
2429
|
+
(n) => n.type === "heading" && typeof n.level === "number" && n.level >= 1 && n.level <= 3
|
|
2430
|
+
);
|
|
2431
|
+
if (headingNodes.length > 0) {
|
|
2432
|
+
const tocParagraphs = [
|
|
1869
2433
|
new Paragraph({
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
2434
|
+
children: [
|
|
2435
|
+
new TextRun({
|
|
2436
|
+
text: "TABLE OF CONTENTS",
|
|
2437
|
+
bold: true,
|
|
2438
|
+
size: 18,
|
|
2439
|
+
// 9pt
|
|
2440
|
+
color: textMutedHex,
|
|
2441
|
+
font: defaultFont
|
|
2442
|
+
})
|
|
2443
|
+
],
|
|
2444
|
+
spacing: { after: 120 },
|
|
2445
|
+
border: {
|
|
2446
|
+
bottom: {
|
|
2447
|
+
color: borderHex,
|
|
2448
|
+
space: 6,
|
|
2449
|
+
style: BorderStyle.SINGLE,
|
|
2450
|
+
size: 4
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
1873
2453
|
})
|
|
1874
|
-
|
|
2454
|
+
];
|
|
2455
|
+
for (const h of headingNodes) {
|
|
2456
|
+
const indentLeft = (h.level - 1) * 240;
|
|
2457
|
+
tocParagraphs.push(
|
|
2458
|
+
new Paragraph({
|
|
2459
|
+
indent: { left: indentLeft },
|
|
2460
|
+
children: [
|
|
2461
|
+
new TextRun({
|
|
2462
|
+
text: h.text,
|
|
2463
|
+
bold: h.level === 1,
|
|
2464
|
+
color: primaryDarkHex,
|
|
2465
|
+
size: h.level === 1 ? 21 : 20,
|
|
2466
|
+
font: defaultFont
|
|
2467
|
+
})
|
|
2468
|
+
],
|
|
2469
|
+
spacing: { before: 20, after: 20 }
|
|
2470
|
+
})
|
|
2471
|
+
);
|
|
2472
|
+
}
|
|
2473
|
+
const tocCard = new Table({
|
|
2474
|
+
width: { size: 100, type: WidthType.PERCENTAGE },
|
|
2475
|
+
columnWidths: [9e3],
|
|
2476
|
+
rows: [
|
|
2477
|
+
new TableRow({
|
|
2478
|
+
children: [
|
|
2479
|
+
new TableCell({
|
|
2480
|
+
width: { size: 9e3, type: WidthType.DXA },
|
|
2481
|
+
shading: { fill: cardBgHex, type: ShadingType.CLEAR },
|
|
2482
|
+
margins: { top: 140, bottom: 140, left: 180, right: 180 },
|
|
2483
|
+
borders: {
|
|
2484
|
+
top: { style: BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2485
|
+
bottom: { style: BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2486
|
+
left: { style: BorderStyle.SINGLE, size: 4, color: borderHex },
|
|
2487
|
+
right: { style: BorderStyle.SINGLE, size: 4, color: borderHex }
|
|
2488
|
+
},
|
|
2489
|
+
children: tocParagraphs
|
|
2490
|
+
})
|
|
2491
|
+
]
|
|
2492
|
+
})
|
|
2493
|
+
]
|
|
2494
|
+
});
|
|
2495
|
+
docElements.push(tocCard);
|
|
2496
|
+
docElements.push(new Paragraph({ spacing: { after: 200 } }));
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
for (const node of doc.nodes) {
|
|
2500
|
+
if (node.type === "heading") {
|
|
2501
|
+
if (node.level === 1) {
|
|
2502
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2503
|
+
font: defaultFont,
|
|
2504
|
+
size: 34,
|
|
2505
|
+
// 17pt
|
|
2506
|
+
color: textHex,
|
|
2507
|
+
bold: true
|
|
2508
|
+
});
|
|
2509
|
+
docElements.push(
|
|
2510
|
+
new Paragraph({
|
|
2511
|
+
heading: HeadingLevel.HEADING_1,
|
|
2512
|
+
children: runs,
|
|
2513
|
+
spacing: { before: 360, after: 140 },
|
|
2514
|
+
border: {
|
|
2515
|
+
bottom: {
|
|
2516
|
+
color: primaryHex,
|
|
2517
|
+
space: 6,
|
|
2518
|
+
style: BorderStyle.SINGLE,
|
|
2519
|
+
size: 16
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
})
|
|
2523
|
+
);
|
|
2524
|
+
} else if (node.level === 2) {
|
|
2525
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2526
|
+
font: defaultFont,
|
|
2527
|
+
size: 26,
|
|
2528
|
+
// 13pt
|
|
2529
|
+
color: primaryDarkHex,
|
|
2530
|
+
bold: true
|
|
2531
|
+
});
|
|
2532
|
+
docElements.push(
|
|
2533
|
+
new Paragraph({
|
|
2534
|
+
heading: HeadingLevel.HEADING_2,
|
|
2535
|
+
children: runs,
|
|
2536
|
+
spacing: { before: 280, after: 100 },
|
|
2537
|
+
border: {
|
|
2538
|
+
bottom: {
|
|
2539
|
+
color: borderHex,
|
|
2540
|
+
space: 4,
|
|
2541
|
+
style: BorderStyle.SINGLE,
|
|
2542
|
+
size: 4
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
})
|
|
2546
|
+
);
|
|
2547
|
+
} else {
|
|
2548
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2549
|
+
font: defaultFont,
|
|
2550
|
+
size: 22,
|
|
2551
|
+
// 11pt
|
|
2552
|
+
color: textHex,
|
|
2553
|
+
bold: true
|
|
2554
|
+
});
|
|
2555
|
+
docElements.push(
|
|
2556
|
+
new Paragraph({
|
|
2557
|
+
heading: node.level === 3 ? HeadingLevel.HEADING_3 : HeadingLevel.HEADING_4,
|
|
2558
|
+
children: runs,
|
|
2559
|
+
spacing: { before: 200, after: 80 }
|
|
2560
|
+
})
|
|
2561
|
+
);
|
|
2562
|
+
}
|
|
1875
2563
|
continue;
|
|
1876
2564
|
}
|
|
1877
2565
|
if (node.type === "paragraph") {
|
|
1878
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
2566
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2567
|
+
font: defaultFont,
|
|
2568
|
+
size: 22,
|
|
2569
|
+
// 11pt
|
|
2570
|
+
color: "334155"
|
|
2571
|
+
});
|
|
1879
2572
|
docElements.push(
|
|
1880
2573
|
new Paragraph({
|
|
1881
2574
|
children: runs,
|
|
1882
|
-
spacing: { before:
|
|
2575
|
+
spacing: { before: 40, after: 140, line: 280 }
|
|
1883
2576
|
})
|
|
1884
2577
|
);
|
|
1885
2578
|
continue;
|
|
@@ -1951,7 +2644,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1951
2644
|
bgFill = "F5F3FF";
|
|
1952
2645
|
title = "IMPORTANT";
|
|
1953
2646
|
}
|
|
1954
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
2647
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2648
|
+
font: defaultFont,
|
|
2649
|
+
size: 21,
|
|
2650
|
+
color: "334155"
|
|
2651
|
+
});
|
|
1955
2652
|
const calloutTable = new Table({
|
|
1956
2653
|
width: { size: 100, type: WidthType.PERCENTAGE },
|
|
1957
2654
|
columnWidths: [9e3],
|
|
@@ -1966,7 +2663,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1966
2663
|
top: { style: BorderStyle.NONE },
|
|
1967
2664
|
bottom: { style: BorderStyle.NONE },
|
|
1968
2665
|
right: { style: BorderStyle.NONE },
|
|
1969
|
-
left: { style: BorderStyle.SINGLE, size:
|
|
2666
|
+
left: { style: BorderStyle.SINGLE, size: 20, color: borderColor }
|
|
1970
2667
|
},
|
|
1971
2668
|
children: [
|
|
1972
2669
|
new Paragraph({
|
|
@@ -1975,13 +2672,15 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1975
2672
|
text: `[${title}]`,
|
|
1976
2673
|
bold: true,
|
|
1977
2674
|
color: borderColor,
|
|
2675
|
+
font: defaultFont,
|
|
1978
2676
|
size: 20
|
|
1979
2677
|
})
|
|
1980
2678
|
],
|
|
1981
|
-
spacing: { after:
|
|
2679
|
+
spacing: { after: 40 }
|
|
1982
2680
|
}),
|
|
1983
2681
|
new Paragraph({
|
|
1984
|
-
children: runs
|
|
2682
|
+
children: runs,
|
|
2683
|
+
spacing: { line: 270 }
|
|
1985
2684
|
})
|
|
1986
2685
|
]
|
|
1987
2686
|
})
|
|
@@ -1999,17 +2698,27 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
1999
2698
|
if (lines.length > 0) {
|
|
2000
2699
|
for (const lineText of lines) {
|
|
2001
2700
|
const spans = parseInlineSpans(lineText.replace(/^>\s?/, "").trim());
|
|
2002
|
-
const lineRuns = await convertInlinesToTextRuns(spans, baseDir
|
|
2701
|
+
const lineRuns = await convertInlinesToTextRuns(spans, baseDir, {
|
|
2702
|
+
font: defaultFont,
|
|
2703
|
+
size: 21,
|
|
2704
|
+
color: "475569",
|
|
2705
|
+
italics: true
|
|
2706
|
+
});
|
|
2003
2707
|
quoteParagraphs.push(
|
|
2004
2708
|
new Paragraph({
|
|
2005
2709
|
children: lineRuns,
|
|
2006
|
-
spacing: { before:
|
|
2710
|
+
spacing: { before: 20, after: 20, line: 260 }
|
|
2007
2711
|
})
|
|
2008
2712
|
);
|
|
2009
2713
|
}
|
|
2010
2714
|
} else {
|
|
2011
|
-
const runs = await convertInlinesToTextRuns(node.inlines, baseDir
|
|
2012
|
-
|
|
2715
|
+
const runs = await convertInlinesToTextRuns(node.inlines, baseDir, {
|
|
2716
|
+
font: defaultFont,
|
|
2717
|
+
size: 21,
|
|
2718
|
+
color: "475569",
|
|
2719
|
+
italics: true
|
|
2720
|
+
});
|
|
2721
|
+
quoteParagraphs.push(new Paragraph({ children: runs, spacing: { line: 260 } }));
|
|
2013
2722
|
}
|
|
2014
2723
|
const quoteTable = new Table({
|
|
2015
2724
|
width: { size: 100, type: WidthType.PERCENTAGE },
|
|
@@ -2025,7 +2734,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2025
2734
|
top: { style: BorderStyle.NONE },
|
|
2026
2735
|
bottom: { style: BorderStyle.NONE },
|
|
2027
2736
|
right: { style: BorderStyle.NONE },
|
|
2028
|
-
left: { style: BorderStyle.SINGLE, size:
|
|
2737
|
+
left: { style: BorderStyle.SINGLE, size: 16, color: primaryHex }
|
|
2029
2738
|
},
|
|
2030
2739
|
children: quoteParagraphs
|
|
2031
2740
|
})
|
|
@@ -2060,7 +2769,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2060
2769
|
docElements.push(
|
|
2061
2770
|
new Paragraph({
|
|
2062
2771
|
children: [
|
|
2063
|
-
new TextRun({ text: "[Mermaid Diagram: " + (node.text || "").slice(0, 40) + "...]", bold: true, color:
|
|
2772
|
+
new TextRun({ text: "[Mermaid Diagram: " + (node.text || "").slice(0, 40) + "...]", bold: true, color: primaryHex })
|
|
2064
2773
|
],
|
|
2065
2774
|
spacing: { before: 60, after: 60 }
|
|
2066
2775
|
})
|
|
@@ -2072,8 +2781,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2072
2781
|
const tableRows = [];
|
|
2073
2782
|
const numCols = ((_b = (_a = node.children[0]) == null ? void 0 : _a.children) == null ? void 0 : _b.length) || 1;
|
|
2074
2783
|
const colWidth = Math.floor(9e3 / numCols);
|
|
2075
|
-
for (
|
|
2784
|
+
for (let rowIdx = 0; rowIdx < node.children.length; rowIdx++) {
|
|
2785
|
+
const rowNode = node.children[rowIdx];
|
|
2076
2786
|
const cells = [];
|
|
2787
|
+
const isHeader = rowNode.isHeader;
|
|
2788
|
+
const rowBg = isHeader ? "F1F5F9" : rowIdx % 2 === 0 ? "FFFFFF" : "F8FAFC";
|
|
2077
2789
|
if (rowNode.children) {
|
|
2078
2790
|
for (let colIdx = 0; colIdx < rowNode.children.length; colIdx++) {
|
|
2079
2791
|
const cellNode = rowNode.children[colIdx];
|
|
@@ -2081,22 +2793,27 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2081
2793
|
let alignment = AlignmentType.LEFT;
|
|
2082
2794
|
if (align === "center") alignment = AlignmentType.CENTER;
|
|
2083
2795
|
if (align === "right") alignment = AlignmentType.RIGHT;
|
|
2084
|
-
const runs = await convertInlinesToTextRuns(cellNode.inlines, baseDir
|
|
2796
|
+
const runs = await convertInlinesToTextRuns(cellNode.inlines, baseDir, {
|
|
2797
|
+
font: defaultFont,
|
|
2798
|
+
size: 20,
|
|
2799
|
+
color: isHeader ? "0F172A" : "334155",
|
|
2800
|
+
bold: isHeader
|
|
2801
|
+
});
|
|
2085
2802
|
cells.push(
|
|
2086
2803
|
new TableCell({
|
|
2087
2804
|
width: { size: colWidth, type: WidthType.DXA },
|
|
2088
|
-
shading:
|
|
2089
|
-
margins: { top: 100, bottom: 100, left:
|
|
2805
|
+
shading: { fill: rowBg, type: ShadingType.CLEAR },
|
|
2806
|
+
margins: { top: 100, bottom: 100, left: 140, right: 140 },
|
|
2090
2807
|
borders: {
|
|
2091
|
-
top: { style: BorderStyle.SINGLE, size: 4, color: "
|
|
2092
|
-
bottom: { style: BorderStyle.SINGLE, size: 4, color: "CBD5E1" },
|
|
2093
|
-
left: { style: BorderStyle.SINGLE, size: 4, color: "
|
|
2094
|
-
right: { style: BorderStyle.SINGLE, size: 4, color: "
|
|
2808
|
+
top: { style: BorderStyle.SINGLE, size: 4, color: "E2E8F0" },
|
|
2809
|
+
bottom: { style: BorderStyle.SINGLE, size: isHeader ? 8 : 4, color: isHeader ? "CBD5E1" : "E2E8F0" },
|
|
2810
|
+
left: { style: BorderStyle.SINGLE, size: 4, color: "E2E8F0" },
|
|
2811
|
+
right: { style: BorderStyle.SINGLE, size: 4, color: "E2E8F0" }
|
|
2095
2812
|
},
|
|
2096
2813
|
children: [
|
|
2097
2814
|
new Paragraph({
|
|
2098
2815
|
alignment,
|
|
2099
|
-
children:
|
|
2816
|
+
children: runs
|
|
2100
2817
|
})
|
|
2101
2818
|
]
|
|
2102
2819
|
})
|
|
@@ -2105,7 +2822,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2105
2822
|
}
|
|
2106
2823
|
tableRows.push(
|
|
2107
2824
|
new TableRow({
|
|
2108
|
-
tableHeader:
|
|
2825
|
+
tableHeader: isHeader,
|
|
2109
2826
|
children: cells
|
|
2110
2827
|
})
|
|
2111
2828
|
);
|
|
@@ -2121,7 +2838,11 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2121
2838
|
}
|
|
2122
2839
|
if (node.type === "list" && node.children) {
|
|
2123
2840
|
for (const item of node.children) {
|
|
2124
|
-
const runs = await convertInlinesToTextRuns(item.inlines, baseDir
|
|
2841
|
+
const runs = await convertInlinesToTextRuns(item.inlines, baseDir, {
|
|
2842
|
+
font: defaultFont,
|
|
2843
|
+
size: 21,
|
|
2844
|
+
color: "334155"
|
|
2845
|
+
});
|
|
2125
2846
|
let prefix = "";
|
|
2126
2847
|
if (item.checked !== void 0) {
|
|
2127
2848
|
prefix = item.checked ? "[X] " : "[ ] ";
|
|
@@ -2133,7 +2854,7 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2133
2854
|
...prefix ? [new TextRun({ text: prefix, bold: true, font: "Consolas" })] : [],
|
|
2134
2855
|
...runs
|
|
2135
2856
|
],
|
|
2136
|
-
spacing: { before:
|
|
2857
|
+
spacing: { before: 20, after: 20, line: 260 }
|
|
2137
2858
|
})
|
|
2138
2859
|
);
|
|
2139
2860
|
}
|
|
@@ -2208,88 +2929,258 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2208
2929
|
continue;
|
|
2209
2930
|
}
|
|
2210
2931
|
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2932
|
+
if (resolved.signatures && resolved.signatures.items.length > 0) {
|
|
2933
|
+
const sig = resolved.signatures;
|
|
2934
|
+
const numItems = sig.items.length;
|
|
2935
|
+
const contentWidth = Math.max(
|
|
2936
|
+
1e3,
|
|
2937
|
+
resolved.paperDimensions.widthTwip - resolved.margins.leftTwip - resolved.margins.rightTwip
|
|
2938
|
+
);
|
|
2939
|
+
docElements.push(new Paragraph({ spacing: { before: sig.spacingBeforeTwip } }));
|
|
2940
|
+
const sigCells = [];
|
|
2941
|
+
const colWidths = [];
|
|
2942
|
+
if (numItems === 1) {
|
|
2943
|
+
const cardWidth = Math.min(3400, Math.floor(contentWidth * 0.42));
|
|
2944
|
+
const spacerWidth = contentWidth - cardWidth;
|
|
2945
|
+
const cardCell = await buildDocxSignatureCell(sig.items[0], sig, cardWidth, defaultFont, baseDir);
|
|
2946
|
+
if (sig.align === "left") {
|
|
2947
|
+
colWidths.push(cardWidth, spacerWidth);
|
|
2948
|
+
sigCells.push(cardCell, createEmptyDocxCell(spacerWidth));
|
|
2949
|
+
} else if (sig.align === "center") {
|
|
2950
|
+
const sideWidth = Math.floor(spacerWidth / 2);
|
|
2951
|
+
colWidths.push(sideWidth, cardWidth, sideWidth);
|
|
2952
|
+
sigCells.push(createEmptyDocxCell(sideWidth), cardCell, createEmptyDocxCell(sideWidth));
|
|
2953
|
+
} else {
|
|
2954
|
+
colWidths.push(spacerWidth, cardWidth);
|
|
2955
|
+
sigCells.push(createEmptyDocxCell(spacerWidth), cardCell);
|
|
2956
|
+
}
|
|
2957
|
+
} else {
|
|
2958
|
+
const colWidth = Math.floor(contentWidth / numItems);
|
|
2959
|
+
for (let i = 0; i < numItems; i++) {
|
|
2960
|
+
colWidths.push(colWidth);
|
|
2961
|
+
const cell = await buildDocxSignatureCell(sig.items[i], sig, colWidth, defaultFont, baseDir);
|
|
2962
|
+
sigCells.push(cell);
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
const sigTable = new Table({
|
|
2966
|
+
width: { size: 100, type: WidthType.PERCENTAGE },
|
|
2967
|
+
columnWidths: colWidths,
|
|
2968
|
+
borders: {
|
|
2969
|
+
top: { style: BorderStyle.NONE, size: 0, color: "auto" },
|
|
2970
|
+
bottom: { style: BorderStyle.NONE, size: 0, color: "auto" },
|
|
2971
|
+
left: { style: BorderStyle.NONE, size: 0, color: "auto" },
|
|
2972
|
+
right: { style: BorderStyle.NONE, size: 0, color: "auto" },
|
|
2973
|
+
insideHorizontal: { style: BorderStyle.NONE, size: 0, color: "auto" },
|
|
2974
|
+
insideVertical: { style: BorderStyle.NONE, size: 0, color: "auto" }
|
|
2975
|
+
},
|
|
2976
|
+
rows: [
|
|
2977
|
+
new TableRow({
|
|
2978
|
+
cantSplit: true,
|
|
2979
|
+
children: sigCells
|
|
2980
|
+
})
|
|
2981
|
+
]
|
|
2982
|
+
});
|
|
2983
|
+
docElements.push(sigTable);
|
|
2984
|
+
}
|
|
2985
|
+
const contentWidthTwip = Math.max(
|
|
2986
|
+
1e3,
|
|
2987
|
+
resolved.paperDimensions.widthTwip - resolved.margins.leftTwip - resolved.margins.rightTwip
|
|
2988
|
+
);
|
|
2989
|
+
const centerPos = Math.round(contentWidthTwip / 2);
|
|
2990
|
+
const rightPos = contentWidthTwip;
|
|
2991
|
+
const headerRuns = [];
|
|
2992
|
+
if ((_d = resolved.header) == null ? void 0 : _d.left) {
|
|
2993
|
+
headerRuns.push(
|
|
2994
|
+
new TextRun({
|
|
2995
|
+
text: resolved.header.left.text,
|
|
2996
|
+
color: resolved.header.left.color.replace("#", ""),
|
|
2997
|
+
size: (resolved.header.left.fontSize || 9) * 2,
|
|
2998
|
+
font: resolved.header.left.fontFamily || defaultFont,
|
|
2999
|
+
bold: resolved.header.left.bold,
|
|
3000
|
+
italics: resolved.header.left.italic
|
|
3001
|
+
})
|
|
3002
|
+
);
|
|
3003
|
+
}
|
|
3004
|
+
headerRuns.push(new TextRun({ text: " " }));
|
|
3005
|
+
if ((_e = resolved.header) == null ? void 0 : _e.center) {
|
|
3006
|
+
headerRuns.push(
|
|
3007
|
+
new TextRun({
|
|
3008
|
+
text: resolved.header.center.text,
|
|
3009
|
+
color: resolved.header.center.color.replace("#", ""),
|
|
3010
|
+
size: (resolved.header.center.fontSize || 9) * 2,
|
|
3011
|
+
font: resolved.header.center.fontFamily || defaultFont,
|
|
3012
|
+
bold: resolved.header.center.bold,
|
|
3013
|
+
italics: resolved.header.center.italic
|
|
3014
|
+
})
|
|
3015
|
+
);
|
|
3016
|
+
}
|
|
3017
|
+
headerRuns.push(new TextRun({ text: " " }));
|
|
3018
|
+
if ((_f = resolved.header) == null ? void 0 : _f.right) {
|
|
3019
|
+
headerRuns.push(
|
|
3020
|
+
new TextRun({
|
|
3021
|
+
text: resolved.header.right.text,
|
|
3022
|
+
color: resolved.header.right.color.replace("#", ""),
|
|
3023
|
+
size: (resolved.header.right.fontSize || 9) * 2,
|
|
3024
|
+
font: resolved.header.right.fontFamily || defaultFont,
|
|
3025
|
+
bold: resolved.header.right.bold,
|
|
3026
|
+
italics: resolved.header.right.italic
|
|
3027
|
+
})
|
|
3028
|
+
);
|
|
3029
|
+
}
|
|
3030
|
+
const docHeader = resolved.header ? new Header2({
|
|
2218
3031
|
children: [
|
|
2219
3032
|
new Paragraph({
|
|
2220
|
-
tabStops:
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
3033
|
+
tabStops: [
|
|
3034
|
+
{
|
|
3035
|
+
type: TabStopType.CENTER,
|
|
3036
|
+
position: centerPos
|
|
3037
|
+
},
|
|
3038
|
+
{
|
|
3039
|
+
type: TabStopType.RIGHT,
|
|
3040
|
+
position: rightPos
|
|
3041
|
+
}
|
|
3042
|
+
],
|
|
3043
|
+
border: resolved.header.divider ? {
|
|
3044
|
+
bottom: {
|
|
3045
|
+
style: BorderStyle.SINGLE,
|
|
3046
|
+
size: 4,
|
|
3047
|
+
space: 6,
|
|
3048
|
+
color: (resolved.header.dividerColor || "#CBD5E1").replace("#", "")
|
|
3049
|
+
}
|
|
3050
|
+
} : void 0,
|
|
3051
|
+
children: headerRuns,
|
|
3052
|
+
spacing: { after: 120 }
|
|
3053
|
+
})
|
|
3054
|
+
]
|
|
3055
|
+
}) : void 0;
|
|
3056
|
+
const footerRuns = [];
|
|
3057
|
+
if ((_g = resolved.footer) == null ? void 0 : _g.left) {
|
|
3058
|
+
footerRuns.push(
|
|
3059
|
+
new TextRun({
|
|
3060
|
+
text: resolved.footer.left.text,
|
|
3061
|
+
color: resolved.footer.left.color.replace("#", ""),
|
|
3062
|
+
size: (resolved.footer.left.fontSize || 9) * 2,
|
|
3063
|
+
font: resolved.footer.left.fontFamily || defaultFont,
|
|
3064
|
+
bold: resolved.footer.left.bold,
|
|
3065
|
+
italics: resolved.footer.left.italic
|
|
3066
|
+
})
|
|
3067
|
+
);
|
|
3068
|
+
}
|
|
3069
|
+
footerRuns.push(new TextRun({ text: " " }));
|
|
3070
|
+
if ((_h = resolved.footer) == null ? void 0 : _h.center) {
|
|
3071
|
+
footerRuns.push(
|
|
3072
|
+
new TextRun({
|
|
3073
|
+
text: resolved.footer.center.text,
|
|
3074
|
+
color: resolved.footer.center.color.replace("#", ""),
|
|
3075
|
+
size: (resolved.footer.center.fontSize || 9) * 2,
|
|
3076
|
+
font: resolved.footer.center.fontFamily || defaultFont,
|
|
3077
|
+
bold: resolved.footer.center.bold,
|
|
3078
|
+
italics: resolved.footer.center.italic
|
|
3079
|
+
})
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
footerRuns.push(new TextRun({ text: " " }));
|
|
3083
|
+
if ((_i = resolved.footer) == null ? void 0 : _i.right) {
|
|
3084
|
+
const rZone = resolved.footer.right;
|
|
3085
|
+
const rColor = rZone.color.replace("#", "");
|
|
3086
|
+
const rSize = (rZone.fontSize || 9) * 2;
|
|
3087
|
+
const rFont = rZone.fontFamily || defaultFont;
|
|
3088
|
+
const rBold = rZone.bold;
|
|
3089
|
+
const rItalics = rZone.italic;
|
|
3090
|
+
if (rZone.text.includes("{page}") || rZone.text.includes("{pages}")) {
|
|
3091
|
+
const parts = rZone.text.split(/(\{page\}|\{pages\})/gi);
|
|
3092
|
+
for (const part of parts) {
|
|
3093
|
+
if (part.toLowerCase() === "{page}") {
|
|
3094
|
+
footerRuns.push(
|
|
2224
3095
|
new TextRun({
|
|
2225
|
-
|
|
2226
|
-
color:
|
|
2227
|
-
size:
|
|
3096
|
+
children: [PageNumber.CURRENT],
|
|
3097
|
+
color: rColor,
|
|
3098
|
+
size: rSize,
|
|
3099
|
+
font: rFont,
|
|
3100
|
+
bold: rBold,
|
|
3101
|
+
italics: rItalics
|
|
2228
3102
|
})
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
new TextRun({ text: " ", color: "94A3B8", size: 18 }),
|
|
3103
|
+
);
|
|
3104
|
+
} else if (part.toLowerCase() === "{pages}") {
|
|
3105
|
+
footerRuns.push(
|
|
2233
3106
|
new TextRun({
|
|
2234
|
-
|
|
2235
|
-
color:
|
|
2236
|
-
size:
|
|
3107
|
+
children: [PageNumber.TOTAL_PAGES],
|
|
3108
|
+
color: rColor,
|
|
3109
|
+
size: rSize,
|
|
3110
|
+
font: rFont,
|
|
3111
|
+
bold: rBold,
|
|
3112
|
+
italics: rItalics
|
|
2237
3113
|
})
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
new TextRun({
|
|
2242
|
-
text: headerObj.left || headerObj.center ? " " : "",
|
|
2243
|
-
color: "94A3B8",
|
|
2244
|
-
size: 18
|
|
2245
|
-
}),
|
|
3114
|
+
);
|
|
3115
|
+
} else if (part) {
|
|
3116
|
+
footerRuns.push(
|
|
2246
3117
|
new TextRun({
|
|
2247
|
-
text:
|
|
2248
|
-
color:
|
|
2249
|
-
size:
|
|
3118
|
+
text: part,
|
|
3119
|
+
color: rColor,
|
|
3120
|
+
size: rSize,
|
|
3121
|
+
font: rFont,
|
|
3122
|
+
bold: rBold,
|
|
3123
|
+
italics: rItalics
|
|
2250
3124
|
})
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
3125
|
+
);
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
} else {
|
|
3129
|
+
footerRuns.push(
|
|
3130
|
+
new TextRun({
|
|
3131
|
+
text: rZone.text,
|
|
3132
|
+
color: rColor,
|
|
3133
|
+
size: rSize,
|
|
3134
|
+
font: rFont,
|
|
3135
|
+
bold: rBold,
|
|
3136
|
+
italics: rItalics
|
|
3137
|
+
})
|
|
3138
|
+
);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
const docFooter = resolved.footer ? new Footer({
|
|
2257
3142
|
children: [
|
|
2258
3143
|
new Paragraph({
|
|
2259
|
-
tabStops:
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
3144
|
+
tabStops: [
|
|
3145
|
+
{
|
|
3146
|
+
type: TabStopType.CENTER,
|
|
3147
|
+
position: centerPos
|
|
3148
|
+
},
|
|
3149
|
+
{
|
|
3150
|
+
type: TabStopType.RIGHT,
|
|
3151
|
+
position: rightPos
|
|
3152
|
+
}
|
|
3153
|
+
],
|
|
3154
|
+
border: resolved.footer.divider ? {
|
|
3155
|
+
top: {
|
|
3156
|
+
style: BorderStyle.SINGLE,
|
|
3157
|
+
size: 4,
|
|
3158
|
+
space: 6,
|
|
3159
|
+
color: (resolved.footer.dividerColor || "#CBD5E1").replace("#", "")
|
|
3160
|
+
}
|
|
3161
|
+
} : void 0,
|
|
3162
|
+
children: footerRuns,
|
|
3163
|
+
spacing: { before: 120 }
|
|
2276
3164
|
})
|
|
2277
3165
|
]
|
|
2278
3166
|
}) : void 0;
|
|
2279
|
-
const
|
|
2280
|
-
const bottomMargin = parseMarginToTwip(((_f = metadata.margins) == null ? void 0 : _f.bottom) || ((_g = config.margins) == null ? void 0 : _g.bottom), 1440);
|
|
2281
|
-
const leftMargin = parseMarginToTwip(((_h = metadata.margins) == null ? void 0 : _h.left) || ((_i = config.margins) == null ? void 0 : _i.left), 1440);
|
|
2282
|
-
const rightMargin = parseMarginToTwip(((_j = metadata.margins) == null ? void 0 : _j.right) || ((_k = config.margins) == null ? void 0 : _k.right), 1440);
|
|
2283
|
-
const isLandscape = (metadata.orientation || config.orientation) === "landscape";
|
|
3167
|
+
const isLandscape = resolved.orientation === "landscape";
|
|
2284
3168
|
const document = new Document({
|
|
2285
3169
|
styles: {
|
|
2286
3170
|
default: {
|
|
2287
3171
|
document: {
|
|
2288
3172
|
run: {
|
|
2289
|
-
font:
|
|
2290
|
-
size:
|
|
2291
|
-
//
|
|
2292
|
-
color:
|
|
3173
|
+
font: defaultFont,
|
|
3174
|
+
size: 21,
|
|
3175
|
+
// 10.5pt
|
|
3176
|
+
color: textHex
|
|
3177
|
+
},
|
|
3178
|
+
paragraph: {
|
|
3179
|
+
spacing: {
|
|
3180
|
+
line: 276,
|
|
3181
|
+
// 1.15 line spacing
|
|
3182
|
+
after: 140
|
|
3183
|
+
}
|
|
2293
3184
|
}
|
|
2294
3185
|
}
|
|
2295
3186
|
}
|
|
@@ -2299,13 +3190,15 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2299
3190
|
properties: {
|
|
2300
3191
|
page: {
|
|
2301
3192
|
size: {
|
|
3193
|
+
width: resolved.paperDimensions.widthTwip,
|
|
3194
|
+
height: resolved.paperDimensions.heightTwip,
|
|
2302
3195
|
orientation: isLandscape ? PageOrientation.LANDSCAPE : PageOrientation.PORTRAIT
|
|
2303
3196
|
},
|
|
2304
3197
|
margin: {
|
|
2305
|
-
top:
|
|
2306
|
-
bottom:
|
|
2307
|
-
left:
|
|
2308
|
-
right:
|
|
3198
|
+
top: resolved.margins.topTwip,
|
|
3199
|
+
bottom: resolved.margins.bottomTwip,
|
|
3200
|
+
left: resolved.margins.leftTwip,
|
|
3201
|
+
right: resolved.margins.rightTwip,
|
|
2309
3202
|
header: 720,
|
|
2310
3203
|
footer: 720
|
|
2311
3204
|
}
|
|
@@ -2319,6 +3212,140 @@ async function buildDocxDocument(doc, config, baseDir = process.cwd()) {
|
|
|
2319
3212
|
});
|
|
2320
3213
|
return await Packer.toBuffer(document);
|
|
2321
3214
|
}
|
|
3215
|
+
async function buildDocxSignatureCell(item, sig, widthDxa, defaultFont, baseDir) {
|
|
3216
|
+
const cellParagraphs = [];
|
|
3217
|
+
if (item.title) {
|
|
3218
|
+
cellParagraphs.push(
|
|
3219
|
+
new Paragraph({
|
|
3220
|
+
children: [
|
|
3221
|
+
new TextRun({
|
|
3222
|
+
text: item.title,
|
|
3223
|
+
font: defaultFont,
|
|
3224
|
+
size: 18,
|
|
3225
|
+
// 9pt
|
|
3226
|
+
color: sig.titleColor.replace("#", ""),
|
|
3227
|
+
bold: true
|
|
3228
|
+
})
|
|
3229
|
+
],
|
|
3230
|
+
spacing: { after: 60 }
|
|
3231
|
+
})
|
|
3232
|
+
);
|
|
3233
|
+
}
|
|
3234
|
+
if (item.image) {
|
|
3235
|
+
const resolvedImg = await resolveImage(item.image, baseDir);
|
|
3236
|
+
if (resolvedImg) {
|
|
3237
|
+
cellParagraphs.push(
|
|
3238
|
+
new Paragraph({
|
|
3239
|
+
children: [
|
|
3240
|
+
new ImageRun({
|
|
3241
|
+
data: resolvedImg.buffer,
|
|
3242
|
+
transformation: {
|
|
3243
|
+
width: 140,
|
|
3244
|
+
height: 60
|
|
3245
|
+
},
|
|
3246
|
+
type: "png"
|
|
3247
|
+
})
|
|
3248
|
+
],
|
|
3249
|
+
spacing: { before: 40, after: 40 }
|
|
3250
|
+
})
|
|
3251
|
+
);
|
|
3252
|
+
} else {
|
|
3253
|
+
cellParagraphs.push(new Paragraph({ spacing: { before: 240, after: 240 } }));
|
|
3254
|
+
}
|
|
3255
|
+
} else {
|
|
3256
|
+
cellParagraphs.push(new Paragraph({ spacing: { before: 240, after: 240 } }));
|
|
3257
|
+
}
|
|
3258
|
+
if (sig.style === "line") {
|
|
3259
|
+
cellParagraphs.push(
|
|
3260
|
+
new Paragraph({
|
|
3261
|
+
border: {
|
|
3262
|
+
bottom: {
|
|
3263
|
+
style: BorderStyle.SINGLE,
|
|
3264
|
+
size: 6,
|
|
3265
|
+
space: 2,
|
|
3266
|
+
color: sig.borderColor.replace("#", "")
|
|
3267
|
+
}
|
|
3268
|
+
},
|
|
3269
|
+
spacing: { after: 60 }
|
|
3270
|
+
})
|
|
3271
|
+
);
|
|
3272
|
+
}
|
|
3273
|
+
cellParagraphs.push(
|
|
3274
|
+
new Paragraph({
|
|
3275
|
+
children: [
|
|
3276
|
+
new TextRun({
|
|
3277
|
+
text: item.name,
|
|
3278
|
+
font: defaultFont,
|
|
3279
|
+
size: 21,
|
|
3280
|
+
// 10.5pt
|
|
3281
|
+
bold: true,
|
|
3282
|
+
color: sig.nameColor.replace("#", "")
|
|
3283
|
+
})
|
|
3284
|
+
],
|
|
3285
|
+
spacing: { before: sig.style === "line" ? 40 : 20, after: 20 }
|
|
3286
|
+
})
|
|
3287
|
+
);
|
|
3288
|
+
if (item.role) {
|
|
3289
|
+
cellParagraphs.push(
|
|
3290
|
+
new Paragraph({
|
|
3291
|
+
children: [
|
|
3292
|
+
new TextRun({
|
|
3293
|
+
text: item.role,
|
|
3294
|
+
font: defaultFont,
|
|
3295
|
+
size: 18,
|
|
3296
|
+
// 9pt
|
|
3297
|
+
color: sig.roleColor.replace("#", "")
|
|
3298
|
+
})
|
|
3299
|
+
],
|
|
3300
|
+
spacing: { after: 20 }
|
|
3301
|
+
})
|
|
3302
|
+
);
|
|
3303
|
+
}
|
|
3304
|
+
if (item.date) {
|
|
3305
|
+
cellParagraphs.push(
|
|
3306
|
+
new Paragraph({
|
|
3307
|
+
children: [
|
|
3308
|
+
new TextRun({
|
|
3309
|
+
text: `Date: ${item.date}`,
|
|
3310
|
+
font: defaultFont,
|
|
3311
|
+
size: 17,
|
|
3312
|
+
// 8.5pt
|
|
3313
|
+
color: sig.roleColor.replace("#", "")
|
|
3314
|
+
})
|
|
3315
|
+
],
|
|
3316
|
+
spacing: { after: 20 }
|
|
3317
|
+
})
|
|
3318
|
+
);
|
|
3319
|
+
}
|
|
3320
|
+
const isBox = sig.style === "box";
|
|
3321
|
+
const boxBorder = { style: BorderStyle.SINGLE, size: 4, color: sig.borderColor.replace("#", "") };
|
|
3322
|
+
const noneBorder = { style: BorderStyle.NONE, size: 0, color: "auto" };
|
|
3323
|
+
return new TableCell({
|
|
3324
|
+
width: { size: widthDxa, type: WidthType.DXA },
|
|
3325
|
+
shading: isBox ? { fill: "F8FAFC", type: ShadingType.CLEAR } : void 0,
|
|
3326
|
+
margins: isBox ? { top: 140, bottom: 140, left: 160, right: 160 } : { top: 60, bottom: 60, left: 60, right: 60 },
|
|
3327
|
+
borders: {
|
|
3328
|
+
top: isBox ? boxBorder : noneBorder,
|
|
3329
|
+
bottom: isBox ? boxBorder : noneBorder,
|
|
3330
|
+
left: isBox ? boxBorder : noneBorder,
|
|
3331
|
+
right: isBox ? boxBorder : noneBorder
|
|
3332
|
+
},
|
|
3333
|
+
children: cellParagraphs
|
|
3334
|
+
});
|
|
3335
|
+
}
|
|
3336
|
+
function createEmptyDocxCell(widthDxa) {
|
|
3337
|
+
const noneBorder = { style: BorderStyle.NONE, size: 0, color: "auto" };
|
|
3338
|
+
return new TableCell({
|
|
3339
|
+
width: { size: widthDxa, type: WidthType.DXA },
|
|
3340
|
+
borders: {
|
|
3341
|
+
top: noneBorder,
|
|
3342
|
+
bottom: noneBorder,
|
|
3343
|
+
left: noneBorder,
|
|
3344
|
+
right: noneBorder
|
|
3345
|
+
},
|
|
3346
|
+
children: [new Paragraph({})]
|
|
3347
|
+
});
|
|
3348
|
+
}
|
|
2322
3349
|
|
|
2323
3350
|
// src/core/engine.ts
|
|
2324
3351
|
async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgress) {
|
|
@@ -2331,15 +3358,15 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
2331
3358
|
if (fs5.existsSync(inputFilePathOrContent)) {
|
|
2332
3359
|
isFilePath = true;
|
|
2333
3360
|
rawMarkdown = fs5.readFileSync(inputFilePathOrContent, "utf-8");
|
|
2334
|
-
baseDir =
|
|
2335
|
-
inputFileName =
|
|
3361
|
+
baseDir = path7.dirname(path7.resolve(inputFilePathOrContent));
|
|
3362
|
+
inputFileName = path7.basename(inputFilePathOrContent);
|
|
2336
3363
|
} else {
|
|
2337
3364
|
rawMarkdown = inputFilePathOrContent;
|
|
2338
3365
|
}
|
|
2339
3366
|
onProgress == null ? void 0 : onProgress(`Parsing markdown AST: ${inputFileName}...`);
|
|
2340
3367
|
const parsedDoc = parseMarkdownDocument(rawMarkdown);
|
|
2341
3368
|
const baseName = inputFileName.replace(/\.(md|mdx|markdown)$/i, "");
|
|
2342
|
-
const outputDir = config.outputDir ?
|
|
3369
|
+
const outputDir = config.outputDir ? path7.isAbsolute(config.outputDir) ? config.outputDir : path7.resolve(process.cwd(), config.outputDir) : baseDir;
|
|
2343
3370
|
if (!fs5.existsSync(outputDir)) {
|
|
2344
3371
|
fs5.mkdirSync(outputDir, { recursive: true });
|
|
2345
3372
|
}
|
|
@@ -2351,7 +3378,7 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
2351
3378
|
if (fmt === "docx") {
|
|
2352
3379
|
onProgress == null ? void 0 : onProgress(`Generating DOCX document: ${baseName}.docx...`);
|
|
2353
3380
|
const docxBuffer = await buildDocxDocument(parsedDoc, config, baseDir);
|
|
2354
|
-
const docxPath =
|
|
3381
|
+
const docxPath = path7.join(outputDir, `${baseName}.docx`);
|
|
2355
3382
|
fs5.writeFileSync(docxPath, docxBuffer);
|
|
2356
3383
|
generatedFiles.push({
|
|
2357
3384
|
format: "docx",
|
|
@@ -2362,7 +3389,7 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
2362
3389
|
} else if (fmt === "html") {
|
|
2363
3390
|
onProgress == null ? void 0 : onProgress(`Generating HTML document: ${baseName}.html...`);
|
|
2364
3391
|
const htmlString = await buildHtmlDocument(parsedDoc, config, baseDir);
|
|
2365
|
-
const htmlPath =
|
|
3392
|
+
const htmlPath = path7.join(outputDir, `${baseName}.html`);
|
|
2366
3393
|
fs5.writeFileSync(htmlPath, htmlString, "utf-8");
|
|
2367
3394
|
generatedFiles.push({
|
|
2368
3395
|
format: "html",
|
|
@@ -2373,7 +3400,7 @@ async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgre
|
|
|
2373
3400
|
} else if (fmt === "pdf") {
|
|
2374
3401
|
onProgress == null ? void 0 : onProgress(`Generating PDF document: ${baseName}.pdf...`);
|
|
2375
3402
|
const pdfBuffer = await buildPdfDocument(parsedDoc, config, baseDir);
|
|
2376
|
-
const pdfPath =
|
|
3403
|
+
const pdfPath = path7.join(outputDir, `${baseName}.pdf`);
|
|
2377
3404
|
fs5.writeFileSync(pdfPath, pdfBuffer);
|
|
2378
3405
|
generatedFiles.push({
|
|
2379
3406
|
format: "pdf",
|
|
@@ -2426,8 +3453,16 @@ var App = ({ inputFile, config, onComplete }) => {
|
|
|
2426
3453
|
}
|
|
2427
3454
|
run();
|
|
2428
3455
|
}, [inputFile, config, onComplete]);
|
|
3456
|
+
const targetFormats = Array.isArray(config.to) ? config.to : config.to ? [String(config.to)] : ["docx", "pdf"];
|
|
2429
3457
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
2430
|
-
/* @__PURE__ */ jsx4(
|
|
3458
|
+
/* @__PURE__ */ jsx4(
|
|
3459
|
+
Header,
|
|
3460
|
+
{
|
|
3461
|
+
inputFile,
|
|
3462
|
+
theme: config.theme,
|
|
3463
|
+
targetFormats
|
|
3464
|
+
}
|
|
3465
|
+
),
|
|
2431
3466
|
/* @__PURE__ */ jsx4(LiveProgress, { status, isCompiling }),
|
|
2432
3467
|
/* @__PURE__ */ jsx4(SummaryTable, { result })
|
|
2433
3468
|
] });
|