/** * Simple Markdown Parser for Tinker Tickets * Supports basic markdown formatting without external dependencies */ function parseMarkdown(markdown) { if (!markdown) return ''; let html = markdown; // Escape HTML first to prevent XSS html = html.replace(/&/g, '&') .replace(//g, '>'); // Code blocks (```code```) html = html.replace(/```([\s\S]*?)```/g, '
$1');
// Inline code (`code`)
html = html.replace(/`([^`]+)`/g, '$1');
// Bold (**text** or __text__)
html = html.replace(/\*\*(.+?)\*\*/g, '$1');
html = html.replace(/__(.+?)__/g, '$1');
// Italic (*text* or _text_)
html = html.replace(/\*(.+?)\*/g, '$1');
html = html.replace(/_(.+?)_/g, '$1');
// Links [text](url)
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1');
// Headers (# H1, ## H2, etc.)
html = html.replace(/^### (.+)$/gm, '$1'); // Horizontal rules (--- or ***) html = html.replace(/^(?:---|___|\*\*\*)$/gm, '
'); // Wrap in paragraph if not already wrapped if (!html.startsWith('<')) { html = '
' + html + '
'; } return html; } // Apply markdown rendering to all elements with data-markdown attribute function renderMarkdownElements() { document.querySelectorAll('[data-markdown]').forEach(element => { const markdownText = element.getAttribute('data-markdown') || element.textContent; element.innerHTML = parseMarkdown(markdownText); }); } // Apply markdown to description and comments on page load document.addEventListener('DOMContentLoaded', renderMarkdownElements); // Expose for manual use window.parseMarkdown = parseMarkdown; window.renderMarkdownElements = renderMarkdownElements;