diff --git a/plugins/plugin-shikiji/src/node/markdown/collapsedLinesPlugin.ts b/plugins/plugin-shikiji/src/node/markdown/collapsedLinesPlugin.ts
new file mode 100644
index 00000000..468ca1b0
--- /dev/null
+++ b/plugins/plugin-shikiji/src/node/markdown/collapsedLinesPlugin.ts
@@ -0,0 +1,61 @@
+import type { Markdown } from 'vuepress/markdown'
+import { resolveCollapsedLines } from '../utils/index.js'
+
+export interface MarkdownItCollapsedLinesOptions {
+ /**
+ * Whether to collapse code blocks when they exceed a certain number of lines,
+ *
+ * - If `number`, collapse starts from line `number`.
+ * - If `true`, collapse starts from line 15 by default.
+ * - If `false`, disable collapse.
+ * @default false
+ */
+ collapsedLines?: boolean | number
+}
+
+export function collapsedLinesPlugin(md: Markdown, {
+ collapsedLines: collapsedLinesOptions = false,
+}: MarkdownItCollapsedLinesOptions = {}): void {
+ const rawFence = md.renderer.rules.fence!
+
+ md.renderer.rules.fence = (...args) => {
+ const [tokens, index] = args
+ const token = tokens[index]
+ // get token info
+ const info = token.info ? md.utils.unescapeAll(token.info).trim() : ''
+ const code = rawFence(...args)
+
+ // resolve collapsed-lines mark from token info
+ const collapsedLinesInfo
+ = resolveCollapsedLines(info) ?? collapsedLinesOptions
+
+ if (collapsedLinesInfo === false) {
+ return code
+ }
+
+ const lines
+ = code.slice(code.indexOf(''), code.indexOf('')).split('\n').length
+
+ const startLines
+ = typeof collapsedLinesInfo === 'number' ? collapsedLinesInfo : 15
+
+ if (lines < startLines) {
+ return code
+ }
+
+ const collapsedLinesCode = `
]*>/, (match) => {
+ if (!match.includes('style=')) {
+ return `${match.slice(0, -1)} style="${styles}">`
+ }
+ return match.replace(/(style=")/, `$1${styles}`)
+ })
+
+ return finalCode
+ }
+}
diff --git a/plugins/plugin-shikiji/src/node/markdown/index.ts b/plugins/plugin-shikiji/src/node/markdown/index.ts
index 18c329c3..1ce8a03d 100644
--- a/plugins/plugin-shikiji/src/node/markdown/index.ts
+++ b/plugins/plugin-shikiji/src/node/markdown/index.ts
@@ -1,3 +1,4 @@
+export * from './collapsedLinesPlugin.js'
export * from './highlightLinesPlugin.js'
export * from './lineNumberPlugin.js'
export * from './preWrapperPlugin.js'
diff --git a/plugins/plugin-shikiji/src/node/markdown/preWrapperPlugin.ts b/plugins/plugin-shikiji/src/node/markdown/preWrapperPlugin.ts
index 089eae83..5da74fd3 100644
--- a/plugins/plugin-shikiji/src/node/markdown/preWrapperPlugin.ts
+++ b/plugins/plugin-shikiji/src/node/markdown/preWrapperPlugin.ts
@@ -1,12 +1,12 @@
// markdown-it plugin for generating line numbers.
// v-pre block logic is in `../highlight.ts`
import type { Markdown } from 'vuepress/markdown'
-import { resolveAttr, resolveCollapsedLines, resolveLanguage } from '../utils/index.js'
+import { resolveAttr, resolveLanguage } from '../utils/index.js'
import type { PreWrapperOptions } from '../types.js'
export function preWrapperPlugin(
md: Markdown,
- { preWrapper = true, collapsedLines = false }: PreWrapperOptions = {},
+ { preWrapper = true }: PreWrapperOptions = {},
): void {
const rawFence = md.renderer.rules.fence!
@@ -33,12 +33,6 @@ export function preWrapperPlugin(
`data-ext="${lang}"`,
`data-title="${title}"`,
]
- const collapsed = resolveCollapsedLines(info, collapsedLines)
- if (collapsed) {
- classes.push('has-collapsed', 'collapsed')
- attrs.push(`style="--vp-collapsed-lines:${collapsed}"`)
- result += `
`
- }
return `
${result}
`
}
diff --git a/plugins/plugin-shikiji/src/node/shikiPlugin.ts b/plugins/plugin-shikiji/src/node/shikiPlugin.ts
index 6cecdffc..6fbc7eda 100644
--- a/plugins/plugin-shikiji/src/node/shikiPlugin.ts
+++ b/plugins/plugin-shikiji/src/node/shikiPlugin.ts
@@ -3,6 +3,7 @@ import type { Plugin } from 'vuepress/core'
import { copyCodeButtonPlugin } from './copy-code-button/index.js'
import { highlight } from './highlight/index.js'
import {
+ collapsedLinesPlugin,
highlightLinesPlugin,
lineNumberPlugin,
preWrapperPlugin,
@@ -53,14 +54,12 @@ export function shikiPlugin({
md.options.highlight = await highlight(theme, options)
md.use(highlightLinesPlugin)
- md.use(preWrapperPlugin, {
- preWrapper,
- collapsedLines,
- })
+ md.use(preWrapperPlugin, { preWrapper })
if (preWrapper) {
copyCodeButtonPlugin(md, app, copyCode)
- md.use
(lineNumberPlugin, { lineNumbers })
+ md.use(lineNumberPlugin, { lineNumbers })
+ md.use(collapsedLinesPlugin, { collapsedLines })
}
},
diff --git a/plugins/plugin-shikiji/src/node/utils/collapsedLines.ts b/plugins/plugin-shikiji/src/node/utils/collapsedLines.ts
index 72d42f37..dddc8c7c 100644
--- a/plugins/plugin-shikiji/src/node/utils/collapsedLines.ts
+++ b/plugins/plugin-shikiji/src/node/utils/collapsedLines.ts
@@ -1,18 +1,24 @@
-export const COLLAPSED_LINES_REGEXP = /:collapsed-lines(?:=(\d+))?\b/
-export const NO_COLLAPSED_LINES_REGEXP = /:no-collapsed-lines\b/
+const COLLAPSED_LINES_REGEXP = /:collapsed-lines\b/
+const COLLAPSED_LINES_START_REGEXP = /:collapsed-lines=(\d+)\b/
+const NO_COLLAPSED_LINES_REGEXP = /:no-collapsed-lines\b/
-const DEFAULT_LINES = 15
+/**
+ * Resolve the `:collapsed-lines` `:collapsed-lines=num` / `:no-collapsed-lines` mark from token info
+ */
+export function resolveCollapsedLines(info: string): boolean | number | null {
+ const lines = COLLAPSED_LINES_START_REGEXP.exec(info)?.[1]
-export function resolveCollapsedLines(info: string, defaultLines: boolean | number): number | false {
- if (NO_COLLAPSED_LINES_REGEXP.test(info))
- return false
-
- const lines = defaultLines === true ? DEFAULT_LINES : defaultLines
-
- const match = info.match(COLLAPSED_LINES_REGEXP)
-
- if (match) {
- return Number(match[1]) || lines || DEFAULT_LINES
+ if (lines) {
+ return Number(lines)
}
- return lines ?? false
+
+ if (COLLAPSED_LINES_REGEXP.test(info)) {
+ return true
+ }
+
+ if (NO_COLLAPSED_LINES_REGEXP.test(info)) {
+ return false
+ }
+
+ return null
}