import { Marked } from 'marked'; import {createDirectives, presetDirectiveConfigs} from 'marked-directive'; import yaml from 'js-yaml'; import markedAlert from "marked-alert"; // 使用 marked-directive 来支持指令语法 const marked = new Marked() .use(markedAlert()) .use(createDirectives([ ...presetDirectiveConfigs, { marker: '::::', level: 'container' }, { marker: ':::::', level: 'container' }, { level: 'inline', marker: ':', // :[blah] becomes renderer(token) { if (!token.meta.name) { return ``; } return false; } }, ]), { // 自定义代码块渲染器,支持 yaml/tag 格式 extensions: [{ name: 'code-block-yaml-tag', level: 'block', start(src: string) { // 检测 ```yaml/tag 开头的代码块 return src.match(/^```yaml\/tag\s*\n/m)?.index; }, tokenizer(src: string) { const rule = /^```yaml\/tag\s*\n([\s\S]*?)\n```/; const match = rule.exec(src); if (match) { const yamlContent = match[1]?.trim() || ''; const props = yaml.load(yamlContent) as Record || {}; // 提取 tag 名称,默认为 tag-unknown const tagName = (props.tag as string) || 'tag-unknown'; // 移除 tag 属性,剩下的作为 HTML 属性 const { tag, ...rest } = props; // 提取 innerText 内容(如果有 body 字段) let content = ''; if ('body' in rest) { content = String(rest.body || ''); delete (rest as Record).body; } // 构建属性字符串 const propsStr = Object.entries(rest) .map(([key, value]) => { const strValue = String(value); // 如果值包含空格或特殊字符,添加引号 if (strValue.includes(' ') || strValue.includes('"')) { return `${key}="${strValue.replace(/"/g, '"')}"`; } return `${key}="${strValue}"`; }) .join(' '); return { type: 'code-block-yaml-tag', raw: match[0], tagName, props: propsStr, content }; } }, renderer(token: any) { // 渲染为自定义 HTML 标签 const propsAttr = token.props ? ` ${token.props}` : ''; return `<${token.tagName}${propsAttr}>${token.content || ''}\n`; } }] }); export function parseMarkdown(content: string): string { return marked.parse(content.trimStart()) as string; } export { marked };