Mercurial
comparison markdown_converter/markdown_to_html_wasm.js @ 154:bdcc610eeed8
[Markdown Converter][GuiZe] Added markdown coverter in C and wasm rule sets. Needs further view on this as I haven't taken a look. Written by Claude.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Mon, 12 Jan 2026 09:11:58 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 153:790930d9bb90 | 154:bdcc610eeed8 |
|---|---|
| 1 /** | |
| 2 * Markdown to HTML Converter - WASM FFI Wrapper | |
| 3 * Loads the C implementation via WebAssembly and provides JavaScript API | |
| 4 * | |
| 5 * Build the WASM with: bazel build //markdown_converter:markdown_to_html_wasm | |
| 6 */ | |
| 7 | |
| 8 class MarkdownConverterWasm { | |
| 9 constructor() { | |
| 10 this.wasm = undefined; | |
| 11 this.ready = false; | |
| 12 } | |
| 13 | |
| 14 /** | |
| 15 * Initialize the WASM module | |
| 16 * @param {string} wasmPath - Path to the .wasm file | |
| 17 * @returns {Promise<void>} | |
| 18 */ | |
| 19 async init(wasmPath = '/markdown_to_html_wasm.wasm') { | |
| 20 if (this.ready) return; | |
| 21 | |
| 22 try { | |
| 23 this.wasm = await WebAssembly.instantiateStreaming(fetch(wasmPath), { | |
| 24 env: {} | |
| 25 }); | |
| 26 this.ready = true; | |
| 27 } catch (err) { | |
| 28 console.error('Failed to load markdown WASM module:', err); | |
| 29 throw err; | |
| 30 } | |
| 31 } | |
| 32 | |
| 33 /** | |
| 34 * Write string to WASM memory | |
| 35 * @private | |
| 36 */ | |
| 37 _writeString(str) { | |
| 38 const encoder = new TextEncoder(); | |
| 39 const bytes = encoder.encode(str + '\0'); | |
| 40 const ptr = this.wasm.instance.exports.malloc(bytes.length); | |
| 41 const memory = new Uint8Array(this.wasm.instance.exports.memory.buffer); | |
| 42 memory.set(bytes, ptr); | |
| 43 return ptr; | |
| 44 } | |
| 45 | |
| 46 /** | |
| 47 * Read string from WASM memory | |
| 48 * @private | |
| 49 */ | |
| 50 _readString(ptr) { | |
| 51 const memory = new Uint8Array(this.wasm.instance.exports.memory.buffer); | |
| 52 let end = ptr; | |
| 53 while (memory[end] !== 0) end++; | |
| 54 const bytes = memory.slice(ptr, end); | |
| 55 const decoder = new TextDecoder(); | |
| 56 return decoder.decode(bytes); | |
| 57 } | |
| 58 | |
| 59 /** | |
| 60 * Reset the WASM heap (call between conversions to reclaim memory) | |
| 61 */ | |
| 62 resetHeap() { | |
| 63 if (this.ready) { | |
| 64 this.wasm.instance.exports.heap_reset(); | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 /** | |
| 69 * Convert markdown string to HTML string using WASM | |
| 70 * @param {string} markdown - The markdown text to convert | |
| 71 * @returns {string} The converted HTML | |
| 72 */ | |
| 73 convert(markdown) { | |
| 74 if (!this.ready) { | |
| 75 throw new Error('WASM module not initialized. Call init() first.'); | |
| 76 } | |
| 77 | |
| 78 // Reset heap before each conversion to reclaim memory | |
| 79 this.resetHeap(); | |
| 80 | |
| 81 // Write markdown to WASM memory | |
| 82 const inputPtr = this._writeString(markdown); | |
| 83 | |
| 84 // Call the C function | |
| 85 const outputPtr = this.wasm.instance.exports.markdown_to_html(inputPtr); | |
| 86 | |
| 87 // Read the result | |
| 88 const html = this._readString(outputPtr); | |
| 89 | |
| 90 return html; | |
| 91 } | |
| 92 | |
| 93 /** | |
| 94 * Convert markdown to DOM elements (compatible with original API) | |
| 95 * @param {string} markdown - The markdown text to convert | |
| 96 * @returns {Array<HTMLElement>} Array of DOM elements | |
| 97 */ | |
| 98 convertToElements(markdown) { | |
| 99 const html = this.convert(markdown); | |
| 100 const template = document.createElement('template'); | |
| 101 template.innerHTML = html; | |
| 102 return Array.from(template.content.children); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 // Singleton instance | |
| 107 const markdownWasm = new MarkdownConverterWasm(); | |
| 108 | |
| 109 /** | |
| 110 * Convert markdown to DOM elements (WASM version) | |
| 111 * Compatible with original markdownConverter() API | |
| 112 * @param {string} value - Markdown string | |
| 113 * @returns {Promise<Array<HTMLElement>>} Array of DOM elements | |
| 114 */ | |
| 115 async function markdownConverterWasm(value) { | |
| 116 if (!markdownWasm.ready) { | |
| 117 await markdownWasm.init(); | |
| 118 } | |
| 119 return markdownWasm.convertToElements(value); | |
| 120 } | |
| 121 | |
| 122 /** | |
| 123 * Render markdown to a container element (WASM version) | |
| 124 * Compatible with original renderMarkdown() API | |
| 125 * @param {HTMLElement} container - Container element | |
| 126 * @param {string} markdown - Markdown string | |
| 127 */ | |
| 128 async function renderMarkdownWasm(container, markdown) { | |
| 129 if (!markdownWasm.ready) { | |
| 130 await markdownWasm.init(); | |
| 131 } | |
| 132 container.innerHTML = markdownWasm.convert(markdown); | |
| 133 } | |
| 134 | |
| 135 // Export for use in other files | |
| 136 if (typeof module !== 'undefined' && module.exports) { | |
| 137 module.exports = { | |
| 138 MarkdownConverterWasm, | |
| 139 markdownWasm, | |
| 140 markdownConverterWasm, | |
| 141 renderMarkdownWasm | |
| 142 }; | |
| 143 } |