vitepress-plugin-code-collapse 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/client/browser/index.d.ts +31 -0
- package/dist/client/browser/index.js +42 -0
- package/dist/client/ssr/index.d.ts +31 -0
- package/dist/client/ssr/index.js +41 -0
- package/dist/client/style.css +75 -0
- package/dist/node/index.d.ts +62 -0
- package/dist/node/index.js +116 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pengzhanbo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# vitepress-plugin-code-collapse
|
|
2
|
+
|
|
3
|
+
provide code block collapsed lines feature
|
|
4
|
+
|
|
5
|
+
在 VitePress 中提供代码块折叠行功能。
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
### With Vitepress-tuck
|
|
10
|
+
|
|
11
|
+
**Installation:**
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# npm
|
|
15
|
+
npm install -D vitepress-tuck vitepress-plugin-code-collapse
|
|
16
|
+
# pnpm
|
|
17
|
+
pnpm add -D vitepress-tuck vitepress-plugin-code-collapse
|
|
18
|
+
# yarn
|
|
19
|
+
yarn add -D vitepress-tuck vitepress-plugin-code-collapse
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Configuration:**
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
// .vitepress/config.ts
|
|
26
|
+
import codeCollapse from 'vitepress-plugin-code-collapse'
|
|
27
|
+
import { defineConfig } from 'vitepress-tuck'
|
|
28
|
+
|
|
29
|
+
export default defineConfig({
|
|
30
|
+
plugins: [codeCollapse()],
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// .vitepress/theme/index.ts
|
|
36
|
+
import type { Theme } from 'vitepress'
|
|
37
|
+
import enhanceApp from 'virtual:enhance-app'
|
|
38
|
+
import DefaultTheme from 'vitepress/theme'
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
extends: DefaultTheme,
|
|
42
|
+
enhanceApp(ctx) {
|
|
43
|
+
enhanceApp(ctx)
|
|
44
|
+
},
|
|
45
|
+
} satisfies Theme
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### With Vitepress
|
|
49
|
+
|
|
50
|
+
**Installation:**
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# npm
|
|
54
|
+
npm install -D vitepress-plugin-code-collapse
|
|
55
|
+
# pnpm
|
|
56
|
+
pnpm add -D vitepress-plugin-code-collapse
|
|
57
|
+
# yarn
|
|
58
|
+
yarn add -D vitepress-plugin-code-collapse
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Configuration:**
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
// .vitepress/config.ts
|
|
65
|
+
import { defineConfig } from 'vitepress'
|
|
66
|
+
import { collapsedLinesMarkdownPlugin } from 'vitepress-plugin-code-collapse'
|
|
67
|
+
|
|
68
|
+
export default defineConfig({
|
|
69
|
+
markdown: {
|
|
70
|
+
config: (md) => {
|
|
71
|
+
md.use(collapsedLinesMarkdownPlugin)
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// .vitepress/theme/index.ts
|
|
79
|
+
import type { Theme } from 'vitepress'
|
|
80
|
+
import { enhanceAppWithCollapsedLines } from 'vitepress-plugin-code-collapse/client'
|
|
81
|
+
import DefaultTheme from 'vitepress/theme'
|
|
82
|
+
|
|
83
|
+
export default {
|
|
84
|
+
extends: DefaultTheme,
|
|
85
|
+
enhanceApp(ctx) {
|
|
86
|
+
enhanceAppWithCollapsedLines(ctx)
|
|
87
|
+
},
|
|
88
|
+
} satisfies Theme
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Syntax
|
|
92
|
+
|
|
93
|
+
use `:collapsed-lines` to collapse lines in code block.
|
|
94
|
+
|
|
95
|
+
````md
|
|
96
|
+
```ts :collapsed-lines
|
|
97
|
+
const a = 1
|
|
98
|
+
```
|
|
99
|
+
````
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/client/setupCollapsedLines.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Setup collapsed lines functionality for code blocks
|
|
4
|
+
*
|
|
5
|
+
* 为代码块设置折叠行功能
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import { setupCollapsedLines } from '@vuepress/highlighter-helper/client'
|
|
9
|
+
*
|
|
10
|
+
* // Use default selector
|
|
11
|
+
* setupCollapsedLines()
|
|
12
|
+
*
|
|
13
|
+
* // Use custom selector
|
|
14
|
+
* setupCollapsedLines({
|
|
15
|
+
* selector: '.my-collapsed-lines',
|
|
16
|
+
* })
|
|
17
|
+
*
|
|
18
|
+
* @param options - Setup options / 设置选项
|
|
19
|
+
* @param options.selector - CSS selector for collapsed lines elements / 折叠行元素的
|
|
20
|
+
* CSS 选择器
|
|
21
|
+
*/
|
|
22
|
+
declare function setupCollapsedLines({
|
|
23
|
+
selector
|
|
24
|
+
}?: {
|
|
25
|
+
selector?: string;
|
|
26
|
+
}): void;
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/client/index.d.ts
|
|
29
|
+
declare function enhanceAppWithCollapsedLines(): void;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { enhanceAppWithCollapsedLines, setupCollapsedLines };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import "../style.css";
|
|
2
|
+
import { useEventListener } from "@vueuse/core";
|
|
3
|
+
//#region src/client/setupCollapsedLines.ts
|
|
4
|
+
/**
|
|
5
|
+
* Setup collapsed lines functionality for code blocks
|
|
6
|
+
*
|
|
7
|
+
* 为代码块设置折叠行功能
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* import { setupCollapsedLines } from '@vuepress/highlighter-helper/client'
|
|
11
|
+
*
|
|
12
|
+
* // Use default selector
|
|
13
|
+
* setupCollapsedLines()
|
|
14
|
+
*
|
|
15
|
+
* // Use custom selector
|
|
16
|
+
* setupCollapsedLines({
|
|
17
|
+
* selector: '.my-collapsed-lines',
|
|
18
|
+
* })
|
|
19
|
+
*
|
|
20
|
+
* @param options - Setup options / 设置选项
|
|
21
|
+
* @param options.selector - CSS selector for collapsed lines elements / 折叠行元素的
|
|
22
|
+
* CSS 选择器
|
|
23
|
+
*/
|
|
24
|
+
function setupCollapsedLines({ selector = "div[class*=\"language-\"].has-collapsed-lines > .collapsed-lines" } = {}) {
|
|
25
|
+
useEventListener("click", (event) => {
|
|
26
|
+
const target = event.target;
|
|
27
|
+
if (target.matches(selector)) {
|
|
28
|
+
const parent = target.parentElement;
|
|
29
|
+
if (parent?.classList.toggle("collapsed")) parent.scrollIntoView({
|
|
30
|
+
block: "center",
|
|
31
|
+
behavior: "instant"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}, { passive: true });
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/client/index.ts
|
|
38
|
+
function enhanceAppWithCollapsedLines() {
|
|
39
|
+
setupCollapsedLines();
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { enhanceAppWithCollapsedLines, setupCollapsedLines };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/client/setupCollapsedLines.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Setup collapsed lines functionality for code blocks
|
|
4
|
+
*
|
|
5
|
+
* 为代码块设置折叠行功能
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import { setupCollapsedLines } from '@vuepress/highlighter-helper/client'
|
|
9
|
+
*
|
|
10
|
+
* // Use default selector
|
|
11
|
+
* setupCollapsedLines()
|
|
12
|
+
*
|
|
13
|
+
* // Use custom selector
|
|
14
|
+
* setupCollapsedLines({
|
|
15
|
+
* selector: '.my-collapsed-lines',
|
|
16
|
+
* })
|
|
17
|
+
*
|
|
18
|
+
* @param options - Setup options / 设置选项
|
|
19
|
+
* @param options.selector - CSS selector for collapsed lines elements / 折叠行元素的
|
|
20
|
+
* CSS 选择器
|
|
21
|
+
*/
|
|
22
|
+
declare function setupCollapsedLines({
|
|
23
|
+
selector
|
|
24
|
+
}?: {
|
|
25
|
+
selector?: string;
|
|
26
|
+
}): void;
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/client/index.d.ts
|
|
29
|
+
declare function enhanceAppWithCollapsedLines(): void;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { enhanceAppWithCollapsedLines, setupCollapsedLines };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEventListener } from "@vueuse/core";
|
|
2
|
+
//#region src/client/setupCollapsedLines.ts
|
|
3
|
+
/**
|
|
4
|
+
* Setup collapsed lines functionality for code blocks
|
|
5
|
+
*
|
|
6
|
+
* 为代码块设置折叠行功能
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import { setupCollapsedLines } from '@vuepress/highlighter-helper/client'
|
|
10
|
+
*
|
|
11
|
+
* // Use default selector
|
|
12
|
+
* setupCollapsedLines()
|
|
13
|
+
*
|
|
14
|
+
* // Use custom selector
|
|
15
|
+
* setupCollapsedLines({
|
|
16
|
+
* selector: '.my-collapsed-lines',
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* @param options - Setup options / 设置选项
|
|
20
|
+
* @param options.selector - CSS selector for collapsed lines elements / 折叠行元素的
|
|
21
|
+
* CSS 选择器
|
|
22
|
+
*/
|
|
23
|
+
function setupCollapsedLines({ selector = "div[class*=\"language-\"].has-collapsed-lines > .collapsed-lines" } = {}) {
|
|
24
|
+
useEventListener("click", (event) => {
|
|
25
|
+
const target = event.target;
|
|
26
|
+
if (target.matches(selector)) {
|
|
27
|
+
const parent = target.parentElement;
|
|
28
|
+
if (parent?.classList.toggle("collapsed")) parent.scrollIntoView({
|
|
29
|
+
block: "center",
|
|
30
|
+
behavior: "instant"
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}, { passive: true });
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/client/index.ts
|
|
37
|
+
function enhanceAppWithCollapsedLines() {
|
|
38
|
+
setupCollapsedLines();
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { enhanceAppWithCollapsedLines, setupCollapsedLines };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* stylelint-disable no-descending-specificity */
|
|
2
|
+
:root {
|
|
3
|
+
--vp-collapsed-lines-icon: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-width='2' d='m18 12l-6 6l-6-6m12-6l-6 6l-6-6'/%3E%3C/svg%3E");
|
|
4
|
+
--vp-collapsed-lines-rotate: 0deg;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
@property --vp-collapsed-lines-bg {
|
|
8
|
+
inherits: false;
|
|
9
|
+
initial-value: #fff;
|
|
10
|
+
syntax: "<color>";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@keyframes code-collapsed-lines {
|
|
14
|
+
0% {
|
|
15
|
+
opacity: 0.3;
|
|
16
|
+
transform: translateY(-2px) rotate(var(--vp-collapsed-lines-rotate));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
100% {
|
|
20
|
+
opacity: 1;
|
|
21
|
+
transform: translateY(2px) rotate(var(--vp-collapsed-lines-rotate));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
div[class*="language-"].has-collapsed-lines .collapsed-lines {
|
|
26
|
+
--vp-collapsed-lines-bg: var(--vp-code-block-bg);
|
|
27
|
+
|
|
28
|
+
position: absolute;
|
|
29
|
+
right: 0;
|
|
30
|
+
bottom: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
z-index: 4;
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
height: 28px;
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
background: linear-gradient(to bottom, transparent 0%, var(--vp-collapsed-lines-bg) 55%, var(--vp-collapsed-lines-bg) 100%);
|
|
39
|
+
transition: --vp-collapsed-lines-bg 0.2s ease-in-out;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
div[class*="language-"].has-collapsed-lines .collapsed-lines:hover {
|
|
43
|
+
--vp-collapsed-lines-bg: var(--vp-c-default-soft);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
div[class*="language-"].has-collapsed-lines .collapsed-lines::before {
|
|
47
|
+
display: inline-block;
|
|
48
|
+
width: 24px;
|
|
49
|
+
height: 24px;
|
|
50
|
+
pointer-events: none;
|
|
51
|
+
content: "";
|
|
52
|
+
background-color: var(--vp-code-block-color);
|
|
53
|
+
mask-image: var(--vp-collapsed-lines-icon);
|
|
54
|
+
mask-repeat: no-repeat;
|
|
55
|
+
mask-position: 50%;
|
|
56
|
+
mask-size: 20px;
|
|
57
|
+
animation: 1.2s ease-in-out infinite alternate-reverse code-collapsed-lines;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
div[class*="language-"].has-collapsed-lines[data-highlighter="shiki"] .collapsed-lines {
|
|
61
|
+
--vp-collapsed-lines-bg: var(--vp-code-block-bg, var(--shiki-light-bg));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
[data-theme="dark"] div[class*="language-"].has-collapsed-lines[data-highlighter="shiki"] .collapsed-lines {
|
|
65
|
+
--vp-collapsed-lines-bg: var(--vp-code-block-bg, var(--shiki-dark-bg));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
div[class*="language-"].has-collapsed-lines.collapsed {
|
|
69
|
+
height: calc(var(--vp-collapsed-lines) * var(--vp-code-line-height) * var(--vp-code-font-size) + 48px);
|
|
70
|
+
overflow-y: hidden;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
div[class*="language-"].has-collapsed-lines:not(.collapsed) .collapsed-lines {
|
|
74
|
+
--vp-collapsed-lines-rotate: 180deg;
|
|
75
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { PluginWithOptions } from "markdown-it";
|
|
2
|
+
|
|
3
|
+
//#region src/node/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Whether to collapse code blocks when they exceed a certain number of lines
|
|
6
|
+
*
|
|
7
|
+
* - If `number`, collapse starts from line `number`.
|
|
8
|
+
* - If `true`, collapse starts from line 15 by default.
|
|
9
|
+
* - If `false`, do not enable code block collapsing globally, but you can
|
|
10
|
+
* enable it for individual code blocks using `:collapsed-lines`
|
|
11
|
+
* - If `'disable'`, Completely disable code block collapsing
|
|
12
|
+
*
|
|
13
|
+
* 当代码块超过一定行数时是否折叠
|
|
14
|
+
*
|
|
15
|
+
* - 如果是 `number`,从第 `number` 行开始折叠
|
|
16
|
+
* - 如果是 `true`,默认从第 15 行开始折叠
|
|
17
|
+
* - 如果是 `false`,不全局启用代码块折叠,但你可以为单个代码块使用 `:collapsed-lines` 启用
|
|
18
|
+
* - 如果是 `'disable'`,完全禁用代码块折叠
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
type CollapsedLinesOptions = boolean | number | 'disable';
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/node/codeCollapsePlugin.d.ts
|
|
25
|
+
/**
|
|
26
|
+
* Add collapsed lines functionality to code blocks in markdown-it
|
|
27
|
+
*
|
|
28
|
+
* 为 markdown-it 中的代码块添加折叠行功能
|
|
29
|
+
*
|
|
30
|
+
* @param md - MarkdownIt instance / MarkdownIt 实例
|
|
31
|
+
* @param options - Plugin options / 插件选项
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* import { collapsedLinesMarkdownPlugin } from 'vitepress-code-collapse'
|
|
36
|
+
* import { defineConfig } from 'vitepress'
|
|
37
|
+
* export default defineConfig({
|
|
38
|
+
* markdown: {
|
|
39
|
+
* config(md) {
|
|
40
|
+
* md.use(collapsedLinesMarkdownPlugin)
|
|
41
|
+
* }
|
|
42
|
+
* }
|
|
43
|
+
* })
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare const collapsedLinesMarkdownPlugin: PluginWithOptions<CollapsedLinesOptions>;
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/node/index.d.ts
|
|
49
|
+
/**
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import collapsedLines from 'vitepress-code-collapse'
|
|
53
|
+
* import { defineConfig } from 'vitepress-tuck'
|
|
54
|
+
* export default defineConfig({
|
|
55
|
+
* plugins: [collapsedLines()]
|
|
56
|
+
* })
|
|
57
|
+
* ```
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare const _default: (option?: number | boolean | "disable" | undefined) => import("vitepress-tuck").VitepressPlugin;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { collapsedLinesMarkdownPlugin, _default as default };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { definePlugin } from "vitepress-tuck";
|
|
2
|
+
//#region src/node/resolveCollapsedLine.ts
|
|
3
|
+
/**
|
|
4
|
+
* Regular expression to match `:collapsed-lines` directive in code block info
|
|
5
|
+
*
|
|
6
|
+
* 匹配代码块信息中 `:collapsed-lines` 指令的正则表达式
|
|
7
|
+
*/
|
|
8
|
+
const COLLAPSED_LINES_REGEXP = /:collapsed-lines\b/u;
|
|
9
|
+
/**
|
|
10
|
+
* Regular expression to match `:collapsed-lines=num` directive in code block
|
|
11
|
+
* info
|
|
12
|
+
*
|
|
13
|
+
* 匹配代码块信息中 `:collapsed-lines=num` 指令的正则表达式
|
|
14
|
+
*/
|
|
15
|
+
const COLLAPSED_LINES_START_REGEXP = /:collapsed-lines=(\d+)\b/u;
|
|
16
|
+
/**
|
|
17
|
+
* Regular expression to match `:no-collapsed-lines` directive in code block
|
|
18
|
+
* info
|
|
19
|
+
*
|
|
20
|
+
* 匹配代码块信息中 `:no-collapsed-lines` 指令的正则表达式
|
|
21
|
+
*/
|
|
22
|
+
const NO_COLLAPSED_LINES_REGEXP = /:no-collapsed-lines\b/u;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the `:collapsed-lines` `:collapsed-lines=num` / `:no-collapsed-lines`
|
|
25
|
+
* mark from token info
|
|
26
|
+
*
|
|
27
|
+
* 从 token 信息中解析 `:collapsed-lines` `:collapsed-lines=num` /
|
|
28
|
+
* `:no-collapsed-lines` 标记
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* resolveCollapsedLines('js :collapsed-lines') // true
|
|
32
|
+
* resolveCollapsedLines('js :collapsed-lines=20') // 20
|
|
33
|
+
* resolveCollapsedLines('js :no-collapsed-lines') // false
|
|
34
|
+
* resolveCollapsedLines('js') // null
|
|
35
|
+
*
|
|
36
|
+
* @param info - Code block info string / 代码块信息字符串
|
|
37
|
+
* @returns Collapsed lines configuration / 折叠行配置
|
|
38
|
+
*
|
|
39
|
+
* - `number` - Start line number for collapsing / 折叠起始行号
|
|
40
|
+
* - `true` - Enable collapsed lines / 启用折叠行
|
|
41
|
+
* - `false` - Disable collapsed lines / 禁用折叠行
|
|
42
|
+
* - `null` - No configuration found / 未找到配置
|
|
43
|
+
*/
|
|
44
|
+
function resolveCollapsedLines(info) {
|
|
45
|
+
const lines = COLLAPSED_LINES_START_REGEXP.exec(info)?.[1];
|
|
46
|
+
if (lines) return Number(lines);
|
|
47
|
+
if (COLLAPSED_LINES_REGEXP.test(info)) return true;
|
|
48
|
+
if (NO_COLLAPSED_LINES_REGEXP.test(info)) return false;
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/node/codeCollapsePlugin.ts
|
|
53
|
+
/**
|
|
54
|
+
* Add collapsed lines functionality to code blocks in markdown-it
|
|
55
|
+
*
|
|
56
|
+
* 为 markdown-it 中的代码块添加折叠行功能
|
|
57
|
+
*
|
|
58
|
+
* @param md - MarkdownIt instance / MarkdownIt 实例
|
|
59
|
+
* @param options - Plugin options / 插件选项
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* import { collapsedLinesMarkdownPlugin } from 'vitepress-code-collapse'
|
|
64
|
+
* import { defineConfig } from 'vitepress'
|
|
65
|
+
* export default defineConfig({
|
|
66
|
+
* markdown: {
|
|
67
|
+
* config(md) {
|
|
68
|
+
* md.use(collapsedLinesMarkdownPlugin)
|
|
69
|
+
* }
|
|
70
|
+
* }
|
|
71
|
+
* })
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
const collapsedLinesMarkdownPlugin = (md, options = false) => {
|
|
75
|
+
if (options === "disable") return;
|
|
76
|
+
const rawFence = md.renderer.rules.fence;
|
|
77
|
+
md.renderer.rules.fence = (...args) => {
|
|
78
|
+
const [tokens, index] = args;
|
|
79
|
+
const token = tokens[index];
|
|
80
|
+
const info = token.info ? md.utils.unescapeAll(token.info).trim() : "";
|
|
81
|
+
const code = rawFence(...args);
|
|
82
|
+
const collapsedLinesInfo = resolveCollapsedLines(info) ?? options;
|
|
83
|
+
if (collapsedLinesInfo === false) return code;
|
|
84
|
+
const lines = code.slice(code.indexOf("<code>"), code.indexOf("</code>")).split("\n").length;
|
|
85
|
+
const startLines = typeof collapsedLinesInfo === "number" ? collapsedLinesInfo : 15;
|
|
86
|
+
if (lines < startLines) return code;
|
|
87
|
+
const collapsedLinesCode = `<div class="collapsed-lines"></div>`;
|
|
88
|
+
const styles = `--vp-collapsed-lines:${startLines};`;
|
|
89
|
+
return code.replace(/<\/div>$/u, `${collapsedLinesCode}</div>`).replace(/"(language-[^"]*)"/u, "\"$1 has-collapsed-lines collapsed\"").replace(/^<div[^>]*>/u, (match) => {
|
|
90
|
+
if (!match.includes("style=")) return `${match.slice(0, -1)} style="${styles}">`;
|
|
91
|
+
return match.replace(/(style=")/u, `$1${styles}`);
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/node/index.ts
|
|
97
|
+
/**
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* import collapsedLines from 'vitepress-code-collapse'
|
|
101
|
+
* import { defineConfig } from 'vitepress-tuck'
|
|
102
|
+
* export default defineConfig({
|
|
103
|
+
* plugins: [collapsedLines()]
|
|
104
|
+
* })
|
|
105
|
+
* ```
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
var node_default = definePlugin((options) => ({
|
|
109
|
+
name: "vitepress-plugin-code-collapse",
|
|
110
|
+
client: { enhance: "enhanceAppWithCollapsedLines" },
|
|
111
|
+
markdown: { config: (md) => {
|
|
112
|
+
md.use(collapsedLinesMarkdownPlugin, options);
|
|
113
|
+
} }
|
|
114
|
+
}));
|
|
115
|
+
//#endregion
|
|
116
|
+
export { collapsedLinesMarkdownPlugin, node_default as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vitepress-plugin-code-collapse",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "provide code block collapsed lines feature",
|
|
6
|
+
"author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"vitepress",
|
|
10
|
+
"vitepress-plugin",
|
|
11
|
+
"code-collapse",
|
|
12
|
+
"collapsed-lines"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./dist/node/index.js",
|
|
16
|
+
"./client": {
|
|
17
|
+
"browser": "./dist/client/browser/index.js",
|
|
18
|
+
"default": "./dist/client/ssr/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./style.css": "./dist/client/style.css"
|
|
21
|
+
},
|
|
22
|
+
"module": "./dist/node/index.js",
|
|
23
|
+
"types": "./dist/node/index.d.ts",
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"vitepress": "^1.6.4 || ^2.0.0-alpha.17",
|
|
29
|
+
"vue": "^3.5.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@vueuse/core": "^14.3.0",
|
|
33
|
+
"vitepress-plugin-toolkit": "0.1.0",
|
|
34
|
+
"vitepress-tuck": "0.1.0"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"clean": "rimraf --glob ./dist",
|
|
41
|
+
"dev": "pnpm '/(tsdown|copy):watch/'",
|
|
42
|
+
"build": "pnpm tsdown && pnpm copy",
|
|
43
|
+
"copy": "cpx \"src/**/*.css\" dist",
|
|
44
|
+
"copy:watch": "pnpm copy -w",
|
|
45
|
+
"tsdown": "tsdown --config-loader unrun",
|
|
46
|
+
"tsdown:watch": "pnpm tsdown -w"
|
|
47
|
+
}
|
|
48
|
+
}
|