import { Marked } from 'marked'; import TurndownService from 'turndown'; import hljs from 'highlight.js'; import { markedHighlight } from 'marked-highlight'; // import { marked } from 'marked'; const markedAndHighlight = new Marked( markedHighlight({ emptyLangClass: 'hljs', langPrefix: 'hljs language-', highlight(code, lang, info) { const language = hljs.getLanguage(lang) ? lang : 'plaintext'; return hljs.highlight(code, { language }).value; }, }), ); export const md2html = async (md: string) => { const html = markedAndHighlight.parse(md); return html; }; export const html2md = async (html: string, opts?: TurndownService.Options) => { const turndownService = new TurndownService({ ...opts }); // 添加代码块规则,保留语言标记 turndownService.addRule('codeBlocks', { filter: function (node) { return node.nodeName === 'PRE' && node.firstChild?.nodeName === 'CODE'; }, replacement: function (content, node) { const code = node.firstChild as HTMLElement; // 从类名中提取语言 (hljs language-xxx) const className = code.className || ''; const language = className.match(/language-(\w+)/)?.[1] || ''; // 确保内容首尾没有多余空行 const trimmedContent = content.trim(); return `\n\n\`\`\`${language}\n${trimmedContent}\n\`\`\`\n\n`; }, }); const md = turndownService.turndown(html); return md; };