import MarkdownIt from "markdown-it"; import type { RenderRule } from "markdown-it/lib/renderer.mjs"; import type Token from "markdown-it/lib/token.mjs"; import type { Options } from "markdown-it/lib/index.mjs"; import type Renderer from "markdown-it/lib/renderer.mjs"; import * as echarts from 'echarts' class EChartsElement extends HTMLDivElement { instance!: echarts.ECharts private resizeHandler!: () => void connectedCallback() { const config = decodeURIComponent(this.getAttribute('config') ?? '') ?? ''; let data: echarts.EChartsOption try { data = JSON.parse(config) } catch (e) { console.error(e) return } this.instance = echarts.init(this) this.instance.setOption(data) // 创建绑定了正确上下文的 resize 处理器 this.resizeHandler = () => { this.instance?.resize() } window.addEventListener('resize', this.resizeHandler) } disconnectedCallback() { // 清理 resize 事件监听器 if (this.resizeHandler) { window.removeEventListener('resize', this.resizeHandler) } // 销毁 ECharts 实例 if (this.instance) { this.instance.dispose() } } } export type EchartsPluginOptions = { } // 生成唯一ID function generateId(): string { return 'echarts-' + Math.random().toString(36).substring(2, 9) } // 验证JSON格式 function isValidJSON(str: string): boolean { try { JSON.parse(str) return true } catch { return false } } // 渲染echarts代码块 const renderEcharts: RenderRule = (tokens: Token[], idx: number, _options: Options, env: any, _self: Renderer) => { const token = tokens[idx] const content = token.content.trim() if (!content) { return '
ECharts配置不能为空
' } const id = generateId() const className = env.echartsClassName || 'echarts-container' // 生成完整HTML return `
` } // markdown-it插件 //@ts-ignore // eslint-disable-next-line no-unused-vars function echartsPlugin(md: MarkdownIt, options: EchartsPluginOptions = {}) { // 保存原始的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())) { console.log(`prepare renderer`,tokens,idx,options,env,renderer,tokens[idx]) return renderEcharts(tokens, idx, options, env, renderer) } // 其他代码块使用默认渲染器 return defaultRender(tokens, idx, options, env, renderer) } } export default echartsPlugin