XMarkdown Rendering Component ๐ โ
Introduction โ
The XMarkdown
component has built-in basic styles such as inline code, code blocks, mathematical formula functions (inline/block), mermaid charts, etc.
๐ Info
โ ๏ธ In this development documentation, some style demonstrations may not be very good, but it should not affect the integrated usage. If there are integration or usage issues, you can join ๐Community Group to get the latest technical support.
๐ Warning
All h function
demonstrations in the documentation demos mean you can use the h
function for component rendering, or use custom Vue components
for rendering.
For example:
<!-- This is the h function demonstration in the documentation -->
(props:any) => {return h('div', props, {default: () => 'Test'})}
2
๐ Actually it can be written as a custom component:
<!-- Import your Vue component from external -->
import SelfButton from './SelfButton.vue'
<!-- Custom component rendering -->
<!-- SelfButton is your custom Vue component above -->
<!-- selfProps are custom properties, receiving props -->
(props:any) => {return h(SelfButton, { selfProps: props })}
2
3
4
5
6
7
๐ In your custom component you can get props like this:
<!-- SelfButton.vue -->
<script setup lang="ts">
const props = defineProps({
selfProps: { type: Object, default: () => ({}) }
});
conslog(props.selfProps); // Check the props you get in console
</script>
<template>
<!-- You can get props properties for some custom rendering -->
<button>{{ selfProps.text }}</button>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
Code Demo โ
Basic Usage โ
Quickly render a basic Markdown text. Built-in basic styles such as inline code, code blocks, mathematical formula functions (inline/block), mermaid charts, etc.
๐ Warning
Supports incremental updates, you can view node update changes in the console. The following code example demonstrates the incremental update effect, simulating the logic of streaming character reception.
<script setup lang="ts">
const markdown = ref(`
# Level 1 Heading
## Level 2 Heading
### Level 3 Heading
#### Level 4 Heading
##### Level 5 Heading
###### Level 6 Heading
**This is bold text**
__This is also bold text__
*This is italic text*
_This is also italic text_
***This is bold italic text***
~~This is strikethrough text~~
- Unordered list item 1
- Unordered list item 2
- Sub list item 2.1
- Sub list item 2.2
1. Ordered list item 1
2. Ordered list item 2
1. Sub list item 2.1
2. Sub list item 2.2
[Element-Plus-X](https://element-plus-x.com "Element-Plus-X")

>This is a quoted text
>
>> This is nested quoted text
---
| Name | Age | Profession |
| ---- | --- | ---------- |
| Zhang San | 25 | Engineer |
| Li Si | 30 | Designer |
### Inline Code
Use \`ElmentPlusX\` to represent inline block code with \`\` statements
### Code Block
\`\`\`javascript
const code = "Element-Plus-X";
\`\`\`
### Inline Formula
$e^{i\\pi} + 1 = 0$
### Block Formula
$$
F(\\omega) = \\int_{-\\infty}^{\\infty} f(t) e^{-i\\omega t} dt
$$
### Mermaid Pie Chart
\`\`\`mermaid
pie
"Media and Culture Related" : 35
"Advertising and Marketing" : 8
"Game Development" : 15
"Film Animation and Effects" : 12
"Internet Product Design" : 10
"VR/AR Development" : 5
"Others" : 15
\`\`\`
`);
const timer = ref();
const index = ref(markdown.value.length); // Default display all content
const content = computed(() => {
return markdown.value.slice(0, index.value);
});
function start() {
timer.value = setInterval(() => {
index.value += 5;
if (index.value > markdown.value.length) {
clearInterval(timer.value);
index.value = markdown.value.length;
}
}, 100);
}
function pause() {
if (timer.value) {
clearInterval(timer.value);
timer.value = null;
}
}
function redo() {
index.value = 0;
if (timer.value) {
clearInterval(timer.value);
timer.value = null;
}
start();
}
onMounted(() => {
start();
});
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<span style="font-size: 20px; font-weight: 700">View incremental rendering in console</span>
<div style="display: flex; gap: 8px">
<el-button @click="start">
Start
</el-button>
<el-button @click="pause">
Pause
</el-button>
<el-button @click="redo">
Restart
</el-button>
</div>
<XMarkdown :markdown="content" class="vp-raw" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
Set Default Highlight/Dark Mode โ
Set code block highlighting through the default-theme-mode
property, whether the default is highlight theme or dark theme.
๐ Info
The demonstration here in the documentation may be affected by vitePress styles, please check the effect yourself. If the property is invalid in your project, you can join ๐Community Group to provide feedback.
<script setup lang="ts">
const markdown = `
\`\`\`js
console.log('hello world');
\`\`\`
`;
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown :markdown="markdown" default-theme-mode="light" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Built-in Shiki Themes โ
Code block highlighting has multiple built-in themes to choose from.
Set code block themes through the themes
property. This property is an object with highlight and dark theme properties, with values being built-in theme IDs
.
themes: {
light: 'vitesse-light'; // Light theme (component default theme)
dark: 'vitesse-dark'; // Dark theme (component default theme)
}
2
3
4
We have built-in shiki styles, you can view them at shiki-theme.
๐ Warning
After resetting the theme, you may need to refresh the page for it to take effect. Below lists all built-in shiki
styles and their corresponding theme IDs
. If you're in a ts project, you should get type inference hints for built-in style themes during development.

๐View all theme ID reference table
Name | Chinese Translation | Corresponding Value (Theme ID ) |
---|---|---|
Andromeeda | Andromeda | andromeeda |
Aurora X | Aurora X | aurora-x |
Ayu Dark | Ayu Dark | ayu-dark |
Catppuccin Frappรฉ | Catppuccin Frappรฉ | catppuccin-frappe |
Catppuccin Latte | Catppuccin Latte | catppuccin-latte |
Catppuccin Macchiato | Catppuccin Macchiato | catppuccin-macchiato |
Catppuccin Mocha | Catppuccin Mocha | catppuccin-mocha |
Dark Plus | Dark Plus | dark-plus |
Dracula Theme | Dracula Theme | dracula |
Dracula Theme Soft | Dracula Soft Theme | dracula-soft |
Everforest Dark | Everforest Dark | everforest-dark |
Everforest Light | Everforest Light | everforest-light |
GitHub Dark | GitHub Dark | github-dark |
GitHub Dark Default | GitHub Dark Default | github-dark-default |
GitHub Dark Dimmed | GitHub Dark Dimmed | github-dark-dimmed |
GitHub Dark High Contrast | GitHub Dark High Contrast | github-dark-high-contrast |
GitHub Light | GitHub Light | github-light |
GitHub Light Default | GitHub Light Default | github-light-default |
GitHub Light High Contrast | GitHub Light High Contrast | github-light-high-contrast |
Gruvbox Dark Hard | Gruvbox Dark Hard | gruvbox-dark-hard |
Gruvbox Dark Medium | Gruvbox Dark Medium | gruvbox-dark-medium |
Gruvbox Dark Soft | Gruvbox Dark Soft | gruvbox-dark-soft |
Gruvbox Light Hard | Gruvbox Light Hard | gruvbox-light-hard |
Gruvbox Light Medium | Gruvbox Light Medium | gruvbox-light-medium |
Gruvbox Light Soft | Gruvbox Light Soft | gruvbox-light-soft |
Houston | Houston | houston |
Kanagawa Dragon | Kanagawa Dragon | kanagawa-dragon |
Kanagawa Lotus | Kanagawa Lotus | kanagawa-lotus |
Kanagawa Wave | Kanagawa Wave | kanagawa-wave |
LaserWave | LaserWave | laserwave |
Light Plus | Light Plus | light-plus |
Material Theme | Material Theme | material-theme |
Material Theme Darker | Material Theme Darker | material-theme-darker |
Material Theme Lighter | Material Theme Lighter | material-theme-lighter |
Material Theme Ocean | Material Theme Ocean | material-theme-ocean |
Material Theme Palenight | Material Theme Palenight | material-theme-palenight |
Min Dark | Min Dark | min-dark |
Min Light | Min Light | min-light |
Monokai | Monokai | monokai |
Night Owl | Night Owl | night-owl |
Nord | Nord | nord |
One Dark Pro | One Dark Pro | one-dark-pro |
One Light | One Light | one-light |
Plastic | Plastic | plastic |
Poimandres | Poimandres | poimandres |
Red | Red Theme | red |
Rosรฉ Pine | Rosรฉ Pine | rose-pine |
Rosรฉ Pine Dawn | Rosรฉ Pine Dawn | rose-pine-dawn |
Rosรฉ Pine Moon | Rosรฉ Pine Moon | rose-pine-moon |
Slack Dark | Slack Dark | slack-dark |
Slack Ochin | Slack Ochin | slack-ochin |
Snazzy Light | Snazzy Light | snazzy-light |
Solarized Dark | Solarized Dark | solarized-dark |
Solarized Light | Solarized Light | solarized-light |
Synthwave '84 | Synthwave '84 | synthwave-84 |
Tokyo Night | Tokyo Night | tokyo-night |
Vesper | Vesper | vesper |
Vitesse Black | Vitesse Black | vitesse-black |
Vitesse Dark | Vitesse Dark | vitesse-dark |
Vitesse Light | Vitesse Light | vitesse-light |
<script setup lang="ts">
const markdown = `
\`\`\`js
console.log('hello world');
\`\`\`
`;
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown
:markdown="markdown"
:themes="{ light: 'andromeeda', dark: 'material-theme-darker' }"
/>
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Define Code Block Highlight Style Separately โ
Through the color-replacements
property, you can individually control code colors under a specific theme.
๐ Warning
Note: Color keys must start with #
and be in lowercase format, otherwise they won't take effect.
Theme IDs have corresponding color variables, which can be viewed in the console. We can replace the built-in color variables with custom colors.
<script setup lang="ts">
const markdown = `
\`\`\`js
console.log('hello world');
\`\`\`
`;
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown
:markdown="markdown"
:color-replacements="{
// Left side is the variable to modify, right side is the modified color
'vitesse-light': {
'#ab5959': '#ee82ee',
'#1e754f': '#9370db'
},
'vitesse-dark': {
'#cb7676': '#ff0066',
'#4d9375': '#952189'
}
}"
/>
<XMarkdown
:markdown="markdown"
:color-replacements="{
// Pass a default value here to prevent it from being affected by other colorReplacements
'vitesse-light': {
'#ab5959': '#ab5959',
'#1e754f': '#1e754f'
},
'vitesse-dark': {
'#cb7676': '#cb7676',
'#4d9375': '#4d9375'
}
}"
/>
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Unified Style Override โ
If you find that the component's built-in styles become strange when integrating this component, it may be because your project's built-in global styles conflict with some basic styles of this component. You can solve this problem by overriding styles.
๐ Info
Create a style file, for example: self-markdown.css
, and add some custom style content:
.h1 {
font-size: 24px;
color: red;
margin-bottom: 16px;
}
2
3
4
5
Import this file into your project, for example:
import 'self-markdown.css'
If it's not overridden, it's likely because your style hierarchy is not sufficient, you can try style penetration
<script setup lang="ts">
const markdown = `
# Level 1 Heading
## Level 2 Heading
### Level 3 Heading
`;
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown :markdown="markdown" class="self-markdown-body" />
</div>
</template>
<style scoped lang="less">
.self-markdown-body {
:deep(h1) {
font-size: 24px;
color: red;
margin-bottom: 16px;
}
:deep(h2) {
margin: 0;
font-size: 20px;
color: blue;
margin-bottom: 16px;
}
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Below uses the github
style file to uniformly override styles as an example
Github Style โ
There are also many excellent authors in the market who have open-sourced their markdown styles. Here demonstrates a case of integrating and using github styles.
You can directly download the github-markdown.css file, or copy the style code to your own css file. Then reference it in your project.
๐ Warning
However, it's worth noting that generally such file styles are wrapped by the markdown-body
class name. Just importing the style file is not enough. You may also need to add a class name to XMarkdown
to make the styles take effect. This class name should be consistent with the outermost class name in the imported style file.
<script setup lang="ts">
// (Assuming your style file exists) Import style file
// import "./github-markdown.css"
const markdown = `
# Level 1 Heading
## Level 2 Heading
### Level 3 Heading
`;
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<!-- Set class name here to make github styles take effect -->
<XMarkdown :markdown="markdown" class="markdown-body" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
If you want to control code block highlighting styles separately, you can do this:
allowHtml โ
Supports HTML tag rendering, use the allowHtml
property to enable it, disabled by default.
<script setup lang="ts">
const markdown = `<div style="color: red;">This is an HTML tag test.</div>`;
const value1 = ref(false);
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<el-switch v-model="value1" />
<XMarkdown :markdown="markdown" :allow-html="value1" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
enableLatex โ
Supports LaTeX math formula rendering, use the enableLatex
property to enable it, enabled by default.
<script setup lang="ts">
const markdown = `
### Inline Formula
$e^{i\\pi} + 1 = 0$
### Block Formula
$$
F(\\omega) = \\int_{-\\infty}^{\\infty} f(t) e^{-i\\omega t} dt
$$
`;
const value1 = ref(true);
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<el-switch v-model="value1" />
<XMarkdown :markdown="markdown" :enable-latex="value1" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
enableBreaks โ
Supports remark-breaks rendering, use the enableBreaks
property to enable it, enabled by default.
Supports hard breaks without requiring spaces or escape characters (converts line breaks to <br>
). Makes your content rendering more authentic.
<script setup lang="ts">
const markdown = `Mars is
the fourth planet`;
const value1 = ref(true);
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<el-switch v-model="value1" />
<XMarkdown :markdown="markdown" :enable-breaks="value1" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
Preview HTML Code Block โ
Supports previewing HTML code blocks.
- If you don't need it, you can hide the button by setting
need-view-code-btn
property tofalse
. Default istrue
. - You can also use the
secure-view-code
property, set totrue
to enablehtml
safe mode. Default isfalse
. If enabled,script
tags will not be rendered. Click to add to cart - You can also configure the popover through the
viewCodeModalOptions
property.
viewCodeModalOptions: {
mode: 'drawer',
customClass: '',
dialogOptions: {
closeOnClickModal: true,
closeOnPressEscape: true
},
drawerOptions: {
closeOnClickModal: true,
closeOnPressEscape: true
}
}
2
3
4
5
6
7
8
9
10
11
12
Property | Value | Description |
---|---|---|
mode | 'drawer' | Modal display form as drawer type |
customClass | '' | No custom style class added |
dialogOptions | - | Dialog mode configuration (currently not enabled) |
- closeOnClickModal | true | Click outside dialog area to close (only effective in dialog mode) |
- closeOnPressEscape | true | Press ESC key to close dialog (only effective in dialog mode) |
drawerOptions | - | Drawer mode configuration (currently enabled) |
- closeOnClickModal | true | Click outside drawer area to close |
- closeOnPressEscape | true | Press ESC key to close drawer |
๐ Warning
You can also control the top preview button style through custom top code blocks.
Or, go completely custom rendering, see details below Custom Code Block Top Rendering
.
<script setup lang="ts">
const markdown = `
\`\`\`html
<div class="product-card">
<div class="badge">New</div>
<img src="https://picsum.photos/300/200?product" alt="Product Image">
<div class="content">
<h3>Wireless Bluetooth Headphones Pro</h3>
<p class="description">Active noise cancellation technology, 30-hour battery life, IPX5 waterproof rating</p>
<div class="rating">
<span>โ
โ
โ
โ
โ</span>
<span class="reviews">(124 reviews)</span>
</div>
<div class="price-container">
<span class="price">$499</span>
<span class="original-price">$699</span>
<span class="discount">30% OFF</span>
</div>
<div class="actions">
<button class="cart-btn" onclick="addToCart(this)">Add to Cart</button>
<button class="fav-btn">โค๏ธ</button>
</div>
<div class="meta">
<span>โ Next Day Delivery</span>
<span>โ 7-Day Return</span>
</div>
</div>
</div>
\<script\>
function addToCart(button) {
// Prevent duplicate clicks
if (button.disabled) return;
// Disable button
button.disabled = true;
button.innerHTML = 'Adding...';
// Simulate API request to add to cart
setTimeout(() => {
// Show success message
button.innerHTML = 'โ Added';
button.classList.add('success');
// Restore button state after 3 seconds
setTimeout(() => {
button.innerHTML = 'Add to Cart';
button.disabled = false;
button.classList.remove('success');
}, 3000);
}, 800);
};
\<\/script\>
<style>
.product-card {
width: 280px;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
position: relative;
background: white;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.badge {
position: absolute;
top: 12px;
left: 12px;
background: #ff6b6b;
color: white;
padding: 4px 10px;
border-radius: 4px;
font-weight: bold;
font-size: 12px;
z-index: 2;
}
img {
width: 100%;
height: 180px;
object-fit: cover;
display: block;
}
.content {
padding: 16px;
}
h3 {
margin: 8px 0;
font-size: 18px;
color: #333;
}
.description {
color: #666;
font-size: 14px;
margin: 8px 0 12px;
line-height: 1.4;
}
.rating {
display: flex;
align-items: center;
margin: 10px 0;
color: #ffb300;
}
.reviews {
font-size: 13px;
color: #888;
margin-left: 8px;
}
.price-container {
display: flex;
align-items: center;
gap: 8px;
margin: 12px 0;
}
.price {
font-size: 22px;
font-weight: bold;
color: #ff4757;
}
.original-price {
font-size: 14px;
color: #999;
text-decoration: line-through;
}
.discount {
background: #fff200;
padding: 2px 6px;
border-radius: 4px;
font-size: 12px;
}
.actions {
display: flex;
gap: 8px;
margin: 16px 0 12px;
}
.cart-btn {
flex: 1;
background: #5352ed;
color: white;
border: none;
padding: 10px;
border-radius: 6px;
font-weight: bold;
cursor: pointer;
transition: background 0.2s;
}
.cart-btn:hover {
background: #3742fa;
}
.cart-btn.disabled {
background: #a4b0be;
cursor: not-allowed;
}
.cart-btn.success {
background: #2ed573;
}
.fav-btn {
width: 42px;
background: white;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 18px;
cursor: pointer;
transition: all 0.2s;
}
.fav-btn:hover {
border-color: #ff6b6b;
color: #ff6b6b;
}
.meta {
display: flex;
gap: 15px;
font-size: 13px;
color: #2ed573;
margin-top: 8px;
}
</style>
\`\`\`
`;
const value1 = ref(true);
const value2 = ref(false);
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<span>Show HTML preview button <el-switch v-model="value1" /></span>
<span>Enable secure preview <el-switch v-model="value2" /></span>
<span>After enabling secure preview, try clicking the Add to Cart button, it
won't trigger events in script tags</span>
<XMarkdown
:markdown="markdown"
:need-view-code-btn="value1"
:secure-view-code="value2"
/>
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
Custom Code Block Rendering โ
Use the codeXRender
property to customize code block rendering. This property accepts an object where the key is the code block language and the value is a function. The function parameter is the code block properties, and the return value is a VNode. This means you can use Vue's template syntax to render code blocks.
๐ Warning
This feature will intercept the code blocks you set. You can discuss the code block language with the backend, then return a corresponding VNode based on the language.
We will build a component library marketplace based on this component in the future. If you're interested in this, welcome to join ๐ฅฐCommunity Group, or add the author's contact information to build this marketplace project together. ๐ฅณStay tuned
<script setup lang="ts">
import { h } from 'vue';
import Echarts from './echarts.vue';
const markdown = `
\`\`\`javascript
const a = 1;
\`\`\`
\`\`\`echarts
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
};
\`\`\`
`;
const selfCodeXRender = {
// Render custom code block identifier javascript, return a component
javascript: (props: { raw: any }) => {
return h(
'pre',
{ class: 'language-javascript' },
h('code', { class: 'language-javascript' }, props.raw.content)
);
},
// Render custom code block identifier echarts, Echarts is a self-encapsulated Vue component
echarts: (props: { raw: any }) => h(Echarts, { code: props.raw.content })
};
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown :markdown="markdown" :code-x-render="selfCodeXRender" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
The echarts component introduced in the example code. The source code is placed here for everyone's understanding. How to customize components, the echarts component implementation here is for example only. In actual use, please encapsulate according to your own backend data and requirements.
๐View echarts
component code example
<!-- echarts.vue -->
<script setup lang="ts">
import * as echarts from 'echarts';
// Keep original props.code logic, while adding optional configuration
const props = defineProps<{
code: string; // Original JSON string configuration
width?: string; // Optional: chart width
height?: string; // Optional: chart height
theme?: string; // Optional: chart theme
}>();
const refEle = ref<HTMLElement>();
let myChart: echarts.ECharts | null = null; // Chart instance reference
function parseEChartsOption(str: string): any {
try {
let cleanedStr = str.replace(/^option\s*=\s*/, '').replace(/;\s*$/, '');
cleanedStr = cleanedStr.replace(/'/g, '"');
cleanedStr = cleanedStr.replace(/(\w+)\s*:/g, '"$1":');
return JSON.parse(cleanedStr);
} catch (error) {
console.error('Failed to parse ECharts option:', error);
return null;
}
}
// Core rendering logic (keep original parsing process)
function renderChart() {
if (!refEle.value) return;
try {
// Parse JSON configuration (keep original logic)
const cleanedStr = parseEChartsOption(props.code);
// Initialize/update chart
if (!myChart) {
myChart = echarts.init(refEle.value, props.theme);
}
myChart.setOption(cleanedStr);
} catch (error) {
console.error('Chart configuration parsing failed:', error);
}
}
// Window resize handling
function handleResize() {
myChart?.resize();
}
// Destroy logic
function destroyChart() {
if (myChart) {
myChart.dispose(); // Release ECharts instance
myChart = null;
}
window.removeEventListener('resize', handleResize);
}
// Initialize rendering
onMounted(() => {
renderChart();
window.addEventListener('resize', handleResize); // Add resize listener
});
// Listen to code changes for automatic updates (key optimization)
watch(
() => props.code,
() => {
renderChart(); // Re-render when configuration changes
}
);
// Clean up resources when unmounting
onUnmounted(() => {
destroyChart();
});
</script>
<template>
<div class="echarts-wrap">
<span class="echarts-titlt">This is my custom echarts component</span>
<div
ref="refEle"
:style="{
height: height || '400px', // Optional height, default 400px
width: width || '100%' // Optional width, default 100%
}"
/>
</div>
</template>
<style scoped lang="less">
.echarts-wrap {
position: relative;
.echarts-titlt {
position: absolute;
width: fit-content;
margin-left: 20px;
color: blue;
font-size: 20px;
font-weight: bold;
}
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
Custom Code Block Top Rendering โ
If you just want to modify the content of our built-in code block top, you can use codeXSlot
. And we expose the built-in collapse
, theme switch
, and copy
methods. You can retain default functionality while only changing styles.
Use the codeXSlot
property to customize code block top slot rendering. This property accepts an object where the key is a fixed property of the CodeBlockHeaderExpose type, and the value is a function. The function parameter is the code block properties, and the return value is a VNode, meaning you can use Vue's template syntax to render the top of code blocks.
You can get props in your custom template, and props has the following properties (specific properties can be printed and viewed in the project):
isExpand
: props.isExpand whether the code block is expanded.toggleExpand
: props.toggleExpand expand code block.isDark
: props.isDark.value get current code block theme.toggleTheme
: props.toggleTheme switch code block theme.renderLines
: props.renderLines get the content of this code block, you can use it to pass to the copy function.copyCode
: props.copyCode(props.renderLines) copy code block (requires parameter).viewCode
: props.viewCode(props.renderLines) trigger built-in preview HTML code block popover (requires parameter).value
: props.value get this code block type is 'Code' | 'Preview'.changeSelectValue
: props.changeSelectValue('Code' | 'Preview') switch code block type (requires parameter).changeSelectValue
: props.changeSelectValue('Code' | 'Preview') switch code block type (requires parameter).content
: props.content get this code block content.close
: props.close() close built-in preview HTML popover (no parameter needed).
The following are built-in properties that can be obtained in the mermaid code block header custom component props:
zoomIn
: props.zoomIn zoom in.zoomOut
: props.zoomOut zoom out.reset
: props.reset return to initial position.toggleCode
: props.toggleCode switch display code.download
: props.download download image.fullscreen
: props.fullscreen enter fullscreen.copyCode
: props.copyCode copy code.
// Type definition for this property
interface CodeBlockHeaderExpose {
// Custom render the entire code block header
codeHeader?: CodeBlockHeaderRenderer;
// Custom render the left language identifier of the code block
codeHeaderLanguage?: CodeBlockHeaderRenderer;
// Custom render the right control button of the code block
codeHeaderControl?: CodeBlockHeaderRenderer;
// Custom render the title area of the right preview popover of the code block
viewCodeHeader?: CodeBlockHeaderRenderer;
// Custom render the content area of the right preview popover of the code block
viewCodeContent?: CodeBlockHeaderRenderer;
// Custom render the close button of the right preview popover of the code block
viewCodeCloseBtn?: CodeBlockHeaderRenderer;
// Custom render mermaid top slot
codeMermaidHeaderControl?: CodeBlockHeaderRenderer;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script setup lang="ts">
// This ts type has not been successfully exported yet, and the props type currently uses any temporarily, needs optimization later
// import type { CodeBlockHeaderExpose, CodeBlockExpose } from 'vue-element-plus-x/types/components/XMarkdownCore/components/CodeBlock/shiki-header.d.ts';
import { h } from 'vue';
const markdown = `
\`\`\`javascript
const a = 1;
\`\`\`
`;
const mermaidMarkdown = `
\`\`\`mermaid
pie
"Media and Culture Related" : 35
"Advertising and Marketing" : 8
"Game Development" : 15
"Film Animation and Effects" : 12
"Internet Product Design" : 10
"VR/AR Development" : 5
"Others" : 15
\`\`\`
`;
// If you use the codeHeader property, the other two properties become invalid
const selfCodeXSlot1 = {
// Custom render the entire code block header, h function can also be written as a custom component form
// (props: any) => h(SelfComponent, { selfProps: props }),
codeHeader: (props: any) =>
h(
'div',
{
onClick: (ev: MouseEvent) => props.toggleExpand(ev)
},
{ default: () => 'This is custom header, click to toggle collapse state' }
),
// Custom render the left language identifier of the code block
codeHeaderLanguage: () =>
h('div', 'Custom code block left language identifier'),
// Custom render the right control button of the code block
codeHeaderControl: () => h('div', 'Custom code block right control button')
};
// If you use the codeHeader property, the other two properties become invalid
const selfCodeXSlot2 = {
// Custom render the left language identifier of the code block
codeHeaderLanguage: () =>
h('div', 'Custom code block left language identifier')
};
const selfCodeXSlot3 = {
// Custom render the right control button of the code block
codeHeaderControl: () => h('div', 'Custom code block right control button')
};
// If you use the codeHeader property, the other two properties become invalid
const selfCodeXSlot4 = {
codeMermaidHeaderControl: (props: any) => {
return h(
'div',
{
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '12px 16px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
color: 'white',
borderRadius: '8px',
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.3)'
}
},
[
h(
'div',
{
style: { display: 'flex', alignItems: 'center', gap: '12px' }
},
[
h('span', { style: { fontSize: '16px' } }, '๐จ'),
h('span', { style: { fontWeight: '600' } }, 'Custom Mermaid'),
h(
'span',
{
style: {
fontSize: '12px',
background: 'rgba(255,255,255,0.25)',
padding: '4px 8px',
borderRadius: '12px'
}
},
props.showSourceCode ? '๐ Source' : '๐ Chart'
)
]
),
h('div', { style: { display: 'flex' } }, [
h(
ElTooltip,
{
content: 'Zoom In',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
onClick: props.zoomIn
},
() => '๐'
)
}
),
h(
ElTooltip,
{
content: 'Reset Zoom',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
onClick: props.reset
},
() => '๐'
)
}
),
h(
ElTooltip,
{
content: props.showSourceCode ? 'View Chart' : 'View Source',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
onClick: props.toggleCode
},
() => (props.showSourceCode ? '๐๏ธ' : '๐')
)
}
),
h(
ElTooltip,
{
content: 'Custom Copy',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
// ๐ฏ User custom copy logic demonstration - complete takeover
onClick: async () => {
try {
const customContent = `๐จ Custom Prefix:\n\n${props.rawContent}\n\n๐ From: Element-Plus-X`;
await navigator.clipboard.writeText(customContent);
ElMessage.success(
'๐ Component slot custom copy successful!'
);
}
catch (err) {
console.error('โ Custom copy failed:', err);
}
}
},
() => '๐'
)
}
),
h(
ElTooltip,
{
content: 'Download Image',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
onClick: props.download
},
() => '๐พ'
)
}
)
])
]
);
}
};
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown :markdown="markdown" :code-x-slot="selfCodeXSlot1" />
<XMarkdown :markdown="markdown" :code-x-slot="selfCodeXSlot2" />
<XMarkdown :markdown="markdown" :code-x-slot="selfCodeXSlot3" />
<XMarkdown :markdown="mermaidMarkdown" :code-x-slot="selfCodeXSlot4" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
Custom Attributes โ
Use the customAttrs
property to receive an object where the properties are tag names and the values are tag attributes. When a tag is matched, the corresponding attributes will be added to that tag.
<script setup lang="ts">
const markdown = `
<a href="https://element-plus-x.com/">element-plus-x</a>
<h1>Title 1</h1>
<h2>Title 2</h2>
<self-btn>Add el-button class name to custom tag</self-btn>
`;
// If you use the codeHeader property, the other two properties become invalid
const selfAttrs = {
a: () => ({
target: '_blank',
rel: 'noopener noreferrer'
}),
h1: {
style: {
color: 'red',
fontSize: '24px'
}
},
h2: {
style: {
color: 'blue',
fontSize: '20px'
}
},
// Add el-button class name to custom tag
'self-btn': {
class: 'el-button'
}
};
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown :markdown="markdown" :custom-attrs="selfAttrs" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Mermaid Operation Bar Configuration โ
Use the mermaidConfig
property to customize the mermaid top ToolbarConfig. This property accepts a MermaidToolbarConfig object, which can control the hide/show of top controls, add some class names, and control hover colors.
๐ Warning
If you set the codeMermaidHeaderControl
property with code-x-slot
, it completely takes over the mermaid Toolbar slot, allowing developers to fully customize it. Of course, we still expose the built-in Toolbar methods, so you can retain some built-in methods you need while only modifying styles.
interface MermaidToolbarConfig {
showToolbar?: boolean;
showFullscreen?: boolean;
showZoomIn?: boolean;
showZoomOut?: boolean;
showReset?: boolean;
showDownload?: boolean;
toolbarStyle?: Record<string, any>;
toolbarClass?: string;
iconColor?: string;
tabTextColor?: string;
hoverBackgroundColor?: string;
tabActiveBackgroundColor?: string;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
<script setup lang="ts">
import { ElButton, ElMessage, ElTooltip } from 'element-plus';
import { h } from 'vue';
const markdown = `
\`\`\`mermaid
pie
"Media and Culture Related" : 35
"Advertising and Marketing" : 8
"Game Development" : 15
"Film Animation and Effects" : 12
"Internet Product Design" : 10
"VR/AR Development" : 5
"Others" : 15
\`\`\`
`;
const selfCodeXSlot = {
codeMermaidHeaderControl: (props: any) => {
return h(
'div',
{
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '12px 16px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
color: 'white',
borderRadius: '8px',
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.3)'
}
},
[
h(
'div',
{
style: { display: 'flex', alignItems: 'center', gap: '12px' }
},
[
h('span', { style: { fontSize: '16px' } }, '๐จ'),
h('span', { style: { fontWeight: '600' } }, 'Custom Mermaid'),
h(
'span',
{
style: {
fontSize: '12px',
background: 'rgba(255,255,255,0.25)',
padding: '4px 8px',
borderRadius: '12px'
}
},
props.showSourceCode ? '๐ Source' : '๐ Chart'
)
]
),
h('div', { style: { display: 'flex' } }, [
h(
ElTooltip,
{
content: 'Zoom In',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
onClick: props.zoomIn
},
() => '๐'
)
}
),
h(
ElTooltip,
{
content: 'Reset Zoom',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
onClick: props.reset
},
() => '๐'
)
}
),
h(
ElTooltip,
{
content: props.showSourceCode ? 'View Chart' : 'View Source',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
onClick: props.toggleCode
},
() => (props.showSourceCode ? '๐๏ธ' : '๐')
)
}
),
h(
ElTooltip,
{
content: 'Custom Copy',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
// ๐ฏ User custom copy logic demonstration - complete takeover
onClick: async () => {
try {
const customContent = `๐จ Custom Prefix:\n\n${props.rawContent}\n\n๐ From: Element-Plus-X`;
await navigator.clipboard.writeText(customContent);
ElMessage.success(
'๐ Component slot custom copy successful!'
);
}
catch (err) {
console.error('โ Custom copy failed:', err);
}
}
},
() => '๐'
)
}
),
h(
ElTooltip,
{
content: 'Download Image',
placement: 'top'
},
{
default: () =>
h(
ElButton,
{
size: 'small',
type: 'primary',
text: true,
bg: true,
style: {
background: 'rgba(255,255,255,0.2)',
color: 'white',
border: 'none'
},
onClick: props.download
},
() => '๐พ'
)
}
)
])
]
);
}
};
const selfMermaidConfig = {
showToolbar: true,
showFullscreen: false,
showZoomIn: true,
showZoomOut: true,
showReset: true,
showDownload: false,
toolbarStyle: {
background: 'linear-gradient(135deg, #8b5cf6 0%, #a855f7 100%)',
boxShadow: '0 4px 16px rgba(139, 92, 246, 0.3)',
borderRadius: '8px'
},
iconColor: '#FFFFFF',
tabTextColor: '#FFFFFF'
};
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown
:markdown="markdown"
:code-x-slot="selfCodeXSlot"
:mermaid-config="selfMermaidConfig"
/>
<XMarkdown :markdown="markdown" :mermaid-config="selfMermaidConfig" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
Slot Tag Interception โ
You can intercept some tags, or custom tags, and then customize the rendering of these tags. If you want to customize the rendering of images or videos, it might be very convenient
<script setup lang="ts">
const markdown = `
<img src="https://avatars.githubusercontent.com/u/76239030?v=4" alt="">
<self-btn>Custom Tag</self-btn>
`;
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown :markdown="markdown">
<template #img="{ ...props }">
<img :key="props.key" :src="props.src" style="border-radius: 30px">
</template>
<template #self-btn="{ ...props }">
<el-button :key="props.key">
Check props in console {{ console.log(props) }}
</el-button>
</template>
</XMarkdown>
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Built-in Code Block Languages โ
We have built-in matching for some commonly used programming and development languages to render corresponding code block content.
๐ Warning
Some languages can be matched using their abbreviations, for example, javascript
can be matched using js
๐ View all supported languages
Language Name | Language Match ID | Language Match Abbreviation |
---|---|---|
ABAP | abap | |
ActionScript | actionscript-3 | |
Ada | ada | |
Angular HTML | angular-html | |
Angular TypeScript | angular-ts | |
Apache Conf | apache | |
Apex | apex | |
APL | apl | |
AppleScript | applescript | |
Ara | ara | |
AsciiDoc | asciidoc | adoc |
Assembly | asm | |
Astro | astro | |
AWK | awk | |
Ballerina | ballerina | |
Batch File | bat | batch |
Beancount | beancount | |
Berry | berry | be |
BibTeX | bibtex | |
Bicep | bicep | |
Blade | blade | |
1C (Enterprise) | bsl | 1c |
C | c | |
Cadence | cadence | cdc |
Cairo | cairo | |
Clarity | clarity | |
Clojure | clojure | clj |
CMake | cmake | |
COBOL | cobol | |
CODEOWNERS | codeowners | |
CodeQL | codeql | ql |
CoffeeScript | coffee | coffeescript |
Common Lisp | common-lisp | lisp |
Coq | coq | |
C++ | cpp | c++ |
Crystal | crystal | |
C# | csharp | c#cs |
CSS | css | |
CSV | csv | |
CUE | cue | |
Cypher | cypher | cql |
D | d | |
Dart | dart | |
DAX | dax | |
Desktop | desktop | |
Diff | diff | |
Dockerfile | docker | dockerfile |
dotEnv | dotenv | |
Dream Maker | dream-maker | |
Edge | edge | |
Elixir | elixir | |
Elm | elm | |
Emacs Lisp | emacs-lisp | elisp |
ERB | erb | |
Erlang | erlang | erl |
Fennel | fennel | |
Fish | fish | |
Fluent | fluent | ftl |
Fortran (Fixed Form) | fortran-fixed-form | fforf77 |
Fortran (Free Form) | fortran-free-form | f90f95f03f08f18 |
F# | fsharp | f#fs |
GDResource | gdresource | |
GDScript | gdscript | |
GDShader | gdshader | |
Genie | genie | |
Gherkin | gherkin | |
Git Commit Message | git-commit | |
Git Rebase Message | git-rebase | |
Gleam | gleam | |
Glimmer JS | glimmer-js | gjs |
Glimmer TS | glimmer-ts | gts |
GLSL | glsl | |
Gnuplot | gnuplot | |
Go | go | |
GraphQL | graphql | gql |
Groovy | groovy | |
Hack | hack | |
Ruby Haml | haml | |
Handlebars | handlebars | hbs |
Haskell | haskell | hs |
Haxe | haxe | |
HashiCorp HCL | hcl | |
Hjson | hjson | |
HLSL | hlsl | |
HTML | html | |
HTML (Derivative) | html-derivative | |
HTTP | http | |
HXML | hxml | |
Hy | hy | |
Imba | imba | |
INI | ini | properties |
Java | java | |
JavaScript | javascript | js |
Jinja | jinja | |
Jison | jison | |
JSON | json | |
JSON5 | json5 | |
JSON with Comments | jsonc | |
JSON Lines | jsonl | |
Jsonnet | jsonnet | |
JSSM | jssm | fsl |
JSX | jsx | |
Julia | julia | jl |
Kotlin | kotlin | ktkts |
Kusto | kusto | kql |
LaTeX | latex | |
Lean 4 | lean | lean4 |
Less | less | |
Liquid | liquid | |
LLVM IR | llvm | |
Log file | log | |
Logo | logo | |
Lua | lua | |
Luau | luau | |
Makefile | make | makefile |
Markdown | markdown | md |
Marko | marko | |
MATLAB | matlab | |
MDC | mdc | |
MDX | mdx | |
Mermaid | mermaid | mmd |
MIPS Assembly | mipsasm | mips |
Mojo | mojo | |
Move | move | |
Narrat Language | narrat | nar |
Nextflow | nextflow | nf |
Nginx | nginx | |
Nim | nim | |
Nix | nix | |
nushell | nushell | nu |
Objective-C | objective-c | objc |
Objective-C++ | objective-cpp | |
OCaml | ocaml | |
Pascal | pascal | |
Perl | perl | |
PHP | php | |
PL/SQL | plsql | |
Gettext PO | po | potpotx |
Polar | polar | |
PostCSS | postcss | |
PowerQuery | powerquery | |
PowerShell | powershell | psps1 |
Prisma | prisma | |
Prolog | prolog | |
Protocol Buffer 3 | proto | protobuf |
Pug | pug | jade |
Puppet | puppet | |
PureScript | purescript | |
Python | python | py |
QML | qml | |
QML Directory | qmldir | |
Qt Style Sheets | qss | |
R | r | |
Racket | racket | |
Raku | raku | perl6 |
ASP.NET Razor | razor | |
Windows Registry Script | reg | |
RegExp | regexp | regex |
Rel | rel | |
RISC-V | riscv | |
reStructuredText | rst | |
Ruby | ruby | rb |
Rust | rust | rs |
SAS | sas | |
Sass | sass | |
Scala | scala | |
Scheme | scheme | |
SCSS | scss | |
1C (Query) | sdbl | 1c-query |
ShaderLab | shaderlab | shader |
Shell | shellscript | bashshshellzsh |
Shell Session | shellsession | console |
Smalltalk | smalltalk | |
Solidity | solidity | |
Closure Templates | soy | closure-templates |
SPARQL | sparql | |
Splunk Query Language | splunk | spl |
SQL | sql | |
SSH Config | ssh-config | |
Stata | stata | |
Stylus | stylus | styl |
Svelte | svelte | |
Swift | swift | |
SystemVerilog | system-verilog | |
Systemd Units | systemd | |
TalonScript | talonscript | talon |
Tasl | tasl | |
Tcl | tcl | |
Templ | templ | |
Terraform | terraform | tftfvars |
TeX | tex | |
TOML | toml | |
TypeScript with Tags | ts-tags | lit |
TSV | tsv | |
TSX | tsx | |
Turtle | turtle | |
Twig | twig | |
TypeScript | typescript | ts |
TypeSpec | typespec | tsp |
Typst | typst | typ |
V | v | |
Vala | vala | |
Visual Basic | vb | cmd |
Verilog | verilog | |
VHDL | vhdl | |
Vim Script | viml | vimvimscript |
Vue | vue | |
Vue HTML | vue-html | |
Vyper | vyper | vy |
WebAssembly | wasm | |
Wenyan | wenyan | wenyan |
WGSL | wgsl | |
Wikitext | wikitext | mediawikiwiki |
WebAssembly Interface Types | wit | |
Wolfram | wolfram | wl |
XML | xml | |
XSL | xsl | |
YAML | yaml | yml |
ZenScript | zenscript | |
Zig | zig |
<script setup lang="ts">
const markdown = `
\`\`\`js
console.log('hello world');
\`\`\`
\`\`\`ts
import 'self-markdown.css'
\`\`\`
`;
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px">
<XMarkdown :markdown="markdown" />
</div>
</template>
<style scoped lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Properties โ
Property Name | Type | Required | Default | Description |
---|---|---|---|---|
markdown | string | Yes | '' | markdown content |
allowHtml | bool | No | false | Whether to render html |
enableLatex | bool | No | true | Whether to render latex |
enableBreaks | bool | No | true | Whether to render breaks |
codeXRender | Object | No | ()=>{} | Custom code block rendering |
codeXSlot | Object | No | ()=>{} | Custom code block top slot rendering |
customAttrs | Object | No | ()=>{} | Custom attributes |
mermaidConfig | Object | No | ()=>{} | mermaid configuration |
Features โ
- Supports incremental rendering, excellent performance
- Supports custom slots, which can be h function components or template components. Easier to get started
- Built-in rich basic styles for mathematical formulas, mermaid diagrams, reducing developer burden
- Supports multiple interceptions and custom rendering, reaching the upper limit