复制下方的代码到您的项目中,请参考 主题定制
+{{ locale.desc }} {{ locale.tip }}
` before copying. This option is only effective when using `useCopyCode()`.
+
+## Composition API
+
+The Composition API for this feature can be configured in `.vuepress/client.ts`:
+
+```ts title=".vuepress/client.ts"
+import { defineClientConfig } from '@vuepress/client'
+import { useCopyCode } from '@vuepress/plugin-copy-code/client'
+
+export default defineClientConfig({
+ setup() {
+ useCopyCode({
+ // ...
+ })
+ },
+})
+```
+
+### Example
+
+Add copyright information when copying code:
+
+```ts title=".vuepress/client.ts"
+import { defineClientConfig } from '@vuepress/client'
+import { useCopyCode } from '@vuepress/plugin-copy-code/client'
+
+export default defineClientConfig({
+ setup() {
+ useCopyCode({
+ transform: (preElement) => {
+ // Insert copyright information
+ pre.innerHTML += `\n Copied by vuepress-theme-plume`
+ },
+ })
+ },
+})
+```
diff --git a/docs/en/guide/code/features.md b/docs/en/guide/code/features.md
new file mode 100644
index 00000000..0aa51d64
--- /dev/null
+++ b/docs/en/guide/code/features.md
@@ -0,0 +1,567 @@
+---
+title: Feature Support
+icon: majesticons:code-block-line
+createTime: 2025/10/08 10:41:28
+permalink: /en/guide/code/features/
+---
+
+The theme provides additional features beyond basic code highlighting, enhancing the expressiveness of your code blocks.
+
+## Code Block Title
+
+Add `title="xxxx"` after \`\`\` [lang] to add a title to the current code block.
+
+**Input:**
+
+````md {1}
+```json title="package.json"
+{
+ "name": "vuepress-theme-plume"
+}
+```
+````
+
+**Output:**
+
+```json title="package.json"
+{
+ "name": "vuepress-theme-plume"
+}
+```
+
+## Line Numbers
+
+Line numbers are displayed by default in the theme, controlled by `codeHighlighter.line-numbers`.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ codeHighlighter: {
+ lineNumbers: true, // [!code ++]
+ }
+ })
+})
+```
+
+You can also control whether to display line numbers for the current code block using `:line-numbers` / `:no-line-numbers`.
+Additionally, you can customize the starting line number by adding `=` after `:line-numbers`,
+for example `:line-numbers=2` indicates that line numbers in the code block start from `2`.
+
+**Input:**
+
+````
+```ts:line-numbers
+// Line numbers enabled
+const line2 = 'This is line 2'
+const line3 = 'This is line 3'
+```
+
+```ts:no-line-numbers
+// Line numbers disabled
+const line3 = 'This is line 3'
+const line4 = 'This is line 4'
+```
+
+```ts:line-numbers=2
+// Line numbers enabled, starting from 2
+const line3 = 'This is line 3'
+const line4 = 'This is line 4'
+```
+````
+
+**Output:**
+
+```ts:line-numbers
+// Line numbers enabled
+const line2 = 'This is line 2'
+const line3 = 'This is line 3'
+```
+
+```ts:no-line-numbers
+// Line numbers disabled
+const line3 = 'This is line 3'
+const line4 = 'This is line 4'
+```
+
+```ts:line-numbers=2
+// Line numbers enabled, starting from 2
+const line3 = 'This is line 3'
+const line4 = 'This is line 4'
+```
+
+## Line Highlighting in Code Blocks
+
+Add `{xxxx}` immediately after `[lang]` to enable line highlighting, where `xxx` represents the line numbers to be highlighted.
+
+**Input:**
+
+````
+```js{4}
+export default {
+ data () {
+ return {
+ msg: 'Highlighted!'
+ }
+ }
+}
+```
+````
+
+**Output:**
+
+```js{4}
+export default {
+ data () {
+ return {
+ msg: 'Highlighted!'
+ }
+ }
+}
+```
+
+In addition to single lines, you can specify multiple single lines, line ranges, or both:
+
+- Line ranges: e.g., `{5-8}`, `{3-10}`, `{10-17}`
+- Multiple single lines: e.g., `{4,7,9}`
+- Mixed single lines and ranges: e.g., `{4,7-13,16,23-27,40}`
+
+**Input:**
+
+````
+```js{1,4,6-8}
+export default { // Highlighted
+ data () {
+ return {
+ msg: `Highlighted!
+ This line isn't highlighted,
+ but this and the next 2 are.`,
+ motd: 'VitePress is awesome',
+ lorem: 'ipsum'
+ }
+ }
+}
+```
+````
+
+**Output:**
+
+```js{1,4,6-8}
+export default { // Highlighted
+ data () {
+ return {
+ msg: `Highlighted!
+ This line isn't highlighted,
+ but this and the next 2 are.`,
+ motd: 'VitePress is awesome',
+ lorem: 'ipsum'
+ }
+ }
+}
+```
+
+You can also use the `// [!code highlight]` comment to enable line highlighting.
+
+**Input:**
+
+````
+```js
+export default {
+ data () {
+ return {
+ msg: 'Highlighted!' // [\!code highlight]
+ }
+ }
+}
+```
+````
+
+**Output:**
+
+```js
+export default {
+ data() {
+ return {
+ msg: 'Highlighted!' // [!code highlight]
+ }
+ }
+}
+```
+
+## Focus in Code Blocks
+
+Adding the `// [!code focus]` comment on a specific line will focus it and blur the rest of the code.
+
+Additionally, you can use `// [!code focus:]` to define the number of lines to focus.
+
+**Input:**
+
+````
+```js
+export default {
+ data () {
+ return {
+ msg: 'Focused!' // [\!code focus]
+ }
+ }
+}
+```
+````
+
+**Output:**
+
+```js
+export default {
+ data() {
+ return {
+ msg: 'Focused!' // [!code focus]
+ }
+ }
+}
+```
+
+::: tip Use the valid line comment syntax for the language in different code blocks
+For example, in bash code blocks, use `# [!code focus]`
+
+````md
+```bash
+mkdir hello && cd hello # [\!code focus]
+pnpm install
+```
+````
+
+```bash
+mkdir hello && cd hello # [!code focus]
+pnpm install
+```
+
+:::
+
+## Diff in Code Blocks
+
+Adding `// [!code --]` or `// [!code ++]` comments to a line will create a diff for that line while preserving the code block's syntax highlighting.
+
+**Input:**
+
+````
+```js
+export default {
+ data () {
+ return {
+ error: 'Removed', // [\!code --]
+ warning: 'Added' // [\!code ++]
+ }
+ }
+}
+```
+````
+
+**Output:**
+
+```js
+export default {
+ data() {
+ return {
+ error: 'Removed', // [!code --]
+ warning: 'Added' // [!code ++]
+ }
+ }
+}
+```
+
+::: tip Use the valid line comment syntax for the language in different code blocks
+For example, in bash code blocks, use `# [!code ++]`
+
+````md
+```bash
+mkdir hello && cd hello # [\!code ++]
+```
+````
+
+```bash
+mkdir hello && cd hello # [!code ++]
+```
+
+:::
+
+## Highlight "Errors" and "Warnings"
+
+Adding `// [!code warning]` or `// [!code error]` comments to a line will apply corresponding coloring to that line.
+
+**Input:**
+
+````
+```js
+export default {
+ data () {
+ return {
+ error: 'Error', // [\!code error]
+ warning: 'Warning' // [\!code warning]
+ }
+ }
+}
+```
+````
+
+**Output:**
+
+```js
+export default {
+ data() {
+ return {
+ error: 'Error', // [!code error]
+ warning: 'Warning' // [!code warning]
+ }
+ }
+}
+```
+
+::: tip Use the valid line comment syntax for the language in different code blocks
+For example, in bash code blocks, use `# [!code warning]`
+
+````md
+```bash
+mkdir hello && cd hello # [\!code warning]
+```
+````
+
+```bash
+mkdir hello && cd hello # [!code warning]
+```
+
+:::
+
+## Word Highlighting in Code Blocks
+
+**Input:**
+
+````
+```ts
+export function foo() { // [\!code word:Hello]
+ const msg = 'Hello World'
+ console.log(msg) // prints Hello World
+}
+```
+````
+
+**Output:**
+
+```ts
+export function foo() { // [!code word:Hello]
+ const msg = 'Hello World'
+ console.log(msg) // prints Hello World
+}
+```
+
+You can also specify the number of occurrences to highlight, for example `[!code word:options:2]`
+will highlight only the first two occurrences of `options`.
+
+**Input:**
+
+````
+```ts
+// [\!code word:options:2]
+const options = { foo: 'bar' }
+options.foo = 'baz'
+console.log(options.foo) // This won't be highlighted
+```
+````
+
+**Output:**
+
+```ts
+// [!code word:options:2]
+const options = { foo: 'bar' }
+options.foo = 'baz'
+console.log(options.foo) // This won't be highlighted
+```
+
+:::tip Use the valid line comment syntax for the language in different code blocks
+For example, in bash code blocks, use `# [!code word:hello]`
+
+````md
+```bash
+mkdir hello && cd hello # [\!code word:hello]
+```
+````
+
+```bash
+mkdir hello && cd hello # [!code word:hello]
+```
+
+:::
+
+## Whitespace in Code Blocks
+
+Render whitespace characters (tabs and spaces) as visible.
+
+Add `:whitespace` after the code block.
+
+
+
+You can also globally enable the `whitespace` feature in `codeHighlighter`:
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ codeHighlighter: {
+ whitespace: true, // [!code ++]
+ }
+ })
+})
+```
+
+When globally enabled, you can use `:no-whitespace` to disable the `whitespace` feature for a specific code block.
+
+## Collapsed Code Blocks
+
+Sometimes code blocks can be very long, which can be cumbersome when reading other content and
+affect the reading experience. In such cases, you can collapse code blocks.
+
+Add `:collapsed-lines` after the code block to collapse it, starting from line 15 by default.
+
+**Input:**
+
+````txt
+```css :collapsed-lines
+html {
+ margin: 0;
+ background: black;
+ height: 100%;
+}
+
+... more code
+```
+````
+
+**Output:**
+
+```css :collapsed-lines
+html {
+ margin: 0;
+ background: black;
+ height: 100%;
+}
+
+body {
+ margin: 0;
+ width: 100%;
+ height: inherit;
+}
+
+/* the three main rows going down the page */
+
+body > div {
+ height: 25%;
+}
+
+.thumb {
+ float: left;
+ width: 25%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.main {
+ display: none;
+}
+
+.blowup {
+ display: block;
+ position: absolute;
+ object-fit: contain;
+ object-position: center;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 2000;
+}
+
+.darken {
+ opacity: 0.4;
+}
+```
+
+You can also specify the starting line for collapsing. `:collapsed-lines=10` indicates collapsing starts from the tenth line.
+
+**Input:**
+
+````txt
+```css :collapsed-lines=10
+html {
+ margin: 0;
+ background: black;
+ height: 100%;
+}
+
+... more code
+```
+````
+
+**Output:**
+
+```css :collapsed-lines=10
+html {
+ margin: 0;
+ background: black;
+ height: 100%;
+}
+
+body {
+ margin: 0;
+ width: 100%;
+ height: inherit;
+}
+
+/* the three main rows going down the page */
+
+body > div {
+ height: 25%;
+}
+
+.thumb {
+ float: left;
+ width: 25%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.main {
+ display: none;
+}
+
+.blowup {
+ display: block;
+ position: absolute;
+ object-fit: contain;
+ object-position: center;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 2000;
+}
+
+.darken {
+ opacity: 0.4;
+}
+```
+
+You can also globally enable the `collapsed-lines` feature in `codeHighlighter`:
+
+::: code-tabs
+@tab .vuepress/config.ts
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ codeHighlighter: {
+ collapsedLines: true // [!code ++]
+ }
+ })
+})
+```
+
+:::
+
+When globally enabled, you can use `:no-collapsed-lines` to disable the `collapsed-lines` feature for a specific code block.
diff --git a/docs/en/guide/code/import.md b/docs/en/guide/code/import.md
new file mode 100644
index 00000000..143b4526
--- /dev/null
+++ b/docs/en/guide/code/import.md
@@ -0,0 +1,43 @@
+---
+title: Import Code
+icon: mdi:import
+createTime: 2025/10/08 10:39:22
+permalink: /en/guide/code/import/
+---
+
+## Overview
+
+Importing code allows you to include code from another file in your markdown file and have it highlighted.
+
+It helps you reference code from other files in your articles, avoiding duplicate code writing.
+
+## Syntax
+
+You can use the following syntax to import code blocks from files:
+
+**Input:**
+
+```md
+@[code](../snippet/snippet-1.js)
+```
+
+**Output:**
+
+@[code](../../../snippet/snippet-1.js)
+
+If you only want to import a specific portion of the file:
+
+```md
+
+@[code{1-10}](../snippet/snippet-1.js)
+```
+
+The code language is inferred from the file extension, but we recommend explicitly specifying it:
+
+```md
+
+@[code js](../snippet/snippet-1.js)
+
+
+@[code js{2,4-5}](../foo.js)
+```
diff --git a/docs/en/guide/code/intro.md b/docs/en/guide/code/intro.md
new file mode 100644
index 00000000..5d1f4cf6
--- /dev/null
+++ b/docs/en/guide/code/intro.md
@@ -0,0 +1,94 @@
+---
+title: Introduction
+icon: ic:outline-code
+createTime: 2025/10/08 10:35:45
+permalink: /en/guide/code/intro/
+---
+
+## Overview
+
+The theme uses [Shiki](https://shiki.style/) to implement syntax highlighting in Markdown code blocks.
+
+::: important Important Changes
+
+Starting from version ==1.0.0-rc.136==, the theme has migrated the code highlighting plugin from the
+internally implemented `@vuepress-plume/plugin-shikiji` to
+[@vuepress/plugin-shiki](https://ecosystem.vuejs.press/zh/plugins/markdown/shiki.html)
+provided by the [vuepress ecosystem](https://github.com/vuepress/ecosystem).
+
+_(No need to worry about significant changes - I am also one of the main developers of_
+_`@vuepress/plugin-shiki`, which implements functionality consistent with the theme's original plugin.)_
+
+Some configuration items require adjustments:
+
+- The `languages` configuration has been changed to the `langs` option. You no longer need to manually
+ add the languages you use; the plugin will automatically recognize and load language packages as needed.
+- The `themes` configuration has been changed to:
+ - When using a single theme configuration, use the `theme` option to configure the code block theme
+ - When using dual theme configuration, use the `themes` option to configure the code block themes.
+
+:::
+
+## Languages
+
+[Shiki](https://shiki.style/) supports over 190+ languages.
+You can view the complete list of supported languages at [languages](https://shiki.style/languages).
+
+You can use the following syntax to enable highlighting for code written in your chosen language:
+
+````md
+``` [lang]
+
+```
+````
+
+Where `[lang]` represents the programming language you are using.
+
+Example:
+
+````md
+// [!code word:js]
+``` js
+const a = 1
+console.log(a)
+```
+````
+
+```js
+const a = 1
+console.log(a)
+```
+
+## Highlighting Themes
+
+[Shiki](https://shiki.style/) supports over 40+ highlighting themes.
+
+You can find the complete list of supported themes at [Themes](https://shiki.style/themes) and
+customize the highlighting theme according to your preference.
+
+Theme Plume's default configuration for code block themes:
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ codeHighlighter: {
+ themes: { light: 'vitesse-light', dark: 'vitesse-dark' }, // [!code highlight]
+ }
+ })
+})
+```
+
+The default configuration supports using the `vitesse-light`/`vitesse-dark` themes for light/dark modes respectively.
+
+## Additional Features
+
+Thanks to the powerful capabilities of [Shiki](https://shiki.style/), Theme Plume provides additional
+[feature support](./features.md) for code blocks, enhancing their expressive power.
+
+Additionally, to facilitate better code demonstrations, Theme Plume provides syntax support for embedding
+[CodePen](../repl/codepen.md), [Js Fiddle](../repl/jsFiddle.md), [Code Sandbox](../repl/codeSandbox.md),
+and [Replit](../repl/replit.md), allowing you to easily embed code demonstrations.
+
+## Examples
+
+
diff --git a/docs/en/guide/code/twoslash.md b/docs/en/guide/code/twoslash.md
new file mode 100644
index 00000000..695eacd4
--- /dev/null
+++ b/docs/en/guide/code/twoslash.md
@@ -0,0 +1,767 @@
+---
+title: Two Slash
+icon: material-symbols:experiment-outline
+createTime: 2025/10/08 11:46:49
+permalink: /en/guide/markdown/twoslash/
+outline: [2, 4]
+---
+
+## Overview
+
+Adds support for [TypeScript TwoSlash](https://www.typescriptlang.org/dev/twoslash/) in code blocks. Provides inline type hints within code blocks.
+
+This feature is powered by [shiki](https://shiki.style/) and [@shikijs/twoslash](https://shiki.style/packages/twoslash), and integrated in [@vuepress-plume/plugin-shikiji](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-shikiji).
+
+::: important __twoslash__ is an advanced feature that requires proficiency in
+[TypeScript](https://www.typescriptlang.org/) and understanding of [twoslash syntax](https://twoslash.netlify.app/).
+:::
+
+::: warning
+`twoslash` is a relatively time-consuming feature. Since it requires type compilation of code,
+if the code imports large packages, it can take considerable time.
+
+Specifically, since VuePress pre-compiles all markdown files on startup, this directly affects VuePress startup time.
+If you include many `twoslash` code blocks, this may significantly increase VuePress startup time.
+
+For example, without `twoslash`, VuePress startup time typically ranges from `300ms ~ 1000ms`.
+With `twoslash`, compiling a single `twoslash` code block may require an additional `500ms` or more.
+
+However, don't worry about compilation time during markdown file hot updates.
+The theme optimizes code highlighting compilation time - even if a single markdown file contains
+multiple code blocks, the theme only compiles __modified code blocks__, so hot updates remain fast.
+:::
+
+[twoslash](https://twoslash.netlify.app/) is a `JavaScript` and `TypeScript` markup language.
+You can write code examples that describe entire `JavaScript` projects.
+
+`twoslash` treats __double-slash comments__ (`//`) as preprocessor directives for code examples.
+
+`twoslash` uses the same compiler APIs as text editors to provide type-driven hover information, accurate errors, and type annotations.
+
+## Feature Preview
+
+Hover over __variables__ or __functions__ to see the effect:
+
+```ts twoslash
+import { createHighlighter } from 'shiki'
+
+const highlighter = await createHighlighter({ themes: ['nord'], langs: ['javascript'] })
+// ^?
+//
+
+// @log: Custom log message
+const a = 1
+// @error: Custom error message
+const b = 1
+// @warn: Custom warning message
+const c = 1
+// @annotate: Custom annotation message
+```
+
+## Configuration
+
+### Enabling the Feature
+
+Before enabling this feature, you need to install the `@vuepress/shiki-twoslash` package:
+
+::: npm-to
+
+```sh
+npm i @vuepress/shiki-twoslash
+```
+
+:::
+
+Enable the `twoslash` option in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ codeHighlighter: {
+ twoslash: true,
+ },
+ }),
+})
+```
+
+::: important
+For most users, `twoslash` is not a necessary feature, and `twoslash`-related dependencies have large
+package sizes. Therefore, all `twoslash` implementations have been moved to `@vuepress/shiki-twoslash`,
+which effectively reduces the initial installation size of the theme.
+
+You only need to install `@vuepress/shiki-twoslash` when you require the `twoslash` feature.
+:::
+
+### Importing Type Files from `node_modules`
+
+The main feature of __twoslash__ is type compilation of code blocks, which natively supports importing type files from your project's `node_modules`.
+
+For example, if you need type hints for `express`, you need to install the `@types/express` dependency in your project:
+
+::: npm-to
+
+```sh
+npm i -D @types/express
+```
+
+:::
+
+Then, you can use `express` types in code blocks as follows:
+
+```` md
+```ts twoslash
+import express from 'express'
+
+const app = express()
+```
+````
+
+### Importing Local Type Files
+
+For importing local type files, since it's difficult to determine the real path of code in code blocks
+during compilation, it's not intuitive to import type files via __relative paths__ in code blocks.
+
+#### Reading Path Mappings from `tsconfig.json`
+
+The theme supports reading path mappings from `compilerOptions.paths` in `tsconfig.json` at the project root to solve this issue.
+
+Assume your project's `tsconfig.json` is configured as follows:
+
+```json title="tsconfig.json"
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
+```
+
+You can directly use paths starting with `@/` in code blocks to import type files from the `src` directory:
+
+````md
+```ts twoslash
+import type { Foo } from '@/foo'
+
+const foo: Foo = 1
+```
+````
+
+#### Reading Path Mappings from `shiki.twoslash`
+
+You can configure `compilerOptions` in `shiki.twoslash` to solve this issue:
+
+```ts title=".vuepress/config.ts"
+import path from 'node:path'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ codeHighlighter: {
+ twoslash: {
+ compilerOptions: { // [!code hl:8]
+ paths: {
+ // Relative to working directory `process.cwd()`
+ '@/*': ['./src/*'],
+ // Using absolute paths
+ '@@/*': [path.resolve(process.cwd(), './src/*')],
+ }
+ }
+ }
+ },
+ }),
+})
+```
+
+You can directly use paths starting with `@/` in code blocks to import type files from the `src` directory:
+
+````md
+```ts twoslash
+import type { Foo } from '@/foo'
+
+const foo: Foo = 1
+```
+````
+
+::: important
+Using `plugins.shiki.twoslash.compilerOptions` allows more flexible configuration of type compilation.
+You can modify `baseUrl` and other configuration options here.
+
+[Refer to CompilerOptions](https://www.typescriptlang.org/tsconfig/#compilerOptions)
+
+Usually you only need to configure the `paths` option, keeping other options default unless you understand what you're configuring.
+:::
+
+## Usage
+
+::: warning `twoslash` only supports `typescript` and `vue` code blocks.
+:::
+
+After enabling this feature, simply add the `twoslash` keyword after the code language declaration in your existing markdown code block syntax:
+
+````md{1}
+```ts twoslash
+const a = 1
+```
+````
+
+The theme only processes code blocks with the `twoslash` keyword.
+
+## Syntax Reference
+
+Complete syntax reference: [ts-twoslasher](https://github.com/microsoft/TypeScript-Website/tree/v2/packages/ts-twoslasher) and [shikijs-twoslash](https://twoslash.netlify.app/)
+
+`twoslash` treats __double slashes__ as preprocessor directives for code examples. Therefore, all annotations are added after `//`.
+
+### Symbol Annotations
+
+Common `twoslash` annotations:
+
+#### `^?` {#extract-type}
+
+Use `^?` to extract type information for specific identifiers on the code line above it.
+
+__Input:__
+
+````md
+```ts twoslash
+const hi = 'Hello'
+const msg = `${hi}, world`
+// ^?
+```
+````
+
+__Output:__
+
+```ts twoslash
+const hi = 'Hello'
+const msg = `${hi}, world`
+// ^?
+//
+```
+
+::: important The symbol `^` must correctly point to the variable whose type you want to highlight.
+:::
+
+#### `^|` {#completions}
+
+Use `^|` to extract autocompletion information at a specific position.
+
+__Input:__
+
+````md
+```ts twoslash
+// @noErrors
+console.e
+// ^|
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @noErrors
+console.e
+// ^|
+//
+```
+
+::: important The symbol `^` must correctly point to the position where you want content prediction.
+:::
+
+Twoslash requests TypeScript for autocompletion suggestions at the `^` position,
+then filters possible outputs based on letters after the `.`. Up to 5 inline results are displayed,
+and if a completion item is marked as deprecated, the output reflects this.
+
+In this case, Twoslash requests completion suggestions for `console` from TypeScript,
+then filters for items starting with `e`. Note the `// @noErrors` compiler flag is set because `console.e`
+is a failing TypeScript code example, but we don't care about that.
+
+#### `^^^` {#highlighting}
+
+Use `^^^` to highlight specific ranges on the line above it.
+
+__Input:__
+
+````md
+```ts twoslash
+function add(a: number, b: number) {
+ // ^^^
+ return a + b
+}
+```
+````
+
+__Output:__
+
+```ts twoslash
+function add(a: number, b: number) {
+ // ^^^
+ return a + b
+}
+```
+
+::: important Use consecutive `^` symbols to correctly point to the range you want to highlight.
+:::
+
+### `@filename` {#import-files}
+
+`@filename: ` declares which file subsequent code will come from. You can import this file via `import` in other parts of the code.
+
+__Input:__
+
+````md
+```ts twoslash
+// @filename: sum.ts
+export function sum(a: number, b: number): number {
+ return a + b
+}
+
+// @filename: ok.ts
+import { sum } from './sum'
+sum(1, 2)
+
+// @filename: error.ts
+// @errors: 2345
+import { sum } from './sum'
+sum(4, 'woops')
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @filename: sum.ts
+export function sum(a: number, b: number): number {
+ return a + b
+}
+
+// @filename: ok.ts
+import { sum } from './sum'
+sum(1, 2)
+
+// @filename: error.ts
+// @errors: 2345
+import { sum } from './sum'
+sum(4, 'woops')
+```
+
+### Code Cutting
+
+#### `---cut-before---` {#cut-before}
+
+After TypeScript generates the project and extracts all editor information (like identifiers,
+queries, highlights, etc.), cutting operations adjust all offsets and line numbers to fit the smaller output.
+
+Users see content below `// ---cut-before---`. The shorthand `// ---cut---` is also supported.
+
+__Input:__
+
+````md
+```ts twoslash
+const level: string = 'Danger'
+// ---cut---
+console.log(level)
+````
+
+__Output:__
+
+```ts twoslash
+const level: string = 'Danger'
+// ---cut---
+console.log(level)
+```
+
+Show only a single file:
+
+__Input:__
+
+````md
+```ts twoslash
+// @filename: a.ts
+export const helloWorld: string = 'Hi'
+// ---cut---
+// @filename: b.ts
+import { helloWorld } from './a'
+
+console.log(helloWorld)
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @filename: a.ts
+export const helloWorld: string = 'Hi'
+// ---cut---
+// @filename: b.ts
+import { helloWorld } from './a'
+
+console.log(helloWorld)
+```
+
+Only the last two lines are displayed, but to TypeScript, this is a program with two files,
+and all IDE information is correctly connected between files. This is why `// @filename: [file]`
+is the only Twoslash command not removed, as it can be `---cut---` if irrelevant.
+
+#### `---cut-after---` {#cut-after}
+
+The sibling of `---cut-before---`, used to trim everything after the symbol:
+
+__Input:__
+
+````md
+```ts twoslash
+const level: string = 'Danger'
+// ---cut-before---
+console.log(level)
+// ---cut-after---
+console.log('This is not shown')
+```
+````
+
+__Output:__
+
+```ts twoslash
+const level: string = 'Danger'
+// ---cut-before---
+console.log(level)
+// ---cut-after---
+console.log('This is not shown')
+```
+
+#### `---cut-start---` and `---cut-end---` {#cut-start-end}
+
+You can also use the `---cut-start---` and `---cut-end---` pair to cut code segments between two symbols.
+
+__Input:__
+
+````md
+```ts twoslash
+const level: string = 'Danger'
+// ---cut-start---
+console.log(level) // This part is cut
+// ---cut-end---
+console.log('This is shown')
+```
+````
+
+__Output:__
+
+```ts twoslash
+const level: string = 'Danger'
+// ---cut-start---
+console.log(level) // This part is cut
+// ---cut-end---
+console.log('This is shown')
+```
+
+Multiple instances are supported to cut multiple sections, but symbols must appear in pairs.
+
+### Custom Output Messages {id=twoslash-custom-message}
+
+`@log`, `@error`, `@warn`, and `@annotate` output custom messages at different levels to users.
+
+````md
+```ts twoslash
+// @log: Custom log message
+const a = 1
+// @error: Custom error message
+const b = 1
+// @warn: Custom warning message
+const c = 1
+// @annotate: Custom annotation message
+```
+````
+
+```ts twoslash
+// @log: Custom log message
+const a = 1
+// @error: Custom error message
+const b = 1
+// @warn: Custom warning message
+const c = 1
+// @annotate: Custom annotation message
+```
+
+### Output Compiled Files
+
+Running Twoslash code examples triggers full TypeScript compilation runs that create files in a virtual
+file system. You can replace code example content with results from running TypeScript on the project.
+
+#### `@showEmit`
+
+`// @showEmit` is the primary command to tell Twoslash you want to replace the code example output with the equivalent `.js` file.
+
+__Input:__
+
+````md
+```ts twoslash
+// @showEmit
+const level: string = 'Danger'
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @showEmit
+const level: string = 'Danger'
+```
+
+The result shows the `.js` file corresponding to this `.ts` file. You can see TypeScript output removes `: string` and adds `export {}`.
+
+#### `@showEmittedFile: [file]`
+
+While `.js` files may be the most useful out of the box, TypeScript does emit other files (`.d.ts` and `.map`)
+when proper flags are enabled, and with multi-file code examples, you may need to tell Twoslash which file to
+display. For all these cases, you can also add `@showEmittedFile: [file]` to tell Twoslash which file you want to display.
+
+__Display `.d.ts` file for TypeScript code example:__
+
+__Input:__
+
+````md
+```ts twoslash
+// @declaration
+// @showEmit
+// @showEmittedFile: index.d.ts
+export const hello = 'world'
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @declaration
+// @showEmit
+// @showEmittedFile: index.d.ts
+export const hello = 'world'
+```
+
+__Display `.map` file from JavaScript to TypeScript:__
+
+__Input:__
+
+````md
+```ts twoslash
+// @sourceMap
+// @showEmit
+// @showEmittedFile: index.js.map
+export const hello = 'world'
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @sourceMap
+// @showEmit
+// @showEmittedFile: index.js.map
+export const hello = 'world'
+```
+
+__Display `.map` for `.d.ts` files (mainly for project references):__
+
+__Input:__
+
+````md
+```ts twoslash
+// @declaration
+// @declarationMap
+// @showEmit
+// @showEmittedFile: index.d.ts.map
+export const hello: string = 'world'
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @declaration
+// @declarationMap
+// @showEmit
+// @showEmittedFile: index.d.ts.map
+export const hello: string = 'world'
+```
+
+__Generate `.js` file for `b.ts`:__
+
+__Input:__
+
+````md
+```ts twoslash
+// @showEmit
+// @showEmittedFile: b.js
+// @filename: a.ts
+export const helloWorld: string = 'Hi'
+
+// @filename: b.ts
+import { helloWorld } from './a'
+console.log(helloWorld)
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @showEmit
+// @showEmittedFile: b.js
+// @filename: a.ts
+export const helloWorld: string = 'Hi'
+
+// @filename: b.ts
+import { helloWorld } from './a'
+console.log(helloWorld)
+```
+
+### `@errors`
+
+`@errors: ` shows how code produces errors:
+
+__Input:__
+
+````md
+```ts twoslash
+// @errors: 2322 2588
+const str: string = 1
+str = 'Hello'
+````
+
+__Output:__
+
+```ts twoslash
+// @errors: 2322 2588
+const str: string = 1
+str = 'Hello'
+```
+
+You need to declare corresponding TypeScript error codes after `@errors`. Separate multiple error codes with spaces.
+
+::: note
+If you don't know which error code to add, try writing the code first and wait for compilation to fail.
+You should see relevant error information in the console, then find the corresponding error code in the
+error message's `description`. Then add the error code to `@errors`.
+
+Don't worry about compilation failures terminating the process - the theme displays error information
+when compilation fails while outputting uncompiled code in the code block.
+:::
+
+### `@noErrors`
+
+Suppresses all errors in code. You can also provide error codes to suppress specific errors.
+
+__Input:__
+
+````md
+```ts twoslash
+// @noErrors
+const str: string = 1
+str = 'Hello'
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @noErrors
+const str: string = 1
+str = 'Hello'
+```
+
+### `@noErrorsCutted`
+
+Ignores errors occurring in cut code.
+
+__Input:__
+
+````md
+```ts twoslash
+// @noErrorsCutted
+const hello = 'world'
+// ---cut-after---
+hello = 'hi' // Should be an error but ignored because it's cut.
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @noErrorsCutted
+const hello = 'world'
+// ---cut-after---
+hello = 'hi' // Should be an error but ignored because it's cut.
+```
+
+### `@noErrorValidation`
+
+Disables error validation. Error messages will still render, but Twoslash won't throw errors from compile-time code.
+
+__Input:__
+
+````md
+```ts twoslash
+// @noErrorValidation
+const str: string = 1
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @noErrorValidation
+const str: string = 1
+```
+
+### `@keepNotations`
+
+Tells Twoslash not to remove any comments and keep original code unchanged. Nodes will contain position information of original code.
+
+__Input:__
+
+````md
+```ts twoslash
+// @keepNotations
+// @module: esnext
+// @errors: 2322
+const str: string = 1
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @keepNotations
+// @module: esnext
+// @errors: 2322
+const str: string = 1
+```
+
+### Overriding Compiler Options
+
+Use `// @name` and `// @name: value` comments to override TypeScript's
+[compiler options](https://www.typescriptlang.org/tsconfig#compilerOptions). These comments will be removed from output.
+
+__Input:__
+
+````md
+```ts twoslash
+// @noImplicitAny: false
+// @target: esnext
+// @lib: esnext
+// This should throw an error,
+// but since we disabled noImplicitAny, it won't.
+const fn = a => a + 1
+```
+````
+
+__Output:__
+
+```ts twoslash
+// @noImplicitAny: false
+// @target: esnext
+// @lib: esnext
+// This should throw an error,
+// but since we disabled noImplicitAny, it won't.
+const fn = a => a + 1
+```
diff --git a/docs/en/guide/components/badge.md b/docs/en/guide/components/badge.md
new file mode 100644
index 00000000..18490dbd
--- /dev/null
+++ b/docs/en/guide/components/badge.md
@@ -0,0 +1,110 @@
+---
+title: Badge
+icon: iconamoon:badge-light
+createTime: 2025/10/08 22:45:50
+permalink: /en/guide/components/badge/
+---
+
+## Overview
+
+Use the `` component to display inline information such as status or labels.
+
+Pass the content you want to display to the `text` prop of the `` component.
+
+## Props
+
+:::: field-group
+
+::: field name="type" type="'info' | 'tip' | 'warning' | 'danger' | string" default="'tip'" optional
+Badge type. Different types use different color schemes. Custom types are supported.
+:::
+
+::: field name="text" type="string" default="''" optional
+Badge text content.
+:::
+
+::: field name="color" type="string" optional
+Custom badge text color.
+:::
+
+::: field name="bgColor" type="string" optional
+Custom badge background color.
+:::
+
+::: field name="borderColor" type="string" optional
+Custom badge border color.
+:::
+
+::::
+
+## Examples
+
+**Input:**
+
+```md :no-line-numbers
+- VuePress -
+- VuePress -
+- VuePress -
+- VuePress -
+- VuePress -
+```
+
+**Output:**
+
+- VuePress -
+- VuePress -
+- VuePress -
+- VuePress -
+- VuePress -
+
+Using custom `type` enables richer visual presentations.
+
+**Input:**
+
+1. Add predefined styles in the theme's [custom style file](../custom/style.md.md):
+
+ ```css
+ /* Light theme */
+ .vp-badge.important {
+ color: #8e5cd9;
+ background-color: rgba(159, 122, 234, 0.14);
+ border-color: transparent;
+ }
+
+ /* Dark theme */
+ [data-theme="dark"] .vp-badge.important {
+ color: #8e5cd9;
+ background-color: rgba(159, 122, 234, 0.16);
+ border-color: transparent;
+ }
+
+ /**
+ 'important' is a custom type
+ */
+ ```
+
+2. Use the custom `type`:
+
+ ```md :no-line-numbers
+ VuePress -
+ ```
+
+ **Output:**
+
+ VuePress -
+
+
diff --git a/docs/en/guide/components/card-grid.md b/docs/en/guide/components/card-grid.md
new file mode 100644
index 00000000..644071c8
--- /dev/null
+++ b/docs/en/guide/components/card-grid.md
@@ -0,0 +1,69 @@
+---
+title: Card Grid
+icon: vaadin:grid-h
+createTime: 2025/10/08 23:38:33
+permalink: /en/guide/components/card-grid/
+---
+
+## Overview
+
+The `` component is used when multiple cards need to be arranged. Cards are automatically arranged when sufficient space is available.
+
+## Props
+
+:::: field-group
+::: field name="cols" type="number | { sm: number, md: number, lg: number }" default="2"
+
+Number of columns for card arrangement.
+
+The component automatically adjusts the number of columns based on screen width by default.
+Two columns are displayed when space permits, while a single column is shown on smaller screens.
+
+The `cols` prop configures the number of columns. When a `number` is provided,
+all screen sizes display `number` columns. When `{ sm: number, md: number, lg: number }` is provided,
+the number of columns adjusts automatically based on screen width.
+
+- `sm` : `< 768px`
+- `md` : `>= 768px < 960px`
+- `lg` : `>= 960px`
+
+It is recommended that the provided `number` does not exceed `3`.
+
+:::
+::::
+
+## Examples
+
+**Input:**
+
+```md :no-line-numbers
+
+
+ This is the card content.
+
+
+ This is the card content.
+
+
+
+
+
+
+
+```
+
+**Output:**
+
+
+
+ This is the card content.
+
+
+ This is the card content.
+
+
+
+
+
+
+
diff --git a/docs/en/guide/components/card-masonry.md b/docs/en/guide/components/card-masonry.md
new file mode 100644
index 00000000..00f95f1d
--- /dev/null
+++ b/docs/en/guide/components/card-masonry.md
@@ -0,0 +1,273 @@
+---
+title: Masonry Card
+icon: ri:layout-masonry-line
+createTime: 2025/10/08 17:17:06
+permalink: /en/guide/components/card-masonry/
+---
+
+## Overview
+
+The Masonry Card is a versatile container component that automatically calculates the height of
+each **item** and arranges them in a masonry layout. Any content can be placed within ``.
+
+::: details What is an item?
+
+An item represents individual content such as an image, text, video, etc.
+
+- In Markdown syntax, any content occupying its own line (with blank lines before and after) is considered an item.
+- In HTML structure, each direct child element of the container is considered an item.
+
+:::
+
+```md
+
+
+
+
+
+
+
+```
+
+## Props
+
+:::: field-group
+
+::: field name="cols" type="number | { sm: number, md: number, lg: number }" optional
+Number of columns.
+
+The component automatically adjusts the number of columns based on screen width by default.
+Three columns are displayed when space permits, while two columns are shown on smaller screens.
+
+The `cols` prop configures the number of columns. When a `number` is provided,
+all screen sizes display `number` columns. When `{ sm: number, md: number, lg: number }` is provided,
+the number of columns adjusts automatically based on screen width.
+
+- `sm` : `< 640px`
+- `md` : `>= 640px < 960px`
+- `lg` : `>= 960px`
+:::
+
+::: field name="gap" type="number" optional default="16"
+Gap between columns.
+:::
+
+::::
+
+## Markdown Syntax Support
+
+In Markdown, the `::: card-masonry` container can be used instead of ``.
+
+``` md
+::: card-masonry cols="3" gap="16"
+
+
+
+
+
+:::
+```
+
+## Examples
+
+### Image Masonry
+
+Masonry layout is particularly suitable for displaying images. You can directly place `` within `::: card-masonry`.
+
+**Input:**
+
+``` md
+::: card-masonry
+
+
+
+
+
+
+
+
+
+
+
+
+
+:::
+```
+
+**Output:**
+
+::: card-masonry
+
+
+
+
+
+
+
+
+
+
+
+
+
+:::
+
+### Card Masonry
+
+Masonry layout is also suitable for displaying cards. You can place `::: card` containers within `::: card-masonry`.
+
+**Input:**
+
+``` md :collapsed-lines
+:::: card-masonry
+
+::: card title="Card 1"
+Card content
+:::
+
+::: card title="Card 2"
+Card content
+
+Additional card content
+:::
+
+::: card title="Card 3"
+Card content
+:::
+
+::: card title="Card 4"
+Card content
+:::
+
+::: card title="Card 5"
+Card content
+
+Additional card content
+:::
+
+::: card title="Card 6"
+Card content
+:::
+
+::::
+```
+
+**Output:**
+
+:::: card-masonry
+
+::: card title="Card 1"
+Card content
+:::
+
+::: card title="Card 2"
+Card content
+
+Additional card content
+:::
+
+::: card title="Card 3"
+Card content
+:::
+
+::: card title="Card 4"
+Card content
+:::
+
+::: card title="Card 5"
+Card content
+
+Additional card content
+:::
+
+::: card title="Card 6"
+Card content
+:::
+
+::::
+
+### Code Block Masonry
+
+**Input:**
+
+````md :collapsed-lines
+:::card-masonry
+
+```ts
+const a = 1
+```
+
+```json
+{
+ "name": "John"
+}
+```
+
+```css
+p {
+ color: red;
+}
+```
+
+```html
+
+
+ Hello world
+
+
+```
+
+```ts
+const a = 12
+const b = 1
+```
+
+```rust
+fn main() {
+ println!("Hello, world!");
+}
+```
+
+:::
+````
+
+**Output:**
+
+:::card-masonry
+
+```ts
+const a = 1
+```
+
+```json
+{
+ "name": "John"
+}
+```
+
+```css
+p {
+ color: red;
+}
+```
+
+```html
+
+
+ Hello world
+
+
+```
+
+```ts
+const a = 12
+const b = 1
+```
+
+```rust
+fn main() {
+ println!("Hello, world!");
+}
+```
+
+:::
diff --git a/docs/en/guide/components/card.md b/docs/en/guide/components/card.md
new file mode 100644
index 00000000..04778b43
--- /dev/null
+++ b/docs/en/guide/components/card.md
@@ -0,0 +1,68 @@
+---
+title: Card
+icon: solar:card-broken
+createTime: 2025/10/08 23:09:07
+permalink: /en/guide/components/card/
+---
+
+## Overview
+
+Use the `` component to display cards within a page.
+
+Alternatively, the markdown [card container](../markdown/card.md) syntax can be used as a substitute for the `` component.
+
+## Props
+
+:::: field-group
+
+::: field name="title" type="string" default="''" optional
+Card title.
+:::
+
+::: field name="icon" type="string | { svg: string }" default="''" optional
+Icon displayed to the left of the title. Supports all icons from iconify, or an image URL can be used.
+:::
+
+::::
+
+## Slots
+
+| Name | Description |
+| ------- | -------------------- |
+| default | Card content. |
+| title | Custom title content.|
+
+## Examples
+
+**Input:**
+
+```md :no-line-numbers
+
+ This is the card content.
+
+
+
+
+ Card Title
+
+ This is the card content.
+
+```
+
+**Output:**
+
+
+ This is the card content.
+
+
+
+
+ Card Title
+
+ This is the card content.
+
+
+:::info
+Markdown syntax can also be used inside slots. However,
+please note that an empty line is required between the markdown syntax and the tags. Otherwise, it will be interpreted as plain text.
+:::
diff --git a/docs/en/guide/components/home-box.md b/docs/en/guide/components/home-box.md
new file mode 100644
index 00000000..cb8e6ad4
--- /dev/null
+++ b/docs/en/guide/components/home-box.md
@@ -0,0 +1,32 @@
+---
+title: Home Layout Container
+icon: tabler:container
+createTime: 2025/10/08 23:49:40
+permalink: /en/guide/components/home-box/
+---
+
+## Home Layout Container
+
+The `` component provides a wrapper container for areas when customizing the homepage layout.
+
+## Props
+
+:::: field-group
+
+::: field name="type" type="string" default="''" optional
+Area type.
+:::
+
+::: field name="full" type="boolean" default="false" optional
+Whether to enable fullscreen mode.
+:::
+
+::: field name="background-image" type="string" default="''" optional
+Area background image.
+:::
+
+::: field name="background-attachment" type="'fixed' | 'local'" default="'local'" optional
+Area background attachment method.
+:::
+
+::::
diff --git a/docs/en/guide/components/icon.md b/docs/en/guide/components/icon.md
new file mode 100644
index 00000000..6e19609c
--- /dev/null
+++ b/docs/en/guide/components/icon.md
@@ -0,0 +1,83 @@
+---
+title: Icon
+icon: grommet-icons:emoji
+createTime: 2025/10/08 22:58:39
+permalink: /en/guide/components/icon/
+---
+
+## Overview
+
+The ` ` component loads icons from different icon libraries based on the `markdown.icon` configuration.
+
+[The theme also provides markdown syntax support. Click to learn more](../markdown/icons.md){.read-more}
+
+## Configuration
+
+```ts title=".vuepress/config.ts" twoslash
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: { // [!code ++:3]
+ icon: { provider: 'iconify' } // Enabled by default
+ }
+ })
+})
+```
+
+```ts
+interface IconOptions {
+ /**
+ * Icon provider
+ */
+ provider: 'iconify' | 'iconfont' | 'fontawesome'
+ /**
+ * Default icon prefix. Different providers have different default prefixes
+ * - iconify - Default: `''`
+ * - iconfont - Default: `iconfont icon-`
+ * - fontawesome - Default: `fas`
+ */
+ prefix?: string
+ /**
+ * Icon asset links
+ */
+ assets?: IconAssetLink | IconAssetLink[]
+ size?: string | number
+ color?: string
+}
+```
+
+## Props
+
+:::: field-group
+
+::: field name="name" type="string" default="''" optional
+Icon name. When `markdown.icon.prefix` has a value, the prefix in `name` can be omitted.
+:::
+
+::: field name="color" type="string" default="'currentcolor'" optional
+Icon color.
+:::
+
+::: field name="size" type="string" default="'1em'" optional
+Icon size.
+:::
+
+::::
+
+## Examples
+
+**Input:**
+
+```md :no-line-numbers
+- home -
+- vscode -
+- twitter -
+```
+
+**Output:**
+
+- home -
+- vscode -
+- twitter -
diff --git a/docs/en/guide/components/image-card.md b/docs/en/guide/components/image-card.md
new file mode 100644
index 00000000..71884cd1
--- /dev/null
+++ b/docs/en/guide/components/image-card.md
@@ -0,0 +1,135 @@
+---
+title: Image Card
+icon: fa:photo
+createTime: 2025/10/08 23:35:51
+permalink: /en/guide/components/image-card/
+---
+
+## Overview
+
+Use the `` component to display image cards on a page.
+
+The Image Card differs from markdown's standard image insertion method by presenting more information
+related to the image, including title, description, author, link, etc.
+It is suitable for scenarios such as photography works, design works, promotional posters, and more.
+
+## Props
+
+:::: field-group
+
+::: field name="image" type="string" required
+The image URL. Local images must use an absolute path, i.e., a path starting with `/`, pointing to the `/public` directory.
+:::
+
+::: field name="title" type="string" optional
+The image title.
+:::
+
+::: field name="description" type="string" optional
+The image description.
+:::
+
+::: field name="author" type="string" optional
+The image author.
+:::
+
+::: field name="href" type="string" optional
+The link to navigate to when the image title is clicked.
+:::
+
+::: field name="date" type="string | Date | number" optional
+The image creation date.
+:::
+
+::: field name="width" type="string | number" optional
+The image width.
+:::
+
+::: field name="center" type="boolean" optional
+Whether to center the image when its width is less than the screen width.
+:::
+
+::::
+
+## Examples
+
+**Input:**
+
+```md :no-line-numbers
+
+```
+
+**Output:**
+
+
+
+It can also be placed within a `` component.
+
+**Input:**
+
+```md :no-line-numbers
+
+
+
+
+```
+
+**Output:**
+
+
+
+
+
+
+[View Photography Works Example](../../../../../blog/1.示例/照片类作品示例.md)
diff --git a/docs/en/guide/components/link-card.md b/docs/en/guide/components/link-card.md
new file mode 100644
index 00000000..2667bc64
--- /dev/null
+++ b/docs/en/guide/components/link-card.md
@@ -0,0 +1,105 @@
+---
+title: Link Card
+icon: solar:card-send-linear
+createTime: 2025/10/08 23:14:00
+permalink: /en/guide/components/link-card/
+---
+
+## Overview
+
+Use the `` component to display link cards on pages.
+
+## Props
+
+:::: field-group
+
+::: field name="title" type="string" default="''" optional
+Link card title.
+:::
+
+::: field name="icon" type="string | { svg: string }" default="''" optional
+Icon displayed to the left of the title. Supports icons from providers configured in
+[markdown.icon](../features/icon.md), or image URLs can be used.
+:::
+
+::: field name="href" type="string" default="''" optional
+Link card navigation URL.
+:::
+
+::: field name="description" type="string" default="''" optional
+Link card description. It is recommended to use the component's default slot for description content.
+:::
+
+::: field name="target" type="string" default="''" optional
+Link target behavior.
+:::
+
+::::
+
+## Slots
+
+| Name | Description |
+|---------|----------------------|
+| default | Card detail content |
+| title | Custom title content |
+
+## Examples
+
+**Input:**
+
+```md :no-line-numbers
+
+
+```
+
+**Output:**
+
+
+
+
+Using component slots enables richer presentations.
+
+**Input:**
+
+```md :no-line-numbers
+
+
+ - Card content
+ - Card content
+
+
+
+
+
+ Title
+
+
+ - Card content
+ - Card content
+
+
+```
+
+**Output:**
+
+
+
+- Card content
+- Card content
+
+
+
+
+
+ Title
+
+
+- Card content
+- Card content
+
+
+
+:::info
+Markdown syntax can also be used within slots, but note that there must be a blank line between the
+markdown syntax and the tags. Otherwise, it will be parsed as plain text.
+:::
diff --git a/docs/en/guide/components/npm-badge.md b/docs/en/guide/components/npm-badge.md
new file mode 100644
index 00000000..ad8d835b
--- /dev/null
+++ b/docs/en/guide/components/npm-badge.md
@@ -0,0 +1,204 @@
+---
+title: Npm Badge
+icon: akar-icons:npm-fill
+createTime: 2025/10/08 22:07:23
+permalink: /en/guide/components/npm-badge/
+---
+
+
+
+## Overview
+
+The Npm Badge component is used to display npm package information and provide relevant links.
+
+The badges are powered by .
+
+## Usage
+
+To use this component, you need to manually import the `NpmBadge` or `NpmBadgeGroup` components:
+
+```md :no-line-numbers
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+## ` `
+
+Single npm badge
+
+### Props
+
+:::: field-group
+
+::: field name="name" type="string" optional
+npm package name. If empty, it will be obtained from `repo`
+:::
+
+::: field name="repo" type="string"
+Package GitHub repository address in `owner/repo` format. Required when `name` is empty
+:::
+
+::: field name="type" type="NpmBadgeType"
+Badge type
+:::
+
+::: field name="theme" type="NpmBadgeTheme" optional default="'flat'"
+Badge theme
+:::
+
+::: field name="label" type="string" optional
+Badge label
+:::
+
+::: field name="color" type="string" optional default="'#32A9C3'"
+Badge color
+:::
+
+::: field name="labelColor" type="string" optional default="'#1B3C4A'"
+Badge label color
+:::
+
+::: field name="branch" type="string" optional default="'main'"
+Repository branch
+:::
+
+::: field name="dir" type="string" optional
+Package directory in repository. Suitable for monorepo projects
+:::
+
+::::
+
+### Types
+
+```ts
+type NpmBadgeType
+ // github
+ = | 'source' // github source
+ | 'stars' // github stars
+ | 'forks' // github forks
+ | 'license' // github license
+ // npm
+ | 'version' // npm version
+ | 'dt' // alias d18m
+ | 'd18m' // npm downloads last 18 months
+ | 'dw' // npm downloads weekly
+ | 'dm' // npm downloads monthly
+ | 'dy' // npm downloads yearly
+
+type NpmBadgeTheme = 'flat' | 'flat-square' | 'plastic' | 'for-the-badge' | 'social'
+```
+
+### Examples
+
+- ` ` -
+- ` ` -
+- ` ` -
+- ` ` -
+- ` ` -
+- ` ` -
+- ` ` -
+- ` ` -
+- ` ` -
+- ` ` -
+
+## ` `
+
+Combines multiple npm badges
+
+### Props
+
+:::: field-group
+
+::: field name="name" type="string" optional
+npm package name. If empty, it will be obtained from `repo`
+:::
+
+::: field name="repo" type="string"
+Package GitHub repository address in `owner/repo` format. Required when `name` is empty
+:::
+
+::: field name="items" type="string | NpmBadgeType[]" optional default="[]"
+List of badge types. When passing a `string`, separate with `','` and it will be automatically converted to `NpmBadgeType[]`
+:::
+
+::: field name="theme" type="NpmBadgeTheme" optional
+Badge theme
+:::
+
+::: field name="color" type="string" optional
+Badge color
+:::
+
+::: field name="labelColor" type="string" optional
+Badge label color
+:::
+
+::: field name="branch" type="string" optional
+Repository branch
+:::
+
+::: field name="dir" type="string" optional
+Package directory in repository. Suitable for monorepo projects
+:::
+
+::::
+
+### Slots
+
+` ` supports passing multiple ` ` components.
+
+The `Props` declared in ` ` will be injected into the ` ` components.
+This approach is used to implement and simplify badge combinations.
+
+### Examples
+
+**Input:**
+
+```md :no-line-numbers
+
+```
+
+**Output:**
+
+
+
+Use ` ` to flexibly define badge combinations:
+
+**Input:**
+
+```md :no-line-numbers
+
+
+
+
+
+
+```
+
+**Output:**
+
+
+
+
+
+
+
diff --git a/docs/en/guide/components/plot.md b/docs/en/guide/components/plot.md
new file mode 100644
index 00000000..3785336c
--- /dev/null
+++ b/docs/en/guide/components/plot.md
@@ -0,0 +1,50 @@
+---
+title: Plot Text
+icon: lets-icons:hide-eye
+createTime: 2025/10/08 23:02:39
+permalink: /en/guide/components/plot/
+---
+
+## Overview
+
+Use the `` component to display [plot text](../markdown/plot.md) with more flexible control over behavior.
+
+This component is disabled by default and needs to be enabled in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ plot: true,
+ },
+ })
+})
+```
+
+## Props
+
+:::: field-group
+
+::: field name="trigger" type="'hover' | 'click'" default="'hover'" optional
+Trigger on mouse hover or click
+:::
+
+::: field name="effect" type="'blur' | 'mask'" default="'mask'" optional
+Mask layer effect or text blur effect
+:::
+
+::::
+
+## Examples
+
+**Input:**
+
+```md :no-line-numbers
+- Hover - Visible on hover
+- Click - Visible on click
+```
+
+**Output:**
+
+- Hover - Visible on hover
+- Click - Visible on click
diff --git a/docs/en/guide/components/repo-card.md b/docs/en/guide/components/repo-card.md
new file mode 100644
index 00000000..04a1fe2a
--- /dev/null
+++ b/docs/en/guide/components/repo-card.md
@@ -0,0 +1,120 @@
+---
+title: Repo Card
+icon: octicon:repo-16
+createTime: 2025/10/08 21:11:56
+permalink: /en/guide/components/github-repo-card/
+---
+
+
+
+## Overview
+
+The Repo Card component is used to display GitHub/Gitee repository information.
+
+## Usage
+
+To use this component, you need to manually import the `RepoCard` component:
+
+```md :no-line-numbers
+
+
+
+
+
+```
+
+Register as a global component:
+
+```ts title=".vuepress/client.ts"
+import RepoCard from 'vuepress-theme-plume/features/RepoCard.vue'
+import { defineClientConfig } from 'vuepress/client'
+
+export default defineClientConfig({
+ enhance({ app }) {
+ app.component('RepoCard', RepoCard)
+ },
+})
+```
+
+Global components can be used in any other markdown file:
+
+```md
+
+```
+
+### Props
+
+:::: field-group
+
+::: field name="repo" type="string" required
+Repository address in `owner/repo` format
+:::
+
+::: field name="provider" type="github | gitee" optional default="'github'"
+Repository platform. Currently only `github`/`gitee` are supported.
+:::
+
+::: field name="fullname" type="boolean" optional
+Whether to display the full repository name.
+
+The full repository name is `owner/repo`.
+
+- If the owner is an individual, the full repository name is not displayed by default, only `repo` is shown.
+- If the owner is an organization, the full repository name is displayed by default.
+:::
+
+::::
+
+## Examples
+
+### Single Card
+
+**Input:**
+
+```md
+
+```
+
+**Output:**
+
+
+
+### Multiple Cards
+
+If you want to display multiple cards side by side in a compact way, you can use the `CardGrid` component.
+
+**Input:**
+
+```md
+
+
+
+
+```
+
+**Output:**
+
+
+
+
+
+
+**Input:**
+
+```md
+
+
+
+
+```
+
+**Output:**
+
+
+
+
+
diff --git a/docs/en/guide/components/swiper.md b/docs/en/guide/components/swiper.md
new file mode 100644
index 00000000..de42231b
--- /dev/null
+++ b/docs/en/guide/components/swiper.md
@@ -0,0 +1,290 @@
+---
+title: Swiper
+icon: dashicons:images-alt2
+createTime: 2025/10/08 22:00:22
+permalink: /en/guide/components/swiper/
+---
+
+## Overview
+
+Use the `` component to display image carousels on pages.
+
+## Usage
+
+To use this component, first manually install the `swiper` library:
+
+::: npm-to
+
+```sh
+npm install swiper
+```
+
+:::
+
+Then, manually import the `Swiper` component:
+
+```md
+
+
+
+
+
+```
+
+Register as a global component:
+
+```ts title=".vuepress/client.ts"
+import Swiper from 'vuepress-theme-plume/features/Swiper.vue'
+import { defineClientConfig } from 'vuepress/client'
+
+export default defineClientConfig({
+ enhance({ app }) {
+ app.component('Swiper', Swiper)
+ },
+})
+```
+
+Global components can be used in any other markdown file:
+
+```md
+
+```
+
+
+
+**Example:**
+
+
+
+## Props
+
+| Name | Type | Default | Description |
+| ----------------- | ---------------------------------------------------------- | ---------- | ----------------------------------------------------------------------------------- |
+| items | `string \| { link: string; href?: string; alt?: string}[]` | `[]` | Image link array. When passing objects, `link` represents image URL, `href` represents navigation link, `alt` represents image description |
+| width | `number \| string` | `100%` | Carousel area width |
+| height | `number \| string` | `100%` | Carousel area height |
+| mode | `'banner' \| 'carousel' \| 'broadcast'` | `'banner'` | Carousel mode: `banner`: banner; `carousel`: carousel; `broadcast`: information display |
+| navigation | `boolean` | `true` | Whether to show navigation buttons |
+| effect | `'slide' \| 'fade' \| 'cube' \| 'coverflow' \| 'flip' \| 'cards' \| 'creative'` | `'slide'` | Carousel effect |
+| delay | `number` | `3000` | Carousel interval time. Only effective when `mode: 'banner'`. Unit: `ms` |
+| speed | `number` | `300` | Animation duration. Unit: `ms` |
+| loop | `boolean` | `true` | Whether to loop |
+| pauseOnMouseEnter | `boolean` | `false` | Whether to pause carousel on mouse hover |
+| swipe | `boolean` | `true` | Whether to enable gesture swiping |
+
+For more props, refer to [Swiper Documentation](https://swiperjs.com/swiper-api#parameters)
+
+## Reference Examples
+
+### Preset Animation Effects
+
+**cube:**
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+**fade:**
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+**coverflow:**
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+**flip:**
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+**cards:**
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+### Custom Animation Effects
+
+**Example 1:**
+
+
+
+::: details View Code
+
+```md
+
+```
+
+:::
+
+**Example 2:**
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+**Example 3:**
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+**Example 4:**
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+### Carousel
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
+
+### Information Display
+
+
+
+:::details View Code
+
+```md
+
+```
+
+:::
diff --git a/docs/en/guide/custom/component-overrides.md b/docs/en/guide/custom/component-overrides.md
new file mode 100644
index 00000000..b58e6b6d
--- /dev/null
+++ b/docs/en/guide/custom/component-overrides.md
@@ -0,0 +1,46 @@
+---
+title: Component Overrides
+icon: carbon:cics-sit-overrides
+createTime: 2025/10/08 16:20:15
+permalink: /en/guide/component-overrides/
+---
+
+## Overview
+
+Layout slots are quite practical, but sometimes you might find them not flexible enough.
+The theme also provides the capability to override individual components.
+
+::: warning
+Before using this feature, you should first familiarize yourself with this theme's source code
+and understand the various built-in components to safely override them.
+
+The theme's component source code is hosted on
+[GitHub](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/theme/src/client/components) under the MIT license.
+:::
+
+## Usage
+
+The theme registers all non-global components with an
+[alias](https://v2.vuepress.vuejs.org/zh/reference/plugin-api.html#alias) prefixed with `@theme`.
+For example, the alias for `VPFooter.vue` is `@theme/VPFooter.vue`.
+
+If you want to override the `VPFooter.vue` component, you simply need to override this alias in the configuration file `.vuepress/config.ts`:
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default defineUserConfig({
+ theme: plumeTheme(),
+
+ alias: {
+ '@theme/VPFooter.vue': path.resolve(
+ __dirname,
+ './components/MyFooter.vue',
+ ),
+ },
+})
+```
diff --git a/docs/en/guide/custom/home.md b/docs/en/guide/custom/home.md
index 326d871b..bf46d4bf 100644
--- a/docs/en/guide/custom/home.md
+++ b/docs/en/guide/custom/home.md
@@ -1,8 +1,698 @@
---
-title: Customize Homepage
+title: Custom Homepage
icon: material-symbols:home-outline
-createTime: 2025/03/04 12:40:11
+createTime: 2025/10/08 10:44:03
permalink: /en/guide/custom-home/
---
-todo ...
+## Overview
+
+The theme provides a highly flexible approach to customizing the homepage. You can tailor your homepage according to your specific requirements.
+
+The theme defines your homepage through `frontmatter`. Write the `frontmatter` in the `README.md` file located in your `sourceDir`.
+
+```md title="README.md"
+---
+home: true
+config:
+ - type: custom
+---
+```
+
+The theme follows a flow layout approach to render the homepage, dividing it vertically into distinct,
+independent sections, with each section applying a different component.
+
+Multiple sections can be defined via the `config` property using an array structure. The `type` field specifies the type of each section.
+The theme includes built-in types such as `banner`, `hero`, `text-image`, `image-text`, `features`, `profile`, and `custom`.
+You can freely combine these to assemble your custom homepage.
+If none of these meet your needs, you can also write custom components to define your homepage.
+
+## Configuration
+
+### home
+
+- Type: `boolean`
+
+Declares whether this page is the homepage.
+
+### config
+
+- Type: `PlumeHomeConfig[]`
+- Default: `[]`
+
+Defines the section content of the page based on the order of the array.
+
+```ts
+interface PlumeHomeConfigBase {
+ /**
+ * The type of this section, which determines the component applied.
+ */
+ type: 'banner' | 'hero' | 'text-image' | 'image-text' | 'features' | 'profile' | 'custom' | string
+ /**
+ * Whether this section should occupy the full viewport height.
+ */
+ full?: boolean
+ /**
+ * The background image for this section.
+ * You can define different images for light and dark modes.
+ */
+ backgroundImage?: string | { light: string, dark: string }
+ /**
+ * The background attachment style for this section.
+ */
+ backgroundAttachment?: 'fixed' | 'local'
+}
+```
+
+## Section Types
+
+### banner
+
+- Type: `PlumeThemeHomeBanner`
+
+A large banner section, suitable for placement at the very top of the homepage.
+
+```ts
+interface PlumeThemeHomeBanner extends PlumeHomeConfigBase {
+ type: 'banner'
+ /**
+ * The large background banner image.
+ */
+ banner?: string
+ /**
+ * Value range: 0 - 1. Configures the opacity of the mask overlay for the homepage banner image.
+ * Supports different values for light and dark modes. When set to 0, the mask is not displayed.
+ * This can be used to darken the image if the first-screen banner is too bright.
+ */
+ bannerMask?: number | { light?: number, dark?: number }
+
+ hero?: {
+ name: string
+ tagline?: string
+ text?: string
+ actions?: {
+ theme?: 'brand' | 'alt'
+ text: string
+ link?: string
+ }
+ }
+}
+```
+
+**Example:**
+
+```md
+---
+home: true
+config:
+ -
+ type: banner
+ banner: https://api.pengzhanbo.cn/wallpaper/bing
+ bannerMask:
+ light: 0.1
+ dark: 0.3
+ hero:
+ name: Peng Zhanbo
+ tagline: Front End Developer
+ text: Even if slow, stop not, even if failed, keep going, but must be able to reach the goal he aims for.
+ actions:
+ -
+ text: My Blog
+ link: /blog/
+ theme: brand
+ -
+ text: Github
+ link: https://github.com/pengzhanbo
+ theme: alt
+---
+```
+
+**Result:**
+
+:::demo-wrapper img no-padding
+
+
+:::
+
+### hero
+
+- Type: `PlumeThemeHomeHero`
+
+Suitable for documentation-type sites, placed at the top.
+
+**Tool Support: [Homepage Hero Tint Plate Configuration Tool](../../tools/home-hero-tint-plate.md)**
+
+```ts
+interface PlumeThemeHomeHero extends PlumeHomeConfigBase {
+ type: 'hero'
+ hero: {
+ name: string
+ tagline?: string
+ text?: string
+ actions?: {
+ theme?: 'brand' | 'alt' | 'sponsor'
+ text: string
+ link?: string
+ icon?: string // Icon to the left of the text
+ suffixIcon?: string // Icon to the right of the text
+ target?: '_blank' | '_self' | string
+ rel?: string
+ }
+ }
+ /**
+ * Background image. "tint-plate" is a preset effect, or a custom image URL can be provided.
+ */
+ background?: 'tint-plate' | string
+
+ /**
+ * When background is the preset, configure RGB values to adjust the background color.
+ * This configuration only takes effect when `background` is set to `tint-plate`.
+ */
+ tintPlate?: TintPlate
+ /**
+ * If using a non-preset background, set the filter effect for the background image.
+ */
+ filter?: string
+}
+interface TintPlateObj {
+ // value represents the base color value, range 0 ~ 255
+ // offset represents the offset from the base value, range 0 ~ (255 - value)
+ r: { value: number, offset: number }
+ g: { value: number, offset: number }
+ b: { value: number, offset: number }
+}
+type TintPlate
+ = | number // e.g., 210
+ | string // e.g., '210,210,210' => red,green,blue
+ // e.g., { r: { value: 220, offset: 36 }, g: { value: 220, offset: 36 }, b: { value: 220, offset: 36 } }
+ | TintPlateObj
+ // e.g., { light: 210, dark: 20 }
+ // e.g., { light: '210,210,210', dark: '20,20,20' }
+ | { light: number | string, dark: number | string }
+ | { light: TintPlateObj, dark: TintPlateObj }
+```
+
+**Example:**
+
+```md
+---
+home: true
+config:
+ -
+ type: hero
+ full: true
+ background: tint-plate
+ hero:
+ name: Theme Plume
+ tagline: Vuepress Next Theme
+ text: A minimalistic, feature-rich vuepress documentation & blog theme
+ actions:
+ -
+ theme: brand
+ text: Get Started →
+ link: /
+ -
+ theme: alt
+ text: Github
+ link: https://github.com/pengzhanbo/vuepress-theme-plume
+---
+```
+
+**Result:**
+
+:::demo-wrapper img no-padding
+
+:::
+
+When `background` is configured as `tint-plate`, you can additionally configure `tintPlate` to adjust
+the background hue, with a range of `0 ~ 255`:
+
+```md
+---
+home: true
+config:
+ -
+ type: hero
+ full: true
+ background: tint-plate
+ tintPlate: 210
+---
+```
+
+`tintPlate` is used to configure RGB values:
+
+- When configured as a single number, it sets the red, green, and blue color channels to the same value (range: 0 - 255). Example: `210`.
+- When configured as three comma-separated values, it sets the red, green, and blue channels to different values (range: 0 - 255). Example: `210,210,210`.
+- When configured as a `TintPlateObj`, it allows more granular control over each color channel and its corresponding offset.
+- It can also be configured as `{ light, dark }` to use different color values in dark and light modes.
+
+::: info
+To facilitate the configuration of aesthetically pleasing and personalized backgrounds,
+the theme also provides a [Homepage Hero Tint Plate Configuration Tool](../../tools/custom-theme.md)
+for visual configuration. You can generate configuration content and copy it directly for use in your own project.
+:::
+
+The theme also supports customizing the colors of `name`, `tagline`, and `text`.
+
+Configure this via CSS Variables.
+
+```css
+/* Default settings, can be overridden in `index.css` */
+:root {
+ /* home hero name background color. The text color is defined via background clipping,
+ allowing gradient backgrounds for more expressive text. */
+ --vp-bg-home-hero-name: linear-gradient(315deg, var(--vp-c-purple-1) 15%, var(--vp-c-brand-2) 65%, var(--vp-c-brand-2) 100%);
+ --vp-c-home-hero-tagline: var(--vp-c-text-2);
+ --vp-c-home-hero-text: var(--vp-c-text-3);
+}
+```
+
+### doc-hero
+
+- Type: `PlumeThemeHomeDocHero`
+
+Suitable for documentation-type sites, placed at the top.
+
+```ts
+interface PlumeThemeHomeDocHero {
+ type: 'doc-hero'
+ hero: {
+ name: string
+ tagline?: string
+ text?: string
+ image?: string
+ | { src: string, alt?: string }
+ | { dark: string, light: string, alt?: string }
+ actions?: {
+ theme?: 'brand' | 'alt' | 'sponsor'
+ text: string
+ link?: string
+ icon?: string // Icon to the left of the text
+ suffixIcon?: string // Icon to the right of the text
+ target?: '_blank' | '_self' | string
+ rel?: string
+ }
+ }
+}
+```
+
+**Example:**
+
+```md
+---
+home: true
+config:
+ -
+ type: doc-hero
+ hero:
+ name: Theme Plume
+ text: VuePress Next Theme
+ tagline: A minimalistic, easy-to-use, feature-rich vuepress documentation & blog theme
+ image: /plume.png
+ actions:
+ -
+ theme: brand
+ text: Get Started →
+ link: /guide/intro/
+ -
+ theme: alt
+ text: Github
+ link: https://github.com/pengzhanbo/vuepress-theme-plume
+---
+```
+
+**Result:**
+
+:::demo-wrapper img no-padding
+
+:::
+
+The theme also supports customizing the colors of `name`, `tagline`, `text`, and the background color of the `image`.
+
+Configure this via CSS Variables.
+
+```css
+/* Default settings, can be overridden in `index.css` */
+:root {
+ --vp-home-hero-name-color: transparent;
+ --vp-home-hero-name-background: linear-gradient(120deg, var(--vp-c-purple-1) 30%, var(--vp-c-brand-2));
+ --vp-home-hero-tagline: var(--vp-c-text-2);
+ --vp-home-hero-text: var(--vp-c-text-1);
+ --vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-soft) 50%, var(--vp-c-brand-2) 50%);
+ --vp-home-hero-image-filter: blur(44px);
+}
+```
+
+### features
+
+- Type: `PlumeThemeHomeFeatures`
+
+Suitable for displaying features, functionalities, etc.
+
+```ts
+interface PlumeThemeHomeFeatures extends PlumeHomeConfigBase {
+ type: 'features'
+ title?: string
+ description?: string
+ features: PlumeThemeHomeFeature[]
+}
+
+interface PlumeThemeHomeFeature {
+ /**
+ * Icon, also supports passing an iconify icon name.
+ */
+ icon?: FeatureIcon
+ title: string
+ details?: string
+ link?: string
+ linkText?: string
+ rel?: string
+ target?: string
+}
+
+type FeatureIcon = string | {
+ src: string
+ alt?: string
+ width?: string
+ height?: string
+ wrap?: boolean
+} | {
+ light: string
+ dark: string
+ alt?: string
+ width?: string
+ height?: string
+ wrap?: boolean
+}
+```
+
+**Example:**
+
+```md
+---
+home: true
+config:
+ -
+ type: features
+ features:
+ -
+ title: Responsive Layout
+ icon: 💻
+ details: Adapts to mobile devices, PCs, and tablets.
+ -
+ title: Blog & Documentation
+ icon: 📖
+ details: Whether you want to write a blog, product documentation, or both.
+ -
+ title: Out of the Box
+ icon: 🚀
+ details: Supports zero-configuration usage, along with rich customization options.
+ -
+ title: Multi-language
+ icon: ⚖
+ details: Built-in support for Chinese/English, with the ability to add more languages.
+ -
+ title: Dual Theme
+ icon: 👨💻
+ details: Supports light/dark themes, including code highlighting.
+ -
+ title: Plugins
+ icon: 📦
+ details: Rich built-in plugins to handle common website needs in one place.
+ -
+ title: Search, Comments
+ icon: 🔍
+ details: Supports multiple comment systems, local search, and Algolia search.
+ -
+ title: Encryption
+ icon: 🔒
+ details: Supports full-site encryption, partial encryption (encrypted directories, encrypted articles).
+ -
+ title: Markdown Enhancements
+ icon: 📝
+ details: Supports Markdown syntax, code block groups, hint containers, task lists, mathematical formulas, code demos, etc.
+---
+```
+
+**Result:**
+
+:::demo-wrapper img no-padding
+
+:::
+
+### text-image | image-text
+
+- Type: `PlumeThemeHomeTextImage`
+
+Left-right layout for text and image.
+
+```ts
+interface PlumeThemeHomeTextImage extends PlumeHomeConfigBase {
+ type: 'text-image' | 'image-text'
+ image: PlumeThemeImage
+ width?: number | string
+ title?: string
+ description?: string
+ list: (string | { title?: string, description?: string })[]
+}
+
+type PlumeThemeImage
+ = | string
+ | { src: string, alt?: string }
+ | { dark: string, light: string, alt?: string }
+```
+
+**Example:**
+
+```md
+---
+home: true
+config:
+ -
+ type: image-text
+ title: Features
+ description: Rich built-in features to meet general website requirements.
+ image: /images/plume-1.svg
+ list:
+ -
+ title: Article Information
+ description: Add tags, categories, word count, reading time, writing date, and other information to articles.
+ -
+ title: Comments
+ description: Support for 4 comment systems, allowing you to freely choose the one that fits your needs.
+ -
+ title: Search
+ description: Supports minisearch-based local search and Algolia search.
+ -
+ title: Encryption
+ description: Supports full-site encryption and partial encryption (encrypted directories, encrypted articles).
+ -
+ title: Code Copy
+ description: One-click copying of code block content.
+ -
+ type: text-image
+ title: Blog
+ description: The theme natively supports blogging, generating your personal blog.
+ image: /images/plume-2.svg
+ list:
+ -
+ title: Article List
+ description: Automatically sorts and generates blog article list pages based on writing dates.
+ -
+ title: Author Information
+ description: Customize name, motto, avatar, and social media links.
+ -
+ title: Tags, Archive
+ description: Automatically generates tag pages and archives articles by year.
+---
+```
+
+**Result:**
+
+:::demo-wrapper img no-padding
+
+:::
+
+:::demo-wrapper img no-padding
+
+:::
+
+### posts
+
+Inserts a post collection article list page as a separate section into the homepage.
+
+```ts
+interface PlumeThemeHomePosts extends PlumeHomeConfigBase {
+ type: 'posts'
+ collection?: string
+}
+```
+
+When multiple post collections exist, it reads the article list from the first collection by default.
+You can specify which collection's article list to read using the `collection` configuration option.
+
+The value of `collection` should match the `dir` value of the collection.
+
+**Example:**
+
+```md
+---
+home: true
+config:
+ -
+ type: posts
+ collection: blog
+---
+```
+
+### profile
+
+- Type: `PlumeThemeHomeProfile`
+
+Displays personal information.
+
+```ts
+interface PlumeThemeHomeProfile extends PlumeHomeConfigBase {
+ type: 'profile'
+ name?: string
+ description?: string
+ avatar?: PlumeThemeImage
+ circle?: boolean
+}
+
+type PlumeThemeImage
+ = | string
+ | { src: string, alt?: string }
+ | { dark: string, light: string, alt?: string }
+```
+
+**Example:**
+
+```md
+---
+home: true
+config:
+ -
+ type: profile
+ name: pengzhanbo
+ description: Even if slow, stop not, even if failed, keep going, but must be able to reach the goal he aims for.
+ avatar: /images/avatar.png
+---
+```
+
+**Result:**
+
+:::demo-wrapper img no-padding
+
+:::
+
+### custom
+
+- Type: `PlumeThemeHomeCustom`
+
+Custom content. The markdown content written in the `README.md` file will be inserted into the corresponding section.
+
+```ts
+interface PlumeThemeHomeCustom extends PlumeHomeConfigBase {
+ type: 'custom'
+}
+```
+
+**Example:**
+
+````md
+---
+home: true
+config:
+ -
+ type: custom
+---
+
+### Installation
+
+:::code-tabs
+@tab pnpm
+```sh
+pnpm add vuepress@next vuepress-theme-plume vue
+```
+@tab npm
+```sh
+npm install vuepress@next vuepress-theme-plume
+```
+@tab yarn
+```sh
+yarn add vuepress@next vuepress-theme-plume
+```
+:::
+````
+
+**Result:**
+
+:::demo-wrapper img no-padding
+
+:::
+
+## Custom Section Types
+
+When the built-in section types are insufficient for your needs, you can create custom section types.
+
+Each custom section type is essentially a component.
+
+A simple example is as follows:
+
+::: code-tabs
+@tab your-component.vue
+
+```vue
+
+
+
+
+
+ ...
+
+
+```
+
+:::
+
+Add the component in the `enhance` hook within `.vuepress/client.ts`
+::: code-tabs
+@tab .vuepress/client.ts
+
+```ts
+import { defineClientConfig } from 'vuepress/client'
+import YourComponent from 'your-component.vue'
+
+export default defineClientConfig({
+ enhance({ app }) {
+ app.component('your-component', YourComponent)
+ },
+})
+```
+
+:::
+
+Then, you can use `your-component` in your `README.md`.
+
+```md
+---
+home: true
+config:
+ -
+ type: 'your-component'
+ # ...
+---
+```
diff --git a/docs/en/guide/custom/slots.md b/docs/en/guide/custom/slots.md
new file mode 100644
index 00000000..e0ff2741
--- /dev/null
+++ b/docs/en/guide/custom/slots.md
@@ -0,0 +1,179 @@
+---
+title: Layout Slots
+icon: ph:layout-duotone
+createTime: 2025/10/08 16:19:43
+permalink: /en/guide/layout-slots/
+---
+
+## Overview
+
+The theme provides extensive layout slots through ` ` and ` ` components,
+allowing content injection at different positions of the page. This enables users to personalize the theme according to their needs.
+
+## Usage
+
+Taking ` ` as an example, first create a client configuration file: `.vuepress/client.ts`:
+
+```ts title=".vuepress/client.ts"
+import { defineClientConfig } from 'vuepress/client'
+import Layout from './layouts/Layout.vue'
+
+export default defineClientConfig({
+ layouts: {
+ Layout,
+ },
+})
+```
+
+::: info
+The `Layout` name in `layouts` is fixed. This uses JavaScript shorthand syntax,
+essentially equivalent to `Layout: Layout`, which is crucial for implementing layout slots.
+The same rule applies to `NotFound`.
+
+Other components passed that are not `Layout`/`NotFound` are considered custom layout components.
+:::
+
+Then, create `.vuepress/layouts/Layout.vue` as the default component for layout slots,
+and import the current theme's ` ` component in this file.
+
+```vue {7-11} title=".vuepress/layouts/Layout.vue"
+
+
+
+
+
+
+ Custom Content
+
+
+
+
+
+
+```
+
+Content injection can also be implemented using render functions in `.vuepress/client.ts`:
+
+::: code-tabs
+@tab .vuepress/client.ts
+
+```ts
+import { h } from 'vue'
+import { Layout } from 'vuepress-theme-plume/client'
+import { defineClientConfig } from 'vuepress/client'
+import CustomContent from './components/CustomContent.vue'
+
+export default defineClientConfig({
+ layouts: {
+ Layout: () => h(Layout, null, {
+ 'page-bottom': () => h(CustomContent),
+ }),
+ },
+})
+```
+
+@tab .vuepress/components/CustomContent.vue
+
+```vue
+
+
+ Custom Content
+
+
+```
+
+:::
+
+## Slots
+
+::: info
+You can preview to see the positions of all available slots in the site.
+:::
+
+### ` ` Slots
+
+- When `pageLayout: doc`:
+
+ - `doc-top`
+ - `doc-bottom`
+ - `doc-content-before`
+ - `doc-footer-before`
+ - `doc-before`
+ - `doc-after`
+ - `doc-meta-top`
+ - `doc-meta-bottom`
+ - `doc-meta-before`
+ - `doc-meta-after`
+ - `sidebar-nav-before`
+ - `sidebar-nav-after`
+ - `aside-top`
+ - `aside-bottom`
+ - `aside-outline-before`
+ - `aside-outline-after`
+
+- When `pageLayout: page`:
+
+ - `page-top`
+ - `page-bottom`
+
+- In post collection related pages (applicable to post list pages, tags pages, and archives pages):
+
+ - `posts-top`
+ - `posts-bottom`
+ - `posts-aside-top`
+ - `posts-aside-bottom`
+ - `posts-extract-before`
+ - `posts-extract-after`
+
+- In post list pages:
+
+ - `posts-post-list-before`
+ - `posts-post-list-after`
+ - `posts-post-list-pagination-after`
+
+- In tags pages:
+
+ - `posts-tags-before`
+ - `posts-tags-title-after`
+ - `posts-tags-content-before`
+ - `posts-tags-after`
+
+- In archives pages:
+
+ - `posts-archives-before`
+ - `posts-archives-after`
+
+- In categories pages:
+
+ - `posts-categories-before`
+ - `posts-categories-content-before`
+ - `posts-categories-after`
+
+### ` ` Slots
+
+- `not-found`
+
+### Common Slots
+
+The following slots are supported in both ` ` and ` `:
+
+- `layout-top`
+- `layout-bottom`
+- `nav-bar-title-before`
+- `nav-bar-title-after`
+- `nav-bar-content-before`
+- `nav-bar-content-after`
+- `nav-bar-menu-before`
+- `nav-bar-menu-after`
+- `nav-screen-content-before`
+- `nav-screen-content-after`
+- `nav-screen-menu-before`
+- `nav-screen-menu-after`
+- `footer-content`
+- `bulletin-content`
diff --git a/docs/en/guide/custom/style.md b/docs/en/guide/custom/style.md
index e3e1cc05..a2c98226 100644
--- a/docs/en/guide/custom/style.md
+++ b/docs/en/guide/custom/style.md
@@ -1,10 +1,96 @@
---
-title: Customize Style
+title: Custom Styles
icon: icon-park-outline:theme
-createTime: 2025/03/23 14:53:21
+createTime: 2025/10/08 20:18:52
permalink: /en/guide/custom-style/
---
+## Theme Customization
+
+Custom styles are supported.
+
+Although the theme uses [SASS](https://sass-lang.com/) as the CSS preprocessor,
+all colors are defined using `CSS Variables`. Therefore, you can create a CSS file or SCSS file to override them.
+
+First, create a `styles/index.css` file in the `.vuepress` directory. Then, import this file in the [client configuration file](https://v2.vuepress.vuejs.org/guide/configuration.html#client-config-file).
+
+:::code-tabs
+
+@tab .vuepress/client.ts
+
+```ts
+import { defineClientConfig } from 'vuepress/client'
+
+import './styles/index.css' // [!code ++]
+
+export default defineClientConfig({
+ // ...
+})
+```
+
+@tab .vuepress/styles/index.css
+
+```css
+:root {
+ --vp-c-brand-1: #5086a1;
+}
+```
+
+:::
+
## Style File
-The titles are used for external jumps.
-todo ...
+
+Create a file such as `custom.css` in the `.vuepress` directory.
+
+Add additional styles or override default styles here:
+
+```scss
+:root {
+ scroll-behavior: smooth;
+}
+```
+
+You can also use it to override the predefined CSS variables of the default theme.
+
+Below are some predefined variables. For the complete list, please refer to [vars.css](https://github.com/pengzhanbo/vuepress-theme-plume/blob/main/theme/src/client/styles/vars.css).
+
+```scss
+:root {
+ /** Theme Colors */
+ --vp-c-brand-1: #5086a1;
+ --vp-c-brand-2: #6aa1b7;
+ --vp-c-brand-3: #8cccd5;
+ --vp-c-brand-soft: rgba(131, 208, 218, 0.314);
+
+ /** Background Colors */
+ --vp-c-bg: #ffffff;
+ --vp-c-bg-alt: #f6f6f7;
+ --vp-c-bg-elv: #ffffff;
+ --vp-c-bg-soft: #f6f6f7;
+
+ /** Text Colors */
+ --vp-c-text-1: rgba(60, 60, 67);
+ --vp-c-text-2: rgba(60, 60, 67, 0.78);
+ --vp-c-text-3: rgba(60, 60, 67, 0.56);
+}
+
+[data-theme="dark"] {
+ --vp-c-brand-1: #8cccd5;
+ --vp-c-brand-2: #6aa1b7;
+ --vp-c-brand-3: #5086a1;
+ --vp-c-brand-soft: rgba(131, 208, 218, 0.314);
+
+ --vp-c-bg: #1b1b1f;
+ --vp-c-bg-alt: #161618;
+ --vp-c-bg-elv: #202127;
+ --vp-c-bg-soft: #202127;
+
+ --vp-c-text-1: rgba(255, 255, 245, 0.86);
+ --vp-c-text-2: rgba(235, 235, 245, 0.6);
+ --vp-c-text-3: rgba(235, 235, 245, 0.38);
+}
+```
+
+::: tip
+The theme provides a [Theme Color Tool](../../../tools/custom-theme.md) that you can use to create custom colors.
+:::
diff --git a/docs/en/guide/embed/acfun.md b/docs/en/guide/embed/acfun.md
new file mode 100644
index 00000000..5196a03b
--- /dev/null
+++ b/docs/en/guide/embed/acfun.md
@@ -0,0 +1,62 @@
+---
+title: AcFun Video
+icon: lets-icons:video-fill
+createTime: 2025/10/08 10:57:45
+permalink: /en/guide/embed/video/acfun/
+badge: New
+---
+
+## Overview
+
+The theme provides the capability to embed AcFun videos.
+
+This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
+
+## Configuration
+
+This feature is disabled by default. You need to enable it in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ acfun: true, // [!code ++]
+ },
+ })
+})
+```
+
+## Syntax
+
+Simple syntax:
+
+```md
+@[acfun](id)
+```
+
+More options:
+
+```md
+@[acfun width="100%" height="400px" ratio="16:9"](id)
+```
+
+**Parameter Description:**
+
+- id: Video ID
+- width: Video width
+- height: Video height
+- ratio: Video aspect ratio, defaults to `16:9`
+
+## Examples
+
+### Widescreen Video
+
+Input:
+
+```md
+@[acfun](ac47431669)
+```
+
+Output:
+
+@[acfun](ac47431669)
diff --git a/docs/en/guide/embed/artplayer.md b/docs/en/guide/embed/artplayer.md
new file mode 100644
index 00000000..03e85c93
--- /dev/null
+++ b/docs/en/guide/embed/artplayer.md
@@ -0,0 +1,164 @@
+---
+title: ArtPlayer Video
+icon: icon-park-outline:video
+createTime: 2025/10/08 16:13:54
+permalink: /en/guide/embed/video/artplayer/
+---
+
+## Overview
+
+The theme provides the capability to embed custom source videos.
+
+This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
+
+## Configuration
+
+This feature is disabled by default. You need to enable it in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ artPlayer: true, // [!code ++]
+ },
+ })
+})
+```
+
+## Installation
+
+This feature relies on the `artplayer` player implementation. The theme does not include this dependency
+by default. When enabling the `artPlayer` feature, manual installation is required.
+
+::: npm-to
+
+```sh
+npm i artplayer
+```
+
+:::
+
+The artPlayer player natively supports video formats including `'mp4'`, `'mp3'`, `'webm'`, and `'ogg'`.
+
+It also supports extending compatibility for additional formats.
+
+If your video format is `'mpd'` or `'dash'`, you need to manually install `dashjs`:
+
+::: npm-to
+
+```sh
+npm i dashjs
+```
+
+:::
+
+If your video format is `'m3u8'` or `'hls'`, you need to manually install `hls.js`:
+
+::: npm-to
+
+```sh
+npm i hls.js
+```
+
+:::
+
+If your video format is `'ts'` or `'flv'`, you need to manually install `mpegts.js`:
+
+::: npm-to
+
+```sh
+npm i mpegts.js
+```
+
+:::
+
+## Markdown Syntax
+
+```md
+@[artPlayer](src)
+```
+
+With configuration options:
+
+```md
+@[artPlayer muted autoplay loop width="100%" height="400px" ratio="16:9"](src)
+```
+
+- `src`: Video source URL
+
+**Parameter Description:**
+
+- `width`: Video width
+- `height`: Video height
+- `ratio`: Video aspect ratio, defaults to `16:9`
+- `type`: Video format, automatically parsed from the video URL by default
+- `autoplay`: Whether to enable autoplay
+- `muted`: Whether to mute, defaults to `true` when autoplay is enabled
+- `volume`: Volume level, range from `0 - 1`
+- `poster`: Video poster image URL
+- `auto-mini`: Automatically enters mini-player mode when the player scrolls out of the browser viewport
+
+## Global Component
+
+The theme provides a global component ` ` to support more flexible and comprehensive usage.
+
+### Props
+
+| Field | Type | Description |
+| -- | -- | -- |
+| src | `string` | Required, video source URL |
+| type | `string` | Optional, video format, parsed from `src` by default |
+| width | `string` | Optional, width, defaults to `100%` |
+| height | `string` | Optional, height |
+| ratio | `string` | Optional, aspect ratio, defaults to `16:9` |
+
+For more `Props`, please refer to the
+[artPlayer documentation](https://artplayer.org/document/start/option.html). The theme supports all available options.
+
+## Examples
+
+::: tip Note
+The video resources in the examples are sourced from [artplayer.org](https://artplayer.org).
+:::
+
+**Input:**
+
+```md
+@[artPlayer](https://artplayer.org/assets/sample/video.mp4)
+```
+
+**Output:**
+
+@[artPlayer](https://artplayer.org/assets/sample/video.mp4)
+
+**Input:**
+
+```md
+
+```
+
+**Output:**
+
+
+
+## Explanation
+
+The markdown syntax `@[artPlayer](src)` is internally converted to the ` ` component, which is equivalent to:
+
+```md
+
+```
diff --git a/docs/en/guide/embed/audioReader.md b/docs/en/guide/embed/audioReader.md
new file mode 100644
index 00000000..8797d335
--- /dev/null
+++ b/docs/en/guide/embed/audioReader.md
@@ -0,0 +1,103 @@
+---
+title: Audio Reader
+icon: rivet-icons:audio
+createTime: 2025/10/08 22:31:01
+permalink: /en/guide/embed/audio/reader/
+---
+
+## Overview
+
+The theme supports embedding audio reading capabilities in documentation.
+
+This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
+
+**Audio Reader** is not a music player; it simply embeds an
+(@[audioReader](https://sensearch.baidu.com/gettts?lan=en&spd=3&source=alading&text=audio))
+button within content that plays an audio clip when clicked.
+
+It is suitable for playing short audio clips, such as **word pronunciation guides**.
+
+## Configuration
+
+This feature is disabled by default. You need to enable it in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ audioReader: true, // [!code ++]
+ },
+ })
+})
+```
+
+## Markdown Syntax
+
+The audio embedding markdown syntax is an inline syntax, allowing usage anywhere within markdown.
+
+```md
+@[audioReader](src)
+```
+
+With configuration options:
+
+```md
+@[audioReader type="audio/mpeg" title="title" autoplay start-time="0" end-time="10" volume="0.7"](src)
+```
+
+**Parameter Description:**
+
+- `type`: Audio type, formatted as `audio/mpeg`.
+ Defaults to inference from the file extension in the audio URL. If the URL lacks an extension, declare manually.
+- `title`: Audio title, displayed before the audio icon.
+- `autoplay`: Whether to enable autoplay (not recommended).
+- `start-time`: Audio playback start time in seconds.
+- `end-time`: Audio playback end time in seconds.
+- `volume`: Audio playback volume, range from `0 ~ 1`.
+
+## Global Component
+
+The theme provides a global component ` ` to support more flexible and comprehensive usage.
+
+### Props
+
+| Field | Type | Description |
+| --------- | --------- | ----------------------------------- |
+| src | `string` | Required, audio source URL |
+| type | `string` | Optional, audio format, parsed from `src` by default |
+| autoplay | `boolean` | Optional, whether to enable autoplay (not recommended) |
+| startTime | `number` | Optional, audio playback start time in seconds |
+| endTime | `number` | Optional, audio playback end time in seconds |
+| volume | `number` | Optional, audio playback volume, range from `0 ~ 1` |
+
+## Examples
+
+**Input:**
+
+```md
+audio 美 [ˈɔːdioʊ] @[audioReader](/audio/audio.mp3)
+```
+
+**Output:**
+
+audio 美 [ˈɔːdioʊ] @[audioReader](https://sensearch.baidu.com/gettts?lan=en&spd=3&source=alading&text=audio)
+
+**Input:**
+
+```md
+audio 美 @[audioReader title="[ˈɔːdioʊ]"](/audio/audio.mp3)
+```
+
+**Output:**
+
+audio 美 @[audioReader title="[ˈɔːdioʊ]"](https://sensearch.baidu.com/gettts?lan=en&spd=3&source=alading&text=audio)
+
+**Input:**
+
+```md
+audio 美 [ˈɔːdioʊ]
+```
+
+**Output:**
+
+audio 美 [ˈɔːdioʊ]
diff --git a/docs/en/guide/embed/bilibili.md b/docs/en/guide/embed/bilibili.md
new file mode 100644
index 00000000..441577f7
--- /dev/null
+++ b/docs/en/guide/embed/bilibili.md
@@ -0,0 +1,85 @@
+---
+title: Bilibili Video
+icon: ri:bilibili-fill
+createTime: 2025/10/08 12:26:47
+permalink: /en/guide/embed/video/bilibili/
+---
+
+## Overview
+
+The theme provides the capability to embed Bilibili videos.
+
+This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdownPower.md).
+
+## Configuration
+
+This feature is disabled by default. You need to enable it in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ bilibili: true, // [!code ++]
+ },
+ })
+})
+```
+
+## Syntax
+
+Simple syntax:
+
+```md
+@[bilibili](bvid)
+```
+
+For videos with multiple parts, add `p1`, `p2`, `p3` etc. after `bilibili`:
+
+```md
+@[bilibili p1](aid cid)
+```
+
+More options:
+
+```md
+@[bilibili p1 autoplay time="0" width="100%" height="400px" ratio="16:9"](bvid aid cid)
+```
+
+**Parameter Description:**
+
+- bvid: Video BV ID
+- aid: Video AID
+- cid: Video CID
+- autoplay: Whether to enable autoplay
+- time: Video playback start time in seconds, or in `mm:ss` or `hh:mm:ss` format
+- width: Video width
+- height: Video height
+- ratio: Video aspect ratio, defaults to `16:9`
+
+For videos with multiple parts, `bvid` can be omitted, but `aid` and `cid` must be provided.
+
+## Examples
+
+### Widescreen Video
+
+Input:
+
+```md
+@[bilibili](BV1EZ42187Hg)
+```
+
+Output:
+
+@[bilibili](BV1EZ42187Hg)
+
+### Vertical Video
+
+Input:
+
+```md
+@[bilibili width="320px" ratio="9:16"](BV1zr42187eg)
+```
+
+Output:
+
+@[bilibili width="320px" ratio="9:16"](BV1zr42187eg)
diff --git a/docs/en/guide/embed/pdf.md b/docs/en/guide/embed/pdf.md
new file mode 100644
index 00000000..8493898a
--- /dev/null
+++ b/docs/en/guide/embed/pdf.md
@@ -0,0 +1,114 @@
+---
+title: PDF Reader
+icon: teenyicons:pdf-outline
+createTime: 2025/10/08 13:30:53
+permalink: /en/guide/embed/pdf/
+---
+
+## Overview
+
+The theme supports embedding PDF files in markdown, enabling direct PDF reading within the page.
+
+This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
+
+## Configuration
+
+This feature is disabled by default. You need to enable it in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ pdf: true, // [!code ++]
+ },
+ })
+})
+```
+
+## Syntax
+
+The simplest syntax is as follows:
+
+```md
+@[pdf](url)
+```
+
+To open a specific page, add a page number after `pdf`:
+
+```md
+@[pdf 2](url)
+```
+
+Additional options can be added to `@[pdf ]` for more flexible control:
+
+```md
+@[pdf 2 no-toolbar width="100%" height="400px" ratio="16:9" zoom="100"](url)
+```
+
+- `no-toolbar` - Hide the toolbar
+- `width` - Width, defaults to 100%
+- `height` - Height, defaults to `auto`
+- `ratio` - Aspect ratio, defaults to `16:9`, only effective when height is not specified
+- `zoom` - Zoom level, percentage
+
+## Examples
+
+### Default
+
+Input:
+
+```md
+@[pdf](https://plume.pengzhanbo.cn/files/sample.pdf)
+```
+
+Output:
+
+@[pdf](/files/sample.pdf)
+
+### Set Page Number to 2
+
+Input:
+
+```md
+@[pdf 2](https://plume.pengzhanbo.cn/files/sample.pdf)
+```
+
+Output:
+
+@[pdf 2 zoom="95"](/files/sample.pdf)
+
+### Hide Toolbar
+
+Input:
+
+```md
+@[pdf no-toolbar](https://plume.pengzhanbo.cn/files/sample.pdf)
+```
+
+Output:
+
+@[pdf no-toolbar](/files/sample.pdf)
+
+### 90% Zoom Level
+
+Input:
+
+```md
+@[pdf zoom="90"](https://plume.pengzhanbo.cn/files/sample.pdf)
+```
+
+Output:
+
+@[pdf zoom="90"](/files/sample.pdf)
+
+### 21:29 Aspect Ratio
+
+Input:
+
+```md
+@[pdf zoom="95" ratio="21:29"](https://plume.pengzhanbo.cn/files/sample.pdf)
+```
+
+Output:
+
+@[pdf zoom="95" ratio="21:29"](/files/sample.pdf)
diff --git a/docs/en/guide/embed/youtube.md b/docs/en/guide/embed/youtube.md
new file mode 100644
index 00000000..db0c1f2b
--- /dev/null
+++ b/docs/en/guide/embed/youtube.md
@@ -0,0 +1,65 @@
+---
+title: YouTube Video
+icon: mdi:youtube
+createTime: 2025/10/08 14:30:33
+permalink: /en/guide/embed/video/youtube/
+---
+
+## Overview
+
+The theme provides the capability to embed YouTube videos.
+
+This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
+
+## Configuration
+
+This feature is disabled by default. You need to enable it in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ youtube: true, // [!code ++]
+ },
+ })
+})
+```
+
+## Syntax
+
+Simple syntax:
+
+```md
+@[youtube](id)
+```
+
+More options:
+
+```md
+@[youtube autoplay loop start="0" end="0" width="100%" height="400px" ratio="16:9"](id)
+```
+
+**Parameter Description:**
+
+- id: Video ID
+- autoplay: Whether to enable autoplay
+- loop: Whether to enable loop playback
+- start: Video playback start time in seconds, or in `mm:ss` or `hh:mm:ss` format
+- end: Video playback end time in seconds, or in `mm:ss` or `hh:mm:ss` format
+- width: Video width
+- height: Video height
+- ratio: Video aspect ratio, defaults to `16:9`
+
+## Examples
+
+### Widescreen Video
+
+Input:
+
+```md
+@[youtube](0JJPfz5dg20)
+```
+
+Output:
+
+@[youtube](0JJPfz5dg20)
diff --git a/docs/en/guide/features/bulletin.md b/docs/en/guide/features/bulletin.md
new file mode 100644
index 00000000..5d5cbaaf
--- /dev/null
+++ b/docs/en/guide/features/bulletin.md
@@ -0,0 +1,391 @@
+---
+title: Bulletin
+icon: mingcute:announcement-line
+createTime: 2025/10/08 21:51:22
+permalink: /en/guide/features/bulletin/
+---
+
+## Overview
+
+The bulletin is a real-time notification component that enables convenient display of notification messages within the site.
+
+Such as the bulletin in the top-right corner.
+
+## Usage
+
+The theme provides very convenient and flexible methods for using the bulletin.
+You can choose the appropriate configuration method based on your requirements.
+
+### Configuration Options
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ bulletin: {
+ // more options...
+ }
+ })
+})
+```
+
+```ts
+interface BulletinOptions {
+ /**
+ * Bulletin position
+ * @default 'top-right'
+ */
+ layout?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center'
+
+ /**
+ * Whether to display gradient border
+ *
+ * @default true
+ */
+ border?: boolean
+
+ /**
+ * Pages where the bulletin is displayed
+ *
+ * - `true` indicates all pages
+ * - `false` indicates no display
+ * - Pass a function that returns `true` when display is enabled
+ */
+ enablePage?: boolean | ((page: Page) => boolean)
+
+ /**
+ * Bulletin display duration
+ *
+ * @default 'always'
+ *
+ * - `'session'`: After closing the bulletin, it won't display again during the current session cycle. It will reappear in new session cycles. Refreshing the page won't make it reappear.
+ * - `'always'`: Always display. After closing, refreshing the page will make it reappear.
+ * - `'once'`: Display only in the current cycle. After closing, it won't display again. Neither new sessions nor page refreshes will make it reappear.
+ */
+ lifetime?: 'session' | 'always' | 'once'
+
+ /**
+ * Bulletin ID
+ *
+ * The bulletin display duration uses the `id` as a unique identifier
+ */
+ id?: string
+
+ /**
+ * Bulletin title
+ */
+ title?: string
+
+ /**
+ * Bulletin content
+ *
+ * Markdown syntax or HTML text can be used.
+ * When using markdown, declare `contentType` as `markdown`
+ */
+ content?: string
+
+ /**
+ * Bulletin content type
+ *
+ * - `markdown` indicates using markdown syntax
+ * - `text` indicates using plain text (can be HTML content)
+ *
+ * @default 'text'
+ */
+ contentType?: 'markdown' | 'text'
+
+ /**
+ * Pass a `markdown` or `html` file path and use the file content as bulletin content
+ *
+ * - When using `.md` files, markdown syntax will be parsed
+ * - When using `.html` files, only include bulletin content. Please avoid using tags like ``, ``, `
+
+
+
+
+
+
+
+
+```
+
+## Custom Bulletin Styles
+
+You can directly override the bulletin styles via CSS.
+
+Modify the following CSS variables to easily control the bulletin styles.
+
+```css
+:root {
+ --vp-bulletin-bg-color: var(--vp-c-bg);
+ --vp-bulletin-text-color: var(--vp-c-text-1);
+ --vp-bulletin-title-color: var(--vp-c-text-1);
+ --vp-bulletin-font-size: 16px;
+ --vp-bulletin-title-font-size: 18px;
+ --vp-bulletin-line-height: 24px;
+ --vp-bulletin-border-width: 2px;
+ --vp-bulletin-border: conic-gradient(var(--vp-c-important-3), var(--vp-c-danger-3), var(--vp-c-success-3), var(--vp-c-important-3));
+ --vp-bulletin-width: 320px;
+}
+```
+
+Alternatively, override the bulletin styles globally via the `.vp-bulletin` class.
+
+```css
+.vp-bulletin {
+ /* Bulletin styles */
+}
+```
+
+## Fully Custom Bulletin
+
+When you don't want to use the theme's built-in bulletin at all, you can completely customize the
+bulletin by registering a global `Bulletin` component.
+
+::: code-tabs
+@tab .vuepress/client.ts
+
+```ts
+import { defineClientConfig } from '@vuepress/client'
+import Bulletin from './components/Bulletin.vue'
+
+export default defineClientConfig({
+ enhance: ({ app }) => {
+ app.component('Bulletin', Bulletin)
+ }
+})
+```
+
+:::
+
+Next, write the `Bulletin.vue` component.
+
+::: code-tabs
+@tab .vuepress/components/Bulletin.vue
+
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+:::
+
+You need to write the bulletin component from scratch. To facilitate writing the bulletin, the theme
+provides the composable API `useBulletinControl()`, which you can use directly in the `Bulletin.vue` component.
+
+```ts
+import { useBulletinControl } from 'vuepress-theme-plume/composables'
+
+const {
+ bulletin, // Bulletin configuration, read from theme configuration
+ showBulletin, // Whether to show the bulletin
+ enableBulletin, // Whether the bulletin is enabled on the current page
+ close, // Close the bulletin
+} = useBulletinControl()
+```
+
+## Related Notes
+
+### Bulletin Unique Identifier
+
+The bulletin's unique identifier is configured via `bulletin.id`.
+
+The unique identifier is used to distinguish bulletins and determine the validity period of `bulletin.lifetime` based on this identifier.
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ bulletin: {
+ layout: 'top-right',
+ title: 'Bulletin Title',
+ id: 'my-bulletin', // [!code hl]
+ }
+ })
+})
+```
+
+When you don't explicitly configure `bulletin.id`, the theme generates a hash value based on the `bulletin` object as the unique identifier.
+
+### Bulletin Display Duration
+
+The bulletin display duration is configured via `bulletin.lifetime`.
+
+- `session`: During the current session cycle, if the user doesn't close the bulletin,
+it will continue to display, including into the next session cycle. When the user closes the bulletin,
+it is considered expired and won't display again during the current session cycle, but will reappear in the next session cycle.
+
+- `always`: Even if the user closes the bulletin, it will reappear not only in the next session cycle but also when refreshing the page.
+
+- `once`: Once the bulletin is closed during the current session cycle, it won't display again afterward.
+
+::: details What is a session?
+**Session** refers to the period when you visit a site. As long as the browser tab where the site is
+located remains open, the site maintains the same session, even if the page is refreshed.
+:::
+
+### Bulletin Position
+
+The bulletin position is configured via `bulletin.layout`.
+
+- `top-left`: Top left
+- `top-right`: Top right
+- `bottom-left`: Bottom left
+- `bottom-right`: Bottom right
+- `center`: Top center
+
+### Pages Where Bulletin is Displayed
+
+The pages where the bulletin is displayed are configured via `bulletin.enablePage`.
+
+- `true` indicates all pages
+- `false` indicates no display
+- Pass a function that returns `true` when display is enabled
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ bulletin: {
+ layout: 'top-right',
+ title: 'Bulletin Title',
+ enablePage: (page) => {
+ return page.path === '/custom-path/'
+ }
+ }
+ })
+})
+```
diff --git a/docs/en/guide/features/changelog.md b/docs/en/guide/features/changelog.md
new file mode 100644
index 00000000..16462738
--- /dev/null
+++ b/docs/en/guide/features/changelog.md
@@ -0,0 +1,160 @@
+---
+title: Changelog
+icon: radix-icons:activity-log
+createTime: 2025/10/08 18:16:25
+permalink: /en/guide/features/changelog/
+---
+
+## Overview
+
+The theme supports adding article changelogs to better track the modification history of your articles.
+
+Article changelogs are obtained through git commit history.
+
+This feature is powered by [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html).
+
+::: warning Note
+This feature relies on the `git log` command to retrieve commit history for each markdown file,
+which can be relatively time-consuming, especially for large projects with extensive commit histories.
+Therefore, this feature is not enabled in development environments by default and is only enabled in production environments.
+
+However, you can still enable it in development environments by setting `theme.plugins.git` to `true` for testing purposes.
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: { git: true }
+ })
+})
+```
+
+:::
+
+## Usage
+
+The theme has built-in support for the
+[@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) plugin, so you can use it without reinstalling.
+
+Enable this feature in the theme configuration file:
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ // Disabled by default, only takes effect when plugins.git is true
+ // This configuration is invalid in plume.config.ts
+ changelog: true,
+
+ plugins: {
+ // If you declare it directly as true here, it means the feature is enabled in both development and production environments
+ git: process.env.NODE_ENV === 'production'
+ }
+ })
+})
+```
+
+## Configuration
+
+```ts
+interface ChangelogOptions {
+ /**
+ * Maximum number of change records, defaults to all records
+ */
+ maxCount?: number
+ /**
+ * Git repository URL, e.g., https://github.com/vuepress/ecosystem
+ */
+ repoUrl?: string
+ /**
+ * Commit URL pattern
+ *
+ * - `:repo` - Git repository URL
+ * - `:hash` - Commit hash
+ *
+ * @default ':repo/commit/:hash'
+ */
+ commitUrlPattern?: string
+ /**
+ * Issue URL pattern
+ *
+ * - `:repo` - Git repository URL
+ * - `:issue` - Issue ID
+ *
+ * @default ':repo/issues/:issue'
+ */
+ issueUrlPattern?: string
+ /**
+ * Tag URL pattern
+ * Default: ':repo/releases/tag/:tag'
+ *
+ * - `:repo` - Git repository URL
+ * - `:tag` - Tag name
+ *
+ * @default ':repo/releases/tag/:tag'
+ */
+ tagUrlPattern?: string
+}
+```
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ changelog: {
+ maxCount: 10,
+ repoUrl: 'https://github.com/vuepress/vuepress',
+ commitUrlPattern: ':repo/commit/:hash',
+ issueUrlPattern: ':repo/issues/:issue',
+ tagUrlPattern: ':repo/releases/tag/:tag'
+ },
+
+ })
+})
+```
+
+::: warning Note
+Ensure that `changelog.repoUrl` is correctly configured. The default value is [docsRepo](../../config/theme.md#docsrepo).
+
+The theme by default adapts to the URL patterns of git hosting services like `GitHub`, `GitLab`, `Gitee`, and `Bitbucket`.
+If you're using a self-hosted service or others, please configure `commitUrlPattern`, `issueUrlPattern`, and `tagUrlPattern` accordingly.
+:::
+
+## Notes
+
+This feature requires your project to be under a
+[Git repository](https://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository) so it can collect information from the commit history.
+
+**When building your site, you should ensure all commit records are accessible.**
+
+For example, CI workflows typically add the `--depth 1` parameter when cloning your repository to avoid
+fetching all commit history. Therefore, you need to disable this feature so the plugin can work properly in CI.
+
+Services like `GitHub Actions`, `Netlify`, and `Vercel` do not fetch all commit history by default.
+
+In `GitHub Actions`, you can add the `--depth 0` parameter to ensure `GitHub Actions` can correctly fetch all commit records.
+
+``` yaml title=".github/workflows/deploy.yml"
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4 # [!code focus:3]
+ with: # [!code ++:2]
+ fetch-depth: 0
+```
+
+For services like `Netlify` and `Vercel`, the processing method is relatively more complex.
+In such cases, you can first complete the build in `GitHub Actions` and output the artifacts to
+a separate branch, then use that branch for deployment in `Netlify` or `Vercel`.
+
+::: info
+For projects created via the theme's `cli` tool, when selecting the deployment method as `GitHub Action`,
+the build artifacts are output to the `gh_pages` branch. You can base your `Netlify` or `Vercel` deployment on this branch.
+:::
diff --git a/docs/en/guide/features/comments.md b/docs/en/guide/features/comments.md
new file mode 100644
index 00000000..2c295c01
--- /dev/null
+++ b/docs/en/guide/features/comments.md
@@ -0,0 +1,262 @@
+---
+title: Comments
+icon: la:comment
+createTime: 2025/10/08 11:58:59
+permalink: /en/guide/features/comments/
+---
+
+## Overview
+
+Article comments are powered by [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/).
+
+The theme has built-in plugin support, so you can use it without reinstalling.
+
+In this theme, configure through the following fields:
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ comment: {
+ // Service provider
+ provider: '', // "Artalk" | "Giscus" | "Twikoo" | "Waline"
+ // Whether comments are enabled by default
+ comment: true,
+
+ // Other configurations based on the service provider
+ // ...
+ }
+ })
+})
+```
+
+### Service Providers
+
+[@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/) supports various
+comment service providers such as `"Artalk" | "Giscus" | "Twikoo" | "Waline"`.
+
+You can configure based on your requirements.
+
+- `Giscus` is a comment system based on GitHub Discussions, easy to set up. [View documentation](https://ecosystem.vuejs.press/zh/plugins/blog/comment/giscus/)
+- `Waline` is a comment system that requires a backend, offering higher security. [View documentation](https://ecosystem.vuejs.press/zh/plugins/blog/comment/waline/)
+- `Twikoo` is a concise, secure, free static website comment system based on Tencent Cloud Base. [View documentation](https://ecosystem.vuejs.press/zh/plugins/blog/comment/twikoo/)
+- `Artalk` is a concise self-hosted comment system that you can easily deploy on your server and embed in frontend pages. [View documentation](https://ecosystem.vuejs.press/zh/plugins/blog/comment/artalk/)
+
+::: tip Recommended Comment Services
+
+- For programmers and developers: Giscus
+- For the general public: Waline
+:::
+
+::: note
+Examples are forked from [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/),
+following the [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) license.
+:::
+
+## Giscus
+
+Giscus is a comment system based on GitHub Discussions, easy to set up.
+
+### Prerequisites
+
+::: steps
+
+1. You need to create a public repository and enable Discussions to serve as the location for storing comments.
+
+2. You need to install the [Giscus App](https://github.com/apps/giscus) to grant it permission to access the corresponding repository.
+
+3. After completing the above steps, go to the [Giscus page](https://giscus.app/zh-CN) to get your settings.
+
+ You only need to fill in the repository and Discussion category, then scroll to the "Enable giscus" section
+ at the bottom of the page to obtain the four attributes: `data-repo`, `data-repo-id`, `data-category`, and `data-category-id`.
+
+:::
+
+### Configuration
+
+Set `provider: 'Giscus'` and pass `data-repo`, `data-repo-id`, `data-category`, and `data-category-id` as
+plugin options to `repo`, `repoId`, `category`, and `categoryId`.
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ comment: {
+ provider: 'Giscus', // "Artalk" | "Giscus" | "Twikoo" | "Waline"
+ comment: true,
+ repo: 'Your_Repo', // [!code ++]
+ repoId: 'Your_RepoId', // [!code ++]
+ category: 'Your_Category', // [!code ++]
+ categoryId: 'Your_CategoryId', // [!code ++]
+ }
+ })
+})
+```
+
+### Themes
+
+By default, Giscus uses `light` or `dark` themes (based on the dark mode state).
+
+If you want to customize themes for light and dark modes, you can set the `lightTheme` and `darkTheme` options
+using built-in theme keywords or custom CSS links starting with `https://`.
+
+## Waline
+
+A secure comment system with a backend.
+
+### Installation
+
+If you want to use Waline in the theme, you need to install `@waline/client` first.
+
+::: npm-to
+
+```sh
+npm i @waline/client
+```
+
+:::
+
+### LeanCloud Setup (Database)
+
+::: steps
+
+1. [Login](https://console.leancloud.app/login) or [Register](https://console.leancloud.app/register) for
+ `LeanCloud International` and enter the [Console](https://console.leancloud.app/apps)
+
+2. Click [Create Application](https://console.leancloud.app/apps) in the upper left corner and choose a name
+ you like (please select the free development plan):
+
+ 
+
+3. Enter the application, select `Settings` > `Application Keys` in the lower left corner.
+ You can see your `APP ID`, `APP Key`, and `Master Key`. Please record them for later use.
+
+ 
+
+:::
+
+::: warning Domestic version requires ICP filing
+
+If you are using the LeanCloud domestic version ([leancloud.cn](https://leancloud.cn)), we recommend
+switching to the international version ([leancloud.app](https://leancloud.app)).
+Otherwise, you need to bind an **already ICP-filed** domain to the application, purchase an independent IP, and complete the ICP filing process:
+
+- Log in to the domestic version and enter the application you need to use
+- Select `Settings` > `Domain Binding` > `API Access Domain` > `Bind New Domain` > Enter domain > `OK`.
+- Follow the instructions on the page to complete the CNAME resolution in DNS as required.
+- Purchase an independent IP and submit a work order to complete the ICP filing. (The current price for an independent IP is ¥50/month)
+
+
+
+:::
+
+### Vercel Deployment (Server)
+
+[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwalinejs%2Fwaline%2Ftree%2Fmain%2Fexample)
+
+:::: steps
+
+1. Click the button above to jump to Vercel for server-side deployment.
+
+ ::: note
+
+ If you are not logged in, Vercel will prompt you to register or log in. Please use your GitHub account for quick login.
+
+ :::
+
+2. Enter a Vercel project name you like and click `Create` to continue:
+
+ 
+
+3. At this point, Vercel will help you create and initialize a repository based on the Waline template,
+with the repository name being the project name you entered earlier.
+
+ 
+
+ After a minute or two, a full screen of fireworks will celebrate your successful deployment.
+ Click `Go to Dashboard` to jump to the application's console.
+
+ 
+
+4. Click `Settings` at the top - `Environment Variables` to enter the environment variable configuration page,
+ and configure the three environment variables `LEAN_ID`, `LEAN_KEY`, and `LEAN_MASTER_KEY`.
+ Their values correspond to the `APP ID`, `APP KEY`, and `Master Key` obtained from LeanCloud in the previous step, respectively.
+
+ 
+
+ ::: note
+
+ If you are using the LeanCloud domestic version, please additionally configure the `LEAN_SERVER`
+ environment variable with the value of your bound domain.
+
+ :::
+
+5. After configuring the environment variables, click `Deployments` at the top,
+ then click the `Redeploy` button on the right side of the latest deployment to redeploy.
+ This step is to make the environment variables you just set take effect.
+
+ 
+
+6. At this point, it will jump to the `Overview` interface to start deployment.
+ Wait a moment until the `STATUS` becomes `Ready`. Then click `Visit` to jump to the deployed
+ website address, which is your server address.
+
+ 
+
+::::
+
+### Domain Binding (Optional)
+
+::: steps
+
+1. Click `Settings` - `Domains` at the top to enter the domain configuration page.
+
+2. Enter the domain you want to bind and click `Add`.
+
+ 
+
+3. Add a new `CNAME` record at your domain DNS provider.
+
+ | Type | Name | Value |
+ | ----- | ------- | -------------------- |
+ | CNAME | example | cname.vercel-dns.com |
+
+4. Wait for it to take effect. You can now access it via your own domain :tada:
+
+ - Comment system: example.your-domain.com
+ - Comment management: example.your-domain.com/ui
+
+ 
+
+:::
+
+### Client
+
+#### Using the Plugin
+
+Set `provider: "Waline"` in the plugin options, and set the server address `serverURL` to the value obtained in the previous step.
+
+At this point, place the `` component in a suitable location on your website
+(usually at the bottom of the page) to use the Waline comment functionality.
+
+::: tip
+
+You can also pass other options supported by Waline (except `el`). For details, see [Waline Configuration](https://ecosystem.vuejs.press/zh/plugins/blog/comment/waline/config.html).
+
+:::
+
+### Comment Management (Admin Panel)
+
+::: steps
+
+1. After deployment is complete, please visit `/ui/register` to register. The first person to register will be set as the administrator.
+
+2. After logging in as an administrator, you can see the comment management interface. Here you can modify, mark, or delete comments.
+
+3. Users can also register accounts through the comment box. After logging in, they will be redirected to their own profile page.
+
+:::
diff --git a/docs/en/guide/features/component.md b/docs/en/guide/features/component.md
deleted file mode 100644
index 9326b394..00000000
--- a/docs/en/guide/features/component.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-title: Component
-icon: radix-icons:component-2
-createTime: 2025/03/24 19:52:21
-outline: 2
-permalink: /en/guide/features/component/
----
-
-The original content of this document has been migrated to Component .
diff --git a/docs/en/guide/features/contributors.md b/docs/en/guide/features/contributors.md
new file mode 100644
index 00000000..45e6ed53
--- /dev/null
+++ b/docs/en/guide/features/contributors.md
@@ -0,0 +1,329 @@
+---
+title: Contributors
+icon: simple-icons:contributorcovenant
+createTime: 2025/10/08 16:26:54
+permalink: /en/guide/features/contributors/
+---
+
+## Overview
+
+The theme supports adding contributor information to articles to better track your article contributors.
+
+Article contributors are obtained through git commit history.
+
+This feature is powered by [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html).
+
+::: warning Note
+This feature relies on the `git log` command to retrieve commit history for each markdown file,
+which can be relatively time-consuming, especially for large projects with extensive commit histories.
+Therefore, this feature is not enabled in development environments by default and is only enabled in production environments.
+
+However, you can still enable it in development environments by setting `theme.plugins.git` to `true` for testing purposes.
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: { git: true }
+ })
+})
+```
+
+:::
+
+## Usage
+
+The theme has built-in support for the
+[@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) plugin, so you can use it without reinstalling.
+
+Enable this feature in the theme configuration file:
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ // Enabled by default, only takes effect when plugins.git is true
+ // This configuration is invalid in plume.config.ts
+ contributors: true,
+
+ plugins: {
+ // If you declare it directly as true here, it means the feature is enabled in both development and production environments
+ git: process.env.NODE_ENV === 'production'
+ }
+ })
+})
+```
+
+## Configuration
+
+### mode
+
+- Type: `'inline' | 'block'`
+- Default: `'inline'`
+- Description:
+
+ - `inline`: Display contributor information at the bottom of the article page,
+ alongside the last updated time. In this mode, only contributor names are displayed.
+
+ 
+
+ - `block`: Insert contributor information at the end of the article content. This mode includes contributor names, links, and avatars.
+ (As shown at the end of the current page's content)
+
+ In `block` mode, avatars are displayed by default for all contributors,
+ even if you haven't provided an avatar URL.
+ The plugin will generate avatar URLs from `https://gravatar.com/` based on email addresses or usernames.
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ contributors: {
+ mode: 'block',
+ },
+ })
+})
+```
+
+### info
+
+- Type: `ContributorInfo[]`
+
+ ```ts
+ interface ContributorInfo {
+ /**
+ * Contributor's username on Git hosting service
+ */
+ username: string
+ /**
+ * Name displayed for the contributor on the page, defaults to `username`
+ */
+ name?: string
+ /**
+ * Contributor alias. Since the username saved in local git configuration might not match the hosting service username,
+ * aliases can be used to map to the actual username
+ */
+ alias?: string[] | string
+ /**
+ * Contributor avatar URL
+ * If the git hosting service is `GitHub`, this can be omitted as the plugin will auto-fill it
+ */
+ avatar?: string
+ /**
+ * Contributor profile URL
+ * If the git hosting service is `GitHub`, this can be omitted as the plugin will auto-fill it
+ */
+ url?: string
+ }
+ ```
+
+- Description:
+
+ List of contributor information.
+
+ The username and email configured in the user's local git service might not match the user information
+ on git hosting services (like GitHub, GitLab, Gitee). You can pre-configure contributor information here.
+
+ (For non-GitHub git hosting services such as GitLab and Gitee, since avatars and user URLs cannot be
+ directly obtained from usernames, please supplement and complete user information here.)
+
+::: code-tabs
+
+@tab Github
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ contributors: {
+ mode: 'block',
+ info: [
+ {
+ username: 'pengzhanbo', // github username
+ alias: ['peng_zhan_bo'], // alias, username in local git configuration
+ }
+ ]
+ },
+ })
+})
+```
+
+@tab Gitlab
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ contributors: {
+ mode: 'block',
+ info: [
+ {
+ username: 'pengzhanbo', // gitlab username
+ alias: ['peng_zhan_bo'], // alias, username in local git configuration
+ url: 'https://gitlab.com/pengzhanbo',
+ avatar: 'https://gitlab.com/uploads/-/system/user/avatar/1/avatar.png',
+ }
+ ]
+ },
+ })
+})
+```
+
+@tab Gitee
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ contributors: {
+ mode: 'block',
+ info: [
+ {
+ username: 'pengzhanbo', // gitee username
+ alias: ['peng_zhan_bo'], // alias, username in local git configuration
+ url: 'https://gitee.com/pengzhanbo',
+ avatar: 'https://foruda.gitee.com/avatar/1234455/avatar.png',
+ }
+ ]
+ },
+ })
+})
+```
+
+@tab Bitbucket
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ contributors: {
+ mode: 'block',
+ info: [
+ {
+ username: 'pengzhanbo', // bitbucket username
+ alias: ['peng_zhan_bo'], // alias, username in local git configuration
+ url: 'https://bitbucket.org/pengzhanbo',
+ avatar: 'https://bitbucket.org/pengzhanbo/avatar/1234455/avatar.png',
+ }
+ ]
+ },
+ })
+})
+```
+
+@tab Others
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ contributors: {
+ mode: 'block',
+ info: [
+ {
+ username: 'pengzhanbo', // username
+ alias: ['peng_zhan_bo'], // alias, username in local git configuration
+ url: 'https://your-git.com/pengzhanbo',
+ avatar: 'https://your-git.com/avatar.png',
+ }
+ ]
+ },
+ })
+})
+```
+
+:::
+
+### avatar
+
+- Type: `boolean`
+- Default: `true`
+- Description: Whether to display contributor avatars
+
+### avatarPattern
+
+- Type: `string`
+- Default: `'https://github.com/:username.png'`
+- Description: Contributor avatar URL pattern
+
+ `:username` will be replaced with the contributor's username
+
+### transform(contributors)
+
+- Type: `(contributors: GitContributor[]) => GitContributor[]`
+
+ ```ts
+ interface GitContributor {
+ name: string // Display name
+ username: string // Git hosting service username
+ email: string
+ commits: number // Number of commits by the contributor
+ avatar?: string
+ }
+ ```
+
+- Description:
+
+ Contributor transformation function. This function should return a new list of contributors.
+ You can add transformation logic here, such as sorting, deduplication, or completing information.
+
+## frontmatter
+
+### contributors
+
+- Type: `boolean | string[]`
+
+- Description:
+
+ Whether to display contributor information.
+
+ If your article comes from a third party and git commits cannot fully list all authors, you can supplement contributors here.
+
+## Notes
+
+This feature requires your project to be under a
+[Git repository](https://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository) so it can collect information from the commit history.
+
+**When building your site, you should ensure all commit records are accessible.**
+
+For example, CI workflows typically add the `--depth 1` parameter when cloning your repository to avoid
+fetching all commit history. Therefore, you need to disable this feature so the plugin can work properly in CI.
+
+Services like `GitHub Actions`, `Netlify`, and `Vercel` do not fetch all commit history by default.
+
+In `GitHub Actions`, you can add the `--depth 0` parameter to ensure `GitHub Actions` can correctly fetch all commit records.
+
+``` yaml title=".github/workflows/deploy.yml"
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4 # [!code focus:3]
+ with: # [!code ++:2]
+ fetch-depth: 0
+```
+
+For services like `Netlify` and `Vercel`, the processing method is relatively more complex.
+In such cases, you can first complete the build in `GitHub Actions` and output the artifacts to a
+separate branch, then use that branch for deployment in `Netlify` or `Vercel`.
+
+::: info
+For projects created via the theme's `cli` tool, when selecting the deployment method as `GitHub Action`,
+the build artifacts are output to the `gh_pages` branch. You can base your `Netlify` or `Vercel` deployment on this branch.
+:::
diff --git a/docs/en/guide/features/copyright.md b/docs/en/guide/features/copyright.md
new file mode 100644
index 00000000..13f2fe23
--- /dev/null
+++ b/docs/en/guide/features/copyright.md
@@ -0,0 +1,261 @@
+---
+title: Article Copyright
+icon: lucide:creative-commons
+createTime: 2025/10/08 10:52:49
+permalink: /en/guide/features/copyright/
+---
+
+
+
+## Overview
+
+The theme supports adding **copyright** declarations for articles.
+
+Articles typically originate from original works, reposts, translations, etc.
+Adding copyright information for different sources helps better protect intellectual property rights and avoid copyright disputes.
+
+### Creative Commons
+
+The theme natively supports copyright declarations using [Creative Commons](https://creativecommons.org/) licenses, including:
+
+
+
+
+
+- [CC0 1.0 Universal (CC0)](https://creativecommons.org/publicdomain/zero/1.0/)
+
+- [Attribution 4.0 International (CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/)
+
+- [Attribution-ShareAlike 4.0 International (CC-BY-SA-4.0)](https://creativecommons.org/licenses/by-sa/4.0/)
+
+- [Attribution-NonCommercial 4.0 International (CC-BY-NC-4.0)](https://creativecommons.org/licenses/by-nc/4.0/)
+
+- [Attribution-NoDerivatives 4.0 International (CC-BY-ND-4.0)](https://creativecommons.org/licenses/by-nd/4.0/)
+
+- [Attribution-NonCommercial-ShareAlike 4.0 International (CC-BY-NC-SA-4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
+
+- [Attribution-NonCommercial-NoDerivatives 4.0 International (CC-BY-NC-ND-4.0)](https://creativecommons.org/licenses/by-nc-nd/4.0/)
+
+
+
+
+You can select different licenses based on your requirements, or define custom licenses.
+
+### Copyright Information
+
+Copyright information includes:
+
+- Copyright owner, copyright owner link
+- Copyright license, copyright license link
+- Original work link
+
+This information is displayed at the bottom of articles.
+
+::: tip It is recommended to enable the [Contributors](./contributors.md) feature when using this
+functionality. For original articles, the theme automatically uses the first contributor as the
+copyright owner. You can also manually specify the copyright owner in the article frontmatter.
+:::
+
+## Global Configuration
+
+You can declare the `CC-BY-4.0` license for all articles on your site with the following configuration:
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ copyright: 'CC-BY-4.0' // [!code hl]
+ })
+})
+```
+
+You can declare a custom copyright license for all articles on your site with the following configuration:
+
+```ts :no-line-numbers title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ copyright: { // [!code hl:6]
+ license: {
+ name: 'MIT', // License name
+ url: 'https://your-license-url' // License URL
+ },
+ author: {
+ name: 'Your Name', // Copyright owner name
+ url: 'https://your-author-url' // Copyright owner URL
+ },
+ creation: 'reprint' // Creation type
+ }
+ })
+})
+```
+
+**Configuration Type:**
+
+```ts
+export type CopyrightLicense
+ = | 'CC-BY-4.0'
+ | 'CC-BY-SA-4.0'
+ | 'CC-BY-NC-4.0'
+ | 'CC-BY-NC-SA-4.0'
+ | 'CC-BY-ND-4.0'
+ | 'CC-BY-NC-ND-4.0'
+ | 'CC0'
+ | string
+
+/**
+ * - When set to `true`, defaults to `CC-BY-4.0`
+ * - When set to `false`, copyright is hidden, but can be overridden in article frontmatter.copyright
+ */
+type CopyrightOptions = boolean | string | CopyrightLicense | {
+ /**
+ * Copyright license
+ */
+ license?: CopyrightLicense | {
+ name: CopyrightLicense | string
+ url: string
+ }
+ /**
+ * Copyright owner. If not configured, defaults to obtaining from git commit records
+ */
+ author?: {
+ name: string
+ url?: string
+ }
+ /**
+ * Creation type: original, translation, or repost
+ * @default 'original'
+ */
+ creation?: 'original' | 'translate' | 'reprint'
+}
+```
+
+::: warning Global configuration only applies to original articles. For non-original articles,
+you should configure copyright information in the article frontmatter.
+:::
+
+## Article Frontmatter Configuration
+
+You can configure copyright information for individual articles in the article frontmatter to override global configuration:
+
+```md
+---
+title: My Article
+copyright: CC-BY-4.0
+---
+```
+
+**Configuration Type:**
+
+```ts
+/**
+ * When set to `false`, copyright is hidden
+ * When set to `true`, defaults to the global copyright configuration
+ */
+export type CopyrightFrontmatter = boolean | string | CopyrightLicense | {
+ /**
+ * Copyright license
+ */
+ license?: CopyrightLicense | { name: string, url: string }
+
+ /**
+ * Copyright owner
+ * - For original articles, defaults to the first contributor
+ * - For non-original articles, the copyright owner must be declared
+ */
+ author?: string | { name: string, url?: string }
+
+ /**
+ * Article creation type: original, translation, or repost
+ * @default 'original'
+ */
+ creation?: 'original' | 'translate' | 'reprint'
+
+ /**
+ * Original article URL. Must be declared for non-original works
+ * @default ''
+ */
+ source?: string
+}
+```
+
+## Article Configuration Examples
+
+### Original Article
+
+```md
+---
+title: My Article
+copyright: CC-BY-4.0
+---
+```
+
+
+
+### Reposted Article
+
+```md
+---
+title: Reposted Article
+copyright:
+ creation: reprint
+ license: CC-BY-4.0
+ source: https://example.com/origin
+ author:
+ name: Reposter
+ url: https://example.com/author
+---
+```
+
+
+
+### Translated Article
+
+```md
+---
+title: Translated Article
+copyright:
+ creation: translate
+ license: CC-BY-4.0
+ source: https://example.com/origin
+ author:
+ name: Original Author
+ url: https://example.com/author
+---
+```
+
+
+
+### Custom License
+
+```md
+---
+title: My Article
+copyright:
+ license:
+ name: MIT
+ url: https://example.com/mit
+---
+```
+
+
diff --git a/docs/en/guide/features/encryption.md b/docs/en/guide/features/encryption.md
new file mode 100644
index 00000000..e352ab9d
--- /dev/null
+++ b/docs/en/guide/features/encryption.md
@@ -0,0 +1,167 @@
+---
+title: Encryption
+icon: mdi:encryption-outline
+createTime: 2025/10/08 15:58:48
+permalink: /en/guide/features/encryption/
+---
+
+## Encryption
+
+This theme supports multiple flexible encryption methods, including **full-site encryption** and **partial encryption**.
+
+::: warning Note
+Due to the inherent limitations of `vuepress` as a static site generator,
+the **encryption** only makes content *appear* invisible and excludes the content from being pre-rendered
+into `html` during compilation. However, the content can still be accessed from the site's source files.
+
+Therefore, the **encryption** feature should not be considered **secure and reliable**.
+
+Avoid using the **encryption feature** for content that requires **strict confidentiality**.
+:::
+
+**Unlocked articles are only visible within the current session.**
+
+## Enabling Encryption
+
+Add the `encrypt` option in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ encrypt: {
+ // more options...
+ }
+ })
+})
+```
+
+## Full-Site Encryption
+
+In some cases, you may need to encrypt the entire site. Configure full-site encryption using the `encrypt.
+global` option, then set one or more passwords using the `encrypt.admin` option.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ encrypt: {
+ global: true,
+ admin: ['123456'],
+ }
+ })
+})
+```
+
+## Partial Encryption
+
+In most cases, you may only need to encrypt specific articles, directories, etc. Configure partial encryption using the `encrypt.rules` option.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ encrypt: {
+ rules: {
+ // Can be relative path to md file - encrypts this file
+ '前端/基础.md': '123456',
+ // Can be directory path - encrypts all articles under this directory
+ '/notes/vuepress-theme-plume/': '123456',
+ // Can be request path - encrypts all articles under this access path
+ '/vuepress-theme-plume/': '123456',
+ // Can be specific page request path - encrypts this page
+ '/article/f8dnci3/': '123456',
+ // If starting with `^`, pages matching this regex will also be encrypted
+ '^/(a|b)/': '123456',
+ }
+ }
+ })
+})
+```
+
+The **keys** in `encrypt.rules` serve as matching rules, and the **values** serve as passwords for those rules. You can set one or multiple passwords.
+
+:::tip Notes
+
+- Passwords must be plain strings.
+- If an entire directory is encrypted, unlocking applies to the entire directory, not individual articles within it.
+- `encrypt.admin` can also be used to unlock **partially encrypted** pages.
+- After unlocking with `encrypt.admin`, the user is considered an administrator and other locked pages are unlocked by default.
+:::
+
+### Frontmatter
+
+Use the `password` field in Markdown file `Frontmatter` to set article passwords.
+
+```md
+---
+title: Encrypted Article
+password: 123456
+---
+```
+
+You can also add the `passwordHint` option to set password hint information.
+
+```md
+---
+title: Encrypted Article
+password: 123456
+passwordHint: The password is 123456
+---
+```
+
+## Example
+
+Click to visit [Encrypted Article, Password: 123456](/article/enx7c9s/)
+
+## Related Configuration
+
+The following configurations support use in [multilingual configuration](../../config/locales.md).
+
+### encryptGlobalText
+
+- **Type**: `string`
+- **Default**: `'Only password can access this site'`
+- **Description**:
+
+ Prompt message for full-site encryption. Supports HTML. Useful if you want to provide contact information for visitors to obtain passwords.
+
+### encryptPageText
+
+- **Type**: `string`
+- **Default**: `'Only password can access this page'`
+- **Description**:
+
+ Prompt message for partial encryption. Supports HTML. Useful if you want to provide contact information for visitors to obtain passwords.
+
+### encryptButtonText
+
+- **Type**: `string`
+- **Default**: `'Confirm'`
+- **Description**: Text for the confirmation button
+
+### encryptPlaceholder
+
+- **Type**: `string`
+- **Default**: `'Enter password'`
+- **Description**: Placeholder text for the password input field
+
+### Example
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ locales: {
+ '/': {
+ encryptButtonText: 'Confirm',
+ encryptPlaceholder: 'Enter password',
+ encryptGlobalText: 'Only password can access this site',
+ encryptPageText: 'Only password can access this page',
+ }
+ }
+ })
+})
+```
diff --git a/docs/en/guide/features/friend-links.md b/docs/en/guide/features/friend-links.md
new file mode 100644
index 00000000..b207466f
--- /dev/null
+++ b/docs/en/guide/features/friend-links.md
@@ -0,0 +1,43 @@
+---
+title: Friend Links Page
+icon: carbon:friendship
+createTime: 2025/10/08 22:44:28
+permalink: /en/guide/friend-links/
+---
+
+## Friend Links
+
+The friend links page is not automatically generated, but you can create it as needed.
+
+Create any `*.md` file in your `{sourceDir}/` directory, such as `friends.md`. Then configure it using `frontmatter` in this file.
+
+```md title="friends.md"
+---
+friends: true
+title: Friend Links
+description: Description text for friend links
+permalink: /friends/
+contentPosition: after
+list:
+ -
+ name: pengzhanbo
+ link: https://github.com/pengzhanbo
+ avatar: https://github.com/pengzhanbo.png
+ desc: Even if slow, persist without stop; even if falling behind, even if failing, one must be able to reach the goal they are heading towards.
+ -
+ name: pengzhanbo
+ link: https://github.com/pengzhanbo
+ avatar: https://github.com/pengzhanbo.png
+ desc: Even if slow, persist without stop; even if falling behind, even if failing, one must be able to reach the goal they are heading towards.
+---
+
+Custom content
+```
+
+The theme will generate the friend links page based on the configuration.
+
+You need to manually configure the entry link for the friend links page in an appropriate location in the `navbar`.
+
+### Configuration
+
+View the [documentation](../../config/frontmatter/friend.md) for more configuration information.
diff --git a/docs/en/guide/features/icon.md b/docs/en/guide/features/icon.md
new file mode 100644
index 00000000..005299a6
--- /dev/null
+++ b/docs/en/guide/features/icon.md
@@ -0,0 +1,116 @@
+---
+title: Icons
+icon: raphael:smile2
+createTime: 2025/10/08 10:45:47
+permalink: /en/guide/features/icon/
+---
+
+## Overview
+
+The theme supports icons from the following sources:
+
+- [iconify](https://iconify.design/) - Supported by default
+- [iconfont](https://www.iconfont.cn/) - Optional
+- [fontawesome](https://fontawesome.com/) - Optional
+
+Icons are used in the same way across the following theme features:
+
+- [Navbar Icons](../../config/navbar.md#configuration)
+- [Sidebar Icons](../../guide/document.md#sidebar-icons)
+- [File Tree Icons](../../guide/markdown/file-tree.md)
+- [Code Group Title Icons](../code/code-tabs.md#group-title-icons)
+
+Provides syntax sugar and component support:
+
+[Markdown Icon Syntax Sugar Support](../markdown/icons.md){.read-more}
+
+[Icon Component Support](../components/icon.md){.read-more}
+
+::: tip Theme Optimization for Icons
+The theme employs the same parsing strategy internally for all the different ways of using icons
+mentioned above. Even if you use the same icon in different locations, the same icon resources will not be loaded repeatedly.
+:::
+
+## Configuration
+
+```ts title=".vuepress/config.ts" twoslash
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: { // [!code ++:3]
+ icon: { provider: 'iconify' } // Supported by default
+ }
+ })
+})
+```
+
+## Configuration Options
+
+### provider
+
+- **Type**: `'iconify' | 'iconfont' | 'fontawesome'`
+- **Default**: `'iconify'`
+
+Icon provider
+
+### prefix
+
+- **Type**: `string`
+- **Default**: `''` (Different icon providers have different default values)
+- **Details**:
+
+ Icon prefix
+
+ - When provider is `iconify`, defaults to `''`. Set the iconify collection as prefix, e.g., `mdi`.
+ - When provider is `iconfont`, defaults to `'iconfont icon-'`
+ - When provider is `fontawesome`, defaults to `'fas'`. Optional values are:
+
+ ```ts
+ type FontAwesomePrefix
+ = | 'fas' | 's' // fa-solid fa-name
+ | 'far' | 'r' // fa-regular fa-name
+ | 'fal' | 'l' // fa-light fa-name
+ | 'fat' | 't' // fa-thin fa-name
+ | 'fads' | 'ds' // fa-duotone fa-solid fa-name
+ | 'fass' | 'ss' // fa-sharp fa-solid fa-name
+ | 'fasr' | 'sr' // fa-sharp fa-regular fa-name
+ | 'fasl' | 'sl' // fa-sharp fa-light fa-name
+ | 'fast' | 'st' // fa-sharp fa-thin fa-name
+ | 'fasds' | 'sds' // fa-sharp-duotone fa-solid fa-name
+ | 'fab' | 'b' // fa-brands fa-name
+ ```
+
+### assets
+
+- **Type**: `(string | FontAwesomeAssetBuiltin)[] | string | FontAwesomeAssetBuiltin`
+
+ ```ts
+ type FontAwesomeAssetBuiltin = 'fontawesome' | 'fontawesome-with-brands'
+ ```
+
+- **Default**: `undefined`
+
+- **Details**:
+
+ - For `iconify`: No configuration needed;
+ - For `iconfont`: Set to the resource URL of iconfont;
+ - For `fontawesome`: Set to the resource URL of fontawesome. Optional values are `fontawesome` or
+ `fontawesome-with-brands`, or custom resource URLs.
+
+### size
+
+- **Type**: `string | number`
+- **Default**: `1em`
+- **Details**:
+
+ Default icon size
+
+### color
+
+- **Type**: `string`
+- **Default**: `'currentColor'`
+- **Details**:
+
+ Default icon color
diff --git a/docs/en/guide/features/image-preview.md b/docs/en/guide/features/image-preview.md
new file mode 100644
index 00000000..31532906
--- /dev/null
+++ b/docs/en/guide/features/image-preview.md
@@ -0,0 +1,46 @@
+---
+title: Image Preview
+icon: ri:image-line
+createTime: 2025/10/08 20:46:17
+permalink: /en/guide/features/image-preview/
+---
+
+In the theme, images support click-to-enlarge preview by default. A preview list is generated by scanning images within the document content.
+
+This feature is powered by the [@vuepress/plugin-photo-swipe](https://ecosystem.vuejs.press/en/plugins/features/photo-swipe.html) plugin.
+
+## Configuration
+
+Image preview is enabled by default. The behavior can be modified through the following configuration:
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ photoSwipe: {
+ // Image selector
+ selector: '.vp-doc :not(a) > img:not([no-view],.no-view,.ignore)',
+ download: true, // Whether to show the download button
+ fullscreen: true, // Whether to show the fullscreen button
+ scrollToClose: true, // Whether to close the current image when scrolling
+ }
+ }
+ })
+})
+```
+
+For more configuration options, please refer to [@vuepress/plugin-photo-swipe](https://ecosystem.vuejs.press/en/plugins/features/photo-swipe.html).
+
+## Ignoring Image Preview
+
+Image preview can be disabled by using the `no-view` or `ignore` class names, or the `no-view` attribute.
+
+```md
+{.no-view}
+{.ignore}
+{no-view}
+
+
+
+
+```
diff --git a/docs/en/guide/features/replace-assets.md b/docs/en/guide/features/replace-assets.md
new file mode 100644
index 00000000..0b740da8
--- /dev/null
+++ b/docs/en/guide/features/replace-assets.md
@@ -0,0 +1,268 @@
+---
+title: Replace Assets
+icon: lucide:replace
+createTime: 2025/10/08 11:45:17
+permalink: /en/guide/features/replace-assets/
+badge: New
+---
+
+## Overview
+
+This feature is powered by the [@vuepress/plugin-replace-assets](https://ecosystem.vuejs.press/en/plugins/tools/replace-assets.html) plugin.
+
+It replaces local asset links within the site, such as images, videos, audio, PDFs, and other resources, rewriting local asset paths to new addresses.
+
+## Why is this feature needed?
+
+Many users choose to store site assets on CDN services to accelerate site access and improve availability.
+
+In this process, assets typically need to be uploaded to the CDN service first, then CDN links are obtained, and finally used in the site content.
+
+This may seem straightforward, but in practice, it often requires repeatedly performing:
+
+```txt
+Upload assets → Get asset links → Use full asset links in content
+```
+
+During this process, content creation is frequently interrupted.
+
+This feature aims to solve this problem. During content creation,
+you only need to use local asset paths directly, and the theme will handle the asset path replacement at the appropriate stage.
+
+::: important This feature does not modify source files; replacements are only made in the compiled content.
+:::
+
+## Usage
+
+The feature is disabled by default in the theme. You can enable it in the configuration:
+
+```ts title=".vuepress/config.ts" twoslash
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ // ReplaceAssetsPluginOptions
+ replaceAssets: 'https://cdn.example.com' // [!code ++]
+ })
+})
+```
+
+==It's recommended to enable asset path replacement only for production builds, using local asset paths directly during development=={.important}
+
+```ts title=".vuepress/config.ts" twoslash
+import process from 'node:process'
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+const isProd = process.env.NODE_ENV === 'production' // [!code ++]
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ // Enable only in production environment
+ replaceAssets: isProd ? 'https://cdn.example.com' : false // [!code ++]
+ })
+})
+```
+
+### Asset Management
+
+**You should store assets in the [.vuepress/public](https://v2.vuepress.vuejs.org/guide/assets.html#public-files) directory**:
+
+```sh
+./docs
+├── .vuepress
+│ └── public # [!code hl:6]
+│ ├── images
+│ │ ├── foo.jpg
+│ │ └── bar.jpg
+│ └── medias
+│ └── foo.mp4
+└── README.md
+```
+
+::: tip Why store assets in this directory?
+When the site is compiled and ready for deployment, we can easily upload files from this directory directly to the CDN.
+:::
+
+In markdown, use local asset paths directly:
+
+```md
+
+
+
+```
+
+In `javascript`:
+
+```js
+const foo = '/images/foo.jpg'
+
+const img = document.createElement('img')
+img.src = '/images/foo.jpg'
+```
+
+And in style files:
+
+```css
+.foo {
+ background: url('/images/foo.jpg');
+}
+```
+
+The plugin will correctly identify these assets and replace them in the compiled content.
+
+:::warning The plugin does not support identifying concatenated paths like `'/images/' + 'foo.jpg'`.
+:::
+
+## Configuration Reference
+
+```ts
+/**
+ * Asset link replacement configuration
+ */
+type ReplaceAssetsPluginOptions
+ = | Replacement
+ | ReplacementRule
+ | ReplacementRule[]
+ | ReplaceAssetsOptions
+
+/**
+ * - `string`: Prepended to the original asset link
+ * - `function`: Returns the replaced asset link
+ */
+type Replacement = string | ((url: string) => string)
+
+interface ReplacementRule {
+ /**
+ * Match asset links
+ */
+ find: RegExp | string
+ /**
+ * Asset link replacement
+ */
+ replacement: Replacement
+}
+
+interface ReplaceAssetsOptions {
+ /**
+ * Custom asset replacement rules
+ */
+ rules?: ReplacementRule | ReplacementRule[]
+ /**
+ * Replacement for built-in asset matching rules
+ */
+ all?: Replacement
+ /**
+ * Replacement for built-in image asset matching rules
+ */
+ image?: Replacement
+ /**
+ * Replacement for built-in media asset matching rules
+ */
+ media?: Replacement
+}
+```
+
+## Built-in Asset Matching Rules
+
+For convenience, the theme plugin provides built-in asset matching rules that you can use directly.
+
+- `image`: Finds image assets, including local image resource links with formats `['apng','bmp','png','jpeg','jpg','jfif','pjpeg','pjp','gif','svg','ico','webp','avif','cur','jxl']`
+- `media`: Finds media assets, including local media resource links with formats `['mp4','webm','ogg','mp3','wav','flac','aac','opus','mov','m4a','vtt','pdf']`
+- `all`: Finds both image and media assets, combining both `image` and `media` rules
+
+When directly passing a **asset link prefix** or **asset link replacement function**, the theme uses the `all` rule to replace asset links.
+
+```ts title=".vuepress/config.ts"
+import process from 'node:process'
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ // replaceAssets: 'https://cdn.example.com' // [!code hl]
+ replaceAssets: url => `https://cdn.example.com${url}` // [!code ++]
+ })
+})
+```
+
+You can also apply different asset link prefixes or replacement functions to different built-in rules:
+
+```ts title=".vuepress/config.ts"
+import process from 'node:process'
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ // replaceAssets: { // [!code hl:4]
+ // image: 'https://image.cdn.com/',
+ // media: 'https://media.cdn.com/'
+ // },
+ replaceAssets: { // [!code ++:4]
+ image: url => `https://image.cdn.com${url}`,
+ media: url => `https://media.cdn.com${url}`
+ }
+ })
+})
+```
+
+## Custom Asset Matching Rules
+
+You can also define custom asset matching rules:
+
+```ts title=".vuepress/config.ts"
+import process from 'node:process'
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ replaceAssets: { // [!code ++:4]
+ find: /^\/images\/.*\.(jpg|jpeg|png|gif|svg|webp|avif)$/,
+ replacement: url => `https://image.cdn.com${url}`
+ }
+ })
+})
+```
+
+You can also define multiple matching rules:
+
+```ts title=".vuepress/config.ts"
+import process from 'node:process'
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ replaceAssets: [ // [!code ++:12]
+ // Find image assets
+ {
+ find: /^\/images\/.*\.(jpg|jpeg|png|gif|svg|webp|avif)$/,
+ replacement: 'https://image.cdn.com'
+ },
+ // Find media assets
+ {
+ find: /^\/medias\/.*\.(mp4|webm|ogg|mp3|wav|flac|aac|m3u8|m3u|flv|pdf)$/,
+ replacement: url => `https://media.cdn.com${url}`
+ },
+ ]
+ })
+})
+```
+
+**`find` Field Explanation**
+
+The `find` field is used to match asset links and can be a **regular expression** or **string**.
+
+When a `string` is provided, if it starts with `^` or ends with `$`, it will be automatically converted to a **regular expression**.
+Otherwise, it will check if the asset link ends with `find` or starts with `find`.
+
+```txt
+'^/images/foo.jpg' -> /^\/images\/foo.jpg/
+'/images/foo.jpg$' -> /^\/images\/foo.jpg$/
+```
+
+::: important All matched asset paths start with `/`.
+:::
diff --git a/docs/en/guide/features/search.md b/docs/en/guide/features/search.md
new file mode 100644
index 00000000..bcf0c8bd
--- /dev/null
+++ b/docs/en/guide/features/search.md
@@ -0,0 +1,234 @@
+---
+title: Content Search
+icon: material-symbols:search
+createTime: 2025/10/08 09:58:39
+permalink: /en/guide/features/content-search/
+---
+
+The theme provides two approaches for content search:
+
+- Local Content Search
+- Algolia DocSearch
+
+Note: Do not configure both approaches simultaneously. When both are configured, only Local Content Search will take effect.
+
+## Local Content Search
+
+Local Content Search is powered by the
+[@vuepress-plume/plugin-search](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-search) plugin.
+
+This plugin uses [minisearch](https://github.com/lucaong/minisearch) for content searching.
+
+### Enabling
+
+The theme enables Local Content Search by default. You can also customize its configuration.
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ search: { // [!code ++:4]
+ provider: 'local',
+ // more options
+ }
+ })
+})
+```
+
+This plugin generates search indexes locally based on your pages, then loads the search index files when users visit your site.
+In other words, this is a lightweight built-in search capability that doesn't make any external requests.
+
+However, when your site contains a large number of pages, the search index file can become very large and may slow down your page loading speed.
+In such cases, we recommend using a more robust solution - [Algolia DocSearch](#algolia-docsearch).
+
+## Algolia DocSearch
+
+Site content search powered by [Algolia DocSearch](https://docsearch.algolia.com/).
+
+### Enabling
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ search: { // [!code ++:4]
+ provider: 'algolia',
+ // more options
+ }
+ })
+})
+```
+
+### Obtaining Search Index
+
+You need to [submit your website URL](https://docsearch.algolia.com/apply/) to join the DocSearch program.
+When your index is successfully created, the DocSearch team will send `apiKey` and `indexName` to your email.
+You can then configure the plugin to enable DocSearch in VuePress.
+
+Alternatively, you can [run your own crawler](https://docsearch.algolia.com/docs/run-your-own/) to create the index,
+then use your own `appId`, `apiKey`, and `indexName` to configure the plugin.
+
+Here's a crawler configuration example used by this theme. You can visit [Algolia Crawler](https://crawler.algolia.com/admin/crawlers/)
+and modify it according to your needs:
+
+```ts
+new Crawler({
+ appId: 'YOUR_APP_ID', // [!code highlight]
+ apiKey: 'YOUR_API_KEY', // [!code highlight]
+ rateLimit: 8,
+ startUrls: [
+ // These are the initial URLs where Algolia starts crawling your site
+ // If your site is divided into several independent sections, you may need to set multiple entry links here
+ 'https://YOUR_WEBSITE_URL/', // [!code highlight]
+ ],
+ renderJavaScript: false,
+ sitemaps: [
+ // The theme generates sitemap by default; replace with your domain link here
+ 'https://YOUR_WEBSITE_URL/sitemap.xml', // [!code highlight]
+ ],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: [
+ // This defines the scope of URLs that Algolia will crawl
+ 'https://YOUR_WEBSITE_URL/**', // [!code highlight]
+ ],
+ // Crawler execution schedule; set according to your documentation update frequency
+ schedule: 'at 02:00 every 1 day',
+ actions: [
+ // You can have multiple actions, especially when deploying multiple documentations under one domain
+ {
+ // Name your index appropriately
+ indexName: 'YOUR_INDEX_NAME', // [!code highlight]
+ // Paths where the index takes effect
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'], // [!code highlight]
+ recordExtractor: ({ helpers }) => {
+ // Options for vuepress-theme-plume
+ return helpers.docsearch({
+ recordProps: { // [!code highlight]
+ lvl1: '.plume-content h1', // [!code highlight]
+ content: '.plume-content p, .plume-content li', // [!code highlight]
+ lvl0: { // [!code highlight]
+ selectors: [ // [!code highlight]
+ '.sidebar-item.is-active p', // [!code highlight]
+ '.content-container .page-title', // [!code highlight]
+ ], // [!code highlight]
+ defaultValue: 'Documentation', // [!code highlight]
+ }, // [!code highlight]
+ lvl2: '.plume-content h2', // [!code highlight]
+ lvl3: '.plume-content h3', // [!code highlight]
+ lvl4: '.plume-content h4', // [!code highlight]
+ lvl5: '.plume-content h5', // [!code highlight]
+ }, // [!code highlight]
+ indexHeadings: true, // [!code highlight]
+ aggregateContent: true, // [!code highlight]
+ recordVersion: 'v3', // [!code highlight]
+ })
+ },
+ },
+ ],
+ initialIndexSettings: {
+ // Controls how the index is initialized; only effective when the index hasn't been generated yet
+ // You may need to manually delete and regenerate the index after modifications
+ YOUR_INDEX_NAME: { // [!code highlight]
+ attributesForFaceting: ['type', 'lang'], // [!code highlight]
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+})
+```
+
+The `recordProps` section contains configuration options used by this theme for index crawling.
+
+### Configuration Options
+
+For complete configuration, please refer to the [documentation](https://ecosystem.vuejs.press/en/plugins/search/docsearch.html).
+
+### Configuration Example
+
+Here's the configuration used by this theme:
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ search: { // [!code ++:6]
+ provider: 'algolia',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+ }
+ })
+})
+```
diff --git a/docs/en/guide/features/seo.md b/docs/en/guide/features/seo.md
new file mode 100644
index 00000000..0444ee43
--- /dev/null
+++ b/docs/en/guide/features/seo.md
@@ -0,0 +1,111 @@
+---
+title: SEO
+icon: tabler:seo
+createTime: 2025/10/08 14:46:25
+permalink: /en/guide/seo/
+---
+
+## Usage
+
+The theme provides out-of-the-box configuration to enable SEO optimization features for your site.
+To enable it, configure the following:
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ hostname: 'http://your_site_url',
+ })
+})
+```
+
+For custom SEO optimization, you can configure it through `plugins.seo`:
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ seo: {
+ // ... SEO configuration
+ }
+ }
+ })
+})
+```
+
+For complete configuration options, please refer to the [documentation](https://ecosystem.vuejs.press/en/plugins/seo/seo/config.html).
+
+::: note
+This example is forked from [@vuepress/plugin-seo](https://ecosystem.vuejs.press/en/plugins/seo/seo/),
+licensed under [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE).
+:::
+
+## Guide
+
+The theme enhances your site's search engine optimization by injecting tags into the website's `` section,
+making it fully compliant with the [Open Graph Protocol (OGP)](https://ogp.me/)
+and [JSON-LD 1.1](https://www.w3.org/TR/json-ld-api/).
+
+By default, the plugin reads site configuration, theme configuration, and page frontmatter to automatically generate
+metadata. Elements such as site name, page title, page type, writing date, last update date, and article tags are automatically generated.
+
+## Default OGP Generation Logic
+
+| Property Name | Value |
+| :------------ | :---- |
+| `og:url` | `options.hostname` + `path` |
+| `og:site_name` | `siteConfig.title` |
+| `og:title` | `page.title` |
+| `og:description` | `page.frontmatter.description` \|\| auto-generated (when `autoDescription` is `true` in plugin options) |
+| `og:type` | `"article"` |
+| `og:image` | `options.hostname` + `page.frontmatter.image` \|\| first image in page \|\| `fallbackImage` from plugin options |
+| `og:updated_time` | `page.git.updatedTime` |
+| `og:locale` | `page.lang` |
+| `og:locale:alternate` | Other languages included in `siteData.locales` |
+| `twitter:card` | `"summary_large_image"` (only when image is found) |
+| `twitter:image:alt` | `page.title` (only when image is found) |
+| `article:author` | `page.frontmatter.author` \|\| `options.author` |
+| `article:tag` | `page.frontmatter.tags` \|\| `page.frontmatter.tag` |
+| `article:published_time` | `page.frontmatter.date` \|\| `page.git.createdTime` |
+| `article:modified_time` | `page.git.updatedTime` |
+
+## Default JSON-LD Generation Logic
+
+| Property Name | Value |
+| :------------ | :---- |
+| `@context` | `"https://schema.org"` |
+| `@type` | `"NewsArticle"` |
+| `headline` | `page.title` |
+| `image` | Images in page \|\| `options.hostname` + `page.frontmatter.image` |
+| `datePublished` | `page.frontmatter.date` \|\| `page.git.createdTime` |
+| `dateModified` | `page.git.updatedTime` |
+| `author` | `page.frontmatter.author` \|\| `options.author` |
+
+## SEO Introduction
+
+Search Engine Optimization (SEO) is a method of adjusting websites by understanding search engine operation rules
+to improve a target website's ranking in search engines. Since many studies have found that search engine users
+often only pay attention to the top few entries in search results, many websites hope to influence search engine
+rankings through various methods to achieve excellent search rankings for their sites.
+
+The so-called "optimization for search engines" refers to making websites more easily accepted by search engines.
+Search engines compare the content between websites for relevance, and then browsers present this content to searchers
+in the fastest and most complete way possible. Search engine optimization follows search engine rules to create better
+user experiences, with the ultimate goal of providing excellent user experience.
+
+## Related Documentation
+
+- [Open Graph Protocol (OGP)](https://ogp.me/)
+
+ This plugin fully supports this protocol and automatically generates compliant `` tags.
+
+- [JSON-LD 1.1](https://www.w3.org/TR/json-ld-api/)
+
+ This plugin generates NewsArticle type tags for article pages.
+
+- [RDFa 1.1](https://www.w3.org/TR/rdfa-primer/)
+
+ RDFa primarily marks up HTML structure.
+
+- [Schema.Org](https://schema.org/)
+
+ Schema definitions for structured markup sites.
diff --git a/docs/en/guide/features/sitemap.md b/docs/en/guide/features/sitemap.md
new file mode 100644
index 00000000..7a08cd5b
--- /dev/null
+++ b/docs/en/guide/features/sitemap.md
@@ -0,0 +1,35 @@
+---
+title: sitemap
+icon: mdi:sitemap-outline
+createTime: 2025/10/08 16:47:00
+permalink: /en/guide/sitemap/
+---
+
+## Usage
+
+The theme provides out-of-the-box configuration to generate a `sitemap.xml` file for the site.
+To enable it, the following configuration is required:
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ hostname: 'http://your_site_url',
+ })
+})
+```
+
+If customization of the sitemap is needed, it can be achieved through the `plugins.sitemap` configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ sitemap: {
+ // ... sitemap configurations
+ }
+ }
+ })
+})
+```
+
+Refer to the [documentation](https://ecosystem.vuejs.press/zh/plugins/seo/sitemap/config.html) for the complete configuration.
diff --git a/docs/en/guide/features/watermark.md b/docs/en/guide/features/watermark.md
new file mode 100644
index 00000000..a9f8ddf2
--- /dev/null
+++ b/docs/en/guide/features/watermark.md
@@ -0,0 +1,194 @@
+---
+title: Article Watermark
+icon: material-symbols-light:branding-watermark-outline
+createTime: 2025/10/08 20:14:57
+permalink: /en/guide/features/watermark/
+---
+
+## Overview
+
+Article watermarking is powered by [@vuepress/plugin-watermark](https://ecosystem.vuejs.press/zh/plugins/features/watermark.html).
+
+The theme supports adding watermarks to articles. Both full-page watermarks and content-area watermarks
+are supported, along with image watermarks and text watermarks.
+
+## Enabling Watermark
+
+Watermark functionality is disabled by default in the theme. You need to enable it in the theme configuration.
+
+```ts title=".vuepress/config.ts"
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ // watermark: true,
+ watermark: {
+ // enabled: false, // boolean type to control global enablement
+ enabled: page => true, // function type to filter which pages enable watermark
+ delay: 500, // Delay for adding watermark. In milliseconds.
+
+ /**
+ * Whether to use full-page watermark, defaults to `true`.
+ * When set to `false`, the watermark is only displayed in the content area.
+ */
+ fullPage: true,
+
+ /** @see https://zhensherlock.github.io/watermark-js-plus/zh/config/ */
+ watermarkOptions: {
+ content: 'your watermark',
+ // ...
+ }
+ }
+ })
+})
+```
+
+### Global Enablement
+
+When `plugins.watermark` is set to `true`, the theme enables watermark globally.
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ watermark: true,
+ })
+})
+```
+
+### Partial Page Enablement
+
+The theme provides two methods to control watermark enablement on specific pages.
+
+#### watermark.enabled
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ watermark: {
+ // Pages returning true will enable watermark, others will disable it
+ enabled: page => page.path.includes('/article/'),
+ }
+ })
+})
+```
+
+#### frontmatter.watermark
+
+Add `frontmatter.watermark` as `true` in the md file:
+
+```md
+---
+watermark: true
+---
+```
+
+You can also customize the watermark configuration for the current page:
+
+```md
+---
+watermark:
+ content: My Custom Content
+ globalAlpha: 0.2
+ rotate: 45
+---
+```
+
+## Image Watermark
+
+The theme supports using images as watermarks.
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ watermark: {
+ watermarkOptions: {
+ contentType: 'image',
+ image: '/images/watermark.png',
+ width: 200,
+ height: 200,
+ imageWidth: 100,
+ imageHeight: 100,
+ }
+ }
+ })
+})
+```
+
+You can also add configuration in the md file to set watermark for the current page:
+
+```md
+---
+watermark:
+ contentType: image
+ image: /images/watermark.png
+ width: 200
+ height: 200
+ imageWidth: 100
+ imageHeight: 100
+---
+```
+
+### Example
+
+[Image Watermark](/article/i4cuuonn/)
+
+## Text Watermark
+
+The theme supports using text as watermarks.
+
+```ts
+import { defineUserConfig } from 'vuepress'
+import { plumeTheme } from 'vuepress-theme-plume'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ watermark: {
+ watermarkOptions: {
+ content: 'Custom Text',
+ fontColor: '#fff', // Text color
+ }
+ }
+ })
+})
+```
+
+You can also add configuration in the md file to set watermark for the current page:
+
+```md
+---
+watermark:
+ content: Custom Text
+ fontColor: #fff
+---
+```
+
+## Frontmatter
+
+The theme supports adding `frontmatter.watermark` in md files to set watermarks for individual pages.
+
+```md
+---
+watermark:
+ content: My Custom Content
+---
+```
+
+For supported configuration options, please refer to: [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/)
+
+Additionally, `fullPage` is supported to control whether to display the watermark full-screen.
+
+```md
+---
+watermark:
+ fullPage: false
+---
+```
+
+## Examples
+
+- [Content Watermark](/article/2z59hh8g/)
+- [Full-page Watermark](/article/97s6ha1e/)
diff --git a/docs/en/guide/markdown/abbr.md b/docs/en/guide/markdown/abbr.md
index 4685ff14..857d6a60 100644
--- a/docs/en/guide/markdown/abbr.md
+++ b/docs/en/guide/markdown/abbr.md
@@ -1,19 +1,19 @@
---
-title: Abbreviation
+title: Abbreviations
icon: mdi:tooltip-question-outline
-createTime: 2025/03/24 17:07:33
+createTime: 2025/10/08 10:48:15
permalink: /en/guide/markdown/abbreviation/
---
## Overview
-**Abbreviations** refer to short forms used in Markdown, such as technical terms like W3C and ECMA.
+**Abbreviations** refer to acronyms used in Markdown, such as professional terms like W3C, ECMA, etc.
-When hovering over an abbreviation, the full term will be displayed along with its definition or explanation.
+When hovering over an abbreviation, the full name of the term is displayed, and it can also include the definition and explanation of the abbreviation.
## Configuration
-This feature is disabled by default. Enable it in `theme` configuration:
+This feature is disabled by default. You need to enable it in the `theme` configuration.
```ts title=".vuepress/config.ts"
export default defineUserConfig({
@@ -27,11 +27,12 @@ export default defineUserConfig({
## Syntax
-In Markdown, define abbreviations using `*[ABBR]: Description` on separate lines. The description may include the abbreviation's definition, explanation, etc.
+In Markdown, use `*[Abbreviation]: Description` on a separate line to define an abbreviation.
+The description can include the definition, explanation, etc., of the abbreviation.
-Place the abbreviation within `[]` and its description after `:`. The description supports Markdown inline syntax.
+Fill in the abbreviation within `[]`, and write the description after `:`. Markdown inline syntax can be used in the description.
-If the Markdown plain text contains defined abbreviations, the explanation of the abbreviation will be automatically displayed when the mouse moves over it.
+If defined abbreviations appear in regular Markdown text, hovering over them will automatically display the abbreviation's explanation.
**Input:**
@@ -50,5 +51,6 @@ The HTML specification is maintained by the W3C.
*[W3C]: World Wide Web Consortium
*[ECMA]: European Computer Manufacturers Association
-::: warning Abbreviations should be standalone words or phrases. For Chinese abbreviations, add spaces around the term to ensure proper detection.
+::: warning
+Abbreviations should be independent words or phrases. For Chinese abbreviations, add spaces on both sides of the word to distinguish them.
:::
diff --git a/docs/en/guide/markdown/annotation.md b/docs/en/guide/markdown/annotation.md
index b772f8c1..ac0363f8 100644
--- a/docs/en/guide/markdown/annotation.md
+++ b/docs/en/guide/markdown/annotation.md
@@ -1,19 +1,19 @@
---
title: Annotation
icon: iconamoon:comment-add-light
-createTime: 2025/03/24 17:19:13
+createTime: 2025/10/08 10:48:35
permalink: /en/guide/markdown/annotation/
---
## Description
-==Annotation== is a special Markdown syntax for adding extra information, explanations, or hints in documents.
+==Annotation== is a special syntax in Markdown used to add extra information, explanations, or hints to a document.
-Annotations are not displayed directly in the document and require user interaction to be shown.
+Annotations are not directly displayed in the document; they require the user to manually click to be revealed.
## Configuration
-This feature is not enabled by default. You need to enable it in the `theme` configuration.
+This feature is disabled by default. You need to enable it in the `theme` configuration.
```ts title=".vuepress/config.ts"
export default defineUserConfig({
@@ -27,120 +27,128 @@ export default defineUserConfig({
## Syntax
-==Annotation== syntax consists of two parts:
+The ==Annotation== syntax consists of two parts:
### Inline Annotation
-Insert an annotation tag inline using the `[+label]` syntax.
+Insert an annotation marker inline using the `[+label]` syntax.
-The annotation tag is composed of `[+` + `label` + `]`. To distinguish it from the content, there should be a space before `[+label]`.
+The annotation marker is composed of `[+` + `label` + `]`.
+To distinguish it clearly from the surrounding content, a space should be present at the left edge of `[+label]`.
-`label` is the annotation tag and can be any string.
+`label` is the tag for the annotation and can be any string.
-::: important The symbol `+` is required
+::: important The `+` symbol is required.
:::
-### Define Annotation
+### Defining Annotations
-Define the annotation in a separate area of the document using the `[+label]:` syntax.
+Define annotations in a separate area of the document using the `[+label]:` syntax.
-The annotation definition area is composed of `[+` + `label` + `]:` + `content`.
+The annotation definition area is composed of `[+` + `label` + `]:` + `Content`.
-`label` should match the `[+label]` used earlier to mark the annotation.
+`label` should match the `[+label]` mentioned above and is used to identify the annotation tag.
-**Content** can be written after the `:`:
+**Content** can be written directly after the `:`:
```md
-[+label]: Here is the content, which can use **Markdown** syntax.
+[+label]: This is the content. **Markdown** syntax can be used here.
```
-**Content** can also start on the next line with indentation, and should maintain consistent indentation for multiple lines.
+**Content** can also start on the next line, but it must be indented. Consistent indentation should be maintained for multiple lines.
```md
[+label]:
- Here is the content.
- Indent consistently, this line is also part of the content.
+ This is the content.
+ The indentation is consistent, so this line is also part of the content.
- Even if the previous line is blank, but this line's indentation is consistent, it is still part of the content.
- You can use **Markdown** syntax.
+ Even with a blank line above, this line is still consistently indented, so it is also content.
+ **Markdown** syntax can be used.
-This line is no longer indented, so the annotation definition for this tag ends on the previous line.
+This line is no longer indented, so the annotation definition for this tag ended on the previous line.
```
-The content of the annotation definition is not rendered directly in the document, but is displayed when the `[+label]` inline annotation is clicked.
+The content of the annotation definition is not rendered directly in the document.
+It is presented only when the inline `[+label]` marker is clicked.
-## Example
+## Examples
### Example 1
**Input:**
```md
-The site is powered by VuePress [+vuepress].
+This site is powered by VuePress [+vuepress].
[+vuepress]:
- VuePress is a [static site generator](https://en.wikipedia.org/wiki/Static_site_generator ) (SSG).
- Designed specifically for building fast, content-focused websites.
+ VuePress is a [Static Site Generator](https://en.wikipedia.org/wiki/Static_site_generator) (SSG).
+ It is specifically designed for building fast, content-centric sites.
```
**Output:**
-The site is powered by VuePress [+vuepress].
+This site is powered by VuePress [+vuepress].
[+vuepress]:
- VuePress is a [static site generator](https://en.wikipedia.org/wiki/Static_site_generator ) (SSG).
- Designed specifically for building fast, content-focused websites.
+ VuePress is a [Static Site Generator](https://en.wikipedia.org/wiki/Static_site_generator) (SSG).
+ It is specifically designed for building fast, content-centric sites.
### Example 2
-**Multiple annotations for the same `label`, rendered as a list.**
+**Multiple annotations defined with the same `label` are rendered as a list.**
**Input:**
```md
-The Four Great Classical Novels of ancient China [+classics] are widely known.
+The ancient Chinese **Four Great Classical Novels** [+novels] are household names.
-[+classics]:
- **Romance of the Three Kingdoms:**
+[+novels]:
+ **"Romance of the Three Kingdoms":**
- Set against the history of the Three Kingdoms period, it depicts the political and military struggles among the Wei, Shu, and Wu kingdoms, creating numerous historical figures like Zhuge Liang, Cao Cao, Guan Yu, and Liu Bei.
+ Set against the backdrop of the Three Kingdoms period in Chinese history, it depicts the political and military struggles between the states of Wei, Shu, and Wu, shaping the images of numerous historical figures such as Zhuge Liang, Cao Cao, Guan Yu, and Liu Bei.
-[+classics]:
- **Journey to the West:**
+[+novels]:
+ **"Journey to the West":**
- Tells the story of Tang僧 and his four disciples (Sun Wukong, Zhu Bajie, Sha僧, and White Dragon Horse) on their pilgrimage to the West for Buddhist scriptures, filled with mythological elements and fantastic adventures.
+ Tells the story of the monk Xuanzang and his three disciples (Sun Wukong, Zhu Bajie, Sha Wujing, and the White Dragon Horse) on their journey to the West to obtain sacred Buddhist texts, filled with mythological elements and fantastical adventures.
-[+classics]:
- **Dream of the Red Chamber:**
+[+novels]:
+ **"Dream of the Red Chamber":**
- Set against the rise and fall of the four major families (Jia, Shi, Wang, and Xue), it depicts the love tragedy of Jia Baoyu, Lin Daiyu, and Xue Baochai, showcasing the decadence and decline of feudal society.
+ Set against the backdrop of the decline of the four major families Jia, Shi, Wang, and Xue, it depicts the love tragedy between Jia Baoyu, Lin Daiyu, and Xue Baochai, revealing the corruption and decay of feudal society.
-[+classics]:
- **Water Margin:**
+[+novels]:
+ **"Water Margin":**
- Depicts the story of 108 heroes led by Song Jiang gathering at Liangshan泊 to resist the court during the late Northern Song Dynasty, revealing the social reality of oppression leading to rebellion.
+ Depicts the story of 108 outlaws, led by Song Jiang, who gather at Liangshan Marsh during the late Northern Song Dynasty to rebel against the imperial government, showcasing the social reality of oppression leading to rebellion.
```
**Output:**
-The Four Great Classical Novels of ancient China [+classics] are widely known.
+The ancient Chinese **Four Great Classical Novels** [+novels] are household names.
-[+classics]:
- **Romance of the Three Kingdoms:**
+[+novels]:
+ **"Romance of the Three Kingdoms":**
- Set against the history of the Three Kingdoms period, it depicts the political and military struggles among the Wei, Shu, and Wu kingdoms, creating numerous historical figures like Zhuge Liang, Cao Cao, Guan Yu, and Liu Bei.
+ Set against the backdrop of the Three Kingdoms period in Chinese history,
+ it depicts the political and military struggles between the states of Wei, Shu, and Wu,
+ shaping the images of numerous historical figures such as Zhuge Liang, Cao Cao, Guan Yu, and Liu Bei.
-[+classics]:
- **Journey to the West:**
+[+novels]:
+ **"Journey to the West":**
- Tells the story of Tang僧 and his four disciples (Sun Wukong, Zhu Bajie, Sha僧, and White Dragon Horse) on their pilgrimage to the West for Buddhist scriptures, filled with mythological elements and fantastic adventures.
+ Tells the story of the monk Xuanzang and his three disciples (Sun Wukong, Zhu Bajie, Sha Wujing,
+ and the White Dragon Horse) on their journey to the West to obtain sacred Buddhist texts,
+ filled with mythological elements and fantastical adventures.
-[+classics]:
- **Dream of the Red Chamber:**
+[+novels]:
+ **"Dream of the Red Chamber":**
- Set against the rise and fall of the four major families (Jia, Shi, Wang, and Xue), it depicts the love tragedy of Jia Baoyu, Lin Daiyu, and Xue Baochai, showcasing the decadence and decline of feudal society.
+ Set against the backdrop of the decline of the four major families Jia, Shi, Wang, and Xue,
+ it depicts the love tragedy between Jia Baoyu, Lin Daiyu, and Xue Baochai, revealing the corruption and decay of feudal society.
-[+classics]:
- **Water Margin:**
+[+novels]:
+ **"Water Margin":**
- Depicts the story of 108 heroes led by Song Jiang gathering at Liangshan泊 to resist the court during the late Northern Song Dynasty, revealing the social reality of oppression leading to rebellion.
+ Depicts the story of 108 outlaws, led by Song Jiang, who gather at Liangshan Marsh during the late
+ Northern Song Dynasty to rebel against the imperial government, showcasing the social reality of oppression leading to rebellion.
diff --git a/docs/en/guide/markdown/caniuse.md b/docs/en/guide/markdown/caniuse.md
index 9a73911b..6ba4c4dd 100644
--- a/docs/en/guide/markdown/caniuse.md
+++ b/docs/en/guide/markdown/caniuse.md
@@ -1,19 +1,19 @@
---
title: Can I Use
-createTime: 2025/03/24 22:10:32
+createTime: 2025/10/08 14:50:55
icon: streamline:desktop-help
permalink: /en/guide/markdown/caniuse/
---
## Overview
-When writing articles, you can embed the support status of [can-i-use](https://caniuse.com/) WEB features across platforms.
+When writing articles, this feature provides the functionality to embed platform support information for WEB features from [can-i-use](https://caniuse.com/).
-This makes it easier to describe the support level of a particular WEB feature.
+This allows for a more intuitive representation of a feature's support level when describing a specific WEB feature.
## Configuration
-This feature is not enabled by default. You can enable it in the configuration file.
+This feature is disabled by default. You can enable it in the configuration file.
```ts title=".vuepress/config.ts"
export default defineUserConfig({
@@ -25,17 +25,18 @@ export default defineUserConfig({
})
```
-In your Markdown file, use the following format:
+In your article's markdown file, use the following format:
-```md
+``` md
@[caniuse](feature)
```
-For convenience, the theme provides a tool: [caniuse feature search](../../../../../notes/tools/caniuse.md), which can help generate the Markdown code.
+For ease of use, the theme provides tool support: [caniuse Feature Search](../../../tools/caniuse.md).
+You can use this tool directly to help generate the markdown code.
## Syntax
-```md
+``` md
@[caniuse](feature)
@[caniuse{browser_versions}](feature)
@[caniuse embed_type](feature)
@@ -44,19 +45,19 @@ For convenience, the theme provides a tool: [caniuse feature search](../../../..
- `feature`
- Required. For correct values, refer to [caniuse-embed.vercel.app](https://caniuse-embed.vercel.app/zh-CN)
+ Required. For correct values, please refer to [caniuse-embed.vercel.app](https://caniuse-embed.vercel.app/zh-CN).
- `{browser_versions}`
- Optional. The support status of the feature across multiple browser versions.
+ Optional. Specifies the support status of the current feature across multiple browser versions.
Default value: `{-2,1}`
- Format: `{past,future}` with values ranging from `-5 ~ 3`
+ Format: `{past,future}` Value range: `-5 ~ 3`
- - Less than `0` indicates support below the current browser version
- - `0` indicates support at the current browser version
- - Greater than `0` indicates support above the current browser version
+ - Values less than `0` indicate support status for browser versions lower than the current one.
+ - `0` indicates the support status for the current browser version.
+ - Values greater than `0` indicate support status for browser versions higher than the current one.
- `embed_type`
@@ -67,37 +68,40 @@ For convenience, the theme provides a tool: [caniuse feature search](../../../..
Default value: `'embed'`
:::caution
-The use of image type is no longer recommended. Instead, use the embed type, as the theme has changed the embed implementation, offering faster loading, smaller size, and better interaction.
+The `image` type is no longer recommended. It is advised to use the `embed` type.
+The theme has changed the implementation technology for the embed component.
+The current `embed` type now offers significant advantages over the `image` type,
+including faster loading speed, smaller size, and better interactive experience.
:::
## Examples
-**Get the browser support status for the CSS pseudo-class selector `:dir()`:**
+**Get the browser support for the CSS pseudo-class selector `:dir()`:**
```md
@[caniuse](css-matches-pseudo)
```
-Effect:
+Result:
@[caniuse](css-matches-pseudo)
-**Get the browser support status for the CSS pseudo-class selector `:dir()` as an image:**
+**Get the browser support for the CSS pseudo-class selector `:dir()` as an image:**
```md
@[caniuse image](css-matches-pseudo)
```
-Effect:
+Result:
@[caniuse image](css-matches-pseudo)
-**Get the browser support status for the CSS pseudo-class selector `:dir()` for specific browser versions:**
+**Get the browser support for the CSS pseudo-class selector `:dir()` for a specific range of browser versions:**
```md
@[caniuse{-2,3}](css-matches-pseudo)
```
-Effect:
+Result:
@[caniuse{-2,3}](css-matches-pseudo)
diff --git a/docs/en/guide/markdown/card.md b/docs/en/guide/markdown/card.md
index c9a092ca..1f61968e 100644
--- a/docs/en/guide/markdown/card.md
+++ b/docs/en/guide/markdown/card.md
@@ -1,26 +1,26 @@
---
title: Card
-createTime: 2025/03/24 19:46:13
+createTime: 2025/10/08 14:37:40
icon: solar:card-broken
permalink: /en/guide/markdown/card/
---
## Overview
-To highlight content, place it in a card container `::: card`.
+Content that needs to be highlighted can be placed within a card container `::: card`.
-To display multiple cards side by side when space allows, use the `card-grid` container around multiple cards.
+When multiple cards need to be displayed side-by-side when space permits, use the `card-grid` container to wrap multiple cards.
## Syntax
```md
-
+
::: card title="Title" icon="twemoji:astonished-face"
This is the card content.
:::
-
+
:::: card-grid
::: card title="Card Title 1" icon="twemoji:astonished-face"
@@ -36,9 +36,18 @@ This is the card content.
::::
```
-Cards support optional `title` and `icon`. The icon can be an image URL or an Iconify icon name.
+## Props
-## Example
+:::: field-group
+::: field name="title" type="string" optional default="''"
+Card title
+:::
+
+::: field name="icon" type="string" optional
+Card icon. Supports image URLs and [iconify](https://icon-sets.iconify.design/) icon names.
+::::
+
+## Examples
**Input:**
@@ -87,5 +96,5 @@ This is the card content.
::::
::: info
-If you prefer to use cards via components, you can check out the [Card Component](/en/guide/features/component/#card).
+If you prefer using cards via components, you can check out the [Card Component](/guide/features/component/#card).
:::
diff --git a/docs/en/guide/markdown/chat.md b/docs/en/guide/markdown/chat.md
new file mode 100644
index 00000000..f5638e37
--- /dev/null
+++ b/docs/en/guide/markdown/chat.md
@@ -0,0 +1,123 @@
+---
+title: Chat Records
+icon: cil:chat-bubble
+createTime: 2025/10/08 21:40:18
+permalink: /en/guide/markdown/chat/
+---
+
+## Preface
+
+::: chat title="User B"
+{:2025-03-24 10:15:00}
+
+{User B}
+Putting chat screenshots in the documentation still looks pretty bad, is there a better way? \[doge\]
+
+{.}
+Sure there is, bro, definitely sure
+
+{.}
+But is it really okay to post chat records like this?
+
+{User B}
+Proof of our fiery debates is worth keeping \[doge\]
+
+{:2025-03-24 15:32:00}
+
+{.}
+Good news: the docs now support chat records!
+
+{.}
+Bad news: I've used you as the example \[doge\]
+
+{User B}
+???
+:::
+
+## Overview
+
+In Markdown, wrapping specially formatted text content within a `:: chat` container allows you to display ==chat records== within the documentation.
+
+::: warning This is a feature you likely won't need most of the time.
+Please consider carefully whether you should use it when the need arises.
+Filter out any private or sensitive content yourself.
+:::
+
+## Enable
+
+This feature is disabled by default. You need to enable it in the `theme` configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ chat: true, // [!code ++]
+ }
+ })
+})
+```
+
+## Usage
+
+Within a `::: chat` container, use specific markers to identify the sender and timestamp of messages,
+which will then render the chat record in the documentation.
+
+```md
+::: chat title="Title"
+{:date}
+
+{username}
+xxx
+
+{.}
+xxx
+:::
+```
+
+- `{:date}` Marks the starting timestamp (Optional). Use the format `{:` + date + `}`. `date` can be in common date formats.
+
+ The theme does not process `date` in any way; it simply renders it.
+
+- `{username}` Marks the sender of the subsequent content. Use the format `{` + username + `}`. `username` can be any string.
+
+- `{.}` Marks the message as sent by the current user.
+
+## Example
+
+__Input:__
+
+``` md
+::: chat title="Title"
+{:2025-03-24 10:15:00}
+
+{User 1}
+Message from User 1
+
+{.}
+Message from the current user
+
+{User 2}
+Message from User 2
+
+{.}
+Message from the current user
+:::
+```
+
+__Output:__
+
+::: chat title="Title"
+{:2025-03-24 10:15:00}
+
+{User 1}
+Message from User 1
+
+{.}
+Message from the current user
+
+{User 2}
+Message from User 2
+
+{.}
+Message from the current user
+:::
diff --git a/docs/en/guide/markdown/code-tree.md b/docs/en/guide/markdown/code-tree.md
new file mode 100644
index 00000000..5ab071aa
--- /dev/null
+++ b/docs/en/guide/markdown/code-tree.md
@@ -0,0 +1,170 @@
+---
+title: Code Tree
+icon: stash:side-peek
+createTime: 2025/10/08 05:59:44
+permalink: /en/guide/markdown/code-tree/
+badge: New
+---
+
+## Overview
+
+In Markdown, use the `::: code-tree` container or `@[code-tree](dir_path)` syntax to display a code block area with a file tree.
+
+Compared to code block grouping, code trees can more clearly present the organizational structure of code files and their dependency relationships.
+
+## Enable
+
+This feature is disabled by default. You need to enable it in the `theme` configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ codeTree: true, // [!code ++]
+ }
+ })
+})
+```
+
+## Usage
+
+The theme provides two usage methods:
+
+### code-tree Container
+
+````md
+::: code-tree title="Project Name" height="400px" entry="filepath"
+```lang title="filepath" :active
+
+```
+
+```lang title="filepath"
+
+```
+
+:::
+````
+
+Use the `::: code-tree` container to wrap multiple code blocks.
+
+- Use `title="Project Name"` after `::: code-tree` to declare the code tree title
+- Use `height="400px"` after `::: code-tree` to declare the code tree height
+- Use `entry="filepath"` after `::: code-tree` to declare the default expanded file path
+- Use `title="filepath"` after the code block \`\`\` lang to declare the current code block's file path
+- If `entry="filepath"` is not declared in `::: code-tree`, you can use `:active` after the code block
+\`\`\` lang to declare the current code block as expanded
+- If no expanded file path is specified, the first file will be expanded by default
+
+::: details Why use `title="filepath"` instead of `filepath="filepath"` on code blocks?
+Because the theme already [supports title syntax on code blocks](../code/features.md#code-block-titles).
+Continuing to use the existing syntax support reduces the learning curve.
+:::
+
+**Input:**
+
+````md :collapsed-lines
+::: code-tree title="Vue App" height="400px" entry="src/main.ts"
+```vue title="src/components/HelloWorld.vue"
+
+
+ Hello World
+
+
+```
+
+```vue title="src/App.vue"
+
+
+ vuepress-theme-plume
+
+
+
+```
+
+```ts title="src/main.ts"
+import { createApp } from 'vue'
+import App from './App.vue'
+
+createApp(App).mount('#app')
+```
+
+```json title="package.json"
+{
+ "name": "Vue App",
+ "scripts": {
+ "dev": "vite"
+ }
+}
+```
+:::
+````
+
+**Output:**
+
+::: code-tree title="Vue App" height="400px" entry="src/main.ts"
+
+```vue title="src/components/HelloWorld.vue"
+
+
+ Hello World
+
+
+```
+
+```vue title="src/App.vue"
+
+
+ vuepress-theme-plume
+
+
+
+```
+
+```ts title="src/main.ts"
+import { createApp } from 'vue'
+import App from './App.vue'
+
+createApp(App).mount('#app')
+```
+
+```json title="package.json"
+{
+ "name": "Vue App",
+ "scripts": {
+ "dev": "vite"
+ }
+}
+```
+
+:::
+
+### Importing code-tree from Directory
+
+The theme supports importing `code-tree` from a directory using the following syntax:
+
+```md
+
+@[code-tree](dir_path)
+
+
+@[code-tree title="Project Name" height="400px" entry="filepath"](dir_path)
+```
+
+- **dir_path**:
+ When an absolute path is provided (starting with `/`), the search begins from the source directory of the documentation site.
+ When a relative path is provided (starting with `.`), it is relative to the current Markdown file.
+
+- **title**: Code tree title, optional, defaults to empty
+- **height**: Code tree height, optional, defaults to empty
+- **entry**: Default expanded file path, optional, defaults to the first file
+
+**Input:**
+
+```md
+
+@[code-tree title="Collections Configuration" height="400px" entry="index.ts"](/.vuepress/collections)
+```
+
+**Output:**
+
+@[code-tree title="Collections Configuration" height="400px" entry="index.ts"](/.vuepress/collections)
diff --git a/docs/en/guide/markdown/collapse.md b/docs/en/guide/markdown/collapse.md
index 11ae7934..92282fc4 100644
--- a/docs/en/guide/markdown/collapse.md
+++ b/docs/en/guide/markdown/collapse.md
@@ -1,22 +1,19 @@
---
-title: Collapsible panel
+title: Collapse Panel
icon: carbon:collapse-categories
-createTime: 2025/03/25 10:13:04
+createTime: 2025/10/08 22:27:22
permalink: /en/guide/markdown/collapse/
-badge:
- type: tip
- text: 1.0.0-rc.137 +
---
## Overview
-In Markdown, the `::: collapse` container, combined with Markdown unordered list syntax, can be used to create ==collapsible panels==.
+In markdown, use the `::: collapse` container with markdown unordered list syntax to implement ==collapse panels==.
-- It supports setting the mode to **accordion** using the `accordion` option.
+- Supports ==accordion== mode via the `accordion` setting
## Enable
-This feature is not enabled by default. You need to enable it in the `theme` configuration.
+This feature is disabled by default. You need to enable it in the `theme` configuration.
```ts title=".vuepress/config.ts"
export default defineUserConfig({
@@ -30,13 +27,13 @@ export default defineUserConfig({
## Usage
-In Markdown, use the `::: collapse` container with Markdown unordered list syntax, where each item represents a separate collapsible area.
+In markdown, use the `::: collapse` container with markdown unordered list syntax. Each item represents a separate collapsible section.
```md title="collapse.md"
::: collapse
- Title 1
-
- Content
+
+ Content
- Title 2
@@ -44,225 +41,227 @@ In Markdown, use the `::: collapse` container with Markdown unordered list synta
:::
```
-For each item in the list:
+For each list item:
-- From the **first line** to the **first empty line** is the **title**.
-- **After the first empty line**: The main content.
+- Everything from the __first line__ to the __first empty line__ is considered the __title__
-:::important Please note the correct indentation
+- __After the first empty line__: Content
+
+:::important Please ensure correct indentation
:::
-**A simple example:**
+__A simple example:__
-**Input:**
+__Input:__
```md
::: collapse
- Title 1
- Main content
+ Content
- Title 2
- Main content
+ Content
:::
```
-**Output:**
+__Output:__
::: collapse
- Title 1
- Main content
+ Content
- Title 2
- Main content
+ Content
:::
## Configuration
-After the `::: collapse` container syntax, you can add configuration options:
+After the `::: collapse` container syntax, follow with configuration options:
-- `accordion`: Sets the collapsible panels to ==accordion== mode. In accordion mode, only one panel can be expanded at a time. Clicking another panel will close the previously opened one.
-- `expand`: Expands all panels by default. This option is invalid in accordion mode.
+- `accordion`: Sets the collapse panel to ==accordion== mode. In accordion mode,
+ only one panel can be expanded at a time; clicking other panels will close the previously opened panel.
+- `expand`: Expands panels by default. Invalid in accordion mode.
-Before the title of each list item, you can use special markers `:+` or `:-` to set the initial state of the item to **expanded** or **collapsed**.
+In list items, before the title, use special markers `:+` / `:-` to set the initial state of the current item to __expanded / collapsed__.
## Examples
### Basic Usage
-**Input:**
+__Input:__
```md
::: collapse
- Title 1
- Main content
+ Content
- Title 2
- Main content
+ Content
:::
```
-**Output:**
+__Output:__
::: collapse
- Title 1
- Main content
+ Content
- Title 2
- Main content
- :::
+ Content
+:::
### Expand All by Default
Add the `expand` option to expand all panels by default.
-**Input:**
+__Input:__
```md /expand/
::: collapse expand
- Title 1
- Main content
+ Content
- Title 2
- Main content
+ Content
:::
```
-**Output:**
+__Output:__
::: collapse expand
- Title 1
- Main content
+ Content
- Title 2
- Main content
- :::
+ Content
+:::
### Accordion Mode
-Add the `accordion` option to set the mode to accordion, allowing only one panel to be expanded at a time. Clicking another panel will close the previously opened one.
+Add the `accordion` option to set accordion mode, where only one panel can be expanded at a time.
```md /accordion/
::: collapse accordion
- Title 1
- Main content
+ Content
- Title 2
- Main content
+ Content
- Title 3
- Main content
+ Content
:::
```
-**Output:**
+__Output:__
::: collapse accordion
- Title 1
- Main content
+ Content
- Title 2
- Main content
+ Content
- Title 3
- Main content
- :::
+ Content
+:::
-### Expand Items with `:+`
+### `:+` Mark Item as Expanded
-By default, all collapsible panels are closed. You can use the `:+` marker to set the initial state of an item to expanded.
+Collapse panels are closed by default. Use `:+` to mark items with an initial expanded state.
-**Input:**
+__Input:__
```md /:+/
::: collapse
- Title 1
- Main content
+ Content
- :+ Title 2
- Main content
+ Content
- :+ Title 3
- Main content
+ Content
:::
```
-**Output:**
+__Output:__
::: collapse
- Title 1
- Main content
+ Content
- :+ Title 2
- Main content
+ Content
- :+ Title 3
- Main content
- :::
+ Content
+:::
-### Collapse Items with `:-`
+### `:-` Mark Item as Collapsed
-When the `expand` option is configured, all panels are expanded by default. You can use the `:-` marker to set the initial state of an item to collapsed.
+When collapse panel is configured with `expand`, all panels are expanded by default. Use `:-` to mark items with an initial collapsed state.
-**Input:**
+__Input:__
```md /:-/
::: collapse expand
- Title 1
- Main content
+ Content
- :- Title 2
- Main content
+ Content
- Title 3
- Main content
+ Content
:::
```
-**Output:**
+__Output:__
::: collapse expand
- Title 1
- Main content
+ Content
- :- Title 2
- Main content
+ Content
- Title 3
- Main content
- :::
+ Content
+:::
diff --git a/docs/en/guide/markdown/demo-wrapper.md b/docs/en/guide/markdown/demo-wrapper.md
index d2b3aaaa..57cc674e 100644
--- a/docs/en/guide/markdown/demo-wrapper.md
+++ b/docs/en/guide/markdown/demo-wrapper.md
@@ -1,6 +1,6 @@
---
-title: Demo Wrapper
-createTime: 2025/03/24 21:49:01
+title: Demo Container
+createTime: 2025/10/08 14:47:12
icon: icon-park-outline:eyes
permalink: /en/guide/markdown/demo-wrapper/
outline: 2
@@ -8,27 +8,27 @@ outline: 2
## Overview
-Sometimes, you may need to add examples in your content but want them to be presented separately from other content.
-The theme supports adding demo wrapper in Markdown files.
+Sometimes you may need to supplement your content with examples but want them to be presented
+separately from other content. The theme supports adding demo containers in Markdown files.
## Syntax
````md
::: demo-wrapper
-Add your example here
+Add your demo here
:::
````
## Options
- `title="xxx"`: Title
-- `no-padding`: No padding
-- `img`: Use when only containing an image
+- `no-padding`: Remove padding
+- `img`: Use when containing only images
- `height="xxx"`: Height
-## Example
+## Examples
-Image only:
+Containing only images:
```md
::: demo-wrapper img no-padding
@@ -41,25 +41,25 @@ Image only:

:::
-Markdown content:
+Containing markdown syntax:
```md
::: demo-wrapper title="Title"
-### Third-level heading
+### Level 3 Heading
-This is the content within the demo wrapper.
+This is content inside the demo container.
:::
```
**Output:**
::: demo-wrapper title="Title"
-### Third-level heading
+### Level 3 Heading
-This is the content within the demo wrapper.
+This is content inside the demo container.
:::
-HTML/Vue code:
+Containing HTML/Vue code:
```md
::: demo-wrapper
@@ -80,7 +80,7 @@ HTML/Vue code:
**Output:**
::: demo-wrapper
-This is a title
+This is a heading
This is a paragraph
diff --git a/docs/en/guide/repl/demo/Toggle.vue b/docs/en/guide/repl/demo/Toggle.vue
new file mode 100644
index 00000000..dbfd39a9
--- /dev/null
+++ b/docs/en/guide/repl/demo/Toggle.vue
@@ -0,0 +1,29 @@
+
+
+
+
+ Value: {{ value ? 'ON' : 'OFF' }}
+
+
+
+
+
+
+
+
+
diff --git a/docs/en/guide/repl/demo/normal-lib.html b/docs/en/guide/repl/demo/normal-lib.html
new file mode 100644
index 00000000..05bec0bf
--- /dev/null
+++ b/docs/en/guide/repl/demo/normal-lib.html
@@ -0,0 +1,30 @@
+
+ vuepress-theme-plume
+
+
+
+
+
+
+
+
+
diff --git a/docs/en/guide/repl/demo/normal.html b/docs/en/guide/repl/demo/normal.html
new file mode 100644
index 00000000..e9d897d8
--- /dev/null
+++ b/docs/en/guide/repl/demo/normal.html
@@ -0,0 +1,16 @@
+
+ vuepress-theme-plume
+
+
+
+
+
diff --git a/docs/en/guide/repl/frontend.md b/docs/en/guide/repl/frontend.md
new file mode 100644
index 00000000..5b614345
--- /dev/null
+++ b/docs/en/guide/repl/frontend.md
@@ -0,0 +1,793 @@
+---
+title: Frontend Demo
+icon: icon-park-outline:html-five
+createTime: 2025/01/08 21:34:26
+permalink: /en/guide/repl/frontend/
+---
+
+::: important Legacy Frontend Code Demo Deprecated - Please Migrate to New Solution
+
+The legacy solution was provided by [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/zh/).
+We appreciate its support for code demos in the past. The code demo functionality in
+`vuepress-plugin-md-enhance` will be migrated to [vuepress/ecosystem](https://github.com/vuepress/ecosystem). For details, please refer to [vuepress/ecosystem#293](https://github.com/vuepress/ecosystem/pull/293).
+
+:::
+
+::: details Why Redesign?
+
+Frontend code demos are a highly useful feature, but the legacy implementation did not align with actual usage scenario expectations.
+
+In the legacy solution, for example, `vue-demo` only supported simple Vue component demonstrations
+and could not directly import dependencies from the project. It relied on loading external scripts for
+additional functionality and did not provide full support for Vue SFC, being limited to simple code demonstrations.
+
+Furthermore, script code compilation occurred in the browser runtime. It required loading `babel` from a
+CDN first, then performing the transformation via `babel`, which introduced additional waiting time.
+Additionally, for internal enterprise projects within an intranet environment that cannot access external
+resources, the demos failed to display properly.
+
+In the new solution, all demo code is compiled and transformed during the Node.js runtime.
+Therefore, demo code can be displayed directly in the browser runtime without extra waiting time.
+Leveraging Node.js's powerful capabilities, it fully supports all features of Vue SFC and allows direct
+import of project dependencies, enabling richer demonstrations that better match real-world usage scenarios.
+:::
+
+## Overview
+
+This feature supports embedding code demonstration functionality within pages. A frontend code demo consists of two main areas:
+==Render Area== and ==Code Area==.
+
+The **Render Area** displays the execution results of the code, including UI rendering and interactions.
+The **Code Area** displays the source code and is collapsed by default.
+
+The theme provides support for three different types of frontend code demos:
+
+- ==Vue Component Demo==: Supports demonstrations of `Vue` components.
+Write your demo code as you would a `Vue` component.
+It can be used to demonstrate external dependencies like component libraries or `Composables API`.
+- ==Markdown Demo==: Supports demonstrations of `Markdown`.
+- ==Normal Code Demo==: Supports native `HTML` + `JS/TS` + `CSS/Less/Sass/Stylus` code demos. Write your demo code as you would a web page.
+
+The theme also provides two different methods for writing demo code:
+
+- Embed Demo Code Files:
+
+ ```md
+ @[demo type](url)
+ ```
+
+ Use simple embedding syntax to import demo code from files.
+
+- Inline Demo Code within Demo Container:
+
+ ````md
+ ::: demo type
+ ``` [lang]
+ code
+ ```
+ :::
+ ````
+
+ Write demo code directly within the markdown file, wrapped in a `demo` container.
+
+## Configuration
+
+Frontend code demos are powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
+
+Frontend code demos are disabled by default. You can enable them via configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ demo: true, // [!code ++]
+ },
+ })
+})
+```
+
+## Language Support
+
+Code demos support the following languages:
+
+- javascript
+- typescript
+- html
+- css
+- less
+- sass
+- stylus
+
+For CSS preprocessor languages, you need to install the corresponding preprocessor in your project, such as `less`, `sass`, or `stylus`.
+
+## Embed Syntax
+
+Different code demos use the same embed syntax, allowing you to quickly grasp their usage.
+
+```md
+
+@[demo](url)
+@[demo [type]](url)
+@[demo [type] title="" desc="" expanded code-setting=""](url)
+```
+
+`@[demo](url)` is a fixed syntax format.
+
+`[type]` indicates the type and supports three different values:
+
+- `normal`: Normal code demo type. This is the default type when the `[type]` parameter is omitted.
+- `vue`: Vue component demo type.
+- `markdown`: Markdown demo type.
+
+`url` indicates the path to the demo code file, which can be relative or absolute.
+
+- Relative paths start with `./` or `../` and are relative to the current markdown file's path.
+- Absolute paths start with `/` and are resolved from the [VuePress source directory path](../quick-start/project-structure.md#document-source-directory).
+
+```md
+
+@[demo](./demo/normal.html)
+@[demo normal](./demo/normal.html)
+@[demo](/.vuepress/demo/normal.html)
+
+
+@[demo vue](./demo/Counter.vue)
+@[demo vue](./demo/Counter.ts)
+@[demo](/.vuepress/demo/Counter.vue)
+
+
+@[demo markdown](./demo/example.md)
+@[demo markdown](/.vuepress/demo/example.md)
+```
+
+Additional parameters:
+
+- `title="xxx"`: Demo title.
+- `desc="xxx"`: Demo description.
+- `expanded`: Expand the code area.
+- `code-setting="xxx"`: Code settings. The value will be appended after ``` [lang]` and is used to add configurations to the code block.
+
+ `code-setting=":lines-number"` will add `:lines-number` after the code block, enabling line numbers.
+
+ `code-setting=":collapsed-lines=10"` will add `:collapsed-lines=10` after the code block,
+ causing the code block to be collapsed starting from line 10.
+
+```md
+@[demo vue expanded title="Title" desc="Description" code-setting=":collapsed-lines=10"](./demo/Counter.vue)
+```
+
+## Demo Container Inline Demo
+
+Demo container inline demos use the `demo` container to wrap the demo code, allowing quick writing of demo code within the markdown file:
+
+```md
+::: demo [type] title="" desc="" expanded
+
+:::
+```
+
+All parameters are the same as the `@[demo](url)` syntax.
+
+````md
+
+::: demo
+```html
+
+```
+``` js
+// js code
+```
+``` css
+/* css code */
+```
+:::
+
+
+::: demo vue
+``` vue
+
+```
+:::
+
+
+::: demo markdown
+``` md
+
+```
+:::
+````
+
+You can also wrap code blocks with the `::: code-tabs` container within the `::: demo` container for better interactive presentation.
+
+````md
+:::: demo
+::: code-tabs
+@tab HTML
+```html
+
+```
+@tab javascript
+``` js
+// js code
+```
+@tab css
+``` css
+/* css code */
+```
+:::
+:::::
+````
+
+When using TypeScript or `Less/Sass/Stylus`, simply modify the value of ` ``` [lang]`:
+
+````md
+:::: demo
+::: code-tabs
+@tab HTML
+```html
+
+```
+@tab Typescript
+``` ts
+// ts code
+```
+@tab Scss
+``` scss
+/* scss code */
+```
+:::
+:::::
+````
+
+## Vue Component Demo
+
+Vue component demo is a powerful feature with no restrictions on the demo code—it ultimately depends on the `bundler`'s support for Vue.
+You can directly import dependencies installed in your project within the demo code, just as you would when writing a component in a Vue project.
+
+Therefore, you can use it directly to provide demonstration examples for your component library or for your `Composables API`.
+
+### Embed Syntax
+
+You can directly embed a Vue component demo in a page using the following method:
+
+**Input:**
+
+```md
+@[demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"](./demo/Counter.vue)
+```
+
+::: details View `./demo/Counter.vue` Code
+
+@[code](./demo/Counter.vue)
+
+:::
+
+**Output:**
+
+@[demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"](./demo/Counter.vue)
+
+---
+
+You can also embed a Vue component written in `.ts`:
+
+**Input:**
+
+```md
+@[demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"](./demo/Counter.ts)
+```
+
+::: details View `./demo/Counter.ts` Code
+
+::: code-tabs
+@tab Counter.ts
+@[code](./demo/Counter.ts)
+@tab Counter.module.css
+@[code](./demo/Counter.module.css)
+:::
+
+**Output:**
+
+@[demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"](./demo/Counter.ts)
+
+:::info For components written in `.js/.ts`, use `CSS Module` to write styles for style isolation.
+:::
+
+---
+You can import external dependencies in the demo code.
+Example using `useToggle()` from `@vueuse/core`:
+
+**Input:**
+
+```md
+@[demo vue title="useToggle" desc="useToggle() Demo"](./demo/Toggle.vue)
+```
+
+::: details ./demo/Toggle.vue
+@[code](./demo/Toggle.vue)
+:::
+
+**Output:**
+
+@[demo vue title="useToggle" desc="useToggle() Demo"](./demo/Toggle.vue)
+
+### Container Syntax
+
+Using the `demo` container to wrap demo code in a markdown file allows for quick demo code writing:
+
+**Input:**
+
+:::: details Expand to view full code
+
+````md
+::: demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"
+```vue
+
+
+
+
+ Counter: {{ count }}
+
+
+
+
+
+```
+:::
+````
+
+::::
+
+**Output:**
+
+::: demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"
+
+```vue
+
+
+
+
+ Counter: {{ count }}
+
+
+
+
+
+```
+
+:::
+
+:::::: warning
+The Vue demo container syntax also supports embedding demo code using the `.js/ts + css` approach,
+but this is not recommended by the theme. Styles cannot be isolated, which may lead to style pollution.
+
+::::: details Reference Example
+
+````md
+:::: demo vue title="Title" desc="Description"
+::: code-tabs
+@tab Counter.ts
+```ts
+import { defineComponent, ref } from 'vue'
+
+export default defineComponent({
+ // code
+})
+```
+@tab Counter.css
+```css
+/* css code */
+```
+:::
+::::
+````
+
+:::::
+::::::
+
+## Normal Code Demo
+
+Normal code demos support `html`, `css/less/sass/stylus`, and `js/ts` languages.
+
+They are suitable for relatively simple code demonstrations, such as a style rendering effect, an interaction effect, or a functionality.
+
+Normal code demos also support jumping to `CodePen` and `jsFiddle` for viewing.
+
+Additionally, they support importing third-party libraries via external links, such as `jQuery` or `dayjs`.
+
+::: warning Overly complex demonstrations are not recommended.
+:::
+
+### Embed Syntax
+
+When using the embed syntax, use `.html` as the file suffix for the imported demo code file.
+In the `.html` file, you can write the demo code as you would an HTML page:
+
+```html
+
+
+ Demo Content
+
+
+
+
+
+
+
+
+
+
+```
+
+Each section is optional. However, note that multiple identical sections are not supported. The order of sections does not matter.
+Content outside of ``.
+
+For example, loading `jQuery` and `normalize.css`:
+
+```html
+xxxx
+
+
+```
+
+---
+
+A conventional example:
+
+**Input:**
+
+```md
+@[demo title="Example" desc="This is a conventional demo"](./demo/normal.html)
+```
+
+::: details View `./demo/normal.html` Code
+@[code](./demo/normal.html)
+:::
+
+**Output:**
+
+@[demo title="Example" desc="This is a conventional demo"](./demo/normal.html)
+
+---
+
+Example introducing `jQuery`, `dayjs`, and `normalize.css`:
+
+**Input:**
+
+```md
+@[demo title="Example" desc="This is a conventional demo"](./demo/normal-lib.html)
+```
+
+::: details View `./demo/normal-lib.html` Code
+@[code](./demo/normal-lib.html)
+:::
+
+**Output:**
+
+@[demo title="Example" desc="This is a conventional demo"](./demo/normal-lib.html)
+
+### Container Syntax
+
+Using the demo container to wrap demo code in a markdown file allows for quick demo code writing:
+
+:::: details Expand to view full example code
+
+````md
+::: demo title="Example" desc="Description" expanded
+```json
+{
+ "jsLib": [],
+ "cssLib": []
+}
+```
+
+```html
+
+```
+
+```js
+// js code
+```
+
+```css
+/* css code */
+```
+:::
+```
+::::
+
+You can also wrap `::: code-tabs` within `::: demo` for better code block presentation:
+
+::::: details Expand to view full example code
+
+````md
+:::: demo title="Example" desc="Description" expanded
+```json
+{
+ "jsLib": [],
+ "cssLib": []
+}
+```
+::: code-tabs
+@tab HTML
+```html
+
+```
+@tab Javascript
+```js
+// js code
+```
+@tab CSS
+```css
+/* css code */
+```
+:::
+::::
+```
+:::::
+
+---
+
+A conventional container example:
+
+**Input:**
+
+::::: details Expand to view full example code
+
+````md
+:::: demo title="Conventional Example" desc="A conventional example"
+::: code-tabs
+@tab HTML
+```html
+
+ vuepress-theme-plume
+
+```
+@tab Javascript
+```js
+const a = 'So Awesome!'
+const app = document.querySelector('#app')
+app.appendChild(document.createElement('small')).textContent = a
+```
+@tab CSS
+```css
+#app {
+ font-size: 2em;
+ text-align: center;
+}
+```
+:::
+::::
+````
+
+:::::
+
+**Output:**
+
+:::: demo title="Conventional Example" desc="A conventional example"
+
+::: code-tabs
+@tab HTML
+
+```html
+
+ vuepress-theme-plume
+
+```
+
+@tab Javascript
+
+```js
+const a = 'So Awesome!'
+const app = document.querySelector('#app')
+app.appendChild(document.createElement('small')).textContent = a
+```
+
+@tab CSS
+
+```css
+#app {
+ font-size: 2em;
+ text-align: center;
+}
+```
+
+:::
+::::
+
+---
+
+Example introducing jQuery, dayjs, and normalize.css:
+
+**Input:**
+
+::::: details Expand to view full example code
+
+````md
+:::: demo title="Conventional Example" desc="A conventional example"
+```json
+{
+ "jsLib": [
+ "https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js",
+ "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js"
+ ],
+ "cssLib": ["https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css"]
+}
+```
+::: code-tabs
+@tab HTML
+```html
+
+ vuepress-theme-plume
+
+
+
+```
+@tab Javascript
+```js
+$('#message').text('So Awesome!')
+const datetime = $('#datetime')
+setInterval(() => {
+ datetime.text(dayjs().format('YYYY-MM-DD HH:mm:ss'))
+}, 1000)
+```
+@tab CSS
+```css
+#app {
+ font-size: 2em;
+ text-align: center;
+}
+```
+:::
+::::
+````
+
+:::::
+
+**Output:**
+
+:::: demo title="Conventional Example" desc="A conventional example"
+
+```json
+{
+ "jsLib": [
+ "https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js",
+ "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js"
+ ],
+ "cssLib": ["https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css"]
+}
+```
+
+::: code-tabs
+@tab HTML
+
+```html
+
+ vuepress-theme-plume
+
+
+
+```
+
+@tab Javascript
+
+```js
+$('#message').text('So Awesome!')
+const datetime = $('#datetime')
+setInterval(() => {
+ datetime.text(dayjs().format('YYYY-MM-DD HH:mm:ss'))
+}, 1000)
+```
+
+@tab CSS
+
+```css
+#app {
+ font-size: 2em;
+ text-align: center;
+}
+```
+
+:::
+::::
+
+## Markdown Demo
+
+Demonstrate markdown source code and rendering results within a page.
+
+### Embed Syntax
+
+**Input:**
+
+```md
+@[demo markdown title="Bulletin Board" desc="Bulletin Board Code Example"](/.vuepress/bulletin.md)
+```
+
+::: details Expand to view `/.vuepress/bulletin.md` Code
+@[code](../../../.vuepress/bulletin.md)
+:::
+
+**Output:**
+
+@[demo markdown title="Bulletin Board" desc="Bulletin Board Code Example"](/.vuepress/bulletin.md)
+
+### Container Syntax
+
+**Input:**
+
+:::::: details Expand to view full code
+
+````md
+:::: demo markdown title="Bulletin Board" desc="Bulletin Board Code Example"
+```md
+::: center
+
+**QQ Group:** [792882761](https://qm.qq.com/q/FbPPoOIscE)
+
+{width="618" height="616" style="width: 200px"}
+
+If you encounter any issues during use, please feel free to provide feedback via [issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new/choose). You are also welcome to join our QQ group for discussion.
+
+:::
+```
+::::
+````
+
+::::::
+
+**Output:**
+
+:::: demo markdown title="Bulletin Board" desc="Bulletin Board Code Example"
+
+```md
+::: center
+
+**QQ Group:** [792882761](https://qm.qq.com/q/FbPPoOIscE)
+
+{width="618" height="616" style="width: 200px"}
+
+If you encounter any issues during use, please feel free to provide feedback via [issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new/choose). You are also welcome to join our QQ group for discussion.
+
+:::
+```
+
+::::
diff --git a/docs/en/guide/repl/golang.md b/docs/en/guide/repl/golang.md
new file mode 100644
index 00000000..f4bb55af
--- /dev/null
+++ b/docs/en/guide/repl/golang.md
@@ -0,0 +1,265 @@
+---
+title: Golang
+icon: devicon-plain:go
+createTime: 2025/10/08 09:44:30
+permalink: /en/guide/repl/golang/
+---
+
+## Overview
+
+The theme provides Golang code demonstration functionality, supporting online execution of Go code.
+
+::: important
+This functionality works by submitting code to a server for compilation and execution.
+
+Therefore, please do not use this feature to execute overly complex code, and avoid making execution requests too frequently.
+:::
+
+## Configuration
+
+This feature is disabled by default. You can enable it through configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ repl: {
+ go: true,
+ },
+ },
+ })
+})
+```
+
+## Usage
+
+Use the `::: go-repl` container syntax to wrap Go code blocks. The theme will detect the code blocks and add execution buttons.
+
+### Read-only Code Demo
+
+Golang code demos are read-only by default and cannot be edited.
+
+````md
+::: go-repl title="Custom Title"
+```go
+// your go code
+```
+:::
+````
+
+### Editable Code Demo
+
+For online editing and execution, wrap the code block in the `::: go-repl editable` container syntax.
+
+````md
+::: go-repl editable title="Custom Title"
+```go
+// your go code
+```
+:::
+````
+
+## Examples
+
+### Print Content
+
+**Input:**
+
+````md
+:::go-repl
+```go
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ fmt.Println("Hello World")
+}
+```
+:::
+````
+
+**Output:**
+:::go-repl
+
+```go
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ fmt.Println("Hello World")
+}
+```
+
+:::
+
+### Editable Code Demo
+
+**Input:**
+
+````md
+:::go-repl editable
+```go
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ fmt.Println("Hello World")
+}
+```
+:::
+````
+
+**Output:**
+
+:::go-repl editable
+
+```go
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ fmt.Println("Hello World")
+}
+```
+
+:::
+
+### Loop with Random Delay Printing
+
+**Input:**
+
+````md
+:::go-repl
+```go
+package main
+
+import (
+ "fmt"
+ "math/rand"
+ "time"
+)
+
+func main() {
+ for i := 0; i < 10; i++ {
+ dur := time.Duration(rand.Intn(1000)) * time.Millisecond
+ fmt.Printf("Sleeping for %v\n", dur)
+ // Sleep for a random duration between 0-1000ms
+ time.Sleep(dur)
+ }
+ fmt.Println("Done!")
+}
+```
+:::
+````
+
+**Output:**
+
+:::go-repl
+
+```go
+package main
+
+import (
+ "fmt"
+ "math/rand"
+ "time"
+)
+
+func main() {
+ for i := 0; i < 10; i++ {
+ dur := time.Duration(rand.Intn(1000)) * time.Millisecond
+ fmt.Printf("Sleeping for %v\n", dur)
+ // Sleep for a random duration between 0-1000ms
+ time.Sleep(dur)
+ }
+ fmt.Println("Done!")
+}
+```
+
+:::
+
+### Network Request
+
+::: go-repl
+
+```go
+package main
+
+import (
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "os"
+)
+
+func main() {
+ http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprint(w, "Hello, playground")
+ })
+
+ log.Println("Starting server...")
+ l, err := net.Listen("tcp", "localhost:8080")
+ if err != nil {
+ log.Fatal(err)
+ }
+ go func() {
+ log.Fatal(http.Serve(l, nil))
+ }()
+
+ log.Println("Sending request...")
+ res, err := http.Get("http://localhost:8080/hello")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ log.Println("Reading response...")
+ if _, err := io.Copy(os.Stdout, res.Body); err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
+:::
+
+### Multiple Files
+
+::: go-repl
+
+```go{10-12}
+package main
+
+import (
+ "play.ground/foo"
+)
+
+func main() {
+ foo.Bar()
+}
+-- go.mod --
+module play.ground
+-- foo/foo.go --
+package foo
+
+import "fmt"
+
+func Bar() {
+ fmt.Println("This function lives in an another file!")
+}
+
+```
+
+:::
diff --git a/docs/en/guide/repl/jsFiddle.md b/docs/en/guide/repl/jsFiddle.md
new file mode 100644
index 00000000..0a78d1b2
--- /dev/null
+++ b/docs/en/guide/repl/jsFiddle.md
@@ -0,0 +1,65 @@
+---
+title: Js Fiddle
+icon: bxl:jsfiddle
+createTime: 2025/10/08 10:42:21
+permalink: /en/guide/code/jsfiddle/
+---
+
+The theme supports embedding [JS Fiddle](https://jsfiddle.net/) in Markdown files.
+
+## Configuration
+
+This feature is disabled by default. You can enable it in the configuration file.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ jsfiddle: true, // [!code highlight]
+ },
+ })
+})
+```
+
+## Syntax
+
+### Basic Syntax
+
+```md
+@[jsfiddle](user/id)
+```
+
+### Extended Options
+
+```md
+@[jsfiddle theme="dark" tab="js,css,html,result" height="500px"](user/id)
+```
+
+- `user`: Username
+- `id`: JS Fiddle identifier
+- `theme`: Theme mode, options: `"light" | "dark"`
+- `tab`: Active tabs, options: `"js" | "css" | "html" | "result"`, multiple values separated by `","`.
+ The order determines tab arrangement, defaults to `js,css,html,result`
+- `height`: Container height
+
+## Examples
+
+Input:
+
+```md
+@[jsfiddle](pengzhanbo/1xbwz2p9)
+```
+
+Output:
+
+@[jsfiddle](pengzhanbo/1xbwz2p9)
+
+Input:
+
+```md
+@[jsfiddle tab="result,js,css,html"](pengzhanbo/1xbwz2p9)
+```
+
+Output:
+
+@[jsfiddle tab="result,js,css,html"](pengzhanbo/1xbwz2p9)
diff --git a/docs/en/guide/repl/kotlin.md b/docs/en/guide/repl/kotlin.md
new file mode 100644
index 00000000..25823824
--- /dev/null
+++ b/docs/en/guide/repl/kotlin.md
@@ -0,0 +1,142 @@
+---
+title: Kotlin
+icon: tabler:brand-kotlin
+createTime: 2024/04/22 09:44:37
+permalink: /en/guide/repl/kotlin/
+---
+
+## 概述
+
+主题提供了 Kotlin 代码演示,支持 在线运行 Kotlin 代码。
+
+::: important
+该功能通过将 代码提交到 服务器 进行 编译并执行,且一次只能提交单个代码文件。
+
+因此,请不要使用此功能 执行 过于复杂的代码,也不要过于频繁的进行执行请求。
+:::
+
+## 配置
+
+该功能默认不启用,你可以通过配置来启用它。
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ repl: {
+ kotlin: true,
+ },
+ },
+ })
+})
+```
+
+## 使用
+
+使用 `::: kotlin-repl` 容器语法 将 kotlin 代码块包裹起来。主题会检查代码块并添加执行按钮。
+
+### 只读代码演示
+
+kotlin 代码演示默认是只读的,不可编辑。
+
+````md
+::: kotlin-repl title="自定义标题"
+```kotlin
+// your kotlin code
+```
+:::
+````
+
+### 可编辑代码演示
+
+如果需要在线编辑并执行,需要将代码块包裹在 `::: kotlin-repl editable` 容器语法中
+
+````md
+::: kotlin-repl editable title="自定义标题"
+```kotlin
+// your kotlin code
+```
+:::
+````
+
+## 示例
+
+### 打印内容
+
+**输入:**
+
+````md
+::: kotlin-repl
+```kotlin
+class Contact(val id: Int, var email: String)
+
+fun main(args: Array) {
+ val contact = Contact(1, "mary@gmail.com")
+ println(contact.id)
+}
+```
+:::
+````
+
+**输出:**
+
+::: kotlin-repl
+
+```kotlin
+class Contact(val id: Int, var email: String)
+
+fun main(args: Array) {
+ val contact = Contact(1, "mary@gmail.com")
+ println(contact.id)
+}
+```
+
+:::
+
+### 运算
+
+::: kotlin-repl
+
+```kotlin
+fun mul(a: Int, b: Int): Int {
+ return a * b
+}
+
+fun main(args: Array) {
+ print(mul(-2, 4))
+}
+```
+
+:::
+
+### 可编辑代码演示
+
+**输入:**
+
+````md
+::: kotlin-repl editable
+```kotlin
+class Contact(val id: Int, var email: String)
+
+fun main(args: Array) {
+ val contact = Contact(1, "mary@gmail.com")
+ println(contact.id)
+}
+```
+:::
+````
+
+**输出:**
+
+::: kotlin-repl editable
+
+```kotlin
+class Contact(val id: Int, var email: String)
+
+fun main(args: Array) {
+ val contact = Contact(1, "mary@gmail.com")
+ println(contact.id)
+}
+```
+
+:::
diff --git a/docs/en/guide/repl/python.md b/docs/en/guide/repl/python.md
new file mode 100644
index 00000000..4ff6b497
--- /dev/null
+++ b/docs/en/guide/repl/python.md
@@ -0,0 +1,153 @@
+---
+title: Python
+icon: devicon-plain:python
+createTime: 2025/10/08 21:53:58
+permalink: /en/guide/repl/python/
+---
+
+## Overview
+
+The theme provides Python code demonstration functionality, supporting online execution of Python code.
+
+## Installation
+
+Online Python execution is powered by [pyodide](https://pyodide.org/en/latest/). Please ensure `pyodide` is available before use.
+
+::: npm-to
+
+```sh
+npm install pyodide
+```
+
+:::
+
+## Configuration
+
+This feature is disabled by default. You can enable it through configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ repl: {
+ python: true,
+ },
+ },
+ })
+})
+```
+
+## Usage
+
+Use the `::: python-repl` container syntax to wrap Python code blocks. The theme will detect the code blocks and add execution buttons.
+
+::: warning The support for python-repl is limited and currently only supports:
+
+- Execution of basic Python syntax (no backend dependencies)
+- Import of basic Python libraries
+- Standard output stream (stdout) capture
+- If the last statement is an expression (and the code doesn't end with a semicolon), the expression value will be returned
+- Exception message output
+
+:::
+
+### Read-only Code Demo
+
+Python code demos are read-only by default and cannot be edited.
+
+````md
+::: python-repl title="Custom Title"
+```python
+# your python code
+```
+:::
+````
+
+### Editable Code Demo
+
+For online editing and execution, wrap the code block in the `::: python-repl editable` container syntax.
+
+````md
+::: python-repl editable title="Custom Title"
+```python
+# your python code
+```
+:::
+````
+
+## Examples
+
+### Print Content
+
+**Input:**
+
+````md
+::: python-repl
+```python
+def hello_world():
+ return 'Hello World!'
+
+hello_world()
+```
+:::
+````
+
+**Output:**
+
+::: python-repl
+
+```python
+def hello_world():
+ print('Hello World!')
+
+hello_world()
+```
+
+:::
+
+### Arithmetic Operations
+
+::: python-repl
+
+```python
+def mul(a: int, b: int) -> int:
+ return a * b
+
+print(mul(-2, 4))
+```
+
+:::
+
+### Editable Code Demo
+
+**Input:**
+
+````md
+::: python-repl editable
+```python
+class Contact:
+ def __init__(self, id: int, email: str):
+ self.id = id
+ self.email = email
+
+contact = Contact(1, 'mary@gmail.com')
+print(contact.id)
+```
+:::
+````
+
+**Output:**
+
+::: python-repl editable
+
+```python
+class Contact:
+ def __init__(self, id: int, email: str):
+ self.id = id
+ self.email = email
+
+contact = Contact(1, 'mary@gmail.com')
+print(contact.id)
+```
+
+:::
diff --git a/docs/en/guide/repl/replit.md b/docs/en/guide/repl/replit.md
new file mode 100644
index 00000000..ee942029
--- /dev/null
+++ b/docs/en/guide/repl/replit.md
@@ -0,0 +1,58 @@
+---
+title: Replit
+icon: simple-icons:replit
+createTime: 2025/10/08 10:42:05
+permalink: /en/guide/code/replit/
+---
+
+
+
+~~The theme supports embedding [Replit](https://replit.com/) in Markdown files.~~
+
+## Configuration
+
+This feature is disabled by default. You can enable it in the configuration file.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ replit: true, // [!code ++]
+ },
+ })
+})
+```
+
+## Syntax
+
+Basic syntax:
+
+```md
+@[replit](user/repl-name)
+```
+
+Extended options:
+
+```md
+@[replit title="" width="100%" height="450px" theme="dark"](user/repl-name#filepath)
+```
+
+- `title`: Title
+- `width`: Container width
+- `height`: Container height
+- `theme`: Theme, options: `dark` and `light`
+- `user`: Replit username
+- `repl-name`: Replit repl name
+- `filepath`: Default file path to open in Replit
+
+## Examples
+
+Input:
+
+```md
+@[replit](@TechPandaPro/Cursor-Hangout#package.json)
+````
+
+Output:
+
+@[replit](@TechPandaPro/Cursor-Hangout#package.json)
diff --git a/docs/en/guide/repl/rust.md b/docs/en/guide/repl/rust.md
new file mode 100644
index 00000000..76d237f4
--- /dev/null
+++ b/docs/en/guide/repl/rust.md
@@ -0,0 +1,178 @@
+---
+title: Rust
+icon: simple-icons:rust
+createTime: 2025/10/08 09:44:43
+permalink: /en/guide/repl/rust/
+---
+
+## Overview
+
+The theme provides Rust code demonstration functionality, supporting online execution of Rust code.
+
+::: important
+This functionality works by submitting code to a server for compilation and execution, and only a single code file can be submitted at a time.
+
+Therefore, please do not use this feature to execute overly complex code, and avoid making execution requests too frequently.
+:::
+
+## Configuration
+
+This feature is disabled by default. You can enable it through configuration.
+
+```ts title=".vuepress/config.ts"
+export default defineUserConfig({
+ theme: plumeTheme({
+ markdown: {
+ repl: {
+ rust: true,
+ },
+ },
+ })
+})
+```
+
+## Usage
+
+Use the `::: rust-repl` container syntax to wrap Rust code blocks. The theme will detect the code blocks and add execution buttons.
+
+### Read-only Code Demo
+
+Rust code demos are read-only by default and cannot be edited.
+
+````md
+::: rust-repl title="Custom Title"
+```rust
+// your rust code
+```
+:::
+````
+
+### Editable Code Demo
+
+For online editing and execution, wrap the code block in the `::: rust-repl editable` container syntax.
+
+````md
+::: rust-repl editable title="Custom Title"
+```rust
+// your rust code
+```
+:::
+````
+
+## Examples
+
+### Print Content
+
+**Input:**
+
+````md
+::: rust-repl title="Print Content"
+```rust
+fn main() {
+ println!("Hello, world!");
+}
+```
+:::
+````
+
+**Output:**
+
+::: rust-repl title="Print Content"
+
+```rust
+fn main() {
+ println!("Hello, world!");
+}
+```
+
+:::
+
+Click the Execute button to run the code.
+
+### Print Error Information
+
+**Input:**
+
+````md
+::: rust-repl
+```rust
+fn main() {
+ printlnl!("Hello, world!");
+}
+```
+:::
+````
+
+**Output:**
+
+::: rust-repl
+
+```rust
+fn main() {
+ printlnl!("Hello, world!");
+}
+```
+
+:::
+
+### Wait for Child Process Execution
+
+**Input:**
+
+````md
+::: rust-repl
+```rust
+use std::process::Command;
+
+fn main() {
+ let mut child = Command::new("sleep").arg("5").spawn().unwrap();
+ let _result = child.wait().unwrap();
+
+ println!("reached end of main");
+}
+```
+:::
+````
+
+**Output:**
+
+::: rust-repl
+
+```rust
+use std::process::Command;
+
+fn main() {
+ let mut child = Command::new("sleep").arg("5").spawn().unwrap();
+ let _result = child.wait().unwrap();
+
+ println!("reached end of main");
+}
+```
+
+:::
+
+### Editable Demo
+
+**Input:**
+
+````md
+::: rust-repl editable
+```rust
+fn main() {
+ println!("Hello, world!");
+}
+```
+:::
+````
+
+**Output:**
+
+::: rust-repl editable
+
+```rust
+fn main() {
+ println!("Hello, world!");
+}
+```
+
+:::
diff --git a/docs/en/questions.md b/docs/en/questions.md
new file mode 100644
index 00000000..3c36151e
--- /dev/null
+++ b/docs/en/questions.md
@@ -0,0 +1,87 @@
+---
+title: Frequently Asked Questions
+createTime: 2025/10/08 08:47:36
+permalink: /en/faq/
+---
+
+This document primarily covers common issues and solutions you might encounter while using the theme.
+
+If you encounter any problems, you can first check the content below to see if there are related issues and solutions.
+
+If you don't find what you're looking for, you can start a discussion with us via GitHub [Discussions](https://github.com/pengzhanbo/vuepress-theme-plume/discussions/new?category=q-a).
+
+If you're certain that there's indeed an issue, please
+[Open an issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new?assignees=pengzhanbo&labels=bug&projects=&template=bug-report.zh-CN.yml&title=%5BBug%5D)
+on GitHub. In the issue, describe the specific details of the problem and, if necessary,
+try to provide a minimal reproduction package. We will address it as soon as possible.
+
+::: details What should I pay attention to when starting a discussion or raising an issue?
+We welcome you to start discussions or ask any questions, regardless of how simple they may seem.
+Asking questions actively is good. However, please ensure the following three points:
+
+1. You have already attempted to search the relevant documentation.
+2. You provide a detailed description in your discussion.
+3. You are not asking questions unrelated to VuePress, nor are you seeking technical support for custom implementations.
+
+ We will not answer questions like "How can I use a specific feature of the theme in isolation in my
+ own project?" or "How can I implement a specific feature of the theme in my own project?".
+:::
+
+## How to update the theme?
+
+You can update the theme using the `vp-update` command.
+
+`vp-update` is a CLI tool maintained by the VuePress team. It helps you check for the latest versions of
+VuePress-related themes, plugins, etc., within your project and automatically installs the dependencies for you.
+
+Copy and run the following command in your project:
+
+::: npm-to
+
+```sh
+npx vp-update
+```
+
+:::
+
+## Why don't new features take effect after updating the theme version?
+
+Because VuePress takes a long time to fully compile all `markdown` files in the source directory when
+starting the dev server, the theme implements caching for `markdown` compilation to improve startup speed.
+After updating the theme and restarting the dev server, if the `markdown` files in the source directory
+haven't changed, the compilation is skipped and the cache is used directly. This can cause new features related to markdown not to take effect.
+
+**Simply delete the cache files and restart**:
+
+1. Method 1: Directly delete the `.vuepress/.cache` directory.
+2. Method 2: Add the `--clean-cache` parameter when starting the dev server command:
+
+ ```sh
+ vuepress dev docs --clean-cache
+ ```
+
+## Why don't changes to theme plugin configurations take effect?
+
+This issue commonly occurs when modifying configurations for `plugins.markdownEnhance`,
+`plugins.markdownPower`, `plugins.markdownImage`, and `plugins.markdownMath`. The reason is the same as
+[Why don't new features take effect after updating the theme version?](#why-dont-new-features-take-effect-after-updating-the-theme-version).
+Therefore,
+
+**Simply delete the cache files and restart**:
+
+1. Method 1: Directly delete the `.vuepress/.cache` directory.
+2. Method 2: Add the `--clean-cache` parameter when starting the dev server command:
+
+ ```sh
+ vuepress dev docs --clean-cache
+ ```
+
+## After updating dependencies, restart prompts `import "xxxx" not exist`
+
+Sometimes, after updating the theme and related dependencies, there might be an issue where the package
+manager fails to correctly generate the new dependency tree, leading to errors
+like "module not found" when importing certain dependencies. At this point, the dependency lock
+files (like `package-lock.json` or `pnpm-lock.yaml`) might be corrupted.
+
+Please directly delete the dependency lock files (`package-lock.json`, `pnpm-lock.yaml`, etc.)
+and the `node_modules` directory, then reinstall the dependencies.
diff --git a/docs/en/tools/README.md b/docs/en/tools/README.md
new file mode 100644
index 00000000..71a4d644
--- /dev/null
+++ b/docs/en/tools/README.md
@@ -0,0 +1,33 @@
+---
+title: Theme Toolkit
+createTime: 2025/10/09 16:27:03
+permalink: /en/tools/
+---
+
+## Overview
+
+The Theme Toolkit is designed to lower the barrier to entry when using some of the features provided by this theme.
+
+## Tool List
+
+
+
+
+
+
+
+## Third-party Tools
+
+
+
+Uses **Unsplash** images to help generate high-quality blog covers.
+
+
+
+
+Uses AI to help generate theme colors and color schemes for websites.
+
+
+
+When you want to add personalized features to your site but face technical limitations, this tool can help you generate code quickly.
+
diff --git a/docs/en/tools/caniuse.md b/docs/en/tools/caniuse.md
new file mode 100644
index 00000000..67e3dbdb
--- /dev/null
+++ b/docs/en/tools/caniuse.md
@@ -0,0 +1,28 @@
+---
+title: CanIUse Feature Search
+icon: fa-brands:css3
+createTime: 2025/10/09 12:41:26
+permalink: /en/tools/caniuse/
+readingTime: false
+editLink: false
+---
+
+In addition to using this tool, you can also directly visit [caniuse.com/](https://caniuse.com/) to search for features.
+On the results page, click the `#` button on the left, and the browser's address bar will update automatically. For example:
+
+Search for `@property`, click `#`, and it will navigate to `https://caniuse.com/mdn-css_at-rules_property`.
+You can directly copy `mdn-css_at-rules_property` and paste it into your markdown file:
+
+```md
+@[caniuse](mdn-css_at-rules_property)
+```
+
+## Tool
+
+This tool helps search for features in caniuse and generates the corresponding caniuse markdown code.
+
+
+
+
diff --git a/docs/en/tools/custom-theme.md b/docs/en/tools/custom-theme.md
new file mode 100644
index 00000000..d0d64100
--- /dev/null
+++ b/docs/en/tools/custom-theme.md
@@ -0,0 +1,24 @@
+---
+title: Theme Colors Tool
+icon: unjs:theme-colors
+createTime: 2025/10/09 13:58:29
+permalink: /en/tools/theme-colors/
+readingTime: false
+editLink: false
+contributors: false
+lastUpdated: false
+---
+
+::: tip
+This tool helps you quickly create custom theme colors. Click the buttons below to select and configure your desired theme colors.
+
+Modifications are automatically applied to the current site, allowing you to navigate to any page and preview the changes.
+
+This tool provides basic theme color creation. For more advanced theme color configuration, please refer to [styles/vars.css](https://github.com/pengzhanbo/vuepress-theme-plume/blob/main/theme/src/client/styles/vars.css)
+:::
+
+
+
+
diff --git a/docs/en/tools/home-hero-tint-plate.md b/docs/en/tools/home-hero-tint-plate.md
new file mode 100644
index 00000000..aaeecf92
--- /dev/null
+++ b/docs/en/tools/home-hero-tint-plate.md
@@ -0,0 +1,17 @@
+---
+title: Homepage Hero Tint Plate
+icon: icon-park-outline:hand-painted-plate
+createTime: 2025/10/09 20:17:42
+permalink: /en/tools/home-hero-tint-plate/
+readingTime: false
+editLink: false
+---
+
+To provide a more intuitive and convenient way to configure the background tint plate for the homepage
+Hero section, the theme offers a tint plate configuration tool that helps generate corresponding configuration information.
+
+
+
+
diff --git a/docs/guide/custom/slots.md b/docs/guide/custom/slots.md
index 9e1c108a..1e13d5dc 100644
--- a/docs/guide/custom/slots.md
+++ b/docs/guide/custom/slots.md
@@ -120,38 +120,38 @@ export default defineClientConfig({
- `page-top`
- `page-bottom`
-- 在 博客页 中 (包括 文章列表页、标签页、归档页 均适用):
+- 在 post 集合相关页面 中 (包括 文章列表页、标签页、归档页 均适用):
- - `blog-top`
- - `blog-bottom`
- - `blog-aside-top`
- - `blog-aside-bottom`
- - `blog-extract-before`
- - `blog-extract-after`
+ - `posts-top`
+ - `posts-bottom`
+ - `posts-aside-top`
+ - `posts-aside-bottom`
+ - `posts-extract-before`
+ - `posts-extract-after`
-- 在 博客文章列表页 中:
+- 在 文章列表页 中:
- - `blog-post-list-before`
- - `blog-post-list-after`
- - `blog-post-list-pagination-after`
+ - `posts-post-list-before`
+ - `posts-post-list-after`
+ - `posts-post-list-pagination-after`
-- 在 博客标签页 中:
+- 在 标签页 中:
- - `blog-tags-before`
- - `blog-tags-title-after`
- - `blog-tags-content-before`
- - `blog-tags-after`
+ - `posts-tags-before`
+ - `posts-tags-title-after`
+ - `posts-tags-content-before`
+ - `posts-tags-after`
-- 在 博客归档页 中:
+- 在 归档页 中:
- - `blog-archives-before`
- - `blog-archives-after`
+ - `posts-archives-before`
+ - `posts-archives-after`
-- 在 博客分类页 中:
+- 在 分类页 中:
- - `blog-categories-before`
- - `blog-categories-content-before`
- - `blog-categories-after`
+ - `posts-categories-before`
+ - `posts-categories-content-before`
+ - `posts-categories-after`
### ` ` 插槽
diff --git a/docs/guide/features/component.md b/docs/guide/features/component.md
deleted file mode 100644
index 1d41e9f7..00000000
--- a/docs/guide/features/component.md
+++ /dev/null
@@ -1,379 +0,0 @@
----
-title: 组件
-icon: radix-icons:component-2
-createTime: 2024/03/06 09:42:42
-outline: 2
-permalink: /guide/features/component/
----
-
-## 概述
-
-VuePress 支持在 Markdown 文件中使用 组件。
-
-主题提供了一些具有通用性的组件,可以在任何地方使用。
-
-## 徽章
-
-使用 `` 组件来显示 行内信息,如状态或标签。
-
-将你想显示的内容传递给 `` 组件的 `text` 属性。
-
-### Props
-
-| 名称 | 类型 | 默认值 | 说明 |
-| ------------ | -------- | ------------------ | ------------------------------------------------------------------ |
-| type | `string` | `'tip'` | 类型,内置值: `'info' \| 'tip' \| 'warning' \| 'danger'`,允许自定义 |
-| text | `string` | `''` | 文本 |
-| color | `string` | `''` | 文本颜色 |
-| bg-color | `string` | `''` | 背景颜色 |
-| border-color | `string` | `'transparent'` | 边框颜色 |
-
-**输入:**
-
-```md :no-line-numbers
-- VuePress -
-- VuePress -
-- VuePress -
-- VuePress -
-- VuePress -
-```
-
-**输出:**
-
-- VuePress -
-- VuePress -
-- VuePress -
-- VuePress -
-- VuePress -
-
-使用自定义`type`,可以实现更丰富的表现。
-
-**输入:**
-
-1. 在主题任意样式文件中,添加预定的样式:
-
-```css
-/* 浅色主题 */
-.vp-badge.important {
- color: #cccccc;
- background-color: #f40f40;
- border-color: transparent;
-}
-
-/* 深色主题 */
-[data-theme="dark"] .vp-badge.important {
- color: #f40f40;
- background-color: #ffffff;
- border-color: transparent;
-}
-
-/**
- important 为自定义 type 类型
-*/
-```
-
-2. 使用自定义`type`:
-
-```md :no-line-numbers
-- VuePress -
-```
-
-**输出:**
-
-- VuePress -
-
-## 图标
-
-支持 iconify 所有图标,通过 icon name 加载图标。
-
-可在 [iconify search](https://icon-sets.iconify.design/) 搜索图标使用。
-
-### Props
-
-| 名称 | 类型 | 默认值 | 说明 |
-| ----- | ------ | ---------------- | -------- |
-| name | string | `''` | 图标名 |
-| color | string | `'currentcolor'` | 图标颜色 |
-| size | string | `'1em'` | 图标大小 |
-
-**输入:**
-
-```md :no-line-numbers
-- home -
-- vscode -
-- twitter -
-```
-
-**输出:**
-
-- home -
-- vscode -
-- twitter -
-
-## “隐秘”文本
-
-使用 `` 组件显示 [“隐秘”文本](../markdown/plot.md) ,能够更灵活的控制行为。
-
-该组件默认不启用,你需要在 theme 配置中启用。
-
-```ts title=".vuepress/config.ts"
-export default defineUserConfig({
- theme: plumeTheme({
- plugins: {
- markdownPower: {
- plot: true,
- },
- }
- })
-})
-```
-
-### Props
-
-| 名称 | 类型 | 默认值 | 说明 |
-| ------- | ------------------------------------------- | --------- | -------------------------- |
-| trigger | `'hover' \| 'click'` | `'hover'` | 鼠标悬停触发,或者点击触发 |
-| mask | `string \| { light: string, dark: string }` | `#000` | 遮罩颜色 |
-| color | `string \| { light: string, dark: string }` | `#fff` | 文本颜色 |
-
-**输入:**
-
-```md :no-line-numbers
-- 鼠标悬停 - 悬停时可见
-- 点击 - 点击时可见
-```
-
-**输出:**
-
-- 鼠标悬停 - 悬停时可见
-- 点击 - 点击时可见
-
-## 卡片
-
-使用 `` 组件在页面中显示卡片。
-
-也可以使用 markdown [卡片容器](../markdown/card.md) 语法,替代 `` 组件。
-
-### Props
-
-| 名称 | 类型 | 默认值 | 说明 |
-| ----- | --------------------------- | ------ | ---------------------------------------------------------------- |
-| title | `string` | `''` | 标题 |
-| icon | `string \| { svg: string }` | `''` | 显示在标题左侧的图标,支持 iconify 所有图标,也可以使用 图片链接 |
-
-### 插槽
-
-| 名称 | 说明 |
-| ------- | ---------- |
-| default | 卡片内容 |
-| title | 自定义标题 |
-
-**输入:**
-
-```md :no-line-numbers
-
- 这里是卡片内容。
-
-
-
-
- 卡片标题
-
- 这里是卡片内容。
-
-```
-
-**输出:**
-
-
- 这里是卡片内容。
-
-
-
-
- 卡片标题
-
- 这里是卡片内容。
-
-
-## 链接卡片
-
-使用 `` 组件在页面中显示链接卡片。
-
-### Props
-
-| 名称 | 类型 | 默认值 | 说明 |
-| ----------- | --------------------------- | ------ | ---------------------------------------------------------------- |
-| title | `string` | `''` | 标题 |
-| icon | `string \| { svg: string }` | `''` | 显示在标题左侧的图标,支持 iconify 所有图标,也可以使用 图片链接 |
-| href | `string` | `''` | 链接 |
-| description | `string` | `''` | 详情 |
-
-### 插槽
-
-| 名称 | 说明 |
-| ------- | ------------ |
-| default | 卡片详情内容 |
-| title | 自定义标题 |
-
-**输入:**
-
-```md :no-line-numbers
-
-
-```
-
-**输出:**
-
-
-
-
-## 图片卡片
-
-使用 `` 组件在页面中显示图片卡片。
-
-图片卡片 有别于 markdown 的 普通插入图片方式,它展示与图片相关的更多信息,包括标题、描述、作者、链接等。
-适用于如 摄影作品、设计作品、宣传海报 等场景。
-
-### Props
-
-| 名称 | 类型 | 默认值 | 说明 |
-| ----------- | -------------------------- | ------ | --------------------------------------- |
-| image | `string` | `''` | 必填,图片链接 |
-| title | `string` | `''` | 可选,标题 (展示其它信息需要依赖此属性) |
-| description | `string` | `''` | 可选,描述 |
-| author | `string` | `''` | 可选,作者 |
-| href | `string` | `''` | 可选,链接 |
-| date | `string \| Date \| number` | `''` | 可选,日期 |
-
-**输入:**
-
-```md :no-line-numbers
-
-```
-
-**输出:**
-
-
-
-还可以放到 `` 组件中。
-
-**输入:**
-
-```md :no-line-numbers
-
-
-
-
-```
-
-**输出:**
-
-
-
-
-
-
-[查看 照片类作品示例](../../../../1.示例/照片类作品示例.md)
-
-## 卡片排列容器
-
-当你需要将多个卡片排列,可以使用 `` 组件。在空间足够时,多个卡片会自动排列。
-
-### Props
-
-| 名称 | 类型 | 默认值 | 说明 |
-| :--- | :----------------------------------------------- | :----- | :------------- |
-| cols | `number \| Record<'sm' \| 'md' \| 'lg', number>` | `2` | 卡片排列列数。 |
-
-**输入:**
-
-```md :no-line-numbers
-
-
- 这里是卡片内容。
-
-
- 这里是卡片内容。
-
-
-
-
-
-
-
-```
-
-**输出:**
-
-
-
- 这里是卡片内容。
-
-
- 这里是卡片内容。
-
-
-
-
-
-
-
-
-
diff --git a/docs/guide/markdown/code-tree.md b/docs/guide/markdown/code-tree.md
index 66ad41f6..cab15b17 100644
--- a/docs/guide/markdown/code-tree.md
+++ b/docs/guide/markdown/code-tree.md
@@ -2,7 +2,7 @@
title: 代码树
icon: stash:side-peek
createTime: 2025/05/02 05:59:44
-permalink: /guide/6smvgtbx/
+permalink: /guide/markdown/code-tree/
badge: 新
---
@@ -161,10 +161,10 @@ createApp(App).mount('#app')
**输入:**
```md
-
-@[code-tree title="Notes 配置" height="400px" entry="index.ts"](/.vuepress/notes)
+
+@[code-tree title="Collections 配置" height="400px" entry="index.ts"](/.vuepress/collections)
```
**输出:**
-@[code-tree title="Notes 配置" height="400px" entry="index.ts"](/.vuepress/notes)
+@[code-tree title="Collections 配置" height="400px" entry="index.ts"](/.vuepress/collections)
diff --git a/docs/guide/quick-start/project-structure.md b/docs/guide/quick-start/project-structure.md
index 1e001073..4fc3a74c 100644
--- a/docs/guide/quick-start/project-structure.md
+++ b/docs/guide/quick-start/project-structure.md
@@ -20,10 +20,10 @@ permalink: /guide/project-structure/
- config.ts \# VuePress 主配置
- navbar.ts \# 导航栏配置(可选)
- plume.config.ts \# 主题配置文件(可选)
- - demo \# 文档类型 collection
+ - demo \# `doc` 类型 collection
- foo.md
- bar.md
- - blog \# 博客类型 collection
+ - blog \# `post` 类型 collection
- preview \# 博客分类
- markdown.md \# 分类文章
- article.md \# 博客文章
diff --git a/docs/shim.d.ts b/docs/shim.d.ts
index d1c3d9ed..0f0a0eb2 100644
--- a/docs/shim.d.ts
+++ b/docs/shim.d.ts
@@ -2,3 +2,15 @@ declare module '*.module.css' {
const classes: { [key: string]: string }
export default classes
}
+
+declare module '*.vue' {
+ import type { Component } from 'vue'
+
+ const comp: Component
+ export default comp
+}
+
+declare module '*.css' {
+ const res: string
+ export default res
+}
diff --git a/docs/tsconfig.json b/docs/tsconfig.json
index d29be14a..fb07c0c9 100644
--- a/docs/tsconfig.json
+++ b/docs/tsconfig.json
@@ -5,7 +5,8 @@
"paths": {
"~/themes/*": ["./.vuepress/themes/*"],
"~/components/*": ["./.vuepress/themes/components/*"],
- "~/composables/*": ["./.vuepress/themes/composables/*"]
+ "~/composables/*": ["./.vuepress/themes/composables/*"],
+ "@theme/*": ["../theme/src/client/components/*"]
}
},
"include": [
diff --git a/theme/src/node/prepare/prepareCollections.ts b/theme/src/node/prepare/prepareCollections.ts
index 890423cf..e252beed 100644
--- a/theme/src/node/prepare/prepareCollections.ts
+++ b/theme/src/node/prepare/prepareCollections.ts
@@ -17,7 +17,7 @@ export async function prepareCollections(app: App): Promise {
collections = fallback
if (!collections?.length)
- return
+ continue
data[locale] = collections?.map((item) => {
if (item.type === 'post') {