Skip to content

Commit c4466b9

Browse files
authored
Merge branch 'main' into main
2 parents 21457a2 + d46107f commit c4466b9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1554
-1337
lines changed

CHANGELOG.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,50 @@
1+
## [2.0.0-alpha.12](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.11...v2.0.0-alpha.12) (2025-08-20)
2+
3+
### Bug Fixes
4+
5+
- **hmr:** don't load config twice on server restart ([d1a8061](https://github.com/vuejs/vitepress/commit/d1a8061eb438c730ccc62ce2d7158dbe89cc5292))
6+
- **hmr:** no need for server restart on theme change ([d3a1567](https://github.com/vuejs/vitepress/commit/d3a15673bd0846c7837bcc4ff5a2e3239a02f1f9))
7+
- **hmr:** hmr not working for snippet imports in dynamic routes ([914467e](https://github.com/vuejs/vitepress/commit/914467e17fb759a9722951a3fd7568eb3bc4d4e6))
8+
- **theme:** fix local nav alignment and increase touch area ([43b36c0](https://github.com/vuejs/vitepress/commit/43b36c0c19c2b4696f8c38fdaf4318786ea7ae8e))
9+
- **theme:** nav background doesn't extend fully and gap after sidebar with non-overlay scrollbars ([7df3052](https://github.com/vuejs/vitepress/commit/7df30525121a28a46cc6c802f3155ccff8effaca)), closes [#4653](https://github.com/vuejs/vitepress/issues/4653)
10+
- **theme:** use clipboard-check instead of clipboard-copy for code copied icon ([1c8815d](https://github.com/vuejs/vitepress/commit/1c8815d53ed2d56b07938260df6566f1514f4bfc))
11+
12+
### Features
13+
14+
- add markdown-it-cjk-friendly ([9fc8462](https://github.com/vuejs/vitepress/commit/9fc8462726ccf1cdb78b6171c9f1f5964e79ca22)), closes [#3762](https://github.com/vuejs/vitepress/issues/3762) [#4752](https://github.com/vuejs/vitepress/issues/4752)
15+
- make postcssIsolateStyles idempotent ([0944777](https://github.com/vuejs/vitepress/commit/094477789328b80cff45cd973efa16b6a4db0a27))
16+
17+
### BREAKING CHANGES
18+
19+
- [markdown-it-cjk-friendly](https://www.npmjs.com/package/markdown-it-cjk-friendly) is enabled by default. This intentionally deviates from the official commonmark spec for the benefit of CJK users. **For most users, no change is required.** If you were using hacks to patch `scanDelims`, you can remove those. To disable the plugin, set `markdown: { cjkFriendly: false }` in your vitepress config.
20+
- `includeFiles` option in `postcssIsolateStyles` now defaults to `[/vp-doc\.css/, /base\.css/]`. You can remove explicit `includeFiles` if you were using it just to run it on `vp-doc.css`. To revert back to older behavior pass `includeFiles: [/base\.css/]`. The underlying implementation is changed and `transform` and `exclude` options are no longer supported. Use `postcss-prefix-selector` directly if you've advanced use cases.
21+
22+
## [2.0.0-alpha.11](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.10...v2.0.0-alpha.11) (2025-08-14)
23+
24+
### Bug Fixes
25+
26+
- hmr working only once for markdown files ([8d8a5ac](https://github.com/vuejs/vitepress/commit/8d8a5ac281f090cd097bece792d9dd3ef00e5545)), closes [#4909](https://github.com/vuejs/vitepress/issues/4909)
27+
- html entities encoded twice in toc plugin ([8abbe29](https://github.com/vuejs/vitepress/commit/8abbe298d545de17d34a9bc1eb72af4c5a4b41b8)), closes [#4908](https://github.com/vuejs/vitepress/issues/4908)
28+
29+
## [2.0.0-alpha.10](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.9...v2.0.0-alpha.10) (2025-08-11)
30+
31+
### Bug Fixes
32+
33+
- **client:** base not stripped from relativePath in 404 pages ([b840877](https://github.com/vuejs/vitepress/commit/b840877aa83a5a24ffc1222e8a5a3dbf3e5105e8)), closes [#4850](https://github.com/vuejs/vitepress/issues/4850)
34+
- hmr of style blocks in dynamic routes ([#4903](https://github.com/vuejs/vitepress/issues/4903)) ([3d0fafb](https://github.com/vuejs/vitepress/commit/3d0fafba545f4b5028cf43d86027dd44dab14421))
35+
- make paths in `watchedFiles` absolute as mentioned in the docs ([318c14f](https://github.com/vuejs/vitepress/commit/318c14fa7c9fb949d74b7d9fae416e917766cf05))
36+
- module graph causing unnecessary route regeneration on every update ([fc267ae](https://github.com/vuejs/vitepress/commit/fc267ae6b787e163d41666e090089821377ead43))
37+
- preserve externally added dynamic routes and pages ([fc267ae](https://github.com/vuejs/vitepress/commit/fc267ae6b787e163d41666e090089821377ead43))
38+
- **search:** input placeholder being cut off in smaller viewports ([162c6a6](https://github.com/vuejs/vitepress/commit/162c6a69bf56945daa20d126aa034c59ee0c8a2e))
39+
- **search:** style tweaks for when searches are empty ([8b23217](https://github.com/vuejs/vitepress/commit/8b232171cc321bd3dc86b4357622815269f0b6f4))
40+
- **types:** externalize markdown-it types ([5bf835b](https://github.com/vuejs/vitepress/commit/5bf835b5074e9567852d552bfb5115c6456026e8))
41+
- **types:** pass generics deeply to user config ([777e2ca](https://github.com/vuejs/vitepress/commit/777e2caaacd93ce41b046f6c9d5ba80cc43ba37c))
42+
43+
### Features
44+
45+
- add source param to the deadlink check fn ([#4870](https://github.com/vuejs/vitepress/issues/4870)) ([8c027c2](https://github.com/vuejs/vitepress/commit/8c027c2a7c443074fd0d4890f7736b444f9254aa))
46+
- **theme:** add `rel="me"` to social links by default ([#4873](https://github.com/vuejs/vitepress/issues/4873)) ([34886c6](https://github.com/vuejs/vitepress/commit/34886c667d1305a79d64c957f8c52931ea122f47))
47+
148
## [2.0.0-alpha.9](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.8...v2.0.0-alpha.9) (2025-07-26)
249

350
### Bug Fixes
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`node/postcss/isolateStyles > transforms selectors and skips keyframes 1`] = `
4+
"
5+
/* simple classes */
6+
.example:not(:where(.vp-raw, .vp-raw *)) { color: red; }
7+
.class-a:not(:where(.vp-raw, .vp-raw *)) { color: coral; }
8+
.class-b:not(:where(.vp-raw, .vp-raw *)) { color: deepskyblue; }
9+
10+
/* escaped colon in class */
11+
.baz\\:not\\(.bar\\):not(:where(.vp-raw, .vp-raw *)) { display: block; }
12+
.disabled\\:opacity-50:not(:where(.vp-raw, .vp-raw *)):disabled { opacity: .5; }
13+
14+
/* pseudos (class + element) */
15+
.button:not(:where(.vp-raw, .vp-raw *)):hover { color: pink; }
16+
.button:not(:where(.vp-raw, .vp-raw *)):focus:hover { color: hotpink; }
17+
.item:not(:where(.vp-raw, .vp-raw *))::before { content: ''; }
18+
:not(:where(.vp-raw, .vp-raw *))::first-letter { color: pink; }
19+
:not(:where(.vp-raw, .vp-raw *))::before { content: ''; }
20+
21+
/* universal + :not */
22+
*:not(:where(.vp-raw, .vp-raw *)) { background-color: red; }
23+
*:not(:where(.vp-raw, .vp-raw *)):not(.b) { text-transform: uppercase; }
24+
25+
/* combinators */
26+
.foo:hover .bar:not(:where(.vp-raw, .vp-raw *)) { background: blue; }
27+
ul > li.active:not(:where(.vp-raw, .vp-raw *)) { color: green; }
28+
a + b ~ c:not(:where(.vp-raw, .vp-raw *)) { color: orange; }
29+
30+
/* ids + attribute selectors */
31+
#wow:not(:where(.vp-raw, .vp-raw *)) { color: yellow; }
32+
[data-world] .d:not(:where(.vp-raw, .vp-raw *)) { padding: 10px 20px; }
33+
34+
/* :root and chained tags */
35+
:not(:where(.vp-raw, .vp-raw *)):root { --bs-blue: #0d6efd; }
36+
:root .a:not(:where(.vp-raw, .vp-raw *)) { --bs-green: #bada55; }
37+
html:not(:where(.vp-raw, .vp-raw *)) { margin: 0; }
38+
body:not(:where(.vp-raw, .vp-raw *)) { padding: 0; }
39+
html body div:not(:where(.vp-raw, .vp-raw *)) { color: blue; }
40+
41+
/* grouping with commas */
42+
.a:not(:where(.vp-raw, .vp-raw *)), .b:not(:where(.vp-raw, .vp-raw *)) { color: red; }
43+
44+
/* multiple repeated groups to ensure stability */
45+
.a:not(:where(.vp-raw, .vp-raw *)), .b:not(:where(.vp-raw, .vp-raw *)) { color: coral; }
46+
.a:not(:where(.vp-raw, .vp-raw *)) { animation: glow 1s linear infinite alternate; }
47+
48+
/* nested blocks */
49+
.foo:not(:where(.vp-raw, .vp-raw *)) {
50+
svg:not(:where(.vp-raw, .vp-raw *)) { display: none; }
51+
.bar:not(:where(.vp-raw, .vp-raw *)) { display: inline; }
52+
}
53+
54+
/* standalone pseudos */
55+
:not(:where(.vp-raw, .vp-raw *)):first-child { color: pink; }
56+
:not(:where(.vp-raw, .vp-raw *)):hover { color: blue; }
57+
:not(:where(.vp-raw, .vp-raw *)):active { color: red; }
58+
59+
/* keyframes (should be ignored) */
60+
@keyframes fade {
61+
from { opacity: 0; }
62+
to { opacity: 1; }
63+
}
64+
@-webkit-keyframes glow {
65+
from { color: coral; }
66+
to { color: red; }
67+
}
68+
@-moz-keyframes glow {
69+
from { color: coral; }
70+
to { color: red; }
71+
}
72+
@-o-keyframes glow {
73+
from { color: coral; }
74+
to { color: red; }
75+
}
76+
"
77+
`;
Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,93 @@
1-
import {
2-
postcssIsolateStyles,
3-
splitSelectorPseudo
4-
} from 'node/postcss/isolateStyles'
5-
6-
// helper to run plugin transform on selector
7-
function apply(
8-
prefixPlugin: ReturnType<typeof postcssIsolateStyles>,
9-
selector: string
10-
) {
11-
// `prepare` is available on the runtime plugin but missing from the types, thus cast to `any`
12-
const { Rule } = (prefixPlugin as any).prepare({
13-
root: { source: { input: { file: 'foo/base.css' } } }
14-
})
15-
const rule = { selectors: [selector] }
16-
Rule(rule, { result: {} })
17-
return rule.selectors[0]
1+
import { postcssIsolateStyles } from 'node/postcss/isolateStyles'
2+
import postcss from 'postcss'
3+
4+
const INPUT_CSS = `
5+
/* simple classes */
6+
.example { color: red; }
7+
.class-a { color: coral; }
8+
.class-b { color: deepskyblue; }
9+
10+
/* escaped colon in class */
11+
.baz\\:not\\(.bar\\) { display: block; }
12+
.disabled\\:opacity-50:disabled { opacity: .5; }
13+
14+
/* pseudos (class + element) */
15+
.button:hover { color: pink; }
16+
.button:focus:hover { color: hotpink; }
17+
.item::before { content: '•'; }
18+
::first-letter { color: pink; }
19+
::before { content: ''; }
20+
21+
/* universal + :not */
22+
* { background-color: red; }
23+
*:not(.b) { text-transform: uppercase; }
24+
25+
/* combinators */
26+
.foo:hover .bar { background: blue; }
27+
ul > li.active { color: green; }
28+
a + b ~ c { color: orange; }
29+
30+
/* ids + attribute selectors */
31+
#wow { color: yellow; }
32+
[data-world] .d { padding: 10px 20px; }
33+
34+
/* :root and chained tags */
35+
:root { --bs-blue: #0d6efd; }
36+
:root .a { --bs-green: #bada55; }
37+
html { margin: 0; }
38+
body { padding: 0; }
39+
html body div { color: blue; }
40+
41+
/* grouping with commas */
42+
.a, .b { color: red; }
43+
44+
/* multiple repeated groups to ensure stability */
45+
.a, .b { color: coral; }
46+
.a { animation: glow 1s linear infinite alternate; }
47+
48+
/* nested blocks */
49+
.foo {
50+
svg { display: none; }
51+
.bar { display: inline; }
1852
}
1953
20-
describe('node/postcss/isolateStyles', () => {
21-
const plugin = postcssIsolateStyles()
54+
/* standalone pseudos */
55+
:first-child { color: pink; }
56+
:hover { color: blue; }
57+
:active { color: red; }
2258
23-
test('splitSelectorPseudo skips escaped colon', () => {
24-
const input = '.foo\\:bar'
25-
const [selector, pseudo] = splitSelectorPseudo(input)
26-
expect(selector).toBe(input)
27-
expect(pseudo).toBe('')
28-
})
59+
/* keyframes (should be ignored) */
60+
@keyframes fade {
61+
from { opacity: 0; }
62+
to { opacity: 1; }
63+
}
64+
@-webkit-keyframes glow {
65+
from { color: coral; }
66+
to { color: red; }
67+
}
68+
@-moz-keyframes glow {
69+
from { color: coral; }
70+
to { color: red; }
71+
}
72+
@-o-keyframes glow {
73+
from { color: coral; }
74+
to { color: red; }
75+
}
76+
`
2977

30-
test('splitSelectorPseudo splits on pseudo selectors', () => {
31-
const input = '.button:hover'
32-
const [selector, pseudo] = splitSelectorPseudo(input)
33-
expect(selector).toBe('.button')
34-
expect(pseudo).toBe(':hover')
78+
describe('node/postcss/isolateStyles', () => {
79+
test('transforms selectors and skips keyframes', () => {
80+
const out = run(INPUT_CSS)
81+
expect(out.css).toMatchSnapshot()
3582
})
3683

37-
it('postcssIsolateStyles inserts :not(...) in the right place', () => {
38-
const input = '.disabled\\:opacity-50:disabled'
39-
const result = apply(plugin, input)
40-
expect(result).toBe(
41-
'.disabled\\:opacity-50:not(:where(.vp-raw, .vp-raw *)):disabled'
42-
)
84+
test('idempotent (running twice produces identical CSS)', () => {
85+
const first = run(INPUT_CSS).css
86+
const second = run(first).css
87+
expect(second).toBe(first)
4388
})
4489
})
90+
91+
function run(css: string, from = 'src/styles/vp-doc.css') {
92+
return postcss([postcssIsolateStyles()]).process(css, { from })
93+
}

docs/.vitepress/config.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,13 @@ export default defineConfig({
124124
},
125125

126126
locales: {
127-
root: { label: 'English' },
128-
zh: { label: '简体中文' },
129-
pt: { label: 'Português' },
130-
ru: { label: 'Русский' },
131-
es: { label: 'Español' },
132-
ko: { label: '한국어' },
133-
fa: { label: 'فارسی' }
127+
root: { label: 'English', lang: 'en-US', dir: 'ltr' },
128+
zh: { label: '简体中文', lang: 'zh-Hans', dir: 'ltr' },
129+
pt: { label: 'Português', lang: 'pt-BR', dir: 'ltr' },
130+
ru: { label: 'Русский', lang: 'ru-RU', dir: 'ltr' },
131+
es: { label: 'Español', lang: 'es', dir: 'ltr' },
132+
ko: { label: '한국어', lang: 'ko-KR', dir: 'ltr' },
133+
fa: { label: 'فارسی', lang: 'fa-IR', dir: 'rtl' }
134134
},
135135

136136
vite: {

docs/config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const require = createRequire(import.meta.url)
55
const pkg = require('vitepress/package.json')
66

77
export default defineAdditionalConfig({
8-
lang: 'en-US',
98
description: 'Vite & Vue powered static site generator.',
109

1110
themeConfig: {

docs/en/guide/getting-started.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,19 @@ VitePress can be used on its own, or be installed into an existing project. In b
1818
::: code-group
1919

2020
```sh [npm]
21-
$ npm add -D vitepress
21+
$ npm add -D vitepress@next
2222
```
2323

2424
```sh [pnpm]
25-
$ pnpm add -D vitepress
25+
$ pnpm add -D vitepress@next
2626
```
2727

2828
```sh [yarn]
29-
$ yarn add -D vitepress
30-
```
31-
32-
```sh [yarn (pnp)]
33-
$ yarn add -D vitepress vue
29+
$ yarn add -D vitepress@next vue
3430
```
3531

3632
```sh [bun]
37-
$ bun add -D vitepress
33+
$ bun add -D vitepress@next
3834
```
3935

4036
:::

docs/en/guide/markdown.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,11 @@ Wraps in a `<div class="vp-raw">`
277277
}
278278
```
279279

280-
It uses [`postcss-prefix-selector`](https://github.com/RadValentin/postcss-prefix-selector) under the hood. You can pass its options like this:
280+
You can pass its options like this:
281281

282282
```js
283283
postcssIsolateStyles({
284-
includeFiles: [/vp-doc\.css/] // defaults to /base\.css/
284+
includeFiles: [/custom\.css/] // defaults to [/vp-doc\.css/, /base\.css/]
285285
})
286286
```
287287

docs/en/guide/what-is-vitepress.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ Unlike many traditional SSGs where each navigation results in a full page reload
5050

5151
## What About VuePress?
5252

53-
VitePress is the spiritual successor of VuePress. The original VuePress was based on Vue 2 and webpack. With Vue 3 and Vite under the hood, VitePress provides significantly better DX, better production performance, a more polished default theme, and a more flexible customization API.
53+
VitePress is the spiritual successor of VuePress 1. The original VuePress 1 was based on Vue 2 and webpack. With Vue 3 and Vite under the hood, VitePress provides significantly better DX, better production performance, a more polished default theme, and a more flexible customization API.
5454

55-
The API difference between VitePress and VuePress mostly lies in theming and customization. If you are using VuePress 1 with the default theme, it should be relatively straightforward to migrate to VitePress.
55+
The API difference between VitePress and VuePress 1 mostly lies in theming and customization. If you are using VuePress 1 with the default theme, it should be relatively straightforward to migrate to VitePress.
5656

57-
There has also been effort invested into VuePress 2, which also supports Vue 3 and Vite with more compatibility with VuePress 1. However, maintaining two SSGs in parallel isn't sustainable, so the Vue team has decided to focus on VitePress as the main recommended SSG in the long run.
57+
Maintaining two SSGs in parallel isn't sustainable, so the Vue team has decided to focus on VitePress as the main recommended SSG in the long run. Now VuePress 1 has been deprecated, and VuePress 2 has been handed over to the VuePress community team for further development and maintenance.

docs/en/reference/site-config.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default {
2424
}
2525
```
2626

27-
:::details Dynamic (Async) Config
27+
::: details Dynamic (Async) Config
2828

2929
If you need to dynamically generate the config, you can also default export a function. For example:
3030

docs/es/config.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const require = createRequire(import.meta.url)
55
const pkg = require('vitepress/package.json')
66

77
export default defineAdditionalConfig({
8-
lang: 'es-CO',
98
description: 'Generador de Sitios Estáticos desarrollado con Vite y Vue.',
109

1110
themeConfig: {
@@ -25,7 +24,7 @@ export default defineAdditionalConfig({
2524

2625
footer: {
2726
message: 'Liberado bajo la licencia MIT',
28-
copyright: `Derechos reservados © 2019-${new Date().getFullYear()} Evan You`
27+
copyright: 'Todos los derechos reservados © 2019-PRESENTE Evan You'
2928
},
3029

3130
docFooter: {

0 commit comments

Comments
 (0)