import { remark } from 'remark' import remarkHtml from 'remark-html' import remarkGfm from 'remark-gfm' // Simple markdown processor with clean output const processor = remark() .use(remarkGfm) // Support for GitHub Flavored Markdown (tables, strikethrough, etc.) // Das Ergebnis geht über dangerouslySetInnerHTML in die öffentliche Seite. // Das Standard-Schema lässt Überschriften, Listen, Tabellen und http(s)- bzw. // mailto-Links durch und entfernt Skripte, Event-Attribute, eingebettete // Rahmen und javascript:-Ziele. .use(remarkHtml, { sanitize: true }) /** * Maskiert Text für die Ausgabe in HTML. Für Werte, die nicht durch den * Markdown-Prozessor laufen – etwa Titel in der Druckfassung. */ export function escapeHtml(value: string): string { return String(value) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, ''') } export async function markdownToHtml(markdown: string): Promise { if (!markdown || typeof markdown !== 'string') { return '' } try { // Simple preprocessing for line breaks const preprocessed = simplePreprocessLineBreaks(markdown) const result = await processor.process(preprocessed) return wrapTables(result.toString()) } catch (error) { console.error('Error processing markdown:', error) // Fallback: return sanitized markdown with basic formatting return sanitizeAndFormatMarkdown(markdown) } } // Synchronous version for use in components that can't use async export function markdownToHtmlSync(markdown: string): string { if (!markdown || typeof markdown !== 'string') { return '' } try { // Simple preprocessing for line breaks const preprocessed = simplePreprocessLineBreaks(markdown) const result = processor.processSync(preprocessed) return wrapTables(result.toString()) } catch (error) { console.error('Error processing markdown synchronously:', error) // Fallback: return sanitized markdown with basic formatting return sanitizeAndFormatMarkdown(markdown) } } // Simple preprocessing for consistent line breaks function simplePreprocessLineBreaks(markdown: string): string { return markdown // Normalize line endings .replace(/\r\n/g, '\n') .replace(/\r/g, '\n') // Add two spaces before single line breaks for hard breaks .replace(/([^\n])\n([^\n])/g, '$1 \n$2') } // Fallback function for basic markdown formatting function sanitizeAndFormatMarkdown(text: string): string { return "

" + escapeHtml(text).replace(/\n/g, "
") + "

" } function wrapTables(html: string) { return html.replace(//g, '
').replace(/<\/table>/g, "
") }