comparison markdown_converter/markdown_to_html.js @ 64:a30944e5719e

Added vibe coded markdown to html script since it is useful for me. Updated Dowa so that it can be compiled without dirnet for windows.
author June Park <parkjune1995@gmail.com>
date Tue, 23 Dec 2025 15:18:46 -0800
parents
children
comparison
equal deleted inserted replaced
63:fff1b048dda6 64:a30944e5719e
1 /**
2 * Simple Markdown to HTML Converter
3 * Supports: headers, bold, italic, links, lists, code blocks, line breaks
4 */
5
6 /**
7 * Create heading element (H1-H6)
8 * @param {string} text - The heading text
9 * @param {number} level - Heading level (1-6)
10 * @returns {HTMLElement}
11 */
12 function createHeadingElement(text, level) {
13 const h = document.createElement(`H${level}`);
14 const t = document.createTextNode(text.trim());
15 h.appendChild(t);
16 return h;
17 }
18
19 /**
20 * Create paragraph element
21 * @param {string} text - The paragraph text
22 * @returns {HTMLElement}
23 */
24 function createParagraphElement(text) {
25 const p = document.createElement("P");
26 p.innerHTML = processInlineMarkdown(text.trim());
27 return p;
28 }
29
30 /**
31 * Create link element
32 * @param {string} text - Link text
33 * @param {string} url - Link URL
34 * @returns {HTMLElement}
35 */
36 function createLinkElement(text, url) {
37 const a = document.createElement("A");
38 a.href = url;
39 a.textContent = text;
40 return a;
41 }
42
43 /**
44 * Create unordered list element
45 * @param {Array<string>} items - List items
46 * @returns {HTMLElement}
47 */
48 function createUnorderedList(items) {
49 const ul = document.createElement("UL");
50 items.forEach(item => {
51 const li = document.createElement("LI");
52 li.innerHTML = processInlineMarkdown(item.trim());
53 ul.appendChild(li);
54 });
55 return ul;
56 }
57
58 /**
59 * Create ordered list element
60 * @param {Array<string>} items - List items
61 * @returns {HTMLElement}
62 */
63 function createOrderedList(items) {
64 const ol = document.createElement("OL");
65 items.forEach(item => {
66 const li = document.createElement("LI");
67 li.innerHTML = processInlineMarkdown(item.trim());
68 ol.appendChild(li);
69 });
70 return ol;
71 }
72
73 /**
74 * Create code block element
75 * @param {string} code - Code content
76 * @returns {HTMLElement}
77 */
78 function createCodeBlock(code) {
79 const pre = document.createElement("PRE");
80 const codeEl = document.createElement("CODE");
81 codeEl.textContent = code;
82 pre.appendChild(codeEl);
83 return pre;
84 }
85
86 /**
87 * Create blockquote element
88 * @param {string} text - Quote text
89 * @returns {HTMLElement}
90 */
91 function createBlockquote(text) {
92 const blockquote = document.createElement("BLOCKQUOTE");
93 blockquote.innerHTML = processInlineMarkdown(text.trim());
94 return blockquote;
95 }
96
97 /**
98 * Create horizontal rule
99 * @returns {HTMLElement}
100 */
101 function createHorizontalRule() {
102 return document.createElement("HR");
103 }
104
105 /**
106 * Process inline markdown (bold, italic, code, links)
107 * @param {string} text - Text with inline markdown
108 * @returns {string} HTML string
109 */
110 function processInlineMarkdown(text) {
111 // Links: [text](url)
112 text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
113
114 // Images: ![alt](url)
115 text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1">');
116
117 // Bold: **text** or __text__
118 text = text.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
119 text = text.replace(/__([^_]+)__/g, '<strong>$1</strong>');
120
121 // Italic: *text* or _text_
122 text = text.replace(/\*([^*]+)\*/g, '<em>$1</em>');
123 text = text.replace(/_([^_]+)_/g, '<em>$1</em>');
124
125 // Inline code: `code`
126 const x = /`([^`]+)`/g;
127 text = text.replace(x, '<code>$1</code>');
128
129 // Strikethrough: ~~text~~
130 text = text.replace(/~~([^~]+)~~/g, '<del>$1</del>');
131
132 // Line breaks: two spaces at end of line
133 text = text.replace(/ \n/g, '<br>\n');
134
135 return text;
136 }
137
138 /**
139 * Main markdown converter function
140 * @param {string} value - Markdown string
141 * @returns {Array<HTMLElement>} Array of DOM elements
142 */
143 function markdownConverter(value) {
144 const lines = value.split('\n');
145 const domElements = [];
146 let i = 0;
147
148 while (i < lines.length) {
149 const line = lines[i];
150 const trimmedLine = line.trim();
151
152 // Skip empty lines
153 if (trimmedLine === '') {
154 i++;
155 continue;
156 }
157
158 if (trimmedLine.startsWith('#'))
159 {
160 const match = trimmedLine.match(/^(#{1,6})\s+(.+)$/);
161 if (match) {
162 const level = match[1].length;
163 const text = match[2];
164 domElements.push(createHeadingElement(text, level));
165 i++;
166 continue;
167 }
168 }
169
170 if (trimmedLine.startsWith('```')) {
171 let codeContent = '';
172 i++; // Skip opening ```
173 while (i < lines.length && !lines[i].trim().startsWith('```')) {
174 codeContent += lines[i] + '\n';
175 i++;
176 }
177 domElements.push(createCodeBlock(codeContent));
178 i++; // Skip closing ```
179 continue;
180 }
181
182 // Blockquote: >
183 if (trimmedLine.startsWith('>')) {
184 let quoteContent = '';
185 while (i < lines.length && lines[i].trim().startsWith('>')) {
186 quoteContent += lines[i].trim().substring(1).trim() + ' ';
187 i++;
188 }
189 domElements.push(createBlockquote(quoteContent));
190 continue;
191 }
192
193 // Horizontal rule: ---, ***, ___
194 if (trimmedLine.match(/^(-{3,}|\*{3,}|_{3,})$/)) {
195 domElements.push(createHorizontalRule());
196 i++;
197 continue;
198 }
199
200 // Unordered list: -, *, +
201 if (trimmedLine.match(/^[-*+]\s+/)) {
202 const listItems = [];
203 while (i < lines.length && lines[i].trim().match(/^[-*+]\s+/)) {
204 listItems.push(lines[i].trim().substring(2));
205 i++;
206 }
207 domElements.push(createUnorderedList(listItems));
208 continue;
209 }
210
211 // Ordered list: 1., 2., etc.
212 if (trimmedLine.match(/^\d+\.\s+/)) {
213 const listItems = [];
214 while (i < lines.length && lines[i].trim().match(/^\d+\.\s+/)) {
215 listItems.push(lines[i].trim().replace(/^\d+\.\s+/, ''));
216 i++;
217 }
218 domElements.push(createOrderedList(listItems));
219 continue;
220 }
221
222 // Regular paragraph
223 let paragraphContent = '';
224 while (i < lines.length && lines[i].trim() !== '' &&
225 !lines[i].trim().match(/^(#{1,6}\s|[-*+]\s|\d+\.\s|>|```|---|\*\*\*|___)/)) {
226 paragraphContent += lines[i] + ' ';
227 i++;
228 }
229 if (paragraphContent.trim()) {
230 domElements.push(createParagraphElement(paragraphContent));
231 }
232 }
233
234 return domElements;
235 }
236
237 /**
238 * Helper function to append all elements to a container
239 * @param {HTMLElement} container - Container element
240 * @param {string} markdown - Markdown string
241 */
242 function renderMarkdown(container, markdown) {
243 const elements = markdownConverter(markdown);
244 elements.forEach(el => container.appendChild(el));
245 }
246
247 // Example usage:
248 // const markdown = `
249 // # Heading 1
250 // ## Heading 2
251 //
252 // This is a paragraph with **bold** and *italic* text.
253 //
254 // - List item 1
255 // - List item 2
256 //
257 // 1. Ordered item 1
258 // 2. Ordered item 2
259 //
260 // [Link text](https://example.com)
261 // `;
262 //
263 // const container = document.getElementById('content');
264 // renderMarkdown(container, markdown);
265
266 // Export for use in other files
267 if (typeof module !== 'undefined' && module.exports) {
268 module.exports = { markdownConverter, renderMarkdown };
269 }