@clevertree/md2ast 1.0.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 ADDED
@@ -0,0 +1,108 @@
1
+
2
+ # @clevertree/md2ast
3
+
4
+ Markdown → JSON AST for CleverScript / Relay hosts (WASM, JNI, Rust).
5
+
6
+ ## Architecture
7
+
8
+ ```mermaid
9
+ graph TD
10
+ subgraph "Input"
11
+ MD[Markdown Source]
12
+ end
13
+
14
+ subgraph "Parser Core (Rust)"
15
+ CM[pulldown-cmark]
16
+ HTML[HTML Tag Filter]
17
+ AST[AST Generator]
18
+ end
19
+
20
+ subgraph "Output"
21
+ JSON[JSON AST]
22
+ end
23
+
24
+ MD --> CM
25
+ CM --> HTML
26
+ HTML --> AST
27
+ AST --> JSON
28
+ ```
29
+
30
+ This library parses Markdown (including GitHub Flavored Markdown) and converts it into a JSON-serializable Abstract Syntax Tree (AST) for CleverScript, Relay, React, or other JSX-like runtimes.
31
+
32
+ ## Features
33
+
34
+ - **Fast**: Powered by Rust and `pulldown-cmark`.
35
+ - **Cross-Platform**: WASM for Web, JNI for Android.
36
+ - **HTML Support**: Supports nested HTML tags within Markdown.
37
+ - **Custom Tag Filtering**: Only renders HTML tags explicitly allowed in `allowed_tags`.
38
+ - **GFM Support**: Tables, task lists, and strikethrough enabled by default.
39
+
40
+ ## Installation
41
+
42
+ ### NPM (Web)
43
+
44
+ ```bash
45
+ npm install @clevertree/md2ast
46
+ ```
47
+
48
+ ### Maven (Android)
49
+
50
+ Add to your `build.gradle`:
51
+
52
+ ```gradle
53
+ dependencies {
54
+ implementation 'com.clevertree:md2ast:1.0.0'
55
+ }
56
+ ```
57
+
58
+ ### Cargo (Rust)
59
+
60
+ ```toml
61
+ [dependencies]
62
+ md2ast = "1.0.0"
63
+ ```
64
+
65
+ ## Usage
66
+
67
+ ### Web (WASM)
68
+
69
+ ```javascript
70
+ import init, { parse_markdown } from '@clevertree/md2ast';
71
+
72
+ async function run() {
73
+ await init();
74
+ const markdown = "# Hello\n<CustomBox title=\"Alert\">Content</CustomBox>";
75
+ const options = {
76
+ allowed_tags: ["CustomBox"]
77
+ };
78
+ const ast = parse_markdown(markdown, options);
79
+ console.log(ast);
80
+ }
81
+ ```
82
+
83
+ ### Android (Kotlin)
84
+
85
+ ```kotlin
86
+ val astJson = MarkdownParser.parse(markdown, allowedTags = listOf("CustomBox"))
87
+ ```
88
+
89
+ ## AST Structure
90
+
91
+ The output is a list of nodes:
92
+
93
+ ```json
94
+ [
95
+ {
96
+ "type": "element",
97
+ "tag": "h1",
98
+ "props": {},
99
+ "children": [
100
+ { "type": "text", "content": "Hello" }
101
+ ]
102
+ }
103
+ ]
104
+ ```
105
+
106
+ ## License
107
+
108
+ MIT OR Apache-2.0
package/md2ast.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ export function transpile(markdown: string, allowed_tags: string[]): string;
5
+
6
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
7
+
8
+ export interface InitOutput {
9
+ readonly memory: WebAssembly.Memory;
10
+ readonly transpile: (a: number, b: number, c: number, d: number, e: number) => void;
11
+ readonly __wbindgen_export: (a: number, b: number) => number;
12
+ readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
13
+ readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
14
+ readonly __wbindgen_export3: (a: number, b: number, c: number) => void;
15
+ }
16
+
17
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
18
+
19
+ /**
20
+ * Instantiates the given `module`, which can either be bytes or
21
+ * a precompiled `WebAssembly.Module`.
22
+ *
23
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
24
+ *
25
+ * @returns {InitOutput}
26
+ */
27
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
28
+
29
+ /**
30
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
31
+ * for everything else, calls `WebAssembly.instantiate` directly.
32
+ *
33
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
34
+ *
35
+ * @returns {Promise<InitOutput>}
36
+ */
37
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
package/md2ast.js ADDED
@@ -0,0 +1,282 @@
1
+ let wasm;
2
+
3
+ function addHeapObject(obj) {
4
+ if (heap_next === heap.length) heap.push(heap.length + 1);
5
+ const idx = heap_next;
6
+ heap_next = heap[idx];
7
+
8
+ heap[idx] = obj;
9
+ return idx;
10
+ }
11
+
12
+ function dropObject(idx) {
13
+ if (idx < 132) return;
14
+ heap[idx] = heap_next;
15
+ heap_next = idx;
16
+ }
17
+
18
+ let cachedDataViewMemory0 = null;
19
+ function getDataViewMemory0() {
20
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
21
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
22
+ }
23
+ return cachedDataViewMemory0;
24
+ }
25
+
26
+ function getStringFromWasm0(ptr, len) {
27
+ ptr = ptr >>> 0;
28
+ return decodeText(ptr, len);
29
+ }
30
+
31
+ let cachedUint8ArrayMemory0 = null;
32
+ function getUint8ArrayMemory0() {
33
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
34
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
35
+ }
36
+ return cachedUint8ArrayMemory0;
37
+ }
38
+
39
+ function getObject(idx) { return heap[idx]; }
40
+
41
+ let heap = new Array(128).fill(undefined);
42
+ heap.push(undefined, null, true, false);
43
+
44
+ let heap_next = heap.length;
45
+
46
+ function isLikeNone(x) {
47
+ return x === undefined || x === null;
48
+ }
49
+
50
+ function passArrayJsValueToWasm0(array, malloc) {
51
+ const ptr = malloc(array.length * 4, 4) >>> 0;
52
+ const mem = getDataViewMemory0();
53
+ for (let i = 0; i < array.length; i++) {
54
+ mem.setUint32(ptr + 4 * i, addHeapObject(array[i]), true);
55
+ }
56
+ WASM_VECTOR_LEN = array.length;
57
+ return ptr;
58
+ }
59
+
60
+ function passStringToWasm0(arg, malloc, realloc) {
61
+ if (realloc === undefined) {
62
+ const buf = cachedTextEncoder.encode(arg);
63
+ const ptr = malloc(buf.length, 1) >>> 0;
64
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
65
+ WASM_VECTOR_LEN = buf.length;
66
+ return ptr;
67
+ }
68
+
69
+ let len = arg.length;
70
+ let ptr = malloc(len, 1) >>> 0;
71
+
72
+ const mem = getUint8ArrayMemory0();
73
+
74
+ let offset = 0;
75
+
76
+ for (; offset < len; offset++) {
77
+ const code = arg.charCodeAt(offset);
78
+ if (code > 0x7F) break;
79
+ mem[ptr + offset] = code;
80
+ }
81
+ if (offset !== len) {
82
+ if (offset !== 0) {
83
+ arg = arg.slice(offset);
84
+ }
85
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
86
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
87
+ const ret = cachedTextEncoder.encodeInto(arg, view);
88
+
89
+ offset += ret.written;
90
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
91
+ }
92
+
93
+ WASM_VECTOR_LEN = offset;
94
+ return ptr;
95
+ }
96
+
97
+ function takeObject(idx) {
98
+ const ret = getObject(idx);
99
+ dropObject(idx);
100
+ return ret;
101
+ }
102
+
103
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
104
+ cachedTextDecoder.decode();
105
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
106
+ let numBytesDecoded = 0;
107
+ function decodeText(ptr, len) {
108
+ numBytesDecoded += len;
109
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
110
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
111
+ cachedTextDecoder.decode();
112
+ numBytesDecoded = len;
113
+ }
114
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
115
+ }
116
+
117
+ const cachedTextEncoder = new TextEncoder();
118
+
119
+ if (!('encodeInto' in cachedTextEncoder)) {
120
+ cachedTextEncoder.encodeInto = function (arg, view) {
121
+ const buf = cachedTextEncoder.encode(arg);
122
+ view.set(buf);
123
+ return {
124
+ read: arg.length,
125
+ written: buf.length
126
+ };
127
+ }
128
+ }
129
+
130
+ let WASM_VECTOR_LEN = 0;
131
+
132
+ /**
133
+ * @param {string} markdown
134
+ * @param {string[]} allowed_tags
135
+ * @returns {string}
136
+ */
137
+ export function transpile(markdown, allowed_tags) {
138
+ let deferred4_0;
139
+ let deferred4_1;
140
+ try {
141
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
142
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
143
+ const len0 = WASM_VECTOR_LEN;
144
+ const ptr1 = passArrayJsValueToWasm0(allowed_tags, wasm.__wbindgen_export);
145
+ const len1 = WASM_VECTOR_LEN;
146
+ wasm.transpile(retptr, ptr0, len0, ptr1, len1);
147
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
148
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
149
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
150
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
151
+ var ptr3 = r0;
152
+ var len3 = r1;
153
+ if (r3) {
154
+ ptr3 = 0; len3 = 0;
155
+ throw takeObject(r2);
156
+ }
157
+ deferred4_0 = ptr3;
158
+ deferred4_1 = len3;
159
+ return getStringFromWasm0(ptr3, len3);
160
+ } finally {
161
+ wasm.__wbindgen_add_to_stack_pointer(16);
162
+ wasm.__wbindgen_export3(deferred4_0, deferred4_1, 1);
163
+ }
164
+ }
165
+
166
+ const EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']);
167
+
168
+ async function __wbg_load(module, imports) {
169
+ if (typeof Response === 'function' && module instanceof Response) {
170
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
171
+ try {
172
+ return await WebAssembly.instantiateStreaming(module, imports);
173
+ } catch (e) {
174
+ const validResponse = module.ok && EXPECTED_RESPONSE_TYPES.has(module.type);
175
+
176
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
177
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
178
+
179
+ } else {
180
+ throw e;
181
+ }
182
+ }
183
+ }
184
+
185
+ const bytes = await module.arrayBuffer();
186
+ return await WebAssembly.instantiate(bytes, imports);
187
+ } else {
188
+ const instance = await WebAssembly.instantiate(module, imports);
189
+
190
+ if (instance instanceof WebAssembly.Instance) {
191
+ return { instance, module };
192
+ } else {
193
+ return instance;
194
+ }
195
+ }
196
+ }
197
+
198
+ function __wbg_get_imports() {
199
+ const imports = {};
200
+ imports.wbg = {};
201
+ imports.wbg.__wbg___wbindgen_string_get_a2a31e16edf96e42 = function(arg0, arg1) {
202
+ const obj = getObject(arg1);
203
+ const ret = typeof(obj) === 'string' ? obj : undefined;
204
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
205
+ var len1 = WASM_VECTOR_LEN;
206
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
207
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
208
+ };
209
+ imports.wbg.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) {
210
+ throw new Error(getStringFromWasm0(arg0, arg1));
211
+ };
212
+ imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
213
+ // Cast intrinsic for `Ref(String) -> Externref`.
214
+ const ret = getStringFromWasm0(arg0, arg1);
215
+ return addHeapObject(ret);
216
+ };
217
+ imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
218
+ takeObject(arg0);
219
+ };
220
+
221
+ return imports;
222
+ }
223
+
224
+ function __wbg_finalize_init(instance, module) {
225
+ wasm = instance.exports;
226
+ __wbg_init.__wbindgen_wasm_module = module;
227
+ cachedDataViewMemory0 = null;
228
+ cachedUint8ArrayMemory0 = null;
229
+
230
+
231
+
232
+ return wasm;
233
+ }
234
+
235
+ function initSync(module) {
236
+ if (wasm !== undefined) return wasm;
237
+
238
+
239
+ if (typeof module !== 'undefined') {
240
+ if (Object.getPrototypeOf(module) === Object.prototype) {
241
+ ({module} = module)
242
+ } else {
243
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
244
+ }
245
+ }
246
+
247
+ const imports = __wbg_get_imports();
248
+ if (!(module instanceof WebAssembly.Module)) {
249
+ module = new WebAssembly.Module(module);
250
+ }
251
+ const instance = new WebAssembly.Instance(module, imports);
252
+ return __wbg_finalize_init(instance, module);
253
+ }
254
+
255
+ async function __wbg_init(module_or_path) {
256
+ if (wasm !== undefined) return wasm;
257
+
258
+
259
+ if (typeof module_or_path !== 'undefined') {
260
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
261
+ ({module_or_path} = module_or_path)
262
+ } else {
263
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
264
+ }
265
+ }
266
+
267
+ if (typeof module_or_path === 'undefined') {
268
+ module_or_path = new URL('md2ast_bg.wasm', import.meta.url);
269
+ }
270
+ const imports = __wbg_get_imports();
271
+
272
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
273
+ module_or_path = fetch(module_or_path);
274
+ }
275
+
276
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
277
+
278
+ return __wbg_finalize_init(instance, module);
279
+ }
280
+
281
+ export { initSync };
282
+ export default __wbg_init;
package/md2ast_bg.wasm ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@clevertree/md2ast",
3
+ "type": "module",
4
+ "description": "Markdown → JSON AST for CleverScript / Relay hosts (WASM, JNI, Rust).",
5
+ "version": "1.0.0",
6
+ "license": "MIT OR Apache-2.0",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "files": [
11
+ "md2ast_bg.wasm",
12
+ "md2ast.js",
13
+ "md2ast.d.ts"
14
+ ],
15
+ "main": "md2ast.js",
16
+ "types": "md2ast.d.ts",
17
+ "scripts": {
18
+ "build": "wasm-pack build --release --target web --features wasm && cp pkg/md2ast.js pkg/md2ast.d.ts pkg/md2ast_bg.wasm .",
19
+ "test": "cargo test",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "devDependencies": {
23
+ "wasm-pack": "^0.12.1"
24
+ }
25
+ }