--- url: /plugins/index.md --- # Plugins --- --- url: /plugins/ai/index.md --- # AI Plugins --- --- url: /plugins/ai/llms.md --- # plugin-llms Add [llms.txt](https://llmstxt.org/) to your site to provide LLM-friendly content. ## Usage ```bash npm i -D @vuepress/plugin-llms@next ``` ```ts title=".vuepress/config.ts" import { llmsPlugin } from '@vuepress/plugin-llms' export default { plugins: [ llmsPlugin({ // options }), ], } ``` ## Why llms.txt? Large Language Models (LLMs) increasingly rely on web-based documentation to answer user queries and write code. However, standard websites present significant challenges: context windows are limited, and raw HTMLโ€”cluttered with navigation, scripts, and stylingโ€”is token-expensive and difficult to parse. **llms.txt** bridges this gap. It creates a standardized entry point for AI agents, providing a concise summary of your project and direct links to clean, expert-level documentation. This is particularly critical for development tools, ensuring LLMs have accurate, low-noise access to your APIs and guides. ### Plugin Overview This plugin automatically converts your VuePress documentation into a structured dataset optimized for machine reading. During the build process, it generates the following assets in your output directory: ```txt ๐Ÿ“‚ .vuepress/dist โ”œโ”€โ”€ ... โ”œโ”€โ”€ llms.txt # The entry point / map of your documentation โ”œโ”€โ”€ llms-full.txt # A single file containing your entire documentation โ”œโ”€โ”€ markdown-examples.html # Your standard web page โ””โ”€โ”€ markdown-examples.md # The clean Markdown version of that page ``` ::: tip These files are generated **only during the production build** (i.e., when running `vuepress build`). They will appear in the `.vuepress/dist` directory alongside your HTML files. ::: ## Output Files ### 1. `llms.txt` The `llms.txt` file acts as the primary index for AI agents. It contains the **Title**, **Description**, **Details (Optional)**, and a **Table of Contents (TOC)** for your site. You can view the generated file for this documentation site here: llms.txt. **Default Format:** ```md title="llms.txt" # Title > Description Details (Optional) ## Table of Contents - [Title](url): Description - [Title](url): Description - ... ``` **Content Resolution Logic:** The plugin determines the content for these fields based on the following priority order (highest priority first): * **Site Title:** 1. `llmsTxtTemplateGetter.title` 2. `heroText` in the homepage frontmatter 3. The current locale's [title](https://v2.vuepress.vuejs.org/reference/config.html#locales) in the VuePress config 4. The main [title](https://v2.vuepress.vuejs.org/reference/config.html#title) in the VuePress config 5. The page title of the locale homepage (`README.md`) * **Site Description:** 1. `llmsTxtTemplateGetter.description` 2. `tagline` in the locale homepage frontmatter 3. The current locale's [description](https://v2.vuepress.vuejs.org/reference/config.html#locales) in the VuePress config 4. The main [description](https://v2.vuepress.vuejs.org/reference/config.html#description) in the VuePress config 5. `frontmatter.description` in the locale homepage (`README.md`) * **Site Details (Optional):** 1. `llmsTxtTemplateGetter.details` 2. `frontmatter.details` in the locale homepage (`README.md`) * **Table of Contents (TOC):** Formatted as `- [title](url): description`. The `description` is pulled from the page's `frontmatter.description`. By default, a flat, first-level TOC is generated. You can customize this behavior (e.g., to support multi-level nesting) by defining a custom getter in the [`llmsTxtTemplateGetter`](#llmstxttemplategetter) option. ### 2. `llms-full.txt` The `llms-full.txt` file is a concatenated version of your documentation. It merges the content of all Markdown files into a single text stream, allowing LLMs to ingest your entire knowledge base in one request. You can view the full file for this site here: llms-full.txt. **Format:** ```txt title="llms-full.txt" --- url: /path/to/page description: A brief summary of the page --- # Page Title Full Markdown content of the page... --- --- url: /path/to/next-page description: ... --- ... ``` ### 3. Individual Page Content In addition to the summary files, the plugin generates a clean Markdown file for every HTML page in your site. For example, if your site has a page at `/guide/quick-start.html`, the plugin generates a corresponding `/guide/quick-start.md` file. This allows LLMs to fetch specific pages with zero HTML noise. ## Options ### llmsTxt * Type: `boolean` * Default: `true` * Details: Specifies whether to generate the `llms.txt` file (the index file containing links to section summaries). ### llmsFullTxt * Type: `boolean` * Default: `true` * Details: Specifies whether to generate the `llms-full.txt` file (a consolidated text file containing the entire documentation). ### llmsPageTxt * Type: `boolean` * Default: `true` * Details: Specifies whether to generate individual LLM-friendly Markdown files for each page of the website. ### stripHTML * Type: `boolean` * Default: `true` * Details: Determines whether HTML tags should be stripped from the generated Markdown files to ensure cleaner input for LLMs. ### filter * Type: `(page: Page) => boolean` * Default: `() => true` * Details: A function to filter which pages are included. If the function returns `true`, the page is included in `llms.txt`. Note that pages explicitly disabled via `frontmatter.llmstxt` or pages not generated from Markdown sources will always be excluded, regardless of this setting. ### domain * Type: `string` * Default: `''` * Details: An optional domain to prepend to all URLs in `llms.txt` and other generated files. While standard relative paths are often sufficient, some AI agents may handle absolute URLs better. Use this option if you need to enforce fully qualified URLs (e.g., `https://example.com/foo/bar.md`). ```md title="llms.txt" - [title](/foo/bar.md) - [title](https://example.com/foo/bar.md) ``` ### locale * Types: `string | 'all'` * Default: `'/'` * Details: Controls which locale to generate content for. * If unset, it defaults to the site's root locale. * If set to a specific locale key (e.g., `'/zh/'`), it generates files only for that language. * If set to `'all'`, the plugin generates `llms.txt` resources for every configured locale. ๏ผš๏ผš๏ผš tip Why use `'all'`? If your documentation contains specialized terminology or concepts that LLMs struggle to translate accurately, generating dedicated `llms.txt` files for each language ensures that international users (and their AI assistants) receive the most precise information available. ::: ### llmsTxtTemplate * Types: `string` * Default: ```ts const DEFAULT_LLMSTXT_TEMPLATE = `\ # {title} {description} {details} ## Table of Contents {toc}` ``` * Details: Defines the structure of the `llms.txt` file. You can rearrange the default placeholdersโ€”`{title}`, `{description}`, `{details}`, and `{toc}`โ€”or introduce new ones using `llmsTxtTemplateGetter`. ### llmsTxtTemplateGetter * Type: `TemplateGetterOptions` ```ts /** * Link extension options for generated links */ export type LinkExtension = '.html' | '.md' /** * Page with additional LLM-friendly content */ export interface LLMPage extends Page { /** * The page's Markdown content * * @example '# Guide\n\nA guide' */ markdown: string /** * The page's excerpt * * @example 'Introduction to the guide' */ excerpt: string } /** * State object for LLM text generation */ export interface LLMState { /** * VuePress app instance */ app: App /** * Site base URL */ base: string /** * Optional domain to prepend to URLs */ domain?: string /** * Link extension for generated links */ linkExtension?: LinkExtension /** * The path of the current locale. */ currentLocale: string /** * Current site locale data */ siteLocale: SiteLocaleData /** * Whether to generate llms.txt files for all locales. */ allLocales: boolean } export type TemplateGetter = (pages: LLMPage[], state: LLMState) => string export interface TemplateGetterOptions { /** Any custom variable */ [key: string]: TemplateGetter | string | undefined } ``` * Default: `{}` * Details: Provides custom variables or getter functions for the [`llmsTxtTemplate`](#llmstxttemplate). You can use this to inject static strings or dynamically generated content. **Example: Overriding the title** ```ts llmsPlugin({ llmsTxtTemplateGetter: { title: 'My Custom Docs Title', }, }) ``` **Example: Adding a custom variable** ```ts llmsPlugin({ llmsTxtTemplate: '# {title}\n\n{customNote}', llmsTxtTemplateGetter: { customNote: 'Note: This content is optimized for AI agents.', }, }) ``` **Example: Generating a custom list of pages** ```ts llmsPlugin({ llmsTxtTemplate: '# {title}\n\n## Page List\n\n{pageList}', llmsTxtTemplateGetter: { pageList: (pages, state) => pages.map((page) => `- ${page.title}`).join('\n'), }, }) ``` ## Frontmatter The plugin respects the following `frontmatter` properties in your Markdown files. ### title {#frontmatter-title} * Types: `string` * Details: * On the **homepage** (`README.md`), this overrides the site title in `llms.txt`. * On **regular pages**, this serves as the page title in the Table of Contents. ### description {#frontmatter-description} * Types: `string` * Details: * On the **homepage** (`README.md`), this overrides the site description in `llms.txt`. * On **regular pages**, this provides the page summary in the Table of Contents. *Recommendation: Write clear, concise descriptions for every page to help LLMs understand the context and relevance of the link.* ### heroText {#frontmatter-herotext} * Types: `string` * Details: * Used exclusively on the homepage (locale `README.md`). It serves as the primary title source for `llms.txt`. ### tagline {#frontmatter-tagline} * Types: `string` * Details: * Used exclusively on the homepage (locale `README.md`). It serves as the primary description source for `llms.txt`. ### details {#frontmatter-details} * Types: `string` * Details: * Used exclusively on the homepage (locale `README.md`). It provides the content for the `{details}` section in `llms.txt`. ### llmstxt * Types: `boolean` * Default: `true` * Details: * Controls whether the current page is included in the generated LLM files. Set to `false` to hide a specific page from AI agents. ## Others It is recommended to configure server redirects so that AI agents can reliably access files via `.md` or `.txt` extensions, even if they guess the URL structure. For example, on **Netlify**, add the following to `public/_redirects`: ```txt /llms.md /llms.txt 200! /llms-full.md /llms-full.txt 200! ``` For more details on redirect syntax, refer to the [Netlify documentation](https://docs.netlify.com/routing/redirects). --- --- url: /plugins/analytics/index.md --- # Analytics Plugins --- --- url: /plugins/analytics/baidu-analytics.md --- # baidu-analytics This plugin integrates [Baidu Analytics](https://tongji.baidu.com/) (Baidu Tongji) into your VuePress site, allowing you to track visitor traffic and user interactions. ::: tip Please **disable** the [SPA mode](https://tongji.baidu.com/web/help/article?id=324\&type=0) in your Baidu Analytics settings. This plugin automatically handles page view reporting on route changes. Enabling Baidu's built-in SPA mode may result in duplicate data or incorrect statistics. ::: ## Usage ```bash npm i -D @vuepress/plugin-baidu-analytics@next ``` ```ts title=".vuepress/config.ts" import { baiduAnalyticsPlugin } from '@vuepress/plugin-baidu-analytics' export default { plugins: [ baiduAnalyticsPlugin({ // options }), ], } ``` ### Event Tracking Once configured, the plugin will automatically report page view (PV) events for both initial page loads and subsequent route navigations. For advanced usage, the global `_hmt` array is exposed on the `window` object. You can utilize this to push [custom events](https://tongji.baidu.com/holmes/Analytics/%E6%8A%80%E6%9C%AF%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97/JS%20API/JS%20API%20%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C) manually. ```ts // Example: Manually reporting a custom event window._hmt = window._hmt || [] window._hmt.push(['_trackEvent', 'category', 'action', 'label', 'value']) ``` ## Options ### id * Type: `string` * Required: Yes * Details: The tracking ID for your Baidu Analytics account. This is usually the string found in the `hm.js` script URL provided by Baidu (e.g., `hm.js?your_tracking_id`). --- --- url: /plugins/analytics/clarity-analytics.md --- s # clarity-analytics Seamlessly integrate [Microsoft Clarity](https://clarity.microsoft.com/) into your VuePress project. ## Usage ```bash npm i -D @vuepress/plugin-clarity-analytics@next ``` ```ts title=".vuepress/config.ts" import { clarityAnalyticsPlugin } from '@vuepress/plugin-clarity-analytics' export default { plugins: [ clarityAnalyticsPlugin({ // options }), ], } ``` ## Features Microsoft Clarity is a behavioral analysis tool that helps you understand how users interact with your website. This plugin simplifies the setup process, enabling you to capture actionable insights without complex configuration. Key features include: * **Session Recordings:** Watch playbacks of user sessions to see exactly how they navigate your site. * **Heatmaps:** Visualize clicks, scrolls, and area engagement to identify what content matters most. * **Smart Insights:** Leverage AI-powered analysis with Copilot to summarize user behavior and trends. For more details on capabilities, please refer to the [Clarity Features Overview](https://learn.microsoft.com/en-us/clarity/setup-and-installation/about-clarity#supported-features). ### Advanced Usage Once the plugin is enabled, the `clarity()` function is exposed on the global `window` object. You can use this to interact with the [Clarity Client API](https://learn.microsoft.com/en-us/clarity/setup-and-installation/clarity-api) for advanced tasks, such as: * Identifying users. * Tracking custom events. * Managing cookie consent. ## Options ### id * Type: `string` * Required: Yes * Details: The Project ID assigned by Microsoft Clarity. You can find this in your Clarity dashboard under Settings. ### crossOrigin * Type: `string` * Default: `undefined` * Details: The `crossorigin` attribute for the injected script tag. This configures the [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) setting for loading the Clarity resources. --- --- url: /plugins/analytics/google-analytics.md --- # google-analytics Seamlessly integrate [Google Analytics 4](https://analytics.google.com/) (GA4) into your VuePress site. This plugin leverages the [Global Site Tag (gtag.js)](https://developers.google.com/analytics/devguides/collection/gtagjs) to enable robust traffic analysis and user tracking. ## Usage ```bash npm i -D @vuepress/plugin-google-analytics@next ``` ```ts title=".vuepress/config.ts" import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics' export default { plugins: [ googleAnalyticsPlugin({ // options }), ], } ``` ### Reporting Events Google Analytics 4 [automatically collects a wide range of events](https://support.google.com/analytics/answer/9234069) by default, such as `page_view`, `first_visit`, and `scroll`. For standard metric collection, simply set the [Measurement ID](#id). If you require advanced tracking capabilities, this plugin exposes the global `gtag()` function on the `window` object. You can utilize this function to report [custom events](https://developers.google.com/analytics/devguides/collection/ga4/events) programmatically based on user interactions within your site. ## Options ### id * Type: `string` * Required: Yes * Details: The Google Analytics 4 Measurement ID (must start with `'G-'`). Please refer to the [official guide](https://support.google.com/analytics/answer/9539598) to locate your Measurement ID. Ensure you are using a GA4 Measurement ID (`G-XXXXXXXXXX`) rather than a Universal Analytics Tracking ID (`UA-XXXXXXXX`). * Example: ```ts title=".vuepress/config.ts" export default { plugins: [ googleAnalyticsPlugin({ id: 'G-XXXXXXXXXX', }), ], } ``` ### debug * Type: `boolean` * Details: Enables the sending of events to the Google Analytics DebugView. This is useful for verifying your setup and troubleshooting event data during development. [Learn more about DebugView](https://support.google.com/analytics/answer/7201382). * Example: ```ts title=".vuepress/config.ts" export default { plugins: [ googleAnalyticsPlugin({ id: 'G-XXXXXXXXXX', debug: true, }), ], } ``` --- --- url: /plugins/analytics/umami-analytics.md --- # umami-analytics Seamlessly integrate [Umami Analytics](https://umami.is/)โ€”a privacy-focused, open-source web analytics solutionโ€”into your VuePress site. ## Usage ```bash npm i -D @vuepress/plugin-umami-analytics@next ``` ```ts title=".vuepress/config.ts" import { umamiAnalyticsPlugin } from '@vuepress/plugin-umami-analytics' export default { plugins: [ umamiAnalyticsPlugin({ // options }), ], } ``` This plugin supports both [Umami Cloud](https://cloud.umami.is/login) and [Self-hosted](https://umami.is/docs/install) instances. ### Reporting Events Out of the box, the plugin automatically captures page view events during initial visits and subsequent route changes. For advanced tracking needs, the global `umami` object is exposed on the `window` instance. You can utilize this to trigger [custom events](https://umami.is/docs/tracker-functions) programmatically via `umami.track()`. ## Options ### id * Type: `string` * Required: Yes * Details: The unique Website ID provided by your Umami dashboard. ### link * Type: `string` * Default: `'https://us.umami.is/script.js'` * Details: The source URL of the Umami tracking script. ### autoTrack * Type: `boolean` * Default: `true` * Details: Controls whether to track pageviews and events automatically. Set this to `false` if you wish to disable automatic data collection and rely solely on manual tracking functions. ### cache * Type: `boolean` * Details: Enables caching to improve the tracking script's performance. **Note:** This feature utilizes Session Storage. Depending on your region's regulations, you may need to disclose this usage to your visitors. ### domains * Type: `string[]` * Details: A list of allowed domains. Tracking will only occur when the site is accessed via these specific domains. ### hostUrl * Type: `string` * Default: `link` * Details: A custom endpoint for sending analytics data. If not specified, it defaults to the script location defined in `link`. --- --- url: /plugins/blog/index.md --- # Blog Plugins --- --- url: /plugins/blog/blog/index.md --- # blog Blog plugin for VuePress, providing article collection, categorization, type filtering, and excerpt generation. ## Usage ```bash npm i -D @vuepress/plugin-blog@next ``` ```ts title=".vuepress/config.ts" import { blogPlugin } from '@vuepress/plugin-blog' export default { plugins: [ blogPlugin({ // options }), ], } ``` --- --- url: /plugins/blog/blog/config.md --- # Config ## Plugin Options ### getInfo * Type: `(page: Page) => Record` * Reference: * [Guide โ†’ Article Collection](./guide.md#gathering-info) * Details: A function to extract article information from pages. The extracted information is injected into the route meta, making it accessible via client-side composables. ### filter * Type: `(page: Page) => boolean` * Default: `(page) => Boolean(page.filePathRelative) && !page.frontmatter.home` * Reference: * [Guide โ†’ Article Collection](./guide.md#collecting-articles) * Details: A function to determine which pages are treated as blog articles. By default, it includes all pages generated from Markdown files, excluding the homepage. ### category * Type: `BlogCategoryOptions[]` * Reference: * [Guide โ†’ Categories and Types](./guide.md#customizing-categories-and-types) * Details: Category configurations. See [Category Config](#blog-category-config). ### type * Type: `BlogTypeOptions[]` * Reference: * [Guide โ†’ Categories and Types](./guide.md#customizing-categories-and-types) * Details: Type configurations. See [Type Config](#blog-type-config). ### slugify * Type: `(name: string) => string` * Default: `(name) => name.replace(/ _/g, '-').replace(/[:?*|\\/<>]/g, "").toLowerCase()` * Details: A function that converts strings into URL-friendly slugs for route registration. ### excerpt * Type: `boolean` * Default: `true` * Reference: [Guide โ†’ Excerpt Generation](./guide.md#generating-excerpt) * Details: Enables or disables excerpt generation for pages. ### excerptSeparator * Type: `string` * Default: `` * Reference: * [Guide โ†’ Excerpt Generation](./guide.md#generating-excerpt) * Details: The separator used to manually define excerpts within the content. ### excerptLength * Type: `number` * Default: `300` * Reference: * [Guide โ†’ Excerpt Generation](./guide.md#generating-excerpt) * Details: The target length for auto-generated excerpts. ::: tip The generator will cut the text at the nearest position meeting or exceeding this length. Set to `0` to disable automatic excerpt generation. ::: ### excerptFilter * Type: `(page: Page) => boolean` * Default: Same as the `filter` option * Reference: * [Guide โ†’ Excerpt Generation](./guide.md#generating-excerpt) * Details: A function to filter pages for excerpt generation. ::: tip Use this to exclude pages from automatic excerpt generation. For instance, if `excerpt` or `description` is already defined in the frontmatter, you might prefer to use those values directly. ::: ### isCustomElement * Type: `(tagName: string) => boolean` * Default: `() => false` * Reference: * [Guide โ†’ Generating Excerpt](./guide.md#generating-excerpt) * Details: A function to identify custom elements. This is used to distinguish custom elements from unknown tags, which are otherwise stripped during excerpt generation. ### metaScope * Type: `string` * Default: `"_blog"` * Details: The key under which the extracted information is injected into the route meta. ::: tip Setting this to an empty string will inject the information directly into the route meta root, rather than nesting it under a field. ::: ### hotReload * Type: `boolean` * Default: Enabled if the `--debug` flag is used * Details: Enables hot reload support in the development server. ::: tip To theme developers This is disabled by default due to potential performance impacts on sites with extensive categories and types. It may also slow down hot updates when editing Markdown. It is recommended to enable this only when users are actively adding or organizing categories/tags. For general use, keep it disabled. Alternatively, you can detect the number of pages in the user's project and decide whether to enable it programmatically. ::: ## Blog Category Config The blog category configuration accepts an array, where each item defines a specific "category" rule. ```ts interface BlogCategoryOptions { /** * Unique category name */ key: string /** * Function to retrieve categories from a page */ getter: (page: Page) => string[] /** * A custom function to sort the pages */ sorter?: (pageA: Page, pageB: Page) => number /** * The path pattern for the registered page * * @description `:key` will be replaced by the "slugify" result of the original key * * @default `/:key/` */ path?: string | false /** * Page layout name * * @default 'Layout' */ layout?: string /** * Frontmatter configuration */ frontmatter?: (localePath: string) => Record /** * The path pattern or custom function for the item page * * @description When providing a string, `:key` and `:name` will be replaced by the "slugify" result of the original key and name * * @default `/:key/:name/` */ itemPath?: string | false | ((name: string) => string) /** * Item page layout name * * @default 'Layout' */ itemLayout?: string /** * Frontmatter configuration for items */ itemFrontmatter?: (name: string, localePath: string) => Record } ``` ## Blog Type Config The blog type configuration accepts an array, where each item defines a specific "type" rule. ```ts interface BlogTypeOptions { /** * Unique type name */ key: string /** * A filter function to determine if a page belongs to this type */ filter: (page: Page) => boolean /** * A custom function to sort the pages */ sorter?: (pageA: Page, pageB: Page) => number /** * The path pattern for the registered page * * @default '/:key/' */ path?: string /** * Layout name * * @default 'Layout' */ layout?: string /** * Frontmatter configuration */ frontmatter?: (localePath: string) => Record } ``` ## Composition API The following APIs are available via `@vuepress/plugin-blog/client`. * Blog category ```ts const useBlogCategory: < T extends Record = Record, >( key?: string, ) => ComputedRef> ``` The `key` argument represents the unique category key. If no key is provided, the plugin attempts to infer the key from the current route. * Blog type ```ts const useBlogType: < T extends Record = Record, >( key?: string, ) => ComputedRef> ``` The `key` argument represents the unique type key. If no key is provided, the plugin attempts to infer the key from the current route. The return values are: ```ts interface Article = Record> { /** Article path */ path: string /** Article info */ info: T } interface BlogCategoryData< T extends Record = Record, > { /** Category path */ path: string /** * Available only when the current route matches a specific item path */ currentItems?: Article[] /** Category map */ map: { /** Unique key under current category */ [key: string]: { /** Category path of the key */ path: string /** Category items of the key */ items: Article[] } } } interface BlogTypeData< T extends Record = Record, > { /** Type path */ path: string /** Items under current type */ items: Article[] } ``` --- --- url: /plugins/blog/blog/guide.md --- # Guide Empowers VuePress themes with blog functionality, including article collection, categorization, and excerpt generation. ## Article Collection The plugin uses the `filter` option to determine which pages should be treated as articles. ::: tip By default, all pages generated from Markdown files are considered articles, excluding the homepage. ::: ## Gathering Info Use the `getInfo` option to define a function that extracts article metadata from pages. The plugin injects this collected information into the `routeMeta` field, making it accessible via the Composition API. ::: details Demo ```ts title="theme entrance" import { blogPlugin } from '@vuepress/plugin-blog' export default { name: 'vuepress-theme-xxx', plugins: [ blogPlugin({ filter: ({ filePathRelative, frontmatter }) => { // Exclude pages not generated from files if (!filePathRelative) return false // Exclude pages in the `archives` directory if (filePathRelative.startsWith('archives/')) return false // Exclude pages that do not use the default layout if (frontmatter.home || frontmatter.layout) return false return true }, getInfo: ({ frontmatter, title, git = {}, data = {} }) => { // Extract page info const info: Record = { title, author: frontmatter.author || '', categories: frontmatter.categories || [], date: frontmatter.date || git.createdTime || null, tags: frontmatter.tags || [], excerpt: data.excerpt || '', } return info }, }), // other plugins ... ], } ``` ::: ## Customizing Categories and Types This plugin allows you to organize articles into two primary collection types: * **Category**: Groups articles based on labels (e.g., Tags, Categories). * **Type**: Filters articles based on specific conditions (e.g., "Diary" entries, "Starred" posts). You can configure these using the `category` and `type` array options. ### Category Configuration Use the `category` option to create label-based groupings. For example, if you want to group articles by "tags" defined in the frontmatter, generate a map page at `/tag/` (using a `TagMap` layout), and list articles for specific tags at `/tag/:tagName` (using a `TagList` layout), you would use the following configuration: ```ts title="theme entrance" import { blogPlugin } from '@vuepress/plugin-blog' export default { name: 'vuepress-theme-xxx', plugins: [ blogPlugin({ // other options ... category: [ { key: 'tag', getter: ({ frontmatter }) => frontmatter.tag || [], path: '/tag/', layout: 'TagMap', frontmatter: () => ({ title: 'Tag page' }), itemPath: '/tag/:name/', itemLayout: 'TagList', itemFrontmatter: (name) => ({ title: `Tag ${name}` }), }, ], }), // other plugins ... ], } ``` ### Type Configuration Use the `type` option to create specific collection lists. For example, to display a list of "Starred" articles (marked by `star: true` in the frontmatter) at `/star/` using a `StarList` layout: ```ts title="theme entrance" import { blogPlugin } from '@vuepress/plugin-blog' export default { name: 'vuepress-theme-xxx', plugins: [ blogPlugin({ // other options ... type: [ { key: 'star', filter: ({ frontmatter }) => frontmatter.star, path: '/star/', layout: 'StarList', frontmatter: () => ({ title: 'Star page' }), }, ], }), // other plugins ... ], } ``` For a complete list of options, please refer to the [Category Config](./config.md#blog-category-config) and [Type Config](./config.md#blog-type-config). ## Using Composition API in Client-side During page generation, the plugin injects the following information into `frontmatter.blog`: ```ts interface BlogFrontmatterOptions { /** Current type of the page */ type: 'category' | 'type' /** Unique key under current category or tag */ key: string /** * Current category name * * @description Only available in category item page */ name?: string } ``` You can use the `useBlogCategory()` and `useBlogType()` hooks to retrieve the data bound to the current route. Alternatively, you can pass a specific `key` as an argument to retrieve data associated with that key. Based on the configuration examples above, here is how you can access "tag" and "star" data on the client side: `TagMap` layout: ```vue ``` `TagList` layout: ```vue ``` `StarList` layout: ```vue ``` For details on return types, please refer to [Composition API Return Types](./config.md#composition-api). ## I18n Support This plugin features native Internationalization (i18n) support. Your configurations are automatically applied to each locale. For example, if you define the following locales in your config: ```ts title=".vuepress/config.ts" export default { locales: { '/': { lang: 'en-US', }, '/zh/': { lang: 'zh-CN', }, }, } ``` The plugin will automatically generate `/zh/star/` alongside `/star/`. Each path will only display articles belonging to the corresponding locale. ## Generating Excerpt The plugin includes a built-in excerpt generator, which can be enabled by setting `excerpt: true`. ::: tip Excerpt Limitations An excerpt is an HTML fragment used to display a short preview of an article. Please note the following restrictions: * **Syntax Support**: Unknown tags (including Vue components) and Vue-specific syntax will be removed during generation. To preserve custom non-Vue elements, use the `isCustomElement` option. * **Assets**: As excerpts are HTML fragments, relative paths and aliases for images will be removed. To ensure images display correctly in excerpts, use absolute paths (based on `.vuepress/public`) or full URLs. ::: The generator prioritizes the use of a separator to determine the excerpt. The default separator is ``, which can be customized via the `excerptSeparator` option. If no valid separator is found, the generator extracts content from the beginning of the file up to a specified length (default: `300` characters). This length can be adjusted using the `excerptLength` option. To control which pages should generate excerpts, use the `excerptFilter` option. ::: tip Example You may prefer to use `frontmatter.description` as excerpt when available, you can configure the filter function to return `false` whenever `frontmatter.description` is present, skipping the automatic generation for those pages. ::: --- --- url: /plugins/blog/comment/index.md --- # comment Comment plugin for VuePress supporting multiple providers. ## Usage ```bash npm i -D @vuepress/plugin-comment@next ``` ```ts title=".vuepress/config.ts" import { commentPlugin } from '@vuepress/plugin-comment' export default { plugins: [ commentPlugin({ provider: 'Waline', // Artalk | Giscus | Waline | Twikoo // provider-specific options }), ], } ``` ## Supported Providers * [Artalk](./artalk/) * [Giscus](./giscus/) * [Twikoo](./twikoo/) * [Waline](./waline/) ## Guide See [Guide](./guide.md) for detailed configuration. --- --- url: /plugins/blog/comment/artalk/index.md --- # Artalk Artalk is a clean self-hosted commenting system that you can easily deploy on your server and integrate into your front-end pages. Deploy the Artalk comment box on your blog or any other page to add rich social functionality. ## Install ```bash npm i -D artalk ``` ## Deploy Artalk Server See the [Artalk documentation](https://artalk.js.org/guide/deploy.html). ## Configuration Please set `provider: "Artalk"` and pass your server link to `server` in the plugin options. For other configuration items, see [Artalk Config](./config.md). ::: tip The plugin retains the `el` option and inserts Artalk itself on the page. At the same time, the plugin will automatically set the `pageTitle`, `pageKey` and `site` options for you according to the VuePress information. ::: ## Dark Mode To let Artalk apply the correct theme, you need to pass a boolean value to `` through `darkmode` prop, representing whether the dark mode is currently enabled. --- --- url: /plugins/blog/comment/artalk/config.md --- # Artalk Options ## Config See [Artalk Configuration](https://artalk.js.org/guide/frontend/config.html) for details. * The `el`, `pageTitle`, `pageKey`, and `site` options are reserved for the plugin and will be automatically inferred from VuePress config. * The two function options `imgUploader` and `avatarURLBuilder` can only be set on the client side. ## Plugin Config You can directly configure serializable options in the plugin options: ```ts title=".vuepress/config.ts" import { commentPlugin } from '@vuepress/plugin-comment' export default { plugins: [ commentPlugin({ provider: 'Artalk', // other options // ... }), ], } ``` ## Client Config You can use the `defineArtalkConfig` function to customize Artalk: ```ts title=".vuepress/client.ts" import { defineArtalkConfig } from '@vuepress/plugin-comment/client' import { defineClientConfig } from 'vuepress/client' defineArtalkConfig({ // Artalk config }) ``` --- --- url: /plugins/blog/comment/giscus/index.md --- # Giscus Giscus is a commenting system based on GitHub Discussion that is easy to start. ## Preparation 1. Create a public repository and open discussion panel as a place to store comments. 2. Install the [Giscus App](https://github.com/apps/giscus) to have permission to access the corresponding repository. 3. After completing the above steps, please go to the [Giscus page](https://giscus.app) to get your settings. You just need to fill in the repository and Discussion categories, then scroll to the "Enable giscus" section at the bottom of the page and obtain four attributes: `data-repo`, `data-repo-id`, `data-category` and `data-category-id`. ## Config Please set `provider: "Giscus"` and pass `data-repo`, `data-repo-id`, `data-category` and `data-category-id` as plugin options as `repo`, `repoId`, `category` `categoryId`. For other options, see [Giscus Config](./config.md). ## Theme By default, the theme of Giscus is `light` or `dark` (based on darkmode status). ::: tip Dark Mode To let Giscus apply the correct theme, you need to pass a boolean value to `` via `darkmode` property, indicating whether darkmode is currently enabled. ::: If you want to customize theme in lightmode and darkmode, you can set `lightTheme` and `darkTheme` option with a built-in theme keyword or a custom CSS link starting with `https://`. --- --- url: /plugins/blog/comment/giscus/config.md --- # Giscus Options ## Config ### repo * Type: `string` * Required: Yes * Details: The name of repository to store discussions ### repoId * Type: `string` * Required: Yes * Details: The ID of repository to store discussions. Generate through [Giscus Page](https://giscus.app/) ### category * Type: `string` * Required: Yes * Details: The name of the discussion category ### categoryId * Type: `string` * Required: Yes * Details: The ID of the discussion category. Generate through [Giscus Page](https://giscus.app/) ### mapping * Type: `string` * Default: `"pathname"` * Details: Page - Discussion mapping. For details see [Giscus Page](https://giscus.app/) ### strict * Type: `boolean` * Default: `true` * Details: Whether to enable strict mapping ### lazyLoading * Type: `boolean` * Default: `true` * Details: Whether to enable lazy loading ### reactionsEnabled * Type: `boolean` * Default: `true` * Details: Whether to enable reactions ### inputPosition * Type: `"top" | "bottom"` * Default: `"top"` * Details: Input position ### lightTheme * Type: `GiscusTheme` ```ts type GiscusTheme = | 'dark_dimmed' | 'dark_high_contrast' | 'dark_protanopia' | 'dark' | 'light_high_contrast' | 'light_protanopia' | 'light' | 'preferred_color_scheme' | 'transparent_dark' | `https://${string}` ``` * Default: `"light"` * Details: Giscus theme used in light mode Should be a built-in theme keyword or a CSS link starting with `https://`. ### darkTheme * Type: `GiscusTheme` ```ts type GiscusTheme = | 'dark_dimmed' | 'dark_high_contrast' | 'dark_protanopia' | 'dark' | 'light_high_contrast' | 'light_protanopia' | 'light' | 'preferred_color_scheme' | 'transparent_dark' | `https://${string}` ``` * Default: `"dark"` * Details: Giscus theme used in dark mode Should be a built-in theme keyword or a CSS link starting with `https://`. ## Plugin Config You can directly configure serializable options in the plugin options: ```ts title=".vuepress/config.ts" import { commentPlugin } from '@vuepress/plugin-comment' export default { plugins: [ commentPlugin({ provider: 'Giscus', // other options // ... }), ], } ``` ## Client Config You can use the `defineGiscusConfig` function to customize Giscus: ```ts title=".vuepress/client.ts" import { defineGiscusConfig } from '@vuepress/plugin-comment/client' import { defineClientConfig } from 'vuepress/client' defineGiscusConfig({ // Giscus config }) ``` --- --- url: /plugins/blog/comment/guide.md --- # Guide ## Configuration The plugin offers flexible configuration through both the plugin options and the client configuration file. ### Using Plugin Options ```ts title=".vuepress/config.ts" import { commentPlugin } from '@vuepress/plugin-comment' export default { plugins: [ commentPlugin({ provider: 'Artalk', // Artalk | Giscus | Waline | Twikoo // provider-specific options }), ], } ``` ### Using Client Config ```ts title=".vuepress/client.ts" import { defineArtalkConfig, // defineGiscusConfig, // defineTwikooConfig, // defineWalineConfig, } from '@vuepress/plugin-comment/client' import { defineClientConfig } from 'vuepress/client' defineArtalkConfig({ // options }) ``` ### Configuration Logic To ensure optimal performance and proper serialization, options are split between the plugin configuration and the client configuration: * **Plugin Options**: Static options such as `provider`, `locales`, and resource links must be set here. This allows the bundler to perform **tree-shaking**, ensuring that code for unused providers is excluded from the final build. * **Client Config**: Dynamic options, specifically those involving functions or callbacks, must be set here. Since these cannot be serialized in the main config, the client config serves as the runtime entry point. ## Component Usage The plugin registers a global `` component that you can place anywhere in your layout. **For Users**: You can inject the component using aliases or layout slots provided by your theme. A common practice is to place it immediately after the `` component. **For Theme Developers**: You should include the `` component directly within your theme's layout files to provide built-in comment support. ### Visibility & Identification You can control the visibility of the comment section and customize the unique identifier for each page: * **Global Toggle**: Use the `comment` option in the plugin configuration to set the default visibility for the entire site. * **Per-Page Toggle**: Use the `comment` key in the frontmatter to enable or disable comments for a specific page, overriding the global setting. * **Custom Identifier**: Use the `commentID` key in the frontmatter to define a custom identifier for the page's comments (e.g., when migrating posts or changing URLs). ## Available Providers We support the following comment services. Please refer to their respective guides for setup details: [Giscus](giscus/README.md), [Waline](waline/README.md), [Artalk](artalk/README.md), and [Twikoo](twikoo/README.md). ::: tip Recommendations * **Giscus**: Ideal for **developers** and technical blogs, as it uses GitHub Discussions to store comments. * **Waline**: A comprehensive choice for **general users**, offering a rich feature set and backend flexibility. ::: ## Common Options ### provider * Type: `"Artalk" | "Giscus" | "Twikoo" | "Waline" | "None"` * Default: `"None"` * Details: The comment service provider to use. ### comment * Type: `boolean` * Default: `true` * Details: Whether to enable the comment feature globally by default. --- --- url: /plugins/blog/comment/twikoo/index.md --- # Twikoo A concise, safe and free static site commenting system, based on [Tencent Cloud Development](https://curl.qcloud.com/KnnJtUom). ## Install ```bash npm i -D twikoo ``` ## Getting started 1. Apply for [MongoDB](https://www.mongodb.com/cloud/atlas/register) account 2. Create a free MongoDB database, the recommended region is `AWS / N. Virginia (us-east-1)` 3. Click CONNECT on the Clusters page, follow the steps to allow connections from all IP addresses ([Why?](https://vercel.com/support/articles/how-to-allowlist-deployment-ip-address)), create Database user, and record the database connection string, please change the `` in the connection string to the database password 4. Sign up for a [Vercel](https://vercel.com/signup) account 5. Click the button below to deploy Twikoo to Vercel in one click [![Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/imaegoo/twikoo/tree/dev/src/vercel-min) 6. Go to Settings - Environment Variables, add the environment variable `MONGODB_URI`, the value is the database connection string in step 3 7. Go to Overview, click the link under Domains, if the environment configuration is correct, you can see the prompt "Twikoo cloud function is running normally" 8. Vercel Domains (with `https://` prefix, e.g. `https://xxx.vercel.app`) is your environment ID ## Configuration Please set `provider: "Twikoo"` and pass your server address to `envId` in the plugin options. For other configuration items, see [Twikoo Config](./config.md). --- --- url: /plugins/blog/comment/twikoo/config.md --- # Twikoo Options ## Config ### envId * Type: `string` * Required: Yes * Details: Vercel address or Tencent CloudBase environment ID. ## Plugin Config You can directly configure serializable options in the plugin options: ```ts title=".vuepress/config.ts" import { commentPlugin } from '@vuepress/plugin-comment' export default { plugins: [ commentPlugin({ provider: 'Twikoo', // other options // ... }), ], } ``` ## Client Config You can use the `defineTwikooConfig` function to customize Twikoo: ```ts title=".vuepress/client.ts" import { defineTwikooConfig } from '@vuepress/plugin-comment/client' import { defineClientConfig } from 'vuepress/client' defineTwikooConfig({ // Twikoo config }) ``` --- --- url: /plugins/blog/comment/waline/index.md --- # Waline A safe comment system with backend. ## Install ```bash npm i -D @waline/client ``` ## LeanCloud Settings (Database) 1. [Sign in](https://console.leancloud.app/login) or [sign up](https://console.leancloud.app/register) to LeanCloud and enter the [Console](https://console.leancloud.app/apps). 2. Click the [Create app](https://console.leancloud.app/apps) button to create a new app and enter a name you like: ![Create App](./assets/leancloud-app-1.jpg) 3. Enter the app, then select `Settings` > `App Keys` in the left bottom corner. You will see `APP ID`, `APP Key` and `Master Key` of your app. We will use them later. ![ID and Key](./assets/leancloud-app-2.jpg) ## Deploy to Vercel (Server) [![Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwalinejs%2Fwaline%2Ftree%2Fmain%2Fexample) 1. Click the button above to redirect to Vercel and deploy with the Waline template. ::: tip If you haven't logged in, we recommend you sign in with GitHub. ::: 2. Input your Vercel project name then click `Create`. ![skip team](/images/comment/vercel-2.png) 3. A repository named as your input will be created and initialized automatically based on the Waline example template by Vercel. ![deploy](/images/comment/vercel-3.png) After a minute or two, Vercel should finish the deployment. Click `Go to Dashboard` to redirect to your application dashboard. ![deploy](/images/comment/vercel-4.png) 4. Click `Settings` menu on the top, and `Environment Variables` button on the side to go to environment variables setting page. Then set `LEAN_ID`, `LEAN_KEY` and `LEAN_MASTER_KEY`. The variables' values should be the ones you got in the previous step. `APP ID` is the value of `LEAN_ID`, and `APP Key` to `LEAN_KEY`, `Master Key` to `LEAN_MASTER_KEY`. ![set environment variables](/images/comment/vercel-5.png) 5. To let your environment variables setting take effect, you need to redeploy your application. Click `Deployments` menu on the top and find the latest deployment at the top of list, click `Redeploy` button in the right dropdown menu. ![redeploy](/images/comment/vercel-6.png) 6. If everything is ok, Vercel will redirect to `Overview` page to start redeployment. Wait a moment and the `STATUS` will change to `Ready`. Now you can click `Visit` to visit the site. This link is your server address. ![redeploy success](/images/comment/vercel-7.png) ## Assign Domain (Optional) 1. Click `Settings` - `Domains` to go to domain setting page. 2. Input domain you want to assign and click `Add` button. ![Add domain](/images/comment/vercel-8.png) 3. Add a new `CNAME` record in your domain service server. | Type | Name | Value | | ----- | ------- | -------------------- | | CNAME | example | cname.vercel-dns.com | 4. You can use your own domain to visit the Waline comment system after it goes into effect. :tada: * serverURL: example.your-domain.com * admin panel: example.your-domain.com/ui ![success](/images/comment/vercel-9.png) ## Client ### Using plugin Set `provider: "Waline"` in the plugin options, and set `serverURL` as the link obtained in the previous step. Then, place the `` component at a suitable location in your site (usually at the bottom of the page), you will be able to see the comment box. ::: tip You can also pass in other options supported by Waline (except `el`). For details, see [Waline Config](config.md) ::: ## Comment Management (Management) 1. After the deployment is complete, please visit `/ui/register` to register. The first person to register will be set as an administrator. 2. After you log in as administrator, you can see the comment management interface. You can edit, mark or delete comments here. 3. Users can also register their account through comment box, and they will be redirected to their profile page after logging in. --- --- url: /plugins/blog/comment/waline/config.md --- # Waline Config ## Config ### serverURL * Type: `string` * Required: Yes * Details: Waline server address URL ### emoji * Type: `(string | WalineEmojiInfo)[] | false` ```ts type WalineEmojiPresets = `http://${string}` | `https://${string}` interface WalineEmojiInfo { /** * Emoji name show on tab */ name: string /** * Current folder link */ folder?: string /** * Common prefix of Emoji icons */ prefix?: string /** * Type of Emoji icons, will be regarded as file extension */ type?: string /** * Emoji icon show on tab */ icon: string /** * Emoji image list */ items: string[] } ``` * Default: `['//unpkg.com/@waline/emojis@1.1.0/weibo']` * Reference: * [Guide โ†’ Emoji](https://waline.js.org/en/guide/features/emoji.html) * Details: Emoji settings ### dark * Type: `string | boolean` * Default: `false` * Reference: * [Custom Style](https://waline.js.org/en/guide/features/style.html) * Details: Dark mode support. Setting a boolean will set the dark mode according to its value. Set it to `'auto'` will display darkmode due to device settings. Filling in a CSS selector will enable darkmode only when the selector match waline ancestor nodes. ### commentSorting * Type: `WalineCommentSorting` * Default: `'latest'` * Details: Comment list sorting method. Should be one of `'latest'`, `'oldest'`, or `'hottest'`. ### meta * Type: `string[]` * Default: `['nick', 'mail', 'link']` * Details: Reviewer attributes. Should be one of `'nick'`, `'mail'`, `'link'`. ### requiredMeta * Type: `string[]` * Default: `[]` * Details: Set required fields. Available values: * `[]` * `['nick']` * `['nick', 'mail']` ### login * Type: `string` * Default: `'enable'` * Details: Login mode status. Available values: * `'enable'`: Enable login (default) * `'disable'`: Login is disabled, users should fill in information to comment * `'force'`: Forced login, users must login to comment ### wordLimit * Type: `number | [number, number]` * Default: `0` * Details: Comment word limit. When a single number is filled in, it's the maximum number of comment words. No limit when set to `0`. ### pageSize * Type: `number` * Default: `10` * Details: Number of comments per page. ### imageUploader * Type: `WalineImageUploader | false` ```ts type WalineImageUploader = (image: File) => Promise ``` * Reference: * [Cookbook โ†’ Upload Image](https://waline.js.org/en/cookbook/customize/upload-image.html) * Details: Custom image upload method. The default behavior is to embed images Base 64 encoded, you can set this to `false` to disable image uploading. The function should receive an image object and return a Promise that provides the image address. ### highlighter * Type: `WalineHighlighter | false` ```ts type WalineHighlighter = (code: string, lang: string) => string ``` * Reference: * [Cookbook โ†’ Customize Highlighter](https://waline.js.org/en/cookbook/customize/highlighter.html) * Details: **Code highlighting** uses `hanabi` by default. The function passes in original content of code block and language of the code block. You should return a string directly. You can pass in a code highlighter of your own, or set to `false` to disable code highlighting. ### texRenderer * Type: `WalineTexRenderer | false` ```ts type WalineTexRenderer = (blockMode: boolean, tex: string) => string ``` * Reference: * [Cookbook โ†’ Customize TeX Renderer](https://waline.js.org/en/cookbook/customize/tex-renderer.html) * [MathJax](https://www.mathjax.org/) * [KaTeX](https://katex.org/) * Details: Customize TeX rendering. The default behavior is to prompt that the preview mode does not support TeX. The function provides two parameters: the first parameter indicates whether it should be rendered in block level, and the second parameter is the string of the TeX content. Return an HTML string as render result. You can import TeX renderer to provide preview feature. We recommend you use KaTeX or MathJax, or set to `false` to disable parsing TeX. ### search * Type: `WalineSearchOptions | false` ```ts interface WalineSearchImageData extends Record { /** * Image link */ src: string /** * Image title * * @description Used for alt attribute of image */ title?: string /** * Image preview link * * @description For better loading performance, we will use this thumbnail first in the list * * @default src */ preview?: string } type WalineSearchResult = WalineSearchImageData[] interface WalineSearchOptions { /** * Search action */ search: (word: string) => Promise /** * Default result when opening list * * @default () => search('') */ default?: () => Promise /** * Fetch more action * * @description It will be triggered when the list scrolls to the bottom. If your search service supports paging, you should set this to achieve infinite scrolling * * @default (word) => search(word) */ more?: (word: string, currentCount: number) => Promise } ``` * Details: Customize search features. You can disable search function by setting it to `false`. ### recaptchaV3Key * Type: `string` * Details: reCAPTCHA V3 is a captcha service provided by Google. You can add reCAPTCHA V3 site key with `recaptchaV3Key` to enable it. You should also set environment variable `RECAPTCHA_V3_SECRET` for server. ### reaction * Type: `boolean | string[]` * Default: `false` * Details: Add emoji interaction function to the article. Set it to `true` to provide the default emoji, you can also customize the emoji image by setting the emoji URL array, and supports a maximum of 8 emojis. ### metaIcon * Type: `boolean` * Default: `true` * Details: Whether to import meta icon. ### locales * Type: `WalineLocales` ```ts interface WalineLocales { [localePath: string]: Partial } ``` * Reference: * [Waline Locales](https://waline.js.org/en/cookbook/customize/locale.html) * Details: Waline locales. ## Plugin Config You can directly configure serializable options in the plugin options: ```ts title=".vuepress/config.ts" import { commentPlugin } from '@vuepress/plugin-comment' export default { plugins: [ commentPlugin({ provider: 'Waline', // other options // ... }), ], } ``` ## Client Config You can use the `defineWalineConfig` function to customize Waline: ```ts title=".vuepress/client.ts" import { defineWalineConfig } from '@vuepress/plugin-comment/client' import { defineClientConfig } from 'vuepress/client' defineWalineConfig({ // Waline config }) ``` --- --- url: /plugins/blog/feed/index.md --- # feed ## Usage ```bash npm i -D @vuepress/plugin-feed@next ``` ```ts title=".vuepress/config.ts" import { feedPlugin } from '@vuepress/plugin-feed' export default { plugins: [ feedPlugin({ // options }), ], } ``` --- --- url: /plugins/blog/feed/channel.md --- # Channel Config The `channel` option allows you to configure metadata for the generated feed channel. ## channel.title * Type: `string` * Default: `SiteConfig.title` * Details: The title of the channel. ## channel.link * Type: `string` * Default: Deployment link (generated from `options.hostname` and `context.base`) * Details: The address of the channel ## channel.description * Type: `string` * Default: `SiteConfig.description` * Details: The description of the channel. ## channel.language * Type: `string` * Default: * `siteConfig.locales['/'].lang` * Falls back to `"en-US"` if the above is not available. * Details: The language of the channel. ## channel.copyright * Type: `string` * Default: * Tries to use `author.name` from the channel options. * Falls back to `Copyright by $author`. * Recommended to set manually: **Yes** * Details: The copyright information for the channel. ## channel.pubDate * Type: `string` (must be a valid Date ISOString) * Default: The current time when the plugin is invoked * Recommended to set manually: **Yes** * Details: The publication date of the channel. ## channel.lastUpdated * Type: `string` (must be a valid Date ISOString) * Default: The current time when the plugin is invoked * Details: The last update time of the channel content. ## channel.ttl * Type: `number` * Recommended to set manually: **Yes** * Details: Time to Live (TTL) in minutes. This indicates how long a feed reader should cache the content before making a new request. ## channel.image * Type: `string` * Recommended to set manually: **Yes** * Details: The channel image. It is recommended to use a square image with a size of at least 512ร—512 pixels. ## channel.icon * Type: `string` * Recommended to set manually: **Yes** * Details: The channel icon. It should be a square image of at least 128ร—128 pixels. A transparent background is recommended. ## channel.author * Type: `FeedAuthor` * Recommended to set manually: **Yes** * Details: The primary author of the channel. ::: details FeedAuthor format ```ts interface FeedAuthor { /** Author name */ name: string /** Author's email */ email?: string /** Author's site */ url?: string /** * Author's avatar address * * Square, preferably not less than 128ร—128 with transparent background */ avatar?: string } ``` ::: ## channel.hub * Type: `string` * Details: The URL for the WebSub hub. Since WebSub requires a server backend (which differs from the static nature of VuePress), you generally do not need to configure this unless you have a specific requirement. For details, see [WebSub](https://w3c.github.io/websub/#subscription-migration). --- --- url: /plugins/blog/feed/config.md --- # Plugin Config ## hostname * Type: `string` * Required: Yes The domain name where the site is deployed. ## atom * Type: `boolean` * Default: `false` Whether to generate an Atom feed. ## json * Type: `boolean` * Default: `false` Whether to generate a JSON feed. ## rss * Type: `boolean` * Default: `false` Whether to generate an RSS feed. ## image * Type: `string` A large image or icon for the feed, typically used as a banner. ## icon * Type: `string` A small icon for the feed, typically used as a favicon. ## count * Type: `number` * Default: `100` The maximum number of items to include in the feed. After sorting all valid pages, only the first `count` items will be preserved. If your site contains a large number of articles, consider adjusting this option to reduce the feed file size. ## preservedElements * Type: `(RegExp | string)[] | (tagName: string) => boolean` Custom elements or components that should be preserved in the feed content. ::: tip By default, all unknown tags will be removed. ::: ## filter * Type: `(page: Page)=> boolean` * Default: ```js ;({ frontmatter, filePathRelative }) => Boolean(frontmatter.feed ?? (filePathRelative && !frontmatter.home)) ``` A custom filter function to determine which pages are included in the feed. ## sorter * Type: `(pageA: Page, pageB: Page)=> number` * Default: ```ts // dateSorter is from @vuepress/helper ;(pageA: Page, pageB: Page): number => dateSorter( pageA.data.git?.createdTime ? new Date(pageA.data.git?.createdTime) : pageA.frontmatter.date, pageB.data.git?.createdTime ? new Date(pageB.data.git?.createdTime) : pageB.frontmatter.date, ) ``` A custom sorter function for feed items. The default behavior sorts items by the file creation time retrieved from git (requires `@vuepress/plugin-git`). ::: tip You should enable `@vuepress/plugin-git` to accurately use the creation time of pages for sorting. Otherwise, feed items will follow the default page order in VuePress. ::: ## channel The `channel` option configures *Feed Channels*. For available options, please see [Config โ†’ Channel](channel.md). ## devServer * Type: `boolean` * Default: `false` Whether to enable feed generation in the development server. ::: tip For performance reasons, hot reload is not available. You must restart the devServer to sync changes. ::: ## devHostname * Type: `string` * Default: `"http://localhost:${port}"` The hostname to use when running in the development server. ## atomOutputFilename * Type: `string` * Default: `"atom.xml"` The output filename for the Atom feed, relative to the output directory. ## atomXslTemplate * Type: `string` * Default: Content of `@vuepress/plugin-feed/templates/atom.xsl` The content of the XSL template file for Atom. ## atomXslFilename * Type: `string` * Default: `"atom.xsl"` The output filename for the Atom XSL file, relative to the output directory. ## jsonOutputFilename * Type: `string` * Default: `"feed.json"` The output filename for the JSON feed, relative to the output directory. ## rssOutputFilename * Type: `string` * Default: `"rss.xml"` The output filename for the RSS feed, relative to the output directory. ## rssXslTemplate * Type: `string` * Default: Content of `@vuepress/plugin-feed/templates/rss.xsl` The content of the XSL template file for RSS. ## rssXslFilename * Type: `string` * Default: `"rss.xsl"` The output filename for the RSS XSL file, relative to the output directory. ## getter The controller for feed generation. See [Feed Getter](./getter.md). ::: tip The plugin includes a built-in getter. Set this option only if you require full control over the feed generation process. ::: ## locales * Type: `Record` Configuration for specific locales. All options listed above are supported within locales, except for `hostname`. --- --- url: /plugins/blog/feed/frontmatter.md --- # Frontmatter Config You can customize how individual pages appear in the feed by configuring the page frontmatter. ## Inclusion Control By default, all valid articles are included in the feed generation. To exclude a specific page from the feed, set `feed: false` in its frontmatter. ## Standard Information The plugin automatically extracts the following standard frontmatter properties to populate feed items. ### title * Type: `string` The title of the page. It is automatically inferred from the first `h1` header if not specified. ### description * Type: `string` A summary or description of the page. ### date * Type: `Date` The publication date of the page. ### article * Type: `boolean` Specifies whether the page is an article. > If set to `false`, the page will be treated as a non-article page and excluded from the feed. ### copyright * Type: `string` Copyright information specific to this page. ### cover / image / banner * Type: `string` The cover image for the page. This must be a complete URL or an absolute path. ## Feed Options You can use the `feed` object to override standard properties or provide specific configurations for the RSS/Atom/JSON feed item. ### feed.title * Type: `string` Overrides the title used for this item in the feed. ### feed.description * Type: `string` Overrides the description used for this item in the feed. ### feed.content * Type: `string` Custom content for the feed item. If not provided, the page content is used. ### feed.author * Type: `FeedAuthor[] | FeedAuthor` The author(s) specific to this feed item. ::: details FeedAuthor format ```ts interface FeedAuthor { /** * Author name */ name?: string /** * Author email */ email?: string /** * Author site * * @description json format only */ url?: string /** * Author avatar * * @description json format only */ avatar?: string } ``` ::: ### feed.contributor * Type: `FeedContributor[] | FeedContributor` The contributor(s) specific to this feed item. ::: details FeedContributor format ```ts interface FeedContributor { /** * Author name */ name?: string /** * Author email */ email?: string /** * Author site * * @description json format only */ url?: string /** * Author avatar * * @description json format only */ avatar?: string } ``` ::: ### feed.guid * Type: `string` A unique identifier for the feed item. ::: tip Ensure that every feed item has a globally unique GUID to prevent feed readers from marking updated items as new or duplicating them. ::: --- --- url: /plugins/blog/feed/getter.md --- # Feed Getter You can take full control of how feed items are generated by configuring the `getter` object in the plugin options. ## getter.title * Type: `(page: Page, app: App) => string` * Details: Customizes the title of the feed item. ## getter.link * Type: `(page: Page, app: App) => string` * Details: Customizes the link (URL) of the feed item. ## getter.description * Type: `(page: Page, app: App) => string | undefined` * Details: Customizes the description or summary of the feed item. ::: tip Since Atom supports HTML in summaries, you can return HTML content here. However, to ensure correct rendering, the returned string must start with the prefix `html:`. ::: ## getter.content * Type: `(page: Page, app: App) => string` * Details: Customizes the main content of the feed item. ## getter.author * Type: `(page: Page, app: App) => FeedAuthor[]` * Details: Retrieves the list of authors for the feed item. ::: tip This getter should return an empty array `[]` if no author information is available. ::: ::: details FeedAuthor format ```ts interface FeedAuthor { /** * Author name */ name?: string /** * Author email */ email?: string /** * Author site * * @description json format only */ url?: string /** * Author avatar * * @description json format only */ avatar?: string } ``` ::: ## getter.category * Type: `(page: Page, app: App) => FeedCategory[] | undefined` * Details: Retrieves the categories associated with the feed item. ::: details FeedCategory format ```ts interface FeedCategory { /** * Category Name */ name: string /** * A string that identifies a categorization taxonomy * * @description rss format only */ domain?: string /** * The categorization scheme via a URI * * @description atom format only */ scheme?: string } ``` ::: ## getter.enclosure * Type: `(page: Page, app: App) => FeedEnclosure | undefined` * Details: Specifies a media enclosure (e.g., audio, video, or attachment) for the feed item. ::: details FeedEnclosure format ```ts interface FeedEnclosure { /** * Enclosure link */ url: string /** * The MIME type of the enclosure * * @description should be a standard MIME Type, rss format only */ type: string /** * Size in bytes * * @description rss format only */ length?: number } ``` ::: ## getter.publishDate * Type: `(page: Page, app: App) => Date | undefined` * Details: Determines the publication date of the feed item. ## getter.lastUpdateDate * Type: `(page: Page, app: App) => Date` * Details: Determines the last modification date of the feed item. ## getter.image * Type: `(page: Page, app: App) => string` * Details: Sets a featured image for the feed item. ::: tip Ensure the returned string is a full, absolute URL. ::: ## getter.contributor * Type: `(page: Page, app: App) => FeedContributor[]` * Details: Retrieves the list of contributors for the feed item. ::: tip This getter should return an empty array `[]` if no contributor information is available. ::: ::: details FeedContributor format ```ts interface FeedContributor { /** * Contributor name */ name?: string /** * Contributor email */ email?: string /** * Contributor site * * @description json format only */ url?: string /** * Contributor avatar * * @description json format only */ avatar?: string } ``` ::: ## getter.copyright * Type: `(page: Page, app: App) => string | undefined` * Details: Specifies the copyright information for the feed item. --- --- url: /plugins/blog/feed/guide.md --- # Guide ## Usage The plugin generates feeds in the following three formats: * Atom 1.0 * JSON 1.1 * RSS 2.0 Enable the formats you need by setting `atom`, `json`, or `rss` to `true` in the plugin options. To ensure feed links are generated correctly, the `hostname` option is required. ## Readable Preview Atom and RSS feeds include XSL templates, allowing them to be rendered as human-readable HTML when opened in a browser. Check out the [atom](/atom.xml) and [rss](/rss.xml) feeds of this site for a live demo. To preview feeds in your development environment, set `devServer: true` in the plugin options. If your local setup differs from the default `http://localhost:{port}`, you should also configure `devHostname`. ## Channel Settings You can customize global feed metadata via the `channel` option. We recommend configuring the following fields: * `channel.pubDate`: Set to the current ISOString to indicate the feed generation time. * `channel.ttl`: Define the content update frequency (in minutes). * `channel.copyright`: Specify copyright information. * `channel.author`: Set the default author for the channel. For a complete list of options and their default values, please refer to [Channel Config](./channel.md). ## Feed Generation By default, all articles are included in the feed. You can control individual feed items using the `feed` option in the page frontmatter. See [Frontmatter Config](./frontmatter.md) for mapping details. For complete control over the item generation logic, you can configure the `getter` function in the plugin options. See [Configuration โ†’ Feed Getter](./getter.md) for details. ### I18n Support The plugin automatically generates separate feeds for each language. You can provide language-specific configurations via the `locales` option. --- --- url: /plugins/development/index.md --- # Development Plugins --- --- url: /plugins/development/active-header-links.md --- # active-header-links This plugin will listen to page scroll event. When the page scrolls to a certain *header anchor*, this plugin will change the route hash to that *header anchor* if there is a corresponding *header link*. This plugin is mainly used to develop themes, and has been integrated into the default theme. You won't need to use it directly in most cases. ## Usage ```bash npm i -D @vuepress/plugin-active-header-links@next ``` ```ts title=".vuepress/config.ts" import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links' export default { plugins: [ activeHeaderLinksPlugin({ // options }), ], } ``` ## Options ### headerLinkSelector * Type: `string` * Default: `'a.vp-sidebar-item'` * Details: Selector of *header link*. If a *header anchor* does not have a corresponding *header link*, this plugin won't change the route hash to that anchor when scrolling to it. ### headerAnchorSelector * Type: `string` * Default: `'.header-anchor'` * Details: Selector of *header anchor*. You don't need to specify this option unless you have changed the `permalinkClass` option of [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor#readme) via [markdown.anchor](https://vuejs.press/reference/config.html#markdown-anchor). * Also see: * [Guide > Markdown > Syntax Extensions > Header Anchors](https://vuejs.press/guide/markdown.html#header-anchors) ### delay * Type: `number` * Default: `200` * Details: The delay of the debounced scroll event listener. ### offset * Type: `number` * Default: `5` * Details: Even if you click the link of the *header anchor* directly, the `scrollTop` might not be exactly equal to `offsetTop` of the *header anchor*, so we add an offset to avoid the error. --- --- url: /plugins/development/git.md --- # git This plugin collects Git information for your pages, including creation and update timestamps, contributor lists, and changelogs. The [lastUpdated](../../themes/default/config.md#lastupdated) and [contributors](../../themes/default/config.md#contributors) features in the default theme are powered by this plugin. This plugin is primarily intended for theme development. In most cases, you will not need to use it directly. ## Usage ```bash npm i -D @vuepress/plugin-git@next ``` ```ts title=".vuepress/config.ts" import { gitPlugin } from '@vuepress/plugin-git' export default { plugins: [ gitPlugin({ // options }), ], } ``` ## Git Repository This plugin requires your project to be located within a [Git Repository](https://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository) to properly collect data from the commit history. Ensure that the full commit history is available when building your site. CI workflows often use [--depth 1](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt) when cloning repositories to improve performance, which prevents the plugin from accessing the necessary history. You must disable this shallow clone behavior (usually by setting `fetch-depth: 0`) for the plugin to work correctly in CI environments. ::: warning This plugin may significantly increase data preparation time during builds, especially for projects with a large number of pages. You may consider disabling this plugin in `dev` mode to improve the development experience. ::: ## Options ### createdTime * Type: `boolean` * Default: `true` * Details: Whether to collect the creation timestamp of the page. ### updatedTime * Type: `boolean` * Default: `true` * Details: Whether to collect the update timestamp of the page. ### contributors * Type: `boolean | ContributorsOptions` ```ts interface ContributorInfo { /** * The contributor's username on the Git hosting service */ username: string /** * The contributor's display name on the page. Defaults to `username`. */ name?: string /** * Aliases for the contributor. * Useful when a contributor's local Git username differs from their * hosting service username. Use aliases to map them to the correct account. */ alias?: string[] | string /** * The primary email of the contributor */ email?: string /** * Alternative emails for the contributor (e.g., emails used in past commits). */ emailAlias?: string[] | string /** * The avatar URL of the contributor. * * If the hosting service is `github`, this can be left blank, * as the plugin will automatically populate it. */ avatar?: string /** * The profile URL of the contributor. * * If the hosting service is `github`, this can be left blank, * as the plugin will automatically populate it. */ url?: string } interface ContributorsOptions { /** * Pre-defined contributor information */ info?: ContributorInfo[] /** * Whether to include avatars in contributor information * @default false */ avatar?: boolean /** * The pattern for avatar URLs * - `:username` - Contributor's username * * @example 'https://github.com/:username' */ avatarPattern?: string /** * A function to transform the contributors list (e.g., to deduplicate or sort). * Accepts the list collected by the plugin and returns the transformed list. */ transform?: (contributors: GitContributorInfo[]) => GitContributorInfo[] } ``` * Default: `true` * Details: Whether to collect contributor information for the page. ### changelog * Type: `boolean | ChangelogOptions` ```ts interface ChangelogOptions { /** * The maximum number of changelog entries to collect */ maxCount?: number /** * The URL of the Git repository, e.g., https://github.com/vuepress/ecosystem */ repoUrl?: string /** * The pattern for commit URLs * * - `:repo` - The URL of the Git repository * - `:hash` - The hash of the commit * * @default ':repo/commit/:hash' */ commitUrlPattern?: string /** * The pattern for issue URLs * * - `:repo` - The URL of the Git repository * - `:issue` - The ID of the issue * * @default ':repo/issues/:issue' */ issueUrlPattern?: string /** * The pattern for tag URLs * * - `:repo` - The URL of the Git repository * - `:tag` - The name of the tag * * @default ':repo/releases/tag/:tag' */ tagUrlPattern?: string } ``` * Default: `false` * Details: Whether to collect the changelog for the page. ### filter * Type: `(page: Page) => boolean` * Details: A function to filter pages. Git information will only be collected if this function returns `true`. ### locales * Type: `Record` ```ts export interface GitLocaleData { /** * The title for the contributors section */ contributors: string /** * The title for the changelog section */ changelog: string /** * The text representing a commit "on" a specific date */ timeOn: string /** * The text for the "View Changelog" button */ viewChangelog: string /** * The text for "Latest Updated" */ latestUpdateAt: string } ``` * Details: Locale configuration, primarily used by the [Git Components](#component). ## Frontmatter ### gitInclude * Type: `string[]` * Details: An array of relative file paths. The Git history of these files will be included when calculating the current page's data (e.g., timestamps and contributors). * Example: ```md --- gitInclude: - relative/path/to/file1 - relative/path/to/file2 --- ``` ### contributors * Type: `boolean | string[]` * Details: Controls the collection of contributor information for the current page. This overrides the global [contributors](#contributors) option. * `true` - Enable collection. * `false` - Disable collection. * `string[]` - A list of additional contributors. Useful for manually specifying contributors who may not appear in the Git history. ### changelog * Type: `boolean` * Details: Whether to collect the changelog for the current page. This overrides the global [changelog](#changelog) option. ## Composables You can import the following composables from `@vuepress/plugin-git/client`. ### useChangelog Returns the changelog for the current page. ```ts export interface CoAuthorInfo { /** * Co-author name */ name: string /** * Co-author email */ email: string } export interface GitChangelogItem extends GitChangelogInfo { /** * Commit hash */ hash: string /** * Unix timestamp in milliseconds */ time: number /** * Commit message */ message: string /** * The URL of the commit */ commitUrl?: string /** * Release tag associated with the commit */ tag?: string /** * The URL of the release tag */ tagUrl?: string /** * Commit author name */ author: string /** * Commit author email */ email: string /** * The co-authors of the commit */ coAuthors?: CoAuthorInfo[] /** * Formatted date string of the commit */ date: string } export const useChangelog: ( enabled?: MaybeRefOrGetter, ) => ComputedRef ``` ### useContributors Returns the list of contributors for the current page. ```ts export interface GitContributorInfo { /** * Contributor display name */ name: string /** * Contributor email */ email: string /** * Contributor username on the Git hosting service */ username: string /** * Number of commits */ commits: number /** * Contributor avatar URL */ avatar?: string /** * Contributor profile URL */ url?: string } export const useContributors: ( enabled?: MaybeRefOrGetter, ) => ComputedRef ``` ### useLastUpdated Returns the last updated time of the current page. ```ts export interface LastUpdated { /** * The Date object of the last updated time */ date: Date /** * The ISO string of the last updated time */ iso: string /** * The formatted text of the last updated time */ text: string /** * The locale string for the date format */ locale: string } export const useLastUpdated: ( enabled?: MaybeRefOrGetter, ) => ComputedRef ``` ## Page Data This plugin injects a `git` field into the page data. You can access the collected Git information via the page data object: ```ts import type { GitPluginPageData } from '@vuepress/plugin-git' import { usePage } from 'vuepress/client' export default { setup(): void { const page = usePage() console.log(page.value.git) }, } ``` ### git.createdTime * Type: `number` * Details: The Unix timestamp (in milliseconds) of the page's first commit. This value reflects the earliest commit timestamp among the current page and any files listed in [gitInclude](#gitinclude). ### git.updatedTime * Type: `number` * Details: The Unix timestamp (in milliseconds) of the page's last commit. This value reflects the latest commit timestamp among the current page and any files listed in [gitInclude](#gitinclude). ### git.contributors * Type: `GitContributorInfo[]` ```ts interface GitContributorInfo { // display name name: string email: string // username on the git hosting service username: string commits: number avatar?: string url?: string } ``` * Details: The list of contributors for the page. This list includes contributors from the current page and any files listed in [gitInclude](#gitinclude). ### git.changelog * Type: `GitChangelogInfo[]` ```ts interface CoAuthorInfo { /** * Co-author name */ name: string /** * Co-author email */ email: string } interface GitChangelogInfo { /** * Commit hash */ hash: string /** * Unix timestamp in milliseconds */ time: number /** * Commit message */ message: string /** * The URL of the commit */ commitUrl?: string /** * Release tag associated with the commit */ tag?: string /** * The URL of the release tag */ tagUrl?: string /** * Commit author name */ author: string /** * Commit author email */ email: string /** * The co-authors of the commit */ coAuthors?: CoAuthorInfo[] } ``` * Details: The changelog for the page. This list includes commit history from the current page and any files listed in [gitInclude](#gitinclude). ## Git Component{#component} The plugin registers global components for displaying Git information, which can be easily used within themes. ### GitContributors Displays a list of contributors for the current page. ```vue{4} ``` **Preview:** ### GitChangelog Displays the changelog for the current page. ```vue{4} ``` **Preview:** --- --- url: /plugins/development/palette.md --- # palette Provide palette support for your theme. This plugin is primarily designed for theme development and has been integrated into the default theme. You typically won't need to use it directly in most cases. For theme authors, this plugin provides users with the ability to customize styles. ## Usage ```bash npm i -D @vuepress/plugin-palette@next ``` ```ts title=".vuepress/config.ts" import { palettePlugin } from '@vuepress/plugin-palette' export default { plugins: [ palettePlugin({ // options }), ], } ``` ## Palette and Style This plugin provides a `@vuepress/plugin-palette/palette` (palette file) and a `@vuepress/plugin-palette/style` (style file) for import in your theme styles. The palette file is used to define style variables, so it's typically imported at the beginning of your theme styles. For example, users can define [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties), [SASS variables](https://sass-lang.com/documentation/variables), [LESS variables](http://lesscss.org/features/#variables-feature), or [Stylus variables](https://stylus-lang.com/docs/variables.html) in the palette, and then you can use those variables in your theme styles. The style file is used to override default styles or add extra styles, so it's typically imported at the end of your theme styles. ## Usage Use this plugin in your theme, assuming you're using SASS: ```ts import { palettePlugin } from '@vuepress/plugin-palette' export default { // ... plugins: [ palettePlugin({ preset: 'sass' }), // ... ], } ``` ### Usage of Palette Import the plugin's palette file wherever your theme needs to use the corresponding variables, such as in the `Layout.vue` file: ```vue ``` Then users can customize variables in `.vuepress/styles/palette.scss`: ```scss $color: green; ``` ### Usage of Style Import the plugin's style file after your theme's styles, for example, in the `clientConfigFile`: ```ts // import your theme's style file import 'path/to/your/theme/style' // import the plugin's style file import '@vuepress/plugin-palette/style' ``` Then users can add extra styles in `.vuepress/styles/index.scss` and override your theme's default styles: ```scss h1 { font-size: 2.5rem; } ``` ## Options ### preset * Type: `'css' | 'less' | 'sass' | 'stylus'` * Default: `'css'` * Details: Set preset for other options. If you don't need advanced customization of the plugin, it's recommended to set only this option and omit others. ### userPaletteFile * Type: `string` * Default: * css: `'.vuepress/styles/palette.css'` * less: `'.vuepress/styles/palette.less'` * sass: `'.vuepress/styles/palette.scss'` * stylus: `'.vuepress/styles/palette.styl'` * Details: File path of the user palette file, relative to source directory. The default value depends on the [preset](#preset) option. This file is where users define style variables, and it's recommended to keep the default file path as a convention. ### tempPaletteFile * Type: `string` * Default: * css: `'styles/palette.css'` * less: `'styles/palette.less'` * sass: `'styles/palette.scss'` * stylus: `'styles/palette.styl'` * Details: File path of the generated palette temp file, relative to temp directory. The default value depends on the [preset](#preset) option. You should import the palette file via `'@vuepress/plugin-palette/palette'` alias, so you don't need to change this option in most cases. ### userStyleFile * Type: `string` * Default: * css: `'.vuepress/styles/index.css'` * less: `'.vuepress/styles/index.less'` * sass: `'.vuepress/styles/index.scss'` * stylus: `'.vuepress/styles/index.styl'` * Details: File path of the user style file, relative to source directory. The default value depends on the [preset](#preset) option. This file is where users override default styles or add extra styles, and it's recommended to keep the default file path as a convention. ### tempStyleFile * Type: `string` * Default: * css: `'styles/index.css'` * less: `'styles/index.less'` * sass: `'styles/index.scss'` * stylus: `'styles/index.styl'` * Details: File path of the generated style temp file, relative to temp directory. The default value depends on the [preset](#preset) option. You should import the style file via `'@vuepress/plugin-palette/style'` alias, so you don't need to change this option in most cases. ### importCode * Type: `(filePath: string) => string` * Default: * css: `` (filePath) => `@import '${filePath}';\n` `` * less: `` (filePath) => `@import '${filePath}';\n` `` * sass: `` (filePath) => `@forward 'file:///${filePath}';\n` `` * stylus: `` (filePath) => `@require '${filePath}';\n` `` * Details: Function to generate import code. The default value depends on the [preset](#preset) option. This option is used for generating [tempPaletteFile](#temppalettefile) and [tempStyleFile](#tempstylefile), and you don't need to change this option in most cases. --- --- url: /plugins/development/reading-time.md --- # reading-time This plugin analyzes your page content to generate word counts and estimated reading times. ## Usage ```bash npm i -D @vuepress/plugin-reading-time@next ``` ```ts title=".vuepress/config.ts" import { readingTimePlugin } from '@vuepress/plugin-reading-time' export default { plugins: [ readingTimePlugin({ // options }), ], } ``` ## Page Data (Node.js Side) The plugin calculates statistics for every page and injects them into the `page.data.readingTime` property. This object contains: * `minutes`: The estimated reading time in minutes (`number`). * `words`: The total word count (`number`). You can access this data directly within Node.js during the build process, such as inside the `extendsPage` or `onInitialized` lifecycles: ```ts export default { // ... extendsPage: (page) => { // Access reading time data for the current page being processed console.log(page.data.readingTime) // { minutes: 3.2, words: 934 } }, onInitialized: (app) => { // Iterate through all pages in the VuePress app app.pages.forEach((page) => { console.log(page.data.readingTime) // { minutes: 3.2, words: 934 } }) }, } ``` ## Composition API (Client Side) To display reading time information in your theme or components, you can use the composition APIs provided by the client module. Import `useReadingTimeData` for raw numbers or `useReadingTimeLocale` for localized strings: ```vue ``` ## Options ### wordPerMinute * Type: `number` * Default: `300` * Details: Reading speed in words per minute. ### locales * Type: `ReadingTimePluginLocaleConfig` ```ts interface ReadingTimePluginLocaleData { /** * Word template, `$word` will be automatically replaced by actual words */ word: string /** * Text for less than one minute */ less1Minute: string /** * Time template, `$time` will be automatically replaced by actual time */ time: string } interface ReadingTimePluginLocaleConfig { [localePath: string]: Partial } ``` * Details: Locale config for reading time text and word count text. ::: details Built-in Supported Languages * **Simplified Chinese** (zh-CN) * **Traditional Chinese** (zh-TW) * **English (United States)** (en-US) * **German** (de-DE) * **Russian** (ru-RU) * **Ukrainian** (uk-UA) * **Vietnamese** (vi-VN) * **Portuguese** (pt) * **Polish** (pl-PL) * **French** (fr-FR) * **Spanish** (es-ES) * **Slovak** (sk-SK) * **Japanese** (ja-JP) * **Turkish** (tr-TR) * **Korean** (ko-KR) * **Finnish** (fi-FI) * **Indonesian** (id-ID) * **Dutch** (nl-NL) ::: ## Client API You can import and use these APIs from `@vuepress/plugin-reading-time/client`: ::: tip These APIs won't throw errors even if you disable the plugin. ::: ### useReadingTimeData ```ts interface ReadingTime { /** Expected reading time in minutes */ minutes: number /** Words count of content */ words: number } const useReadingTimeData: () => ComputedRef ``` Returns `null` when the plugin is disabled. ### useReadingTimeLocale ```ts interface ReadingTimeLocale { /** Expected reading time text in locale */ time: string /** Word count text in locale */ words: string } const useReadingTimeLocale: () => ComputedRef ``` ## Theme Integration For plugin and theme authors, a programmatic "Use API" is available. This approach is recommended over adding the plugin to the `plugins` array directly in your theme, as it handles registration ordering and prevents duplicate registration. ```js title="your plugin or theme entry" import { useReadingTimePlugin } from '@vuepress/plugin-reading-time' export default (options) => (app) => { useReadingTimePlugin(app, { // your options }) return { name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx } } ``` ::: tip Why use the "Use API"? 1. **Singleton Pattern**: VuePress warns if a plugin is registered multiple times (where only the first takes effect). `useReadingTimePlugin` checks for existing instances and skips registration if already present. 2. **Execution Order**: If you rely on reading time data within the `extendsPage` lifecycle, the reading time plugin must execute *before* your code. `useReadingTimePlugin` ensures the correct initialization order so `page.data.readingTime` is available when you need it. ::: If you need to force a specific configuration or reset the plugin state, you can use `removeReadingTimePlugin`: ```js title="your plugin or theme entry" import { useReadingTimePlugin } from '@vuepress/plugin-reading-time' export default (options) => (app) => { // Remove any previously registered instances of the reading time plugin removeReadingTimePlugin(app) // Register the plugin again to ensure your specific options take precedence useReadingTimePlugin(app, { // your options }) return { name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx } } ``` --- --- url: /plugins/development/rtl.md --- # RTL This plugin sets text direction to RTL on configured locales. ## Usage ```bash npm i -D @vuepress/plugin-rtl@next ``` ```ts title=".vuepress/config.ts" import { rtlPlugin } from '@vuepress/plugin-rtl' export default { plugins: [ rtlPlugin({ // options locales: ['/ar/'], }), ], } ``` ## Demo ## Options ### locales * Type: `string[]` * Default: `['/']` * Details: RTL locale paths to enable RTL layout. ### selector * Type: `SelectorOptions` ```ts interface SelectorOptions { [cssSelector: string]: { [attr: string]: string } } ``` * Default: `{ 'html': { dir: 'rtl' } }` * Details: Selector configuration to enable RTL layout. The default settings mean that the `dir` attribute of the `html` element will be set to `rtl` in RTL locales. --- --- url: /plugins/development/sass-palette/index.md --- # sass-palette This plugin is mainly facing plugin and theme developers, it is more powerful than [`@vuepress/plugin-palette`](../palette.md). ::: tip You should manually install these deps in your project: * When using Vite bundler: `sass-embedded` * When using Webpack bundler: `sass-embedded` and `sass-loader` ::: ## Usage You must invoke `useSassPalettePlugin` function during plugin initialization to use this plugin. ```bash npm i -D @vuepress/plugin-sass-palette@next ``` ```js title="Your plugin or theme entry" import { useSassPalettePlugin } from '@vuepress/plugin-sass-palette' export const yourPlugin = (options) => (app) => { useSassPalettePlugin(app, { // plugin options }) return { // your plugin api } } ``` --- --- url: /plugins/development/sass-palette/config.md --- # Config ## Options ### id * Type: `string` * Required: Yes * Details: The unique identifier for the plugin instance. This is used to scope the style system and avoid conflicts between different plugins or themes. ### config * Type: `string` * Default: `` `.vuepress/styles/${id}-config.scss` `` * Details: The path to the user's Sass configuration file, relative to the source directory. ::: tip This file is where users define Sass variables. The default filename is prefixed with the `id` defined above. ::: ### defaultConfig * Type: `string` * Default: `"@vuepress/plugin-sass-palette/styles/default/config.scss"` * Details: The absolute path to the default Sass configuration file. ::: tip As a plugin developer, you should use this file to provide fallback values for variables using the `!default` flag. ::: ### palette * Type: `string` * Default: `` `.vuepress/styles/${id}-palette.scss` `` * Details: The path to the user's palette file, relative to the source directory. ::: tip This file allows users to control injected CSS variables. All variables defined here will be converted to kebab-case and injected into the CSS root. The default filename is prefixed with the `id` defined above. ::: ### defaultPalette * Type: `string` * Details: The absolute path to the default palette file. ::: tip As a plugin developer, you should use this file to provide default CSS variables via Sass variables using the `!default` flag. These will also be converted to kebab-case and injected. ::: ### generator * Type: `string` * Details: The absolute path to a custom generator file. This is used to derive new values based on the palette configuration. For example, you can use this to generate a `$theme-color-light` variable based on the `$theme-color` provided by the user. ### style * Type: `string` * Details: The path to the user's custom style file, relative to the source directory. This is used for standard CSS/Sass customization. ## Alias The following aliases are available for import: * **config**: `@sass-palette/${id}-config` (Derived from `id`) * **palette**: `@sass-palette/${id}-palette` (Derived from `id`) * **style**: `@sass-palette/${id}-style` (Only available when the `style` option is set) * **helper**: `@sass-palette/helper` --- --- url: /plugins/development/sass-palette/guide.md --- # Guide Compared to [`@vuepress/plugin-palette`](../palette.md), this plugin offers advanced styling capabilities: * **Derived Styles:** Generate related styles based on user configuration. * **Theme-like Customization:** Allow plugins to offer style customization similar to themes. * **Style Isolation/Sharing:** Group applications across multiple plugins or themes via the `id` option. To use this plugin effectively, you need to understand the **ID option** and three core styling concepts: **Configuration**, **Palette**, and **Generator**. ## ID Option This plugin is designed to work across both plugins and themes (unlike the official palette plugin, which is restricted to themes). The `id` option is the key mechanism for scoping. Calling `useSassPalette` creates a style system isolated by this ID. All generated aliases and module names will be prefixed with this ID. This mechanism allows you to: * **Share a style system:** By using the same ID, multiple plugins (or a theme and its plugins) can share variables. Since aliases are prefixed with the ID, you can use a unified set of style variables. Users can configure color variables, breakpoints, and other settings in a single file, and the changes will automatically apply to all themes and plugins using that ID. ::: tip Example `vuepress-theme-hope` uses the ID `hope`. Any plugin that also uses the ID `hope` will inherit the styles configured by the user for the theme. ::: * **Isolate styles:** By using different IDs, plugins will not affect each other. We recommend setting the `id` to your plugin name to ensure isolation. With default settings, users configure your plugin styles in the `.vuepress/styles` directory using Sass files starting with your ID. You access these variables via `${id}-config` and `${id}-palette`. ::: tip Example If `vuepress-theme-hope` uses ID `hope` and a separate plugin uses ID `abc`, they are completely independent. They access their specific variables via modules like `hope-config`/`hope-palette` and `abc-config`/`abc-palette` respectively. ::: * **Avoid side effects:** Calling the plugin multiple times with the same ID is safe and causes no conflicts. ## Config The **Config** file is dedicated to **Sass variables**. These variables can be accessed via the `${id}-config` module. You can specify a user configuration file (typically in `.vuepress/styles/`) and provide a default configuration file. The default file should use the `!default` flag to allow user overrides. ::: details Example Invoking the plugin in `vuepress-plugin-abc`: ```js useSassPalette(app, { id: 'abc', defaultConfig: 'vuepress-plugin-abc/styles/config.scss', }) ``` **User config file:** ```scss title=".vuepress/styles/abc-palette.scss" $navbar-height: 3.5rem; ``` **Default config file:** ```scss title="vuepress-plugin-abc/styles/palette.scss" $navbar-height: 2rem !default; $sidebar-width: 18rem !default; ``` **Usage in plugin Sass files:** ```scss // @endregex ::: ::: preview Network @startuml nwdiag { group nightly { color = "#FFAAAA"; description = "<\&clock> Restarted nightly <\&clock>"; web02; db01; } network dmz { address = "210.x.x.x/24" ``` user [description = "<&person*4.5>\n user1"]; web01 [address = "210.x.x.1, 210.x.x.20", description = "<&cog*4>\nweb01"] web02 [address = "210.x.x.2", description = "<&cog*4>\nweb02"]; ``` } network internal { address = "172.x.x.x/24"; ``` web01 [address = "172.x.x.1"]; web02 [address = "172.x.x.2"]; db01 [address = "172.x.x.100", description = "<&spreadsheet*4>\n db01"]; db02 [address = "172.x.x.101", description = "<&spreadsheet*4>\n db02"]; ptr [address = "172.x.x.110", description = "<&print*4>\n ptr01"]; ``` } } @enduml ::: ::: preview Salt @startsalt {+ {/ General | Fullscreen | Behavior | Saving } { { Open image in: | ^Smart Mode^ } \[X] Smooth images when zoomed \[X] Confirm image deletion \[ ] Show hidden images } \[Close] } @endsalt ::: ::: preview Archimate @startuml skinparam rectangle<> { roundCorner 25 } sprite $bProcess jar:archimate/business-process sprite $aService jar:archimate/application-service sprite $aComponent jar:archimate/application-component rectangle "Handle claim" as HC <<$bProcess>><> #Business rectangle "Capture Information" as CI <<$bProcess>><> #Business rectangle "Notify\nAdditional Stakeholders" as NAS <<$bProcess>><> #Business rectangle "Validate" as V <<$bProcess>><> #Business rectangle "Investigate" as I <<$bProcess>><> #Business rectangle "Pay" as P <<$bProcess>><> #Business HC \*-down- CI HC \*-down- NAS HC \*-down- V HC \*-down- I HC \*-down- P CI -right->> NAS NAS -right->> V V -right->> I I -right->> P rectangle "Scanning" as scanning <<$aService>><> #Application rectangle "Customer admnistration" as customerAdministration <<$aService>><> #Application rectangle "Claims admnistration" as claimsAdministration <<$aService>><> #Application rectangle Printing <<$aService>><> #Application rectangle Payment <<$aService>><> #Application scanning -up-> CI customerAdministration -up-> CI claimsAdministration -up-> NAS claimsAdministration -up-> V claimsAdministration -up-> I Payment -up-> P Printing -up-> V Printing -up-> P rectangle "Document\nManagement\nSystem" as DMS <<$aComponent>> #Application rectangle "General\nCRM\nSystem" as CRM <<$aComponent>> #Application rectangle "Home & Away\nPolicy\nAdministration" as HAPA <<$aComponent>> #Application rectangle "Home & Away\nFinancial\nAdministration" as HFPA <<$aComponent>> #Application DMS .up.|> scanning DMS .up.|> Printing CRM .up.|> customerAdministration HAPA .up.|> claimsAdministration HFPA .up.|> Payment legend left Example from the "Archisurance case study" (OpenGroup). See === # <$bProcess> :business process # <$aService> : application service <$aComponent> : application component endlegend @enduml ::: ::: preview Gantt @startgantt Project starts the 2020-12-01 \[Task1] requires 10 days sunday are closed note bottom memo1 ... memo2 ... explanations1 ... explanations2 ... end note \[Task2] requires 20 days \[Task2] starts 10 days after \[Task1]'s end \-- Separator title -- \[M1] happens on 5 days after \[Task1]'s end \-- end -- @endgantt ::: ::: preview Mindmap @startmindmap caption figure 1 title My super title * <\&flag>Debian \*\* <\&globe>Ubuntu \*\*\* Linux Mint \*\*\* Kubuntu \*\*\* Lubuntu \*\*\* KDE Neon \*\* <\&graph>LMDE \*\* <\&pulse>SolydXK \*\* <\&people>SteamOS \*\* <\&star>Raspbian with a very long name \*\*\* Raspmbc => OSMC \*\*\* Raspyfi => Volumio header My super header endheader center footer My super footer legend right Short legend endlegend @endmindmap ::: ::: preview WBS @startwbs * New Job ++ Decide on Job Requirements +++ Identity gaps +++ Review JDs ++++ Sign-Up for courses ++++ Volunteer ++++ Reading ++- Checklist +++- Responsibilities +++- Location ++ CV Upload Done +++ CV Updated ++++ Spelling & Grammar ++++ Check dates \---- Skills +++ Recruitment sites chosen @endwbs ::: ::: preview JSON @startjson \#highlight "lastName" \#highlight "address" / "city" \#highlight "phoneNumbers" / "0" / "number" { "firstName": "John", "lastName": "Smith", "isAlive": true, "age": 28, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021-3100" }, "phoneNumbers": \[ { "type": "home", "number": "212 555-1234" }, { "type": "office", "number": "646 555-4567" } ], "children": \[], "spouse": null } @endjson ::: ::: preview YAML @startyaml doe: "a deer, a female deer" ray: "a drop of golden sun" pi: 3.14159 xmas: true french-hens: 3 calling-birds: \- huey \- dewey \- louie \- fred xmas-fifth-day: calling-birds: four french-hens: 3 golden-rings: 5 partridges: count: 1 location: "a pear tree" turtle-doves: two @endyaml ::: --- --- url: /plugins/markdown/markdown-container.md --- # markdown-container Register markdown custom containers in your VuePress site. This plugin simplifies the use of [markdown-it-container](https://github.com/markdown-it/markdown-it-container), but also retains its original capabilities. ## Usage ```bash npm i -D @vuepress/plugin-markdown-container@next ``` ```ts title=".vuepress/config.ts" import { markdownContainerPlugin } from '@vuepress/plugin-markdown-container' export default { plugins: [ markdownContainerPlugin({ // options }), ], } ``` ## Container Syntax ```md ::: [info] [content] ::: ``` * The `type` is required and should be specified via [type](#type) option. * The `info` is optional, and the default value can be specified via `defaultInfo` in [locales](#locales) option. * The `content` can be any valid markdown content. ::: tip This plugin can be used multiple times to support different types of containers. ::: ## Options ### type * Type: `string` * Required: Yes * Details: The type of the container. It will be used as the `name` param of [markdown-it-container](https://github.com/markdown-it/markdown-it-container#api). ### locales * Type: `Record` * Default: `{}` * Details: The default `info` of the container in different locales. If this option is not specified, the default `info` will fallback to the uppercase of the [type](#type) option. * Example: ```ts title=".vuepress/config.ts" export default { plugins: [ markdownContainerPlugin({ type: 'tip', locales: { '/': { defaultInfo: 'TIP', }, '/zh/': { defaultInfo: 'ๆ็คบ', }, }, }), ], } ``` * Reference: * [Guide > I18n](https://vuejs.press/guide/i18n.html) ### before * Type: `(info: string) => string` * Default: ```ts ;(info: string): string => `
${info ? `

${info}

` : ''}\n` ``` * Details: A function to render the starting tag of the container. The first param is the `info` part of [container syntax](#container-syntax). This option will not take effect if you don't specify the [after](#after) option. ### after * Type: `(info: string) => string` * Default: ```ts ;(): string => '
\n' ``` * Details: A function to render the ending tag of the container. The first param is the `info` part of [container syntax](#container-syntax). This option will not take effect if you don't specify the [before](#before) option. ### render * Type: ```ts type MarkdownItContainerRenderFunction = ( tokens: Token[], index: number, options: unknown, env: MarkdownEnv, self: Renderer, ) => string ``` * Details: The `render` option of [markdown-it-container](https://github.com/markdown-it/markdown-it-container#api). This plugin uses a default `render` function. If you specify this option, the default `render` function will be replaced, and the [locales](#locales), [before](#before) and [after](#after) options will be ignored. ### validate * Type: `(params: string) => boolean` * Details: The `validate` option of [markdown-it-container](https://github.com/markdown-it/markdown-it-container#api). ### marker * Type: `string` * Default: `':'` * Details: The `marker` option of [markdown-it-container](https://github.com/markdown-it/markdown-it-container#api). --- --- url: /plugins/markdown/markdown-ext.md --- # markdown-ext Add basic GFM support to VuePress with useful features. ## Usage ```bash npm i -D @vuepress/plugin-markdown-ext@next ``` ```ts title=".vuepress/config.ts" import { markdownExtPlugin } from '@vuepress/plugin-markdown-ext' export default { plugins: [ markdownExtPlugin({ // options }), ], } ``` ## Syntax ### Footnote * Use `[^Anchor text]` in Markdown to define a footnote * Use `[^Anchor text]: ...` to describe footnote content * If there are multiple paragraphs in footnote, the paragraph show be double indented ::: preview Footnote 1 link\[^first]. Footnote 2 link\[^second]. Inline footnote^\[Text of inline footnote] definition. Duplicated footnote reference\[^second]. \[^first]: Footnote **can have markup** ``` and multiple paragraphs. ``` \[^second]: Footnote text. ::: ### Task list * Use `- [ ] some text` to render an unchecked task item. * Use `- [x] some text` to render a checked task item. (Capital `X` is also supported) ::: preview * \[ ] Plan A * \[x] Plan B ::: ### Component You can use component fence block to add a component into your markdown content. Both YAML and JSON format props data are supported: * YAML : ````md ```component ComponentName # component data here ``` ```` * JSON: ````md ```component ComponentName { // component data here } ``` ```` ::: preview ```component Badge text: Mr.Hope type: tip ``` ```component Badge { "text": "Mr.Hope", "type": "tip" } ``` ::: ### v-pre You can use any mustache syntax as raw text in `v-pre` container: :::: preview ::: v-pre {{ abc }} ::: :::: ## Options ### gfm * Type: `boolean` * Details: Whether tweaks the behavior and features to be more similar to GitHub Flavored Markdown. `markdown-it` already supports tables and strike through by default. If this option is `true`, the following new features will be enabled: * Auto link (named `linkify` in `markdown-it`) * Hard breaks * Footnote * Task list Note: Not all behavior is exactly the same as GitHub Flavored Markdown. ### footnote * Type: `boolean` * Details: Whether to enable footnote format support. * Enabled in GFM: Yes ### tasklist * Type: `MarkdownItTaskListOptions | boolean` ```ts interface MarkdownItTaskListOptions { /** * Whether disable checkbox * * @default true */ disabled?: boolean /** * Whether use `