import MarkdownIt from "markdown-it"; import type {RenderRule} from "markdown-it/lib/renderer.mjs"; import type Token from "markdown-it/lib/token.mjs"; import {defineMarkdownPlugin} from "../type/markdown.ts"; import {h} from "vue"; import VueCharts from "./VueCharts.vue"; // 验证JSON格式 function isValidJSON(str: string): boolean { try { JSON.parse(str) return true } catch { return false } } // 渲染echarts代码块 const renderEcharts: RenderRule = (tokens: Token[], idx: number) => { const token = tokens[idx] const content = token.content.trim() if (!content) { return '
ECharts配置不能为空
' } // 生成完整HTML return `` } const EChartsPlugin = defineMarkdownPlugin({ tagName: 'echarts-container', mdItPlugin: function (md: MarkdownIt) { // 保存原始的fence渲染器 const defaultRender = md.renderer.rules.fence ?? function (tokens, idx, options, _env, renderer) { return renderer.renderToken(tokens, idx, options) } // if (customElements.get('echarts-container') === undefined) { // customElements.define('echarts-container', EChartsElement, { extends: 'div' }) // } // 重写fence渲染器 md.renderer.rules.fence = function (tokens, idx, options, env, renderer) { const token = tokens[idx] const info = token.info ? token.info.trim() : '' // 检查是否是echarts代码块 if (info === 'echarts' && isValidJSON(token.content.trim())) { return renderEcharts(tokens, idx, options, env, renderer) } // 其他代码块使用默认渲染器 return defaultRender(tokens, idx, options, env, renderer) } }, renderer: (node: {attribs: Record}) => { return h(VueCharts, { data: node.attribs.data, charts: node.attribs.id, style: 'width: 100%;height: 350px;margin: 16px 0; border-radius: 6px' } ) } }) export default EChartsPlugin