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