markdansi 0.3.1 → 0.3.2
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/cli.js +71 -44
- package/package.json +8 -8
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,31 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { render } from "./index.js";
|
|
6
|
+
function readOptionValue(argv, index, option, allowLeadingDashes = false) {
|
|
7
|
+
const value = argv[index + 1];
|
|
8
|
+
if (value === undefined || (!allowLeadingDashes && value.startsWith("--"))) {
|
|
9
|
+
throw new Error(`${option} requires a value`);
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function parseIntegerOption(option, value, minimum) {
|
|
14
|
+
const parsed = Number(value);
|
|
15
|
+
if (!/^\d+$/u.test(value) || !Number.isSafeInteger(parsed) || parsed < minimum) {
|
|
16
|
+
const range = minimum === 0 ? "a non-negative integer" : "a positive integer";
|
|
17
|
+
throw new Error(`${option} must be ${range}`);
|
|
18
|
+
}
|
|
19
|
+
return parsed;
|
|
20
|
+
}
|
|
21
|
+
function parseTheme(value) {
|
|
22
|
+
if (value === "default" || value === "dim" || value === "bright")
|
|
23
|
+
return value;
|
|
24
|
+
throw new Error("--theme must be default, dim, or bright");
|
|
25
|
+
}
|
|
26
|
+
function parseTableBorder(value) {
|
|
27
|
+
if (value === "unicode" || value === "ascii" || value === "none")
|
|
28
|
+
return value;
|
|
29
|
+
throw new Error("--table-border must be unicode, ascii, or none");
|
|
30
|
+
}
|
|
6
31
|
/**
|
|
7
32
|
* Ignore EPIPE when downstream (e.g., `head`) closes early.
|
|
8
33
|
*/
|
|
@@ -32,80 +57,85 @@ export function parseArgs(argv) {
|
|
|
32
57
|
args.color = false;
|
|
33
58
|
else if (a === "--no-links")
|
|
34
59
|
args.hyperlinks = false;
|
|
60
|
+
else if (a === "--code-wrap")
|
|
61
|
+
args.codeWrap = true;
|
|
35
62
|
else if (a === "--code-wrap=false")
|
|
36
63
|
args.codeWrap = false;
|
|
37
64
|
else if (a === "--code-wrap=true")
|
|
38
65
|
args.codeWrap = true;
|
|
66
|
+
else if (a === "--code-box")
|
|
67
|
+
args.codeBox = true;
|
|
39
68
|
else if (a === "--code-box=false")
|
|
40
69
|
args.codeBox = false;
|
|
41
70
|
else if (a === "--code-box=true")
|
|
42
71
|
args.codeBox = true;
|
|
72
|
+
else if (a === "--code-gutter")
|
|
73
|
+
args.codeGutter = true;
|
|
43
74
|
else if (a === "--code-gutter=true")
|
|
44
75
|
args.codeGutter = true;
|
|
45
76
|
else if (a === "--code-gutter=false")
|
|
46
77
|
args.codeGutter = false;
|
|
47
78
|
else if (a.startsWith("--table-border=")) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
79
|
+
args.tableBorder = parseTableBorder(a.slice("--table-border=".length));
|
|
80
|
+
}
|
|
81
|
+
else if (a === "--table-border") {
|
|
82
|
+
args.tableBorder = parseTableBorder(readOptionValue(argv, i, a));
|
|
83
|
+
i += 1;
|
|
51
84
|
}
|
|
52
85
|
else if (a === "--table-dense")
|
|
53
86
|
args.tableDense = true;
|
|
87
|
+
else if (a === "--table-truncate")
|
|
88
|
+
args.tableTruncate = true;
|
|
54
89
|
else if (a === "--table-truncate=false")
|
|
55
90
|
args.tableTruncate = false;
|
|
56
91
|
else if (a === "--table-truncate=true")
|
|
57
92
|
args.tableTruncate = true;
|
|
58
93
|
else if (a === "--table-padding") {
|
|
59
|
-
const next = argv
|
|
60
|
-
|
|
61
|
-
args.tablePadding = Number(next);
|
|
94
|
+
const next = readOptionValue(argv, i, a);
|
|
95
|
+
args.tablePadding = parseIntegerOption(a, next, 0);
|
|
62
96
|
i += 1;
|
|
63
97
|
}
|
|
64
98
|
else if (a === "--table-ellipsis") {
|
|
65
|
-
|
|
66
|
-
if (next)
|
|
67
|
-
args.tableEllipsis = next;
|
|
99
|
+
args.tableEllipsis = readOptionValue(argv, i, a, true);
|
|
68
100
|
i += 1;
|
|
69
101
|
}
|
|
70
102
|
else if (a === "--in") {
|
|
71
|
-
|
|
72
|
-
if (next)
|
|
73
|
-
args.in = next;
|
|
103
|
+
args.in = readOptionValue(argv, i, a, true);
|
|
74
104
|
i += 1;
|
|
75
105
|
}
|
|
76
106
|
else if (a === "--out") {
|
|
77
|
-
|
|
78
|
-
if (next)
|
|
79
|
-
args.out = next;
|
|
107
|
+
args.out = readOptionValue(argv, i, a, true);
|
|
80
108
|
i += 1;
|
|
81
109
|
}
|
|
82
110
|
else if (a === "--width") {
|
|
83
|
-
const next = argv
|
|
84
|
-
|
|
85
|
-
args.width = Number(next);
|
|
111
|
+
const next = readOptionValue(argv, i, a);
|
|
112
|
+
args.width = parseIntegerOption(a, next, 1);
|
|
86
113
|
i += 1;
|
|
87
114
|
}
|
|
88
115
|
else if (a.startsWith("--theme=")) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
116
|
+
args.theme = parseTheme(a.slice("--theme=".length));
|
|
117
|
+
}
|
|
118
|
+
else if (a === "--theme") {
|
|
119
|
+
args.theme = parseTheme(readOptionValue(argv, i, a));
|
|
120
|
+
i += 1;
|
|
92
121
|
}
|
|
93
122
|
else if (a === "--list-indent") {
|
|
94
|
-
const next = argv
|
|
95
|
-
|
|
96
|
-
args.listIndent = Number(next);
|
|
123
|
+
const next = readOptionValue(argv, i, a);
|
|
124
|
+
args.listIndent = parseIntegerOption(a, next, 0);
|
|
97
125
|
i += 1;
|
|
98
126
|
}
|
|
99
127
|
else if (a === "--quote-prefix") {
|
|
100
|
-
|
|
101
|
-
if (next)
|
|
102
|
-
args.quotePrefix = next;
|
|
128
|
+
args.quotePrefix = readOptionValue(argv, i, a, true);
|
|
103
129
|
i += 1;
|
|
104
130
|
}
|
|
105
131
|
else if (a === "--help" || a === "-h")
|
|
106
132
|
args.help = true;
|
|
107
|
-
else if (
|
|
133
|
+
else if (a.startsWith("-"))
|
|
134
|
+
throw new Error(`unknown option: ${a}`);
|
|
135
|
+
else if (!args.in)
|
|
108
136
|
args.in = a;
|
|
137
|
+
else
|
|
138
|
+
throw new Error(`unexpected positional argument: ${a}`);
|
|
109
139
|
}
|
|
110
140
|
return args;
|
|
111
141
|
}
|
|
@@ -114,8 +144,8 @@ export function parseArgs(argv) {
|
|
|
114
144
|
*/
|
|
115
145
|
function main() {
|
|
116
146
|
handleStdoutEpipe();
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
147
|
+
const { in: inputPath, out: outputPath, help, ...renderOptions } = parseArgs(process.argv);
|
|
148
|
+
if (help) {
|
|
119
149
|
process.stdout.write(`markdansi [FILE] [options]
|
|
120
150
|
|
|
121
151
|
markdansi file.md Render file
|
|
@@ -143,21 +173,12 @@ Options:
|
|
|
143
173
|
`);
|
|
144
174
|
process.exit(0);
|
|
145
175
|
}
|
|
146
|
-
const input =
|
|
147
|
-
? fs.readFileSync(path.resolve(
|
|
176
|
+
const input = inputPath && inputPath !== "-"
|
|
177
|
+
? fs.readFileSync(path.resolve(inputPath), "utf8")
|
|
148
178
|
: fs.readFileSync(0, "utf8");
|
|
149
|
-
const renderOptions = {
|
|
150
|
-
...(args.wrap !== undefined ? { wrap: args.wrap } : {}),
|
|
151
|
-
...(args.width !== undefined ? { width: args.width } : {}),
|
|
152
|
-
...(args.color !== undefined ? { color: args.color } : {}),
|
|
153
|
-
...(args.hyperlinks !== undefined ? { hyperlinks: args.hyperlinks } : {}),
|
|
154
|
-
...(args.theme !== undefined ? { theme: args.theme } : {}),
|
|
155
|
-
...(args.listIndent !== undefined ? { listIndent: args.listIndent } : {}),
|
|
156
|
-
...(args.quotePrefix !== undefined ? { quotePrefix: args.quotePrefix } : {}),
|
|
157
|
-
};
|
|
158
179
|
const output = render(input, renderOptions);
|
|
159
|
-
if (
|
|
160
|
-
fs.writeFileSync(path.resolve(
|
|
180
|
+
if (outputPath) {
|
|
181
|
+
fs.writeFileSync(path.resolve(outputPath), output, "utf8");
|
|
161
182
|
}
|
|
162
183
|
else {
|
|
163
184
|
process.stdout.write(output);
|
|
@@ -177,5 +198,11 @@ export function isDirectCliInvocation(metaUrl, argv1) {
|
|
|
177
198
|
}
|
|
178
199
|
// Only run the CLI when executed directly, not when imported for tests.
|
|
179
200
|
if (isDirectCliInvocation(import.meta.url, process.argv[1])) {
|
|
180
|
-
|
|
201
|
+
try {
|
|
202
|
+
main();
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
console.error(`markdansi: ${error instanceof Error ? error.message : String(error)}`);
|
|
206
|
+
process.exitCode = 1;
|
|
207
|
+
}
|
|
181
208
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdansi",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Tiny dependency-light markdown to ANSI converter.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ansi",
|
|
@@ -61,16 +61,16 @@
|
|
|
61
61
|
"slice-ansi": "^9.0.0",
|
|
62
62
|
"string-width": "^8.2.1",
|
|
63
63
|
"strip-ansi": "^7.2.0",
|
|
64
|
-
"supports-hyperlinks": "^4.
|
|
64
|
+
"supports-hyperlinks": "^4.5.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@types/node": "^
|
|
68
|
-
"@vitest/coverage-v8": "^4.1.
|
|
69
|
-
"oxfmt": "^0.
|
|
70
|
-
"oxlint": "^1.
|
|
71
|
-
"tsx": "^4.
|
|
67
|
+
"@types/node": "^26.0.1",
|
|
68
|
+
"@vitest/coverage-v8": "^4.1.9",
|
|
69
|
+
"oxfmt": "^0.57.0",
|
|
70
|
+
"oxlint": "^1.72.0",
|
|
71
|
+
"tsx": "^4.22.4",
|
|
72
72
|
"typescript": "^6.0.3",
|
|
73
|
-
"vitest": "^4.1.
|
|
73
|
+
"vitest": "^4.1.9"
|
|
74
74
|
},
|
|
75
75
|
"engines": {
|
|
76
76
|
"node": ">=22"
|