/**
* Markdown 渲染器配置
*/
import { SAFE_URI_SCHEMES } from './sanitizer.js';
// 简化的 Markdown 解析器(内联,不依赖外部 marked 库)
// 支持基本 GFM 语法:标题、粗体、斜体、代码块、链接、列表、表格
function parseMarkdown(md: string): string {
if (!md) return '';
let html = escapeForMd(md);
// 代码块 ```...```
const codeBlockRe = new RegExp('```(\\w*)\\n([\\s\\S]*?)```', 'g');
html = html.replace(codeBlockRe, (_m, lang, code) => {
return `
${code.trim()}
`;
});
// 行内代码
html = html.replace(/`([^`]+)`/g, '$1');
// 标题
html = html.replace(/^######\s+(.+)$/gm, '$1
');
html = html.replace(/^#####\s+(.+)$/gm, '$1
');
html = html.replace(/^####\s+(.+)$/gm, '$1
');
html = html.replace(/^###\s+(.+)$/gm, '$1
');
html = html.replace(/^##\s+(.+)$/gm, '$1
');
html = html.replace(/^#\s+(.+)$/gm, '$1
');
// 粗体+斜体
html = html.replace(/\*\*\*(.+?)\*\*\*/g, '$1');
// 粗体
html = html.replace(/\*\*(.+?)\*\*/g, '$1');
// 斜体
html = html.replace(/\*(.+?)\*/g, '$1');
// 删除线
html = html.replace(/~~(.+?)~~/g, '$1');
// 链接 [text](url)
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, text, href) => {
try {
const safe = SAFE_URI_SCHEMES.has(new URL(href, 'https://placeholder').protocol);
if (!safe) return `${text}`;
} catch { /* allow relative */ }
return `${text}`;
});
// 图片 
html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '
');
// 引用块
html = html.replace(/^>\s+(.+)$/gm, '$1
');
// 水平线
html = html.replace(/^---+$/gm, '
');
// 无序列表
html = html.replace(/^[\-\*]\s+(.+)$/gm, '$1');
html = html.replace(/((?:.*<\/li>\n?)+)/g, '');
// 有序列表
html = html.replace(/^\d+\.\s+(.+)$/gm, '$1');
// 换行
html = html.replace(/\n\n/g, '');
html = html.replace(/\n/g, '
');
// 包裹在 p 标签中
if (!html.startsWith('<')) {
html = '
' + html + '
';
}
return html;
}
function escapeForMd(str: string): string {
return str
.replace(/&/g, '&')
.replace(//g, '>');
}
export { parseMarkdown as marked };