markdown-it-echarts.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import MarkdownIt from "markdown-it";
  2. import type {RenderRule} from "markdown-it/lib/renderer.mjs";
  3. import type Token from "markdown-it/lib/token.mjs";
  4. import {defineMarkdownPlugin} from "../type/markdown.ts";
  5. import {h} from "vue";
  6. import VueCharts from "./VueCharts.vue";
  7. // 验证JSON格式
  8. function isValidJSON(str: string): boolean {
  9. try {
  10. JSON.parse(str)
  11. return true
  12. } catch {
  13. return false
  14. }
  15. }
  16. // 渲染echarts代码块
  17. const renderEcharts: RenderRule = (tokens: Token[], idx: number) => {
  18. const token = tokens[idx]
  19. const content = token.content.trim()
  20. if (!content) {
  21. return '<div style="padding: 16px;background-color: #fff5f5;border: 1px solid #fed7d7;border-radius: 6px;color: #c53030;margin: 16px 0;">ECharts配置不能为空</div>'
  22. }
  23. // 生成完整HTML
  24. return `<echarts-container style="width: 100%;height: 350px;margin: 16px 0; border-radius: 6px" data="${encodeURIComponent(content)}"></echarts-container>`
  25. }
  26. const EChartsPlugin = defineMarkdownPlugin({
  27. tagName: 'echarts-container',
  28. mdItPlugin: function (md: MarkdownIt) {
  29. // 保存原始的fence渲染器
  30. const defaultRender = md.renderer.rules.fence ?? function (tokens, idx, options, _env, renderer) {
  31. return renderer.renderToken(tokens, idx, options)
  32. }
  33. // if (customElements.get('echarts-container') === undefined) {
  34. // customElements.define('echarts-container', EChartsElement, { extends: 'div' })
  35. // }
  36. // 重写fence渲染器
  37. md.renderer.rules.fence = function (tokens, idx, options, env, renderer) {
  38. const token = tokens[idx]
  39. const info = token.info ? token.info.trim() : ''
  40. // 检查是否是echarts代码块
  41. if (info === 'echarts' && isValidJSON(token.content.trim())) {
  42. return renderEcharts(tokens, idx, options, env, renderer)
  43. }
  44. // 其他代码块使用默认渲染器
  45. return defaultRender(tokens, idx, options, env, renderer)
  46. }
  47. },
  48. renderer: (node: {attribs: Record<string, string>}) => {
  49. return h(VueCharts, {
  50. data: node.attribs.data,
  51. charts: node.attribs.id,
  52. style: 'width: 100%;height: 350px;margin: 16px 0; border-radius: 6px'
  53. }
  54. )
  55. }
  56. })
  57. export default EChartsPlugin