@chromamark/cli 0.2.0 → 0.3.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/LICENSE.md +5 -11
- package/README.md +20 -4
- package/package.json +11 -6
- package/src/cli.js +80 -13
- package/src/index.d.ts +28 -0
- package/src/index.js +6 -1
package/LICENSE.md
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
# MIT License
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Copyright (c) 2026 CJ Fravel
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
8
|
|
|
9
|
-
THE SOFTWARE IS PROVIDED
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Third-party components
|
|
14
|
-
|
|
15
|
-
The published browser bundles in `packages/renderer/dist/` and the bundled VS Code extension embed [markdown-it](https://github.com/markdown-it/markdown-it), which is licensed under the [MIT License](https://github.com/markdown-it/markdown-it/blob/master/LICENSE).
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Compile [ChromaMark](https://github.com/cjfravel-dev/ChromaMark) (`.cm`) files
|
|
4
4
|
into **self-contained HTML** — the theme is inlined, so there's no CDN or build
|
|
5
|
-
step to deploy —
|
|
6
|
-
in CI.
|
|
5
|
+
step to deploy — transpile them to **GitHub-native GFM**, render them straight
|
|
6
|
+
to a **color terminal**, or **lint** them in CI.
|
|
7
7
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
@@ -27,6 +27,10 @@ chromamark render report.cm # render to the terminal (ANSI)
|
|
|
27
27
|
cat report.cm | chromamark render # render piped stdin
|
|
28
28
|
chromamark render report.cm --no-color # plain, icon-annotated text
|
|
29
29
|
|
|
30
|
+
chromamark github report.cm # GitHub-native GFM on stdout
|
|
31
|
+
chromamark github report.cm -o report.md # write GitHub-native GFM
|
|
32
|
+
cat report.cm | chromamark github # render piped stdin
|
|
33
|
+
|
|
30
34
|
chromamark lint report.cm # check for common mistakes (CI)
|
|
31
35
|
chromamark lint report.cm --disable CM001 # suppress a rule
|
|
32
36
|
```
|
|
@@ -35,11 +39,18 @@ Options: `-o/--output`, `--stdout`, `--title <text>`, `--watch`,
|
|
|
35
39
|
`--color <auto|always|never>`, `--no-color`, `--disable <rules>`, `-h/--help`,
|
|
36
40
|
`-v/--version`.
|
|
37
41
|
|
|
42
|
+
Commands accept one input source. Extra positional arguments, including a second
|
|
43
|
+
`-` stdin marker, are rejected instead of being silently ignored.
|
|
44
|
+
|
|
38
45
|
The `render` command turns tones into terminal colors, pills into bracketed
|
|
39
46
|
icon chips (`[✓ PASS]`), blocks into a colored left bar, and meters into a
|
|
40
47
|
unicode bar. Color is automatic on a TTY and can be forced with `--color`; it
|
|
41
48
|
also honors the [`NO_COLOR`](https://no-color.org) convention.
|
|
42
49
|
|
|
50
|
+
The `github` command maps callouts to GitHub Alerts, details and tables to native
|
|
51
|
+
GitHub structures, and pills to tone-aware `<kbd>` badges. See the complete
|
|
52
|
+
[mapping contract](../../docs/github-export.md).
|
|
53
|
+
|
|
43
54
|
The `lint` command flags mistakes that otherwise degrade silently — a construct
|
|
44
55
|
wrapped in backticks (`CM001`), an unknown tone (`CM002`), an unknown block kind
|
|
45
56
|
(`CM003`), a bad meter value (`CM004`), or an unclosed container (`CM005`) — and
|
|
@@ -48,15 +59,20 @@ exits non-zero when any are found. Suppress rules with `--disable CM001,CM003`.
|
|
|
48
59
|
## Programmatic
|
|
49
60
|
|
|
50
61
|
```js
|
|
51
|
-
import { compile, render, renderAnsi, lint } from '@chromamark/cli';
|
|
62
|
+
import { compile, render, renderAnsi, renderGitHub, lint } from '@chromamark/cli';
|
|
52
63
|
|
|
53
64
|
const page = compile('::: success\nAll good [!pass]\n:::', { title: 'Report' });
|
|
54
65
|
// → complete <!DOCTYPE html> document with the theme inlined
|
|
55
66
|
const fragment = render('[!pass]'); // just the HTML fragment
|
|
56
67
|
const ansi = renderAnsi('[!pass]', { color: 'always' }); // terminal-styled text
|
|
68
|
+
const github = renderGitHub('[!pass]'); // ✅ <kbd>PASS</kbd>
|
|
57
69
|
const problems = lint('Use `[!pass]` here'); // [{ line, column, rule, ... }]
|
|
58
70
|
```
|
|
59
71
|
|
|
72
|
+
TypeScript declarations ship with the package.
|
|
73
|
+
|
|
60
74
|
## License
|
|
61
75
|
|
|
62
|
-
|
|
76
|
+
This software package is licensed under the MIT License; see LICENSE.md. The
|
|
77
|
+
[ChromaMark specification](https://github.com/cjfravel-dev/ChromaMark/blob/main/LICENSE-SPEC.md)
|
|
78
|
+
is licensed separately under CC BY-SA 4.0.
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chromamark/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "ChromaMark command-line tool — compile .cm to
|
|
5
|
-
"license": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "ChromaMark command-line tool — compile .cm to HTML or GitHub GFM, render to a color terminal, or lint.",
|
|
5
|
+
"license": "MIT",
|
|
6
6
|
"author": "cjfravel-dev",
|
|
7
7
|
"homepage": "https://github.com/cjfravel-dev/ChromaMark#readme",
|
|
8
8
|
"repository": {
|
|
@@ -24,8 +24,12 @@
|
|
|
24
24
|
"chromamark": "./bin/chromamark.js"
|
|
25
25
|
},
|
|
26
26
|
"main": "./src/index.js",
|
|
27
|
+
"types": "./src/index.d.ts",
|
|
27
28
|
"exports": {
|
|
28
|
-
".":
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./src/index.d.ts",
|
|
31
|
+
"default": "./src/index.js"
|
|
32
|
+
}
|
|
29
33
|
},
|
|
30
34
|
"files": [
|
|
31
35
|
"bin/",
|
|
@@ -39,9 +43,10 @@
|
|
|
39
43
|
"markdown",
|
|
40
44
|
"cli",
|
|
41
45
|
"static-site",
|
|
42
|
-
"html"
|
|
46
|
+
"html",
|
|
47
|
+
"github"
|
|
43
48
|
],
|
|
44
49
|
"dependencies": {
|
|
45
|
-
"@chromamark/renderer": "^0.
|
|
50
|
+
"@chromamark/renderer": "^0.4.0"
|
|
46
51
|
}
|
|
47
52
|
}
|
package/src/cli.js
CHANGED
|
@@ -8,21 +8,25 @@ import {
|
|
|
8
8
|
} from 'node:fs';
|
|
9
9
|
import { join, basename, extname, dirname, relative } from 'node:path';
|
|
10
10
|
import { fileURLToPath } from 'node:url';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
compile, renderAnsi, renderGitHub, lint,
|
|
13
|
+
} from './index.js';
|
|
12
14
|
|
|
13
|
-
const HELP = `chromamark — compile ChromaMark (.cm) to HTML,
|
|
15
|
+
const HELP = `chromamark — compile ChromaMark (.cm) to HTML, GitHub GFM, ANSI, or lint it
|
|
14
16
|
|
|
15
17
|
Usage:
|
|
16
18
|
chromamark [build] <input.cm> [-o <output.html>] compile one file to HTML
|
|
17
19
|
chromamark [build] <dir> -o <outdir> compile every .cm in a tree
|
|
18
20
|
chromamark render <input.cm> render to ANSI on stdout
|
|
21
|
+
chromamark github <input.cm> [-o <output.md>] render to GitHub-native GFM
|
|
19
22
|
chromamark lint <input.cm> check for common mistakes
|
|
20
23
|
cat file.cm | chromamark render render stdin to ANSI
|
|
24
|
+
cat file.cm | chromamark github render stdin to GitHub GFM
|
|
21
25
|
chromamark <input.cm> --stdout write HTML to stdout
|
|
22
26
|
cat file.cm | chromamark - read HTML from stdin
|
|
23
27
|
|
|
24
28
|
Options:
|
|
25
|
-
-o, --output <path> output file or directory (build)
|
|
29
|
+
-o, --output <path> output file or directory (build/github)
|
|
26
30
|
--stdout write HTML to stdout instead of a file
|
|
27
31
|
--title <text> page title (default: derived from the file name)
|
|
28
32
|
--color <when> colorize render output: auto (default), always, never
|
|
@@ -33,7 +37,7 @@ Options:
|
|
|
33
37
|
-v, --version print the version
|
|
34
38
|
`;
|
|
35
39
|
|
|
36
|
-
const COMMANDS = new Set(['build', 'render', 'lint']);
|
|
40
|
+
const COMMANDS = new Set(['build', 'render', 'github', 'lint']);
|
|
37
41
|
|
|
38
42
|
/**
|
|
39
43
|
* Read all of stdin synchronously. Unlike readFileSync(0), this tolerates a
|
|
@@ -66,7 +70,8 @@ function version() {
|
|
|
66
70
|
|
|
67
71
|
function parseArgs(argv) {
|
|
68
72
|
const opts = {
|
|
69
|
-
command: 'build', input: null, output: null, stdout: false, title: null, watch: false,
|
|
73
|
+
command: 'build', input: null, output: null, stdout: false, title: null, watch: false,
|
|
74
|
+
color: 'auto', colorSpecified: false, disable: [],
|
|
70
75
|
};
|
|
71
76
|
let rest = argv;
|
|
72
77
|
if (argv.length && COMMANDS.has(argv[0])) {
|
|
@@ -87,18 +92,24 @@ function parseArgs(argv) {
|
|
|
87
92
|
else if (a === '-v' || a === '--version') opts.version = true;
|
|
88
93
|
else if (a === '--stdout') opts.stdout = true;
|
|
89
94
|
else if (a === '--watch') opts.watch = true;
|
|
90
|
-
else if (a === '--no-color')
|
|
95
|
+
else if (a === '--no-color') {
|
|
96
|
+
opts.color = 'never';
|
|
97
|
+
opts.colorSpecified = true;
|
|
98
|
+
}
|
|
91
99
|
else if (a === '--color') {
|
|
92
100
|
const v = takeValue(a);
|
|
93
101
|
if (!['auto', 'always', 'never'].includes(v)) throw new Error('--color must be auto, always, or never');
|
|
94
102
|
opts.color = v;
|
|
103
|
+
opts.colorSpecified = true;
|
|
95
104
|
} else if (a === '--disable') {
|
|
96
105
|
opts.disable = opts.disable.concat(takeValue(a).split(',').map((s) => s.trim()).filter(Boolean));
|
|
97
106
|
} else if (a === '-o' || a === '--output') opts.output = takeValue(a);
|
|
98
107
|
else if (a === '--title') opts.title = takeValue(a);
|
|
99
|
-
else if (a === '-') opts.input = '-';
|
|
108
|
+
else if (a === '-' && opts.input == null) opts.input = '-';
|
|
109
|
+
else if (a === '-') throw new Error('unexpected argument: -');
|
|
100
110
|
else if (a.startsWith('-')) throw new Error(`unknown option: ${a}`);
|
|
101
111
|
else if (opts.input == null) opts.input = a;
|
|
112
|
+
else throw new Error(`unexpected argument: ${a}`);
|
|
102
113
|
}
|
|
103
114
|
return opts;
|
|
104
115
|
}
|
|
@@ -136,6 +147,44 @@ function runRender(opts) {
|
|
|
136
147
|
return 0;
|
|
137
148
|
}
|
|
138
149
|
|
|
150
|
+
/** Render ChromaMark to GitHub-native GFM, from a file, `-`, or piped stdin. */
|
|
151
|
+
function runGitHub(opts) {
|
|
152
|
+
const unsupported = [];
|
|
153
|
+
if (opts.watch) unsupported.push('--watch');
|
|
154
|
+
if (opts.title !== null) unsupported.push('--title');
|
|
155
|
+
if (opts.colorSpecified) unsupported.push('--color');
|
|
156
|
+
if (opts.disable.length) unsupported.push('--disable');
|
|
157
|
+
if (unsupported.length) {
|
|
158
|
+
process.stderr.write(`error: ${unsupported.join(', ')} not supported by the github command\n`);
|
|
159
|
+
return 1;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let input;
|
|
163
|
+
try {
|
|
164
|
+
input = readInput(opts);
|
|
165
|
+
} catch (err) {
|
|
166
|
+
process.stderr.write(`error: ${err.message}\n`);
|
|
167
|
+
return 1;
|
|
168
|
+
}
|
|
169
|
+
if (!input || input.empty) {
|
|
170
|
+
process.stderr.write(`error: github needs an input file or piped stdin\n\n${HELP}`);
|
|
171
|
+
return 1;
|
|
172
|
+
}
|
|
173
|
+
const output = renderGitHub(input.src);
|
|
174
|
+
try {
|
|
175
|
+
if (opts.output && !opts.stdout) {
|
|
176
|
+
mkdirSync(dirname(opts.output), { recursive: true });
|
|
177
|
+
writeFileSync(opts.output, output);
|
|
178
|
+
} else {
|
|
179
|
+
process.stdout.write(output);
|
|
180
|
+
}
|
|
181
|
+
} catch (err) {
|
|
182
|
+
process.stderr.write(`error: ${err.message}\n`);
|
|
183
|
+
return 1;
|
|
184
|
+
}
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
|
|
139
188
|
/** Lint ChromaMark and print diagnostics; exit non-zero when any are found. */
|
|
140
189
|
function runLint(opts) {
|
|
141
190
|
let input;
|
|
@@ -211,6 +260,9 @@ export function run(argv = process.argv.slice(2)) {
|
|
|
211
260
|
if (opts.command === 'render') {
|
|
212
261
|
return runRender(opts);
|
|
213
262
|
}
|
|
263
|
+
if (opts.command === 'github') {
|
|
264
|
+
return runGitHub(opts);
|
|
265
|
+
}
|
|
214
266
|
if (opts.command === 'lint') {
|
|
215
267
|
return runLint(opts);
|
|
216
268
|
}
|
|
@@ -234,23 +286,38 @@ export function run(argv = process.argv.slice(2)) {
|
|
|
234
286
|
|
|
235
287
|
try {
|
|
236
288
|
info = statSync(opts.input);
|
|
237
|
-
rebuild();
|
|
238
289
|
} catch (err) {
|
|
239
290
|
process.stderr.write(`error: ${err.message}\n`);
|
|
240
291
|
return 1;
|
|
241
292
|
}
|
|
242
293
|
|
|
243
294
|
if (opts.watch && !opts.stdout) {
|
|
244
|
-
|
|
245
|
-
|
|
295
|
+
const onChange = (_eventType, filename) => {
|
|
296
|
+
if (info.isDirectory() && filename && extname(String(filename)) !== '.cm') return;
|
|
246
297
|
try { rebuild(); } catch (err) { process.stderr.write(`error: ${err.message}\n`); }
|
|
247
298
|
};
|
|
299
|
+
let watcher;
|
|
248
300
|
try {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
301
|
+
try {
|
|
302
|
+
watcher = watch(opts.input, { recursive: info.isDirectory() }, onChange);
|
|
303
|
+
} catch {
|
|
304
|
+
watcher = watch(opts.input, onChange); // non-recursive fallback (older Node / platforms)
|
|
305
|
+
}
|
|
306
|
+
process.stderr.write('watching for changes… (Ctrl+C to stop)\n');
|
|
307
|
+
rebuild();
|
|
308
|
+
} catch (err) {
|
|
309
|
+
if (watcher) watcher.close();
|
|
310
|
+
process.stderr.write(`error: ${err.message}\n`);
|
|
311
|
+
return 1;
|
|
252
312
|
}
|
|
253
313
|
return 0;
|
|
254
314
|
}
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
rebuild();
|
|
318
|
+
} catch (err) {
|
|
319
|
+
process.stderr.write(`error: ${err.message}\n`);
|
|
320
|
+
return 1;
|
|
321
|
+
}
|
|
255
322
|
return 0;
|
|
256
323
|
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
LintDiagnostic,
|
|
3
|
+
LintOptions,
|
|
4
|
+
RendererOptions,
|
|
5
|
+
RenderAnsiOptions,
|
|
6
|
+
RenderGitHubOptions,
|
|
7
|
+
} from '@chromamark/renderer';
|
|
8
|
+
|
|
9
|
+
export interface CompileOptions {
|
|
10
|
+
title?: string;
|
|
11
|
+
theme?: string;
|
|
12
|
+
rendererOptions?: RendererOptions;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function render(source: unknown, options?: RendererOptions): string;
|
|
16
|
+
export function renderAnsi(source: unknown, options?: RenderAnsiOptions): string;
|
|
17
|
+
export function renderGitHub(source: unknown, options?: RenderGitHubOptions): string;
|
|
18
|
+
export function lint(source: unknown, options?: LintOptions): LintDiagnostic[];
|
|
19
|
+
export function theme(): string;
|
|
20
|
+
export function compile(source: unknown, options?: CompileOptions): string;
|
|
21
|
+
|
|
22
|
+
export type {
|
|
23
|
+
LintDiagnostic,
|
|
24
|
+
LintOptions,
|
|
25
|
+
RendererOptions,
|
|
26
|
+
RenderAnsiOptions,
|
|
27
|
+
RenderGitHubOptions,
|
|
28
|
+
};
|
package/src/index.js
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import { readFileSync } from 'node:fs';
|
|
7
7
|
import { createRequire } from 'node:module';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
render as renderFragment, renderAnsi, renderGitHub, lint,
|
|
10
|
+
} from '@chromamark/renderer';
|
|
9
11
|
|
|
10
12
|
const require = createRequire(import.meta.url);
|
|
11
13
|
|
|
@@ -15,6 +17,9 @@ export const render = renderFragment;
|
|
|
15
17
|
/** Render ChromaMark to ANSI-styled text for a terminal. */
|
|
16
18
|
export { renderAnsi };
|
|
17
19
|
|
|
20
|
+
/** Render ChromaMark to GitHub-native GFM. */
|
|
21
|
+
export { renderGitHub };
|
|
22
|
+
|
|
18
23
|
/** Lint ChromaMark source, returning an array of diagnostics. */
|
|
19
24
|
export { lint };
|
|
20
25
|
|