@cenk1cenk2/md-printer 2.5.7 → 2.6.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/dist/commands/index.js +142 -139
- package/dist/constants/index.js +1 -1
- package/dist/hooks/not-found.hook.js +5 -1
- package/dist/hooks/update-notifier.hook.js +5 -1
- package/oclif.manifest.json +1 -1
- package/package.json +13 -10
package/dist/commands/index.js
CHANGED
|
@@ -1,68 +1,65 @@
|
|
|
1
|
-
import { RequiredTemplateFiles, TEMPLATE_DIRECTORY, TemplateFiles } from "../constants/template.constants.js";
|
|
2
1
|
import { OUTPUT_FILE_ACCEPTED_TYPES } from "../constants/file.constants.js";
|
|
2
|
+
import { RequiredTemplateFiles, TEMPLATE_DIRECTORY, TemplateFiles } from "../constants/template.constants.js";
|
|
3
3
|
import "../constants/index.js";
|
|
4
4
|
import tailwind from "@tailwindcss/postcss";
|
|
5
5
|
import { watch } from "chokidar";
|
|
6
6
|
import graymatter from "gray-matter";
|
|
7
|
-
import {
|
|
7
|
+
import { defaultConfig } from "md-to-pdf/dist/lib/config.js";
|
|
8
|
+
import { convertMdToPdf } from "md-to-pdf/dist/lib/md-to-pdf.js";
|
|
9
|
+
import { serveDirectory } from "md-to-pdf/dist/lib/serve-dir.js";
|
|
8
10
|
import Nunjucks from "nunjucks";
|
|
9
11
|
import { basename, dirname, extname, join } from "path";
|
|
10
12
|
import postcss from "postcss";
|
|
13
|
+
import puppeteer from "puppeteer";
|
|
11
14
|
import showdown from "showdown";
|
|
12
|
-
import { Args, Command, ConfigService, FileSystemService, Flags, JsonParser, ParserService, YamlParser } from "@cenk1cenk2/oclif-common";
|
|
15
|
+
import { Args, Command, ConfigService, FileSystemService, Flags, JsonParser, MergeStrategy, ParserService, YamlParser, merge } from "@cenk1cenk2/oclif-common";
|
|
13
16
|
|
|
14
17
|
//#region src/commands/index.ts
|
|
15
18
|
var MDPrinter = class extends Command {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
output: Args.string({
|
|
61
|
-
description: "Output file that will be generated. Overwrites the one define in front-matter.",
|
|
62
|
-
required: false
|
|
63
|
-
})
|
|
64
|
-
};
|
|
65
|
-
}
|
|
19
|
+
static description = "Generates a PDF from the given markdown file with the selected HTML template.";
|
|
20
|
+
static flags = {
|
|
21
|
+
template: Flags.string({
|
|
22
|
+
char: "t",
|
|
23
|
+
default: "default",
|
|
24
|
+
description: "HTML template for the generated PDF file."
|
|
25
|
+
}),
|
|
26
|
+
title: Flags.string({
|
|
27
|
+
char: "T",
|
|
28
|
+
description: "Overwrite document title."
|
|
29
|
+
}),
|
|
30
|
+
browser: Flags.string({
|
|
31
|
+
char: "b",
|
|
32
|
+
description: "Browser path that is going to be used for the PDF generation.",
|
|
33
|
+
default: "/usr/bin/brave"
|
|
34
|
+
}),
|
|
35
|
+
watch: Flags.boolean({
|
|
36
|
+
char: "w",
|
|
37
|
+
description: "Watch the changes on the given file."
|
|
38
|
+
}),
|
|
39
|
+
dev: Flags.boolean({
|
|
40
|
+
char: "d",
|
|
41
|
+
description: "Run with Chrome browser instead of publishing the file."
|
|
42
|
+
})
|
|
43
|
+
};
|
|
44
|
+
static args = {
|
|
45
|
+
file: Args.string({
|
|
46
|
+
description: "File to be processed.",
|
|
47
|
+
required: true
|
|
48
|
+
}),
|
|
49
|
+
output: Args.string({
|
|
50
|
+
description: "Output file that will be generated. Overwrites the one define in front-matter.",
|
|
51
|
+
required: false
|
|
52
|
+
})
|
|
53
|
+
};
|
|
54
|
+
nunjucks = Nunjucks.configure({
|
|
55
|
+
autoescape: false,
|
|
56
|
+
throwOnUndefined: true,
|
|
57
|
+
trimBlocks: true,
|
|
58
|
+
lstripBlocks: false
|
|
59
|
+
});
|
|
60
|
+
cs;
|
|
61
|
+
fs;
|
|
62
|
+
browser;
|
|
66
63
|
async shouldRunBefore() {
|
|
67
64
|
this.cs = this.app.get(ConfigService);
|
|
68
65
|
this.fs = this.app.get(FileSystemService);
|
|
@@ -73,78 +70,69 @@ var MDPrinter = class extends Command {
|
|
|
73
70
|
this.tasks.options = { silentRendererCondition: true };
|
|
74
71
|
}
|
|
75
72
|
async run() {
|
|
76
|
-
this.tasks.add([
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
case ".yml":
|
|
91
|
-
ctx.content = await this.fs.read(file);
|
|
92
|
-
ctx.metadata = await this.app.get(ParserService).parse(ctx.file, ctx.content);
|
|
93
|
-
break;
|
|
94
|
-
default: throw new Error("File type is not accepted.");
|
|
73
|
+
this.tasks.add([{ task: async (ctx) => {
|
|
74
|
+
const file = join(process.cwd(), this.args.file);
|
|
75
|
+
if (!this.fs.exists(file)) throw new Error(`File does not exists: ${file}`);
|
|
76
|
+
this.logger.info("Loading file: %s", file);
|
|
77
|
+
ctx.file = file;
|
|
78
|
+
switch (extname(ctx.file)) {
|
|
79
|
+
case ".md": {
|
|
80
|
+
const data = graymatter.read(ctx.file);
|
|
81
|
+
ctx.content = await this.fs.read(file);
|
|
82
|
+
ctx.content = data.content;
|
|
83
|
+
ctx.metadata = data.data;
|
|
84
|
+
break;
|
|
95
85
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
ctx.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
} }
|
|
147
|
-
]);
|
|
86
|
+
case ".yml":
|
|
87
|
+
ctx.content = await this.fs.read(file);
|
|
88
|
+
ctx.metadata = await this.app.get(ParserService).parse(ctx.file, ctx.content);
|
|
89
|
+
break;
|
|
90
|
+
default: throw new Error("File type is not accepted.");
|
|
91
|
+
}
|
|
92
|
+
} }, { task: async (ctx) => {
|
|
93
|
+
const template = ctx.metadata?.template ?? this.flags.template;
|
|
94
|
+
ctx.templates = (/* @__PURE__ */ new RegExp(/\.\.?\//)).test(template) ? join(process.cwd(), template) : join(this.config.root, TEMPLATE_DIRECTORY, template);
|
|
95
|
+
this.logger.info("Loading template: %s from %s", template, ctx.templates);
|
|
96
|
+
await Promise.all(RequiredTemplateFiles.map(async (file) => {
|
|
97
|
+
const current = join(ctx.templates, file);
|
|
98
|
+
if (!this.fs.exists(current)) throw new Error(`Template does not exists: ${current}`);
|
|
99
|
+
}));
|
|
100
|
+
const paths = {
|
|
101
|
+
[TemplateFiles.SETTINGS]: join(ctx.templates, TemplateFiles.SETTINGS),
|
|
102
|
+
[TemplateFiles.CSS]: join(ctx.templates, TemplateFiles.CSS),
|
|
103
|
+
[TemplateFiles.TAILWIND_CSS]: join(ctx.templates, TemplateFiles.TAILWIND_CSS),
|
|
104
|
+
[TemplateFiles.HEADER]: join(ctx.templates, TemplateFiles.HEADER),
|
|
105
|
+
[TemplateFiles.FOOTER]: join(ctx.templates, TemplateFiles.FOOTER),
|
|
106
|
+
[TemplateFiles.TEMPLATE]: join(ctx.templates, TemplateFiles.TEMPLATE)
|
|
107
|
+
};
|
|
108
|
+
ctx.options = await this.cs.extend([paths[TemplateFiles.SETTINGS], {
|
|
109
|
+
dest: this.args?.output ?? ctx.metadata?.dest ?? `${basename(this.args.file, extname(this.args.file))}.pdf`,
|
|
110
|
+
document_title: ctx.metadata?.document_title ?? this.flags.title ?? this.args.file,
|
|
111
|
+
launch_options: { executablePath: this.flags.browser }
|
|
112
|
+
}]);
|
|
113
|
+
this.logger.debug("Options: %o", ctx.options);
|
|
114
|
+
if (this.fs.exists(paths[TemplateFiles.HEADER])) {
|
|
115
|
+
this.logger.debug("Header exists for template.");
|
|
116
|
+
ctx.options.pdf_options.headerTemplate = await this.fs.read(paths[TemplateFiles.HEADER]);
|
|
117
|
+
}
|
|
118
|
+
if (this.fs.exists(paths[TemplateFiles.FOOTER])) {
|
|
119
|
+
this.logger.debug("Footer exists for template.");
|
|
120
|
+
ctx.options.pdf_options.footerTemplate = await this.fs.read(paths[TemplateFiles.FOOTER]);
|
|
121
|
+
}
|
|
122
|
+
if (this.fs.exists(paths[TemplateFiles.TEMPLATE])) {
|
|
123
|
+
this.logger.debug("Design template exists for template.");
|
|
124
|
+
ctx.template = await this.fs.read(paths[TemplateFiles.TEMPLATE]);
|
|
125
|
+
this.logger.debug("Metadata: %o", ctx.metadata);
|
|
126
|
+
}
|
|
127
|
+
if (this.fs.exists(paths[TemplateFiles.CSS])) {
|
|
128
|
+
this.logger.debug("CSS exists for template.");
|
|
129
|
+
ctx.options.css = await this.fs.read(paths[TemplateFiles.CSS]);
|
|
130
|
+
}
|
|
131
|
+
if (this.fs.exists(paths[TemplateFiles.TAILWIND_CSS])) {
|
|
132
|
+
this.logger.debug("Tailwind CSS exists for template: %s -> %s", paths[TemplateFiles.TAILWIND_CSS]);
|
|
133
|
+
ctx.options.css = await postcss([tailwind({ base: ctx.templates })]).process(await this.fs.read(paths[TemplateFiles.TAILWIND_CSS]), { from: paths[TemplateFiles.TAILWIND_CSS] }).then((result) => result.css);
|
|
134
|
+
}
|
|
135
|
+
} }]);
|
|
148
136
|
}
|
|
149
137
|
async shouldRunAfter(ctx) {
|
|
150
138
|
if (this.flags.watch) {
|
|
@@ -155,33 +143,48 @@ var MDPrinter = class extends Command {
|
|
|
155
143
|
join(ctx.templates, "**/*")
|
|
156
144
|
]).on("change", async () => {
|
|
157
145
|
await this.run();
|
|
158
|
-
await this.runTasks();
|
|
146
|
+
const ctx$1 = await this.runTasks();
|
|
159
147
|
this.logger.info("Waiting for the next change.");
|
|
160
|
-
return this.runMd2Pdf(ctx)
|
|
148
|
+
return this.runMd2Pdf(ctx$1).catch((err) => {
|
|
149
|
+
this.logger.error(err);
|
|
150
|
+
throw err;
|
|
151
|
+
});
|
|
161
152
|
});
|
|
153
|
+
return this.runMd2Pdf(ctx);
|
|
162
154
|
}
|
|
163
|
-
|
|
155
|
+
await this.runMd2Pdf(ctx);
|
|
156
|
+
if (this.browser) await this.browser.close();
|
|
164
157
|
}
|
|
165
158
|
async runMd2Pdf(ctx) {
|
|
166
|
-
|
|
159
|
+
const options = merge(MergeStrategy.EXTEND, { basedir: process.cwd() }, defaultConfig, ctx.options, { devtools: this.flags.dev });
|
|
160
|
+
this.browser ??= await puppeteer.launch({
|
|
161
|
+
devtools: options.devtools,
|
|
162
|
+
...options.launch_options
|
|
163
|
+
});
|
|
164
|
+
const server = await serveDirectory(ctx.options);
|
|
165
|
+
options.port = server.address().port;
|
|
166
|
+
let output;
|
|
167
167
|
if (ctx.template) {
|
|
168
168
|
this.logger.info("Rendering as template.");
|
|
169
|
-
|
|
169
|
+
output = await convertMdToPdf({ content: this.nunjucks.renderString(ctx.template, {
|
|
170
170
|
...ctx.metadata ?? {},
|
|
171
171
|
content: ctx.content
|
|
172
|
-
}) },
|
|
172
|
+
}) }, options, { browser: this.browser });
|
|
173
173
|
} else {
|
|
174
174
|
this.logger.info("Rendering as plain file.");
|
|
175
|
-
|
|
175
|
+
output = await convertMdToPdf({ content: ctx.content }, options, { browser: this.browser });
|
|
176
176
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
177
|
+
await new Promise((resolve, reject) => server.close((err) => {
|
|
178
|
+
if (err) return reject(err);
|
|
179
|
+
resolve(null);
|
|
180
|
+
}));
|
|
181
|
+
if (output) {
|
|
182
|
+
if (!output.filename) throw new Error("Output should either be defined with the variable or front-matter.");
|
|
183
|
+
else if (!OUTPUT_FILE_ACCEPTED_TYPES.includes(extname(output.filename))) throw new Error(`Output file should be ending with the extension: ${OUTPUT_FILE_ACCEPTED_TYPES.join(", ")} -> current: ${extname(output.filename)}`);
|
|
184
|
+
this.logger.info("Output file will be: %s", output.filename);
|
|
185
|
+
await this.fs.mkdir(dirname(output.filename));
|
|
186
|
+
this.logger.info("Writing file to output: %s", output.filename);
|
|
187
|
+
await this.fs.write(output.filename, output.content);
|
|
185
188
|
}
|
|
186
189
|
}
|
|
187
190
|
};
|
package/dist/constants/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RequiredTemplateFiles, TEMPLATE_DIRECTORY, TemplateFiles } from "./template.constants.js";
|
|
2
1
|
import { OUTPUT_FILE_ACCEPTED_TYPES } from "./file.constants.js";
|
|
2
|
+
import { RequiredTemplateFiles, TEMPLATE_DIRECTORY, TemplateFiles } from "./template.constants.js";
|
|
3
3
|
|
|
4
4
|
export { OUTPUT_FILE_ACCEPTED_TYPES, RequiredTemplateFiles, TEMPLATE_DIRECTORY, TemplateFiles };
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { updateNotifierHook } from "@cenk1cenk2/oclif-common";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
//#region src/hooks/update-notifier.hook.ts
|
|
4
|
+
var update_notifier_hook_default = updateNotifierHook;
|
|
5
|
+
|
|
6
|
+
//#endregion
|
|
7
|
+
export { update_notifier_hook_default as default };
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cenk1cenk2/md-printer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "A markdown printer.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"dev": "./bin/dev.js",
|
|
18
18
|
"start": "./bin/run.js",
|
|
19
|
-
"build": "tsdown
|
|
20
|
-
"dev:start": "tsdown --watch
|
|
19
|
+
"build": "tsdown",
|
|
20
|
+
"dev:start": "tsdown --watch",
|
|
21
21
|
"clean": "rimraf oclif.manifset.json",
|
|
22
22
|
"format": "prettier --write src/ --log-level warn && eslint --fix",
|
|
23
23
|
"lint": "eslint",
|
|
@@ -63,27 +63,30 @@
|
|
|
63
63
|
"topicSeparator": " "
|
|
64
64
|
},
|
|
65
65
|
"engines": {
|
|
66
|
-
"node": ">=
|
|
66
|
+
"node": ">=20.0.0"
|
|
67
67
|
},
|
|
68
68
|
"keywords": [
|
|
69
69
|
"oclif",
|
|
70
70
|
"cenk1cenk2"
|
|
71
71
|
],
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@cenk1cenk2/oclif-common": "^6.4.
|
|
74
|
-
"@listr2/manager": "^3.0.
|
|
73
|
+
"@cenk1cenk2/oclif-common": "^6.4.10",
|
|
74
|
+
"@listr2/manager": "^3.0.2",
|
|
75
75
|
"@oclif/core": "^4.5.2",
|
|
76
76
|
"@oclif/plugin-help": "^6.2.32",
|
|
77
77
|
"@tailwindcss/forms": "^0.5.10",
|
|
78
78
|
"@tailwindcss/postcss": "^4.1.12",
|
|
79
79
|
"@tailwindcss/typography": "^0.5.16",
|
|
80
|
+
"@tsconfig/node20": "^20.1.6",
|
|
80
81
|
"chokidar": "^4.0.3",
|
|
81
82
|
"fs-extra": "^11.3.1",
|
|
83
|
+
"get-port": "^7.1.0",
|
|
82
84
|
"gray-matter": "^4.0.3",
|
|
83
|
-
"listr2": "^9.0.
|
|
85
|
+
"listr2": "^9.0.2",
|
|
84
86
|
"md-to-pdf": "^5.2.4",
|
|
85
87
|
"nunjucks": "^3.2.4",
|
|
86
88
|
"postcss": "^8.5.6",
|
|
89
|
+
"puppeteer": "^24.17.0",
|
|
87
90
|
"showdown": "^2.1.0",
|
|
88
91
|
"source-map-support": "^0.5.21",
|
|
89
92
|
"tailwindcss": "^4.1.12"
|
|
@@ -100,13 +103,13 @@
|
|
|
100
103
|
"execa": "^9.6.0",
|
|
101
104
|
"globby": "^14.1.0",
|
|
102
105
|
"lint-staged": "^16.1.5",
|
|
103
|
-
"oclif": "^4.22.
|
|
106
|
+
"oclif": "^4.22.14",
|
|
104
107
|
"prettier": "^3.6.2",
|
|
105
108
|
"simple-git-hooks": "^2.13.1",
|
|
106
109
|
"theme-colors": "^0.1.0",
|
|
107
110
|
"ts-node": "^10.9.2",
|
|
108
111
|
"tsconfig-paths": "^4.2.0",
|
|
109
|
-
"tsdown": "^0.
|
|
112
|
+
"tsdown": "^0.14.2",
|
|
110
113
|
"typescript": "^5.9.2"
|
|
111
114
|
},
|
|
112
115
|
"config": {
|
|
@@ -114,5 +117,5 @@
|
|
|
114
117
|
"path": "./node_modules/@cenk1cenk2/cz-cc"
|
|
115
118
|
}
|
|
116
119
|
},
|
|
117
|
-
"packageManager": "pnpm@
|
|
120
|
+
"packageManager": "pnpm@10.15.0"
|
|
118
121
|
}
|