md4x 0.0.9 → 0.0.10
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/build/md4x.darwin-arm64.node +0 -0
- package/build/md4x.darwin-x64.node +0 -0
- package/build/md4x.linux-arm.node +0 -0
- package/build/md4x.linux-arm64-musl.node +0 -0
- package/build/md4x.linux-arm64.node +0 -0
- package/build/md4x.linux-x64-musl.node +0 -0
- package/build/md4x.linux-x64.node +0 -0
- package/build/md4x.wasm +0 -0
- package/build/md4x.win32-arm64.node +0 -0
- package/build/md4x.win32-x64.node +0 -0
- package/lib/cli.mjs +34 -15
- package/lib/napi.d.mts +22 -3
- package/lib/napi.mjs +44 -19
- package/lib/{types.d.ts → types.d.mts} +16 -0
- package/lib/wasm.d.mts +15 -7
- package/lib/wasm.mjs +48 -30
- package/package.json +10 -16
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/build/md4x.wasm
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/cli.mjs
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
renderToHtml,
|
|
7
|
+
renderToAnsi,
|
|
8
|
+
renderToText,
|
|
9
|
+
parseAST,
|
|
10
|
+
parseMeta,
|
|
11
|
+
} from "./napi.mjs";
|
|
6
12
|
|
|
7
13
|
const { values, positionals } = parseArgs({
|
|
8
14
|
allowPositionals: true,
|
|
@@ -11,7 +17,7 @@ const { values, positionals } = parseArgs({
|
|
|
11
17
|
format: {
|
|
12
18
|
type: "string",
|
|
13
19
|
short: "t",
|
|
14
|
-
default: process.stdout.isTTY ? "ansi" : "
|
|
20
|
+
default: process.stdout.isTTY ? "ansi" : "text",
|
|
15
21
|
},
|
|
16
22
|
"full-html": { type: "boolean", short: "f", default: false },
|
|
17
23
|
"html-title": { type: "string" },
|
|
@@ -37,7 +43,7 @@ ${_g("Usage:")} ${_b("md4x")} ${_d("[OPTION]... [FILE]")}
|
|
|
37
43
|
|
|
38
44
|
${_g("General options:")}
|
|
39
45
|
${_c("-o")}, ${_c("--output")}=${_d("FILE")} Output file ${_d("(default: stdout)")}
|
|
40
|
-
${_c("-t")}, ${_c("--format")}=${_d("FORMAT")} Output format: html,
|
|
46
|
+
${_c("-t")}, ${_c("--format")}=${_d("FORMAT")} Output format: ${_c("html")}, ${_c("text")}, ${_c("ast")}, ${_c("ansi")}, ${_c("meta")} ${_d("(default: ansi for TTY, text otherwise)")}
|
|
41
47
|
${_c("-s")}, ${_c("--stat")} Measure parsing time
|
|
42
48
|
${_c("-h")}, ${_c("--help")} Display this help and exit
|
|
43
49
|
${_c("-v")}, ${_c("--version")} Display version and exit
|
|
@@ -53,13 +59,19 @@ ${_g("HTML options:")}
|
|
|
53
59
|
${_c("--html-css")}=${_d("URL")} CSS link
|
|
54
60
|
|
|
55
61
|
${_g("Examples:")}
|
|
56
|
-
${_d("$")} ${_b("md4x")} README.md
|
|
57
|
-
${_d("$")} ${_b("md4x")} ${_c("-t html")}
|
|
58
|
-
${_d("$")} ${_b("md4x")} ${_c("-t
|
|
59
|
-
${_d("$")} ${_b("md4x")} ${_c("
|
|
60
|
-
${_d("$")} ${_b("md4x")} ${_c("
|
|
61
|
-
${_d("$")}
|
|
62
|
-
${_d("$")} ${_b("md4x")} ${_c("
|
|
62
|
+
${_d("$")} ${_b("md4x")} README.md ${_d("# ANSI output")}
|
|
63
|
+
${_d("$")} ${_b("md4x")} README.md ${_c("-t html")} ${_d("# HTML output")}
|
|
64
|
+
${_d("$")} ${_b("md4x")} README.md ${_c("-t text")} ${_d("# Plain text output (strip markdown)")}
|
|
65
|
+
${_d("$")} ${_b("md4x")} README.md ${_c("-t ast")} ${_d("# JSON AST output (comark)")}
|
|
66
|
+
${_d("$")} ${_b("md4x")} README.md ${_c("-t meta")} ${_d("# Metadata JSON output")}
|
|
67
|
+
${_d("$")} ${_b("md4x")} ${_c("https://nitro.build/guide")} ${_d("# Fetch and render any URL")}
|
|
68
|
+
${_d("$")} ${_b("md4x")} ${_c("gh:")}nitrojs/nitro ${_d("# GitHub repo → README.md")}
|
|
69
|
+
${_d("$")} ${_b("md4x")} ${_c("npm:")}vue@3 ${_d("# npm package at specific version")}
|
|
70
|
+
${_d("$")} echo "# Hello" | ${_b("md4x")} ${_c("-t text")}
|
|
71
|
+
${_d("$")} cat README.md | ${_b("md4x")} ${_c("-t html")}
|
|
72
|
+
${_d("$")} ${_b("md4x")} README.md ${_c("-t meta -o")} README.json ${_d("# Write to file")}
|
|
73
|
+
${_d("$")} ${_b("md4x")} README.md ${_c("-t html -f --html-title")}="My Docs" ${_d("# Full HTML with <head>")}
|
|
74
|
+
${_d("$")} ${_b("md4x")} README.md ${_c("-t html -f --html-css")}=style.css ${_d("# Add CSS link")}
|
|
63
75
|
`,
|
|
64
76
|
);
|
|
65
77
|
}
|
|
@@ -77,10 +89,11 @@ if (values.version) {
|
|
|
77
89
|
process.exit(0);
|
|
78
90
|
}
|
|
79
91
|
|
|
92
|
+
const supportedFormats = ["html", "ast", "ansi", "text", "meta"];
|
|
80
93
|
const format = values.format;
|
|
81
|
-
if (!
|
|
94
|
+
if (!supportedFormats.includes(format)) {
|
|
82
95
|
process.stderr.write(`Unknown format: ${format}\n`);
|
|
83
|
-
process.stderr.write(
|
|
96
|
+
process.stderr.write(`Supported formats: ${supportedFormats.join(", ")}\n`);
|
|
84
97
|
process.exit(1);
|
|
85
98
|
}
|
|
86
99
|
|
|
@@ -146,12 +159,18 @@ switch (format) {
|
|
|
146
159
|
case "html":
|
|
147
160
|
output = renderToHtml(input);
|
|
148
161
|
break;
|
|
149
|
-
case "json":
|
|
150
|
-
output = JSON.stringify(renderToAST(input));
|
|
151
|
-
break;
|
|
152
162
|
case "ansi":
|
|
153
163
|
output = renderToAnsi(input);
|
|
154
164
|
break;
|
|
165
|
+
case "text":
|
|
166
|
+
output = renderToText(input);
|
|
167
|
+
break;
|
|
168
|
+
case "ast":
|
|
169
|
+
output = JSON.stringify(parseAST(input), null, 2);
|
|
170
|
+
break;
|
|
171
|
+
case "meta":
|
|
172
|
+
output = JSON.stringify(parseMeta(input), null, 2);
|
|
173
|
+
break;
|
|
155
174
|
}
|
|
156
175
|
|
|
157
176
|
if (values.stat) {
|
package/lib/napi.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComarkTree } from "./types.
|
|
1
|
+
import type { ComarkTree, ComarkMeta, HtmlOptions } from "./types.mjs";
|
|
2
2
|
|
|
3
3
|
export type {
|
|
4
4
|
ComarkTree,
|
|
@@ -6,9 +6,28 @@ export type {
|
|
|
6
6
|
ComarkElement,
|
|
7
7
|
ComarkText,
|
|
8
8
|
ComarkElementAttributes,
|
|
9
|
-
|
|
9
|
+
ComarkHeading,
|
|
10
|
+
ComarkMeta,
|
|
11
|
+
HtmlOptions,
|
|
12
|
+
} from "./types.mjs";
|
|
10
13
|
|
|
11
|
-
export
|
|
14
|
+
export interface NAPIBinding {
|
|
15
|
+
renderToHtml(input: string, flags?: number): string;
|
|
16
|
+
renderToAST(input: string): string;
|
|
17
|
+
renderToAnsi(input: string): string;
|
|
18
|
+
renderToMeta(input: string): string;
|
|
19
|
+
renderToText(input: string): string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface InitOptions {
|
|
23
|
+
binding?: NAPIBinding;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export declare function init(opts?: InitOptions): Promise<void>;
|
|
27
|
+
export declare function renderToHtml(input: string, opts?: HtmlOptions): string;
|
|
12
28
|
export declare function renderToAST(input: string): string;
|
|
13
29
|
export declare function parseAST(input: string): ComarkTree;
|
|
14
30
|
export declare function renderToAnsi(input: string): string;
|
|
31
|
+
export declare function renderToMeta(input: string): string;
|
|
32
|
+
export declare function parseMeta(input: string): ComarkMeta;
|
|
33
|
+
export declare function renderToText(input: string): string;
|
package/lib/napi.mjs
CHANGED
|
@@ -1,31 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
import { arch, platform } from "node:process";
|
|
1
|
+
// --- internal ---
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
let binding;
|
|
5
4
|
|
|
6
|
-
function
|
|
7
|
-
if (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return !process.report?.getReport?.()?.header?.glibcVersionRuntime;
|
|
11
|
-
} catch {
|
|
12
|
-
return false;
|
|
5
|
+
function getBinding(opts) {
|
|
6
|
+
if (binding) return binding;
|
|
7
|
+
if (opts?.binding) {
|
|
8
|
+
return (binding = opts.binding);
|
|
13
9
|
}
|
|
10
|
+
const { arch, platform } = globalThis.process || {};
|
|
11
|
+
const { createRequire } = globalThis.process?.getBuiltinModule?.("module");
|
|
12
|
+
const isMusl =
|
|
13
|
+
platform === "linux" &&
|
|
14
|
+
!process.report?.getReport?.()?.header?.glibcVersionRuntime;
|
|
15
|
+
return (binding = createRequire(import.meta.url)(
|
|
16
|
+
`../build/md4x.${platform}-${arch}${isMusl ? "-musl" : ""}.node`,
|
|
17
|
+
));
|
|
14
18
|
}
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
const suffix = isMusl() ? "-musl" : "";
|
|
18
|
-
return require(`../build/md4x.${platform}-${arch}${suffix}.node`);
|
|
19
|
-
}
|
|
20
|
+
// --- exports ----
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
export function init(opts) {
|
|
23
|
+
try {
|
|
24
|
+
getBinding(opts);
|
|
25
|
+
return Promise.resolve(binding);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
return Promise.reject(err);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
22
30
|
|
|
23
|
-
export function renderToHtml(input) {
|
|
24
|
-
|
|
31
|
+
export function renderToHtml(input, opts) {
|
|
32
|
+
const flags = opts?.full ? 0x0008 : 0;
|
|
33
|
+
return getBinding().renderToHtml(input, flags);
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
export function renderToAST(input) {
|
|
28
|
-
return
|
|
37
|
+
return getBinding().renderToAST(input);
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
export function parseAST(input) {
|
|
@@ -33,5 +42,21 @@ export function parseAST(input) {
|
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
export function renderToAnsi(input) {
|
|
36
|
-
return
|
|
45
|
+
return getBinding().renderToAnsi(input);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function renderToMeta(input) {
|
|
49
|
+
return getBinding().renderToMeta(input);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function renderToText(input) {
|
|
53
|
+
return getBinding().renderToText(input);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function parseMeta(input) {
|
|
57
|
+
const meta = JSON.parse(renderToMeta(input));
|
|
58
|
+
if (!meta.title && meta.headings?.[0]) {
|
|
59
|
+
meta.title = meta.headings[0].text;
|
|
60
|
+
}
|
|
61
|
+
return meta;
|
|
37
62
|
}
|
|
@@ -16,3 +16,19 @@ export type ComarkElement = [
|
|
|
16
16
|
export type ComarkElementAttributes = {
|
|
17
17
|
[key: string]: unknown;
|
|
18
18
|
};
|
|
19
|
+
|
|
20
|
+
export type ComarkHeading = {
|
|
21
|
+
level: number;
|
|
22
|
+
text: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type ComarkMeta = {
|
|
26
|
+
title?: string;
|
|
27
|
+
headings: ComarkHeading[];
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export interface HtmlOptions {
|
|
32
|
+
/** Generate a full HTML document with `<!DOCTYPE html>`, `<head>`, and `<body>`. */
|
|
33
|
+
full?: boolean;
|
|
34
|
+
}
|
package/lib/wasm.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComarkTree } from "./types.
|
|
1
|
+
import type { ComarkTree, ComarkMeta, HtmlOptions } from "./types.mjs";
|
|
2
2
|
|
|
3
3
|
export type {
|
|
4
4
|
ComarkTree,
|
|
@@ -6,17 +6,25 @@ export type {
|
|
|
6
6
|
ComarkElement,
|
|
7
7
|
ComarkText,
|
|
8
8
|
ComarkElementAttributes,
|
|
9
|
-
|
|
9
|
+
ComarkHeading,
|
|
10
|
+
ComarkMeta,
|
|
11
|
+
HtmlOptions,
|
|
12
|
+
} from "./types.mjs";
|
|
10
13
|
|
|
11
|
-
export
|
|
12
|
-
|
|
14
|
+
export interface InitOptions {
|
|
15
|
+
wasm?:
|
|
13
16
|
| ArrayBuffer
|
|
14
17
|
| Uint8Array
|
|
15
18
|
| WebAssembly.Module
|
|
16
19
|
| Response
|
|
17
|
-
| Promise<Response
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
| Promise<Response>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export declare function init(opts?: InitOptions): Promise<void>;
|
|
24
|
+
export declare function renderToHtml(input: string, opts?: HtmlOptions): string;
|
|
20
25
|
export declare function renderToAST(input: string): string;
|
|
21
26
|
export declare function parseAST(input: string): ComarkTree;
|
|
22
27
|
export declare function renderToAnsi(input: string): string;
|
|
28
|
+
export declare function renderToMeta(input: string): string;
|
|
29
|
+
export declare function parseMeta(input: string): ComarkMeta;
|
|
30
|
+
export declare function renderToText(input: string): string;
|
package/lib/wasm.mjs
CHANGED
|
@@ -1,16 +1,46 @@
|
|
|
1
|
+
// --- internal ---
|
|
2
|
+
|
|
1
3
|
let _instance;
|
|
2
4
|
|
|
3
5
|
function getExports() {
|
|
4
6
|
if (!_instance) {
|
|
5
|
-
throw new Error(
|
|
6
|
-
"md4x: WASM not initialized. Call `await initWasm()` first.",
|
|
7
|
-
);
|
|
7
|
+
throw new Error("md4x: WASM not initialized. Call `await init()` first.");
|
|
8
8
|
}
|
|
9
9
|
return _instance.exports;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const wasiStub = {
|
|
13
|
+
fd_close: () => 0,
|
|
14
|
+
fd_seek: () => 0,
|
|
15
|
+
fd_write: () => 0,
|
|
16
|
+
proc_exit: () => {},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function render(exports, fn, input, ...extra) {
|
|
20
|
+
const { memory, md4x_alloc, md4x_free, md4x_result_ptr, md4x_result_size } =
|
|
21
|
+
exports;
|
|
22
|
+
const encoded = new TextEncoder().encode(input);
|
|
23
|
+
const ptr = md4x_alloc(encoded.length);
|
|
24
|
+
new Uint8Array(memory.buffer).set(encoded, ptr);
|
|
25
|
+
const ret = fn(ptr, encoded.length, ...extra);
|
|
26
|
+
md4x_free(ptr);
|
|
27
|
+
if (ret !== 0) {
|
|
28
|
+
throw new Error("md4x: render failed");
|
|
29
|
+
}
|
|
30
|
+
const outPtr = md4x_result_ptr();
|
|
31
|
+
const outSize = md4x_result_size();
|
|
32
|
+
const result = new TextDecoder().decode(
|
|
33
|
+
new Uint8Array(memory.buffer, outPtr, outSize),
|
|
34
|
+
);
|
|
35
|
+
md4x_free(outPtr);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// --- exports ----
|
|
40
|
+
|
|
41
|
+
export async function init(opts) {
|
|
13
42
|
if (_instance) return;
|
|
43
|
+
const input = opts?.wasm;
|
|
14
44
|
let bytes;
|
|
15
45
|
if (input instanceof ArrayBuffer || input instanceof Uint8Array) {
|
|
16
46
|
bytes = input;
|
|
@@ -47,8 +77,9 @@ export async function initWasm(input) {
|
|
|
47
77
|
_instance = instance;
|
|
48
78
|
}
|
|
49
79
|
|
|
50
|
-
export function renderToHtml(input) {
|
|
51
|
-
|
|
80
|
+
export function renderToHtml(input, opts) {
|
|
81
|
+
const flags = opts?.full ? 0x0008 : 0;
|
|
82
|
+
return render(getExports(), getExports().md4x_to_html, input, flags);
|
|
52
83
|
}
|
|
53
84
|
|
|
54
85
|
export function renderToAST(input) {
|
|
@@ -63,31 +94,18 @@ export function renderToAnsi(input) {
|
|
|
63
94
|
return render(getExports(), getExports().md4x_to_ansi, input);
|
|
64
95
|
}
|
|
65
96
|
|
|
66
|
-
|
|
97
|
+
export function renderToMeta(input) {
|
|
98
|
+
return render(getExports(), getExports().md4x_to_meta, input);
|
|
99
|
+
}
|
|
67
100
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
fd_write: () => 0,
|
|
72
|
-
proc_exit: () => {},
|
|
73
|
-
};
|
|
101
|
+
export function renderToText(input) {
|
|
102
|
+
return render(getExports(), getExports().md4x_to_text, input);
|
|
103
|
+
}
|
|
74
104
|
|
|
75
|
-
function
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const ptr = md4x_alloc(encoded.length);
|
|
80
|
-
new Uint8Array(memory.buffer).set(encoded, ptr);
|
|
81
|
-
const ret = fn(ptr, encoded.length);
|
|
82
|
-
md4x_free(ptr);
|
|
83
|
-
if (ret !== 0) {
|
|
84
|
-
throw new Error("md4x: render failed");
|
|
105
|
+
export function parseMeta(input) {
|
|
106
|
+
const meta = JSON.parse(renderToMeta(input));
|
|
107
|
+
if (!meta.title && meta.headings?.[0]) {
|
|
108
|
+
meta.title = meta.headings[0].text;
|
|
85
109
|
}
|
|
86
|
-
|
|
87
|
-
const outSize = md4x_result_size();
|
|
88
|
-
const result = new TextDecoder().decode(
|
|
89
|
-
new Uint8Array(memory.buffer, outPtr, outSize),
|
|
90
|
-
);
|
|
91
|
-
md4x_free(outPtr);
|
|
92
|
-
return result;
|
|
110
|
+
return meta;
|
|
93
111
|
}
|
package/package.json
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "md4x",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
|
+
"repository": "pi0/md4x",
|
|
4
5
|
"license": "MIT",
|
|
5
6
|
"type": "module",
|
|
6
|
-
"repository": "pi0/md4x",
|
|
7
|
-
"bin": {
|
|
8
|
-
"md4x": "./lib/cli.mjs"
|
|
9
|
-
},
|
|
10
7
|
"exports": {
|
|
8
|
+
"./wasm": "./lib/wasm.mjs",
|
|
9
|
+
"./napi": "./lib/napi.mjs",
|
|
11
10
|
".": {
|
|
12
|
-
"types": "./lib/napi.d.mts",
|
|
13
11
|
"node": "./lib/napi.mjs",
|
|
14
12
|
"default": "./lib/wasm.mjs"
|
|
15
|
-
},
|
|
16
|
-
"./wasm": {
|
|
17
|
-
"types": "./lib/wasm.d.mts",
|
|
18
|
-
"default": "./lib/wasm.mjs"
|
|
19
|
-
},
|
|
20
|
-
"./napi": {
|
|
21
|
-
"types": "./lib/napi.d.mts",
|
|
22
|
-
"default": "./lib/napi.mjs"
|
|
23
13
|
}
|
|
24
14
|
},
|
|
25
|
-
"
|
|
26
|
-
|
|
15
|
+
"types": "./lib/types.d.mts",
|
|
16
|
+
"bin": {
|
|
17
|
+
"md4x": "./lib/cli.mjs"
|
|
27
18
|
},
|
|
28
19
|
"files": [
|
|
29
20
|
"build",
|
|
30
21
|
"lib",
|
|
31
22
|
"README.md"
|
|
32
23
|
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"prepack": "cd ../.. && zig build --verbose"
|
|
26
|
+
},
|
|
33
27
|
"devDependencies": {
|
|
34
28
|
"markdown-it": "^14.1.1",
|
|
35
29
|
"markdown-it-mdc": "^0.2.12",
|