Skip to content

Commit 76ebc89

Browse files
committed
feat(plugin-markdown-code-tree): add code tree plugin (#603)
1 parent 81aaaa9 commit 76ebc89

36 files changed

Lines changed: 2876 additions & 12 deletions

File tree

AGENTS.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@ scripts/ # Shared build scripts (tsdown config, release helpers)
4848

4949
Plugins are grouped into sub-categories:
5050

51-
| Category | Plugins |
52-
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
53-
| `ai/` | `plugin-llms` — generates `llms.txt` / `llms-full.txt` for LLM crawlers |
54-
| `analytics/` | `plugin-baidu-analytics`, `plugin-clarity-analytics`, `plugin-google-analytics`, `plugin-umami-analytics` |
55-
| `blog/` | `plugin-blog`, `plugin-comment`, `plugin-feed` |
56-
| `development/` | `plugin-active-header-links`, `plugin-git`, `plugin-palette`, `plugin-reading-time`, `plugin-rtl`, `plugin-sass-palette`, `plugin-theme-data`, `plugin-toc` |
57-
| `features/` | `plugin-back-to-top`, `plugin-catalog`, `plugin-copy-code`, `plugin-copyright`, `plugin-icon`, `plugin-medium-zoom`, `plugin-notice`, `plugin-nprogress`, `plugin-photo-swipe`, `plugin-watermark` |
58-
| `markdown/` | `plugin-append-date`, `plugin-links-check`, `plugin-markdown-chart`, `plugin-markdown-container`, `plugin-markdown-ext`, `plugin-markdown-file-tree`, `plugin-markdown-hint`, `plugin-markdown-image`, `plugin-markdown-include`, `plugin-markdown-math`, `plugin-markdown-preview`, `plugin-markdown-stylize`, `plugin-markdown-tab`, `plugin-prismjs`, `plugin-revealjs`, `plugin-shiki` |
59-
| `pwa/` | `plugin-pwa`, `plugin-remove-pwa` |
60-
| `search/` | `plugin-docsearch`, `plugin-meilisearch`, `plugin-search`, `plugin-slimsearch` |
61-
| `seo/` | `plugin-seo`, `plugin-sitemap` |
62-
| `tools/` | `plugin-auto-frontmatter`, `plugin-cache`, `plugin-google-tag-manager`, `plugin-redirect`, `plugin-register-components`, `plugin-replace-assets` |
51+
| Category | Plugins |
52+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
53+
| `ai/` | `plugin-llms` — generates `llms.txt` / `llms-full.txt` for LLM crawlers |
54+
| `analytics/` | `plugin-baidu-analytics`, `plugin-clarity-analytics`, `plugin-google-analytics`, `plugin-umami-analytics` |
55+
| `blog/` | `plugin-blog`, `plugin-comment`, `plugin-feed` |
56+
| `development/` | `plugin-active-header-links`, `plugin-git`, `plugin-palette`, `plugin-reading-time`, `plugin-rtl`, `plugin-sass-palette`, `plugin-theme-data`, `plugin-toc` |
57+
| `features/` | `plugin-back-to-top`, `plugin-catalog`, `plugin-copy-code`, `plugin-copyright`, `plugin-icon`, `plugin-medium-zoom`, `plugin-notice`, `plugin-nprogress`, `plugin-photo-swipe`, `plugin-watermark` |
58+
| `markdown/` | `plugin-append-date`, `plugin-links-check`, `plugin-markdown-chart`, `plugin-markdown-code-tree`, `plugin-markdown-container`, `plugin-markdown-ext`, `plugin-markdown-field`, `plugin-markdown-file-tree`, `plugin-markdown-hint`, `plugin-markdown-image`, `plugin-markdown-include`, `plugin-markdown-math`, `plugin-markdown-preview`, `plugin-markdown-stylize`, `plugin-markdown-tab`, `plugin-prismjs`, `plugin-revealjs`, `plugin-shiki` |
59+
| `pwa/` | `plugin-pwa`, `plugin-remove-pwa` |
60+
| `search/` | `plugin-docsearch`, `plugin-meilisearch`, `plugin-search`, `plugin-slimsearch` |
61+
| `seo/` | `plugin-seo`, `plugin-sitemap` |
62+
| `tools/` | `plugin-auto-frontmatter`, `plugin-cache`, `plugin-google-tag-manager`, `plugin-redirect`, `plugin-register-components`, `plugin-replace-assets` |
6363

6464
### `themes/`
6565

docs/.vuepress/configs/plugins.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { feedPlugin } from '@vuepress/plugin-feed'
77
import { iconPlugin } from '@vuepress/plugin-icon'
88
import { llmsPlugin } from '@vuepress/plugin-llms'
99
import { markdownChartPlugin } from '@vuepress/plugin-markdown-chart'
10+
import { markdownCodeTreePlugin } from '@vuepress/plugin-markdown-code-tree'
1011
import { markdownExtPlugin } from '@vuepress/plugin-markdown-ext'
1112
import { markdownFieldPlugin } from '@vuepress/plugin-markdown-field'
1213
import { markdownFileTreePlugin } from '@vuepress/plugin-markdown-file-tree'
@@ -63,6 +64,7 @@ export const plugins = [
6364
'zh/plugins/markdown/markdown-chart/echarts',
6465
],
6566
}),
67+
markdownCodeTreePlugin(),
6668
markdownExtPlugin({
6769
gfm: true,
6870
component: true,

docs/.vuepress/configs/sidebar/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export const sidebarEn: SidebarOptions = {
124124
],
125125
},
126126
'markdown-container',
127+
'markdown-code-tree',
127128
'markdown-ext',
128129
'markdown-field',
129130
'markdown-file-tree',

docs/.vuepress/configs/sidebar/zh.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export const sidebarZh: SidebarOptions = {
124124
],
125125
},
126126
'markdown-container',
127+
'markdown-code-tree',
127128
'markdown-ext',
128129
'markdown-field',
129130
'markdown-file-tree',

docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"@vuepress/plugin-icon": "workspace:*",
2828
"@vuepress/plugin-llms": "workspace:*",
2929
"@vuepress/plugin-markdown-chart": "workspace:*",
30+
"@vuepress/plugin-markdown-code-tree": "workspace:*",
3031
"@vuepress/plugin-markdown-ext": "workspace:*",
3132
"@vuepress/plugin-markdown-field": "workspace:*",
3233
"@vuepress/plugin-markdown-file-tree": "workspace:*",
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
icon: file-code
3+
---
4+
5+
# markdown-code-tree
6+
7+
<NpmBadge package="@vuepress/plugin-markdown-code-tree" />
8+
9+
In Markdown, use the `::: code-tree` container to display the code blocks of several files together with a file tree, so that the structure of a small template is clear at a glance.
10+
11+
## Usage
12+
13+
```bash
14+
npm i -D @vuepress/plugin-markdown-code-tree@next
15+
```
16+
17+
```ts title=".vuepress/config.ts"
18+
import { markdownCodeTreePlugin } from '@vuepress/plugin-markdown-code-tree'
19+
20+
export default {
21+
plugins: [markdownCodeTreePlugin()],
22+
}
23+
```
24+
25+
## Syntax
26+
27+
Wrap several code blocks in a `::: code-tree` container, and add a `title="filepath"` attribute to a code block to declare the file it belongs to.
28+
29+
````md
30+
::: code-tree title="Project Name" height="400px" entry="src/index.ts"
31+
32+
```ts title="src/index.ts"
33+
console.log('main')
34+
```
35+
36+
```json title="package.json"
37+
{}
38+
```
39+
40+
:::
41+
````
42+
43+
- Add a title after the `::: code-tree` container to declare the title of the code tree.
44+
- Add a `height` attribute after the `::: code-tree` container to declare the height of the code tree. A bare number is treated as pixels.
45+
- Add an `entry` attribute after the `::: code-tree` container to declare the file opened by default.
46+
- Add `:active` after a code block to declare the file opened by default, which has a higher priority than `entry`.
47+
- When neither `entry` nor `:active` is declared, the first code block is opened by default.
48+
49+
Code blocks without a `title` attribute are not included in the file tree, and they are not displayed.
50+
51+
Files and folders are displayed with their icons. The icons come from <https://icon-sets.iconify.design/> and are rendered by `<VPIcon />` provided by `@vuepress/plugin-icon`. When that plugin is not enabled, a generic file or folder icon is used instead.
52+
53+
## Related
54+
55+
Only the container syntax is supported. The `@[code-tree](dir_path)` syntax of other themes is not supported.
56+
57+
::: warning
58+
59+
The code tree relies on the code block title feature of the highlighter, which is enabled by default in `@vuepress/plugin-shiki` and `@vuepress/plugin-prismjs`.
60+
61+
Do not disable `codeBlockTitle`, or replace it with a custom render function, otherwise the file tree is rendered without any code block.
62+
63+
:::
64+
65+
## Example
66+
67+
**Input:**
68+
69+
````md
70+
::: code-tree title="Vue App" height="400px" entry="src/main.ts"
71+
72+
```vue title="src/components/HelloWorld.vue"
73+
<template>
74+
<div class="hello">
75+
<h1>Hello World</h1>
76+
</div>
77+
</template>
78+
```
79+
80+
```vue title="src/App.vue"
81+
<template>
82+
<div id="app">
83+
<h3>Vue App</h3>
84+
<HelloWorld />
85+
</div>
86+
</template>
87+
```
88+
89+
```ts title="src/main.ts"
90+
import { createApp } from 'vue'
91+
import App from './App.vue'
92+
93+
createApp(App).mount('#app')
94+
```
95+
96+
```json title="package.json"
97+
{
98+
"name": "Vue App",
99+
"scripts": {
100+
"dev": "vite"
101+
}
102+
}
103+
```
104+
105+
:::
106+
````
107+
108+
**Output:**
109+
110+
::: code-tree title="Vue App" height="400px" entry="src/main.ts"
111+
112+
```vue title="src/components/HelloWorld.vue"
113+
<template>
114+
<div class="hello">
115+
<h1>Hello World</h1>
116+
</div>
117+
</template>
118+
```
119+
120+
```vue title="src/App.vue"
121+
<template>
122+
<div id="app">
123+
<h3>Vue App</h3>
124+
<HelloWorld />
125+
</div>
126+
</template>
127+
```
128+
129+
```ts title="src/main.ts"
130+
import { createApp } from 'vue'
131+
import App from './App.vue'
132+
133+
createApp(App).mount('#app')
134+
```
135+
136+
```json title="package.json"
137+
{
138+
"name": "Vue App",
139+
"scripts": {
140+
"dev": "vite"
141+
}
142+
}
143+
```
144+
145+
:::
146+
147+
## Options
148+
149+
### height
150+
151+
- Type: `number | string`
152+
- Default: `'320px'`
153+
- Details: The default height of the code tree. A number will be treated as pixels.
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
icon: file-code
3+
---
4+
5+
# markdown-code-tree
6+
7+
<NpmBadge package="@vuepress/plugin-markdown-code-tree" />
8+
9+
在 Markdown 中,使用 `::: code-tree` 容器,将多个文件的代码块和文件树一起展示,让小型模板的结构一目了然。
10+
11+
## 使用
12+
13+
```bash
14+
npm i -D @vuepress/plugin-markdown-code-tree@next
15+
```
16+
17+
```ts title=".vuepress/config.ts"
18+
import { markdownCodeTreePlugin } from '@vuepress/plugin-markdown-code-tree'
19+
20+
export default {
21+
plugins: [markdownCodeTreePlugin()],
22+
}
23+
```
24+
25+
## 语法
26+
27+
使用 `::: code-tree` 容器包裹多个代码块,并在代码块上使用 `title="文件路径"` 属性声明其所属的文件。
28+
29+
````md
30+
::: code-tree title="Project Name" height="400px" entry="src/index.ts"
31+
32+
```ts title="src/index.ts"
33+
console.log('main')
34+
```
35+
36+
```json title="package.json"
37+
{}
38+
```
39+
40+
:::
41+
````
42+
43+
-`::: code-tree` 容器后添加标题来声明代码树的标题。
44+
-`::: code-tree` 容器后添加 `height` 属性来声明代码树的高度。纯数字会被视为像素值。
45+
-`::: code-tree` 容器后添加 `entry` 属性来声明默认打开的文件。
46+
- 在代码块后添加 `:active` 来声明默认打开的文件,其优先级高于 `entry`
47+
-`entry``:active` 均未声明时,默认打开第一个代码块。
48+
49+
未使用 `title` 属性声明文件路径的代码块不会出现在文件树中,也不会被显示。
50+
51+
文件和文件夹会展示各自的图标。图标来自 <https://icon-sets.iconify.design/>,由 `@vuepress/plugin-icon` 提供的 `<VPIcon />` 渲染。未启用该插件时,将使用通用的文件或文件夹图标。
52+
53+
## 相关
54+
55+
仅支持容器语法,不支持其他主题的 `@[code-tree](dir_path)` 语法。
56+
57+
::: warning
58+
59+
代码树依赖高亮器的代码块标题功能,该功能在 `@vuepress/plugin-shiki``@vuepress/plugin-prismjs` 中默认启用。
60+
61+
请勿关闭 `codeBlockTitle`,或将其替换为自定义渲染函数,否则文件树将不会渲染出任何代码块。
62+
63+
:::
64+
65+
## 示例
66+
67+
**输入:**
68+
69+
````md
70+
::: code-tree title="Vue App" height="400px" entry="src/main.ts"
71+
72+
```vue title="src/components/HelloWorld.vue"
73+
<template>
74+
<div class="hello">
75+
<h1>Hello World</h1>
76+
</div>
77+
</template>
78+
```
79+
80+
```vue title="src/App.vue"
81+
<template>
82+
<div id="app">
83+
<h3>Vue App</h3>
84+
<HelloWorld />
85+
</div>
86+
</template>
87+
```
88+
89+
```ts title="src/main.ts"
90+
import { createApp } from 'vue'
91+
import App from './App.vue'
92+
93+
createApp(App).mount('#app')
94+
```
95+
96+
```json title="package.json"
97+
{
98+
"name": "Vue App",
99+
"scripts": {
100+
"dev": "vite"
101+
}
102+
}
103+
```
104+
105+
:::
106+
````
107+
108+
**输出:**
109+
110+
::: code-tree title="Vue App" height="400px" entry="src/main.ts"
111+
112+
```vue title="src/components/HelloWorld.vue"
113+
<template>
114+
<div class="hello">
115+
<h1>Hello World</h1>
116+
</div>
117+
</template>
118+
```
119+
120+
```vue title="src/App.vue"
121+
<template>
122+
<div id="app">
123+
<h3>Vue App</h3>
124+
<HelloWorld />
125+
</div>
126+
</template>
127+
```
128+
129+
```ts title="src/main.ts"
130+
import { createApp } from 'vue'
131+
import App from './App.vue'
132+
133+
createApp(App).mount('#app')
134+
```
135+
136+
```json title="package.json"
137+
{
138+
"name": "Vue App",
139+
"scripts": {
140+
"dev": "vite"
141+
}
142+
}
143+
```
144+
145+
:::
146+
147+
## 选项
148+
149+
### height
150+
151+
- 类型:`number | string`
152+
- 默认值:`'320px'`
153+
- 详情:代码树的默认高度。数字将被视为像素值。

e2e/docs/.vuepress/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { blogPlugin } from '@vuepress/plugin-blog'
1313
import { catalogPlugin } from '@vuepress/plugin-catalog'
1414
import { copyrightPlugin } from '@vuepress/plugin-copyright'
1515
import { feedPlugin } from '@vuepress/plugin-feed'
16+
import { markdownCodeTreePlugin } from '@vuepress/plugin-markdown-code-tree'
1617
import { noticePlugin } from '@vuepress/plugin-notice'
1718
import { photoSwipePlugin } from '@vuepress/plugin-photo-swipe'
1819
import { pwaPlugin } from '@vuepress/plugin-pwa'
@@ -247,6 +248,7 @@ export default defineUserConfig({
247248
json: true,
248249
rss: true,
249250
}),
251+
markdownCodeTreePlugin(),
250252
noticePlugin({
251253
config: [
252254
{

0 commit comments

Comments
 (0)