From 834ac6691295b0240bddcf0b26245f4fe7b14616 Mon Sep 17 00:00:00 2001 From: "Jinjing.Zhou" Date: Fri, 26 Aug 2022 03:16:01 +0800 Subject: [PATCH 1/7] feat: MVP for code group Signed-off-by: Jinjing.Zhou --- docs/.vitepress/config.ts | 1 + docs/guide/test.md | 51 +++++++++++ .../theme-default/components/VPCodeGroup.vue | 89 +++++++++++++++++++ src/client/theme-default/index.ts | 1 + .../styles/components/vp-doc.css | 6 +- src/client/theme-default/styles/vars.css | 1 + src/node/markdown/plugins/containers.ts | 7 ++ src/node/markdown/plugins/preWrapper.ts | 28 +++++- 8 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 docs/guide/test.md create mode 100644 src/client/theme-default/components/VPCodeGroup.vue diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 037c3064a5e9..d2c0b96cac87 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -81,6 +81,7 @@ function sidebarGuide() { collapsible: true, items: [ { text: 'Markdown', link: '/guide/markdown' }, + { text: 'Code Group', link: '/guide/test' }, { text: 'Asset Handling', link: '/guide/asset-handling' }, { text: 'Frontmatter', link: '/guide/frontmatter' }, { text: 'Using Vue in Markdown', link: '/guide/using-vue' }, diff --git a/docs/guide/test.md b/docs/guide/test.md new file mode 100644 index 000000000000..65c440295f07 --- /dev/null +++ b/docs/guide/test.md @@ -0,0 +1,51 @@ + + +# Code Groups + +test + +:::code-group + +```js [app.vue] + +``` + +```js{3,4} [layouts/custom.vue] + +``` + +```js{1-3,5} [layouts/default.vue] +export default { + name: 'MyComponent' + // ... +} + +``` + +```js + +``` + +::: + + diff --git a/src/client/theme-default/components/VPCodeGroup.vue b/src/client/theme-default/components/VPCodeGroup.vue new file mode 100644 index 000000000000..1f58246e5caa --- /dev/null +++ b/src/client/theme-default/components/VPCodeGroup.vue @@ -0,0 +1,89 @@ + + + + + \ No newline at end of file diff --git a/src/client/theme-default/index.ts b/src/client/theme-default/index.ts index 7b7921283586..57140038e3c4 100644 --- a/src/client/theme-default/index.ts +++ b/src/client/theme-default/index.ts @@ -19,6 +19,7 @@ export { default as VPTeamPage } from './components/VPTeamPage.vue' export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue' export { default as VPTeamPageSection } from './components/VPTeamPageSection.vue' export { default as VPTeamMembers } from './components/VPTeamMembers.vue' +export { default as VPCodeGroup } from './components/VPCodeGroup.vue' const theme: Theme = { Layout, diff --git a/src/client/theme-default/styles/components/vp-doc.css b/src/client/theme-default/styles/components/vp-doc.css index 909fbc108f7c..2136603d3374 100644 --- a/src/client/theme-default/styles/components/vp-doc.css +++ b/src/client/theme-default/styles/components/vp-doc.css @@ -405,7 +405,7 @@ content: 'Copied'; } -.vp-doc [class*='language-'] > span.lang { +.vp-doc [class*='language-'] > span.code-title { position: absolute; top: 6px; right: 12px; @@ -416,8 +416,8 @@ transition: color 0.4s, opacity 0.4s; } -.vp-doc [class*='language-']:hover > button.copy + span.lang, -.vp-doc [class*='language-'] > button.copy:focus + span.lang { +.vp-doc [class*='language-']:hover > button.copy + span.code-title, +.vp-doc [class*='language-'] > button.copy:focus + span.code-title { opacity: 0; } diff --git a/src/client/theme-default/styles/vars.css b/src/client/theme-default/styles/vars.css index 5b09364b911c..862309555648 100644 --- a/src/client/theme-default/styles/vars.css +++ b/src/client/theme-default/styles/vars.css @@ -202,6 +202,7 @@ --vp-code-block-color: var(--vp-c-text-dark-1); --vp-code-block-bg: #292d3e; + --vp-code-block-tab-header-bg: #363b51; --vp-code-line-highlight-color: rgba(0, 0, 0, 0.5); --vp-code-line-number-color: var(--vp-c-text-dark-3); diff --git a/src/node/markdown/plugins/containers.ts b/src/node/markdown/plugins/containers.ts index 810b194501c6..433e6baeae0c 100644 --- a/src/node/markdown/plugins/containers.ts +++ b/src/node/markdown/plugins/containers.ts @@ -14,6 +14,13 @@ export const containerPlugin = (md: MarkdownIt) => { render: (tokens: Token[], idx: number) => tokens[idx].nesting === 1 ? `
\n` : `
\n` }) + .use(container, 'code-group', { + render: (tokens: Token[], idx: number) => { + return tokens[idx].nesting === 1 + ? `\n` + : `\n` + } + }) } type ContainerArgs = [typeof container, string, { render: RenderRule }] diff --git a/src/node/markdown/plugins/preWrapper.ts b/src/node/markdown/plugins/preWrapper.ts index 3daf18fcc603..a43aba246314 100644 --- a/src/node/markdown/plugins/preWrapper.ts +++ b/src/node/markdown/plugins/preWrapper.ts @@ -11,12 +11,32 @@ import MarkdownIt from 'markdown-it' export const preWrapperPlugin = (md: MarkdownIt) => { const fence = md.renderer.rules.fence! + const RE = /(\w*)(?:{[\d,-]+})?\s*\[(.+)\]/ md.renderer.rules.fence = (...args) => { const [tokens, idx] = args - const lang = tokens[idx].info.trim().replace(/-vue$/, '') + const token = tokens[idx] + const hint = token.info.trim().replace(/-vue$/, '') + let codeTitle = '' + let lang = hint + if (RE.test(hint)) { + const matchGroup = RE.exec(hint) + if (matchGroup && matchGroup.length == 3) { + lang = matchGroup[1].trim() + codeTitle = matchGroup[2] + } + } else { + // Use language name as code title if not specified + codeTitle = lang === 'vue-html' ? 'template' : lang + } + token.info = tokens[idx].info.replace(/\[(.+)\]/, '') const rawCode = fence(...args) - return `
${ - lang === 'vue-html' ? 'template' : lang - }${rawCode}
` + + return `
+
+ + ${codeTitle} + ${rawCode} +
+
` } } From 8c4437b636a41606a67056377b2abf2eb3c05079 Mon Sep 17 00:00:00 2001 From: "Jinjing.Zhou" Date: Sat, 27 Aug 2022 01:32:41 +0800 Subject: [PATCH 2/7] fix: fix mobile display and indent Signed-off-by: Jinjing.Zhou --- .../theme-default/components/VPCodeGroup.vue | 80 +++++++++---------- .../styles/components/vp-doc.css | 1 - 2 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/client/theme-default/components/VPCodeGroup.vue b/src/client/theme-default/components/VPCodeGroup.vue index 1f58246e5caa..50716e0b8c92 100644 --- a/src/client/theme-default/components/VPCodeGroup.vue +++ b/src/client/theme-default/components/VPCodeGroup.vue @@ -2,8 +2,8 @@ import { onMounted, ref, watch } from 'vue'; interface Tab { - label: string; - elm: Element; + label: string; + elm: Element; } const codeblocks = ref(null) @@ -11,79 +11,79 @@ let tabs = ref>([]) const activeTabIndex = ref(0) onMounted(() => { - if (codeblocks !== undefined) { - codeblocks.value?.querySelectorAll(".code-block").forEach((element, i) => { - const title = element.querySelector("span.code-title")?.textContent! - tabs.value.push({ - label: title, - elm: element - }) - }) - switchTab(0) - } + if (codeblocks !== undefined) { + codeblocks.value?.querySelectorAll(".code-block").forEach((element, i) => { + const title = element.querySelector("span.code-title")?.textContent! + tabs.value.push({ + label: title, + elm: element + }) + }) + switchTab(0) + } }) function switchTab(i: number) { - tabs.value.forEach((tab) => { - tab["elm"].classList.remove('active') - }) - tabs.value[i]["elm"].classList.add('active') + tabs.value.forEach((tab) => { + tab["elm"].classList.remove('active') + }) + tabs.value[i]["elm"].classList.add('active') } watch(activeTabIndex, (newValue, oldValue) => { - switchTab(newValue) + switchTab(newValue) }) \ No newline at end of file diff --git a/src/client/theme-default/styles/components/vp-doc.css b/src/client/theme-default/styles/components/vp-doc.css index 2136603d3374..c232e18a262d 100644 --- a/src/client/theme-default/styles/components/vp-doc.css +++ b/src/client/theme-default/styles/components/vp-doc.css @@ -259,7 +259,6 @@ .vp-doc div[class*='language-'] { position: relative; - margin: 16px -24px; background-color: var(--vp-code-block-bg); overflow-x: auto; transition: background-color 0.5s; From 553d5108c9f925ed73782d63aae89968f8ccb4fc Mon Sep 17 00:00:00 2001 From: "Jinjing.Zhou" Date: Sat, 27 Aug 2022 01:47:03 +0800 Subject: [PATCH 3/7] fix: use builtin color Signed-off-by: Jinjing.Zhou --- src/client/theme-default/components/VPCodeGroup.vue | 4 ++-- src/client/theme-default/styles/vars.css | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/theme-default/components/VPCodeGroup.vue b/src/client/theme-default/components/VPCodeGroup.vue index 50716e0b8c92..de4ba1762185 100644 --- a/src/client/theme-default/components/VPCodeGroup.vue +++ b/src/client/theme-default/components/VPCodeGroup.vue @@ -65,12 +65,12 @@ watch(activeTabIndex, (newValue, oldValue) => { } .tabs-header button:hover { - color: rgba(255, 255, 255, 0.82); + color: var(--vp-c-gray-light-4); } .tabs-header button.active { - background-color: var(--vp-c-gray); + background-color: var(--vp-c-gray-dark-3); } diff --git a/src/client/theme-default/styles/vars.css b/src/client/theme-default/styles/vars.css index 862309555648..070ec5b40bbc 100644 --- a/src/client/theme-default/styles/vars.css +++ b/src/client/theme-default/styles/vars.css @@ -202,7 +202,7 @@ --vp-code-block-color: var(--vp-c-text-dark-1); --vp-code-block-bg: #292d3e; - --vp-code-block-tab-header-bg: #363b51; + --vp-code-block-tab-header-bg: var(--vp-c-indigo); --vp-code-line-highlight-color: rgba(0, 0, 0, 0.5); --vp-code-line-number-color: var(--vp-c-text-dark-3); From 68f41f2259f5367a008bfd55787c14172cf9c550 Mon Sep 17 00:00:00 2001 From: "Jinjing.Zhou" Date: Sat, 27 Aug 2022 16:22:26 +0800 Subject: [PATCH 4/7] fix: import code group sfc by default Signed-off-by: Jinjing.Zhou --- docs/guide/test.md | 4 ---- src/client/theme-default/index.ts | 7 +++++-- src/node/markdown/plugins/containers.ts | 4 +--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/guide/test.md b/docs/guide/test.md index 65c440295f07..5a539ed5392f 100644 --- a/docs/guide/test.md +++ b/docs/guide/test.md @@ -1,7 +1,3 @@ - - # Code Groups test diff --git a/src/client/theme-default/index.ts b/src/client/theme-default/index.ts index 57140038e3c4..c5fd8caacf63 100644 --- a/src/client/theme-default/index.ts +++ b/src/client/theme-default/index.ts @@ -10,6 +10,7 @@ import './styles/components/vp-sponsor.css' import { Theme } from 'vitepress' import Layout from './Layout.vue' import NotFound from './NotFound.vue' +import VPCodeGroup from './components/VPCodeGroup.vue' export { default as VPHomeHero } from './components/VPHomeHero.vue' export { default as VPHomeFeatures } from './components/VPHomeFeatures.vue' @@ -19,11 +20,13 @@ export { default as VPTeamPage } from './components/VPTeamPage.vue' export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue' export { default as VPTeamPageSection } from './components/VPTeamPageSection.vue' export { default as VPTeamMembers } from './components/VPTeamMembers.vue' -export { default as VPCodeGroup } from './components/VPCodeGroup.vue' const theme: Theme = { Layout, - NotFound + NotFound, + enhanceApp(ctx) { + ctx.app.component('CodeGroup', VPCodeGroup) + } } export default theme diff --git a/src/node/markdown/plugins/containers.ts b/src/node/markdown/plugins/containers.ts index 433e6baeae0c..4c2ddfb2af29 100644 --- a/src/node/markdown/plugins/containers.ts +++ b/src/node/markdown/plugins/containers.ts @@ -16,9 +16,7 @@ export const containerPlugin = (md: MarkdownIt) => { }) .use(container, 'code-group', { render: (tokens: Token[], idx: number) => { - return tokens[idx].nesting === 1 - ? `\n` - : `\n` + return tokens[idx].nesting === 1 ? `\n` : `\n` } }) } From 912c456168ae83a906a232df01529b771b07552a Mon Sep 17 00:00:00 2001 From: "Jinjing.Zhou" Date: Sat, 27 Aug 2022 16:26:38 +0800 Subject: [PATCH 5/7] fix: remove unused parameters Signed-off-by: Jinjing.Zhou --- src/client/theme-default/components/VPCodeGroup.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/theme-default/components/VPCodeGroup.vue b/src/client/theme-default/components/VPCodeGroup.vue index de4ba1762185..8f4bda1e082d 100644 --- a/src/client/theme-default/components/VPCodeGroup.vue +++ b/src/client/theme-default/components/VPCodeGroup.vue @@ -12,7 +12,7 @@ const activeTabIndex = ref(0) onMounted(() => { if (codeblocks !== undefined) { - codeblocks.value?.querySelectorAll(".code-block").forEach((element, i) => { + codeblocks.value?.querySelectorAll(".code-block").forEach((element) => { const title = element.querySelector("span.code-title")?.textContent! tabs.value.push({ label: title, From c30eb0da05c104a16a43de8cb0cfe78f98cbf347 Mon Sep 17 00:00:00 2001 From: "Jinjing.Zhou" Date: Sun, 18 Sep 2022 23:08:08 +0800 Subject: [PATCH 6/7] use js implement Signed-off-by: Jinjing.Zhou --- src/client/app/composables/codeGroup.ts | 20 +++++ src/client/app/index.ts | 4 + .../theme-default/components/VPCodeGroup.vue | 89 ------------------- .../styles/components/vp-code.css | 36 ++++++++ src/node/markdown/plugins/codeGroup.ts | 21 +++++ src/node/markdown/plugins/containers.ts | 52 +++++++++-- src/node/markdown/plugins/preWrapper.ts | 22 ++--- 7 files changed, 135 insertions(+), 109 deletions(-) create mode 100644 src/client/app/composables/codeGroup.ts delete mode 100644 src/client/theme-default/components/VPCodeGroup.vue create mode 100644 src/node/markdown/plugins/codeGroup.ts diff --git a/src/client/app/composables/codeGroup.ts b/src/client/app/composables/codeGroup.ts new file mode 100644 index 000000000000..927885d536f6 --- /dev/null +++ b/src/client/app/composables/codeGroup.ts @@ -0,0 +1,20 @@ +import { inBrowser } from '../utils.js' + +export function useCodeGroup() { + if (inBrowser) { + window.addEventListener('click', (e) => { + const el = e.target as HTMLElement + if (el.matches('.code-group>.tabs-header>button')) { + const codeblocks = + el.parentElement!.parentElement!.querySelectorAll('.code-block') + const buttons = + el.parentElement!.parentElement!.querySelectorAll('button') + const index = parseInt(el.getAttribute('tab-index')!) + codeblocks.forEach((ele) => ele.classList.remove('active')) + buttons.forEach((ele) => ele.classList.remove('active')) + el.classList.add('active') + codeblocks[index].classList.add('active') + } + }) + } +} diff --git a/src/client/app/index.ts b/src/client/app/index.ts index 84bd1c23da8b..cc9d93e1391c 100644 --- a/src/client/app/index.ts +++ b/src/client/app/index.ts @@ -17,6 +17,7 @@ import { dataSymbol, initData } from './data.js' import { Content } from './components/Content.js' import { ClientOnly } from './components/ClientOnly.js' import { useCopyCode } from './composables/copyCode.js' +import { useCodeGroup } from './composables/codeGroup.js' const NotFound = Theme.NotFound || (() => '404 Not Found') @@ -44,6 +45,9 @@ const VitePressApp = defineComponent({ // setup global copy code handler useCopyCode() + // setup code group button handler + useCodeGroup() + if (Theme.setup) Theme.setup() return () => h(Theme.Layout) } diff --git a/src/client/theme-default/components/VPCodeGroup.vue b/src/client/theme-default/components/VPCodeGroup.vue deleted file mode 100644 index 8f4bda1e082d..000000000000 --- a/src/client/theme-default/components/VPCodeGroup.vue +++ /dev/null @@ -1,89 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/client/theme-default/styles/components/vp-code.css b/src/client/theme-default/styles/components/vp-code.css index ee74e5b27d70..19a4d6a8848b 100644 --- a/src/client/theme-default/styles/components/vp-code.css +++ b/src/client/theme-default/styles/components/vp-code.css @@ -5,3 +5,39 @@ html:not(.dark) .vp-code-dark { display: none; } + +.code-group .tabs-header { + border-radius: 8px 8px 0 0; + padding: 0 12px 0 12px; + background-color: var(--vp-code-block-tab-header-bg); + transition: background-color 0.5s; +} + +.code-group .tabs-header button { + padding: 6px 8px 6px 8px; + margin: 8px 0 8px 0; + border-radius: 8px; + color: white; + outline: none; +} + +.code-group .tabs-header button:hover { + color: var(--vp-c-gray-light-4); +} + +.code-group .tabs-header button.active { + background-color: var(--vp-c-gray-dark-3); +} + +.code-group .code-block { + display: none; +} + +.code-group .code-block.active { + display: block; +} + +.code-group div[class*='language-'] { + border-radius: 0 0 8px 8px !important; + margin-top: 0 !important; +} diff --git a/src/node/markdown/plugins/codeGroup.ts b/src/node/markdown/plugins/codeGroup.ts new file mode 100644 index 000000000000..5d12fd7d572d --- /dev/null +++ b/src/node/markdown/plugins/codeGroup.ts @@ -0,0 +1,21 @@ +import Token from 'markdown-it/lib/token' + +export const extractCodeTitleAndLang = (token: Token): [string, string] => { + const RE = /(\w*)(?:{[\d,-]+})?\s*\[(.+)\]/ + const hint = token.info.trim().replace(/-vue$/, '') + let codeTitle = '' + let lang = hint + if (RE.test(hint)) { + const matchGroup = RE.exec(hint) + if (matchGroup && matchGroup.length == 3) { + lang = matchGroup[1].trim() + codeTitle = matchGroup[2] + } + } else { + // Use language name as code title if not specified + codeTitle = lang === 'vue-html' ? 'template' : lang + } + return [codeTitle, lang] +} + +export const codeGroupInternalActiveMark = '#vitepress-internal-active#' diff --git a/src/node/markdown/plugins/containers.ts b/src/node/markdown/plugins/containers.ts index 20ca0e20c282..cfff1b3d885d 100644 --- a/src/node/markdown/plugins/containers.ts +++ b/src/node/markdown/plugins/containers.ts @@ -2,6 +2,10 @@ import MarkdownIt from 'markdown-it' import { RenderRule } from 'markdown-it/lib/renderer' import Token from 'markdown-it/lib/token' import container from 'markdown-it-container' +import { + extractCodeTitleAndLang, + codeGroupInternalActiveMark +} from './codeGroup' export const containerPlugin = (md: MarkdownIt) => { md.use(...createContainer('tip', 'TIP', md)) @@ -14,11 +18,7 @@ export const containerPlugin = (md: MarkdownIt) => { render: (tokens: Token[], idx: number) => tokens[idx].nesting === 1 ? `
\n` : `
\n` }) - .use(container, 'code-group', { - render: (tokens: Token[], idx: number) => { - return tokens[idx].nesting === 1 ? `\n` : `\n` - } - }) + .use(...createCodeGroup()) .use(container, 'raw', { render: (tokens: Token[], idx: number) => tokens[idx].nesting === 1 ? `
\n` : `
\n` @@ -52,3 +52,45 @@ function createContainer( } ] } + +function createCodeGroup(): ContainerArgs { + const klass = 'code-group' + return [ + container, + klass, + { + render(tokens, idx) { + const token = tokens[idx] + if (token.nesting === 1) { + const startTokenId = idx + const endTokenId = tokens.findIndex( + (token) => token.type === 'container_code-group_close' + ) + const codeGroupTokens = tokens.slice(startTokenId + 1, endTokenId) + // Mark first code block as active + const firstCodeBlock = codeGroupTokens.findIndex( + (token) => token.type === 'fence' && token.tag === 'code' + ) + tokens[startTokenId + 1 + firstCodeBlock].info += + codeGroupInternalActiveMark + const codeTitles = codeGroupTokens + .filter((token) => token.type === 'fence' && token.tag === 'code') + .map((token) => extractCodeTitleAndLang(token)[0]) + let headerBlock = `
\n
` + const buttonsBlock = codeTitles + .map((title, idx) => { + return `` + }) + .join('\n') + headerBlock += buttonsBlock + headerBlock += `
\n` + return headerBlock + } else { + return `
\n` + } + } + } + ] +} diff --git a/src/node/markdown/plugins/preWrapper.ts b/src/node/markdown/plugins/preWrapper.ts index a43aba246314..271211819ccf 100644 --- a/src/node/markdown/plugins/preWrapper.ts +++ b/src/node/markdown/plugins/preWrapper.ts @@ -8,30 +8,22 @@ // 4. import MarkdownIt from 'markdown-it' +import { + codeGroupInternalActiveMark, + extractCodeTitleAndLang +} from './codeGroup' export const preWrapperPlugin = (md: MarkdownIt) => { const fence = md.renderer.rules.fence! - const RE = /(\w*)(?:{[\d,-]+})?\s*\[(.+)\]/ md.renderer.rules.fence = (...args) => { const [tokens, idx] = args const token = tokens[idx] - const hint = token.info.trim().replace(/-vue$/, '') - let codeTitle = '' - let lang = hint - if (RE.test(hint)) { - const matchGroup = RE.exec(hint) - if (matchGroup && matchGroup.length == 3) { - lang = matchGroup[1].trim() - codeTitle = matchGroup[2] - } - } else { - // Use language name as code title if not specified - codeTitle = lang === 'vue-html' ? 'template' : lang - } + const [codeTitle, lang] = extractCodeTitleAndLang(token) + const isActive = token.info.includes(codeGroupInternalActiveMark) token.info = tokens[idx].info.replace(/\[(.+)\]/, '') const rawCode = fence(...args) - return `
+ return `
${codeTitle} From 4dc5508d388d737d7b9e6eb8d1e140d49c1b59b0 Mon Sep 17 00:00:00 2001 From: "Jinjing.Zhou" Date: Sun, 18 Sep 2022 23:51:28 +0800 Subject: [PATCH 7/7] fix Signed-off-by: Jinjing.Zhou --- docs/guide/test.md | 44 ++++++++++++++++--- .../styles/components/vp-code.css | 6 +-- .../styles/components/vp-doc.css | 14 ++---- src/node/markdown/plugins/codeGroup.ts | 5 ++- src/node/markdown/plugins/containers.ts | 20 ++++++--- 5 files changed, 62 insertions(+), 27 deletions(-) diff --git a/docs/guide/test.md b/docs/guide/test.md index 5a539ed5392f..741b4cda3c48 100644 --- a/docs/guide/test.md +++ b/docs/guide/test.md @@ -34,14 +34,48 @@ export default { ``` +```python +import torch as th +print("Hello world") +``` + +::: + + +:::code-group + ```js - +printf("111") +``` + + +```python +import torch as th +print("Hello world") ``` ::: +``` +. +├─ index.md +├─ foo +│ ├─ index.md +│ ├─ one.md +│ └─ two.md +└─ bar + ├─ index.md + ├─ three.md + └─ four.md +``` + + +```md +[Home](/) +[foo](/foo/) +[foo heading](./#heading) +[bar - three](../bar/three) +[bar - three](../bar/three.md) +[bar - four](../bar/four.html) +``` diff --git a/src/client/theme-default/styles/components/vp-code.css b/src/client/theme-default/styles/components/vp-code.css index 19a4d6a8848b..158570608470 100644 --- a/src/client/theme-default/styles/components/vp-code.css +++ b/src/client/theme-default/styles/components/vp-code.css @@ -37,7 +37,7 @@ html:not(.dark) .vp-code-dark { display: block; } -.code-group div[class*='language-'] { - border-radius: 0 0 8px 8px !important; - margin-top: 0 !important; +.vp-doc .code-group div[class*='language-'] { + border-radius: 0 0 8px 8px; + margin-top: 0; } diff --git a/src/client/theme-default/styles/components/vp-doc.css b/src/client/theme-default/styles/components/vp-doc.css index c232e18a262d..3c803a5c8d18 100644 --- a/src/client/theme-default/styles/components/vp-doc.css +++ b/src/client/theme-default/styles/components/vp-doc.css @@ -264,17 +264,9 @@ transition: background-color 0.5s; } -@media (min-width: 640px) { - .vp-doc div[class*='language-'] { - border-radius: 8px; - margin: 16px 0; - } -} - -@media (max-width: 639px) { - .vp-doc li div[class*='language-'] { - border-radius: 8px 0 0 8px; - } +.vp-doc div[class*='language-'] { + border-radius: 8px; + margin: 16px 0; } .vp-doc div[class*='language-'] + div[class*='language-'], diff --git a/src/node/markdown/plugins/codeGroup.ts b/src/node/markdown/plugins/codeGroup.ts index 5d12fd7d572d..a18b6f44e914 100644 --- a/src/node/markdown/plugins/codeGroup.ts +++ b/src/node/markdown/plugins/codeGroup.ts @@ -2,7 +2,10 @@ import Token from 'markdown-it/lib/token' export const extractCodeTitleAndLang = (token: Token): [string, string] => { const RE = /(\w*)(?:{[\d,-]+})?\s*\[(.+)\]/ - const hint = token.info.trim().replace(/-vue$/, '') + const hint = token.info + .trim() + .replace(codeGroupInternalActiveMark, '') + .replace(/-vue$/, '') let codeTitle = '' let lang = hint if (RE.test(hint)) { diff --git a/src/node/markdown/plugins/containers.ts b/src/node/markdown/plugins/containers.ts index cfff1b3d885d..cb5a38f17632 100644 --- a/src/node/markdown/plugins/containers.ts +++ b/src/node/markdown/plugins/containers.ts @@ -60,19 +60,25 @@ function createCodeGroup(): ContainerArgs { klass, { render(tokens, idx) { - const token = tokens[idx] - if (token.nesting === 1) { + if (tokens[idx].nesting === 1) { const startTokenId = idx - const endTokenId = tokens.findIndex( - (token) => token.type === 'container_code-group_close' - ) + const endTokenId = + tokens + .slice(startTokenId) + .findIndex( + (token) => + token.nesting == -1 && + token.type === 'container_code-group_close' + ) + startTokenId const codeGroupTokens = tokens.slice(startTokenId + 1, endTokenId) + // Mark first code block as active const firstCodeBlock = codeGroupTokens.findIndex( (token) => token.type === 'fence' && token.tag === 'code' ) - tokens[startTokenId + 1 + firstCodeBlock].info += - codeGroupInternalActiveMark + tokens[ + startTokenId + 1 + firstCodeBlock + ].info += ` ${codeGroupInternalActiveMark}` const codeTitles = codeGroupTokens .filter((token) => token.type === 'fence' && token.tag === 'code') .map((token) => extractCodeTitleAndLang(token)[0])