import { Component, Prop, State, Watch, h } from '@stencil/core'; import { marked } from 'marked'; @Component({ tag: 'internal-markdown-renderer', styleUrl: 'markdown-renderer.css', shadow: true }) export class InternalMarkdownRenderer { @Prop() content: string = ''; @Prop() enableTables: boolean = true; @Prop() enableTaskLists: boolean = true; @Prop() enableFootnotes: boolean = true; @Prop() highlightCode: boolean = true; @State() private renderedHtml: string = ''; async componentWillLoad() { await this.renderMarkdown(); } @Watch('content') async contentChanged() { await this.renderMarkdown(); } private async renderMarkdown() { if (!this.content) { this.renderedHtml = ''; return; } try { // 配置 marked marked.setOptions({ breaks: true, gfm: true, }); // 自定义渲染器 const renderer = new marked.Renderer(); // 链接渲染 renderer.link = (token) => { const href = token.href; const title = token.title ? ` title="${token.title}"` : ''; return `${token.text}`; }; // 图片渲染 renderer.image = (token) => { const src = token.href; const alt = token.text; const title = token.title ? ` title="${token.title}"` : ''; return `${alt}`; }; // 代码渲染 renderer.code = (token) => { const code = token.text; const lang = token.lang || ''; const className = lang ? `language-${lang}` : ''; return `
${code}
`; }; // 表格渲染 if (this.enableTables) { renderer.table = (token) => { let html = ''; // 表头 if (token.header) { html += ''; token.header.forEach(cell => { html += ``; }); html += ''; } // 表体 if (token.rows) { html += ''; token.rows.forEach(row => { html += ''; row.forEach(cell => { html += ``; }); html += ''; }); html += ''; } html += '
${cell}
${cell}
'; return html; }; } marked.use({ renderer }); const html = await marked(this.content); this.renderedHtml = html; } catch (error) { console.error('Markdown rendering error:', error); this.renderedHtml = this.content; } } render() { return (
); } }