mduck 1.0.2 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/mduck.js +44 -69
- package/package.json +1 -1
package/bin/mduck.js
CHANGED
|
@@ -1,37 +1,12 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
-
mod
|
|
24
|
-
));
|
|
25
|
-
|
|
26
1
|
// src/index.ts
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
2
|
+
import { mkdir, readFile, stat, writeFile } from "fs/promises";
|
|
3
|
+
import { basename, dirname, extname, isAbsolute, join, resolve, sep } from "path";
|
|
4
|
+
import { createRequire } from "module";
|
|
5
|
+
import { pathToFileURL } from "url";
|
|
6
|
+
import { defineCommand, runMain } from "citty";
|
|
7
|
+
import { marked } from "marked";
|
|
8
|
+
import puppeteer from "puppeteer";
|
|
9
|
+
import { compile } from "tailwindcss";
|
|
35
10
|
|
|
36
11
|
// src/template.html
|
|
37
12
|
var template_default = '<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>Document</title>\n</head>\n<body>\n <article class="prose lg:prose-xl print:prose-sm mx-auto my-8 print:m-0 px-4">\n [BODY]\n </article>\n <style>\n @media print {\n @page {\n margin: 2cm !important; /* Sets a 2cm margin on all sides of every printed page */\n }\n }\n table {\n border: 1px solid black;\n border-collapse: collapse;\n }\n th, td {\n border: 1px solid black;\n padding: 0.5em;\n }\n </style>\n</body>\n</html>\n';
|
|
@@ -39,7 +14,7 @@ var template_default = '<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta cha
|
|
|
39
14
|
// package.json
|
|
40
15
|
var package_default = {
|
|
41
16
|
name: "mduck",
|
|
42
|
-
version: "1.0.
|
|
17
|
+
version: "1.0.5",
|
|
43
18
|
description: "A CLI tool to convert Markdown files into HTML and PDF documents using Tailwind CSS v4 for styling.",
|
|
44
19
|
files: [
|
|
45
20
|
"bin/",
|
|
@@ -86,8 +61,8 @@ var package_default = {
|
|
|
86
61
|
var BODY_PLACEHOLDER = "[BODY]";
|
|
87
62
|
var DEFAULT_TEMPLATE_HTML = template_default;
|
|
88
63
|
var DEFAULT_EJECTED_TEMPLATE_FILENAME = "mduck.template.html";
|
|
89
|
-
var RUNTIME_ENTRY_DIR =
|
|
90
|
-
var require2 =
|
|
64
|
+
var RUNTIME_ENTRY_DIR = dirname(resolve(process.argv[1] ?? process.cwd()));
|
|
65
|
+
var require2 = createRequire(resolve(RUNTIME_ENTRY_DIR, "__mduck_require__.cjs"));
|
|
91
66
|
var TAILWIND_INPUT_CSS = `@import "tailwindcss";
|
|
92
67
|
@plugin "@tailwindcss/typography";`;
|
|
93
68
|
var pageBreak = {
|
|
@@ -102,20 +77,20 @@ var pageBreak = {
|
|
|
102
77
|
renderer: () => '<div class="break-after-page"></div>'
|
|
103
78
|
};
|
|
104
79
|
var toAbsolutePath = (filePath) => {
|
|
105
|
-
return
|
|
80
|
+
return isAbsolute(filePath) ? filePath : resolve(process.cwd(), filePath);
|
|
106
81
|
};
|
|
107
82
|
var inferOutputPath = (inputPath) => {
|
|
108
|
-
const inputExt =
|
|
83
|
+
const inputExt = extname(inputPath).toLowerCase();
|
|
109
84
|
if (inputExt === ".md") {
|
|
110
85
|
return inputPath.slice(0, -3) + ".html";
|
|
111
86
|
}
|
|
112
87
|
return `${inputPath}.html`;
|
|
113
88
|
};
|
|
114
89
|
var inferHtmlBasename = (inputPath) => {
|
|
115
|
-
return
|
|
90
|
+
return basename(inferOutputPath(inputPath));
|
|
116
91
|
};
|
|
117
92
|
var inferPdfPath = (htmlOutputPath) => {
|
|
118
|
-
const outputExt =
|
|
93
|
+
const outputExt = extname(htmlOutputPath).toLowerCase();
|
|
119
94
|
if (!outputExt) {
|
|
120
95
|
return `${htmlOutputPath}.pdf`;
|
|
121
96
|
}
|
|
@@ -163,19 +138,19 @@ var resolveCssImportPath = (id, base) => {
|
|
|
163
138
|
}
|
|
164
139
|
};
|
|
165
140
|
var compileTailwindCss = async (html) => {
|
|
166
|
-
const compiler = await
|
|
141
|
+
const compiler = await compile(TAILWIND_INPUT_CSS, {
|
|
167
142
|
base: process.cwd(),
|
|
168
143
|
from: "mduck.inline.css",
|
|
169
144
|
loadModule: async (id, base) => {
|
|
170
145
|
const resolvedPath = resolveCssImportPath(id, base);
|
|
171
|
-
const imported = await import(
|
|
172
|
-
const
|
|
173
|
-
return { path: resolvedPath, base:
|
|
146
|
+
const imported = await import(pathToFileURL(resolvedPath).href);
|
|
147
|
+
const module = imported.default ?? imported;
|
|
148
|
+
return { path: resolvedPath, base: dirname(resolvedPath), module };
|
|
174
149
|
},
|
|
175
150
|
loadStylesheet: async (id, base) => {
|
|
176
151
|
const resolvedPath = resolveCssImportPath(id, base);
|
|
177
|
-
const content = await
|
|
178
|
-
return { path: resolvedPath, base:
|
|
152
|
+
const content = await readFile(resolvedPath, "utf8");
|
|
153
|
+
return { path: resolvedPath, base: dirname(resolvedPath), content };
|
|
179
154
|
}
|
|
180
155
|
});
|
|
181
156
|
return compiler.build(collectTailwindCandidates(html));
|
|
@@ -191,7 +166,7 @@ ${headCloseTag}`);
|
|
|
191
166
|
${html}`;
|
|
192
167
|
};
|
|
193
168
|
var renderPdf = async (html, outputPath) => {
|
|
194
|
-
const browser = await
|
|
169
|
+
const browser = await puppeteer.launch();
|
|
195
170
|
try {
|
|
196
171
|
const page = await browser.newPage();
|
|
197
172
|
await page.setContent(html, { waitUntil: "networkidle0" });
|
|
@@ -207,21 +182,21 @@ var renderPdf = async (html, outputPath) => {
|
|
|
207
182
|
};
|
|
208
183
|
var resolveEjectedTemplatePath = async (outputArg) => {
|
|
209
184
|
if (!outputArg) {
|
|
210
|
-
return
|
|
185
|
+
return resolve(process.cwd(), DEFAULT_EJECTED_TEMPLATE_FILENAME);
|
|
211
186
|
}
|
|
212
187
|
const resolvedTargetPath = toAbsolutePath(outputArg);
|
|
213
|
-
const targetStats = await
|
|
214
|
-
const looksLikeDirectory = outputArg.endsWith(
|
|
188
|
+
const targetStats = await stat(resolvedTargetPath).catch(() => null);
|
|
189
|
+
const looksLikeDirectory = outputArg.endsWith(sep) || outputArg.endsWith("/");
|
|
215
190
|
const isDirectoryTarget = Boolean(targetStats?.isDirectory() || looksLikeDirectory);
|
|
216
191
|
if (isDirectoryTarget) {
|
|
217
|
-
return
|
|
192
|
+
return join(resolvedTargetPath, DEFAULT_EJECTED_TEMPLATE_FILENAME);
|
|
218
193
|
}
|
|
219
194
|
return resolvedTargetPath;
|
|
220
195
|
};
|
|
221
196
|
var runEjectTemplate = async (outputArg) => {
|
|
222
197
|
const templateOutputPath = await resolveEjectedTemplatePath(outputArg);
|
|
223
|
-
await
|
|
224
|
-
await
|
|
198
|
+
await mkdir(dirname(templateOutputPath), { recursive: true });
|
|
199
|
+
await writeFile(templateOutputPath, DEFAULT_TEMPLATE_HTML, "utf8");
|
|
225
200
|
console.log(`Wrote template to: ${templateOutputPath}`);
|
|
226
201
|
};
|
|
227
202
|
var runVersion = async () => {
|
|
@@ -229,11 +204,11 @@ var runVersion = async () => {
|
|
|
229
204
|
console.log(version);
|
|
230
205
|
};
|
|
231
206
|
var runConvert = async (inputArg, outputArg, templateArg) => {
|
|
232
|
-
|
|
207
|
+
marked.use({ extensions: [pageBreak] });
|
|
233
208
|
const inputPath = toAbsolutePath(inputArg);
|
|
234
209
|
let outputPath = toAbsolutePath(outputArg ?? inferOutputPath(inputPath));
|
|
235
210
|
let activeTemplateHtml = DEFAULT_TEMPLATE_HTML;
|
|
236
|
-
const inputStats = await
|
|
211
|
+
const inputStats = await stat(inputPath).catch(() => null);
|
|
237
212
|
if (!inputStats) {
|
|
238
213
|
throw new Error(`Input file does not exist: ${inputPath}`);
|
|
239
214
|
}
|
|
@@ -241,38 +216,38 @@ var runConvert = async (inputArg, outputArg, templateArg) => {
|
|
|
241
216
|
throw new Error(`Input path is not a file: ${inputPath}`);
|
|
242
217
|
}
|
|
243
218
|
if (outputArg) {
|
|
244
|
-
const outputStats = await
|
|
219
|
+
const outputStats = await stat(outputPath).catch(() => null);
|
|
245
220
|
if (outputStats?.isDirectory()) {
|
|
246
|
-
outputPath =
|
|
221
|
+
outputPath = join(outputPath, inferHtmlBasename(inputPath));
|
|
247
222
|
}
|
|
248
223
|
}
|
|
249
224
|
if (templateArg) {
|
|
250
225
|
const templatePath = toAbsolutePath(templateArg);
|
|
251
|
-
const templateStats = await
|
|
226
|
+
const templateStats = await stat(templatePath).catch(() => null);
|
|
252
227
|
if (!templateStats) {
|
|
253
228
|
throw new Error(`Template file does not exist: ${templatePath}`);
|
|
254
229
|
}
|
|
255
230
|
if (!templateStats.isFile()) {
|
|
256
231
|
throw new Error(`Template path is not a file: ${templatePath}`);
|
|
257
232
|
}
|
|
258
|
-
activeTemplateHtml = await
|
|
233
|
+
activeTemplateHtml = await readFile(templatePath, "utf8");
|
|
259
234
|
}
|
|
260
|
-
const markdown = await
|
|
261
|
-
const markdownHtml = await
|
|
235
|
+
const markdown = await readFile(inputPath, "utf8");
|
|
236
|
+
const markdownHtml = await marked.parse(markdown);
|
|
262
237
|
const documentHtml = renderDocument(activeTemplateHtml, markdownHtml);
|
|
263
238
|
const tailwindCss = await compileTailwindCss(documentHtml);
|
|
264
239
|
const html = inlineCssInHead(documentHtml, tailwindCss);
|
|
265
240
|
const pdfOutputPath = inferPdfPath(outputPath);
|
|
266
241
|
console.log("Rendering HTML...");
|
|
267
|
-
await
|
|
268
|
-
await
|
|
242
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
243
|
+
await writeFile(outputPath, html, "utf8");
|
|
269
244
|
console.log(`Wrote HTML to: ${outputPath}`);
|
|
270
245
|
console.log("Rendering PDF...");
|
|
271
|
-
await
|
|
246
|
+
await mkdir(dirname(pdfOutputPath), { recursive: true });
|
|
272
247
|
await renderPdf(html, pdfOutputPath);
|
|
273
248
|
console.log(`Wrote PDF to: ${pdfOutputPath}`);
|
|
274
249
|
};
|
|
275
|
-
var convertCommand =
|
|
250
|
+
var convertCommand = defineCommand({
|
|
276
251
|
meta: {
|
|
277
252
|
name: "convert",
|
|
278
253
|
description: "Convert Markdown files to HTML and PDF."
|
|
@@ -302,7 +277,7 @@ var convertCommand = (0, import_citty.defineCommand)({
|
|
|
302
277
|
await runConvert(inputArg, outputArg, templateArg);
|
|
303
278
|
}
|
|
304
279
|
});
|
|
305
|
-
var ejectTemplateCommand =
|
|
280
|
+
var ejectTemplateCommand = defineCommand({
|
|
306
281
|
meta: {
|
|
307
282
|
name: "eject-template",
|
|
308
283
|
description: "Write the default HTML template to disk."
|
|
@@ -319,7 +294,7 @@ var ejectTemplateCommand = (0, import_citty.defineCommand)({
|
|
|
319
294
|
await runEjectTemplate(outputArg);
|
|
320
295
|
}
|
|
321
296
|
});
|
|
322
|
-
var versionCommand =
|
|
297
|
+
var versionCommand = defineCommand({
|
|
323
298
|
meta: {
|
|
324
299
|
name: "version",
|
|
325
300
|
description: "Print current CLI version."
|
|
@@ -328,7 +303,7 @@ var versionCommand = (0, import_citty.defineCommand)({
|
|
|
328
303
|
await runVersion();
|
|
329
304
|
}
|
|
330
305
|
});
|
|
331
|
-
var main =
|
|
306
|
+
var main = defineCommand({
|
|
332
307
|
meta: {
|
|
333
308
|
name: "mduck",
|
|
334
309
|
description: "Convert Markdown files to HTML/PDF and manage templates."
|
|
@@ -339,4 +314,4 @@ var main = (0, import_citty.defineCommand)({
|
|
|
339
314
|
version: versionCommand
|
|
340
315
|
}
|
|
341
316
|
});
|
|
342
|
-
|
|
317
|
+
await runMain(main);
|