@helping-ai-workflow/md2doc 2.0.1 → 2.1.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 +3 -2
- package/bin/md2doc.js +26 -12
- package/lib/md2doc.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ md2doc --html --pdf foo.md # render both formats
|
|
|
49
49
|
md2doc *.md # batch: each file → temp + open
|
|
50
50
|
|
|
51
51
|
md2doc foo.md --out bar.html # write to a specific file (no auto-open)
|
|
52
|
+
md2doc foo.md --out report.pdf # --pdf inferred from the extension
|
|
52
53
|
md2doc foo.md --out ./build/ # write to ./build/foo.html (no auto-open)
|
|
53
54
|
md2doc *.md --out ./build/ # batch into ./build/
|
|
54
55
|
md2doc foo.md --out ./build/ --open # explicit open with --out
|
|
@@ -62,9 +63,9 @@ also pass `--open`.
|
|
|
62
63
|
|
|
63
64
|
| Flag | Meaning |
|
|
64
65
|
|---|---|
|
|
65
|
-
| `--html` | Render HTML (default
|
|
66
|
+
| `--html` | Render HTML (default when neither `--html`/`--pdf` nor a `.pdf` file `--out` is given; directory targets always default to HTML). |
|
|
66
67
|
| `--pdf` | Render PDF. Combine with `--html` to render both. |
|
|
67
|
-
| `--out <path>` | Output path. Ends with `/` or an existing directory → directory mode. Ends with `.html` / `.pdf` → file mode (single input only). Implies `--no-open` unless `--open` is also passed. |
|
|
68
|
+
| `--out <path>` | Output path. Ends with `/` or an existing directory → directory mode. Ends with `.html` / `.pdf` → file mode (single input only). Without `--html`/`--pdf`, the extension selects the format. Implies `--no-open` unless `--open` is also passed. |
|
|
68
69
|
| `--open` | Launch the platform viewer (`xdg-open` / `open` / `start`) after render. Default when `--out` is absent. |
|
|
69
70
|
| `--no-open` | Skip the viewer launch. |
|
|
70
71
|
| `--quiet` | Suppress per-file progress messages. |
|
package/bin/md2doc.js
CHANGED
|
@@ -19,13 +19,15 @@ function printHelp() {
|
|
|
19
19
|
' md2doc --pdf <input.md>... Render to PDF instead',
|
|
20
20
|
' md2doc --html --pdf <input.md> Render both formats',
|
|
21
21
|
' md2doc <input.md> --out <file.html> Write to a specific file (no auto-open)',
|
|
22
|
+
' md2doc <input.md> --out <file.pdf> Write a PDF (format inferred from extension)',
|
|
22
23
|
' md2doc <input.md>... --out <dir>/ Write each to <dir>/<stem>.html (no auto-open)',
|
|
23
24
|
'',
|
|
24
25
|
'Flags:',
|
|
25
|
-
' --html Render HTML (default
|
|
26
|
+
' --html Render HTML (default when neither --html/--pdf nor a .pdf file --out is given).',
|
|
26
27
|
' --pdf Render PDF.',
|
|
27
28
|
' --out <path> Output path. Ends with \'/\' or existing dir → directory mode.',
|
|
28
29
|
' Ends with .html/.pdf → file mode (single input only).',
|
|
30
|
+
' Without --html/--pdf, the .html/.pdf extension selects the format.',
|
|
29
31
|
' Implies --no-open unless --open is also passed.',
|
|
30
32
|
' --open Launch the platform viewer after render (default when --out is absent).',
|
|
31
33
|
' --no-open Skip the viewer launch.',
|
|
@@ -85,7 +87,9 @@ function parseArgs(argv) {
|
|
|
85
87
|
process.exit(2);
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
// Format defaults: neither flag → HTML only.
|
|
90
|
+
// Format defaults: neither flag → HTML only. formatsExplicit lets
|
|
91
|
+
// resolveOutputs infer the format from the --out extension instead.
|
|
92
|
+
const formatsExplicit = html || pdf;
|
|
89
93
|
const formats = [];
|
|
90
94
|
if (html || (!html && !pdf)) formats.push('html');
|
|
91
95
|
if (pdf) formats.push('pdf');
|
|
@@ -98,7 +102,7 @@ function parseArgs(argv) {
|
|
|
98
102
|
open = (out === null);
|
|
99
103
|
}
|
|
100
104
|
|
|
101
|
-
return { inputs, formats, out, open, quiet };
|
|
105
|
+
return { inputs, formats, formatsExplicit, out, open, quiet };
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
function shortHash(absPath) {
|
|
@@ -123,8 +127,11 @@ function classifyOut(outValue) {
|
|
|
123
127
|
return { kind: 'dir', ext: null };
|
|
124
128
|
}
|
|
125
129
|
} catch (_) { /* fall through */ }
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
// Require a stem character before the extension: a basename that is just
|
|
131
|
+
// '.pdf'/'.html' is extensionless to path.extname() in the renderer, so
|
|
132
|
+
// treat it as ambiguous here instead of failing late in the child.
|
|
133
|
+
if (/[^/\\]\.html$/i.test(outValue)) return { kind: 'file', ext: 'html' };
|
|
134
|
+
if (/[^/\\]\.pdf$/i.test(outValue)) return { kind: 'file', ext: 'pdf' };
|
|
128
135
|
return { kind: 'ambiguous', ext: null };
|
|
129
136
|
}
|
|
130
137
|
|
|
@@ -144,27 +151,34 @@ function resolveOutputs(args) {
|
|
|
144
151
|
if (cls.kind === 'ambiguous') {
|
|
145
152
|
process.stderr.write(
|
|
146
153
|
'error: --out \'' + args.out + '\' must end with \'/\' to mean a directory ' +
|
|
147
|
-
'or \'.html\'/\'.pdf\' to mean a file
|
|
154
|
+
'or \'.html\'/\'.pdf\' to mean a file ' +
|
|
155
|
+
'(the extension also selects the format when no --html/--pdf is given)\n'
|
|
148
156
|
);
|
|
149
157
|
process.exit(2);
|
|
150
158
|
}
|
|
151
159
|
|
|
160
|
+
// No --html/--pdf given: the --out extension selects the format. classifyOut
|
|
161
|
+
// is the single authority for dir/file/ext — never re-derive from args.out here
|
|
162
|
+
// (an existing directory named e.g. foo.pdf must stay in dir mode).
|
|
163
|
+
const formats = (!args.formatsExplicit && cls.kind === 'file') ? [cls.ext] : args.formats;
|
|
164
|
+
|
|
152
165
|
if (cls.kind === 'file') {
|
|
153
166
|
if (args.inputs.length > 1) {
|
|
154
167
|
process.stderr.write('error: --out file path is only valid with one input\n');
|
|
155
168
|
process.exit(2);
|
|
156
169
|
}
|
|
157
|
-
if (
|
|
158
|
-
process.stderr.write('error: --out file path is not valid when producing both formats\n');
|
|
170
|
+
if (formats.length > 1) {
|
|
171
|
+
process.stderr.write('error: --out file path is not valid when producing both formats; use --out <dir>/ to write both\n');
|
|
159
172
|
process.exit(2);
|
|
160
173
|
}
|
|
161
|
-
if (cls.ext !==
|
|
174
|
+
if (cls.ext !== formats[0]) {
|
|
162
175
|
process.stderr.write(
|
|
163
|
-
'error: --out \'' + args.out + '\' extension does not match
|
|
176
|
+
'error: --out \'' + args.out + '\' extension does not match the --html/--pdf flag; ' +
|
|
177
|
+
'drop the flag to infer the format from --out, or make them agree\n'
|
|
164
178
|
);
|
|
165
179
|
process.exit(2);
|
|
166
180
|
}
|
|
167
|
-
pairs.push({ input: args.inputs[0], format:
|
|
181
|
+
pairs.push({ input: args.inputs[0], format: formats[0], output: args.out });
|
|
168
182
|
return pairs;
|
|
169
183
|
}
|
|
170
184
|
|
|
@@ -172,7 +186,7 @@ function resolveOutputs(args) {
|
|
|
172
186
|
fs.mkdirSync(args.out, { recursive: true });
|
|
173
187
|
for (const input of args.inputs) {
|
|
174
188
|
const stem = path.basename(input).replace(/\.md$/i, '');
|
|
175
|
-
for (const format of
|
|
189
|
+
for (const format of formats) {
|
|
176
190
|
pairs.push({
|
|
177
191
|
input,
|
|
178
192
|
format,
|
package/lib/md2doc.js
CHANGED
|
@@ -1515,7 +1515,9 @@ if (ext === '.html') {
|
|
|
1515
1515
|
}
|
|
1516
1516
|
|
|
1517
1517
|
// Write temporary HTML, launch headless Chromium, export PDF
|
|
1518
|
-
|
|
1518
|
+
// Case-insensitive: an uppercase .PDF dst must not make tmp === dst, or the
|
|
1519
|
+
// unlinkSync below deletes the freshly written PDF.
|
|
1520
|
+
const tmp = dst.replace(/\.pdf$/i, '._tmp.html');
|
|
1519
1521
|
fs.writeFileSync(tmp, html, 'utf8');
|
|
1520
1522
|
|
|
1521
1523
|
const browser = await puppeteer.launch({
|