Spaces:
Sleeping
Sleeping
| /** | |
| * Markdown渲染器库(支持HTML标签) | |
| * 依赖: | |
| * - markdown-it | |
| * - highlight.js | |
| * - clipboard.js | |
| */ | |
| const MarkdownRenderer = (function () { | |
| // 初始化 markdown-it 实例,启用 HTML 支持 | |
| hljs.configure({ | |
| ignoreUnescapedHTML: true | |
| }); | |
| const md = window.markdownit({ | |
| html: true, // 启用HTML标签支持 | |
| breaks: true, | |
| xhtmlOut: true, | |
| typographer: true, // 启用智能标点转换 | |
| highlight: function (str, lang) { | |
| if (lang && hljs.getLanguage(lang)) { | |
| try { | |
| return hljs.highlight(str, { language: lang }).value; | |
| } catch (__) { } | |
| } | |
| return hljs.highlight(str, { language: 'plaintext' }).value; | |
| } | |
| }); | |
| /** | |
| * 渲染Markdown内容为HTML | |
| * @param {string} content - Markdown格式的内容 | |
| * @returns {string} 渲染后的HTML字符串 | |
| */ | |
| function renderMessage(content) { | |
| // 处理有序列表 | |
| content = content.replace(/(\d+)\.\s/g, ' $1\\. '); | |
| // 渲染markdown内容 | |
| let renderedContent = md.render(content); | |
| // 创建临时容器 | |
| const container = document.createElement('div'); | |
| container.innerHTML = renderedContent; | |
| // 处理代码块 | |
| container.querySelectorAll('pre code').forEach((block) => { | |
| const pre = block.parentNode; | |
| const lang = block.className.split('-')[1] || 'plaintext'; | |
| // 生成唯一ID | |
| pre.id = 'code-' + Math.random().toString(36).substr(2, 9); | |
| // 创建代码头部 | |
| const header = document.createElement('div'); | |
| header.className = 'code-header bg-gradient-to-b from-gray-900 via-gray-800 to-gray-700 text-white rounded-lg rounded-br-none rounded-bl-none'; | |
| header.innerHTML = ` | |
| <div style="margin-left: 8px;"> | |
| <span class="code-language">${lang}</span> | |
| <button class="copy-button" data-clipboard-target="#${pre.id}">✄</button> | |
| </div> | |
| `; | |
| // 添加样式类 | |
| pre.classList.add('code-block', 'rounded-tr-none', 'rounded-tl-none'); | |
| pre.parentNode.insertBefore(header, pre); | |
| // 代码高亮 | |
| hljs.highlightElement(block); | |
| // 初始化复制功能 | |
| setTimeout(() => { | |
| const clipboard = new ClipboardJS('.copy-button'); | |
| clipboard.on('success', function (e) { | |
| e.trigger.textContent = '♫'; | |
| setTimeout(() => { | |
| e.trigger.textContent = '✄'; | |
| }, 1000); | |
| e.clearSelection(); | |
| }); | |
| clipboard.on('error', function (e) { | |
| console.error('Copy failed!'); | |
| }); | |
| }, 0); | |
| }); | |
| // 不再需要转换HTML实体,因为我们现在允许HTML标签 | |
| return container.innerHTML; | |
| } | |
| // 只暴露需要的方法 | |
| return { | |
| render: renderMessage | |
| }; | |
| })(); | |
| // 支持 CommonJS | |
| if (typeof module !== 'undefined' && module.exports) { | |
| module.exports = MarkdownRenderer; | |
| } | |
| // 支持 ES6 模块 | |
| if (typeof exports !== 'undefined') { | |
| exports.default = MarkdownRenderer; | |
| } | |
| // 支持全局变量 | |
| if (typeof window !== 'undefined') { | |
| window.MarkdownRenderer = MarkdownRenderer; | |
| } |