From 3cf63c44f01b291699d38eda7bd2b2e610947118 Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Tue, 28 May 2024 17:48:10 +0800 Subject: [PATCH 1/8] feat: add `:line-numbers=number` supports --- .../src/node/markdown/lineNumbersPlugin.ts | 10 ++++++- .../src/node/markdown/lineNumberPlugin.ts | 9 ++++++- .../theme-default/src/client/styles/code.scss | 26 ++++++++++++++----- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/plugins/plugin-prismjs/src/node/markdown/lineNumbersPlugin.ts b/plugins/plugin-prismjs/src/node/markdown/lineNumbersPlugin.ts index 59a61450e4..f2c4ba7c9c 100644 --- a/plugins/plugin-prismjs/src/node/markdown/lineNumbersPlugin.ts +++ b/plugins/plugin-prismjs/src/node/markdown/lineNumbersPlugin.ts @@ -2,6 +2,8 @@ import type { Markdown } from 'vuepress/markdown' import type { LineNumbersOptions } from '../types.js' import { resolveLineNumbers } from '../utils/index.js' +const LINE_NUMBERS_START_REGEXP = /:line-numbers=(\d+)\b/ + export const lineNumbersPlugin = ( md: Markdown, { lineNumbers = true }: LineNumbersOptions = {}, @@ -33,8 +35,14 @@ export const lineNumbersPlugin = ( return rawCode } + const startNumbers = Number(info.match(LINE_NUMBERS_START_REGEXP)?.[1] ?? 1) + + /** + * Originally intended to use `counter-reset: line-number attr(data-start number)`, + * but due to its poor compatibility, the current approach was chosen. + */ const lineNumbersCode = [...Array(lines.length)] - .map(() => `
`) + .map((_, i) => `
${startNumbers + i}
`) .join('') const lineNumbersWrapperCode = `` diff --git a/plugins/plugin-shiki/src/node/markdown/lineNumberPlugin.ts b/plugins/plugin-shiki/src/node/markdown/lineNumberPlugin.ts index 577e3cda1c..024dec7a5c 100644 --- a/plugins/plugin-shiki/src/node/markdown/lineNumberPlugin.ts +++ b/plugins/plugin-shiki/src/node/markdown/lineNumberPlugin.ts @@ -6,6 +6,7 @@ import type { LineNumberOptions } from '../types.js' const LINE_NUMBERS_REGEXP = /:line-numbers\b/ const NO_LINE_NUMBERS_REGEXP = /:no-line-numbers\b/ +const LINE_NUMBERS_START_REGEXP = /:line-numbers=(\d+)\b/ export const lineNumberPlugin = ( md: Markdown, @@ -43,8 +44,14 @@ export const lineNumberPlugin = ( return rawCode } + const startNumbers = Number(info.match(LINE_NUMBERS_START_REGEXP)?.[1] ?? 1) + + /** + * Originally intended to use `counter-reset: line-number attr(data-start number)`, + * but due to its poor compatibility, the current approach was chosen. + */ const lineNumbersCode = [...Array(lines.length)] - .map(() => `
`) + .map((_, i) => `
${startNumbers + i}
`) .join('') const lineNumbersWrapperCode = `` diff --git a/themes/theme-default/src/client/styles/code.scss b/themes/theme-default/src/client/styles/code.scss index f080689b58..426ae25475 100644 --- a/themes/theme-default/src/client/styles/code.scss +++ b/themes/theme-default/src/client/styles/code.scss @@ -229,18 +229,12 @@ div[class*='language-'] { padding-top: 1.3rem; font-size: 0.875em; line-height: $line-height; - counter-reset: line-number; .line-number { position: relative; z-index: 3; user-select: none; height: #{$line-height}em; - - &::before { - counter-increment: line-number; - content: counter(line-number); - } } } @@ -257,6 +251,26 @@ div[class*='language-'] { } } +// ------------ plugin-shiki code highlighting ------------ +// when defaultColor is `false`, override the background color +div[class*='language'] { + background-color: var(--shiki-light-bg, var(--code-bg-color)); + transition: background-color var(--t-color); +} + +.dark div[class*='language'] { + background-color: var(--shiki-dark-bg, var(--code-bg-color)); +} + +// dual themes, override the color +.vp-code pre span { + color: var(--shiki-light, inherit); +} + +.dark .vp-code pre span { + color: var(--shiki-dark, inherit); +} + // ------------ code notation highlighting ------------ // matches `` From 33da021759b4341be1f0cadaac290fa93bf1d46d Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Tue, 28 May 2024 17:50:22 +0800 Subject: [PATCH 2/8] perf: move additional attributes of `
` to
 `preWrapper`

---
 .../src/node/markdown/preWrapperPlugin.ts           | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/plugins/plugin-shiki/src/node/markdown/preWrapperPlugin.ts b/plugins/plugin-shiki/src/node/markdown/preWrapperPlugin.ts
index f25c199690..55c100627d 100644
--- a/plugins/plugin-shiki/src/node/markdown/preWrapperPlugin.ts
+++ b/plugins/plugin-shiki/src/node/markdown/preWrapperPlugin.ts
@@ -4,6 +4,8 @@ import type { Markdown } from 'vuepress/markdown'
 import type { PreWrapperOptions } from '../types.js'
 import { resolveAttr, resolveLanguage } from '../utils.js'
 
+const PRE_ATTRS_REGEXP = /]*)>/
+
 export const preWrapperPlugin = (
   md: Markdown,
   { preWrapper = true }: PreWrapperOptions = {},
@@ -46,7 +48,16 @@ export const preWrapperPlugin = (
     }
 
     const title = resolveAttr(info, 'title') || lang
+    let attrs = ''
+
+    // before: maybe `v-pre class="shiki *"`
+    // after: style="*" tab-index="*"
+    result = result.replace(PRE_ATTRS_REGEXP, (_, before, after) => {
+      attrs = after.trim()
+      // Keep `v-pre`, remove the rest.
+      return ``
+    })
 
-    return `
${result}
` + return `
${result}
` } } From edd0fc491ccb05b17267935dc32c2489f3da4cf3 Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Tue, 28 May 2024 17:50:49 +0800 Subject: [PATCH 3/8] docs: update doc --- docs/.vuepress/config.ts | 14 -------------- docs/plugins/prismjs.md | 14 ++++++++++++++ docs/plugins/shiki.md | 14 ++++++++++++-- docs/zh/plugins/prismjs.md | 14 ++++++++++++++ docs/zh/plugins/shiki.md | 14 ++++++++++++++ 5 files changed, 54 insertions(+), 16 deletions(-) diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts index d156505384..68756bd6c5 100644 --- a/docs/.vuepress/config.ts +++ b/docs/.vuepress/config.ts @@ -72,20 +72,6 @@ export default defineUserConfig({ extendsMarkdown: (md) => { md.use(footnote) - - // FIXME: Should be removed with next vuepress version - const rawFence = md.renderer.rules.fence! - const rawCodeInline = md.renderer.rules.code_inline! - - md.renderer.rules.fence = (...args) => { - const result = rawFence(...args) - return result.replace(' { - const result = rawCodeInline(...args) - return ` Date: Tue, 28 May 2024 17:51:04 +0800 Subject: [PATCH 4/8] test: add unit tests --- .../prismjs-preWrapper.spec.ts.snap | 110 +++++++++----- .../tests/prismjs-preWrapper.spec.ts | 43 ++++++ .../shiki-preWrapper.spec.ts.snap | 137 +++++++++++------- .../tests/shiki-preWrapper.spec.ts | 43 ++++++ 4 files changed, 247 insertions(+), 86 deletions(-) diff --git a/plugins/plugin-prismjs/tests/__snapshots__/prismjs-preWrapper.spec.ts.snap b/plugins/plugin-prismjs/tests/__snapshots__/prismjs-preWrapper.spec.ts.snap index 40603fd690..b530f48a9b 100644 --- a/plugins/plugin-prismjs/tests/__snapshots__/prismjs-preWrapper.spec.ts.snap +++ b/plugins/plugin-prismjs/tests/__snapshots__/prismjs-preWrapper.spec.ts.snap @@ -5,7 +5,7 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
Raw text
 
-
Raw text
+
Raw text
 
const foo = 'foo'
 
@@ -19,7 +19,7 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -37,7 +37,7 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -49,9 +49,9 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
 exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers / :no-line-numbers > should work properly if \`lineNumbers\` is enabled by default 1`] = `
 "
Raw text
 
-
Raw text
+
Raw text
 
-
Raw text
+
Raw text
 
const foo = 'foo'
 
@@ -59,13 +59,13 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -77,13 +77,13 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -97,7 +97,7 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
 
Raw text
 
-
Raw text
+
Raw text
 
const foo = 'foo'
 
@@ -105,13 +105,13 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -123,13 +123,13 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -138,6 +138,48 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers /
 
" `; +exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers=number > should work properly if \`lineNumbers\` is disabled by default 1`] = ` +"
const line2 = 'line 2'
+const line3 = 'line 3'
+
+
const line3 = 'line 3'
+const line4 = 'line 4'
+const line5 = 'line 5'
+
+
const line10 = 'line 10'
+const line11 = 'line 11'
+
+
" +`; + +exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers=number > should work properly if \`lineNumbers\` is enabled by default 1`] = ` +"
const line2 = 'line 2'
+const line3 = 'line 3'
+
+
const line3 = 'line 3'
+const line4 = 'line 4'
+const line5 = 'line 5'
+
+
const line10 = 'line 10'
+const line11 = 'line 11'
+
+
" +`; + +exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > :line-numbers=number > should work properly if \`lineNumbers\` is set to a number by default 1`] = ` +"
const line2 = 'line 2'
+const line3 = 'line 3'
+
+
const line3 = 'line 3'
+const line4 = 'line 4'
+const line5 = 'line 5'
+
+
const line10 = 'line 10'
+const line11 = 'line 11'
+
+
" +`; + exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > highlight notation > should highlight notation 1`] = ` "
const foo = 'foo' 
 const bar = 'bar' 
@@ -146,25 +188,25 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > highlight notati
 const quux = 'quux' 
 const corge = 'corge' 
 
-
" +
" `; exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > plugin options > should disable \`highlightLines\` 1`] = ` "
Raw text
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -174,7 +216,7 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > plugin options >
   return 2048
 }
 
-

{{ inlineCode }}

+

{{ inlineCode }}

" `; @@ -245,13 +287,13 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > plugin options > return 1024 }
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -261,26 +303,26 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > plugin options >
   return 2048
 }
 
-

{{ inlineCode }}

+

{{ inlineCode }}

" `; exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > plugin options > should process code fences with default options 1`] = ` "
Raw text
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
 }
 
-
const foo = 'foo'
+
const foo = 'foo'
 
 function bar () {
   return 1024
@@ -290,56 +332,56 @@ exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > plugin options >
   return 2048
 }
 
-

{{ inlineCode }}

+

{{ inlineCode }}

" `; exports[`@vuepress/plugin-prismjs > markdown fence preWrapper > syntax highlighting > should work if highlighted code is not wrapped with \`
\` 1`] = `
 "
highlighted code: Raw text
 , lang: 
-
highlighted code: const foo = 'foo'
+
highlighted code: const foo = 'foo'
 
 function bar () {
   return 1024
 }
 , lang: js
-
highlighted code: const foo: string = 'foo'
+
highlighted code: const foo: string = 'foo'
 
 function bar (): number {
   return 1024
 }
 , lang: ts
-
highlighted code: