代码块
样式(自定义添加代码块标题,不用插件)
配置
config.mts
ts
export default defineConfig({
markdown: {
config: md => {
// 为代码块添加 code-label 类
md.use(function (md) {
// 保存默认的代码块渲染器
const defaultFence =
md.renderer.rules.fence ||
function (tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options);
};
// 修改代码块的渲染规则,保留默认样式
md.renderer.rules.fence = (tokens, idx, options, env, self) => {
const token = tokens[idx];
const info = token.info.trim();
// 初始化标志变量,检测是否在 code-group 内
let inCodeGroup = false;
// 遍历 tokens,判断是否位于 code-group 中
for (let i = 0; i <= idx; i++) {
const tokenType = tokens[i].type;
// 如果遇到 container_code-group_open,标记为 true
if (tokenType === 'container_code-group_open') {
inCodeGroup = true;
}
// 如果遇到 container_code-group_close,标记为 false
if (tokenType === 'container_code-group_close') {
inCodeGroup = false;
}
}
// 如果当前代码块在 code-group 中,保持默认渲染
if (inCodeGroup) {
return defaultFence(tokens, idx, options, env, self);
}
// 自定义逻辑:匹配带有中括号的代码块(如:css [custom.css])
const match = info.match(/^(\w+)\s*\[(.*)\]$/);
if (match) {
const language = match[1]; // 语言 (如 css, js 等)
const customLabel = match[2]; // 自定义内容 (如 custom.css)
// 在代码块之前插入 div,并保留代码块的默认渲染
return (
`<div class="code-label"><div class="code-label-text">${customLabel}</div></div>` +
defaultFence(tokens, idx, options, env, self)
);
}
// 如果不匹配,保持默认渲染
return defaultFence(tokens, idx, options, env, self);
};
});
},
},
});
1
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
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
custom.css
css
/**
* Component: 自定义Code代码块添加标题[label.ts]
* -------------------------------------------------------------------------- */
.code-label {
position: relative;
height: 50px;
margin: 16px -24px -25px -24px;
padding: 0 24px;
background-color: var(--vp-code-tab-bg);
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
font-size: 14px;
font-weight: 500;
white-space: nowrap;
line-height: 40px;
}
.code-label::after {
content: '';
position: absolute;
bottom: 9px;
left: 0;
width: 100%;
height: 1px;
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
}
.code-label-text {
position: relative;
width: fit-content;
}
.code-label-text::after {
content: '';
position: absolute;
right: -4px;
bottom: -1px;
left: -4px;
z-index: 1;
height: 2px;
border-radius: 2px;
background-color: var(--vp-code-tab-active-bar-color);
}
@media (min-width: 640px) {
.code-label {
margin-right: 0;
margin-left: 0;
border-radius: 8px 8px 0 0;
}
}
1
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
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
使用
提醒
ts
为代码块语言
[config.mts]
为代码块标题,显示config.mts
,只要写了就显示。[]中括号内可以写任意内容
markdown
```ts [config.mts]
export default defineConfig({
// ...
});
```
1
2
3
4
5
2
3
4
5
不带代码块标题
ts
export default defineConfig({
// ...
});
1
2
3
2
3
带代码块标题
config.mts
ts
export default defineConfig({
// ...
});
1
2
3
2
3
自动折叠
安装
地址:https://github.com/T-miracle/vitepress-plugin-codeblocks-fold/blob/main/README_zh.md
shell
pnpm add vitepress-plugin-codeblocks-fold
1
配置
提醒
codeblocksFold()
接收三个参数:
vitepressObj
这是一个对象,对象里面必须有两个值:路由和前言。
defaultAllFold
是否默认所有页面的代码块都设置成折叠状态,默认为
true
;设置成false
则默认不折叠。可以忽略不填。height
代码块被折叠后的高度,默认为
400
(单位px
)。可以忽略不填。
注意
官方的有点小问题(展开不显示滚动条),所以不要直接导入样式import 'vitepress-plugin-codeblocks-fold/style/index.css';
新建文件/docs/.vitepress/theme/plugin-codeblocks-fold.css
并导入
index.ts
ts
import { useRoute, useData } from 'vitepress';
// 代码块
import codeblocksFold from 'vitepress-plugin-codeblocks-fold'; // 导入方法
import './plugin-codeblocks-fold.css'; // 导入样式
export default {
setup() {
// 获取前言和路由
const { frontmatter } = useData();
const route = useRoute();
// 基础使用
codeblocksFold({ route, frontmatter }, true, 400);
},
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
plugin-codeblocks-fold.css
css
.vp-doc div.fold[class*='language-'] {
overflow: unset;
margin-bottom: var(--codeblocks-margin-bottom);
}
.vp-doc div.fold[class*='language-'] > .line-numbers-wrapper {
overflow: hidden;
}
.vp-doc div.fold[class*='language-'] > .codeblocks-mask {
display: block;
position: absolute;
left: 0;
bottom: 0;
height: 48px;
width: 100%;
z-index: 9;
pointer-events: none;
}
.vp-doc div.fold[class*='language-'] > .fold-btn {
display: flex;
position: absolute;
left: 0;
bottom: -36px;
height: 36px;
width: 100%;
z-index: 9;
border-radius: 0 0 8px 8px;
cursor: pointer;
user-select: none;
justify-content: center;
align-items: center;
}
/* 默认禁止。想要上下跳动就解开跳动代码,注释禁止代码 */
/* 禁止折叠按钮上下跳动 */
.vp-doc div.fold[class*='language-'] > .fold-btn > svg.fold-btn-icon.turn {
transform: translateY(0px) rotate(180deg);
}
/* 使折叠按钮可以上下跳动👇 */
/*.vp-doc div.fold[class*='language-'] > .fold-btn > svg.fold-btn-icon {
animation: float1 infinite 0.8s;
}
.vp-doc div.fold[class*='language-'] > .fold-btn > svg.fold-btn-icon.turn {
animation: float2 infinite 0.8s;
}*/
@keyframes float1 {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-5px);
}
100% {
transform: translateY(0px);
}
}
@keyframes float2 {
0% {
transform: translateY(0px) rotate(180deg);
}
50% {
transform: translateY(-5px) rotate(180deg);
}
100% {
transform: translateY(0px) rotate(180deg);
}
}
/* 使折叠按钮可以上下跳动👆 */
1
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
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
扩展使用
单个.md 文件可以设置前言
---
cbf: [1,2,3]
---
1
2
3
2
3
该数组含义为:
- 当
defaultAllFold
设置为true
(即默认全部页面开启折叠)时,当前页面第 1、2、3 个代码块强制不开启折叠 - 当
defaultAllFold
设置为false
(即默认全部页面不开启折叠)时,当前页面第 1、2、3 个代码块强制开启折叠
cbf` 还有两个参数:`true` 和 `false
1
true
表示当前页面所有代码块开启折叠false
表示当前页面所有代码块不开启折叠
添加图标和标题
注意
使用该插件时需要将上方样式(自定义添加代码块标题,不用插件)
中的配置先删除
安装
地址:https://github.com/yuyinws/vitepress-plugin-group-icons
sh
npm install vitepress-plugin-group-icons
1
sh
yarn add vitepress-plugin-group-icons
1
sh
pnpm add vitepress-plugin-group-icons
1
sh
bun add vitepress-plugin-group-icons
1
配置
config.mts
ts
import { defineConfig } from 'vitepress';
import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons';
export default defineConfig({
markdown: {
config(md) {
md.use(groupIconMdPlugin);
},
},
vite: {
plugins: [groupIconVitePlugin()],
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
index.ts
ts
import DefaultTheme from 'vitepress/theme';
import 'virtual:group-icons.css';
1
2
2
自定义图标
你可以从 iconify 或本地 svg 文件中添加任何图标。
图标默认映射
ts
export const builtinIcons = {
// 包管理器
pnpm: 'vscode-icons:file-type-light-pnpm',
npm: 'vscode-icons:file-type-npm',
yarn: 'vscode-icons:file-type-yarn',
bun: 'vscode-icons:file-type-bun',
deno: 'vscode-icons:file-type-light-deno',
// 框架
vue: 'vscode-icons:file-type-vue',
svelte: 'vscode-icons:file-type-svelte',
angular: 'vscode-icons:file-type-angular',
react: 'vscode-icons:file-type-reactjs',
next: 'vscode-icons:file-type-light-next',
nuxt: 'vscode-icons:file-type-nuxt',
solid: 'logos:solidjs-icon',
astro: 'vscode-icons:file-type-light-astro',
// 打包工具
rollup: 'vscode-icons:file-type-rollup',
webpack: 'vscode-icons:file-type-webpack',
vite: 'vscode-icons:file-type-vite',
esbuild: 'vscode-icons:file-type-esbuild',
// 配置文件
'package.json': 'vscode-icons:file-type-node',
'tsconfig.json': 'vscode-icons:file-type-tsconfig',
'.npmrc': 'vscode-icons:file-type-npm',
'.editorconfig': 'vscode-icons:file-type-editorconfig',
'.eslintrc': 'vscode-icons:file-type-eslint',
'.eslintignore': 'vscode-icons:file-type-eslint',
'eslint.config': 'vscode-icons:file-type-eslint',
'.gitignore': 'vscode-icons:file-type-git',
'.gitattributes': 'vscode-icons:file-type-git',
'.env': 'vscode-icons:file-type-dotenv',
'.env.example': 'vscode-icons:file-type-dotenv',
'.vscode': 'vscode-icons:file-type-vscode',
'tailwind.config': 'vscode-icons:file-type-tailwind',
'uno.config': 'vscode-icons:file-type-unocss',
// 文件扩展名
'.ts': 'vscode-icons:file-type-typescript',
'.tsx': 'vscode-icons:file-type-typescript',
'.mjs': 'vscode-icons:file-type-js',
'.cjs': 'vscode-icons:file-type-js',
'.json': 'vscode-icons:file-type-json',
'.js': 'vscode-icons:file-type-js',
'.jsx': 'vscode-icons:file-type-js',
'.md': 'vscode-icons:file-type-markdown',
'.py': 'vscode-icons:file-type-python',
'.ico': 'vscode-icons:file-type-favicon',
'.html': 'vscode-icons:file-type-html',
'.css': 'vscode-icons:file-type-css',
'.yml': 'vscode-icons:file-type-light-yaml',
'.yaml': 'vscode-icons:file-type-light-yaml',
};
1
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
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
config.mts
ts
import { defineConfig } from 'vitepress';
import { groupIconMdPlugin, groupIconVitePlugin, localIconLoader } from 'vitepress-plugin-group-icons';
export default defineConfig({
markdown: {
config(md) {
md.use(groupIconMdPlugin);
},
},
vite: {
plugins: [
groupIconVitePlugin({
customIcon: {
'.mts': 'vscode-icons:file-type-typescript',
'.mdx': 'vscode-icons:file-type-light-mdx',
babel: 'vscode-icons:file-type-babel',
vitepress: localIconLoader(import.meta.url, '../public/logo/vitepress-logo-mini.svg'),
oxc: 'https://cdn.jsdelivr.net/gh/oxc-project/oxc-assets/round.svg',
},
}),
],
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ts
.mts文件
1
markdown
.mdx 文件
1
markdown
babel 文件
1
markdown
vitepress 文件
1
markdown
oxc 文件
1