Markdown
The Markdown component's core is built on the unified and remark ecosystem. It parses Markdown text into an AST (Abstract Syntax Tree) and leverages Vue's rendering mechanism to convert it into DOM nodes. This architecture design gives the component extremely high flexibility, supporting Slots and custom component rendering to meet complex business requirements.
Features:
- Core Engine: Based on
unifiedandremark, providing precise parsing and a rich ecosystem. - Vue Rendering: Uses Vue to render AST, supporting seamless embedding of Vue components and slots.
- Built-in Support: Default support for math formulas (KaTeX), code highlighting, Mermaid flowcharts/sequence diagrams, etc.
- Extensibility: Supports custom extensions, easily integrating third-party chart libraries like ECharts.
- Component Decomposition: Markdown breaks down basic Code Highlighting and Mermaid into two separate components.
Basic Usage
Basic Mathematical Formulas
Slot - Custom Toolbar
Slot - Custom Code Block Using ECharts
Custom ECharts File Example ./echarts-test.vue
vue
<template>
<div
ref="echartsDom"
style="width: 100%; height: 400px; margin: 16px 0"
></div>
</template>
<script setup lang="ts">
import { computed, onMounted, onUnmounted, useTemplateRef, watch } from 'vue'
import JSON5 from 'json5'
import * as echarts from 'echarts'
const props = defineProps({
content: {
type: String,
required: true,
},
theme: {
type: String,
default: 'light',
},
})
let myChart: echarts.ECharts | null = null
const echartsDom = useTemplateRef('echartsDom')
const options = computed(() => {
const regex = /option\s*=\s*({[\s\S]*});?$/
const match = props.content.trim().match(regex)
if (match) {
try {
return JSON5.parse(match[1])
} catch (e) {
return null
}
}
})
const renderChart = () => {
if (!echartsDom.value) return
if (!myChart) {
myChart = echarts.init(echartsDom.value, props.theme)
}
if (options.value) {
myChart.setTheme(props.theme === 'dark' ? 'dark' : 'default')
myChart.setOption(options.value)
}
}
const handleResize = () => {
myChart?.resize()
}
watch([options, () => props.theme], () => {
renderChart()
})
onMounted(() => {
renderChart()
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
if (myChart) {
myChart.dispose()
myChart = null
}
window.removeEventListener('resize', handleResize)
})
</script>
<style scoped></style>Typewriter Output
Props
| Property | Description | Type | Default |
|---|---|---|---|
| theme | Theme mode | 'dark' | 'light' | 'light' |
| content | Markdown content | string | '' |
| remarkPlugins | Custom remark plugins | MiddlewarePluginItem[] | [] |
| codeHighlightProps | Props passed to CodeHighlight component | CodeHighlightPropsType | {} |
| codeMermaidProps | Props passed to CodeMermaid component | CodeMermaidPropsType | {} |
Slots
| Slot Name | Description | Parameters |
|---|---|---|
| mermaid | Custom Mermaid code block render | { content, language, theme, ...codeMermaidProps } |
| code-mermaid-toolbar | Custom Mermaid toolbar | See CodeMermaid component docs |
| code-mermaid-fullscreen-toolbar | Custom Mermaid fullscreen toolbar | See CodeMermaid component docs |
| code | Custom code block render | { content, language, theme, ...codeHighlightProps } |
| code-highlight-header | Custom code block header | See CodeHighlight component docs |