feat(theme): migrate to @vuepress/plugin-replace-assets (#644)
This commit is contained in:
parent
cd1d457d31
commit
0fe98a38f1
@ -13,7 +13,6 @@ In the `plugins` directory:
|
||||
|
||||
- `plugin-search`: Provides full-text fuzzy search functionality for the theme.
|
||||
- `plugin-md-power`: Provides enhanced markdown features.
|
||||
- `plugin-replace-assets`: Provides resource link replacement functionality
|
||||
- `plugin-fonts`: Provides special character font support
|
||||
|
||||
## Development Configuration
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
- `plugin-search`: 为主题提供 全文模糊搜索 功能
|
||||
- `plugin-md-power`: 提供 markdown 增强功能
|
||||
- `plugin-replace-assets`: 提供资源链接替换功能
|
||||
- `plugin-fonts`: 提供特殊字符字体支持
|
||||
|
||||
## 开发配置
|
||||
|
||||
@ -8,11 +8,12 @@ badge: 新
|
||||
|
||||
## 概述
|
||||
|
||||
此功能由 [vuepress-plugin-replace-assets](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-replace-assets) 插件提供。
|
||||
此功能由 [@vuepress/plugin-replace-assets](https://ecosystem.vuejs.press/zh/plugins/tools/replace-assets.html) 插件提供。
|
||||
|
||||
替换站点内的本地资源链接,比如 图片、视频、音频、PDF 等资源的链接地址,将本地资源地址改写到新的地址。
|
||||
|
||||
::: tip 为什么需要这个功能?
|
||||
## 为什么需要这个功能?
|
||||
|
||||
不少用户会选择将站点的资源存放到 CDN 服务上,从而加速站点的访问速度,提升站点的可用性。
|
||||
|
||||
在这个过程中,通常需要先将资源上传到 CDN 服务,然后再获取 CDN 服务的资源链接,最后才在站点内容中使用。
|
||||
@ -26,10 +27,6 @@ badge: 新
|
||||
在此过程中,内容创作被频繁的打断。
|
||||
|
||||
此功能旨在解决这个问题。在内容创作过程中,只需要直接使用本地资源地址,由主题内部在合适的阶段,完成资源地址的替换。
|
||||
:::
|
||||
|
||||
::: important 此功能仅查找 `/` 开头的本地静态资源链接,比如 `/images/foo.jpg`
|
||||
:::
|
||||
|
||||
::: important 此功能不会修改源文件,仅在编译后的内容中进行替换
|
||||
:::
|
||||
@ -67,6 +64,56 @@ export default defineUserConfig({
|
||||
})
|
||||
```
|
||||
|
||||
### 资源管理
|
||||
|
||||
**你应该将资源存放在 [.vuepress/public](https://v2.vuepress.vuejs.org/zh/guide/assets.html#public-%E6%96%87%E4%BB%B6) 目录下**:
|
||||
|
||||
```sh
|
||||
./docs
|
||||
├── .vuepress
|
||||
│ └── public # [!code hl:6]
|
||||
│ ├── images
|
||||
│ │ ├── foo.jpg
|
||||
│ │ └── bar.jpg
|
||||
│ └── medias
|
||||
│ └── foo.mp4
|
||||
└── README.md
|
||||
```
|
||||
|
||||
::: tip 为什么需要存放在这个目录下?
|
||||
当站点完成编译准备部署前,我们可以很方便地直接将这个目录下的文件上传到 CDN 。
|
||||
:::
|
||||
|
||||
在 markdown 中,直接使用本地资源地址:
|
||||
|
||||
```md
|
||||

|
||||
|
||||
<img src="/images/foo.jpg">
|
||||
```
|
||||
|
||||
在 `javascript` 中:
|
||||
|
||||
```js
|
||||
const foo = '/images/foo.jpg'
|
||||
|
||||
const img = document.createElement('img')
|
||||
img.src = '/images/foo.jpg'
|
||||
```
|
||||
|
||||
以及在 样式文件 中:
|
||||
|
||||
```css
|
||||
.foo {
|
||||
background: url('/images/foo.jpg');
|
||||
}
|
||||
```
|
||||
|
||||
插件会正确识别这些资源,并在编译后的内容中进行替换。
|
||||
|
||||
:::warning 插件不支持识别 `'/images/' + 'foo.jpg'` 拼接的路径。
|
||||
:::
|
||||
|
||||
## 配置说明
|
||||
|
||||
```ts
|
||||
@ -120,11 +167,11 @@ interface ReplaceAssetsOptions {
|
||||
|
||||
为便于使用,主题插件内部提供了内置的资源匹配规则,你可以直接使用它们。
|
||||
|
||||
- `image`: 查找图片资源,包括 `['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'avif']` 格式的本地图片资源链接
|
||||
- `media`: 查找媒体资源,包括 `['mp4', 'webm', 'ogg', 'mp3', 'wav', 'flac', 'aac', 'm3u8', 'm3u', 'flv', 'pdf']` 格式的本地媒体资源链接
|
||||
- `image`: 查找图片资源,包括 `['apng','bmp','png','jpeg','jpg','jfif','pjpeg','pjp','gif','svg','ico','webp','avif','cur','jxl']` 格式的本地图片资源链接
|
||||
- `media`: 查找媒体资源,包括 `['mp4','webm','ogg','mp3','wav','flac','aac','opus','mov','m4a','vtt','pdf']` 格式的本地媒体资源链接
|
||||
- `all`: 查找 图片 和 媒体资源,即 `image` 和 `media` 的合集
|
||||
|
||||
直接传入 __资源链接前缀__ 或 __资源链接替换函数__ 时,主题使用 `all` 规则替换资源链接。
|
||||
直接传入 **资源链接前缀** 或 **资源链接替换函数** 时,主题使用 `all` 规则替换资源链接。
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import process from 'node:process'
|
||||
@ -204,11 +251,11 @@ export default defineUserConfig({
|
||||
})
|
||||
```
|
||||
|
||||
__`find` 字段说明__
|
||||
**`find` 字段说明**
|
||||
|
||||
`find` 字段用于匹配资源链接,可以是一个 __正则表达式__ 或 __字符串__。
|
||||
`find` 字段用于匹配资源链接,可以是一个 **正则表达式** 或 **字符串**。
|
||||
|
||||
当传入的是一个 `字符串` 时,如果是以 `^` 开头或者以 `$` 结尾的字符串,则会自动转换为一个 __正则表达式__。
|
||||
当传入的是一个 `字符串` 时,如果是以 `^` 开头或者以 `$` 结尾的字符串,则会自动转换为一个 **正则表达式**。
|
||||
否则则会检查资源链接是否 以 `find` 结尾 或者 以 `find` 开头。
|
||||
|
||||
```txt
|
||||
@ -217,3 +264,4 @@ __`find` 字段说明__
|
||||
```
|
||||
|
||||
::: important 所有匹配的资源地址都是以 `/` 开头。
|
||||
:::
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2021 - PRESENT by pengzhanbo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@ -1,51 +0,0 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`plugin-replace-assets > transformAssets > should work with like css 1`] = `
|
||||
".foo {
|
||||
background-image: url("https://example.com/assets/images/foo.jpg");
|
||||
background-image: url("https://example.com/assets/images/foo.png");
|
||||
background-image: url("https://example.com/assets/images/foo.gif");
|
||||
background-image: url("https://example.com/assets/images/foo.svg");
|
||||
background-image: url("https://example.com/assets/medias/foo.mp4");
|
||||
|
||||
background-image: url("https://example.com/assets/images/foo.jpg");
|
||||
background-image: url("https://example.com/assets/images/foo.png");
|
||||
|
||||
background-image: url("https://example.com/assets/images/foo.jpg?a=1");
|
||||
|
||||
background-image: url("https://not-replace.com/images/foo.jpg");
|
||||
|
||||
background: url("https://example.com/assets/images/foo.png");
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`plugin-replace-assets > transformAssets > should work with like html 1`] = `
|
||||
"<img src="https://example.com/assets/images/foo.jpg" />
|
||||
<img src="https://example.com/assets/images/foo.png" />
|
||||
<img src="https://example.com/assets/images/foo.gif" />
|
||||
<img src="https://example.com/assets/images/foo.svg" />
|
||||
<img src="/images/foo.txt" />
|
||||
<img src="https://example.com/assets/medias/foo.mp4" />
|
||||
|
||||
<img src="https://example.com/assets/images/foo.jpg?a=1" />
|
||||
|
||||
<img src="https://not-replace.com/images/foo.jpg" />
|
||||
|
||||
<video src="https://example.com/assets/medias/foo.mp4" />
|
||||
<audio src="https://example.com/assets/medias/foo.mp3" />
|
||||
|
||||
<embed src="https://example.com/assets/medias/foo.pdf" />
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`plugin-replace-assets > transformAssets > should work with like js 1`] = `
|
||||
" const a = "https://example.com/assets/images/foo.jpg"
|
||||
const b = "https://example.com/assets/images/foo.jpg"
|
||||
const c = "https://example.com/assets/images/foo.jpg?a=1"
|
||||
const d = "https://not-replace.com/images/foo.jpg"
|
||||
|
||||
const json_string = JSON.parse("{\\"a\\":\\"https://example.com/assets/images/foo.jpg\\"}")
|
||||
"
|
||||
`;
|
||||
@ -1,131 +0,0 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { KNOWN_ASSET_EXTENSIONS, KNOWN_IMAGE_EXTENSIONS, KNOWN_MEDIA_EXTENSIONS } from '../src/constants.js'
|
||||
import { createFindPattern, normalizeRules } from '../src/normalizeRules.js'
|
||||
|
||||
describe('plugin-replace-assets > normalizeRules', () => {
|
||||
it('should work with empty options', () => {
|
||||
expect(normalizeRules('')).toEqual([])
|
||||
expect(normalizeRules([])).toEqual([])
|
||||
expect(normalizeRules({})).toEqual([])
|
||||
expect(normalizeRules({ rules: [] })).toEqual([])
|
||||
})
|
||||
|
||||
it('should work with string', () => {
|
||||
const rules = normalizeRules('https://example.com/assets/')
|
||||
|
||||
expect(rules).toEqual([{
|
||||
find: createFindPattern(KNOWN_ASSET_EXTENSIONS),
|
||||
replacement: 'https://example.com/assets/',
|
||||
}])
|
||||
})
|
||||
|
||||
it('should work with function', () => {
|
||||
const replacement = vi.fn((url: string) => `https://example.com/assets/${url}`)
|
||||
const rules = normalizeRules(replacement)
|
||||
|
||||
expect(rules).toEqual([{
|
||||
find: createFindPattern(KNOWN_ASSET_EXTENSIONS),
|
||||
replacement,
|
||||
}])
|
||||
})
|
||||
|
||||
it('should work with single rule', () => {
|
||||
const rules = normalizeRules({
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)$',
|
||||
replacement: 'https://example.com/images/',
|
||||
})
|
||||
|
||||
expect(rules).toEqual([{
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)$',
|
||||
replacement: 'https://example.com/images/',
|
||||
}])
|
||||
})
|
||||
|
||||
it('should work with multiple rules', () => {
|
||||
const rules = normalizeRules([
|
||||
{
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)$',
|
||||
replacement: 'https://example.com/images/',
|
||||
},
|
||||
{
|
||||
find: '^/medias/.*\\.(mp4|ogg|ogv|webm)$',
|
||||
replacement: 'https://example.com/medias/',
|
||||
},
|
||||
])
|
||||
|
||||
expect(rules).toEqual([
|
||||
{
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)$',
|
||||
replacement: 'https://example.com/images/',
|
||||
},
|
||||
{
|
||||
find: '^/medias/.*\\.(mp4|ogg|ogv|webm)$',
|
||||
replacement: 'https://example.com/medias/',
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should work with presets', () => {
|
||||
const media = vi.fn((url: string) => `https://example.com/medias/${url}`)
|
||||
const rules = normalizeRules({
|
||||
image: 'https://example.com/images/',
|
||||
media,
|
||||
all: 'https://example.com/assets/',
|
||||
})
|
||||
|
||||
expect(rules).toEqual([
|
||||
{
|
||||
find: createFindPattern(KNOWN_IMAGE_EXTENSIONS),
|
||||
replacement: 'https://example.com/images/',
|
||||
},
|
||||
{
|
||||
find: createFindPattern(KNOWN_MEDIA_EXTENSIONS),
|
||||
replacement: media,
|
||||
},
|
||||
{
|
||||
find: createFindPattern(KNOWN_ASSET_EXTENSIONS),
|
||||
replacement: 'https://example.com/assets/',
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should work with custom single rule', () => {
|
||||
const rules = normalizeRules({
|
||||
rules: {
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)$',
|
||||
replacement: 'https://example.com/images/',
|
||||
},
|
||||
})
|
||||
|
||||
expect(rules).toEqual([{
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)$',
|
||||
replacement: 'https://example.com/images/',
|
||||
}])
|
||||
})
|
||||
|
||||
it('should work with custom multiple rules', () => {
|
||||
const rules = normalizeRules({
|
||||
rules: [
|
||||
{
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)$',
|
||||
replacement: 'https://example.com/images/',
|
||||
},
|
||||
{
|
||||
find: '^/medias/.*\\.(mp4|ogg|ogv|webm)$',
|
||||
replacement: 'https://example.com/medias/',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(rules).toEqual([
|
||||
{
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)$',
|
||||
replacement: 'https://example.com/images/',
|
||||
},
|
||||
{
|
||||
find: '^/medias/.*\\.(mp4|ogg|ogv|webm)$',
|
||||
replacement: 'https://example.com/medias/',
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
@ -1,218 +0,0 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { normalizeRules } from '../src/normalizeRules.js'
|
||||
import { isMatchUrl, replacementAssetWithRules, transformAssets } from '../src/unplugin/transform.js'
|
||||
import { createAssetPattern } from '../src/unplugin/utils.js'
|
||||
|
||||
describe('plugin-replace-assets > isMatchUrl', () => {
|
||||
it.each([
|
||||
{
|
||||
name: 'string like regexp with ^ and $',
|
||||
find: '^/images/.*\\.(jpe?g|png|gif|svg)(\\?.*)?$',
|
||||
expects: [
|
||||
['/images/foo.jpg', true],
|
||||
['/images/foo.png', true],
|
||||
['/images/foo.gif', true],
|
||||
['/images/foo.svg', true],
|
||||
['/images/foo.jpg?a=1', true],
|
||||
['/images/foo.txt', false],
|
||||
['/medias/foo.mp4', false],
|
||||
] as const,
|
||||
},
|
||||
{
|
||||
name: 'string like regexp start with ^',
|
||||
find: '^/medias/',
|
||||
expects: [
|
||||
['/medias/foo.mp4', true],
|
||||
['/medias/foo.ogg', true],
|
||||
['/medias/foo.ogv', true],
|
||||
['/medias/foo.webm', true],
|
||||
['/images/foo.jpg', false],
|
||||
] as const,
|
||||
},
|
||||
{
|
||||
name: 'string like regexp end with $',
|
||||
find: '\\.(jpe?g|png|gif|svg)$',
|
||||
expects: [
|
||||
['/images/foo.jpg', true],
|
||||
['/images/foo.png', true],
|
||||
['/images/foo.gif', true],
|
||||
['/images/foo.svg', true],
|
||||
['/images/foo.txt', false],
|
||||
['/medias/foo.mp4', false],
|
||||
] as const,
|
||||
},
|
||||
{
|
||||
name: 'string start width pathname',
|
||||
find: '/images/',
|
||||
expects: [
|
||||
['/images/foo.jpg', true],
|
||||
['/images/foo.png', true],
|
||||
['/images/foo.gif', true],
|
||||
['/images/foo', true],
|
||||
['/medias/foo.mp4', false],
|
||||
] as const,
|
||||
},
|
||||
{
|
||||
name: 'string end width extension',
|
||||
find: '.jpg',
|
||||
expects: [
|
||||
['/images/foo.jpg', true],
|
||||
['/images/foo.png', false],
|
||||
['/images/foo.gif', false],
|
||||
['/images/foo', false],
|
||||
['/medias/foo.mp4', false],
|
||||
] as const,
|
||||
},
|
||||
{
|
||||
name: 'regexp',
|
||||
find: /^\/images\/.*\.(jpe?g|png|gif|svg)$/,
|
||||
expects: [
|
||||
['/images/foo.jpg', true],
|
||||
['/images/foo.png', true],
|
||||
['/images/foo.gif', true],
|
||||
['/images/foo.svg', true],
|
||||
['/images/foo.txt', false],
|
||||
['/medias/foo.mp4', false],
|
||||
] as const,
|
||||
},
|
||||
])('$name', ({ find, expects }) => {
|
||||
for (const [url, expected] of expects) {
|
||||
expect(isMatchUrl(find, url)).toBe(expected)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('plugin-replace-assets > replacementAssetWithRules', () => {
|
||||
const IMAGE_SUPPORTED = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'avif']
|
||||
const MEDIA_SUPPORTED = ['mp4', 'webm', 'ogg', 'mp3', 'wav', 'flac', 'aac', 'm3u8', 'm3u', 'flv', 'pdf']
|
||||
const replacementFn = vi.fn(url => `https://example.com/assets${url}`)
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: 'string replacement',
|
||||
rules: normalizeRules('https://example.com/assets/'),
|
||||
expects: [
|
||||
// images
|
||||
...IMAGE_SUPPORTED.map(ext => [
|
||||
`/images/foo.${ext}`,
|
||||
`https://example.com/assets/images/foo.${ext}`,
|
||||
]),
|
||||
// media
|
||||
...MEDIA_SUPPORTED.map(ext => [
|
||||
`/medias/foo.${ext}`,
|
||||
`https://example.com/assets/medias/foo.${ext}`,
|
||||
]),
|
||||
// have query string
|
||||
['/images/foo.jpg?a=1', 'https://example.com/assets/images/foo.jpg?a=1'],
|
||||
// cached images
|
||||
['/images/foo.jpg', 'https://example.com/assets/images/foo.jpg'],
|
||||
// no supported
|
||||
['/images/foo.txt', undefined],
|
||||
['/medias/foo', undefined],
|
||||
] as const,
|
||||
},
|
||||
{
|
||||
name: 'function replacement',
|
||||
rules: normalizeRules(replacementFn),
|
||||
expects: [
|
||||
// images
|
||||
...IMAGE_SUPPORTED.map(ext => [
|
||||
`/images-1/foo.${ext}`,
|
||||
`https://example.com/assets/images-1/foo.${ext}`,
|
||||
]),
|
||||
// media
|
||||
...MEDIA_SUPPORTED.map(ext => [
|
||||
`/medias-1/foo.${ext}`,
|
||||
`https://example.com/assets/medias-1/foo.${ext}`,
|
||||
]),
|
||||
// have query string
|
||||
['/images-1/foo.jpg?a=1', 'https://example.com/assets/images-1/foo.jpg?a=1'],
|
||||
// cached images
|
||||
['/images-1/foo.jpg', 'https://example.com/assets/images-1/foo.jpg'],
|
||||
// no supported
|
||||
['/images-1/foo.txt', undefined],
|
||||
['/medias-1/foo', undefined],
|
||||
] as const,
|
||||
},
|
||||
])('$name', ({ name, rules, expects }) => {
|
||||
for (const [url, expected] of expects) {
|
||||
expect(replacementAssetWithRules(rules, url)).toBe(expected)
|
||||
}
|
||||
if (name === 'function replacement') {
|
||||
// should not called with cached, and not called with no supported
|
||||
expect(replacementFn).toBeCalledTimes(expects.length - 3)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('plugin-replace-assets > transformAssets', () => {
|
||||
const rules = normalizeRules('https://example.com/assets/')
|
||||
const pattern = createAssetPattern('/[^/]')
|
||||
|
||||
it('should work with like html', () => {
|
||||
const source = `\
|
||||
<img src="/images/foo.jpg" />
|
||||
<img src="/images/foo.png" />
|
||||
<img src="/images/foo.gif" />
|
||||
<img src="/images/foo.svg" />
|
||||
<img src="/images/foo.txt" />
|
||||
<img src="/medias/foo.mp4" />
|
||||
|
||||
<img src="/images/foo.jpg?a=1" />
|
||||
|
||||
<img src="https://not-replace.com/images/foo.jpg" />
|
||||
|
||||
<video src="/medias/foo.mp4" />
|
||||
<audio src="/medias/foo.mp3" />
|
||||
|
||||
<embed src="/medias/foo.pdf" />
|
||||
`
|
||||
expect(transformAssets(source, pattern, rules)).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should work with like css', () => {
|
||||
const source = `\
|
||||
.foo {
|
||||
background-image: url("/images/foo.jpg");
|
||||
background-image: url("/images/foo.png");
|
||||
background-image: url("/images/foo.gif");
|
||||
background-image: url("/images/foo.svg");
|
||||
background-image: url("/medias/foo.mp4");
|
||||
|
||||
background-image: url('/images/foo.jpg');
|
||||
background-image: url(/images/foo.png);
|
||||
|
||||
background-image: url("/images/foo.jpg?a=1");
|
||||
|
||||
background-image: url("https://not-replace.com/images/foo.jpg");
|
||||
|
||||
background: url('/images/foo.png');
|
||||
|
||||
}
|
||||
`
|
||||
expect(transformAssets(source, pattern, rules)).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should work with like js', () => {
|
||||
const source = `\
|
||||
const a = "/images/foo.jpg"
|
||||
const b = '/images/foo.jpg'
|
||||
const c = '/images/foo.jpg?a=1'
|
||||
const d = "https://not-replace.com/images/foo.jpg"
|
||||
|
||||
const json_string = JSON.parse("{\\"a\\":\\"/images/foo.jpg\\"}")
|
||||
`
|
||||
|
||||
expect(transformAssets(source, pattern, rules)).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should work with no match', () => {
|
||||
const source = `\
|
||||
<video src="./medias/foo.mp4" />
|
||||
<img src="https://not-replace.com/images/foo.jpg" />
|
||||
|
||||
const a = "images/foo.jpg"
|
||||
`
|
||||
expect(transformAssets(source, pattern, rules)).toBe(source)
|
||||
})
|
||||
})
|
||||
@ -1,25 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { createAssetPattern, normalizeUrl } from '../src/unplugin/utils.js'
|
||||
|
||||
describe('plugin-replace-assets > utils', () => {
|
||||
it('createAssetPattern', () => {
|
||||
expect(createAssetPattern('/[^/]').test(`'/images/foo.jpg'`)).toBe(true)
|
||||
expect(createAssetPattern('/[^/]').test(`"/images/foo.jpg"`)).toBe(true)
|
||||
expect(createAssetPattern('/[^/]').test(`(/images/foo.jpg)`)).toBe(true)
|
||||
expect(createAssetPattern('/[^/]').test(`('/images/foo.jpg')`)).toBe(true)
|
||||
expect(createAssetPattern('/[^/]').test(`("/images/foo.jpg")`)).toBe(true)
|
||||
expect(createAssetPattern('/[^/]').test(`"/images/foo.jpg?a=1"`)).toBe(true)
|
||||
|
||||
expect(createAssetPattern('/[^/]').test(`'https://example.com/images/foo.jpg'`)).toBe(false)
|
||||
expect(createAssetPattern('/[^/]').test(`"./images/foo.jpg"`)).toBe(false)
|
||||
expect(createAssetPattern('/[^/]').test(`"images/foo.jpg"`)).toBe(false)
|
||||
})
|
||||
|
||||
it('normalizeUrl', () => {
|
||||
expect(normalizeUrl('')).toBe('')
|
||||
expect(normalizeUrl('/images/foo.jpg')).toBe('/images/foo.jpg')
|
||||
expect(normalizeUrl('/images/foo.jpg?a=1')).toBe('/images/foo.jpg?a=1')
|
||||
expect(normalizeUrl('/images/foo.jpg', 'https://example.com/')).toBe('https://example.com/images/foo.jpg')
|
||||
expect(normalizeUrl('/images/foo.jpg?a=1', 'https://example.com/')).toBe('https://example.com/images/foo.jpg?a=1')
|
||||
})
|
||||
})
|
||||
@ -1,50 +0,0 @@
|
||||
{
|
||||
"name": "vuepress-plugin-replace-assets",
|
||||
"type": "module",
|
||||
"version": "1.0.0-rc.156",
|
||||
"description": "The Plugin for VuePress 2 - replace assets url",
|
||||
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/pengzhanbo/vuepress-theme-plume#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git",
|
||||
"directory": "plugins/plugin-replace-assets"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/index.d.ts",
|
||||
"import": "./lib/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "pnpm run tsdown",
|
||||
"tsdown": "tsdown"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vuepress": "catalog:vuepress"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vuepress/helper": "catalog:vuepress",
|
||||
"magic-string": "catalog:prod",
|
||||
"unplugin": "catalog:prod"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"keyword": [
|
||||
"VuePress",
|
||||
"vuepress plugin",
|
||||
"replace assets",
|
||||
"vuepress-plugin-replace-assets"
|
||||
]
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
export const PLUGIN_NAME = 'vuepress-plugin-replace-assets'
|
||||
|
||||
export const KNOWN_IMAGE_EXTENSIONS: string[] = [
|
||||
'png',
|
||||
'jpg',
|
||||
'jpeg',
|
||||
'gif',
|
||||
'webp',
|
||||
'svg',
|
||||
'avif',
|
||||
]
|
||||
|
||||
export const KNOWN_MEDIA_EXTENSIONS: string[] = [
|
||||
'mp4',
|
||||
'webm',
|
||||
'ogg',
|
||||
'mp3',
|
||||
'wav',
|
||||
'flac',
|
||||
'aac',
|
||||
'm3u8',
|
||||
'm3u',
|
||||
'flv',
|
||||
|
||||
'pdf',
|
||||
]
|
||||
|
||||
export const KNOWN_ASSET_EXTENSIONS: string[] = [
|
||||
...KNOWN_IMAGE_EXTENSIONS,
|
||||
...KNOWN_MEDIA_EXTENSIONS,
|
||||
]
|
||||
@ -1,4 +0,0 @@
|
||||
export * from './normalizeRules.js'
|
||||
export * from './options.js'
|
||||
export * from './plugin.js'
|
||||
export * from './unplugin/index.js'
|
||||
@ -1,56 +0,0 @@
|
||||
import type { ReplaceAssetsPluginOptions, ReplacementRule } from './options.js'
|
||||
import { isArray, isFunction } from '@vuepress/helper'
|
||||
import { KNOWN_ASSET_EXTENSIONS, KNOWN_IMAGE_EXTENSIONS, KNOWN_MEDIA_EXTENSIONS } from './constants.js'
|
||||
|
||||
export function createFindPattern(extensions: string[]): RegExp {
|
||||
return new RegExp(`\\.(?:${extensions.join('|')})(\\?.*)?$`)
|
||||
}
|
||||
|
||||
export function normalizeRules(options: ReplaceAssetsPluginOptions): ReplacementRule[] {
|
||||
const normalized: ReplacementRule[] = []
|
||||
|
||||
if ((typeof options === 'string' || isFunction(options))) {
|
||||
options && normalized.push({
|
||||
find: createFindPattern(KNOWN_ASSET_EXTENSIONS),
|
||||
replacement: options,
|
||||
})
|
||||
return normalized
|
||||
}
|
||||
|
||||
if (isArray(options)) {
|
||||
normalized.push(...options)
|
||||
return normalized
|
||||
}
|
||||
|
||||
if ('find' in options) {
|
||||
options.find && options.replacement && normalized.push(options)
|
||||
return normalized
|
||||
}
|
||||
|
||||
if (options.image) {
|
||||
normalized.push({
|
||||
find: createFindPattern(KNOWN_IMAGE_EXTENSIONS),
|
||||
replacement: options.image,
|
||||
})
|
||||
}
|
||||
|
||||
if (options.media) {
|
||||
normalized.push({
|
||||
find: createFindPattern(KNOWN_MEDIA_EXTENSIONS),
|
||||
replacement: options.media,
|
||||
})
|
||||
}
|
||||
|
||||
if (options.all) {
|
||||
normalized.push({
|
||||
find: createFindPattern(KNOWN_ASSET_EXTENSIONS),
|
||||
replacement: options.all,
|
||||
})
|
||||
}
|
||||
|
||||
if (options.rules) {
|
||||
normalized.push(...isArray(options.rules) ? options.rules : [options.rules])
|
||||
}
|
||||
|
||||
return normalized
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
export type Replacement = string | ((url: string) => string)
|
||||
|
||||
export interface ReplacementRule {
|
||||
find: RegExp | string
|
||||
replacement: Replacement
|
||||
}
|
||||
|
||||
export interface ReplaceAssetsOptions {
|
||||
rules?: ReplacementRule | ReplacementRule[]
|
||||
all?: Replacement
|
||||
image?: Replacement
|
||||
media?: Replacement
|
||||
}
|
||||
|
||||
export type ReplaceAssetsPluginOptions
|
||||
= | Replacement
|
||||
| ReplacementRule
|
||||
| ReplacementRule[]
|
||||
| ReplaceAssetsOptions
|
||||
@ -1,40 +0,0 @@
|
||||
import type { Plugin } from 'vuepress/core'
|
||||
import type { ReplaceAssetsPluginOptions } from './options.js'
|
||||
import { addViteConfig, configWebpack, getBundlerName } from '@vuepress/helper'
|
||||
import { PLUGIN_NAME } from './constants.js'
|
||||
import { normalizeRules } from './normalizeRules.js'
|
||||
import { createVitePlugin, createWebpackPlugin } from './unplugin/index.js'
|
||||
|
||||
const EMPTY_PLUGIN = { name: PLUGIN_NAME }
|
||||
|
||||
export function replaceAssetsPlugin(
|
||||
options: ReplaceAssetsPluginOptions = {},
|
||||
): Plugin {
|
||||
const rules = normalizeRules(options)
|
||||
|
||||
if (rules.length === 0)
|
||||
return EMPTY_PLUGIN
|
||||
|
||||
return {
|
||||
...EMPTY_PLUGIN,
|
||||
|
||||
extendsBundlerOptions(bundlerOptions, app) {
|
||||
const bundle = getBundlerName(app)
|
||||
|
||||
if (bundle === 'vite') {
|
||||
const replaceAssets = createVitePlugin()
|
||||
addViteConfig(bundlerOptions, app, {
|
||||
plugins: [replaceAssets(rules)],
|
||||
})
|
||||
}
|
||||
|
||||
if (bundle === 'webpack') {
|
||||
const replaceAssets = createWebpackPlugin()
|
||||
configWebpack(bundlerOptions, app, (config) => {
|
||||
config.plugins ??= []
|
||||
config.plugins.push(replaceAssets(rules))
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
import type { UnpluginFactory } from 'unplugin'
|
||||
import type { ReplacementRule } from '../options.js'
|
||||
import { transformAssets } from './transform.js'
|
||||
import { createAssetPattern } from './utils.js'
|
||||
|
||||
export const unpluginFactory: UnpluginFactory<ReplacementRule[]> = (rules) => {
|
||||
const pattern = createAssetPattern('/[^/]')
|
||||
return {
|
||||
name: 'vuepress:replace-assets',
|
||||
enforce: 'pre',
|
||||
transform: {
|
||||
filter: { id: { exclude: [/\.json(?:$|\?)/, /\.html?$/] } },
|
||||
handler(code) {
|
||||
return transformAssets(code, pattern, rules)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
import type { VitePlugin, WebpackPluginInstance } from 'unplugin'
|
||||
import type { ReplacementRule } from '../options.js'
|
||||
import {
|
||||
createVitePlugin as _createVitePlugin,
|
||||
createWebpackPlugin as _createWebpackPlugin,
|
||||
} from 'unplugin'
|
||||
import { unpluginFactory } from './factory.js'
|
||||
|
||||
export const createVitePlugin: () => (
|
||||
options: ReplacementRule[]
|
||||
) => VitePlugin | VitePlugin[] = () => _createVitePlugin(unpluginFactory)
|
||||
|
||||
export const createWebpackPlugin: () => (
|
||||
options: ReplacementRule[]
|
||||
) => WebpackPluginInstance = () => _createWebpackPlugin(unpluginFactory)
|
||||
|
||||
export * from './transform.js'
|
||||
@ -1,69 +0,0 @@
|
||||
import type { ReplacementRule } from '../options.js'
|
||||
import MagicString from 'magic-string'
|
||||
import { normalizeUrl } from './utils.js'
|
||||
|
||||
const cache = new Map<string, string>()
|
||||
|
||||
export function transformAssets(code: string, pattern: RegExp, rules: ReplacementRule[]): string {
|
||||
const s = new MagicString(code)
|
||||
let matched: RegExpExecArray | null
|
||||
let hasMatched = false
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while ((matched = pattern.exec(code))) {
|
||||
const assetUrl = matched[6] || matched[5] || matched[4] || matched[3] || matched[2] || matched[1]
|
||||
const [left, right] = matched[0].startsWith('(')
|
||||
? ['("', '")']
|
||||
: matched[0].startsWith('\\"')
|
||||
? ['\\"', '\\"']
|
||||
: ['"', '"']
|
||||
|
||||
const start = matched.index
|
||||
const end = start + matched[0].length
|
||||
const resolved = replacementAssetWithRules(rules, assetUrl)
|
||||
if (resolved) {
|
||||
hasMatched = true
|
||||
s.update(start, end, `${left}${resolved}${right}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasMatched)
|
||||
return code
|
||||
|
||||
return s.toString()
|
||||
}
|
||||
|
||||
export function replacementAssetWithRules(rules: ReplacementRule[], url: string): string | void {
|
||||
if (cache.has(url))
|
||||
return cache.get(url)
|
||||
|
||||
for (const { find, replacement } of rules) {
|
||||
if (find && isMatchUrl(find, url)) {
|
||||
let replaced = ''
|
||||
if (typeof replacement === 'function') {
|
||||
replaced = normalizeUrl(replacement(url))
|
||||
}
|
||||
else {
|
||||
replaced = normalizeUrl(url, replacement)
|
||||
}
|
||||
/* istanbul ignore if -- @preserve */
|
||||
if (replaced) {
|
||||
cache.set(url, replaced)
|
||||
return replaced
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function isMatchUrl(find: string | RegExp, url: string): boolean {
|
||||
if (typeof find === 'string') {
|
||||
if (find[0] === '^' || find[find.length - 1] === '$') {
|
||||
return new RegExp(find).test(url)
|
||||
}
|
||||
else {
|
||||
return url.endsWith(find) || url.startsWith(find)
|
||||
}
|
||||
}
|
||||
|
||||
return find.test(url)
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
import { removeEndingSlash, removeLeadingSlash } from '@vuepress/helper'
|
||||
|
||||
export function createAssetPattern(prefix: string): RegExp {
|
||||
const s = `(${prefix}.*?)`
|
||||
return new RegExp(
|
||||
[
|
||||
`(?:"${s}")`, // "prefix"
|
||||
`(?:'${s}')`, // 'prefix'
|
||||
`(?:\\(${s}\\))`, // (prefix)
|
||||
`(?:\\('${s}'\\))`, // ('prefix')
|
||||
`(?:\\("${s}"\\))`, // ("prefix")
|
||||
`(?:\\\\"${s}\\\\")`, // \"prefix\"
|
||||
].join('|'),
|
||||
'gu',
|
||||
)
|
||||
}
|
||||
|
||||
export function normalizeUrl(url: string, base?: string): string {
|
||||
if (!url)
|
||||
return ''
|
||||
|
||||
if (base) {
|
||||
url = `${removeEndingSlash(base)}/${removeLeadingSlash(url)}`
|
||||
}
|
||||
return url
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
import type { Options } from 'tsdown'
|
||||
import { defineConfig } from 'tsdown'
|
||||
import { argv } from '../../scripts/tsup-args.js'
|
||||
|
||||
export default defineConfig(() => {
|
||||
const DEFAULT_OPTIONS: Options = {
|
||||
dts: true,
|
||||
sourcemap: false,
|
||||
format: 'esm',
|
||||
}
|
||||
const options: Options[] = []
|
||||
|
||||
if (argv.node) {
|
||||
options.push({
|
||||
...DEFAULT_OPTIONS,
|
||||
entry: ['./src/index.ts'],
|
||||
outDir: './lib',
|
||||
target: 'node20.6.0',
|
||||
})
|
||||
}
|
||||
|
||||
return options
|
||||
}) as Options[]
|
||||
44
pnpm-lock.yaml
generated
44
pnpm-lock.yaml
generated
@ -245,9 +245,6 @@ catalogs:
|
||||
lru-cache:
|
||||
specifier: ^11.1.0
|
||||
version: 11.1.0
|
||||
magic-string:
|
||||
specifier: ^0.30.17
|
||||
version: 0.30.17
|
||||
mark.js:
|
||||
specifier: ^8.11.1
|
||||
version: 8.11.1
|
||||
@ -296,9 +293,6 @@ catalogs:
|
||||
tm-themes:
|
||||
specifier: ^1.10.6
|
||||
version: 1.10.6
|
||||
unplugin:
|
||||
specifier: ^2.3.5
|
||||
version: 2.3.5
|
||||
vue:
|
||||
specifier: ^3.5.17
|
||||
version: 3.5.17
|
||||
@ -351,6 +345,9 @@ catalogs:
|
||||
'@vuepress/plugin-reading-time':
|
||||
specifier: 2.0.0-rc.112
|
||||
version: 2.0.0-rc.112
|
||||
'@vuepress/plugin-replace-assets':
|
||||
specifier: 2.0.0-rc.112
|
||||
version: 2.0.0-rc.112
|
||||
'@vuepress/plugin-seo':
|
||||
specifier: 2.0.0-rc.112
|
||||
version: 2.0.0-rc.112
|
||||
@ -706,21 +703,6 @@ importers:
|
||||
specifier: catalog:peer
|
||||
version: 1.7.3
|
||||
|
||||
plugins/plugin-replace-assets:
|
||||
dependencies:
|
||||
'@vuepress/helper':
|
||||
specifier: catalog:vuepress
|
||||
version: 2.0.0-rc.112(typescript@5.8.3)(vuepress@2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)))
|
||||
magic-string:
|
||||
specifier: catalog:prod
|
||||
version: 0.30.17
|
||||
unplugin:
|
||||
specifier: catalog:prod
|
||||
version: 2.3.5
|
||||
vuepress:
|
||||
specifier: catalog:vuepress
|
||||
version: 2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3))
|
||||
|
||||
plugins/plugin-search:
|
||||
dependencies:
|
||||
'@vuepress/helper':
|
||||
@ -813,6 +795,9 @@ importers:
|
||||
'@vuepress/plugin-reading-time':
|
||||
specifier: catalog:vuepress
|
||||
version: 2.0.0-rc.112(typescript@5.8.3)(vuepress@2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)))
|
||||
'@vuepress/plugin-replace-assets':
|
||||
specifier: catalog:vuepress
|
||||
version: 2.0.0-rc.112(typescript@5.8.3)(vuepress@2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)))
|
||||
'@vuepress/plugin-seo':
|
||||
specifier: catalog:vuepress
|
||||
version: 2.0.0-rc.112(typescript@5.8.3)(vuepress@2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)))
|
||||
@ -879,9 +864,6 @@ importers:
|
||||
vuepress-plugin-md-power:
|
||||
specifier: workspace:*
|
||||
version: link:../plugins/plugin-md-power
|
||||
vuepress-plugin-replace-assets:
|
||||
specifier: workspace:*
|
||||
version: link:../plugins/plugin-replace-assets
|
||||
devDependencies:
|
||||
'@iconify/json':
|
||||
specifier: catalog:peer
|
||||
@ -2943,6 +2925,11 @@ packages:
|
||||
peerDependencies:
|
||||
vuepress: 2.0.0-rc.24
|
||||
|
||||
'@vuepress/plugin-replace-assets@2.0.0-rc.112':
|
||||
resolution: {integrity: sha512-i502eqHUhZU+9kBALOHQ81t/aoJU10i6IegztXE+/ZOnKh8ryeW5q4o8b1uDUQqfEazo4kM4tjGC+l2n//5T3w==}
|
||||
peerDependencies:
|
||||
vuepress: 2.0.0-rc.24
|
||||
|
||||
'@vuepress/plugin-seo@2.0.0-rc.112':
|
||||
resolution: {integrity: sha512-WWZ0Dx1MxF9Mj6UVdB8TP5GozTNv51ZQQP6EAKYzprKCw0RVQYg5/tXWlg7IWcSw72go5iFiMBj5wZQigN+t4g==}
|
||||
peerDependencies:
|
||||
@ -9375,6 +9362,15 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vuepress/plugin-replace-assets@2.0.0-rc.112(typescript@5.8.3)(vuepress@2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)))':
|
||||
dependencies:
|
||||
'@vuepress/helper': 2.0.0-rc.112(typescript@5.8.3)(vuepress@2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)))
|
||||
magic-string: 0.30.17
|
||||
unplugin: 2.3.5
|
||||
vuepress: 2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3))
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vuepress/plugin-seo@2.0.0-rc.112(typescript@5.8.3)(vuepress@2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)))':
|
||||
dependencies:
|
||||
'@vuepress/helper': 2.0.0-rc.112(typescript@5.8.3)(vuepress@2.0.0-rc.24(@vuepress/bundler-vite@2.0.0-rc.24(@types/node@24.0.12)(jiti@2.4.2)(less@4.3.0)(sass-embedded@1.89.2)(sass@1.89.2)(stylus@0.64.0)(typescript@5.8.3)(yaml@2.8.0))(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)))
|
||||
|
||||
@ -98,7 +98,6 @@ catalogs:
|
||||
katex: ^0.16.22
|
||||
local-pkg: ^1.1.1
|
||||
lru-cache: ^11.1.0
|
||||
magic-string: ^0.30.17
|
||||
mark.js: ^8.11.1
|
||||
markdown-it-container: ^4.0.0
|
||||
markmap-lib: ^0.18.12
|
||||
@ -115,7 +114,6 @@ catalogs:
|
||||
tinyglobby: 0.2.13
|
||||
tm-grammars: ^1.23.26
|
||||
tm-themes: ^1.10.6
|
||||
unplugin: ^2.3.5
|
||||
vue: ^3.5.17
|
||||
vuepress:
|
||||
'@vuepress/bundler-vite': 2.0.0-rc.24
|
||||
@ -134,6 +132,7 @@ catalogs:
|
||||
'@vuepress/plugin-nprogress': 2.0.0-rc.112
|
||||
'@vuepress/plugin-photo-swipe': 2.0.0-rc.112
|
||||
'@vuepress/plugin-reading-time': 2.0.0-rc.112
|
||||
'@vuepress/plugin-replace-assets': 2.0.0-rc.112
|
||||
'@vuepress/plugin-seo': 2.0.0-rc.112
|
||||
'@vuepress/plugin-shiki': 2.0.0-rc.112
|
||||
'@vuepress/plugin-sitemap': 2.0.0-rc.112
|
||||
|
||||
@ -105,6 +105,7 @@
|
||||
"@vuepress/plugin-nprogress": "catalog:vuepress",
|
||||
"@vuepress/plugin-photo-swipe": "catalog:vuepress",
|
||||
"@vuepress/plugin-reading-time": "catalog:vuepress",
|
||||
"@vuepress/plugin-replace-assets": "catalog:vuepress",
|
||||
"@vuepress/plugin-seo": "catalog:vuepress",
|
||||
"@vuepress/plugin-shiki": "catalog:vuepress",
|
||||
"@vuepress/plugin-sitemap": "catalog:vuepress",
|
||||
@ -123,8 +124,7 @@
|
||||
"nanoid": "catalog:prod",
|
||||
"package-manager-detector": "catalog:prod",
|
||||
"vue": "catalog:prod",
|
||||
"vuepress-plugin-md-power": "workspace:*",
|
||||
"vuepress-plugin-replace-assets": "workspace:*"
|
||||
"vuepress-plugin-md-power": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify/json": "catalog:peer",
|
||||
|
||||
@ -11,10 +11,10 @@ import { docsearchPlugin } from '@vuepress/plugin-docsearch'
|
||||
import { nprogressPlugin } from '@vuepress/plugin-nprogress'
|
||||
import { photoSwipePlugin } from '@vuepress/plugin-photo-swipe'
|
||||
import { readingTimePlugin } from '@vuepress/plugin-reading-time'
|
||||
import { replaceAssetsPlugin } from '@vuepress/plugin-replace-assets'
|
||||
import { seoPlugin } from '@vuepress/plugin-seo'
|
||||
import { sitemapPlugin } from '@vuepress/plugin-sitemap'
|
||||
import { watermarkPlugin } from '@vuepress/plugin-watermark'
|
||||
import { replaceAssetsPlugin } from 'vuepress-plugin-replace-assets'
|
||||
import { getThemeConfig } from '../loadConfig/index.js'
|
||||
import { codePlugins } from './code.js'
|
||||
import { gitPlugin } from './git.js'
|
||||
|
||||
@ -2,9 +2,9 @@ import type { CommentPluginOptions } from '@vuepress/plugin-comment'
|
||||
import type { CopyCodePluginOptions } from '@vuepress/plugin-copy-code'
|
||||
import type { ChangelogOptions, ContributorsOptions } from '@vuepress/plugin-git'
|
||||
import type { ReadingTimePluginOptions } from '@vuepress/plugin-reading-time'
|
||||
import type { ReplaceAssetsPluginOptions } from '@vuepress/plugin-replace-assets'
|
||||
import type { ShikiPluginOptions } from '@vuepress/plugin-shiki'
|
||||
import type { WatermarkPluginOptions } from '@vuepress/plugin-watermark'
|
||||
import type { ReplaceAssetsPluginOptions } from 'vuepress-plugin-replace-assets'
|
||||
import type { ThemeBaseData, ThemeData } from './data.js'
|
||||
import type {
|
||||
AutoFrontmatterOptions,
|
||||
|
||||
@ -9,12 +9,12 @@ import type { MarkdownIncludePluginOptions } from '@vuepress/plugin-markdown-inc
|
||||
import type { MarkdownMathPluginOptions } from '@vuepress/plugin-markdown-math'
|
||||
import type { PhotoSwipePluginOptions } from '@vuepress/plugin-photo-swipe'
|
||||
import type { ReadingTimePluginOptions } from '@vuepress/plugin-reading-time'
|
||||
import type { ReplaceAssetsPluginOptions } from '@vuepress/plugin-replace-assets'
|
||||
import type { SeoPluginOptions } from '@vuepress/plugin-seo'
|
||||
import type { ShikiPluginOptions } from '@vuepress/plugin-shiki'
|
||||
import type { SitemapPluginOptions } from '@vuepress/plugin-sitemap'
|
||||
import type { WatermarkPluginOptions } from '@vuepress/plugin-watermark'
|
||||
import type { MarkdownPowerPluginOptions } from 'vuepress-plugin-md-power'
|
||||
import type { ReplaceAssetsPluginOptions } from 'vuepress-plugin-replace-assets'
|
||||
|
||||
export interface ThemeBuiltinPlugins {
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user