Compare commits
23 Commits
073ab00ad3
...
d91a20e65c
| Author | SHA1 | Date | |
|---|---|---|---|
| d91a20e65c | |||
|
|
cfc89adab8 | ||
|
|
e0ba59a6f9 | ||
|
|
352874b29a | ||
|
|
c824ad85f4 | ||
|
|
db2eda82f3 | ||
|
|
e9fe35bc4f | ||
|
|
709ade741c | ||
|
|
d8b79e89e8 | ||
|
|
dbc6f0be0f | ||
|
|
9fe294b9dd | ||
|
|
ecf100cfc6 | ||
|
|
b7ee45642e | ||
|
|
54c05c8cea | ||
|
|
86cb872ce6 | ||
|
|
a6cb3820b1 | ||
|
|
184d1aee76 | ||
|
|
cbc5c55891 | ||
|
|
4f40f8441d | ||
|
|
fe0d4bbc92 | ||
|
|
39a76a35d7 | ||
|
|
a01bc13c66 | ||
|
|
1b213d4c28 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -15,3 +15,6 @@ dist/
|
|||||||
|
|
||||||
coverage/
|
coverage/
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
.claude/
|
||||||
|
!.claude/skills/
|
||||||
|
|||||||
499
CHANGELOG.md
499
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
111
CLAUDE.md
Normal file
111
CLAUDE.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
vuepress-theme-plume is a VuePress 2 theme monorepo for building blogs, documentation, and knowledge bases.
|
||||||
|
It includes a main theme, several plugins, a CLI tool, and example implementations.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install dependencies
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# Build all packages (required after clone, outputs to lib/)
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# Development - runs theme + docs dev servers concurrently
|
||||||
|
pnpm dev
|
||||||
|
|
||||||
|
# Lint (eslint + stylelint)
|
||||||
|
pnpm lint
|
||||||
|
pnpm lint:fix # auto-fix
|
||||||
|
|
||||||
|
# Run tests (vitest)
|
||||||
|
pnpm test
|
||||||
|
|
||||||
|
# Run a single test file
|
||||||
|
pnpm test src/path/to/file.spec.ts
|
||||||
|
|
||||||
|
# Run tests related to changed files (for pre-commit)
|
||||||
|
cross-env TZ=Etc/UTC vitest related --run
|
||||||
|
|
||||||
|
# Build docs only
|
||||||
|
pnpm docs:build
|
||||||
|
|
||||||
|
# Serve docs locally
|
||||||
|
pnpm docs:serve
|
||||||
|
|
||||||
|
# Release workflow
|
||||||
|
pnpm release # runs lint + build + version bump + changelog + git commit
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monorepo Structure
|
||||||
|
|
||||||
|
```txt
|
||||||
|
├── theme/ # Main VuePress theme (vuepress-theme-plume)
|
||||||
|
├── plugins/ # VuePress plugins
|
||||||
|
│ ├── plugin-search/ # Full-text fuzzy search
|
||||||
|
│ ├── plugin-md-power/ # Markdown enhancements
|
||||||
|
│ └── plugin-fonts/ # Special character font support
|
||||||
|
├── cli/ # CLI tool (create project scaffolding)
|
||||||
|
├── docs/ # Documentation site
|
||||||
|
└── examples/ # Example implementations
|
||||||
|
├── pure-blog/
|
||||||
|
└── layout-slots/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Theme Architecture
|
||||||
|
|
||||||
|
The theme is organized into three layers:
|
||||||
|
|
||||||
|
- **`src/node/`** - Build-time code (runs during `vuepress build/dev`)
|
||||||
|
- `prepare/` - Content preparation (frontmatter parsing, collection resolution)
|
||||||
|
- `plugins/` - VuePress plugin registration
|
||||||
|
- `config/` - Theme configuration handling
|
||||||
|
- `autoFrontmatter/` - Automatic frontmatter generation
|
||||||
|
|
||||||
|
- **`src/client/`** - Client-side code (runs in browser)
|
||||||
|
- `components/` - Vue components
|
||||||
|
- `composables/` - Vue composables (outline, search, etc.)
|
||||||
|
- `styles/` - CSS/SCSS styles
|
||||||
|
- `features/` - Feature-specific components and logic
|
||||||
|
|
||||||
|
- **`src/shared/`** - Shared code (used by both node and client)
|
||||||
|
- `frontmatter/` - Frontmatter schemas and utilities
|
||||||
|
- `locale/` - i18n translations
|
||||||
|
- `options.ts` - Theme options types
|
||||||
|
- `features/` - Feature flags and shared feature logic
|
||||||
|
|
||||||
|
## Build Output
|
||||||
|
|
||||||
|
Each package uses [tsdown](https://tsdown.dev/) to compile TypeScript. Build output goes to `lib/`:
|
||||||
|
|
||||||
|
- `lib/node/` - Node-side exports
|
||||||
|
- `lib/client/` - Client-side exports
|
||||||
|
- `lib/shared/` - Shared exports
|
||||||
|
|
||||||
|
The `lib/` directory is gitignored and must be built with `pnpm build`.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Tests use Vitest with coverage enabled. Test files are located at `**/__test__/**/*.spec.ts` and are excluded from coverage reports. Run tests with timezone fixed to UTC to ensure consistent results.
|
||||||
|
|
||||||
|
## Key Dependencies
|
||||||
|
|
||||||
|
- **VuePress**: v2.0.0-rc.28 with @vuepress/bundler-vite
|
||||||
|
- **Vue**: ^3.5.30
|
||||||
|
- **Shiki**: ^4.x for syntax highlighting
|
||||||
|
- **VueUse**: ^14.x for composables
|
||||||
|
- **markdown-it**: ^14.x for Markdown processing
|
||||||
|
|
||||||
|
## Development Notes
|
||||||
|
|
||||||
|
- Node.js 20.19.0+ required
|
||||||
|
- pnpm catalogs are used for dependency management (`dev`, `peer`, `prod`, `vuepress`)
|
||||||
|
- The theme depends on `vuepress-plugin-md-power` and `@vuepress-plume/plugin-search` as workspace dependencies
|
||||||
|
- Some peer dependencies are optional (e.g., artplayer, dashjs, three.js)
|
||||||
|
- Plugins (`plugins/*`) do not have dev commands — changes require `pnpm build` to take effect
|
||||||
|
- The `lib/` directory is gitignored and must be rebuilt after `pnpm install`
|
||||||
@ -19,7 +19,7 @@ In the `plugins` directory:
|
|||||||
|
|
||||||
Development requirements:
|
Development requirements:
|
||||||
|
|
||||||
- [Node.js](http://nodejs.org/) version 20.6.0+
|
- [Node.js](http://nodejs.org/) version 20.19.0+
|
||||||
- [pnpm](https://pnpm.io/zh/) version 9+
|
- [pnpm](https://pnpm.io/zh/) version 9+
|
||||||
|
|
||||||
Clone the repository and install dependencies:
|
Clone the repository and install dependencies:
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
开发要求:
|
开发要求:
|
||||||
|
|
||||||
- [Node.js](http://nodejs.org/) version 20.6.0+
|
- [Node.js](http://nodejs.org/) version 20.19.0+
|
||||||
- [pnpm](https://pnpm.io/zh/) version 9+
|
- [pnpm](https://pnpm.io/zh/) version 9+
|
||||||
|
|
||||||
克隆代码仓库,并安装依赖:
|
克隆代码仓库,并安装依赖:
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ---------------- | ------------------ |
|
| ---------------- | ------------------ |
|
||||||
| >= 1.0.0-rc.170 | :white_check_mark: |
|
| >= 1.0.0-rc.190 | :white_check_mark: |
|
||||||
| < 1.0.0-rc.170 | :x: |
|
| < 1.0.0-rc.190 | :x: |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "create-vuepress-theme-plume",
|
"name": "create-vuepress-theme-plume",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.0-rc.192",
|
"version": "1.0.0-rc.193",
|
||||||
"description": "The cli for create vuepress-theme-plume's project",
|
"description": "The cli for create vuepress-theme-plume's project",
|
||||||
"author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
|
"author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -27,7 +27,7 @@
|
|||||||
"templates"
|
"templates"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsdown"
|
"build": "tsdown --config-loader unrun"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@clack/prompts": "catalog:prod",
|
"@clack/prompts": "catalog:prod",
|
||||||
|
|||||||
@ -93,6 +93,12 @@ docs:
|
|||||||
logo: https://official.skycraft.cn/i/3.jpg
|
logo: https://official.skycraft.cn/i/3.jpg
|
||||||
url: https://docs.skycraft.cn/
|
url: https://docs.skycraft.cn/
|
||||||
preview: https://bbsimage.skycraft.cn/docs-preview.jpg
|
preview: https://bbsimage.skycraft.cn/docs-preview.jpg
|
||||||
|
-
|
||||||
|
name: mcenahle Docs
|
||||||
|
desc: mcenahle 的文档网站。
|
||||||
|
logo: https://d.mcenahle.cn/images/logo.png
|
||||||
|
url: https://d.mcenahle.cn/
|
||||||
|
preview: https://mcenahle.cn/resources/docs-site-preview.jpg
|
||||||
|
|
||||||
blog:
|
blog:
|
||||||
-
|
-
|
||||||
|
|||||||
@ -3,6 +3,9 @@ title: File Tree
|
|||||||
createTime: 2025/10/08 14:41:57
|
createTime: 2025/10/08 14:41:57
|
||||||
icon: mdi:file-tree
|
icon: mdi:file-tree
|
||||||
permalink: /en/guide/markdown/file-tree/
|
permalink: /en/guide/markdown/file-tree/
|
||||||
|
badge:
|
||||||
|
text: Change
|
||||||
|
type: warning
|
||||||
---
|
---
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
@ -18,7 +21,7 @@ displayed, simply add a slash `/` at the end of the list item.
|
|||||||
The following syntax can be used to customize the appearance of the file tree:
|
The following syntax can be used to customize the appearance of the file tree:
|
||||||
|
|
||||||
- Emphasize file or directory names by making them bold, e.g., `**README.md**`
|
- Emphasize file or directory names by making them bold, e.g., `**README.md**`
|
||||||
- Add comments to files or directories by adding additional text after the name
|
- Add comments to files or directories by appending a comment starting with `#` after the name, for example, `README.md This is a README file`
|
||||||
- Mark files or directories as **added** or **deleted** by prefixing the name with `++` or `--`
|
- Mark files or directories as **added** or **deleted** by prefixing the name with `++` or `--`
|
||||||
- Use `...` or `…` as the name to add placeholder files and directories.
|
- Use `...` or `…` as the name to add placeholder files and directories.
|
||||||
- Add `icon="simple"` or `icon="colored"` after `:::file-tree` to switch to simple icons or colored icons. The default is colored icons.
|
- Add `icon="simple"` or `icon="colored"` after `:::file-tree` to switch to simple icons or colored icons. The default is colored icons.
|
||||||
@ -34,7 +37,7 @@ The following syntax can be used to customize the appearance of the file tree:
|
|||||||
- ++ config.ts
|
- ++ config.ts
|
||||||
- -- page1.md
|
- -- page1.md
|
||||||
- README.md
|
- README.md
|
||||||
- theme A **theme** directory
|
- theme # A **theme** directory
|
||||||
- client
|
- client
|
||||||
- components
|
- components
|
||||||
- **Navbar.vue**
|
- **Navbar.vue**
|
||||||
@ -61,7 +64,7 @@ The following syntax can be used to customize the appearance of the file tree:
|
|||||||
- ++ config.ts
|
- ++ config.ts
|
||||||
- -- page1.md
|
- -- page1.md
|
||||||
- README.md
|
- README.md
|
||||||
- theme A **theme** directory
|
- theme # A **theme** directory
|
||||||
- client
|
- client
|
||||||
- components
|
- components
|
||||||
- **Navbar.vue**
|
- **Navbar.vue**
|
||||||
|
|||||||
@ -28,10 +28,10 @@ A typical VuePress static site has the following file structure:
|
|||||||
:::file-tree
|
:::file-tree
|
||||||
|
|
||||||
- my-site
|
- my-site
|
||||||
- docs \# Source directory
|
- docs # Source directory
|
||||||
- .vuepress/
|
- .vuepress/
|
||||||
- …
|
- …
|
||||||
- README.md \# Homepage
|
- README.md # Homepage
|
||||||
- package.json
|
- package.json
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|||||||
@ -13,22 +13,22 @@ For projects created via the [command-line tool](./usage.md#command-line-install
|
|||||||
::: file-tree
|
::: file-tree
|
||||||
|
|
||||||
- .git/
|
- .git/
|
||||||
- **docs** \# Documentation source directory
|
- **docs** # Documentation source directory
|
||||||
- .vuepress \# VuePress configuration directory
|
- .vuepress/ # VuePress configuration directory
|
||||||
- public/ \# Static assets
|
- public/ # Static assets
|
||||||
- client.ts \# Client configuration (optional)
|
- client.ts # Client configuration (optional)
|
||||||
- collections.ts \# Collections configuration (optional)
|
- collections.ts # Collections configuration (optional)
|
||||||
- config.ts \# VuePress main configuration
|
- config.ts # VuePress main configuration
|
||||||
- navbar.ts \# Navbar configuration (optional)
|
- navbar.ts # Navbar configuration (optional)
|
||||||
- plume.config.ts \# Theme configuration file (optional)
|
- plume.config.ts # Theme configuration file (optional)
|
||||||
- demo \# `doc` type collection
|
- demo # `doc` type collection
|
||||||
- foo.md
|
- foo.md
|
||||||
- bar.md
|
- bar.md
|
||||||
- blog \# `post` type collection
|
- blog # `post` type collection
|
||||||
- preview \# Blog category
|
- preview # Blog category
|
||||||
- markdown.md \# Category article
|
- markdown.md # Category article
|
||||||
- article.md \# Blog article
|
- article.md # Blog article
|
||||||
- README.md \# Site homepage
|
- README.md # Site homepage
|
||||||
- …
|
- …
|
||||||
- package.json
|
- package.json
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|||||||
@ -139,14 +139,14 @@ The numeric part serves as the **sorting basis**. Directories without numbers ar
|
|||||||
::: file-tree
|
::: file-tree
|
||||||
|
|
||||||
- docs
|
- docs
|
||||||
- blog \# post type collection
|
- blog # post type collection
|
||||||
- 1.Frontend
|
- 1.Frontend
|
||||||
- 1.html/
|
- 1.html/
|
||||||
- 2.css/
|
- 2.css/
|
||||||
- 3.javascript/
|
- 3.javascript/
|
||||||
- 2.Backend/
|
- 2.Backend/
|
||||||
- DevOps/
|
- DevOps/
|
||||||
- typescript \# doc type collection
|
- typescript # doc type collection
|
||||||
- 1.Basics
|
- 1.Basics
|
||||||
- 1.Variables.md
|
- 1.Variables.md
|
||||||
- 2.Types.md
|
- 2.Types.md
|
||||||
|
|||||||
@ -3,6 +3,9 @@ title: 文件树
|
|||||||
createTime: 2024/09/30 14:41:57
|
createTime: 2024/09/30 14:41:57
|
||||||
icon: mdi:file-tree
|
icon: mdi:file-tree
|
||||||
permalink: /guide/markdown/file-tree/
|
permalink: /guide/markdown/file-tree/
|
||||||
|
badge:
|
||||||
|
text: 变更
|
||||||
|
type: warning
|
||||||
---
|
---
|
||||||
|
|
||||||
## 概述
|
## 概述
|
||||||
@ -17,12 +20,19 @@ permalink: /guide/markdown/file-tree/
|
|||||||
以下语法可用于自定义文件树的外观:
|
以下语法可用于自定义文件树的外观:
|
||||||
|
|
||||||
- 通过加粗文件名或目录名来突出显示,例如 `**README.md**`
|
- 通过加粗文件名或目录名来突出显示,例如 `**README.md**`
|
||||||
- 通过在名称后添加更多文本来为文件或目录添加注释
|
- 通过在名称后添加以 `#` 开头的注释来为文件或目录添加注释,例如 `README.md # 这是一个 README 文件`
|
||||||
- 通过在名称前添加 `++` 或 `--` 来标记文件或目录为 **新增** 或 **删除**
|
- 通过在名称前添加 `++` 或 `--` 来标记文件或目录为 **新增** 或 **删除**
|
||||||
- 使用 `...` 或 `…` 作为名称来添加占位符文件和目录。
|
- 使用 `...` 或 `…` 作为名称来添加占位符文件和目录。
|
||||||
- 在 `:::file-tree` 后添加 `icon="simple"` 或 添加 `icon="colored"` 可以切换为简单图标或彩色图标,默认为彩色图标。
|
- 在 `:::file-tree` 后添加 `icon="simple"` 或 添加 `icon="colored"` 可以切换为简单图标或彩色图标,默认为彩色图标。
|
||||||
- 在 `:::file-tree` 后添加 `title="xxxx"` 可以为文件树添加标题。
|
- 在 `:::file-tree` 后添加 `title="xxxx"` 可以为文件树添加标题。
|
||||||
|
|
||||||
|
::: important `rc.193` 主题更新说明
|
||||||
|
过去 `file-tree` 使用 **空格** 来区分文件名和注释,这在某些情况下会导致问题,例如文件名中包含空格时。
|
||||||
|
为了解决这个问题,我们引入了 **# 号注释** 语法,您可以在文件名后添加以 `#` 开头的注释,例如 `README.md # 这是一个 README 文件`。
|
||||||
|
|
||||||
|
**此修改为 ==破坏性更新=={.danger} 更新。**
|
||||||
|
:::
|
||||||
|
|
||||||
**输入:**
|
**输入:**
|
||||||
|
|
||||||
```md /++/ /--/
|
```md /++/ /--/
|
||||||
@ -33,7 +43,7 @@ permalink: /guide/markdown/file-tree/
|
|||||||
- ++ config.ts
|
- ++ config.ts
|
||||||
- -- page1.md
|
- -- page1.md
|
||||||
- README.md
|
- README.md
|
||||||
- theme 一个 **主题** 目录
|
- theme # 一个 **主题** 目录
|
||||||
- client
|
- client
|
||||||
- components
|
- components
|
||||||
- **Navbar.vue**
|
- **Navbar.vue**
|
||||||
@ -60,7 +70,7 @@ permalink: /guide/markdown/file-tree/
|
|||||||
- ++ config.ts
|
- ++ config.ts
|
||||||
- -- page1.md
|
- -- page1.md
|
||||||
- README.md
|
- README.md
|
||||||
- theme 一个 **主题** 目录
|
- theme # 一个 **主题** 目录
|
||||||
- client
|
- client
|
||||||
- components
|
- components
|
||||||
- **Navbar.vue**
|
- **Navbar.vue**
|
||||||
|
|||||||
@ -27,10 +27,10 @@ permalink: /guide/collection/
|
|||||||
:::file-tree
|
:::file-tree
|
||||||
|
|
||||||
- my-site
|
- my-site
|
||||||
- docs \# 源目录
|
- docs # 源目录
|
||||||
- .vuepress/
|
- .vuepress/
|
||||||
- …
|
- …
|
||||||
- README.md \# 首页
|
- README.md # 首页
|
||||||
- package.json
|
- package.json
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|||||||
@ -12,22 +12,22 @@ permalink: /guide/project-structure/
|
|||||||
::: file-tree
|
::: file-tree
|
||||||
|
|
||||||
- .git/
|
- .git/
|
||||||
- **docs** \# 文档源目录
|
- **docs** # 文档源目录
|
||||||
- .vuepress \# VuePress 配置目录
|
- .vuepress/ # VuePress 配置目录
|
||||||
- public/ \# 静态资源
|
- public/ # 静态资源
|
||||||
- client.ts \# 客户端配置(可选)
|
- client.ts # 客户端配置(可选)
|
||||||
- collections.ts \# Collections 配置(可选)
|
- collections.ts # Collections 配置(可选)
|
||||||
- config.ts \# VuePress 主配置
|
- config.ts # VuePress 主配置
|
||||||
- navbar.ts \# 导航栏配置(可选)
|
- navbar.ts # 导航栏配置(可选)
|
||||||
- plume.config.ts \# 主题配置文件(可选)
|
- plume.config.ts # 主题配置文件(可选)
|
||||||
- demo \# `doc` 类型 collection
|
- demo # `doc` 类型 collection
|
||||||
- foo.md
|
- foo.md
|
||||||
- bar.md
|
- bar.md
|
||||||
- blog \# `post` 类型 collection
|
- blog # `post` 类型 collection
|
||||||
- preview \# 博客分类
|
- preview # 博客分类
|
||||||
- markdown.md \# 分类文章
|
- markdown.md # 分类文章
|
||||||
- article.md \# 博客文章
|
- article.md # 博客文章
|
||||||
- README.md \# 站点首页
|
- README.md # 站点首页
|
||||||
- …
|
- …
|
||||||
- package.json
|
- package.json
|
||||||
- pnpm-lock.yaml
|
- pnpm-lock.yaml
|
||||||
|
|||||||
@ -130,14 +130,14 @@ const dir = /\d+\.[\s\S]+/
|
|||||||
::: file-tree
|
::: file-tree
|
||||||
|
|
||||||
- docs
|
- docs
|
||||||
- blog \# post 类型 collection
|
- blog # post 类型 collection
|
||||||
- 1.前端
|
- 1.前端
|
||||||
- 1.html/
|
- 1.html/
|
||||||
- 2.css/
|
- 2.css/
|
||||||
- 3.javascript/
|
- 3.javascript/
|
||||||
- 2.后端/
|
- 2.后端/
|
||||||
- 运维/
|
- 运维/
|
||||||
- typescript \# doc 类型 collection
|
- typescript # doc 类型 collection
|
||||||
- 1.基础
|
- 1.基础
|
||||||
- 1.变量.md
|
- 1.变量.md
|
||||||
- 2.类型.md
|
- 2.类型.md
|
||||||
|
|||||||
20
package.json
20
package.json
@ -3,7 +3,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.0-rc.192",
|
"version": "1.0.0-rc.192",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@10.30.3",
|
"packageManager": "pnpm@10.33.0",
|
||||||
"author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
|
"author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@ -18,9 +18,9 @@
|
|||||||
"pnpm": ">=9"
|
"pnpm": ">=9"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm clean && pnpm build:package",
|
"build": "pnpm run clean && pnpm build:package",
|
||||||
"build:package": "pnpm -r --stream build",
|
"build:package": "pnpm -r --stream build",
|
||||||
"clean": "pnpm -r --stream clean",
|
"clean": "pnpm -r --stream run clean",
|
||||||
"dev": "pnpm --stream '/(dev:package|docs:dev)/'",
|
"dev": "pnpm --stream '/(dev:package|docs:dev)/'",
|
||||||
"dev:package": "pnpm --parallel dev",
|
"dev:package": "pnpm --parallel dev",
|
||||||
"docs:dev": "wait-on -d 100 theme/lib/node/index.js && pnpm -F=docs docs:dev",
|
"docs:dev": "wait-on -d 100 theme/lib/node/index.js && pnpm -F=docs docs:dev",
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"lint:css": "stylelint **/*.{css,vue}",
|
"lint:css": "stylelint **/*.{css,vue}",
|
||||||
"test": "cross-env TZ=Etc/UTC vitest --coverage",
|
"test": "cross-env TZ=Etc/UTC vitest --coverage",
|
||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
"release:changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
|
"release:changelog": "conventional-changelog -p angular",
|
||||||
"release:check": "pnpm lint && pnpm build",
|
"release:check": "pnpm lint && pnpm build",
|
||||||
"release:sync": "node scripts/mirror-sync.mjs",
|
"release:sync": "node scripts/mirror-sync.mjs",
|
||||||
"release:publish": "pnpm -r publish --tag latest",
|
"release:publish": "pnpm -r publish --tag latest",
|
||||||
@ -60,7 +60,8 @@
|
|||||||
"@vitest/coverage-v8": "catalog:dev",
|
"@vitest/coverage-v8": "catalog:dev",
|
||||||
"bumpp": "catalog:dev",
|
"bumpp": "catalog:dev",
|
||||||
"commitizen": "catalog:dev",
|
"commitizen": "catalog:dev",
|
||||||
"conventional-changelog-cli": "catalog:dev",
|
"conventional-changelog": "catalog:dev",
|
||||||
|
"conventional-changelog-angular": "catalog:dev",
|
||||||
"cpx2": "catalog:dev",
|
"cpx2": "catalog:dev",
|
||||||
"cross-env": "catalog:dev",
|
"cross-env": "catalog:dev",
|
||||||
"cz-conventional-changelog": "catalog:dev",
|
"cz-conventional-changelog": "catalog:dev",
|
||||||
@ -90,12 +91,19 @@
|
|||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@bufbuild/protobuf": "^2.11.0",
|
"@bufbuild/protobuf": "^2.11.0",
|
||||||
"@eslint-community/eslint-utils": "catalog:peer",
|
"@eslint-community/eslint-utils": "catalog:peer",
|
||||||
|
"@shikijs/core": "^4.0.2",
|
||||||
|
"@shikijs/twoslash": "^4.0.2",
|
||||||
"@typescript-eslint/types": "catalog:peer",
|
"@typescript-eslint/types": "catalog:peer",
|
||||||
"@typescript-eslint/utils": "catalog:peer",
|
"@typescript-eslint/utils": "catalog:peer",
|
||||||
"baseline-browser-mapping": "^2.10.0",
|
"@xmldom/xmldom": ">=0.9.9",
|
||||||
|
"baseline-browser-mapping": "^2.10.13",
|
||||||
"chokidar": "catalog:prod",
|
"chokidar": "catalog:prod",
|
||||||
"esbuild": "catalog:prod",
|
"esbuild": "catalog:prod",
|
||||||
|
"lodash": ">=4.18.1",
|
||||||
|
"lodash-es": ">=4.18.1",
|
||||||
"sass-embedded": "catalog:peer",
|
"sass-embedded": "catalog:peer",
|
||||||
|
"shiki": "^4.0.2",
|
||||||
|
"tmp": ">=0.2.5",
|
||||||
"vite": "catalog:dev",
|
"vite": "catalog:dev",
|
||||||
"vue-router": "catalog:prod"
|
"vue-router": "catalog:prod"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@vuepress-plume/plugin-fonts",
|
"name": "@vuepress-plume/plugin-fonts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.0-rc.192",
|
"version": "1.0.0-rc.193",
|
||||||
"description": "The Plugin for VuePress 2 - fonts",
|
"description": "The Plugin for VuePress 2 - fonts",
|
||||||
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -30,7 +30,7 @@
|
|||||||
"build": "pnpm run tsdown && pnpm run copy",
|
"build": "pnpm run tsdown && pnpm run copy",
|
||||||
"clean": "rimraf --glob ./lib",
|
"clean": "rimraf --glob ./lib",
|
||||||
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png,woff2}\" lib",
|
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png,woff2}\" lib",
|
||||||
"tsdown": "tsdown"
|
"tsdown": "tsdown --config-loader unrun"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vuepress": "catalog:vuepress"
|
"vuepress": "catalog:vuepress"
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
import { defineConfig } from 'tsdown'
|
import { defineConfig, type UserConfig } from 'tsdown'
|
||||||
import { argv } from '../../scripts/tsdown-args.mjs'
|
import { argv } from '../../scripts/tsdown-args'
|
||||||
|
|
||||||
/** @import {Options} from 'tsdown' */
|
|
||||||
|
|
||||||
const clientExternal = [
|
const clientExternal = [
|
||||||
/.*\.vue$/,
|
/.*\.vue$/,
|
||||||
@ -9,15 +7,13 @@ const clientExternal = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export default defineConfig(() => {
|
export default defineConfig(() => {
|
||||||
/** @type {Options} */
|
const DEFAULT_OPTIONS: UserConfig = {
|
||||||
const DEFAULT_OPTIONS = {
|
|
||||||
dts: true,
|
dts: true,
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
format: 'esm',
|
format: 'esm',
|
||||||
fixedExtension: false,
|
fixedExtension: false,
|
||||||
}
|
}
|
||||||
/** @type {Options[]} */
|
const options: UserConfig[] = []
|
||||||
const options = []
|
|
||||||
|
|
||||||
if (argv.node) {
|
if (argv.node) {
|
||||||
options.push({
|
options.push({
|
||||||
@ -36,7 +32,7 @@ export default defineConfig(() => {
|
|||||||
entry: ['./src/client/config.ts'],
|
entry: ['./src/client/config.ts'],
|
||||||
outDir: './lib/client',
|
outDir: './lib/client',
|
||||||
dts: false,
|
dts: false,
|
||||||
external: clientExternal,
|
deps: { neverBundle: clientExternal },
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ describe('fileTreePlugin', () => {
|
|||||||
- client
|
- client
|
||||||
- components
|
- components
|
||||||
- **Navbar.vue**
|
- **Navbar.vue**
|
||||||
- index.ts \# comment
|
- index.ts # comment
|
||||||
- node
|
- node
|
||||||
- index.ts
|
- index.ts
|
||||||
- .gitignore
|
- .gitignore
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "vuepress-plugin-md-power",
|
"name": "vuepress-plugin-md-power",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.0-rc.192",
|
"version": "1.0.0-rc.193",
|
||||||
"description": "The Plugin for VuePress 2 - markdown power",
|
"description": "The Plugin for VuePress 2 - markdown power",
|
||||||
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -36,8 +36,8 @@
|
|||||||
"clean": "rimraf --glob ./lib",
|
"clean": "rimraf --glob ./lib",
|
||||||
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib",
|
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib",
|
||||||
"copy:watch": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib -w",
|
"copy:watch": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib -w",
|
||||||
"tsdown": "tsdown",
|
"tsdown": "tsdown --config-loader unrun",
|
||||||
"tsdown:watch": "tsdown --watch -- -c"
|
"tsdown:watch": "tsdown --config-loader unrun --watch -- -c"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"artplayer": "catalog:peer",
|
"artplayer": "catalog:peer",
|
||||||
|
|||||||
@ -119,9 +119,9 @@ export function parseFileTreeNodeInfo(info: string): FileTreeNodeProps {
|
|||||||
|
|
||||||
// Extract filename and comment
|
// Extract filename and comment
|
||||||
if (filename === '' && !focus) {
|
if (filename === '' && !focus) {
|
||||||
const spaceIndex = info.indexOf(' ')
|
const sharpIndex = info.indexOf('#')
|
||||||
filename = info.slice(0, spaceIndex === -1 ? info.length : spaceIndex)
|
filename = info.slice(0, sharpIndex === -1 ? info.length : sharpIndex).trim()
|
||||||
info = spaceIndex === -1 ? '' : info.slice(spaceIndex)
|
info = sharpIndex === -1 ? '' : info.slice(sharpIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
comment = info.trim()
|
comment = info.trim()
|
||||||
|
|||||||
@ -559,11 +559,11 @@ export const definitions: Definitions = {
|
|||||||
'rolldown.config.prod.cjs': 'vscode-icons:file-type-light-rolldown',
|
'rolldown.config.prod.cjs': 'vscode-icons:file-type-light-rolldown',
|
||||||
'rolldown.config.prod.mjs': 'vscode-icons:file-type-light-rolldown',
|
'rolldown.config.prod.mjs': 'vscode-icons:file-type-light-rolldown',
|
||||||
'rolldown.config.prod.ts': 'vscode-icons:file-type-light-rolldown',
|
'rolldown.config.prod.ts': 'vscode-icons:file-type-light-rolldown',
|
||||||
'tsdown.config.js': 'vscode-icons:file-type-light-tsdown',
|
'tsdown.config.js': 'vscode-icons:file-type-tsdown',
|
||||||
'tsdown.config.cjs': 'vscode-icons:file-type-light-tsdown',
|
'tsdown.config.cjs': 'vscode-icons:file-type-tsdown',
|
||||||
'tsdown.config.mjs': 'vscode-icons:file-type-light-tsdown',
|
'tsdown.config.mjs': 'vscode-icons:file-type-tsdown',
|
||||||
'tsdown.config.ts': 'vscode-icons:file-type-light-tsdown',
|
'tsdown.config.ts': 'vscode-icons:file-type-tsdown',
|
||||||
'tsdown.config.json': 'vscode-icons:file-type-light-tsdown',
|
'tsdown.config.json': 'vscode-icons:file-type-tsdown',
|
||||||
|
|
||||||
'.oxlintignore': 'vscode-icons:file-type-oxc',
|
'.oxlintignore': 'vscode-icons:file-type-oxc',
|
||||||
'.oxlintrc.json': 'vscode-icons:file-type-oxc',
|
'.oxlintrc.json': 'vscode-icons:file-type-oxc',
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
import { defineConfig } from 'tsdown'
|
import { defineConfig, type UserConfig } from 'tsdown'
|
||||||
import { argv } from '../../scripts/tsdown-args.mjs'
|
import { argv } from '../../scripts/tsdown-args'
|
||||||
|
|
||||||
/** @import {Options} from 'tsdown' */
|
|
||||||
|
|
||||||
const config = [
|
const config = [
|
||||||
{ dir: 'composables', files: ['codeRepl.ts', 'pdf.ts', 'rustRepl.ts', 'size.ts', 'audio.ts', 'demo.ts', 'mark.ts', 'decrypt.ts'] },
|
{ dir: 'composables', files: ['codeRepl.ts', 'pdf.ts', 'rustRepl.ts', 'size.ts', 'audio.ts', 'demo.ts', 'mark.ts', 'decrypt.ts'] },
|
||||||
@ -18,8 +16,7 @@ const clientExternal = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export default defineConfig((cli) => {
|
export default defineConfig((cli) => {
|
||||||
/** @type {Options} */
|
const DEFAULT_OPTIONS: UserConfig = {
|
||||||
const DEFAULT_OPTIONS = {
|
|
||||||
dts: true,
|
dts: true,
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
format: 'esm',
|
format: 'esm',
|
||||||
@ -27,8 +24,7 @@ export default defineConfig((cli) => {
|
|||||||
fixedExtension: false,
|
fixedExtension: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {Options[]} */
|
const options: UserConfig[] = []
|
||||||
const options = []
|
|
||||||
|
|
||||||
// shared
|
// shared
|
||||||
options.push({
|
options.push({
|
||||||
@ -43,7 +39,7 @@ export default defineConfig((cli) => {
|
|||||||
entry: ['./src/node/index.ts'],
|
entry: ['./src/node/index.ts'],
|
||||||
outDir: './lib/node',
|
outDir: './lib/node',
|
||||||
target: 'node20.19.0',
|
target: 'node20.19.0',
|
||||||
external: ['markdown-it', /^@?vuepress/],
|
deps: { neverBundle: ['markdown-it', /^@?vuepress/] },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +48,7 @@ export default defineConfig((cli) => {
|
|||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: files.map(file => `./src/client/${dir}/${file}`),
|
entry: files.map(file => `./src/client/${dir}/${file}`),
|
||||||
outDir: `./lib/client/${dir}`,
|
outDir: `./lib/client/${dir}`,
|
||||||
external: clientExternal,
|
deps: { neverBundle: clientExternal },
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
return options
|
return options
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@vuepress-plume/plugin-search",
|
"name": "@vuepress-plume/plugin-search",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.0-rc.192",
|
"version": "1.0.0-rc.193",
|
||||||
"description": "The Plugin for VuePress 2 - local search",
|
"description": "The Plugin for VuePress 2 - local search",
|
||||||
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"build": "pnpm run tsdown && pnpm run copy",
|
"build": "pnpm run tsdown && pnpm run copy",
|
||||||
"clean": "rimraf --glob ./lib",
|
"clean": "rimraf --glob ./lib",
|
||||||
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib",
|
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib",
|
||||||
"tsdown": "tsdown"
|
"tsdown": "tsdown --config-loader unrun"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vuepress": "catalog:vuepress"
|
"vuepress": "catalog:vuepress"
|
||||||
|
|||||||
@ -31,6 +31,11 @@ export interface SearchIndexOptions {
|
|||||||
isSearchable: SearchPluginOptions['isSearchable']
|
isSearchable: SearchPluginOptions['isSearchable']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface UpdateSearchIndexOptions extends Omit<SearchIndexOptions, 'app'> {
|
||||||
|
/** VuePress page instance / VuePress 页面实例 */
|
||||||
|
page: Page
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal index object structure for MiniSearch.
|
* Internal index object structure for MiniSearch.
|
||||||
*
|
*
|
||||||
@ -165,29 +170,25 @@ export async function prepareSearchIndex({
|
|||||||
*
|
*
|
||||||
* 当页面被修改时处理搜索索引更新。
|
* 当页面被修改时处理搜索索引更新。
|
||||||
*
|
*
|
||||||
* @param filepath - Path of the modified file relative to project root / 相对于项目根目录的修改文件路径
|
* @param app - VuePress application instance / VuePress 应用实例
|
||||||
* @param options - Search index preparation options / 搜索索引准备选项
|
* @param options - Search index preparation options / 搜索索引准备选项
|
||||||
* @param options.app - VuePress application instance / VuePress 应用实例
|
* @param options.page - VuePress page instance / VuePress 页面实例
|
||||||
* @param options.isSearchable - Function to filter searchable pages / 过滤可搜索页面的函数
|
* @param options.isSearchable - Function to filter searchable pages / 过滤可搜索页面的函数
|
||||||
* @param options.searchOptions - MiniSearch configuration / MiniSearch 配置
|
* @param options.searchOptions - MiniSearch configuration / MiniSearch 配置
|
||||||
*/
|
*/
|
||||||
export async function onSearchIndexUpdated(
|
export async function onSearchIndexUpdated(
|
||||||
filepath: string,
|
app: App,
|
||||||
{
|
{
|
||||||
app,
|
page,
|
||||||
isSearchable,
|
isSearchable,
|
||||||
searchOptions,
|
searchOptions,
|
||||||
}: SearchIndexOptions,
|
}: UpdateSearchIndexOptions,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const pages = isSearchable ? app.pages.filter(isSearchable) : app.pages
|
if (isSearchable && !isSearchable(page))
|
||||||
if (pages.some(p => p.filePathRelative?.endsWith(filepath))) {
|
return
|
||||||
await indexFile(
|
|
||||||
app.pages.find(p => p.filePathRelative?.endsWith(filepath))!,
|
await indexFile(page, searchOptions, isSearchable)
|
||||||
searchOptions,
|
|
||||||
isSearchable,
|
|
||||||
)
|
|
||||||
await writeTemp(app)
|
await writeTemp(app)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -195,23 +196,24 @@ export async function onSearchIndexUpdated(
|
|||||||
*
|
*
|
||||||
* 当页面被删除时处理搜索索引更新。
|
* 当页面被删除时处理搜索索引更新。
|
||||||
*
|
*
|
||||||
* @param filepath - Path of the removed file relative to project root / 相对于项目根目录的删除文件路径
|
* @param app - VuePress application instance / VuePress 应用实例
|
||||||
* @param options - Search index preparation options / 搜索索引准备选项
|
* @param options - Search index preparation options / 搜索索引准备选项
|
||||||
* @param options.app - VuePress application instance / VuePress 应用实例
|
* @param options.page - VuePress page instance / VuePress 页面实例
|
||||||
* @param options.isSearchable - Function to filter searchable pages / 过滤可搜索页面的函数
|
* @param options.isSearchable - Function to filter searchable pages / 过滤可搜索页面的函数
|
||||||
* @param options.searchOptions - MiniSearch configuration / MiniSearch 配置
|
* @param options.searchOptions - MiniSearch configuration / MiniSearch 配置
|
||||||
*/
|
*/
|
||||||
export async function onSearchIndexRemoved(
|
export async function onSearchIndexRemoved(
|
||||||
filepath: string,
|
app: App,
|
||||||
{
|
{
|
||||||
app,
|
page,
|
||||||
isSearchable,
|
isSearchable,
|
||||||
searchOptions,
|
searchOptions,
|
||||||
}: SearchIndexOptions,
|
}: UpdateSearchIndexOptions,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const pages = isSearchable ? app.pages.filter(isSearchable) : app.pages
|
if (isSearchable && !isSearchable(page))
|
||||||
if (pages.some(p => p.filePathRelative?.endsWith(filepath))) {
|
return
|
||||||
const page = app.pages.find(p => p.filePathRelative?.endsWith(filepath))!
|
|
||||||
|
if (page.filePathRelative) {
|
||||||
const fileId = page.path
|
const fileId = page.path
|
||||||
const locale = page.pathLocale
|
const locale = page.pathLocale
|
||||||
const lang = page.lang
|
const lang = page.lang
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import type { Plugin } from 'vuepress/core'
|
import type { Plugin } from 'vuepress/core'
|
||||||
import type { SearchPluginOptions } from '../shared/index.js'
|
import type { SearchPluginOptions } from '../shared/index.js'
|
||||||
import { addViteOptimizeDepsInclude, getFullLocaleConfig } from '@vuepress/helper'
|
import { addViteOptimizeDepsInclude, getFullLocaleConfig } from '@vuepress/helper'
|
||||||
import chokidar from 'chokidar'
|
|
||||||
import { getDirname, path } from 'vuepress/utils'
|
import { getDirname, path } from 'vuepress/utils'
|
||||||
import { SEARCH_LOCALES } from './locales/index.js'
|
import { SEARCH_LOCALES } from './locales/index.js'
|
||||||
import { onSearchIndexRemoved, onSearchIndexUpdated, prepareSearchIndex, prepareSearchIndexPlaceholder } from './prepareSearchIndex.js'
|
import { onSearchIndexRemoved, onSearchIndexUpdated, prepareSearchIndex, prepareSearchIndexPlaceholder } from './prepareSearchIndex.js'
|
||||||
@ -72,22 +71,16 @@ export function searchPlugin({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onWatched: (app, watchers) => {
|
onPageUpdated: async (app, type, page) => {
|
||||||
const searchIndexWatcher = chokidar.watch('pages', {
|
if (!page?.filePathRelative)
|
||||||
cwd: app.dir.temp(),
|
return
|
||||||
ignoreInitial: true,
|
|
||||||
ignored: (filepath, stats) => Boolean(stats?.isFile()) && !filepath.endsWith('.js'),
|
if (type === 'create' || type === 'update') {
|
||||||
})
|
await onSearchIndexUpdated(app, { page, isSearchable, searchOptions })
|
||||||
searchIndexWatcher.on('add', (filepath) => {
|
}
|
||||||
onSearchIndexUpdated(filepath, { app, isSearchable, searchOptions })
|
else if (type === 'delete') {
|
||||||
})
|
await onSearchIndexRemoved(app, { page, isSearchable, searchOptions })
|
||||||
searchIndexWatcher.on('change', (filepath) => {
|
}
|
||||||
onSearchIndexUpdated(filepath, { app, isSearchable, searchOptions })
|
|
||||||
})
|
|
||||||
searchIndexWatcher.on('unlink', (filepath) => {
|
|
||||||
onSearchIndexRemoved(filepath, { app, isSearchable, searchOptions })
|
|
||||||
})
|
|
||||||
watchers.push(searchIndexWatcher)
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
import { defineConfig } from 'tsdown'
|
import { defineConfig, type UserConfig } from 'tsdown'
|
||||||
import { argv } from '../../scripts/tsdown-args.mjs'
|
import { argv } from '../../scripts/tsdown-args'
|
||||||
|
|
||||||
/** @import {Options} from 'tsdown' */
|
|
||||||
|
|
||||||
const sharedExternal = [
|
const sharedExternal = [
|
||||||
/.*\/shared\/index\.js$/,
|
/.*\/shared\/index\.js$/,
|
||||||
@ -15,16 +13,14 @@ const clientExternal = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export default defineConfig(() => {
|
export default defineConfig(() => {
|
||||||
/** @type {Options} */
|
const DEFAULT_OPTIONS: UserConfig = {
|
||||||
const DEFAULT_OPTIONS = {
|
|
||||||
dts: true,
|
dts: true,
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
format: 'esm',
|
format: 'esm',
|
||||||
fixedExtension: false,
|
fixedExtension: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {Options[]} */
|
const options: UserConfig[] = []
|
||||||
const options = []
|
|
||||||
|
|
||||||
// shared
|
// shared
|
||||||
options.push({
|
options.push({
|
||||||
@ -38,7 +34,7 @@ export default defineConfig(() => {
|
|||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: ['./src/node/index.ts'],
|
entry: ['./src/node/index.ts'],
|
||||||
outDir: './lib/node',
|
outDir: './lib/node',
|
||||||
external: sharedExternal,
|
deps: { neverBundle: sharedExternal },
|
||||||
target: 'node20.19.0',
|
target: 'node20.19.0',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -50,21 +46,21 @@ export default defineConfig(() => {
|
|||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: ['./src/client/utils/index.ts'],
|
entry: ['./src/client/utils/index.ts'],
|
||||||
outDir: './lib/client/utils',
|
outDir: './lib/client/utils',
|
||||||
external: clientExternal,
|
deps: { neverBundle: clientExternal },
|
||||||
},
|
},
|
||||||
// client/composables/index.js
|
// client/composables/index.js
|
||||||
{
|
{
|
||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: ['./src/client/composables/index.ts'],
|
entry: ['./src/client/composables/index.ts'],
|
||||||
outDir: './lib/client/composables',
|
outDir: './lib/client/composables',
|
||||||
external: clientExternal,
|
deps: { neverBundle: clientExternal },
|
||||||
},
|
},
|
||||||
// client/config.js
|
// client/config.js
|
||||||
{
|
{
|
||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: ['./src/client/config.ts'],
|
entry: ['./src/client/config.ts'],
|
||||||
outDir: './lib/client',
|
outDir: './lib/client',
|
||||||
external: clientExternal,
|
deps: { neverBundle: clientExternal },
|
||||||
dts: false,
|
dts: false,
|
||||||
},
|
},
|
||||||
// client/index.js
|
// client/index.js
|
||||||
@ -72,10 +68,10 @@ export default defineConfig(() => {
|
|||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: ['./src/client/index.ts'],
|
entry: ['./src/client/index.ts'],
|
||||||
outDir: './lib/client',
|
outDir: './lib/client',
|
||||||
external: [
|
deps: { neverBundle: [
|
||||||
...clientExternal,
|
...clientExternal,
|
||||||
'./composables/index.js',
|
'./composables/index.js',
|
||||||
],
|
] },
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
7220
pnpm-lock.yaml
generated
7220
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
|||||||
catalogMode: prefer
|
catalogMode: prefer
|
||||||
|
|
||||||
ignoreWorkspaceRootCheck: true
|
ignoreWorkspaceRootCheck: true
|
||||||
|
|
||||||
shamefullyHoist: true
|
shamefullyHoist: true
|
||||||
shellEmulator: true
|
shellEmulator: true
|
||||||
strictPeerDependencies: false
|
strictPeerDependencies: false
|
||||||
@ -9,117 +11,110 @@ trustPolicyExclude:
|
|||||||
- cached-factory
|
- cached-factory
|
||||||
- memfs
|
- memfs
|
||||||
- semver
|
- semver
|
||||||
- '@mdit/plugin-attrs'
|
|
||||||
- '@mdit/plugin-mark'
|
|
||||||
- '@mdit/plugin-sup'
|
|
||||||
- '@mdit/plugin-sub'
|
|
||||||
- '@mdit/plugin-tab'
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- docs
|
- docs
|
||||||
- theme
|
- theme
|
||||||
- cli
|
- cli
|
||||||
- plugins/*
|
- plugins/*
|
||||||
- examples/*
|
- examples/*
|
||||||
|
|
||||||
patchedDependencies:
|
patchedDependencies:
|
||||||
floating-vue: patches/floating-vue.patch
|
floating-vue: patches/floating-vue.patch
|
||||||
|
|
||||||
catalogs:
|
catalogs:
|
||||||
dev:
|
dev:
|
||||||
'@commitlint/cli': ^20.4.3
|
'@commitlint/cli': ^20.5.0
|
||||||
'@commitlint/config-conventional': ^20.4.3
|
'@commitlint/config-conventional': ^20.5.0
|
||||||
'@lunariajs/core': ^0.1.1
|
'@lunariajs/core': ^0.1.1
|
||||||
'@pengzhanbo/eslint-config-vue': ^2.1.0
|
'@pengzhanbo/eslint-config-vue': ^2.2.0
|
||||||
'@pengzhanbo/stylelint-config': ^2.1.0
|
'@pengzhanbo/stylelint-config': ^2.2.0
|
||||||
'@simonwep/pickr': ^1.9.1
|
'@simonwep/pickr': ^1.9.1
|
||||||
'@types/express': ^5.0.6
|
'@types/express': ^5.0.6
|
||||||
'@types/js-yaml': ^4.0.9
|
'@types/js-yaml': ^4.0.9
|
||||||
'@types/less': ^3.0.8
|
'@types/less': ^3.0.8
|
||||||
'@types/markdown-it': ^14.1.2
|
'@types/markdown-it': ^14.1.2
|
||||||
'@types/minimist': ^1.2.5
|
'@types/minimist': ^1.2.5
|
||||||
'@types/node': ^25.3.3
|
'@types/node': ^25.5.0
|
||||||
'@types/picomatch': ^4.0.2
|
'@types/picomatch': ^4.0.2
|
||||||
'@types/qrcode': ^1.5.6
|
'@types/qrcode': ^1.5.6
|
||||||
'@types/stylus': ^0.48.43
|
'@types/stylus': ^0.48.43
|
||||||
'@types/three': ^0.183.1
|
'@types/three': ^0.183.1
|
||||||
'@types/webpack-env': ^1.18.8
|
'@types/webpack-env': ^1.18.8
|
||||||
'@vitest/coverage-v8': ^4.0.18
|
'@vitest/coverage-v8': ^4.1.2
|
||||||
bumpp: ^10.4.1
|
bumpp: ^11.0.1
|
||||||
commitizen: ^4.3.1
|
commitizen: ^4.3.1
|
||||||
conventional-changelog-cli: ^5.0.0
|
conventional-changelog: ^7.2.0
|
||||||
|
conventional-changelog-angular: ^8.3.1
|
||||||
cpx2: ^8.0.0
|
cpx2: ^8.0.0
|
||||||
cross-env: 7.0.3
|
cross-env: 7.0.3
|
||||||
cz-conventional-changelog: ^3.3.0
|
cz-conventional-changelog: ^3.3.0
|
||||||
eslint: ^10.0.2
|
eslint: ^10.1.0
|
||||||
http-server: ^14.1.1
|
http-server: ^14.1.1
|
||||||
husky: ^9.1.7
|
husky: ^9.1.7
|
||||||
less: ^4.5.1
|
less: ^4.6.4
|
||||||
lint-staged: ^16.3.2
|
lint-staged: ^16.4.0
|
||||||
markdown-it: ^14.1.1
|
markdown-it: ^14.1.1
|
||||||
memfs: ^4.56.11
|
memfs: ^4.57.1
|
||||||
mermaid: ^11.12.3
|
mermaid: ^11.14.0
|
||||||
minimist: ^1.2.8
|
minimist: ^1.2.8
|
||||||
postcss: ^8.5.8
|
postcss: ^8.5.8
|
||||||
rimraf: ^6.1.3
|
rimraf: ^6.1.3
|
||||||
stylelint: ^17.4.0
|
stylelint: ^17.6.0
|
||||||
stylus: ^0.64.0
|
stylus: ^0.64.0
|
||||||
tsconfig-vuepress: ^7.0.0
|
tsconfig-vuepress: ^7.0.0
|
||||||
tsdown: ^0.20.3
|
tsdown: ^0.21.7
|
||||||
typescript: ^5.9.3
|
typescript: ^5.9.3
|
||||||
vite: ^8.0.0-beta.16
|
vite: ^8.0.3
|
||||||
vitest: ^4.0.18
|
vitest: ^4.1.2
|
||||||
wait-on: ^9.0.4
|
wait-on: ^9.0.4
|
||||||
peer:
|
peer:
|
||||||
'@eslint-community/eslint-utils': ^4.9.1
|
'@eslint-community/eslint-utils': ^4.9.1
|
||||||
'@iconify/json': ^2.2.446
|
'@iconify/json': ^2.2.458
|
||||||
'@mathjax/src': ^4.1.1
|
'@mathjax/src': ^4.1.1
|
||||||
'@pinyin-pro/data': ^1.3.1
|
'@pinyin-pro/data': ^1.3.1
|
||||||
'@typescript-eslint/types': ^8.56.1
|
'@typescript-eslint/types': ^8.58.0
|
||||||
'@typescript-eslint/utils': ^8.56.1
|
'@typescript-eslint/utils': ^8.58.0
|
||||||
artplayer: ^5.3.0
|
artplayer: ^5.4.0
|
||||||
dashjs: ^5.1.1
|
dashjs: ^5.1.1
|
||||||
gsap: ^3.14.2
|
gsap: ^3.14.2
|
||||||
hls.js: ^1.6.15
|
hls.js: ^1.6.15
|
||||||
mpegts.js: 1.7.3
|
mpegts.js: 1.7.3
|
||||||
ogl: ^1.0.11
|
ogl: ^1.0.11
|
||||||
pinyin-pro: ^3.28.0
|
pinyin-pro: ^3.28.0
|
||||||
postprocessing: ^6.38.3
|
postprocessing: ^6.39.0
|
||||||
pyodide: ^0.29.3
|
pyodide: ^0.29.3
|
||||||
sass: ^1.97.3
|
sass: ^1.98.0
|
||||||
sass-embedded: ^1.97.3
|
sass-embedded: ^1.98.0
|
||||||
swiper: ^12.1.2
|
swiper: ^12.1.3
|
||||||
three: ^0.183.2
|
three: ^0.183.2
|
||||||
prod:
|
prod:
|
||||||
'@clack/prompts': ^1.1.0
|
'@clack/prompts': ^1.2.0
|
||||||
'@iconify/utils': ^3.1.0
|
'@iconify/utils': ^3.1.0
|
||||||
'@iconify/vue': ^5.0.0
|
'@iconify/vue': ^5.0.0
|
||||||
'@mdit/plugin-attrs': ^0.25.1
|
'@mdit/plugin-attrs': ^0.25.2
|
||||||
'@mdit/plugin-footnote': ^0.23.1
|
'@mdit/plugin-footnote': ^0.23.2
|
||||||
'@mdit/plugin-mark': ^0.23.1
|
'@mdit/plugin-mark': ^0.23.2
|
||||||
'@mdit/plugin-sub': ^0.24.1
|
'@mdit/plugin-sub': ^0.24.2
|
||||||
'@mdit/plugin-sup': ^0.24.1
|
'@mdit/plugin-sup': ^0.24.2
|
||||||
'@mdit/plugin-tab': ^0.24.1
|
'@mdit/plugin-tab': ^0.24.2
|
||||||
'@mdit/plugin-tasklist': ^0.23.1
|
'@mdit/plugin-tasklist': ^0.23.2
|
||||||
'@pengzhanbo/utils': ^3.3.1
|
'@pengzhanbo/utils': ^3.3.1
|
||||||
'@vueuse/core': ^14.2.1
|
'@vueuse/core': ^14.2.1
|
||||||
'@vueuse/integrations': ^14.2.1
|
'@vueuse/integrations': ^14.2.1
|
||||||
cac: ^7.0.0
|
cac: ^7.0.0
|
||||||
chart.js: ^4.5.1
|
chart.js: ^4.5.1
|
||||||
chokidar: 5.0.0
|
chokidar: 5.0.0
|
||||||
dayjs: ^1.11.19
|
dayjs: ^1.11.20
|
||||||
echarts: ^6.0.0
|
echarts: ^6.0.0
|
||||||
esbuild: ^0.27.3
|
esbuild: ^0.27.5
|
||||||
flowchart.ts: ^3.0.1
|
flowchart.ts: ^3.0.1
|
||||||
focus-trap: ^8.0.0
|
focus-trap: ^8.0.1
|
||||||
gray-matter: ^4.0.3
|
gray-matter: ^4.0.3
|
||||||
handlebars: ^4.7.8
|
handlebars: ^4.7.9
|
||||||
hash-wasm: ^4.12.0
|
hash-wasm: ^4.12.0
|
||||||
image-size: ^2.0.2
|
image-size: ^2.0.2
|
||||||
js-yaml: ^4.1.1
|
js-yaml: ^4.1.1
|
||||||
katex: ^0.16.33
|
katex: ^0.16.44
|
||||||
local-pkg: ^1.1.2
|
local-pkg: ^1.1.2
|
||||||
lru-cache: ^11.2.6
|
lru-cache: ^11.2.7
|
||||||
mark.js: ^8.11.1
|
mark.js: ^8.11.1
|
||||||
markdown-it-cjk-friendly: ^2.0.2
|
markdown-it-cjk-friendly: ^2.0.2
|
||||||
markdown-it-container: ^4.0.0
|
markdown-it-container: ^4.0.0
|
||||||
@ -127,45 +122,44 @@ catalogs:
|
|||||||
markmap-toolbar: ^0.18.12
|
markmap-toolbar: ^0.18.12
|
||||||
markmap-view: ^0.18.12
|
markmap-view: ^0.18.12
|
||||||
minisearch: ^7.2.0
|
minisearch: ^7.2.0
|
||||||
nano-spawn: ^2.0.0
|
nano-spawn: ^2.1.0
|
||||||
nanoid: ^5.1.6
|
nanoid: ^5.1.7
|
||||||
os-locale: ^8.0.0
|
os-locale: ^8.0.0
|
||||||
p-map: ^7.0.4
|
p-map: ^7.0.4
|
||||||
package-manager-detector: ^1.6.0
|
package-manager-detector: ^1.6.0
|
||||||
picocolors: ^1.1.1
|
picocolors: ^1.1.1
|
||||||
picomatch: ^4.0.3
|
picomatch: ^4.0.4
|
||||||
qrcode: ^1.5.4
|
qrcode: ^1.5.4
|
||||||
shiki: ^4.0.1
|
shiki: ^4.0.2
|
||||||
sort-package-json: ^3.6.1
|
sort-package-json: ^3.6.1
|
||||||
tm-grammars: ^1.31.5
|
tm-grammars: ^1.31.15
|
||||||
tm-themes: ^1.12.1
|
tm-themes: ^1.12.2
|
||||||
vue: ^3.5.29
|
vue: ^3.5.31
|
||||||
vue-router: ^5.0.3
|
vue-router: ^5.0.4
|
||||||
vuepress:
|
vuepress:
|
||||||
'@vuepress/bundler-vite': 2.0.0-rc.26
|
'@vuepress/bundler-vite': 2.0.0-rc.28
|
||||||
'@vuepress/helper': 2.0.0-rc.123
|
'@vuepress/helper': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-cache': 2.0.0-rc.123
|
'@vuepress/plugin-cache': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-comment': 2.0.0-rc.123
|
'@vuepress/plugin-comment': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-copy-code': 2.0.0-rc.123
|
'@vuepress/plugin-copy-code': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-docsearch': 2.0.0-rc.123
|
'@vuepress/plugin-docsearch': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-git': 2.0.0-rc.123
|
'@vuepress/plugin-git': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-llms': 2.0.0-rc.123
|
'@vuepress/plugin-llms': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-markdown-chart': 2.0.0-rc.123
|
'@vuepress/plugin-markdown-chart': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-markdown-hint': 2.0.0-rc.123
|
'@vuepress/plugin-markdown-hint': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-markdown-image': 2.0.0-rc.123
|
'@vuepress/plugin-markdown-image': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-markdown-include': 2.0.0-rc.123
|
'@vuepress/plugin-markdown-include': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-markdown-math': 2.0.0-rc.123
|
'@vuepress/plugin-markdown-math': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-nprogress': 2.0.0-rc.123
|
'@vuepress/plugin-nprogress': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-photo-swipe': 2.0.0-rc.123
|
'@vuepress/plugin-photo-swipe': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-reading-time': 2.0.0-rc.123
|
'@vuepress/plugin-reading-time': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-replace-assets': 2.0.0-rc.123
|
'@vuepress/plugin-replace-assets': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-seo': 2.0.0-rc.123
|
'@vuepress/plugin-seo': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-shiki': 2.0.0-rc.123
|
'@vuepress/plugin-shiki': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-sitemap': 2.0.0-rc.123
|
'@vuepress/plugin-sitemap': 2.0.0-rc.128
|
||||||
'@vuepress/plugin-watermark': 2.0.0-rc.123
|
'@vuepress/plugin-watermark': 2.0.0-rc.128
|
||||||
'@vuepress/shiki-twoslash': 2.0.0-rc.123
|
'@vuepress/shiki-twoslash': 2.0.0-rc.128
|
||||||
vuepress: 2.0.0-rc.26
|
vuepress: 2.0.0-rc.28
|
||||||
|
|
||||||
onlyBuiltDependencies:
|
onlyBuiltDependencies:
|
||||||
- '@parcel/watcher'
|
- '@parcel/watcher'
|
||||||
- core-js
|
- core-js
|
||||||
|
|||||||
@ -33,9 +33,7 @@ async function npmMirrorSync() {
|
|||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
|
|
||||||
req.on('error', (error) => {
|
req.on('error', reject)
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
|
|
||||||
req.end()
|
req.end()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,16 +1,10 @@
|
|||||||
import process from 'node:process'
|
import process from 'node:process'
|
||||||
import minimist from 'minimist'
|
import minimist from 'minimist'
|
||||||
|
|
||||||
// interface ArgvOptions {
|
interface ArgvOptions {
|
||||||
// client: boolean
|
client: boolean
|
||||||
// node: boolean
|
node: boolean
|
||||||
// }
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {object} ArgvOptions
|
|
||||||
* @property {boolean} client - 是否构建客户端
|
|
||||||
* @property {boolean} node - 是否构建 node 端
|
|
||||||
*/
|
|
||||||
|
|
||||||
const rawArgv = process.argv.slice(2)
|
const rawArgv = process.argv.slice(2)
|
||||||
const tsupArgv = rawArgv.includes('--') ? rawArgv.slice(rawArgv.indexOf('--') + 1) : []
|
const tsupArgv = rawArgv.includes('--') ? rawArgv.slice(rawArgv.indexOf('--') + 1) : []
|
||||||
@ -30,8 +24,7 @@ const parsed = tsupArgv.length
|
|||||||
all: true,
|
all: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {ArgvOptions} */
|
export const argv: ArgvOptions = {
|
||||||
export const argv = {
|
|
||||||
client: parsed.client || parsed.all,
|
client: parsed.client || parsed.all,
|
||||||
node: parsed.node || parsed.all,
|
node: parsed.node || parsed.all,
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "vuepress-theme-plume",
|
"name": "vuepress-theme-plume",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.0-rc.192",
|
"version": "1.0.0-rc.193",
|
||||||
"description": "A Blog&Document Theme for VuePress 2.0",
|
"description": "A Blog&Document Theme for VuePress 2.0",
|
||||||
"author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
|
"author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -62,8 +62,8 @@
|
|||||||
"clean": "rimraf --glob ./lib",
|
"clean": "rimraf --glob ./lib",
|
||||||
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png,woff2}\" lib",
|
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png,woff2}\" lib",
|
||||||
"copy:watch": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png,woff2}\" lib -w",
|
"copy:watch": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png,woff2}\" lib -w",
|
||||||
"tsdown": "tsdown",
|
"tsdown": "tsdown --config-loader unrun",
|
||||||
"tsdown:watch": "tsdown --watch -- -c"
|
"tsdown:watch": "tsdown --config-loader unrun --watch -- -c"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@iconify/json": ">=2",
|
"@iconify/json": ">=2",
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import VPIcon from '@theme/VPIcon.vue'
|
import VPIcon from '@theme/VPIcon.vue'
|
||||||
import { computed, toRef } from 'vue'
|
import { computed, toRef } from 'vue'
|
||||||
import { useRouter, withBase } from 'vuepress/client'
|
import { useRouter, withBase } from 'vuepress/client'
|
||||||
import { useLink } from '../composables/index.js'
|
import { useData, useLink } from '../composables/index.js'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tag?: string
|
tag?: string
|
||||||
@ -21,7 +21,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
text: '',
|
text: '',
|
||||||
})
|
})
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { theme: themeData } = useData()
|
||||||
const component = computed(() => {
|
const component = computed(() => {
|
||||||
return props.tag || props.href ? 'a' : 'button'
|
return props.tag || props.href ? 'a' : 'button'
|
||||||
})
|
})
|
||||||
@ -44,12 +44,15 @@ function linkTo(e: Event) {
|
|||||||
:class="[size, theme]"
|
:class="[size, theme]"
|
||||||
:href=" link ? link[0] === '#' || isExternalProtocol ? link : withBase(link) : undefined"
|
:href=" link ? link[0] === '#' || isExternalProtocol ? link : withBase(link) : undefined"
|
||||||
:target="target ?? (isExternal ? '_blank' : undefined)"
|
:target="target ?? (isExternal ? '_blank' : undefined)"
|
||||||
:rel="rel ?? (isExternal ? 'noreferrer' : undefined)"
|
:rel="rel ?? (isExternal ? 'noopener noreferrer' : undefined)"
|
||||||
@click="linkTo($event)"
|
@click="linkTo($event)"
|
||||||
>
|
>
|
||||||
<span class="button-content">
|
<span class="button-content">
|
||||||
<VPIcon v-if="icon" :name="icon" />
|
<VPIcon v-if="icon" :name="icon" />
|
||||||
<slot><span>{{ text }}</span></slot>
|
<slot><span>{{ text }}</span></slot>
|
||||||
|
<span v-if="isExternal" class="visually-hidden">
|
||||||
|
{{ themeData.openNewWindowText || '(Open in new window)' }}
|
||||||
|
</span>
|
||||||
<VPIcon v-if="suffixIcon" :name="suffixIcon" />
|
<VPIcon v-if="suffixIcon" :name="suffixIcon" />
|
||||||
</span>
|
</span>
|
||||||
</Component>
|
</Component>
|
||||||
@ -73,6 +76,10 @@ function linkTo(e: Event) {
|
|||||||
background-color 0.1s;
|
background-color 0.1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vp-button:focus-visible {
|
||||||
|
outline-offset: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.vp-button.medium {
|
.vp-button.medium {
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
@ -51,6 +51,8 @@ async function onSubmit() {
|
|||||||
type="password"
|
type="password"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="theme.encryptPlaceholder ?? 'Enter Password'"
|
:placeholder="theme.encryptPlaceholder ?? 'Enter Password'"
|
||||||
|
:aria-invalid="errorCode === 1"
|
||||||
|
:aria-describedby="errorCode === 1 ? 'encrypt-error' : undefined"
|
||||||
@keyup.enter="onSubmit"
|
@keyup.enter="onSubmit"
|
||||||
@focus="!password && (errorCode = 0)"
|
@focus="!password && (errorCode = 0)"
|
||||||
@input="password && (errorCode = 0)"
|
@input="password && (errorCode = 0)"
|
||||||
|
|||||||
@ -138,6 +138,10 @@ function onBlur() {
|
|||||||
transition: color var(--vp-t-color);
|
transition: color var(--vp-t-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vp-flyout .button:focus-visible {
|
||||||
|
outline-offset: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.option-icon {
|
.option-icon {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, toRef } from 'vue'
|
import { computed, toRef } from 'vue'
|
||||||
import { useRouter, withBase } from 'vuepress/client'
|
import { useRouter, withBase } from 'vuepress/client'
|
||||||
import { useLink } from '../composables/index.js'
|
import { useData, useLink } from '../composables/index.js'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tag?: string
|
tag?: string
|
||||||
@ -13,6 +13,7 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { theme } = useData()
|
||||||
|
|
||||||
const tag = computed(() => props.tag ?? (props.href ? 'a' : 'span'))
|
const tag = computed(() => props.tag ?? (props.href ? 'a' : 'span'))
|
||||||
|
|
||||||
@ -32,11 +33,20 @@ function linkTo(e: Event) {
|
|||||||
class="vp-link" :class="{ link, 'no-icon': noIcon, 'vp-external-link-icon': isExternal }"
|
class="vp-link" :class="{ link, 'no-icon': noIcon, 'vp-external-link-icon': isExternal }"
|
||||||
:href="link ? isExternalProtocol ? link : isExternal ? link : withBase(link) : undefined"
|
:href="link ? isExternalProtocol ? link : isExternal ? link : withBase(link) : undefined"
|
||||||
:target="target ?? (isExternal ? '_blank' : undefined)"
|
:target="target ?? (isExternal ? '_blank' : undefined)"
|
||||||
:rel="rel ?? (isExternal ? 'noreferrer' : undefined)"
|
:rel="rel ?? (isExternal ? 'noopener noreferrer' : undefined)"
|
||||||
@click="linkTo($event)"
|
@click="linkTo($event)"
|
||||||
>
|
>
|
||||||
<slot>
|
<slot>
|
||||||
{{ text || href }}
|
{{ text || href }}
|
||||||
</slot>
|
</slot>
|
||||||
|
<span v-if="isExternal && !noIcon" class="visually-hidden">
|
||||||
|
{{ theme.openNewWindowText || '(Open in new window)' }}
|
||||||
|
</span>
|
||||||
</Component>
|
</Component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.vp-link:focus-visible {
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -58,12 +58,6 @@ function onItemInteraction(e: MouseEvent | Event) {
|
|||||||
toggle()
|
toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCaretClick() {
|
|
||||||
if (item.link) {
|
|
||||||
toggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -107,17 +101,16 @@ function onCaretClick() {
|
|||||||
/>
|
/>
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
<div
|
<button
|
||||||
v-if="item.collapsed != null"
|
v-if="item.collapsed != null"
|
||||||
|
type="button"
|
||||||
class="caret"
|
class="caret"
|
||||||
role="button"
|
:aria-label="`${collapsed ? 'Expand' : 'Collapse'} ${item.text}`"
|
||||||
aria-label="toggle section"
|
:aria-expanded="!collapsed"
|
||||||
tabindex="0"
|
tabindex="-1"
|
||||||
@click="onCaretClick"
|
|
||||||
@keydown.enter="onCaretClick"
|
|
||||||
>
|
>
|
||||||
<span class="vpi-chevron-right caret-icon" />
|
<span class="vpi-chevron-right caret-icon" />
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-if="item.items && item.items.length && depth < 5">
|
<template v-if="item.items && item.items.length && depth < 5">
|
||||||
|
|||||||
@ -56,6 +56,11 @@ const label = computed(() => {
|
|||||||
color: var(--vp-c-text-1);
|
color: var(--vp-c-text-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vp-social-link:focus-visible {
|
||||||
|
border-radius: 50%;
|
||||||
|
outline-offset: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.vp-social-link > :deep([class*="vpi-"]),
|
.vp-social-link > :deep([class*="vpi-"]),
|
||||||
.vp-social-link > :deep(.vp-icon.is-svg) {
|
.vp-social-link > :deep(.vp-icon.is-svg) {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
|||||||
@ -1,6 +1,16 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
defineProps<{
|
||||||
|
ariaChecked?: boolean
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- eslint-disable-next-line vue-a11y/role-has-required-aria-props -->
|
<button
|
||||||
<button class="vp-switch" type="button" role="switch">
|
class="vp-switch"
|
||||||
|
type="button"
|
||||||
|
role="switch"
|
||||||
|
:aria-checked="ariaChecked ?? false"
|
||||||
|
>
|
||||||
<span class="check">
|
<span class="check">
|
||||||
<span v-if="$slots.default" class="icon">
|
<span v-if="$slots.default" class="icon">
|
||||||
<slot />
|
<slot />
|
||||||
@ -28,6 +38,10 @@
|
|||||||
border-color: var(--vp-c-brand-1);
|
border-color: var(--vp-c-brand-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vp-switch:focus-visible {
|
||||||
|
outline-offset: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.check {
|
.check {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
|
|||||||
@ -6,6 +6,10 @@ import { enableTransitions, resolveTransitionKeyframes, useData } from '../compo
|
|||||||
const checked = ref(false)
|
const checked = ref(false)
|
||||||
const { theme, isDark } = useData()
|
const { theme, isDark } = useData()
|
||||||
|
|
||||||
|
watchPostEffect(() => {
|
||||||
|
checked.value = isDark.value
|
||||||
|
})
|
||||||
|
|
||||||
const transitionMode = computed(() => {
|
const transitionMode = computed(() => {
|
||||||
const transition = theme.value.transition
|
const transition = theme.value.transition
|
||||||
const options = typeof transition === 'object' ? transition : {}
|
const options = typeof transition === 'object' ? transition : {}
|
||||||
@ -15,8 +19,12 @@ const transitionMode = computed(() => {
|
|||||||
return typeof options.appearance === 'string' ? options.appearance : 'fade'
|
return typeof options.appearance === 'string' ? options.appearance : 'fade'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function shouldReduceMotion(): boolean {
|
||||||
|
return window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||||
|
}
|
||||||
|
|
||||||
const toggleAppearance = inject('toggle-appearance', async ({ clientX, clientY }: MouseEvent) => {
|
const toggleAppearance = inject('toggle-appearance', async ({ clientX, clientY }: MouseEvent) => {
|
||||||
if (!enableTransitions() || transitionMode.value === false) {
|
if (!enableTransitions() || transitionMode.value === false || shouldReduceMotion()) {
|
||||||
isDark.value = !isDark.value
|
isDark.value = !isDark.value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -80,6 +88,12 @@ watchPostEffect(() => {
|
|||||||
/* rtl:ignore */
|
/* rtl:ignore */
|
||||||
transform: translateX(18px);
|
transform: translateX(18px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.vp-switch-appearance :deep(.check) {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@ -104,6 +104,8 @@ export function useHeaders(): Ref<MenuItem[]> {
|
|||||||
return headers
|
return headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IGNORE_WRAPPERS = ['.vp-bulletin', '.vp-demo-wrapper']
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get headers from the page content
|
* Get headers from the page content
|
||||||
* Extracts and filters headings based on the outline configuration
|
* Extracts and filters headings based on the outline configuration
|
||||||
@ -117,7 +119,7 @@ export function useHeaders(): Ref<MenuItem[]> {
|
|||||||
export function getHeaders(range?: ThemeOutline): MenuItem[] {
|
export function getHeaders(range?: ThemeOutline): MenuItem[] {
|
||||||
const heading = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
|
const heading = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
|
||||||
const ignores = Array.from(document.querySelectorAll(
|
const ignores = Array.from(document.querySelectorAll(
|
||||||
heading.map(h => `.vp-demo-wrapper ${h}`).join(','),
|
heading.map(h => IGNORE_WRAPPERS.map(w => `${w} ${h}`)).flat().join(','),
|
||||||
))
|
))
|
||||||
const headers = Array.from(
|
const headers = Array.from(
|
||||||
document.querySelectorAll(heading.map(h => `.vp-doc ${h}`).join(',')),
|
document.querySelectorAll(heading.map(h => `.vp-doc ${h}`).join(',')),
|
||||||
|
|||||||
5
theme/src/client/styles/normalize.css
vendored
5
theme/src/client/styles/normalize.css
vendored
@ -262,6 +262,11 @@ figure {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:where(#app) :focus-visible {
|
||||||
|
outline: var(--vp-focus-ring-width) solid var(--vp-focus-ring-color);
|
||||||
|
outline-offset: var(--vp-focus-ring-offset);
|
||||||
|
}
|
||||||
|
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
|
|||||||
@ -703,3 +703,12 @@
|
|||||||
--vp-c-control-hover: var(--vp-c-default-2);
|
--vp-c-control-hover: var(--vp-c-default-2);
|
||||||
--vp-c-control-disabled: var(--vp-c-default-soft);
|
--vp-c-control-disabled: var(--vp-c-default-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Focus ring
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
:root {
|
||||||
|
--vp-focus-ring-color: var(--vp-c-brand-1);
|
||||||
|
--vp-focus-ring-width: 2px;
|
||||||
|
--vp-focus-ring-offset: 2px;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,75 +0,0 @@
|
|||||||
/**
|
|
||||||
* Temporary enhancement for VuePress app.
|
|
||||||
* This enhancement will be removed in the next version of vuepress/core.
|
|
||||||
*
|
|
||||||
* VuePress 应用的临时增强。
|
|
||||||
* 此增强将在 vuepress/core 的下一个版本中被移除。
|
|
||||||
*/
|
|
||||||
|
|
||||||
import type { App } from 'vuepress'
|
|
||||||
import { fs, hash } from 'vuepress/utils'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache structure for writeTemp operations.
|
|
||||||
* Tracks content hash and writing promises for optimization.
|
|
||||||
*
|
|
||||||
* writeTemp 操作的缓存结构。
|
|
||||||
* 跟踪内容哈希和写入承诺以进行优化。
|
|
||||||
*/
|
|
||||||
interface WriteTempCache {
|
|
||||||
/** Content hash for change detection / 用于变更检测的内容哈希 */
|
|
||||||
hash?: string
|
|
||||||
/** Current writing promise / 当前写入承诺 */
|
|
||||||
current?: Promise<void>
|
|
||||||
/** Next writing promise to chain / 要链接的下一个写入承诺 */
|
|
||||||
next?: () => Promise<void>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enhance the VuePress app with optimized writeTemp method.
|
|
||||||
* Implements caching and promise chaining for better performance.
|
|
||||||
*
|
|
||||||
* 使用优化的 writeTemp 方法增强 VuePress 应用。
|
|
||||||
* 实现缓存和承诺链接以获得更好的性能。
|
|
||||||
*
|
|
||||||
* @param app - VuePress application instance / VuePress 应用实例
|
|
||||||
*/
|
|
||||||
export function enhanceApp(app: App): void {
|
|
||||||
// rewrite writeTemp to cache the writing promise
|
|
||||||
const cache = new Map<string, WriteTempCache>()
|
|
||||||
app.writeTemp = async function (file: string, content: string): Promise<string> {
|
|
||||||
const filePath = app.dir.temp(file)
|
|
||||||
const contentHash = hash(content)
|
|
||||||
|
|
||||||
let item = cache.get(filePath)
|
|
||||||
if (!item) {
|
|
||||||
cache.set(filePath, (item = {}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// if content hash is the same as the last one, skip writing
|
|
||||||
if (item.hash === contentHash) {
|
|
||||||
return filePath
|
|
||||||
}
|
|
||||||
|
|
||||||
item.hash = contentHash
|
|
||||||
|
|
||||||
if (!item.current) {
|
|
||||||
item.current = (async () => {
|
|
||||||
await fs.outputFile(filePath, content)
|
|
||||||
// if there is a next writing promise, chain it with the current one
|
|
||||||
item.current = item.next?.()
|
|
||||||
return item.current
|
|
||||||
})()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// if there is a current writing promise, save the next writing promise
|
|
||||||
item.next = async () => {
|
|
||||||
await fs.outputFile(filePath, content)
|
|
||||||
item.next = undefined
|
|
||||||
item.current = undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await item.current
|
|
||||||
return filePath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -28,6 +28,8 @@ export const deLocale: ThemeLocaleText = {
|
|||||||
copyrightCreationReprintText: 'Nachdruck von:',
|
copyrightCreationReprintText: 'Nachdruck von:',
|
||||||
copyrightLicenseText: 'Lizenz:',
|
copyrightLicenseText: 'Lizenz:',
|
||||||
|
|
||||||
|
openNewWindowText: '(In neuem Fenster öffnen)',
|
||||||
|
|
||||||
notFound: {
|
notFound: {
|
||||||
code: '404',
|
code: '404',
|
||||||
title: 'Seite nicht gefunden',
|
title: 'Seite nicht gefunden',
|
||||||
|
|||||||
@ -22,6 +22,8 @@ export const enLocale: ThemeLocaleText = {
|
|||||||
copyrightCreationReprintText: 'This article is reprint from:',
|
copyrightCreationReprintText: 'This article is reprint from:',
|
||||||
copyrightLicenseText: 'License under:',
|
copyrightLicenseText: 'License under:',
|
||||||
|
|
||||||
|
openNewWindowText: '(Open in new window)',
|
||||||
|
|
||||||
encryptButtonText: 'Confirm',
|
encryptButtonText: 'Confirm',
|
||||||
encryptPlaceholder: 'Enter password',
|
encryptPlaceholder: 'Enter password',
|
||||||
encryptGlobalText: 'Only password can access this site',
|
encryptGlobalText: 'Only password can access this site',
|
||||||
|
|||||||
@ -28,6 +28,8 @@ export const frLocale: ThemeLocaleText = {
|
|||||||
copyrightCreationReprintText: 'Reproduit de :',
|
copyrightCreationReprintText: 'Reproduit de :',
|
||||||
copyrightLicenseText: 'Licence :',
|
copyrightLicenseText: 'Licence :',
|
||||||
|
|
||||||
|
openNewWindowText: '(Ouvrir dans une nouvelle fenêtre)',
|
||||||
|
|
||||||
notFound: {
|
notFound: {
|
||||||
code: '404',
|
code: '404',
|
||||||
title: 'Page non trouvée',
|
title: 'Page non trouvée',
|
||||||
|
|||||||
@ -28,6 +28,8 @@ export const jaLocale: ThemeLocaleText = {
|
|||||||
copyrightCreationReprintText: '本文の転載元:',
|
copyrightCreationReprintText: '本文の転載元:',
|
||||||
copyrightLicenseText: 'ライセンス:',
|
copyrightLicenseText: 'ライセンス:',
|
||||||
|
|
||||||
|
openNewWindowText: '(新しいウィンドウで開く)',
|
||||||
|
|
||||||
notFound: {
|
notFound: {
|
||||||
code: '404',
|
code: '404',
|
||||||
title: 'ページが見つかりません',
|
title: 'ページが見つかりません',
|
||||||
|
|||||||
@ -40,6 +40,8 @@ export const koLocale: ThemeLocaleText = {
|
|||||||
categoryText: '카테고리',
|
categoryText: '카테고리',
|
||||||
archiveTotalText: '{count}개의 글',
|
archiveTotalText: '{count}개의 글',
|
||||||
|
|
||||||
|
openNewWindowText: '(새 창에서 열기)',
|
||||||
|
|
||||||
notFound: {
|
notFound: {
|
||||||
code: '404',
|
code: '404',
|
||||||
title: '페이지를 찾을 수 없습니다',
|
title: '페이지를 찾을 수 없습니다',
|
||||||
|
|||||||
@ -28,6 +28,8 @@ export const ruLocale: ThemeLocaleText = {
|
|||||||
copyrightCreationReprintText: 'Перепечатано из:',
|
copyrightCreationReprintText: 'Перепечатано из:',
|
||||||
copyrightLicenseText: 'Лицензия:',
|
copyrightLicenseText: 'Лицензия:',
|
||||||
|
|
||||||
|
openNewWindowText: '(Открыть в новой вкладке)',
|
||||||
|
|
||||||
notFound: {
|
notFound: {
|
||||||
code: '404',
|
code: '404',
|
||||||
title: 'Страница не найдена',
|
title: 'Страница не найдена',
|
||||||
|
|||||||
@ -28,6 +28,8 @@ export const zhTwLocale: ThemeLocaleText = {
|
|||||||
copyrightCreationReprintText: '本文轉載自:',
|
copyrightCreationReprintText: '本文轉載自:',
|
||||||
copyrightLicenseText: '授權條款:',
|
copyrightLicenseText: '授權條款:',
|
||||||
|
|
||||||
|
openNewWindowText: '(在新窗口打開)',
|
||||||
|
|
||||||
notFound: {
|
notFound: {
|
||||||
code: '404',
|
code: '404',
|
||||||
title: '頁面未找到',
|
title: '頁面未找到',
|
||||||
|
|||||||
@ -27,6 +27,8 @@ export const zhLocale: ThemeLocaleText = {
|
|||||||
copyrightCreationReprintText: '本文转载自:',
|
copyrightCreationReprintText: '本文转载自:',
|
||||||
copyrightLicenseText: '许可证:',
|
copyrightLicenseText: '许可证:',
|
||||||
|
|
||||||
|
openNewWindowText: '(在新窗口打开)',
|
||||||
|
|
||||||
notFound: {
|
notFound: {
|
||||||
code: '404',
|
code: '404',
|
||||||
title: '页面未找到',
|
title: '页面未找到',
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import type { App } from 'vuepress'
|
import type { App } from 'vuepress'
|
||||||
import { watch } from 'chokidar'
|
|
||||||
import { perf } from '../utils/index.js'
|
import { perf } from '../utils/index.js'
|
||||||
import { prepareArticleTagColors } from './prepareArticleTagColor.js'
|
import { prepareArticleTagColors } from './prepareArticleTagColor.js'
|
||||||
import { prepareCollections } from './prepareCollections.js'
|
import { prepareCollections } from './prepareCollections.js'
|
||||||
@ -29,24 +28,3 @@ export async function prepareData(app: App): Promise<void> {
|
|||||||
|
|
||||||
perf.log('prepare:data')
|
perf.log('prepare:data')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Watch for changes in prepared data and re-prepare when needed
|
|
||||||
*
|
|
||||||
* 监听准备数据的变化,并在需要时重新准备数据
|
|
||||||
*/
|
|
||||||
export function watchPrepare(
|
|
||||||
app: App,
|
|
||||||
watchers: any[],
|
|
||||||
): void {
|
|
||||||
const pagesWatcher = watch('pages', {
|
|
||||||
cwd: app.dir.temp(),
|
|
||||||
ignoreInitial: true,
|
|
||||||
ignored: (filepath, stats) => Boolean(stats?.isFile()) && !filepath.endsWith('.js'),
|
|
||||||
})
|
|
||||||
watchers.push(pagesWatcher)
|
|
||||||
|
|
||||||
pagesWatcher.on('change', () => prepareData(app))
|
|
||||||
pagesWatcher.on('add', () => prepareData(app))
|
|
||||||
pagesWatcher.on('unlink', () => prepareData(app))
|
|
||||||
}
|
|
||||||
|
|||||||
@ -173,7 +173,7 @@ function getAutoDirSidebar(
|
|||||||
current.text = title
|
current.text = title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (frontmatter.icon) {
|
if (frontmatter.icon && dir.endsWith('.md')) {
|
||||||
current.icon = frontmatter.icon as ThemeIcon
|
current.icon = frontmatter.icon as ThemeIcon
|
||||||
}
|
}
|
||||||
if (parent?.items?.length) {
|
if (parent?.items?.length) {
|
||||||
@ -235,7 +235,12 @@ function getAllSidebar(): Record<string, ThemeSidebar> {
|
|||||||
const sidebar = locale === '/' ? (opt.sidebar || options.sidebar) : opt.sidebar
|
const sidebar = locale === '/' ? (opt.sidebar || options.sidebar) : opt.sidebar
|
||||||
locales[locale] = {}
|
locales[locale] = {}
|
||||||
for (const [key, value] of entries(sidebar || {})) {
|
for (const [key, value] of entries(sidebar || {})) {
|
||||||
locales[locale][ensureLeadingSlash(key)] = value
|
locales[locale][ensureLeadingSlash(key)] = isPlainObject(value) && 'items' in value
|
||||||
|
? { ...value, prefix: value.prefix?.startsWith('/') ? value.prefix : normalizeLink(locale, removeLeadingSlash(key)) }
|
||||||
|
: {
|
||||||
|
items: value,
|
||||||
|
prefix: normalizeLink(locale, removeLeadingSlash(key)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const collections = rawCollections?.filter(item => item.type === 'doc')
|
const collections = rawCollections?.filter(item => item.type === 'doc')
|
||||||
if (collections?.length) {
|
if (collections?.length) {
|
||||||
|
|||||||
@ -12,11 +12,10 @@ import {
|
|||||||
templateBuildRenderer,
|
templateBuildRenderer,
|
||||||
} from './config/index.js'
|
} from './config/index.js'
|
||||||
import { detectThemeOptions, detectVersions } from './detector/index.js'
|
import { detectThemeOptions, detectVersions } from './detector/index.js'
|
||||||
import { enhanceApp } from './enhance.js'
|
|
||||||
import { configLoader } from './loadConfig/index.js'
|
import { configLoader } from './loadConfig/index.js'
|
||||||
import { createPages, extendsPageData } from './pages/index.js'
|
import { createPages, extendsPageData } from './pages/index.js'
|
||||||
import { setupPlugins } from './plugins/index.js'
|
import { setupPlugins } from './plugins/index.js'
|
||||||
import { prepareData, watchPrepare } from './prepare/index.js'
|
import { prepareData } from './prepare/index.js'
|
||||||
import { prepareThemeData } from './prepare/prepareThemeData.js'
|
import { prepareThemeData } from './prepare/prepareThemeData.js'
|
||||||
import { perf, resolve, setTranslateLang, templates, THEME_NAME } from './utils/index.js'
|
import { perf, resolve, setTranslateLang, templates, THEME_NAME } from './utils/index.js'
|
||||||
|
|
||||||
@ -40,8 +39,6 @@ import { perf, resolve, setTranslateLang, templates, THEME_NAME } from './utils/
|
|||||||
*/
|
*/
|
||||||
export function plumeTheme(options: ThemeOptions = {}): Theme {
|
export function plumeTheme(options: ThemeOptions = {}): Theme {
|
||||||
return (app) => {
|
return (app) => {
|
||||||
enhanceApp(app)
|
|
||||||
|
|
||||||
setTranslateLang(app.options.lang)
|
setTranslateLang(app.options.lang)
|
||||||
perf.init(app.env.isDebug)
|
perf.init(app.env.isDebug)
|
||||||
|
|
||||||
@ -87,9 +84,12 @@ export function plumeTheme(options: ThemeOptions = {}): Theme {
|
|||||||
await prepareData(app)
|
await prepareData(app)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onPageUpdated: async (app) => {
|
||||||
|
await prepareData(app)
|
||||||
|
},
|
||||||
|
|
||||||
onWatched: async (app, watchers) => {
|
onWatched: async (app, watchers) => {
|
||||||
configLoader.watch(watchers as any)
|
configLoader.watch(watchers as any)
|
||||||
watchPrepare(app, watchers)
|
|
||||||
watchAutoFrontmatter(app, watchers as any)
|
watchAutoFrontmatter(app, watchers as any)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import type { MarkdownPowerPluginOptions } from 'vuepress-plugin-md-power'
|
|||||||
*/
|
*/
|
||||||
export interface MarkdownOptions extends MarkdownPowerPluginOptions,
|
export interface MarkdownOptions extends MarkdownPowerPluginOptions,
|
||||||
MarkdownChartPluginOptions,
|
MarkdownChartPluginOptions,
|
||||||
Pick<MarkdownHintPluginOptions, 'alert' | 'hint'> {
|
Partial<Pick<MarkdownHintPluginOptions, 'alert' | 'hint'>> {
|
||||||
/**
|
/**
|
||||||
* 已弃用
|
* 已弃用
|
||||||
* @deprecated use `demo` instead
|
* @deprecated use `demo` instead
|
||||||
|
|||||||
@ -339,6 +339,13 @@ export interface ThemeLocaleText {
|
|||||||
*/
|
*/
|
||||||
nextPageLabel?: string
|
nextPageLabel?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开新窗口的文本
|
||||||
|
*
|
||||||
|
* @default '(Open in new window)'
|
||||||
|
*/
|
||||||
|
openNewWindowText?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 404 页面配置
|
* 404 页面配置
|
||||||
*/
|
*/
|
||||||
@ -404,13 +411,44 @@ export interface ThemeLocaleText {
|
|||||||
*/
|
*/
|
||||||
encryptPlaceholder?: string
|
encryptPlaceholder?: string
|
||||||
|
|
||||||
|
// 以下字段与 PageContextMenu 相关 ------ start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制页面的文本
|
||||||
|
*/
|
||||||
copyPageText?: string
|
copyPageText?: string
|
||||||
|
/**
|
||||||
|
* 复制页面成功的文本
|
||||||
|
*/
|
||||||
copiedPageText?: string
|
copiedPageText?: string
|
||||||
|
/**
|
||||||
|
* 复制页面中的文本
|
||||||
|
*/
|
||||||
copingPageText?: string
|
copingPageText?: string
|
||||||
|
/**
|
||||||
|
* 复制页面的标签文本
|
||||||
|
*/
|
||||||
copyTagline?: string
|
copyTagline?: string
|
||||||
|
/**
|
||||||
|
* 查看 Markdown 文本
|
||||||
|
*/
|
||||||
viewMarkdown?: string
|
viewMarkdown?: string
|
||||||
|
/**
|
||||||
|
* 查看 Markdown 标签文本
|
||||||
|
*/
|
||||||
viewMarkdownTagline?: string
|
viewMarkdownTagline?: string
|
||||||
|
/**
|
||||||
|
* 咨询 AI 文本
|
||||||
|
*/
|
||||||
askAIText?: string
|
askAIText?: string
|
||||||
|
/**
|
||||||
|
* 咨询 AI 标签文本
|
||||||
|
*/
|
||||||
askAITagline?: string
|
askAITagline?: string
|
||||||
|
/**
|
||||||
|
* 咨询 AI 消息文本
|
||||||
|
*/
|
||||||
askAIMessage?: string
|
askAIMessage?: string
|
||||||
|
|
||||||
|
// 以上字段与 PageContextMenu 相关 ------ end
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import process from 'node:process'
|
import process from 'node:process'
|
||||||
import { defineConfig } from 'tsdown'
|
import { defineConfig, type UserConfig } from 'tsdown'
|
||||||
import { argv } from '../scripts/tsdown-args.mjs'
|
import { argv } from '../scripts/tsdown-args'
|
||||||
|
|
||||||
/** @import {Options} from 'tsdown' */
|
/** @import {Options} from 'tsdown' */
|
||||||
|
|
||||||
@ -24,25 +24,22 @@ const featuresComposables = fs.readdirSync(
|
|||||||
)
|
)
|
||||||
|
|
||||||
export default defineConfig((cli) => {
|
export default defineConfig((cli) => {
|
||||||
/** @type {Options} */
|
const DEFAULT_OPTIONS: UserConfig = {
|
||||||
const DEFAULT_OPTIONS = {
|
|
||||||
dts: true,
|
dts: true,
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
watch: cli.watch,
|
watch: cli.watch,
|
||||||
format: 'esm',
|
format: 'esm',
|
||||||
silent: !!cli.watch,
|
|
||||||
clean: !cli.watch,
|
clean: !cli.watch,
|
||||||
fixedExtension: false,
|
fixedExtension: false,
|
||||||
}
|
}
|
||||||
/** @type {Options[]} */
|
const options: UserConfig[] = []
|
||||||
const options = []
|
|
||||||
|
|
||||||
// shared
|
// shared
|
||||||
options.push({
|
options.push({
|
||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: ['./src/shared/index.ts'],
|
entry: ['./src/shared/index.ts'],
|
||||||
outDir: './lib/shared',
|
outDir: './lib/shared',
|
||||||
external: ['sax'],
|
deps: { neverBundle: ['sax'] },
|
||||||
})
|
})
|
||||||
|
|
||||||
if (argv.node) {
|
if (argv.node) {
|
||||||
@ -50,20 +47,20 @@ export default defineConfig((cli) => {
|
|||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: ['./src/node/index.ts'],
|
entry: ['./src/node/index.ts'],
|
||||||
outDir: './lib/node',
|
outDir: './lib/node',
|
||||||
external: [...sharedExternal, '@pinyin-pro/data/complete'],
|
deps: { neverBundle: [...sharedExternal, '@pinyin-pro/data/complete'] },
|
||||||
target: 'node20.19.0',
|
target: 'node20.19.0',
|
||||||
watch: false,
|
watch: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (argv.client) {
|
if (argv.client) {
|
||||||
options.push(...[
|
options.push(
|
||||||
// client/utils/index.js
|
// client/utils/index.js
|
||||||
{
|
{
|
||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: ['./src/client/utils/index.ts'],
|
entry: ['./src/client/utils/index.ts'],
|
||||||
outDir: './lib/client/utils',
|
outDir: './lib/client/utils',
|
||||||
platform: 'browser',
|
platform: 'browser',
|
||||||
external: clientExternal,
|
deps: { neverBundle: clientExternal },
|
||||||
},
|
},
|
||||||
// client/composables/index.js
|
// client/composables/index.js
|
||||||
{
|
{
|
||||||
@ -71,10 +68,10 @@ export default defineConfig((cli) => {
|
|||||||
entry: ['./src/client/composables/index.ts'],
|
entry: ['./src/client/composables/index.ts'],
|
||||||
outDir: './lib/client/composables',
|
outDir: './lib/client/composables',
|
||||||
platform: 'browser',
|
platform: 'browser',
|
||||||
external: [
|
deps: { neverBundle: [
|
||||||
...clientExternal,
|
...clientExternal,
|
||||||
'../utils/index.js',
|
'../utils/index.js',
|
||||||
],
|
] },
|
||||||
},
|
},
|
||||||
// client/config.js
|
// client/config.js
|
||||||
{
|
{
|
||||||
@ -83,11 +80,11 @@ export default defineConfig((cli) => {
|
|||||||
outDir: './lib/client',
|
outDir: './lib/client',
|
||||||
dts: false,
|
dts: false,
|
||||||
platform: 'browser',
|
platform: 'browser',
|
||||||
external: [
|
deps: { neverBundle: [
|
||||||
...clientExternal,
|
...clientExternal,
|
||||||
'./composables/index.js',
|
'./composables/index.js',
|
||||||
'./utils/index.js',
|
'./utils/index.js',
|
||||||
],
|
] },
|
||||||
},
|
},
|
||||||
// client/index.js
|
// client/index.js
|
||||||
{
|
{
|
||||||
@ -95,26 +92,26 @@ export default defineConfig((cli) => {
|
|||||||
entry: ['./src/client/index.ts'],
|
entry: ['./src/client/index.ts'],
|
||||||
outDir: './lib/client',
|
outDir: './lib/client',
|
||||||
platform: 'browser',
|
platform: 'browser',
|
||||||
external: [
|
deps: { neverBundle: [
|
||||||
...clientExternal,
|
...clientExternal,
|
||||||
'./composables/index.js',
|
'./composables/index.js',
|
||||||
'./utils/index.js',
|
'./utils/index.js',
|
||||||
'./config.js',
|
'./config.js',
|
||||||
],
|
] },
|
||||||
},
|
},
|
||||||
...featuresComposables.map(file => ({
|
...featuresComposables.map(file => ({
|
||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
entry: [`./src/client/features/composables/${file}`],
|
entry: [`./src/client/features/composables/${file}`],
|
||||||
outDir: `./lib/client/features/composables/`,
|
outDir: `./lib/client/features/composables/`,
|
||||||
platform: 'browser',
|
platform: 'browser',
|
||||||
external: [
|
deps: { neverBundle: [
|
||||||
...clientExternal,
|
...clientExternal,
|
||||||
'../../composables/index.js',
|
'../../composables/index.js',
|
||||||
'../../utils/index.js',
|
'../../utils/index.js',
|
||||||
...featuresComposables.map(file => `./${file.replace('.ts', '.js')}`),
|
...featuresComposables.map(file => `./${file.replace('.ts', '.js')}`),
|
||||||
],
|
] },
|
||||||
})),
|
} as UserConfig)),
|
||||||
])
|
)
|
||||||
}
|
}
|
||||||
return options
|
return options
|
||||||
})
|
})
|
||||||
@ -14,7 +14,8 @@
|
|||||||
"theme/**/*",
|
"theme/**/*",
|
||||||
"docs/.vuepress/**/*",
|
"docs/.vuepress/**/*",
|
||||||
"cli/**/*",
|
"cli/**/*",
|
||||||
"scripts/**/*"
|
"scripts/**/*",
|
||||||
|
"**/tsdown.config.ts"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"**/node_modules/**",
|
"**/node_modules/**",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user