@masumdev/markforge 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/App-JOOTPDJN.mjs +847 -0
- package/dist/{chunk-CRV7R2BG.mjs → chunk-H3ZUUSHP.mjs} +303 -98
- package/dist/{chunk-TNWZ4MFS.mjs → chunk-UNWAEVDU.mjs} +4 -3
- package/dist/cli.mjs +14 -6
- package/dist/index.d.mts +117 -50
- package/dist/index.d.ts +117 -50
- package/dist/index.js +838 -145
- package/dist/index.mjs +826 -139
- package/dist/{previewServer-XAUOBNBZ.mjs → previewServer-U47WQ5FV.mjs} +1 -1
- package/package.json +1 -1
- package/dist/App-3QDKBKHG.mjs +0 -328
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masumdev/markforge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Modern, high-performance Markdown & MDX multi-format document publishing engine and CLI (DOCX, PDF, HTML, and Images) with embedded HTML/CSS, image inliner, and Ink terminal UI.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
package/dist/App-3QDKBKHG.mjs
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
try {
|
|
3
|
-
if (typeof globalThis !== "undefined" && (!globalThis.localStorage || typeof globalThis.localStorage.getItem !== "function")) {
|
|
4
|
-
Object.defineProperty(globalThis, "localStorage", {
|
|
5
|
-
value: { getItem: () => null, setItem: () => {}, removeItem: () => {}, clear: () => {}, key: () => null, length: 0 },
|
|
6
|
-
configurable: true, writable: true,
|
|
7
|
-
});
|
|
8
|
-
}
|
|
9
|
-
} catch {}
|
|
10
|
-
import {
|
|
11
|
-
MARKFORGE_VERSION
|
|
12
|
-
} from "./chunk-TNWZ4MFS.mjs";
|
|
13
|
-
import {
|
|
14
|
-
buildDocxDocument,
|
|
15
|
-
buildHtmlDocument,
|
|
16
|
-
buildPdfDocument,
|
|
17
|
-
parseMarkdownDocument
|
|
18
|
-
} from "./chunk-CRV7R2BG.mjs";
|
|
19
|
-
import {
|
|
20
|
-
DEFAULT_CONFIG
|
|
21
|
-
} from "./chunk-BPHDY6VB.mjs";
|
|
22
|
-
import "./chunk-YZHGBG4N.mjs";
|
|
23
|
-
|
|
24
|
-
// src/ui/App.tsx
|
|
25
|
-
import { useState, useEffect } from "react";
|
|
26
|
-
import { Box as Box4 } from "ink";
|
|
27
|
-
|
|
28
|
-
// src/ui/Header.tsx
|
|
29
|
-
import * as path from "path";
|
|
30
|
-
import { Box, Text } from "ink";
|
|
31
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
32
|
-
function formatDisplayPath(p) {
|
|
33
|
-
if (!p) return "";
|
|
34
|
-
try {
|
|
35
|
-
const rel = path.relative(process.cwd(), p);
|
|
36
|
-
return rel && !rel.startsWith("..") && rel.length < p.length ? `./${rel}` : p;
|
|
37
|
-
} catch {
|
|
38
|
-
return p;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
var Header = ({
|
|
42
|
-
inputFile,
|
|
43
|
-
theme = "corporate",
|
|
44
|
-
targetFormats = ["docx", "pdf"]
|
|
45
|
-
}) => {
|
|
46
|
-
const themeLabel = typeof theme === "object" ? "Custom (ThemeProps)" : String(theme || "corporate");
|
|
47
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: /* @__PURE__ */ jsxs(
|
|
48
|
-
Box,
|
|
49
|
-
{
|
|
50
|
-
borderStyle: "round",
|
|
51
|
-
borderColor: "cyan",
|
|
52
|
-
paddingX: 2,
|
|
53
|
-
paddingY: 1,
|
|
54
|
-
flexDirection: "column",
|
|
55
|
-
children: [
|
|
56
|
-
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", alignItems: "center", children: [
|
|
57
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
58
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "MARKFORGE" }),
|
|
59
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: " | Document Publishing Engine" })
|
|
60
|
-
] }),
|
|
61
|
-
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "black", backgroundColor: "cyan", bold: true, children: [
|
|
62
|
-
" ",
|
|
63
|
-
"v",
|
|
64
|
-
MARKFORGE_VERSION,
|
|
65
|
-
" "
|
|
66
|
-
] }) })
|
|
67
|
-
] }),
|
|
68
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
69
|
-
inputFile && /* @__PURE__ */ jsxs(Box, { children: [
|
|
70
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Source: " }),
|
|
71
|
-
/* @__PURE__ */ jsx(Text, { color: "white", bold: true, children: formatDisplayPath(inputFile) })
|
|
72
|
-
] }),
|
|
73
|
-
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", marginTop: 0, children: [
|
|
74
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
75
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Theme: " }),
|
|
76
|
-
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: themeLabel })
|
|
77
|
-
] }),
|
|
78
|
-
targetFormats && targetFormats.length > 0 && /* @__PURE__ */ jsxs(Box, { children: [
|
|
79
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Targets: " }),
|
|
80
|
-
/* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: targetFormats.map((f) => f.toUpperCase()).join(", ") })
|
|
81
|
-
] })
|
|
82
|
-
] })
|
|
83
|
-
] }),
|
|
84
|
-
/* @__PURE__ */ jsxs(Box, { marginTop: 1, justifyContent: "space-between", children: [
|
|
85
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
86
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Author: " }),
|
|
87
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "Ma'sum" }),
|
|
88
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: " (@masumrpg)" })
|
|
89
|
-
] }),
|
|
90
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
91
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "GitHub: " }),
|
|
92
|
-
/* @__PURE__ */ jsx(Text, { color: "blue", underline: true, children: "https://github.com/masumrpg" })
|
|
93
|
-
] })
|
|
94
|
-
] })
|
|
95
|
-
]
|
|
96
|
-
}
|
|
97
|
-
) });
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// src/ui/LiveProgress.tsx
|
|
101
|
-
import { Box as Box2, Text as Text2 } from "ink";
|
|
102
|
-
import Spinner from "ink-spinner";
|
|
103
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
104
|
-
var LiveProgress = ({ status, isCompiling }) => {
|
|
105
|
-
if (!isCompiling) return null;
|
|
106
|
-
return /* @__PURE__ */ jsxs2(Box2, { marginY: 1, alignItems: "center", children: [
|
|
107
|
-
/* @__PURE__ */ jsx2(Text2, { color: "cyan", children: /* @__PURE__ */ jsx2(Spinner, { type: "dots" }) }),
|
|
108
|
-
/* @__PURE__ */ jsxs2(Box2, { marginLeft: 1, children: [
|
|
109
|
-
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "[COMPILING] " }),
|
|
110
|
-
/* @__PURE__ */ jsx2(Text2, { color: "white", children: status })
|
|
111
|
-
] })
|
|
112
|
-
] });
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// src/ui/SummaryTable.tsx
|
|
116
|
-
import * as path2 from "path";
|
|
117
|
-
import { Box as Box3, Text as Text3 } from "ink";
|
|
118
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
119
|
-
function formatBytes(bytes) {
|
|
120
|
-
if (bytes === 0) return "0 B";
|
|
121
|
-
const k = 1024;
|
|
122
|
-
const sizes = ["B", "KB", "MB", "GB"];
|
|
123
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
124
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
|
125
|
-
}
|
|
126
|
-
function formatDisplayPath2(p) {
|
|
127
|
-
if (!p) return "";
|
|
128
|
-
try {
|
|
129
|
-
const rel = path2.relative(process.cwd(), p);
|
|
130
|
-
return rel && !rel.startsWith("..") && rel.length < p.length ? `./${rel}` : p;
|
|
131
|
-
} catch {
|
|
132
|
-
return p;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
var SummaryTable = ({ result }) => {
|
|
136
|
-
if (!result) return null;
|
|
137
|
-
const hasErrors = result.errors.length > 0;
|
|
138
|
-
return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", marginY: 1, children: /* @__PURE__ */ jsxs3(
|
|
139
|
-
Box3,
|
|
140
|
-
{
|
|
141
|
-
borderStyle: "round",
|
|
142
|
-
borderColor: hasErrors ? "red" : "green",
|
|
143
|
-
paddingX: 2,
|
|
144
|
-
paddingY: 1,
|
|
145
|
-
flexDirection: "column",
|
|
146
|
-
children: [
|
|
147
|
-
/* @__PURE__ */ jsxs3(Box3, { justifyContent: "space-between", alignItems: "center", children: [
|
|
148
|
-
/* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: hasErrors ? "red" : "green", children: hasErrors ? "[COMPILATION FAILED]" : "[COMPILATION SUCCESSFUL]" }) }),
|
|
149
|
-
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
150
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Duration: " }),
|
|
151
|
-
/* @__PURE__ */ jsxs3(Text3, { color: "yellow", bold: true, children: [
|
|
152
|
-
result.durationMs,
|
|
153
|
-
"ms"
|
|
154
|
-
] })
|
|
155
|
-
] })
|
|
156
|
-
] }),
|
|
157
|
-
result.files.length > 0 && /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
|
|
158
|
-
/* @__PURE__ */ jsxs3(Text3, { bold: true, color: "white", children: [
|
|
159
|
-
"Generated Documents (",
|
|
160
|
-
result.files.length,
|
|
161
|
-
"):"
|
|
162
|
-
] }),
|
|
163
|
-
result.files.map((f, i) => {
|
|
164
|
-
const formatColor = f.format === "docx" ? "blue" : f.format === "pdf" ? "red" : "yellow";
|
|
165
|
-
const paddedBadge = `[${f.format.toUpperCase()}]`.padEnd(7, " ");
|
|
166
|
-
return /* @__PURE__ */ jsxs3(Box3, { marginTop: 0, flexDirection: "column", marginLeft: 1, children: [
|
|
167
|
-
/* @__PURE__ */ jsxs3(Box3, { justifyContent: "space-between", alignItems: "center", children: [
|
|
168
|
-
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
169
|
-
/* @__PURE__ */ jsx3(Text3, { color: formatColor, bold: true, children: paddedBadge }),
|
|
170
|
-
/* @__PURE__ */ jsx3(Text3, { color: "white", bold: true, children: f.fileName })
|
|
171
|
-
] }),
|
|
172
|
-
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: formatBytes(f.sizeBytes) })
|
|
173
|
-
] }),
|
|
174
|
-
/* @__PURE__ */ jsx3(Box3, { marginLeft: 2, children: /* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
175
|
-
"\u2514\u2500 ",
|
|
176
|
-
formatDisplayPath2(f.filePath)
|
|
177
|
-
] }) })
|
|
178
|
-
] }, i);
|
|
179
|
-
})
|
|
180
|
-
] }),
|
|
181
|
-
hasErrors && /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
|
|
182
|
-
/* @__PURE__ */ jsx3(Text3, { bold: true, color: "red", children: "Errors:" }),
|
|
183
|
-
result.errors.map((err, i) => /* @__PURE__ */ jsx3(Box3, { marginLeft: 2, children: /* @__PURE__ */ jsxs3(Text3, { color: "red", children: [
|
|
184
|
-
"- ",
|
|
185
|
-
err
|
|
186
|
-
] }) }, i))
|
|
187
|
-
] }),
|
|
188
|
-
/* @__PURE__ */ jsxs3(Box3, { marginTop: 1, justifyContent: "space-between", alignItems: "center", children: [
|
|
189
|
-
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
190
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Author: " }),
|
|
191
|
-
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: "Ma'sum" }),
|
|
192
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: " (@masumrpg)" })
|
|
193
|
-
] }),
|
|
194
|
-
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
195
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "GitHub: " }),
|
|
196
|
-
/* @__PURE__ */ jsx3(Text3, { color: "blue", underline: true, children: "https://github.com/masumrpg" })
|
|
197
|
-
] })
|
|
198
|
-
] })
|
|
199
|
-
]
|
|
200
|
-
}
|
|
201
|
-
) });
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
// src/core/engine.ts
|
|
205
|
-
import * as fs from "fs";
|
|
206
|
-
import * as path3 from "path";
|
|
207
|
-
async function compileMarkdown(inputFilePathOrContent, userConfig = {}, onProgress) {
|
|
208
|
-
const startTime = Date.now();
|
|
209
|
-
const config = { ...DEFAULT_CONFIG, ...userConfig };
|
|
210
|
-
let rawMarkdown = "";
|
|
211
|
-
let baseDir = process.cwd();
|
|
212
|
-
let inputFileName = "document.md";
|
|
213
|
-
let isFilePath = false;
|
|
214
|
-
if (fs.existsSync(inputFilePathOrContent)) {
|
|
215
|
-
isFilePath = true;
|
|
216
|
-
rawMarkdown = fs.readFileSync(inputFilePathOrContent, "utf-8");
|
|
217
|
-
baseDir = path3.dirname(path3.resolve(inputFilePathOrContent));
|
|
218
|
-
inputFileName = path3.basename(inputFilePathOrContent);
|
|
219
|
-
} else {
|
|
220
|
-
rawMarkdown = inputFilePathOrContent;
|
|
221
|
-
}
|
|
222
|
-
onProgress == null ? void 0 : onProgress(`Parsing markdown AST: ${inputFileName}...`);
|
|
223
|
-
const parsedDoc = parseMarkdownDocument(rawMarkdown);
|
|
224
|
-
const baseName = inputFileName.replace(/\.(md|mdx|markdown)$/i, "");
|
|
225
|
-
const outputDir = config.outputDir ? path3.isAbsolute(config.outputDir) ? config.outputDir : path3.resolve(process.cwd(), config.outputDir) : baseDir;
|
|
226
|
-
if (!fs.existsSync(outputDir)) {
|
|
227
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
228
|
-
}
|
|
229
|
-
const formats = Array.isArray(config.to) ? config.to : [config.to || "docx", "pdf"];
|
|
230
|
-
const generatedFiles = [];
|
|
231
|
-
const errors = [];
|
|
232
|
-
for (const fmt of formats) {
|
|
233
|
-
try {
|
|
234
|
-
if (fmt === "docx") {
|
|
235
|
-
onProgress == null ? void 0 : onProgress(`Generating DOCX document: ${baseName}.docx...`);
|
|
236
|
-
const docxBuffer = await buildDocxDocument(parsedDoc, config, baseDir);
|
|
237
|
-
const docxPath = path3.join(outputDir, `${baseName}.docx`);
|
|
238
|
-
fs.writeFileSync(docxPath, docxBuffer);
|
|
239
|
-
generatedFiles.push({
|
|
240
|
-
format: "docx",
|
|
241
|
-
filePath: docxPath,
|
|
242
|
-
fileName: `${baseName}.docx`,
|
|
243
|
-
sizeBytes: docxBuffer.length
|
|
244
|
-
});
|
|
245
|
-
} else if (fmt === "html") {
|
|
246
|
-
onProgress == null ? void 0 : onProgress(`Generating HTML document: ${baseName}.html...`);
|
|
247
|
-
const htmlString = await buildHtmlDocument(parsedDoc, config, baseDir);
|
|
248
|
-
const htmlPath = path3.join(outputDir, `${baseName}.html`);
|
|
249
|
-
fs.writeFileSync(htmlPath, htmlString, "utf-8");
|
|
250
|
-
generatedFiles.push({
|
|
251
|
-
format: "html",
|
|
252
|
-
filePath: htmlPath,
|
|
253
|
-
fileName: `${baseName}.html`,
|
|
254
|
-
sizeBytes: Buffer.byteLength(htmlString, "utf-8")
|
|
255
|
-
});
|
|
256
|
-
} else if (fmt === "pdf") {
|
|
257
|
-
onProgress == null ? void 0 : onProgress(`Generating PDF document: ${baseName}.pdf...`);
|
|
258
|
-
const pdfBuffer = await buildPdfDocument(parsedDoc, config, baseDir);
|
|
259
|
-
const pdfPath = path3.join(outputDir, `${baseName}.pdf`);
|
|
260
|
-
fs.writeFileSync(pdfPath, pdfBuffer);
|
|
261
|
-
generatedFiles.push({
|
|
262
|
-
format: "pdf",
|
|
263
|
-
filePath: pdfPath,
|
|
264
|
-
fileName: `${baseName}.pdf`,
|
|
265
|
-
sizeBytes: pdfBuffer.length
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
} catch (err) {
|
|
269
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
270
|
-
errors.push(`Failed to generate ${fmt}: ${errMsg}`);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
const durationMs = Date.now() - startTime;
|
|
274
|
-
return {
|
|
275
|
-
inputFile: isFilePath ? inputFilePathOrContent : "inline-string",
|
|
276
|
-
durationMs,
|
|
277
|
-
metadata: parsedDoc.metadata,
|
|
278
|
-
files: generatedFiles,
|
|
279
|
-
errors
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// src/ui/App.tsx
|
|
284
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
285
|
-
var App = ({ inputFile, config, onComplete }) => {
|
|
286
|
-
const [status, setStatus] = useState("Initializing...");
|
|
287
|
-
const [isCompiling, setIsCompiling] = useState(true);
|
|
288
|
-
const [result, setResult] = useState(null);
|
|
289
|
-
useEffect(() => {
|
|
290
|
-
async function run() {
|
|
291
|
-
try {
|
|
292
|
-
const res = await compileMarkdown(inputFile, config, (msg) => setStatus(msg));
|
|
293
|
-
setResult(res);
|
|
294
|
-
setIsCompiling(false);
|
|
295
|
-
onComplete == null ? void 0 : onComplete(res);
|
|
296
|
-
} catch (err) {
|
|
297
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
298
|
-
const errResult = {
|
|
299
|
-
inputFile,
|
|
300
|
-
durationMs: 0,
|
|
301
|
-
metadata: {},
|
|
302
|
-
files: [],
|
|
303
|
-
errors: [errMsg]
|
|
304
|
-
};
|
|
305
|
-
setResult(errResult);
|
|
306
|
-
setIsCompiling(false);
|
|
307
|
-
onComplete == null ? void 0 : onComplete(errResult);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
run();
|
|
311
|
-
}, [inputFile, config, onComplete]);
|
|
312
|
-
const targetFormats = Array.isArray(config.to) ? config.to : config.to ? [String(config.to)] : ["docx", "pdf"];
|
|
313
|
-
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
314
|
-
/* @__PURE__ */ jsx4(
|
|
315
|
-
Header,
|
|
316
|
-
{
|
|
317
|
-
inputFile,
|
|
318
|
-
theme: config.theme,
|
|
319
|
-
targetFormats
|
|
320
|
-
}
|
|
321
|
-
),
|
|
322
|
-
/* @__PURE__ */ jsx4(LiveProgress, { status, isCompiling }),
|
|
323
|
-
/* @__PURE__ */ jsx4(SummaryTable, { result })
|
|
324
|
-
] });
|
|
325
|
-
};
|
|
326
|
-
export {
|
|
327
|
-
App
|
|
328
|
-
};
|