Mercurial
view markdown_converter/markdown_to_html.js @ 136:75c144fd6964
[MrJuneJune] Fix the js file to hit correct endpoints.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Fri, 09 Jan 2026 11:21:54 -0800 |
| parents | a30944e5719e |
| children |
line wrap: on
line source
/** * Simple Markdown to HTML Converter * Supports: headers, bold, italic, links, lists, code blocks, line breaks */ /** * Create heading element (H1-H6) * @param {string} text - The heading text * @param {number} level - Heading level (1-6) * @returns {HTMLElement} */ function createHeadingElement(text, level) { const h = document.createElement(`H${level}`); const t = document.createTextNode(text.trim()); h.appendChild(t); return h; } /** * Create paragraph element * @param {string} text - The paragraph text * @returns {HTMLElement} */ function createParagraphElement(text) { const p = document.createElement("P"); p.innerHTML = processInlineMarkdown(text.trim()); return p; } /** * Create link element * @param {string} text - Link text * @param {string} url - Link URL * @returns {HTMLElement} */ function createLinkElement(text, url) { const a = document.createElement("A"); a.href = url; a.textContent = text; return a; } /** * Create unordered list element * @param {Array<string>} items - List items * @returns {HTMLElement} */ function createUnorderedList(items) { const ul = document.createElement("UL"); items.forEach(item => { const li = document.createElement("LI"); li.innerHTML = processInlineMarkdown(item.trim()); ul.appendChild(li); }); return ul; } /** * Create ordered list element * @param {Array<string>} items - List items * @returns {HTMLElement} */ function createOrderedList(items) { const ol = document.createElement("OL"); items.forEach(item => { const li = document.createElement("LI"); li.innerHTML = processInlineMarkdown(item.trim()); ol.appendChild(li); }); return ol; } /** * Create code block element * @param {string} code - Code content * @returns {HTMLElement} */ function createCodeBlock(code) { const pre = document.createElement("PRE"); const codeEl = document.createElement("CODE"); codeEl.textContent = code; pre.appendChild(codeEl); return pre; } /** * Create blockquote element * @param {string} text - Quote text * @returns {HTMLElement} */ function createBlockquote(text) { const blockquote = document.createElement("BLOCKQUOTE"); blockquote.innerHTML = processInlineMarkdown(text.trim()); return blockquote; } /** * Create horizontal rule * @returns {HTMLElement} */ function createHorizontalRule() { return document.createElement("HR"); } /** * Process inline markdown (bold, italic, code, links) * @param {string} text - Text with inline markdown * @returns {string} HTML string */ function processInlineMarkdown(text) { // Links: [text](url) text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>'); // Images:  text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1">'); // Bold: **text** or __text__ text = text.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>'); text = text.replace(/__([^_]+)__/g, '<strong>$1</strong>'); // Italic: *text* or _text_ text = text.replace(/\*([^*]+)\*/g, '<em>$1</em>'); text = text.replace(/_([^_]+)_/g, '<em>$1</em>'); // Inline code: `code` const x = /`([^`]+)`/g; text = text.replace(x, '<code>$1</code>'); // Strikethrough: ~~text~~ text = text.replace(/~~([^~]+)~~/g, '<del>$1</del>'); // Line breaks: two spaces at end of line text = text.replace(/ \n/g, '<br>\n'); return text; } /** * Main markdown converter function * @param {string} value - Markdown string * @returns {Array<HTMLElement>} Array of DOM elements */ function markdownConverter(value) { const lines = value.split('\n'); const domElements = []; let i = 0; while (i < lines.length) { const line = lines[i]; const trimmedLine = line.trim(); // Skip empty lines if (trimmedLine === '') { i++; continue; } if (trimmedLine.startsWith('#')) { const match = trimmedLine.match(/^(#{1,6})\s+(.+)$/); if (match) { const level = match[1].length; const text = match[2]; domElements.push(createHeadingElement(text, level)); i++; continue; } } if (trimmedLine.startsWith('```')) { let codeContent = ''; i++; // Skip opening ``` while (i < lines.length && !lines[i].trim().startsWith('```')) { codeContent += lines[i] + '\n'; i++; } domElements.push(createCodeBlock(codeContent)); i++; // Skip closing ``` continue; } // Blockquote: > if (trimmedLine.startsWith('>')) { let quoteContent = ''; while (i < lines.length && lines[i].trim().startsWith('>')) { quoteContent += lines[i].trim().substring(1).trim() + ' '; i++; } domElements.push(createBlockquote(quoteContent)); continue; } // Horizontal rule: ---, ***, ___ if (trimmedLine.match(/^(-{3,}|\*{3,}|_{3,})$/)) { domElements.push(createHorizontalRule()); i++; continue; } // Unordered list: -, *, + if (trimmedLine.match(/^[-*+]\s+/)) { const listItems = []; while (i < lines.length && lines[i].trim().match(/^[-*+]\s+/)) { listItems.push(lines[i].trim().substring(2)); i++; } domElements.push(createUnorderedList(listItems)); continue; } // Ordered list: 1., 2., etc. if (trimmedLine.match(/^\d+\.\s+/)) { const listItems = []; while (i < lines.length && lines[i].trim().match(/^\d+\.\s+/)) { listItems.push(lines[i].trim().replace(/^\d+\.\s+/, '')); i++; } domElements.push(createOrderedList(listItems)); continue; } // Regular paragraph let paragraphContent = ''; while (i < lines.length && lines[i].trim() !== '' && !lines[i].trim().match(/^(#{1,6}\s|[-*+]\s|\d+\.\s|>|```|---|\*\*\*|___)/)) { paragraphContent += lines[i] + ' '; i++; } if (paragraphContent.trim()) { domElements.push(createParagraphElement(paragraphContent)); } } return domElements; } /** * Helper function to append all elements to a container * @param {HTMLElement} container - Container element * @param {string} markdown - Markdown string */ function renderMarkdown(container, markdown) { const elements = markdownConverter(markdown); elements.forEach(el => container.appendChild(el)); } // Example usage: // const markdown = ` // # Heading 1 // ## Heading 2 // // This is a paragraph with **bold** and *italic* text. // // - List item 1 // - List item 2 // // 1. Ordered item 1 // 2. Ordered item 2 // // [Link text](https://example.com) // `; // // const container = document.getElementById('content'); // renderMarkdown(container, markdown); // Export for use in other files if (typeof module !== 'undefined' && module.exports) { module.exports = { markdownConverter, renderMarkdown }; }