ironmark 1.8.1 → 1.10.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 +134 -1
- package/package.json +5 -1
- package/wasm/cli.js +154 -0
- package/wasm/index.d.ts +46 -0
- package/wasm/node.js +4 -2
- package/wasm/pkg/ironmark.d.ts +15 -0
- package/wasm/pkg/ironmark.js +1 -1
- package/wasm/pkg/ironmark_bg.js +55 -0
- package/wasm/pkg/ironmark_bg.wasm +0 -0
- package/wasm/pkg/ironmark_bg.wasm.d.ts +1 -0
- package/wasm/shared.js +30 -18
- package/wasm/web.js +2 -1
package/README.md
CHANGED
|
@@ -84,6 +84,37 @@ const ast = JSON.parse(astJson);
|
|
|
84
84
|
|
|
85
85
|
`parseToAst()` returns a JSON string for portability across JS runtimes and WASM boundaries.
|
|
86
86
|
|
|
87
|
+
### ANSI Terminal Output
|
|
88
|
+
|
|
89
|
+
Use `renderAnsi()` to render Markdown as coloured terminal output (ANSI 256-colour escape codes). Useful for CLI tools, terminal UIs, or any environment with a TTY.
|
|
90
|
+
|
|
91
|
+
````ts
|
|
92
|
+
import { renderAnsi } from "ironmark";
|
|
93
|
+
|
|
94
|
+
// Render with defaults (width 80, colour enabled)
|
|
95
|
+
const ansi = renderAnsi("# Hello\n\n**bold** and `code`");
|
|
96
|
+
process.stdout.write(ansi);
|
|
97
|
+
|
|
98
|
+
// Custom terminal width and line numbers in code blocks
|
|
99
|
+
const ansi = renderAnsi(
|
|
100
|
+
"# Hello\n\n```rust\nfn main() {}\n```",
|
|
101
|
+
{}, // parse options (same as parse())
|
|
102
|
+
{ width: 120, lineNumbers: true },
|
|
103
|
+
);
|
|
104
|
+
process.stdout.write(ansi);
|
|
105
|
+
|
|
106
|
+
// Plain text — strips all ANSI codes (useful for piping to files)
|
|
107
|
+
const plain = renderAnsi("# Hello\n\n> quote", {}, { color: false });
|
|
108
|
+
````
|
|
109
|
+
|
|
110
|
+
#### ANSI options
|
|
111
|
+
|
|
112
|
+
| Option | Type | Default | Description |
|
|
113
|
+
| ------------- | --------- | ------- | ------------------------------------------------------------------------------- |
|
|
114
|
+
| `width` | `number` | `80` | Column width for word-wrap, heading underlines, rule length. `0` = use default. |
|
|
115
|
+
| `color` | `boolean` | `true` | Emit ANSI colour codes. `false` = plain text output. |
|
|
116
|
+
| `lineNumbers` | `boolean` | `false` | Show line numbers in fenced code blocks. |
|
|
117
|
+
|
|
87
118
|
### Browser / Bundler
|
|
88
119
|
|
|
89
120
|
Call `init()` once before using `parse()`. It's idempotent and optionally accepts a custom `.wasm` URL.
|
|
@@ -107,6 +138,71 @@ await init(wasmUrl);
|
|
|
107
138
|
const html = parse("# Hello\n\nThis is **fast**.");
|
|
108
139
|
```
|
|
109
140
|
|
|
141
|
+
## CLI
|
|
142
|
+
|
|
143
|
+
Render Markdown as coloured terminal output. Two ways to install:
|
|
144
|
+
|
|
145
|
+
### npm
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx ironmark --ansi README.md
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Or install globally:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npm install -g ironmark
|
|
155
|
+
ironmark --ansi README.md
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Rust
|
|
159
|
+
|
|
160
|
+
Native binary — faster startup, auto-detects terminal width via `$COLUMNS` / `tput cols`.
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
cargo install ironmark --features cli
|
|
164
|
+
ironmark --ansi README.md
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Options
|
|
168
|
+
|
|
169
|
+
Both CLIs support the same flags (the npm CLI requires `--ansi` as the first flag):
|
|
170
|
+
|
|
171
|
+
```text
|
|
172
|
+
OPTIONS:
|
|
173
|
+
--width N Terminal column width (default: auto-detect, fallback 80)
|
|
174
|
+
--no-color Disable ANSI escape codes (plain text)
|
|
175
|
+
-n, --line-numbers Show line numbers in fenced code blocks
|
|
176
|
+
--no-hard-breaks Don't turn soft newlines into hard line breaks
|
|
177
|
+
--no-tables Disable pipe table syntax
|
|
178
|
+
--no-highlight Disable ==highlight== syntax
|
|
179
|
+
--no-strikethrough Disable ~~strikethrough~~ syntax
|
|
180
|
+
--no-underline Disable ++underline++ syntax
|
|
181
|
+
--no-autolink Disable bare URL auto-linking
|
|
182
|
+
--no-task-lists Disable - [x] task list syntax
|
|
183
|
+
--math Enable $inline$ and $$display$$ math
|
|
184
|
+
--wiki-links Enable [[wiki link]] syntax
|
|
185
|
+
--max-size N Truncate input to N bytes (Rust only)
|
|
186
|
+
-h, --help Print this help and exit
|
|
187
|
+
-V, --version Print version and exit
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Examples
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# npm
|
|
194
|
+
npx ironmark --ansi README.md
|
|
195
|
+
npx ironmark --ansi --width 120 README.md
|
|
196
|
+
echo '# Hello' | npx ironmark --ansi
|
|
197
|
+
npx ironmark --ansi --no-color README.md | less
|
|
198
|
+
|
|
199
|
+
# Rust (after cargo install ironmark --features cli)
|
|
200
|
+
ironmark --ansi README.md
|
|
201
|
+
ironmark --ansi --width 120 README.md
|
|
202
|
+
echo '# Hello' | ironmark --ansi
|
|
203
|
+
cat doc.md | ironmark --ansi --math --wiki-links
|
|
204
|
+
```
|
|
205
|
+
|
|
110
206
|
## Rust
|
|
111
207
|
|
|
112
208
|
```bash
|
|
@@ -162,6 +258,43 @@ Exported AST types:
|
|
|
162
258
|
- `TableData`
|
|
163
259
|
- `TableAlignment`
|
|
164
260
|
|
|
261
|
+
### ANSI Terminal Output
|
|
262
|
+
|
|
263
|
+
`render_ansi()` renders Markdown as ANSI-coloured terminal output. Pass `Some(&AnsiOptions { .. })` to control width, colour, and line numbers, or `None` for defaults.
|
|
264
|
+
|
|
265
|
+
````rust
|
|
266
|
+
use ironmark::{AnsiOptions, ParseOptions, render_ansi};
|
|
267
|
+
|
|
268
|
+
fn main() {
|
|
269
|
+
// Defaults — width 80, colour enabled
|
|
270
|
+
let out = render_ansi("# Hello\n\n**bold** and `code`", &ParseOptions::default(), None);
|
|
271
|
+
print!("{out}");
|
|
272
|
+
|
|
273
|
+
// Custom options — 120 columns, line numbers in code blocks
|
|
274
|
+
let out = render_ansi(
|
|
275
|
+
"# Hello\n\n```rust\nfn main() {}\n```",
|
|
276
|
+
&ParseOptions::default(),
|
|
277
|
+
Some(&AnsiOptions { width: 120, line_numbers: true, ..AnsiOptions::default() }),
|
|
278
|
+
);
|
|
279
|
+
print!("{out}");
|
|
280
|
+
|
|
281
|
+
// Plain text — no ANSI codes (e.g. for writing to a file)
|
|
282
|
+
let plain = render_ansi(
|
|
283
|
+
"# Hello",
|
|
284
|
+
&ParseOptions::default(),
|
|
285
|
+
Some(&AnsiOptions { color: false, ..AnsiOptions::default() }),
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
````
|
|
289
|
+
|
|
290
|
+
`AnsiOptions` fields:
|
|
291
|
+
|
|
292
|
+
| Field | Type | Default | Description |
|
|
293
|
+
| -------------- | ------- | ------- | --------------------------------------------------------------------------- |
|
|
294
|
+
| `width` | `usize` | `80` | Column width for word-wrap, heading underlines, rule length. `0` = disable. |
|
|
295
|
+
| `color` | `bool` | `true` | Emit ANSI 256-colour escape codes. |
|
|
296
|
+
| `line_numbers` | `bool` | `false` | Show line numbers in fenced code blocks. |
|
|
297
|
+
|
|
165
298
|
## C / C++
|
|
166
299
|
|
|
167
300
|
The crate compiles to a static library (`libironmark.a`) that exposes two C functions. A header is provided at `include/ironmark.h`.
|
|
@@ -236,4 +369,4 @@ pnpm build
|
|
|
236
369
|
|
|
237
370
|
### Troubleshooting
|
|
238
371
|
|
|
239
|
-
**`wasm32-unknown-unknown target not found`** or **`wasm-bindgen not found`** — run `pnpm setup:wasm` to install all prerequisites
|
|
372
|
+
**`wasm32-unknown-unknown target not found`** or **`wasm-bindgen not found`** — run `pnpm setup:wasm` to install all prerequisites
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ironmark",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Very fast markdown parser in Rust, consumable from JavaScript/TypeScript via WebAssembly",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -17,11 +17,15 @@
|
|
|
17
17
|
"type": "git",
|
|
18
18
|
"url": "https://github.com/ph1p/ironmark.git"
|
|
19
19
|
},
|
|
20
|
+
"bin": {
|
|
21
|
+
"ironmark": "wasm/cli.js"
|
|
22
|
+
},
|
|
20
23
|
"files": [
|
|
21
24
|
"wasm/pkg",
|
|
22
25
|
"wasm/shared.js",
|
|
23
26
|
"wasm/web.js",
|
|
24
27
|
"wasm/node.js",
|
|
28
|
+
"wasm/cli.js",
|
|
25
29
|
"wasm/index.d.ts",
|
|
26
30
|
"README.md"
|
|
27
31
|
],
|
package/wasm/cli.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { renderAnsi } from "./node.js";
|
|
4
|
+
|
|
5
|
+
const VERSION = JSON.parse(
|
|
6
|
+
readFileSync(new URL("../package.json", import.meta.url), "utf8"),
|
|
7
|
+
).version;
|
|
8
|
+
|
|
9
|
+
const HELP = `ironmark — render Markdown as coloured terminal output
|
|
10
|
+
|
|
11
|
+
USAGE:
|
|
12
|
+
ironmark --ansi [OPTIONS] [FILE...]
|
|
13
|
+
|
|
14
|
+
When no FILE is given, reads from stdin. Use '-' for stdin explicitly.
|
|
15
|
+
|
|
16
|
+
OPTIONS:
|
|
17
|
+
--ansi Render as ANSI-coloured terminal output (required)
|
|
18
|
+
--width N Terminal column width (default: auto-detect, fallback 80)
|
|
19
|
+
--no-color Disable ANSI escape codes (plain text)
|
|
20
|
+
-n, --line-numbers Show line numbers in fenced code blocks
|
|
21
|
+
--no-hard-breaks Don't turn soft newlines into hard line breaks
|
|
22
|
+
--no-tables Disable pipe table syntax
|
|
23
|
+
--no-highlight Disable ==highlight== syntax
|
|
24
|
+
--no-strikethrough Disable ~~strikethrough~~ syntax
|
|
25
|
+
--no-underline Disable ++underline++ syntax
|
|
26
|
+
--no-autolink Disable bare URL auto-linking
|
|
27
|
+
--no-task-lists Disable - [x] task list syntax
|
|
28
|
+
--math Enable $inline$ and $$display$$ math
|
|
29
|
+
--wiki-links Enable [[wiki link]] syntax
|
|
30
|
+
-h, --help Print this help and exit
|
|
31
|
+
-V, --version Print version and exit
|
|
32
|
+
|
|
33
|
+
EXAMPLES:
|
|
34
|
+
npx ironmark --ansi README.md
|
|
35
|
+
npx ironmark --ansi --width 120 README.md
|
|
36
|
+
npx ironmark --ansi --no-color README.md | less
|
|
37
|
+
echo '# Hello' | npx ironmark --ansi
|
|
38
|
+
cat doc.md | npx ironmark --ansi --math --wiki-links
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
const args = process.argv.slice(2);
|
|
42
|
+
const files = [];
|
|
43
|
+
const parseOptions = {};
|
|
44
|
+
const ansiOptions = {};
|
|
45
|
+
let ansiMode = false;
|
|
46
|
+
|
|
47
|
+
for (let i = 0; i < args.length; i++) {
|
|
48
|
+
switch (args[i]) {
|
|
49
|
+
case "-h":
|
|
50
|
+
case "--help":
|
|
51
|
+
process.stdout.write(HELP);
|
|
52
|
+
process.exit(0);
|
|
53
|
+
break;
|
|
54
|
+
case "-V":
|
|
55
|
+
case "--version":
|
|
56
|
+
console.log(`ironmark ${VERSION}`);
|
|
57
|
+
process.exit(0);
|
|
58
|
+
break;
|
|
59
|
+
case "--ansi":
|
|
60
|
+
ansiMode = true;
|
|
61
|
+
break;
|
|
62
|
+
case "--no-color":
|
|
63
|
+
case "--no-colour":
|
|
64
|
+
ansiOptions.color = false;
|
|
65
|
+
break;
|
|
66
|
+
case "-n":
|
|
67
|
+
case "--line-numbers":
|
|
68
|
+
ansiOptions.lineNumbers = true;
|
|
69
|
+
break;
|
|
70
|
+
case "--width": {
|
|
71
|
+
const val = args[++i];
|
|
72
|
+
if (val === undefined || Number.isNaN(Number(val))) {
|
|
73
|
+
console.error("error: --width requires a numeric value");
|
|
74
|
+
process.exit(2);
|
|
75
|
+
}
|
|
76
|
+
ansiOptions.width = Number(val);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case "--no-hard-breaks":
|
|
80
|
+
parseOptions.hardBreaks = false;
|
|
81
|
+
break;
|
|
82
|
+
case "--no-tables":
|
|
83
|
+
parseOptions.enableTables = false;
|
|
84
|
+
break;
|
|
85
|
+
case "--no-highlight":
|
|
86
|
+
parseOptions.enableHighlight = false;
|
|
87
|
+
break;
|
|
88
|
+
case "--no-strikethrough":
|
|
89
|
+
parseOptions.enableStrikethrough = false;
|
|
90
|
+
break;
|
|
91
|
+
case "--no-underline":
|
|
92
|
+
parseOptions.enableUnderline = false;
|
|
93
|
+
break;
|
|
94
|
+
case "--no-autolink":
|
|
95
|
+
parseOptions.enableAutolink = false;
|
|
96
|
+
break;
|
|
97
|
+
case "--no-task-lists":
|
|
98
|
+
parseOptions.enableTaskLists = false;
|
|
99
|
+
break;
|
|
100
|
+
case "--math":
|
|
101
|
+
parseOptions.enableLatexMath = true;
|
|
102
|
+
break;
|
|
103
|
+
case "--wiki-links":
|
|
104
|
+
parseOptions.enableWikiLinks = true;
|
|
105
|
+
break;
|
|
106
|
+
default:
|
|
107
|
+
if (args[i].startsWith("--width=")) {
|
|
108
|
+
const val = Number(args[i].slice("--width=".length));
|
|
109
|
+
if (Number.isNaN(val)) {
|
|
110
|
+
console.error("error: --width requires a numeric value");
|
|
111
|
+
process.exit(2);
|
|
112
|
+
}
|
|
113
|
+
ansiOptions.width = val;
|
|
114
|
+
} else if (args[i].startsWith("-") && args[i] !== "-") {
|
|
115
|
+
console.error(`error: unknown flag: ${args[i]}`);
|
|
116
|
+
console.error("Run 'ironmark --help' for usage.");
|
|
117
|
+
process.exit(2);
|
|
118
|
+
} else {
|
|
119
|
+
files.push(args[i]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!ansiMode) {
|
|
125
|
+
console.error("error: --ansi flag is required");
|
|
126
|
+
console.error("Run 'ironmark --help' for usage.");
|
|
127
|
+
process.exit(2);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Auto-detect terminal width
|
|
131
|
+
if (ansiOptions.width === undefined) {
|
|
132
|
+
ansiOptions.width = process.stdout.columns || 80;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let input = "";
|
|
136
|
+
|
|
137
|
+
if (files.length === 0) {
|
|
138
|
+
input = readFileSync(0, "utf8");
|
|
139
|
+
} else {
|
|
140
|
+
for (const file of files) {
|
|
141
|
+
if (file === "-") {
|
|
142
|
+
input += readFileSync(0, "utf8");
|
|
143
|
+
} else {
|
|
144
|
+
try {
|
|
145
|
+
input += readFileSync(file, "utf8");
|
|
146
|
+
} catch (err) {
|
|
147
|
+
console.error(`error: ${file}: ${err.message}`);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
process.stdout.write(renderAnsi(input, parseOptions, ansiOptions));
|
package/wasm/index.d.ts
CHANGED
|
@@ -66,3 +66,49 @@ export declare function parse(markdown: MarkdownInput, options?: ParseOptions):
|
|
|
66
66
|
* @returns JSON string representing the AST.
|
|
67
67
|
*/
|
|
68
68
|
export declare function parseToAst(markdown: MarkdownInput, options?: ParseOptions): string;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Options for the ANSI terminal renderer.
|
|
72
|
+
*/
|
|
73
|
+
export interface AnsiOptions {
|
|
74
|
+
/**
|
|
75
|
+
* Terminal column width for word-wrap, heading underlines, and thematic breaks.
|
|
76
|
+
* Set to `0` to disable all width-dependent formatting. Default: `80`.
|
|
77
|
+
*/
|
|
78
|
+
width?: number;
|
|
79
|
+
/**
|
|
80
|
+
* Emit ANSI 256-colour escape codes. Set to `false` for plain-text output
|
|
81
|
+
* (e.g. when piping to a file or a non-colour terminal). Default: `true`.
|
|
82
|
+
*/
|
|
83
|
+
color?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Show line numbers in fenced code blocks, right-aligned to the total line
|
|
86
|
+
* count and separated from the code by a `│` border. Default: `false`.
|
|
87
|
+
*/
|
|
88
|
+
lineNumbers?: boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Render Markdown as ANSI-coloured terminal output.
|
|
93
|
+
*
|
|
94
|
+
* Produces a string containing ANSI 256-colour escape codes suitable for
|
|
95
|
+
* display in a terminal emulator. Headings, code blocks, inline code,
|
|
96
|
+
* blockquotes, tables, and inline formatting are all styled distinctly.
|
|
97
|
+
*
|
|
98
|
+
* @param markdown - Markdown source (string or binary).
|
|
99
|
+
* @param options - Optional parse options (same flags as `parse()`).
|
|
100
|
+
* @param ansiOptions - Optional ANSI rendering options (width, color, lineNumbers).
|
|
101
|
+
* @returns String with ANSI escape codes (or plain text when `color: false`).
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* import { renderAnsi } from "ironmark";
|
|
106
|
+
* const out = renderAnsi("# Hello\n\n**bold** and `code`");
|
|
107
|
+
* process.stdout.write(out);
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export declare function renderAnsi(
|
|
111
|
+
markdown: MarkdownInput,
|
|
112
|
+
options?: ParseOptions,
|
|
113
|
+
ansiOptions?: AnsiOptions,
|
|
114
|
+
): string;
|