Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add code-group component #1560

Merged
merged 6 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/__tests__/e2e/.vitepress/cache
/coverage
/src/client/shared.ts
/src/node/shared.ts
Expand Down
75 changes: 68 additions & 7 deletions docs/guide/markdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ export default {

```js
export default {
data () {
data() {
return {
msg: 'Highlighted!' // [!code hl]
}
Expand All @@ -381,7 +381,7 @@ export default {

## Focus in Code Blocks

Adding the `// [!code focus]` comment on a line will focus it and blur the other parts of the code.
Adding the `// [!code focus]` comment on a line will focus it and blur the other parts of the code.

Additionally, you can define a number of lines to focus using `// [!code focus:<lines>]`.

Expand All @@ -405,17 +405,17 @@ export default {

```js
export default {
data () {
data() {
return {
msg: 'Focused!' // [!code focus]
}
}
}
```

## Colored diffs in Code Blocks
## Colored Diffs in Code Blocks

Adding the `// [!code --]` or `// [!code ++]` comments on a line will create a diff of that line, while keeping the colors of the codeblock.
Adding the `// [!code --]` or `// [!code ++]` comments on a line will create a diff of that line, while keeping the colors of the codeblock.

**Input**

Expand Down Expand Up @@ -447,7 +447,7 @@ export default {
}
```

## Errors and warnings
## Errors and Warnings in Code Blocks

Adding the `// [!code warning]` or `// [!code error]` comments on a line will color it accordingly.

Expand All @@ -472,7 +472,7 @@ export default {

```js
export default {
data () {
data() {
return {
msg: 'Error', // [!code error]
msg: 'Warning' // [!code warning]
Expand Down Expand Up @@ -549,11 +549,72 @@ You can also specify the language inside the braces (`{}`) like this:
<<< @/snippets/snippet.cs{c#}

<!-- with line highlighting: -->

<<< @/snippets/snippet.cs{1,2,4-6 c#}
```

This is helpful if source language cannot be inferred from your file extension.

## Code Groups

You can group multiple code blocks like this:

**Input**

````md
::: code-group

```js [config.js]
/**
* @type {import('vitepress').UserConfig}
*/
const config = {
// ...
}

export default config
```

```ts [config.ts]
import type { UserConfig } from 'vitepress'

const config: UserConfig = {
// ...
}

export default config
```

:::
````

**Output**

::: code-group

```js [config.js]
/**
* @type {import('vitepress').UserConfig}
*/
const config = {
// ...
}

export default config
```

```ts [config.ts]
import type { UserConfig } from 'vitepress'

const config: UserConfig = {
// ...
}

export default config
```

:::

## Markdown File Inclusion

You can include a markdown file in another markdown file like this:
Expand Down
84 changes: 84 additions & 0 deletions docs/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Code Groups

::: code-group

```txt-vue{1}
{{ 1 + 1 }}
```

```js [app.vue]
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
```

<!-- kkk -->

```vue-html{3,4} [layouts/custom.vue]
<template>
<div>
Some *custom* layout
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur imperdiet mi in nunc faucibus consequat.
<slot />
</div>
</template>
```

```js{1-3,5} [layouts/default.vue]
export default {
name: 'MyComponent'
// ...
}
<template>
<div>
Some *custom* layout
<slot />
</div>
</template>
```

:::

- in list

- ::: code-group

```js
printf('111')
```

```python
import torch as th
print("Hello world")
```

```
import torch as th
print("Hello world")
```

:::

```
.
├─ index.md
├─ foo
│ ├─ index.md
│ ├─ one.md
│ └─ two.md
└─ bar
├─ index.md
├─ three.md
└─ four.md
```

- ```md{1-3,5}
[Home](/) <!-- sends the user to the root index.md -->
[foo](/foo/) <!-- sends the user to index.html of directory foo -->
[foo heading](./#heading) <!-- anchors user to a heading in the foo index file -->
[bar - three](../bar/three) <!-- you can omit extention -->
[bar - three](../bar/three.md) <!-- you can append .md -->
[bar - four](../bar/four.html) <!-- or you can append .html -->
```
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"@vue/devtools-api": "^6.4.5",
"@vueuse/core": "^9.6.0",
"body-scroll-lock": "4.0.0-beta.0",
"nanoid": "3.3.4",
"shiki": "^0.11.1",
"vite": "^4.0.0",
"vue": "^3.2.45"
Expand Down
2 changes: 2 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions src/client/app/composables/codeGroups.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { inBrowser } from 'vitepress'

export function useCodeGroups() {
if (inBrowser) {
window.addEventListener('click', (e) => {
const el = e.target as HTMLInputElement

if (el.matches('.vp-code-group input')) {
// input <- .tabs <- .vp-code-group
const group = el.parentElement?.parentElement
const i = Array.from(group?.querySelectorAll('input') || []).indexOf(el)

const current = group?.querySelector('div[class*="language-"].active')
const next = group?.querySelectorAll('div[class*="language-"]')?.[i]

if (current && next && current !== next) {
current.classList.remove('active')
next.classList.add('active')
}
}
})
}
}
2 changes: 1 addition & 1 deletion src/client/app/composables/copyCode.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { inBrowser } from '../utils.js'
import { inBrowser } from 'vitepress'

export function useCopyCode() {
if (inBrowser) {
Expand Down
3 changes: 3 additions & 0 deletions src/client/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { useCodeGroups } from './composables/codeGroups.js'

const NotFound = Theme.NotFound || (() => '404 Not Found')

Expand All @@ -43,6 +44,8 @@ const VitePressApp = defineComponent({

// setup global copy code handler
useCopyCode()
// setup global code groups handler
useCodeGroups()

if (Theme.setup) Theme.setup()
return () => h(Theme.Layout)
Expand Down
1 change: 1 addition & 0 deletions src/client/theme-default/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import './styles/base.css'
import './styles/utils.css'
import './styles/components/custom-block.css'
import './styles/components/vp-code.css'
import './styles/components/vp-code-group.css'
import './styles/components/vp-doc.css'
import './styles/components/vp-sponsor.css'

Expand Down
87 changes: 87 additions & 0 deletions src/client/theme-default/styles/components/vp-code-group.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
.vp-code-group {
margin-top: 16px;
}

.vp-code-group .tabs {
position: relative;
display: flex;
margin-right: -24px;
margin-left: -24px;
padding: 0 12px;
background-color: var(--vp-code-tab-bg);
overflow: auto;
}

.vp-code-group .tabs::after {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 1px;
background-color: var(--vp-code-tab-divider);
content: '';
}

@media (min-width: 640px) {
.vp-code-group .tabs {
margin-right: 0;
margin-left: 0;
border-radius: 8px 8px 0 0;
}
}

.vp-code-group .tabs input {
position: absolute;
opacity: 0;
pointer-events: none;
}

.vp-code-group .tabs label {
position: relative;
display: inline-block;
border-bottom: 1px solid transparent;
padding: 0 12px;
line-height: 48px;
font-size: 14px;
font-weight: 500;
color: var(--vp-code-tab-text-color);
background-color: var(--vp-code-tab-bg);
white-space: nowrap;
cursor: pointer;
transition: color 0.25s;
}

.vp-code-group .tabs label::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 10;
height: 1px;
content: '';
background-color: transparent;
transition: background-color 0.25s;
}

.vp-code-group label:hover {
color: var(--vp-code-tab-hover-text-color);
}

.vp-code-group input:checked + label {
color: var(--vp-code-tab-active-text-color);
}

.vp-code-group input:checked + label::after {
background-color: var(--vp-code-tab-active-bar-color);
}

.vp-code-group div[class*='language-'] {
display: none;
margin-top: 0 !important;
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;
}

.vp-code-group div[class*='language-'].active {
display: block;
}
Loading