Files
metona-ollama-desktop/src/renderer/utils/marked-config.ts
T
thzxx 8805858b79 refactor: 第三方库替换 & 代码精简 — v5.1.5
- Markdown 解析器:内联正则 → marked 库(完整 GFM 支持)
- HTML 净化器:内联 DOM 遍历 → DOMPurify(业界标准)
- crypto.ts:删除 sha256js/xorBytes 死代码回退路径
- 消除 5 个文件中 escapeHtml/formatSize 重复定义
- 版本号升级至 5.1.5
2026-04-19 20:48:56 +08:00

47 lines
1.3 KiB
TypeScript

/**
* Markdown 渲染器配置 — 基于 marked 库
*/
import { marked as markedLib, Renderer } from 'marked';
import { sanitize } from './sanitizer.js';
// 自定义渲染器:链接安全检查
const renderer = new Renderer();
const SAFE_SCHEMES = new Set(['http:', 'https:', 'mailto:', 'tel:', 'ftp:', 'ftps:', 'xmpp:']);
renderer.link = function ({ href, text, tokens }) {
try {
const protocol = new URL(href, 'https://placeholder').protocol;
if (!SAFE_SCHEMES.has(protocol)) {
return `<span class="blocked-link">${text}</span>`;
}
} catch { /* 允许相对路径 */ }
return `<a href="${href}" target="_blank" rel="noopener noreferrer">${text}</a>`;
};
renderer.image = function ({ href, text }) {
try {
const protocol = new URL(href, 'https://placeholder').protocol;
if (!SAFE_SCHEMES.has(protocol)) {
return `<span class="blocked-link">${text || '图片'}</span>`;
}
} catch { /* 允许相对路径 */ }
return `<img src="${href}" alt="${text || ''}" loading="lazy">`;
};
// 配置 marked
markedLib.use({
renderer,
gfm: true,
breaks: true,
});
/**
* 解析 Markdown 并净化 HTML 输出
*/
export function marked(md: string): string {
if (!md) return '';
const raw = markedLib.parse(md) as string;
return sanitize(raw);
}