diff --git a/assets/js/base.js b/assets/js/base.js index 9778205..329f022 100644 --- a/assets/js/base.js +++ b/assets/js/base.js @@ -2930,73 +2930,6 @@ }, }; - /* ================================================================ - MODULE 54 — MARKDOWN RENDERER - lt.markdown.render(mdString) → HTML string (sanitized) - lt.markdown.init(selector) → renders all matching el's .textContent - Uses a built-in micro-renderer (no deps) for common syntax. - For full GFM, swap in marked.js: window.marked && marked.parse() - ================================================================ */ - const markdown = { - render(md) { - // Always use the built-in XSS-safe micro-renderer. Do NOT delegate to - // window.marked / window.markdownit: their raw HTML output is not sanitized - // here, so delegating would enable stored XSS if such a lib were ever loaded. - // Micro-renderer: covers headings, bold, italic, code, links, lists, blockquote, hr - let html = escHtml(md) - // Fenced code blocks - .replace(/```(\w*)\n([\s\S]*?)```/g, (_, lang, code) => `
${code.trim()}
`) - // Inline code - .replace(/`([^`]+)`/g, '$1') - // Headings - .replace(/^######\s(.+)$/gm, '
$1
') - .replace(/^#####\s(.+)$/gm, '
$1
') - .replace(/^####\s(.+)$/gm, '

$1

') - .replace(/^###\s(.+)$/gm, '

$1

') - .replace(/^##\s(.+)$/gm, '

$1

') - .replace(/^#\s(.+)$/gm, '

$1

') - // Bold / italic - .replace(/\*\*\*(.+?)\*\*\*/g, '$1') - .replace(/\*\*(.+?)\*\*/g, '$1') - .replace(/\*(.+?)\*/g, '$1') - .replace(/__(.+?)__/g, '$1') - .replace(/_(.+?)_/g, '$1') - // Links — block javascript: and data: URIs - .replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => { - const safeUrl = /^(https?:\/\/|\/|#|\.\.?\/)/i.test(url) ? url : '#'; - return `${escHtml(text)}`; - }) - // Images — block javascript: and data: URIs - .replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_, alt, src) => { - const safeSrc = /^(https?:\/\/|\/|\.\.?\/)/i.test(src) ? src : ''; - return `${escHtml(alt)}`; - }) - // Blockquote - .replace(/^>\s(.+)$/gm, '
$1
') - // Horizontal rule - .replace(/^(-{3,}|\*{3,}|_{3,})$/gm, '
') - // Unordered list items - .replace(/^[-*+]\s(.+)$/gm, '
  • $1
  • ') - .replace(/(
  • [\s\S]+?<\/li>\n?)+/g, m => ``) - // Ordered list items - .replace(/^\d+\.\s(.+)$/gm, '
  • $1
  • ') - // Paragraphs (double newline) - .replace(/\n{2,}/g, '

    ') - .replace(/\n/g, '
    '); - return `

    ${html}

    ` - .replace(/

    (<(?:pre|ul|ol|h[1-6]|blockquote|hr)[^>]*>)/g, '$1') - .replace(/(<\/(?:pre|ul|ol|h[1-6]|blockquote|hr)>)<\/p>/g, '$1'); - }, - - init(selector) { - document.querySelectorAll(selector).forEach(el => { - const raw = el.getAttribute('data-markdown') || el.textContent; - el.innerHTML = markdown.render(raw); - el.classList.add('lt-markdown'); - }); - }, - }; - /* ================================================================ MODULE 55 — PAGINATION lt.pagination.init(navEl, opts) @@ -3159,7 +3092,6 @@ timer, lightbox, auth, - markdown, ticketStatus, pagination, sidebarSubmenus: { init: initSidebarSubmenus },