diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..8c958afa1
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,23 @@
+# CONTRIBUTING
+
+## Development
+
+- Run `pnpm run dev` to start the development toolchain
+- Run `pnpm link -g` to link the package globally
+- Run `pnpm link -g surgio` in your local surgio config repository to use the local version of surgio
+- Run generate command to check the result
+
+## Testing
+
+- Run `pnpm run test` to run the tests
+- Tests will be automatically checked by GitHub Actions
+- A green pipeline is required to merge a PR
+
+## Versioning
+
+TODO
+
+## Documentation
+
+- Run `pnpm run docs:dev` to start the live preview of the documentation
+- Add version tag in Markdown if the feature is only available in/after a specific version
diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts
index f5d5a9232..275e9f481 100644
--- a/docs/.vuepress/config.ts
+++ b/docs/.vuepress/config.ts
@@ -1,9 +1,10 @@
-import { defineUserConfig, HeadConfig, PluginConfig } from 'vuepress'
+import { defineUserConfig, type HeadConfig, type PluginConfig, type UserConfig } from 'vuepress'
import { path } from '@vuepress/utils'
-import docsearchPlugin from '@vuepress/plugin-docsearch'
-import registerComponentsPlugin from '@vuepress/plugin-register-components'
+import { docsearchPlugin } from '@vuepress/plugin-docsearch'
+import { registerComponentsPlugin } from '@vuepress/plugin-register-components'
import { sitemapPlugin } from 'vuepress-plugin-sitemap2'
import { umamiAnalyticsPlugin } from 'vuepress-plugin-umami-analytics'
+import { viteBundler } from '@vuepress/bundler-vite'
import customTheme from './theme'
@@ -60,14 +61,16 @@ if (process.env.NODE_ENV === 'production') {
sitemapPlugin({
hostname: 'https://surgio.js.org',
}),
- umamiAnalyticsPlugin({
- id: '444a5a25-af75-4c30-b7a4-6aaba520daf6',
- src: 'https://sashimi.royli.dev/sashimi.js',
- }),
+ // umamiAnalyticsPlugin({
+ // id: '444a5a25-af75-4c30-b7a4-6aaba520daf6',
+ // src: 'https://sashimi.royli.dev/sashimi.js',
+ // }) as any,
)
}
export default defineUserConfig({
+ bundler: viteBundler(),
+ theme: customTheme,
locales: {
'/': {
lang: 'zh-CN',
@@ -78,6 +81,5 @@ export default defineUserConfig({
title: meta.title,
description: meta.description,
head,
- theme: customTheme,
plugins,
-})
+}) as UserConfig
diff --git a/docs/.vuepress/theme/index.ts b/docs/.vuepress/theme/index.ts
index 74127469f..1b2e04d94 100644
--- a/docs/.vuepress/theme/index.ts
+++ b/docs/.vuepress/theme/index.ts
@@ -35,7 +35,7 @@ export default {
},
{
text: '客户端规则维护指南',
- children: ['/guide/client/clash', '/guide/client/examples'],
+ children: ['/guide/client/sing-box', '/guide/client/clash', '/guide/client/examples'],
},
'/guide/api',
'/guide/cli',
diff --git a/docs/guide/client/sing-box.md b/docs/guide/client/sing-box.md
new file mode 100644
index 000000000..69d24b2be
--- /dev/null
+++ b/docs/guide/client/sing-box.md
@@ -0,0 +1,115 @@
+---
+sidebarDepth: 1
+---
+
+# sing-box
+
+>
+
+因为 sing-box 的配置文件为 JSON 格式,所以我们引入了一种新的方式来维护 sing-box 规则,或是其它 JSON 格式的规则。
+
+## 准备
+
+首先我们找到一份基础的规则文件,它可能是这样的:
+
+```json
+{
+ "inbounds": [],
+ "outbounds": [
+ {
+ "type": "block",
+ "tag": "block"
+ },
+ {
+ "type": "dns",
+ "tag": "dns"
+ }
+ ],
+ "route": {},
+ "experimental": {
+ "cache_file": {
+ "enabled": true
+ },
+ "clash_api": {
+ "external_controller": "127.0.0.1:9090"
+ }
+ }
+}
+```
+
+我们看到此时 `outbounds` 已经包含了一些内容,我们要做的就是把节点信息填充到 `outbounds` 中。
+
+把这个文件保存在 `tempalte` 目录下,命名为 `singbox.json`。
+
+## 编写 Artifact
+
+```js{9-26}
+const { extendOutbounds } = require('surgio');
+
+module.exports = {
+ artifacts: [
+ {
+ name: 'singbox.json',
+ template: 'singbox',
+ templateType: 'json',
+ extendTemplate: extendOutbounds(
+ ({ getSingboxNodes, getSingboxNodeNames, nodeList }) => [
+ {
+ type: 'direct',
+ tag: 'direct',
+ tcp_fast_open: false,
+ tcp_multi_path: true,
+ },
+ {
+ type: 'selector',
+ tag: 'proxy',
+ outbounds: ['auto', ...getSingboxNodeNames(nodeList)],
+ // outbounds: getSingboxNodeNames(nodeList), // 如果你不需要 auto 节点
+ interrupt_exist_connections: false,
+ },
+ ...getSingboxNodes(nodeList),
+ ],
+ ),
+ provider: 'ss',
+ },
+ ]
+}
+```
+
+这个配置的含义是:
+
+- `template` 为 `singbox`,即我们刚刚创建的模板文件
+- `extendTemplate` 为 `extendOutbounds`,这个函数会把节点信息填充到 `outbounds` 中
+
+第 10 行的 `getSingboxNodes`, `getSingboxNodeNames` 属于「模板方法」,具体有哪些可用的模板方法可以看 [这里](/guide/custom-template.md#模板方法)。
+
+## `extendOutbounds` 函数
+
+`extendOutbounds` 支持两种写法,一种是直接输入一个不可变的变量,另一种是输入一个函数。变量即确定的不会变化的内容,函数则是相对动态的内容。上面的例子中我们使用了函数的写法。
+
+### 直接输入变量
+
+```js
+const { extendOutbounds } = require('surgio');
+
+module.exports = {
+ artifacts: [
+ {
+ name: 'singbox.json',
+ template: 'singbox',
+ templateType: 'json',
+ extendTemplate: extendOutbounds([
+ {
+ type: 'direct',
+ tag: 'direct',
+ tcp_fast_open: false,
+ tcp_multi_path: true,
+ },
+ ]),
+ provider: 'ss',
+ },
+ ]
+}
+```
+
+你可以在 [这里](/guide/custom-template.md#模板方法) 查看这篇文章中提到的所有模板方法的文档。
diff --git a/docs/guide/custom-artifact.md b/docs/guide/custom-artifact.md
index 0757ef10b..4dc9fa6ba 100644
--- a/docs/guide/custom-artifact.md
+++ b/docs/guide/custom-artifact.md
@@ -7,7 +7,7 @@ sidebarDepth: 2
Surgio 会根据 Artifact 的值来生成配置文件。你可以一次性配置多个 Artifact,一次性生成所有需要的配置文件。
-```js
+```json5
{
name: 'SurgeV3.conf',
template: 'surge_v3',
@@ -33,6 +33,23 @@ Surgio 会根据 Artifact 的值来生成配置文件。你可以一次性配置
模板名。会在 `./template` 目录内寻找同名文件(`.tpl` 后缀可省略)。
+### templateType
+
+- 类型: `string`
+- 默认值: `default`
+- 有效值: `default`, `json`
+-
+
+模板类型。默认为 `default`,即以传统方式解析模板文件。
+
+### extendTemplate
+
+- 类型: `function`
+- 默认值: `undefined`
+-
+
+拓展 JSON 类型的模板,在编写 sing-box 规则时会用到。
+
### provider
- 类型: `string`
@@ -81,7 +98,7 @@ Surgio 会根据 Artifact 的值来生成配置文件。你可以一次性配置
例如:
-```js
+```json5
{
customParams: {
beta: true,
diff --git a/docs/guide/custom-provider.md b/docs/guide/custom-provider.md
index d25e52d7f..563f1e80c 100644
--- a/docs/guide/custom-provider.md
+++ b/docs/guide/custom-provider.md
@@ -45,12 +45,12 @@ module.exports = defineCustomProvider(async function () {
## 订阅类型
-目前 Surgio 支持两种 Provider 类型:
+目前 Surgio 支持以下几种 Provider 类型:
| 类型 | 描述 | 备注 |
| :----------------------------------------------: | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
-| `custom` | 自己维护的节点 | 支持 Shadowsocks, Shadowsocksr, Snell, HTTPS, HTTP, Vmess, Socks5, Tuic |
-| `clash` | Clash 配置 | 支持 Shadowsocks, Shadowsocksr, Snell, HTTPS, HTTP, Vmess, Vless, Hysteria 2, Socks5, Tuic |
+| `custom` | 自己维护的节点 | 支持 Shadowsocks, Shadowsocksr, Snell, HTTPS, HTTP, Vmess, Vless, Hysteria 2, Socks5, Tuic, Trojan, Wireguard |
+| `clash` | Clash 配置 | 支持 Shadowsocks, Shadowsocksr, Snell, HTTPS, HTTP, Vmess, Vless, Hysteria 2, Socks5, Tuic, Trojan, Wireguard |
| `trojan` | Trojan 订阅 | Shadowrocket 支持的 Trojan 订阅格式 |
| `shadowsocks_json_subscribe` | 针对 Windows 客户端的 Shadowsocks 订阅地址 | 通常命名为 _gui-config.json_ |
| `shadowsocks_subscribe` | 通用的 Shadowsocks 订阅地址 | |
@@ -159,6 +159,7 @@ module.exports = defineCustomProvider({
tfo: false, // TCP Fast Open
tls13: false, // TLS 1.3,适用于 v2ray-plugin
mux: false, // 目前仅 Clash + Shadowsocks + v2ray-plugin 可用
+ multiplex: {}, // 多路复用,可选,见本页面的 `multiplex多路复用` 部分
}
```
@@ -228,6 +229,7 @@ module.exports = defineCustomProvider({
'x-key': 'x-value',
},
},
+ multiplex: {}, // 多路复用,可选,见本页面的 `multiplex多路复用` 部分
}
```
@@ -251,6 +253,7 @@ module.exports = defineCustomProvider({
Host: 'www.example.com',
},
},
+ multiplex: {}, // 多路复用,可选,见本页面的 `multiplex多路复用` 部分
}
```
@@ -271,6 +274,7 @@ module.exports = defineCustomProvider({
grpcOpts: {
serviceName: 'example',
},
+ multiplex: {}, // 多路复用,可选,见本页面的 `multiplex多路复用` 部分
}
```
@@ -295,6 +299,47 @@ module.exports = defineCustomProvider({
}
```
+#### `network: 'quic'`
+
+```json5
+{
+ nodeName: '🇭🇰HK',
+ type: 'vmess',
+ hostname: 'hk.example.com',
+ method: 'auto',
+ network: 'quic',
+ alterId: '64',
+ port: 8080,
+ tls: true,
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ udpRelay: true,
+}
+```
+
+#### `network: 'httpupgrade'`
+
+```json5
+{
+ nodeName: '🇭🇰HK',
+ type: 'vmess',
+ hostname: 'hk.example.com',
+ method: 'auto',
+ network: 'httpupgrade',
+ alterId: '64',
+ port: 8080,
+ tls: false,
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ udpRelay: true,
+ httpUpgradeOpts: {
+ path: '/',
+ host: 'www.example.com',
+ headers: {
+ 'x-key': 'x-value',
+ }
+ },
+}
+```
+
### Vless
Vless 节点遵循和 Vmess 类似的配置规则,除了以下几个差异:
@@ -347,6 +392,10 @@ Vless 节点遵循和 Vmess 类似的配置规则,除了以下几个差异:
username: 'username',
password: 'password',
tls13: false, // TLS 1.3
+ path: '/', // 可选
+ headers: { // 可选
+ 'x-key': 'x-value',
+ },
}
```
@@ -360,6 +409,10 @@ Vless 节点遵循和 Vmess 类似的配置规则,除了以下几个差异:
port: 8080,
username: 'username',
password: 'password',
+ path: '/', // 可选
+ headers: { // 可选
+ 'x-key': 'x-value',
+ },
}
```
@@ -380,6 +433,7 @@ Vless 节点遵循和 Vmess 类似的配置规则,除了以下几个差异:
network: 'ws', // 可不填
wsPath: '/', // 可选
wsHeaders: {}, // 可选
+ multiplex: {}, // 多路复用,可选,见本页面的 `multiplex多路复用` 部分
}
```
@@ -1064,3 +1118,24 @@ module.exports = defineClashProvider({
}
})
```
+
+## Multiplex 多路复用
+
+- sing-box 的多路复用说明:[链接](https://sing-box.sagernet.org/configuration/shared/multiplex/)
+- mihomo 的多路复用说明:[链接](https://wiki.metacubex.one/config/proxies/sing-mux/)
+
+```json5
+{
+ multiplex: {
+ protocol: '', // smux, yamux, h2mux
+ maxConnections: 1, // 最大连接数量,与 max_streams 冲突
+ minStreams: 1, // 在打开新连接之前,连接中的最小多路复用流数量,与 max_streams 冲突
+ maxStreams: 1, // 在打开新连接之前,连接中的最大多路复用流数量,与 max_connections 和 min_streams 冲突
+ padding: false, // 启用填充
+ brutal: { // 可选,TCP Brutal 拥塞控制算法
+ upMbps: 0, // 上行 Mbps
+ downMbps: 0, // 下行 Mbps
+ },
+ }
+}
+```
diff --git a/docs/guide/custom-template.md b/docs/guide/custom-template.md
index 4ef48ca3d..b8599dcc5 100644
--- a/docs/guide/custom-template.md
+++ b/docs/guide/custom-template.md
@@ -324,6 +324,36 @@ getClashNodeNames(nodeList, netflixFilter, ['测试节点']);
getClashNodeNames(nodeList, netflixFilter, [], ['默认节点']);
```
+### getSingboxNodes
+
+>
+
+`getSingboxNodes(nodeList, filter?)`
+
+该方法会返回一个包含有节点信息的数组,可用于编写 sing-box 规则。
+
+:::tip 提示
+- `filter` 为可选参数
+:::
+
+### getSingboxNodeNames
+
+>
+
+`getSingboxNodeNames(nodeList, filter?)`
+
+该方法会返回一个包含有节点名称的数组,用于编写 sing-box 规则。
+
+:::tip 提示
+- `filter` 为可选参数
+:::
+
+若需要过滤 Netflix 节点则传入:
+
+```js
+getSingboxNodeNames(nodeList, netflixFilter);
+```
+
### getLoonNodes
`getLoonNodes(nodeList, filter?)`
@@ -464,6 +494,118 @@ PROCESS-NAME,YT Music
和远程片段一样,`.text` 可以获取到原始的字符串内容。
+## JSON 模板方法
+
+### extendOutbounds
+
+>
+
+`extendOutbounds(function|object)`
+
+用于拓展 sing-box 规则的 `outbounds` 字段。
+
+#### 函数类型
+
+```js
+extendOutbounds((props) => {
+ // props 包含本文中的模板方法和变量
+ return props.getSingboxNodes(props.nodeList)
+})
+```
+
+#### 对象类型
+
+```js
+extendOutbounds([
+ {
+ type: 'direct',
+ tag: 'direct',
+ tcp_fast_open: false,
+ tcp_multi_path: true,
+ },
+ {
+ type: 'block',
+ tag: 'block',
+ },
+])
+```
+
+### createExtendFunction
+
+>
+
+`createExtendFunction(string)`
+
+`extendOutbounds` 其实就是用下面的方法生成的。
+
+```js
+const { createExtendFunction } = require('surgio')
+
+const extendOutbounds = createExtendFunction('outbounds')
+```
+
+### combineExtendFunctions
+
+>
+
+`combineExtendFunctions(function1, function2, ...)`
+
+用于合并多个拓展函数。
+
+```js
+const { combineExtendFunctions, createExtendFunction } = require('surgio')
+
+const extendDNS = createExtendFunction('dns')
+const extendInbounds = createExtendFunction('inbounds')
+
+const combined = combineExtendFunctions(
+ extendDNS({
+ nameserver: ['1.1.1.1']
+ }),
+ extendInbounds([
+ {
+ port: 7890,
+ protocol: 'http',
+ }
+ ]),
+)
+```
+
+模板:
+
+```json
+{
+ "dns": {
+ "nameserver": [
+ "1.0.0.1"
+ ]
+ }
+}
+```
+
+结果:
+
+```json
+{
+ "dns": {
+ "nameserver": [
+ "1.0.0.1",
+ "1.1.1.1"
+ ]
+ },
+ "inbounds": [
+ {
+ "port": 7890,
+ "protocol": "http"
+ }
+ ]
+}
+```
+
+:::tip 提示
+- 拓展数组时新的配置会被追加到原有配置的后面
+:::
+
## 片段 (Snippet)
### 如何使用片段?
diff --git a/package.json b/package.json
index c5c3635e9..8e98f7a33 100644
--- a/package.json
+++ b/package.json
@@ -146,12 +146,13 @@
"@types/urlsafe-base64": "^1.0.31",
"@typescript-eslint/eslint-plugin": "^7",
"@typescript-eslint/parser": "^7",
- "@vuepress/client": "2.0.0-beta.62",
- "@vuepress/plugin-docsearch": "2.0.0-beta.62",
- "@vuepress/plugin-google-analytics": "2.0.0-beta.62",
- "@vuepress/plugin-register-components": "2.0.0-beta.62",
- "@vuepress/theme-default": "2.0.0-beta.62",
- "@vuepress/utils": "2.0.0-beta.62",
+ "@vuepress/bundler-vite": "2.0.0-rc.7",
+ "@vuepress/client": "2.0.0-rc.9",
+ "@vuepress/plugin-docsearch": "2.0.0-rc.26",
+ "@vuepress/plugin-google-analytics": "2.0.0-rc.21",
+ "@vuepress/plugin-register-components": "2.0.0-rc.21",
+ "@vuepress/theme-default": "2.0.0-rc.26",
+ "@vuepress/utils": "2.0.0-rc.9",
"ava": "^5.3.1",
"benchmark": "^2.1.4",
"bumpp": "^9.4.0",
@@ -176,8 +177,8 @@
"ts-node": "^10.9.2",
"typescript": "^5.3.3",
"vue": "^3.4.21",
- "vuepress": "2.0.0-beta.62",
- "vuepress-plugin-sitemap2": "2.0.0-beta.205",
+ "vuepress": "2.0.0-rc.9",
+ "vuepress-plugin-sitemap2": "2.0.0-rc.16",
"vuepress-plugin-umami-analytics": "^1.8.1"
},
"ava": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ec52d5489..25fc47aa6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -223,24 +223,27 @@ devDependencies:
'@typescript-eslint/parser':
specifier: ^7
version: 7.1.1(eslint@8.57.0)(typescript@5.3.3)
+ '@vuepress/bundler-vite':
+ specifier: 2.0.0-rc.7
+ version: 2.0.0-rc.7(@types/node@18.19.21)(sass@1.71.1)(typescript@5.3.3)
'@vuepress/client':
- specifier: 2.0.0-beta.62
- version: 2.0.0-beta.62(typescript@5.3.3)
+ specifier: 2.0.0-rc.9
+ version: 2.0.0-rc.9(typescript@5.3.3)
'@vuepress/plugin-docsearch':
- specifier: 2.0.0-beta.62
- version: 2.0.0-beta.62(@algolia/client-search@4.22.1)(typescript@5.3.3)
+ specifier: 2.0.0-rc.26
+ version: 2.0.0-rc.26(@algolia/client-search@4.22.1)(typescript@5.3.3)(vuepress@2.0.0-rc.9)
'@vuepress/plugin-google-analytics':
- specifier: 2.0.0-beta.62
- version: 2.0.0-beta.62(typescript@5.3.3)
+ specifier: 2.0.0-rc.21
+ version: 2.0.0-rc.21(vuepress@2.0.0-rc.9)
'@vuepress/plugin-register-components':
- specifier: 2.0.0-beta.62
- version: 2.0.0-beta.62(typescript@5.3.3)
+ specifier: 2.0.0-rc.21
+ version: 2.0.0-rc.21(vuepress@2.0.0-rc.9)
'@vuepress/theme-default':
- specifier: 2.0.0-beta.62
- version: 2.0.0-beta.62(typescript@5.3.3)
+ specifier: 2.0.0-rc.26
+ version: 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
'@vuepress/utils':
- specifier: 2.0.0-beta.62
- version: 2.0.0-beta.62
+ specifier: 2.0.0-rc.9
+ version: 2.0.0-rc.9
ava:
specifier: ^5.3.1
version: 5.3.1
@@ -314,11 +317,11 @@ devDependencies:
specifier: ^3.4.21
version: 3.4.21(typescript@5.3.3)
vuepress:
- specifier: 2.0.0-beta.62
- version: 2.0.0-beta.62(@types/node@18.19.21)(@vuepress/client@2.0.0-beta.62)(sass@1.71.1)(ts-node@10.9.2)(typescript@5.3.3)(vue@3.4.21)
+ specifier: 2.0.0-rc.9
+ version: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
vuepress-plugin-sitemap2:
- specifier: 2.0.0-beta.205
- version: 2.0.0-beta.205(typescript@5.3.3)(vuepress@2.0.0-beta.62)
+ specifier: 2.0.0-rc.16
+ version: 2.0.0-rc.16(typescript@5.3.3)(vuepress@2.0.0-rc.9)
vuepress-plugin-umami-analytics:
specifier: ^1.8.1
version: 1.8.1(typescript@5.3.3)
@@ -622,6 +625,14 @@ packages:
dependencies:
'@babel/types': 7.24.0
+ /@babel/parser@7.24.5:
+ resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.24.0
+ dev: true
+
/@babel/runtime@7.24.0:
resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==}
engines: {node: '>=6.9.0'}
@@ -860,14 +871,14 @@ packages:
kuler: 2.0.0
dev: false
- /@docsearch/css@3.5.2:
- resolution: {integrity: sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==}
+ /@docsearch/css@3.6.0:
+ resolution: {integrity: sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==}
dev: true
- /@docsearch/js@3.5.2(@algolia/client-search@4.22.1):
- resolution: {integrity: sha512-p1YFTCDflk8ieHgFJYfmyHBki1D61+U9idwrLh+GQQMrBSP3DLGKpy0XUJtPjAOPltcVbqsTjiPFfH7JImjUNg==}
+ /@docsearch/js@3.6.0(@algolia/client-search@4.22.1):
+ resolution: {integrity: sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==}
dependencies:
- '@docsearch/react': 3.5.2(@algolia/client-search@4.22.1)
+ '@docsearch/react': 3.6.0(@algolia/client-search@4.22.1)
preact: 10.19.6
transitivePeerDependencies:
- '@algolia/client-search'
@@ -877,8 +888,8 @@ packages:
- search-insights
dev: true
- /@docsearch/react@3.5.2(@algolia/client-search@4.22.1):
- resolution: {integrity: sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==}
+ /@docsearch/react@3.6.0(@algolia/client-search@4.22.1):
+ resolution: {integrity: sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==}
peerDependencies:
'@types/react': '>= 16.8.0 < 19.0.0'
react: '>= 16.8.0 < 19.0.0'
@@ -896,14 +907,41 @@ packages:
dependencies:
'@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.22.1)(algoliasearch@4.22.1)
'@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.22.1)(algoliasearch@4.22.1)
- '@docsearch/css': 3.5.2
+ '@docsearch/css': 3.6.0
algoliasearch: 4.22.1
transitivePeerDependencies:
- '@algolia/client-search'
dev: true
- /@esbuild/android-arm64@0.17.19:
- resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
+ /@esbuild/aix-ppc64@0.19.12:
+ resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/aix-ppc64@0.20.2:
+ resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64@0.19.12:
+ resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64@0.20.2:
+ resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
@@ -911,8 +949,17 @@ packages:
dev: true
optional: true
- /@esbuild/android-arm@0.17.19:
- resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
+ /@esbuild/android-arm@0.19.12:
+ resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.20.2:
+ resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
@@ -920,8 +967,17 @@ packages:
dev: true
optional: true
- /@esbuild/android-x64@0.17.19:
- resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
+ /@esbuild/android-x64@0.19.12:
+ resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.20.2:
+ resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
@@ -929,8 +985,17 @@ packages:
dev: true
optional: true
- /@esbuild/darwin-arm64@0.17.19:
- resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
+ /@esbuild/darwin-arm64@0.19.12:
+ resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.20.2:
+ resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
@@ -938,8 +1003,17 @@ packages:
dev: true
optional: true
- /@esbuild/darwin-x64@0.17.19:
- resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
+ /@esbuild/darwin-x64@0.19.12:
+ resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.20.2:
+ resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
@@ -947,8 +1021,17 @@ packages:
dev: true
optional: true
- /@esbuild/freebsd-arm64@0.17.19:
- resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
+ /@esbuild/freebsd-arm64@0.19.12:
+ resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.20.2:
+ resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
@@ -956,8 +1039,17 @@ packages:
dev: true
optional: true
- /@esbuild/freebsd-x64@0.17.19:
- resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
+ /@esbuild/freebsd-x64@0.19.12:
+ resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.20.2:
+ resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
@@ -965,8 +1057,17 @@ packages:
dev: true
optional: true
- /@esbuild/linux-arm64@0.17.19:
- resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
+ /@esbuild/linux-arm64@0.19.12:
+ resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.20.2:
+ resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
@@ -974,8 +1075,17 @@ packages:
dev: true
optional: true
- /@esbuild/linux-arm@0.17.19:
- resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
+ /@esbuild/linux-arm@0.19.12:
+ resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.20.2:
+ resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
@@ -983,8 +1093,17 @@ packages:
dev: true
optional: true
- /@esbuild/linux-ia32@0.17.19:
- resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
+ /@esbuild/linux-ia32@0.19.12:
+ resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.20.2:
+ resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
@@ -992,8 +1111,17 @@ packages:
dev: true
optional: true
- /@esbuild/linux-loong64@0.17.19:
- resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
+ /@esbuild/linux-loong64@0.19.12:
+ resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.20.2:
+ resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
@@ -1001,8 +1129,17 @@ packages:
dev: true
optional: true
- /@esbuild/linux-mips64el@0.17.19:
- resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
+ /@esbuild/linux-mips64el@0.19.12:
+ resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.20.2:
+ resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
@@ -1010,8 +1147,17 @@ packages:
dev: true
optional: true
- /@esbuild/linux-ppc64@0.17.19:
- resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
+ /@esbuild/linux-ppc64@0.19.12:
+ resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.20.2:
+ resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
@@ -1019,8 +1165,8 @@ packages:
dev: true
optional: true
- /@esbuild/linux-riscv64@0.17.19:
- resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
+ /@esbuild/linux-riscv64@0.19.12:
+ resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
@@ -1028,8 +1174,26 @@ packages:
dev: true
optional: true
- /@esbuild/linux-s390x@0.17.19:
- resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
+ /@esbuild/linux-riscv64@0.20.2:
+ resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.19.12:
+ resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.20.2:
+ resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
@@ -1037,8 +1201,17 @@ packages:
dev: true
optional: true
- /@esbuild/linux-x64@0.17.19:
- resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
+ /@esbuild/linux-x64@0.19.12:
+ resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.20.2:
+ resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
@@ -1046,8 +1219,17 @@ packages:
dev: true
optional: true
- /@esbuild/netbsd-x64@0.17.19:
- resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
+ /@esbuild/netbsd-x64@0.19.12:
+ resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.20.2:
+ resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
@@ -1055,8 +1237,17 @@ packages:
dev: true
optional: true
- /@esbuild/openbsd-x64@0.17.19:
- resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
+ /@esbuild/openbsd-x64@0.19.12:
+ resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.20.2:
+ resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
@@ -1064,8 +1255,17 @@ packages:
dev: true
optional: true
- /@esbuild/sunos-x64@0.17.19:
- resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
+ /@esbuild/sunos-x64@0.19.12:
+ resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.20.2:
+ resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
@@ -1073,8 +1273,17 @@ packages:
dev: true
optional: true
- /@esbuild/win32-arm64@0.17.19:
- resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
+ /@esbuild/win32-arm64@0.19.12:
+ resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.20.2:
+ resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
@@ -1082,8 +1291,17 @@ packages:
dev: true
optional: true
- /@esbuild/win32-ia32@0.17.19:
- resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
+ /@esbuild/win32-ia32@0.19.12:
+ resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.20.2:
+ resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
@@ -1091,8 +1309,17 @@ packages:
dev: true
optional: true
- /@esbuild/win32-x64@0.17.19:
- resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
+ /@esbuild/win32-x64@0.19.12:
+ resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.20.2:
+ resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
@@ -1232,13 +1459,6 @@ packages:
type-detect: 4.0.8
dev: true
- /@mdit-vue/plugin-component@0.12.1:
- resolution: {integrity: sha512-L3elbvuKUufXwPLHrmJGd/ijd/QKxfcHXy3kRy4O+P7UIV7HSWePpfB0k+wWee+by3MviYYxjVAi392z+DGy3Q==}
- dependencies:
- '@types/markdown-it': 13.0.7
- markdown-it: 13.0.2
- dev: true
-
/@mdit-vue/plugin-component@2.0.0:
resolution: {integrity: sha512-cTRxlocav/+mfgDcp0P2z/gWuWBez+iNuN4D+b74LpX4AR6UAx2ZvWtCrUZ8VXrO4eCt1/G0YC/Af7mpIb3aoQ==}
dependencies:
@@ -1246,15 +1466,6 @@ packages:
markdown-it: 14.0.0
dev: true
- /@mdit-vue/plugin-frontmatter@0.12.1:
- resolution: {integrity: sha512-C6ycNjrJ+T4JgbVxwo9cUkfLacOO841Yl8ogqd5PJmAVpc5cM2OLBkqqkZxNRXos3g9xM1VvIQ7gK/047UNADg==}
- dependencies:
- '@mdit-vue/types': 0.12.0
- '@types/markdown-it': 13.0.7
- gray-matter: 4.0.3
- markdown-it: 13.0.2
- dev: true
-
/@mdit-vue/plugin-frontmatter@2.0.0:
resolution: {integrity: sha512-/LrT6E60QI4XV4mqx3J87hqYXlR7ZyMvndmftR2RGz7cRAwa/xL+kyFLlgrMxkBIKitOShKa3LS/9Ov9b0fU+g==}
dependencies:
@@ -1264,15 +1475,6 @@ packages:
markdown-it: 14.0.0
dev: true
- /@mdit-vue/plugin-headers@0.12.1:
- resolution: {integrity: sha512-DXAw/iWW8f3qUYMDHgQmamL+XGjnaoeRzdvDseLRyr7gXX4xpYO9OIhe/pv9LzSvUoY7UGYmn4kFeI+0qpWJ+g==}
- dependencies:
- '@mdit-vue/shared': 0.12.1
- '@mdit-vue/types': 0.12.0
- '@types/markdown-it': 13.0.7
- markdown-it: 13.0.2
- dev: true
-
/@mdit-vue/plugin-headers@2.0.0:
resolution: {integrity: sha512-ITMMPCnLEYHHgj3XEUL2l75jsNn8guxNqr26YrMSi1f5zcgq4XVy1LIvfwvJ1puqM6Cc5v4BHk3oAyorAi7l1A==}
dependencies:
@@ -1282,14 +1484,6 @@ packages:
markdown-it: 14.0.0
dev: true
- /@mdit-vue/plugin-sfc@0.12.1:
- resolution: {integrity: sha512-6j332CsSqumy1+StIM3XphdXG1zj9NXuWestDJrKgS3OLy5P0EAioXScUYiZYysw61ZG+2pP37MW7Hg+eHbyIg==}
- dependencies:
- '@mdit-vue/types': 0.12.0
- '@types/markdown-it': 13.0.7
- markdown-it: 13.0.2
- dev: true
-
/@mdit-vue/plugin-sfc@2.0.0:
resolution: {integrity: sha512-OXrMXOyk0iwdIou2jRoIHIbjskwghkO14C9/OjgVHXSSX+iM/WQ4l4yi1aWmNlbQNjtP8IXcVAyJB9K0DFYmLg==}
dependencies:
@@ -1298,15 +1492,6 @@ packages:
markdown-it: 14.0.0
dev: true
- /@mdit-vue/plugin-title@0.12.1:
- resolution: {integrity: sha512-JOsiDj+CryGbrTDWUnDAwB9kSkN6o9GDo3udR6BPDgBNVb3zAnx9ZNaRpEhDW1LnQhf9/LYicWJ2eTNRKPcJNQ==}
- dependencies:
- '@mdit-vue/shared': 0.12.1
- '@mdit-vue/types': 0.12.0
- '@types/markdown-it': 13.0.7
- markdown-it: 13.0.2
- dev: true
-
/@mdit-vue/plugin-title@2.0.0:
resolution: {integrity: sha512-eqBoETPVkMXNLvwFshz/A2+Cz81VB5HEkXDm0tt6RBW/rTvnoWmGJ1Z+mvcjR5ck5W4nYdIyT68oHxX2JI2M4g==}
dependencies:
@@ -1316,15 +1501,6 @@ packages:
markdown-it: 14.0.0
dev: true
- /@mdit-vue/plugin-toc@0.12.1:
- resolution: {integrity: sha512-nFGwTwVa8GLCKJMV7cGST7lYuljSjEiCTPgKIpQ/WifwouHsQaL/rnBDr22kpzY2hRTAhM3+TT5GDwLyxa/e6A==}
- dependencies:
- '@mdit-vue/shared': 0.12.1
- '@mdit-vue/types': 0.12.0
- '@types/markdown-it': 13.0.7
- markdown-it: 13.0.2
- dev: true
-
/@mdit-vue/plugin-toc@2.0.0:
resolution: {integrity: sha512-PKQ8sZna3D5chTnt2lxL+ddpyXd++6Nyc0l8VXCeDgStlySQwiP9jaLeeC88oqY4BtRu4cAmILmxDrvuX0Rrdg==}
dependencies:
@@ -1334,14 +1510,6 @@ packages:
markdown-it: 14.0.0
dev: true
- /@mdit-vue/shared@0.12.1:
- resolution: {integrity: sha512-bXgd0KThe4jC2leCFDFsyrudXIckvTwV4WnQK/rRMrXq0/BAuVdSNdIv1LGCWZxD5+oDyPyEPd0lalTIFwqsmg==}
- dependencies:
- '@mdit-vue/types': 0.12.0
- '@types/markdown-it': 13.0.7
- markdown-it: 13.0.2
- dev: true
-
/@mdit-vue/shared@2.0.0:
resolution: {integrity: sha512-PdxpQpbyTazeo2JT87qms6RPZIzyJd+gwuB+1jSwLDI7+0u5g79y2XgTAbZromSVgY2f3UU5HWdwaLbV9w4uOw==}
dependencies:
@@ -1350,10 +1518,6 @@ packages:
markdown-it: 14.0.0
dev: true
- /@mdit-vue/types@0.12.0:
- resolution: {integrity: sha512-mrC4y8n88BYvgcgzq9bvTlDgFyi2zuvzmPilRvRc3Uz1iIvq8mDhxJ0rHKFUNzPEScpDvJdIujqiDrulMqiudA==}
- dev: true
-
/@mdit-vue/types@2.0.0:
resolution: {integrity: sha512-1BeEB+DbtmDMUAfvbNUj5Hso8cSl2sBVK2iTyOMAqhfDVLdh+/9+D0JmQHaCeUk/vuJoMhOwbweZvh55wHxm4w==}
dev: true
@@ -1464,6 +1628,134 @@ packages:
- typescript
dev: true
+ /@rollup/rollup-android-arm-eabi@4.17.2:
+ resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-android-arm64@4.17.2:
+ resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-arm64@4.17.2:
+ resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-x64@4.17.2:
+ resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-gnueabihf@4.17.2:
+ resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-musleabihf@4.17.2:
+ resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-gnu@4.17.2:
+ resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-musl@4.17.2:
+ resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-powerpc64le-gnu@4.17.2:
+ resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-riscv64-gnu@4.17.2:
+ resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-s390x-gnu@4.17.2:
+ resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-gnu@4.17.2:
+ resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-musl@4.17.2:
+ resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-arm64-msvc@4.17.2:
+ resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-ia32-msvc@4.17.2:
+ resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-x64-msvc@4.17.2:
+ resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@royli/hygen@6.2.0:
resolution: {integrity: sha512-Qs5pC3ETSRQb7iqZ9eAgFxpedyb1Ezu76H/d4HULT/T/YNO3o5QQ/+lwAAfpIFWh5ws3G9TPrwZ3tAKScNIVjQ==}
hasBin: true
@@ -1639,7 +1931,6 @@ packages:
/@types/estree@1.0.5:
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
- dev: false
/@types/fs-extra@11.0.4:
resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==}
@@ -1724,6 +2015,13 @@ packages:
'@types/mdurl': 1.0.5
dev: true
+ /@types/markdown-it@14.0.1:
+ resolution: {integrity: sha512-6WfOG3jXR78DW8L5cTYCVVGAsIFZskRHCDo5tbqa+qtKVt4oDRVH7hyIWu1SpDQJlmIoEivNQZ5h+AGAOrgOtQ==}
+ dependencies:
+ '@types/linkify-it': 3.0.5
+ '@types/mdurl': 1.0.5
+ dev: true
+
/@types/mdurl@1.0.5:
resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==}
dev: true
@@ -1961,15 +2259,15 @@ packages:
/@ungap/structured-clone@1.2.0:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
- /@vitejs/plugin-vue@4.6.2(vite@4.3.9)(vue@3.4.21):
- resolution: {integrity: sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==}
- engines: {node: ^14.18.0 || >=16.0.0}
+ /@vitejs/plugin-vue@5.0.4(vite@5.0.13)(vue@3.4.26):
+ resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
peerDependencies:
- vite: ^4.0.0 || ^5.0.0
+ vite: ^5.0.0
vue: ^3.2.25
dependencies:
- vite: 4.3.9(@types/node@18.19.21)(sass@1.71.1)
- vue: 3.4.21(typescript@5.3.3)
+ vite: 5.0.13(@types/node@18.19.21)(sass@1.71.1)
+ vue: 3.4.26(typescript@5.3.3)
dev: true
/@vue/compiler-core@3.4.21:
@@ -1982,6 +2280,16 @@ packages:
source-map-js: 1.0.2
dev: true
+ /@vue/compiler-core@3.4.26:
+ resolution: {integrity: sha512-N9Vil6Hvw7NaiyFUFBPXrAyETIGlQ8KcFMkyk6hW1Cl6NvoqvP+Y8p1Eqvx+UdqsnrnI9+HMUEJegzia3mhXmQ==}
+ dependencies:
+ '@babel/parser': 7.24.5
+ '@vue/shared': 3.4.26
+ entities: 4.5.0
+ estree-walker: 2.0.2
+ source-map-js: 1.2.0
+ dev: true
+
/@vue/compiler-dom@3.4.21:
resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==}
dependencies:
@@ -1989,6 +2297,13 @@ packages:
'@vue/shared': 3.4.21
dev: true
+ /@vue/compiler-dom@3.4.26:
+ resolution: {integrity: sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA==}
+ dependencies:
+ '@vue/compiler-core': 3.4.26
+ '@vue/shared': 3.4.26
+ dev: true
+
/@vue/compiler-sfc@3.4.21:
resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==}
dependencies:
@@ -2003,6 +2318,20 @@ packages:
source-map-js: 1.0.2
dev: true
+ /@vue/compiler-sfc@3.4.26:
+ resolution: {integrity: sha512-It1dp+FAOCgluYSVYlDn5DtZBxk1NCiJJfu2mlQqa/b+k8GL6NG/3/zRbJnHdhV2VhxFghaDq5L4K+1dakW6cw==}
+ dependencies:
+ '@babel/parser': 7.24.5
+ '@vue/compiler-core': 3.4.26
+ '@vue/compiler-dom': 3.4.26
+ '@vue/compiler-ssr': 3.4.26
+ '@vue/shared': 3.4.26
+ estree-walker: 2.0.2
+ magic-string: 0.30.10
+ postcss: 8.4.38
+ source-map-js: 1.2.0
+ dev: true
+
/@vue/compiler-ssr@3.4.21:
resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==}
dependencies:
@@ -2010,6 +2339,13 @@ packages:
'@vue/shared': 3.4.21
dev: true
+ /@vue/compiler-ssr@3.4.26:
+ resolution: {integrity: sha512-FNwLfk7LlEPRY/g+nw2VqiDKcnDTVdCfBREekF8X74cPLiWHUX6oldktf/Vx28yh4STNy7t+/yuLoMBBF7YDiQ==}
+ dependencies:
+ '@vue/compiler-dom': 3.4.26
+ '@vue/shared': 3.4.26
+ dev: true
+
/@vue/devtools-api@6.6.1:
resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==}
dev: true
@@ -2020,6 +2356,12 @@ packages:
'@vue/shared': 3.4.21
dev: true
+ /@vue/reactivity@3.4.26:
+ resolution: {integrity: sha512-E/ynEAu/pw0yotJeLdvZEsp5Olmxt+9/WqzvKff0gE67tw73gmbx6tRkiagE/eH0UCubzSlGRebCbidB1CpqZQ==}
+ dependencies:
+ '@vue/shared': 3.4.26
+ dev: true
+
/@vue/runtime-core@3.4.21:
resolution: {integrity: sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==}
dependencies:
@@ -2027,6 +2369,13 @@ packages:
'@vue/shared': 3.4.21
dev: true
+ /@vue/runtime-core@3.4.26:
+ resolution: {integrity: sha512-AFJDLpZvhT4ujUgZSIL9pdNcO23qVFh7zWCsNdGQBw8ecLNxOOnPcK9wTTIYCmBJnuPHpukOwo62a2PPivihqw==}
+ dependencies:
+ '@vue/reactivity': 3.4.26
+ '@vue/shared': 3.4.26
+ dev: true
+
/@vue/runtime-dom@3.4.21:
resolution: {integrity: sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==}
dependencies:
@@ -2035,6 +2384,14 @@ packages:
csstype: 3.1.3
dev: true
+ /@vue/runtime-dom@3.4.26:
+ resolution: {integrity: sha512-UftYA2hUXR2UOZD/Fc3IndZuCOOJgFxJsWOxDkhfVcwLbsfh2CdXE2tG4jWxBZuDAs9J9PzRTUFt1PgydEtItw==}
+ dependencies:
+ '@vue/runtime-core': 3.4.26
+ '@vue/shared': 3.4.26
+ csstype: 3.1.3
+ dev: true
+
/@vue/server-renderer@3.4.21(vue@3.4.21):
resolution: {integrity: sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==}
peerDependencies:
@@ -2045,99 +2402,104 @@ packages:
vue: 3.4.21(typescript@5.3.3)
dev: true
+ /@vue/server-renderer@3.4.26(vue@3.4.26):
+ resolution: {integrity: sha512-xoGAqSjYDPGAeRWxeoYwqJFD/gw7mpgzOvSxEmjWaFO2rE6qpbD1PC172YRpvKhrihkyHJkNDADFXTfCyVGhKw==}
+ peerDependencies:
+ vue: 3.4.26
+ dependencies:
+ '@vue/compiler-ssr': 3.4.26
+ '@vue/shared': 3.4.26
+ vue: 3.4.26(typescript@5.3.3)
+ dev: true
+
/@vue/shared@3.4.21:
resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==}
dev: true
- /@vuepress/bundler-vite@2.0.0-beta.62(@types/node@18.19.21)(sass@1.71.1)(ts-node@10.9.2)(typescript@5.3.3):
- resolution: {integrity: sha512-Dpb4rJycssM1gs3MlQ5z0cwQ0KCx9Iliojt+qs5lVIUHP9vfw6ANYx51R3ojctt3dCoWfC4bAL4NhGQndGKvrQ==}
+ /@vue/shared@3.4.26:
+ resolution: {integrity: sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==}
+ dev: true
+
+ /@vuepress/bundler-vite@2.0.0-rc.7(@types/node@18.19.21)(sass@1.71.1)(typescript@5.3.3):
+ resolution: {integrity: sha512-2jNnU3sgHJuUCPfE0DvGRsAxo/A/Locguvnv4Q6QwJYdB1fuAqE6x5p8RDzq8Lv/GsyeexDWiV/PFER5EtVP3w==}
dependencies:
- '@vitejs/plugin-vue': 4.6.2(vite@4.3.9)(vue@3.4.21)
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
- autoprefixer: 10.4.18(postcss@8.4.35)
+ '@vitejs/plugin-vue': 5.0.4(vite@5.0.13)(vue@3.4.26)
+ '@vuepress/client': 2.0.0-rc.7(typescript@5.3.3)
+ '@vuepress/core': 2.0.0-rc.7(typescript@5.3.3)
+ '@vuepress/shared': 2.0.0-rc.7
+ '@vuepress/utils': 2.0.0-rc.7
+ autoprefixer: 10.4.19(postcss@8.4.38)
connect-history-api-fallback: 2.0.0
- postcss: 8.4.35
- postcss-load-config: 4.0.2(postcss@8.4.35)(ts-node@10.9.2)
- rollup: 3.29.4
- vite: 4.3.9(@types/node@18.19.21)(sass@1.71.1)
- vue: 3.4.21(typescript@5.3.3)
- vue-router: 4.3.0(vue@3.4.21)
+ postcss: 8.4.38
+ postcss-load-config: 5.0.3(postcss@8.4.38)
+ rollup: 4.17.2
+ vite: 5.0.13(@types/node@18.19.21)(sass@1.71.1)
+ vue: 3.4.26(typescript@5.3.3)
+ vue-router: 4.3.0(vue@3.4.26)
transitivePeerDependencies:
- '@types/node'
+ - '@vue/composition-api'
+ - jiti
- less
+ - lightningcss
- sass
- stylus
- sugarss
- supports-color
- terser
- - ts-node
- typescript
dev: true
- /@vuepress/cli@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-z5mpxORVSZUWsSGtA0bqvsd4vhMDWXAGnQfHjYZ5ylUgnYMxBZMRWrQcpz9doMCk5Qkn56B2s2jKZEvhyFvdAg==}
+ /@vuepress/cli@2.0.0-rc.9(typescript@5.3.3):
+ resolution: {integrity: sha512-uv7Xmv3QmPpzCaUAq0oKEwp2tY64AO+7mxamgr7tr+t6FEnCYqr+X0nLlH17UtMkmGWIsbHLIlMjteprxGxIMg==}
hasBin: true
dependencies:
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
+ '@vuepress/core': 2.0.0-rc.9(typescript@5.3.3)
+ '@vuepress/shared': 2.0.0-rc.9
+ '@vuepress/utils': 2.0.0-rc.9
cac: 6.7.14
chokidar: 3.6.0
envinfo: 7.11.1
- esbuild: 0.17.19
+ esbuild: 0.20.2
transitivePeerDependencies:
- supports-color
- typescript
dev: true
- /@vuepress/client@2.0.0-beta.61(typescript@5.3.3):
- resolution: {integrity: sha512-C5QbdQkPsurEsKUkLclVucUAKMzBph9kHMUvfKHJqBaAsiXKYVLa61AICTJeyDkhTYF0faOjmpqmaElfMt1S9w==}
+ /@vuepress/client@2.0.0-rc.2(typescript@5.3.3):
+ resolution: {integrity: sha512-gQ4CfBhzWYOCW4OcAUd6S8Jr9m/8UkZZuN/70t12GltbX/cdm6zrGnf89GiVjgvoK8+OYoc7luoBuWbyc/X5sg==}
dependencies:
'@vue/devtools-api': 6.6.1
- '@vuepress/shared': 2.0.0-beta.61
+ '@vuepress/shared': 2.0.0-rc.2
+ '@vueuse/core': 10.9.0(vue@3.4.21)
vue: 3.4.21(typescript@5.3.3)
vue-router: 4.3.0(vue@3.4.21)
transitivePeerDependencies:
+ - '@vue/composition-api'
- typescript
dev: true
- /@vuepress/client@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-5JT0H6EibhZMVmg1fel2BWFFaAEv5zOoD397LOiMQmcEuUneeKNSwGcLrJDyvv8AOXz4wsXwET/to3TsOFoHDQ==}
+ /@vuepress/client@2.0.0-rc.7(typescript@5.3.3):
+ resolution: {integrity: sha512-T8jf9h8dfP1ln/7uOIiTAJrdyKRTyq1x+RHXuc7GoRxTfOw+bIYgGvh63Z7m1e3K/yh1nO9aM1WcXbDN1Swp4w==}
dependencies:
'@vue/devtools-api': 6.6.1
- '@vuepress/shared': 2.0.0-beta.62
- vue: 3.4.21(typescript@5.3.3)
- vue-router: 4.3.0(vue@3.4.21)
+ '@vuepress/shared': 2.0.0-rc.7
+ '@vueuse/core': 10.9.0(vue@3.4.26)
+ vue: 3.4.26(typescript@5.3.3)
+ vue-router: 4.3.0(vue@3.4.26)
transitivePeerDependencies:
+ - '@vue/composition-api'
- typescript
dev: true
- /@vuepress/client@2.0.0-rc.2(typescript@5.3.3):
- resolution: {integrity: sha512-gQ4CfBhzWYOCW4OcAUd6S8Jr9m/8UkZZuN/70t12GltbX/cdm6zrGnf89GiVjgvoK8+OYoc7luoBuWbyc/X5sg==}
+ /@vuepress/client@2.0.0-rc.9(typescript@5.3.3):
+ resolution: {integrity: sha512-V5jA6L1nHQ8tXBshRHBJKei7HPFonGxFzmVK5yjj2Ho/Xtp/SD9rBS6dyYd5CSkKRGQDgy19Z+BUUPXtdI1qzg==}
dependencies:
'@vue/devtools-api': 6.6.1
- '@vuepress/shared': 2.0.0-rc.2
- '@vueuse/core': 10.9.0(vue@3.4.21)
+ '@vuepress/shared': 2.0.0-rc.9
vue: 3.4.21(typescript@5.3.3)
vue-router: 4.3.0(vue@3.4.21)
transitivePeerDependencies:
- - '@vue/composition-api'
- - typescript
- dev: true
-
- /@vuepress/core@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-IyL1lxkRg2PO6oFDcioa5YKckKO8jEIwPaNG4mwv7bIEwaN5kpsROVtBeYHKkcnncWQMrbBG/z8aHDvjO/vFJA==}
- dependencies:
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/markdown': 2.0.0-beta.62
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
- vue: 3.4.21(typescript@5.3.3)
- transitivePeerDependencies:
- - supports-color
- typescript
dev: true
@@ -2155,27 +2517,46 @@ packages:
- typescript
dev: true
- /@vuepress/markdown@2.0.0-beta.62:
- resolution: {integrity: sha512-OTGSHDALEE1zgAJgx9Py1AKR1JA/eLTjw63ul77ymt/5eNlU8/EVJg8Pj2nwL3cpvCpzB6sQ1Xkj4TF7D0aD1Q==}
+ /@vuepress/core@2.0.0-rc.7(typescript@5.3.3):
+ resolution: {integrity: sha512-SPd2C9MIwHLe4mEWJfbcTHT5caS/vW+oeP79wAW0otSGgn2uY3Mmu5qcYPzl+17o8EYv7vDvPiO+uitp/Cek+A==}
dependencies:
- '@mdit-vue/plugin-component': 0.12.1
- '@mdit-vue/plugin-frontmatter': 0.12.1
- '@mdit-vue/plugin-headers': 0.12.1
- '@mdit-vue/plugin-sfc': 0.12.1
- '@mdit-vue/plugin-title': 0.12.1
- '@mdit-vue/plugin-toc': 0.12.1
- '@mdit-vue/shared': 0.12.1
- '@mdit-vue/types': 0.12.0
- '@types/markdown-it': 12.2.3
- '@types/markdown-it-emoji': 2.0.4
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
- markdown-it: 13.0.2
- markdown-it-anchor: 8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.2)
- markdown-it-emoji: 2.0.2
- mdurl: 1.0.1
+ '@vuepress/client': 2.0.0-rc.7(typescript@5.3.3)
+ '@vuepress/markdown': 2.0.0-rc.7
+ '@vuepress/shared': 2.0.0-rc.7
+ '@vuepress/utils': 2.0.0-rc.7
+ vue: 3.4.26(typescript@5.3.3)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/core@2.0.0-rc.9(typescript@5.3.3):
+ resolution: {integrity: sha512-uvMkIqYJ7vjfYEC91rMmT8YJt8xXnob5YYY3TzlwWUSEv4yoV3nlVu0l6Zfhenx/7FwKaxRJ/ePlUGIgUHBcBw==}
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.9(typescript@5.3.3)
+ '@vuepress/markdown': 2.0.0-rc.9
+ '@vuepress/shared': 2.0.0-rc.9
+ '@vuepress/utils': 2.0.0-rc.9
+ vue: 3.4.26(typescript@5.3.3)
transitivePeerDependencies:
- supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/helper@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-/x5Txye+47UmongbiYzsNSuNBiez4mKnnzW1ldX1e6LtAa71zvNH1KD9/MAKlYs34he0NkVrOysJE9/f79tmig==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
+ dependencies:
+ '@vue/shared': 3.4.26
+ cheerio: 1.0.0-rc.12
+ fflate: 0.8.2
+ gray-matter: 4.0.3
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
+ transitivePeerDependencies:
+ - typescript
dev: true
/@vuepress/markdown@2.0.0-rc.2:
@@ -2201,62 +2582,117 @@ packages:
- supports-color
dev: true
- /@vuepress/plugin-active-header-links@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-NUoa0JP2npSydJQvM1oOPEtPCKRmtqpkPLxTeBCP6ucR/eHpCbBMrgYt3w6kdmMJykc/AWFd4oZA1QS/MAoEtw==}
+ /@vuepress/markdown@2.0.0-rc.7:
+ resolution: {integrity: sha512-mczvo7MZxxXXj5htDXK22r0a7JjTP5sTlcywtVOTJurzCKp8SNSbr3HdmsAnr9S838Hn9+dkvhs57rqgPG3UHA==}
dependencies:
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/utils': 2.0.0-beta.62
- ts-debounce: 4.0.0
- vue: 3.4.21(typescript@5.3.3)
- vue-router: 4.3.0(vue@3.4.21)
+ '@mdit-vue/plugin-component': 2.0.0
+ '@mdit-vue/plugin-frontmatter': 2.0.0
+ '@mdit-vue/plugin-headers': 2.0.0
+ '@mdit-vue/plugin-sfc': 2.0.0
+ '@mdit-vue/plugin-title': 2.0.0
+ '@mdit-vue/plugin-toc': 2.0.0
+ '@mdit-vue/shared': 2.0.0
+ '@mdit-vue/types': 2.0.0
+ '@types/markdown-it': 13.0.7
+ '@types/markdown-it-emoji': 2.0.4
+ '@vuepress/shared': 2.0.0-rc.7
+ '@vuepress/utils': 2.0.0-rc.7
+ markdown-it: 14.1.0
+ markdown-it-anchor: 8.6.7(@types/markdown-it@13.0.7)(markdown-it@14.1.0)
+ markdown-it-emoji: 3.0.0
+ mdurl: 2.0.0
transitivePeerDependencies:
- supports-color
- - typescript
dev: true
- /@vuepress/plugin-back-to-top@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-ndStdKobpq7/YxhtUg2YrSkd8FNoE0v4pPVdTBND6jlkPns4CCcyu+w6BZ8mkiiB2dzS27JrhKcXHz1Tsb0nUA==}
+ /@vuepress/markdown@2.0.0-rc.9:
+ resolution: {integrity: sha512-e7as2ar3RQp0bUyMiwBPi7L/G2fzscb3s0BywNcAwubFR22o0/dBEYRYdrN0clPQ2FXpPxF6AFj4aD7O1heCbw==}
dependencies:
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/utils': 2.0.0-beta.62
- ts-debounce: 4.0.0
- vue: 3.4.21(typescript@5.3.3)
+ '@mdit-vue/plugin-component': 2.0.0
+ '@mdit-vue/plugin-frontmatter': 2.0.0
+ '@mdit-vue/plugin-headers': 2.0.0
+ '@mdit-vue/plugin-sfc': 2.0.0
+ '@mdit-vue/plugin-title': 2.0.0
+ '@mdit-vue/plugin-toc': 2.0.0
+ '@mdit-vue/shared': 2.0.0
+ '@mdit-vue/types': 2.0.0
+ '@types/markdown-it': 13.0.7
+ '@types/markdown-it-emoji': 2.0.4
+ '@vuepress/shared': 2.0.0-rc.9
+ '@vuepress/utils': 2.0.0-rc.9
+ markdown-it: 14.1.0
+ markdown-it-anchor: 8.6.7(@types/markdown-it@13.0.7)(markdown-it@14.1.0)
+ markdown-it-emoji: 3.0.0
+ mdurl: 2.0.0
transitivePeerDependencies:
- supports-color
+ dev: true
+
+ /@vuepress/plugin-active-header-links@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-8znvmaw0QBX0SXhV49ob3OIrDustpGN8SrJJecVE6d39OThyJ470XAX3vWteyMnsdDnlD0RckqMbhxbTmXbXxw==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
+ dependencies:
+ '@vueuse/core': 10.9.0(vue@3.4.26)
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
- typescript
dev: true
- /@vuepress/plugin-container@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-ibo0J8ye5KA6zkwIttkVqleSLy4Sq0rcSW+X8cTzyFfoKKs0Y+ECjmf4wRrDl79m+lgpA43mlFpCcbgtmV9aqw==}
+ /@vuepress/plugin-back-to-top@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-1pkSPmXc6CyhDu/KrXbhF0tUzRbOFEXItCMedvjgYBH1eJ9upUZm/M/xbQICfm/Vt8zB3asU7pIW0Q4RBJk/eQ==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@types/markdown-it': 12.2.3
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/markdown': 2.0.0-beta.62
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
- markdown-it: 13.0.2
- markdown-it-container: 3.0.0
+ '@vuepress/helper': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vueuse/core': 10.9.0(vue@3.4.26)
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- - supports-color
+ - '@vue/composition-api'
- typescript
dev: true
- /@vuepress/plugin-docsearch@2.0.0-beta.62(@algolia/client-search@4.22.1)(typescript@5.3.3):
- resolution: {integrity: sha512-XdY4o15CKLqTEn485/pjWLdfV3fsm9JkoDJ97b9Cv0I9T/oW8NV3BFVezdX1d06vxB/doqoGj+JFEJH7t1lEuw==}
+ /@vuepress/plugin-container@2.0.0-rc.25(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-2yUuBWy09d1JGs6v4siebxN1Uo80XXUv800XfUqZ+Nnlu/362i5Ro2GDYww9MSP3yKKZjTnvIlUeX8S0H0wqrg==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@docsearch/css': 3.5.2
- '@docsearch/js': 3.5.2(@algolia/client-search@4.22.1)
- '@docsearch/react': 3.5.2(@algolia/client-search@4.22.1)
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
- '@vueuse/core': 10.9.0(vue@3.4.21)
+ '@types/markdown-it': 14.0.1
+ markdown-it: 14.1.0
+ markdown-it-container: 4.0.0
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
+ dev: true
+
+ /@vuepress/plugin-copy-code@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-kYb0t49cvhJHYam03OSt5bq7mKUaWKU6ko5jex/C6kjEsuSusCWdY7pnJ4PXl63/umFcdJPfTvtaZfbJE5SAHA==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
+ dependencies:
+ '@vuepress/helper': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vueuse/core': 10.9.0(vue@3.4.26)
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-docsearch@2.0.0-rc.26(@algolia/client-search@4.22.1)(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-/Wa0FAURLFtxyvoH1TS793GeVvsOWy9VrIeil5wAMwR1O9pI1EOID+BzgeiaWAav4H4/sdwaG1OsB68N9q3MLQ==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
+ dependencies:
+ '@docsearch/css': 3.6.0
+ '@docsearch/js': 3.6.0(@algolia/client-search@4.22.1)
+ '@docsearch/react': 3.6.0(@algolia/client-search@4.22.1)
+ '@vuepress/helper': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vueuse/core': 10.9.0(vue@3.4.26)
ts-debounce: 4.0.0
- vue: 3.4.21(typescript@5.3.3)
- vue-router: 4.3.0(vue@3.4.21)
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- '@algolia/client-search'
- '@types/react'
@@ -2264,213 +2700,228 @@ packages:
- react
- react-dom
- search-insights
- - supports-color
- typescript
dev: true
- /@vuepress/plugin-external-link-icon@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-mQ7gj6pMHYCp7zk6N92omxUz9CjKYZtvZXkNmsloZsz0hiGS1SdG29vLo8yKm/qVzyu9F45WgVNcdQD5mkzx3Q==}
+ /@vuepress/plugin-external-link-icon@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-jTa3JNgV6ZfKRjBm+tjwTh7ZU23cEPcC5alGeYMTyUf9wHkv0fmWJ7IO6HFrilTgXE+ejaj7ouZDqwTYeNej3g==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/markdown': 2.0.0-beta.62
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
- vue: 3.4.21(typescript@5.3.3)
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- - supports-color
- typescript
dev: true
- /@vuepress/plugin-git@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-vTYUguI+X5G7JPTySDnZ6lcAGXBWlD1Nsw9IV42Hh4fvevWzZ3WIjkAhjZpdURIz+xQPEZBbgqnOKjBpbPx0jA==}
+ /@vuepress/plugin-git@2.0.0-rc.22(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-+T50AdCZ68Pkld4r8IEHTXLugfNVCxxPp2G1hlI/lpQ6IZcpLbswMI6l9xbbo15RrOBg/V0jkim/B/jaaVIM6A==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/utils': 2.0.0-beta.62
- execa: 7.2.0
- transitivePeerDependencies:
- - supports-color
- - typescript
+ execa: 8.0.1
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
+ dev: true
+
+ /@vuepress/plugin-google-analytics@2.0.0-rc.21(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-ZqDw3MrxA3tY5WXD/LIaZoCSgnynO9aQboOUgm1SF8GoR/7ULqiCWmxbLD3L8kkWS3TWKnH+JwK0VG0J6FNyFA==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
+ dependencies:
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
dev: true
- /@vuepress/plugin-google-analytics@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-Nm2GGb2KCooZjKD0ZgmmlI+2N05/mCMIJ8ziZU/3xrao6oRCxlKFm+g1L0iE/1XY2vNQpX76OedhSwRtYEjsRw==}
+ /@vuepress/plugin-links-check@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-4npcEmyEOxUx0/+YrvWJ8+Wcy4QZHyLG8vARTB7nz+70VoPIgQT3pysc1l3V282wou0WSsNhRKTN6YqF8k6RYg==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/utils': 2.0.0-beta.62
+ '@vuepress/helper': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- - supports-color
- typescript
dev: true
- /@vuepress/plugin-medium-zoom@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-1BolO1OE9Dxf4xLpEDEYjWTmx+luD6RSwjM+Wbgp7gBMK98yY8N9rHxWCzhLWbTffVezmAO0ze37l7hVd4ypTA==}
+ /@vuepress/plugin-medium-zoom@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-JIrMrvHEy+5Jw/xF4hfD90tmYPpMX/v/ltLmQk2tKOOn0DyuFhu9j7urs3roxdJwULf3kWNNIwJEK4xg6sl2Qw==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/utils': 2.0.0-beta.62
+ '@vuepress/helper': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
medium-zoom: 1.1.0
- vue: 3.4.21(typescript@5.3.3)
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- - supports-color
- typescript
dev: true
- /@vuepress/plugin-nprogress@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-w1Qqw1pP7+fXN+Aznmbfdp62XnQJ2s/FJyoGfV7LjVfV+gWFtqymiJiahvd2aQpBi4/qZNvtFJ1SOQf5tn1CxA==}
+ /@vuepress/plugin-nprogress@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-DXuPEc7TXfNm9yg3cOk9gQzmYBinb0BamJpZEpn3JPibfEsB8M2mzWxDHt/QU/ERSEkBy4BODOUKYq824+LAZQ==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/utils': 2.0.0-beta.62
- vue: 3.4.21(typescript@5.3.3)
- vue-router: 4.3.0(vue@3.4.21)
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- - supports-color
- typescript
dev: true
- /@vuepress/plugin-palette@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-Tw+KFxC8c3KIGeXANqMXFLoQ96ZQ/hJaKC0qm6iN04Wk9hKYazkxhPZTAZkOG3SrxaxvOrgnzvicpci6FJgnGA==}
+ /@vuepress/plugin-palette@2.0.0-rc.21(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-jnWzTiM3xHXweD3AKZVTCnuliH/aoIGaV1C5yhIeinXPZHn49syH8wMQ3kAgxWO+Y4xfihiY8E32V33XQ8Lf6w==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/utils': 2.0.0-beta.62
chokidar: 3.6.0
- transitivePeerDependencies:
- - supports-color
- - typescript
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
dev: true
- /@vuepress/plugin-prismjs@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-kPrlh+I4w+YyU6joahjvuMo2zMwbpB36drZYfjXtYFFIxpBQ5Xdse4xx89vYOX0KqckOQrNa/tnYnfBuHBkgAQ==}
+ /@vuepress/plugin-prismjs@2.0.0-rc.21(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-dMTCu/TZ1QCmTHXL4THVeh9gWzuqkJV8qhck5U77OP1qmgyf+r529A+MTOgp3ddcph1Yzb/FRb2orlefHk+yNQ==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
prismjs: 1.29.0
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
+ dev: true
+
+ /@vuepress/plugin-register-components@2.0.0-rc.21(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-kfzM1fYTXJh0z0kmzA/Fwm7iTdcWJMtoncy42p/p/RwGjYtVfQw5PGbV/0mnwwupxsjA+VcOTcrJOcaphsUMUA==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
+ dependencies:
+ chokidar: 3.6.0
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
+ dev: true
+
+ /@vuepress/plugin-seo@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-V8GVPz6PlKXIHNjPlGpTzokO4mmxIaWkCDHQO/zexP9bIjad+oi8m/UL32hwisw42aEyLBAr13l3pRV6HGwgCg==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
+ dependencies:
+ '@vuepress/helper': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- - supports-color
- typescript
dev: true
- /@vuepress/plugin-register-components@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-H500SYMlPgw85tE3Gcpfn5phlS6t+CeQo+Nj7epzfe0cDfZ9cnqwyM5KPNfd9NBl1Lan8JsEU9YTEmTxasujDw==}
+ /@vuepress/plugin-sitemap@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-MGj8m+2gajFQ6ZibgkjZFA/BLhwPncYIGJ1D2k934VnziQNHJC3hz4THhr8jN+xv5DbD/LhU1TTo2vqJQ3iGnQ==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/utils': 2.0.0-beta.62
- chokidar: 3.6.0
+ '@vuepress/helper': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ sitemap: 7.1.1
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- - supports-color
- typescript
dev: true
- /@vuepress/plugin-theme-data@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-q6XHIDnZcJ5W55TlynKrwHtHormZedEY5man9zT4hlZywr3vVBgToHztObNTqgn6CssFaW2BFXDlW17iyS2D2A==}
+ /@vuepress/plugin-theme-data@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-3eN68ada9+gdzCNzK6o6uRfpTUoUHXo8EUXRUBk2K9bCtb/dL20Q+BUE61iN9zeEidVcf02BBrqvgBrjEU5CGQ==}
+ peerDependencies:
+ vuepress: 2.0.0-rc.9
dependencies:
'@vue/devtools-api': 6.6.1
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
- vue: 3.4.21(typescript@5.3.3)
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- - supports-color
- typescript
dev: true
- /@vuepress/shared@2.0.0-beta.61:
- resolution: {integrity: sha512-NhOQ1FDr5lDSu5IinNlNNzrF+jGOZ+bMFUyAlCxlTvK9oY6aRBCNwV8dWme+yoh3/zviKHGu62Xp7J2hKAHNZA==}
+ /@vuepress/shared@2.0.0-rc.2:
+ resolution: {integrity: sha512-2kmm0rw+WalRWrSC5pW0TXRz8Wyuh57XmOZEUOhPOflw4o8Dno+PcaWbdOZ/TLkTgTt3X1n7r1/c1ALtaLta8g==}
dependencies:
- '@mdit-vue/types': 0.12.0
- '@vue/shared': 3.4.21
+ '@mdit-vue/types': 2.0.0
dev: true
- /@vuepress/shared@2.0.0-beta.62:
- resolution: {integrity: sha512-+OH8WzFz7+IUv+WbcBbCiy3ZTWZ4a2uVRd4GYHWkTE4Ux5V2Sx3KwY17POIGpn/PfMqNHHtjpDH6rO7qmaD+pg==}
+ /@vuepress/shared@2.0.0-rc.7:
+ resolution: {integrity: sha512-zNsYzAW5tuENb4vML0pK/61W3EscyOcn5JVPC+c6AwvsYWyAigZaMSu9ycGAptjDwzdYSi3gd33N9Q9T7pG77Q==}
dependencies:
- '@mdit-vue/types': 0.12.0
- '@vue/shared': 3.4.21
+ '@mdit-vue/types': 2.0.0
dev: true
- /@vuepress/shared@2.0.0-rc.2:
- resolution: {integrity: sha512-2kmm0rw+WalRWrSC5pW0TXRz8Wyuh57XmOZEUOhPOflw4o8Dno+PcaWbdOZ/TLkTgTt3X1n7r1/c1ALtaLta8g==}
+ /@vuepress/shared@2.0.0-rc.9:
+ resolution: {integrity: sha512-XfI6CWNv4/Vp9Iew6GJil9RUSy1rM7zGdjwikr0j3Rkh55q3f00w1wud47wE9kxRqsZ0PIvsMget5CxEn5rA/w==}
dependencies:
'@mdit-vue/types': 2.0.0
dev: true
- /@vuepress/theme-default@2.0.0-beta.62(typescript@5.3.3):
- resolution: {integrity: sha512-J6wLH4tevMnn/2y+MrTpZEVDWf5yvikx0S9TIfpcxjR/nN4XD9eSZrMB3Lt8JqTW/lwFze5MVBdTtVafZs4b3g==}
- dependencies:
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-active-header-links': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-back-to-top': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-container': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-external-link-icon': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-git': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-medium-zoom': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-nprogress': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-palette': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-prismjs': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/plugin-theme-data': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/shared': 2.0.0-beta.62
- '@vuepress/utils': 2.0.0-beta.62
- '@vueuse/core': 10.9.0(vue@3.4.21)
- sass: 1.71.1
- sass-loader: 13.3.3(sass@1.71.1)
- vue: 3.4.21(typescript@5.3.3)
- vue-router: 4.3.0(vue@3.4.21)
+ /@vuepress/theme-default@2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-g0knQJpsCVGBRm6iGBMmW0uSlReAA42I9qt6fmt2sRlVjhjAniStTHoZUM4kzRGFSwqqi6BzMdp8RVXolkE/fQ==}
+ peerDependencies:
+ sass-loader: ^14.0.0
+ vuepress: 2.0.0-rc.9
+ peerDependenciesMeta:
+ sass-loader:
+ optional: true
+ dependencies:
+ '@vuepress/helper': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-active-header-links': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-back-to-top': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-container': 2.0.0-rc.25(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-copy-code': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-external-link-icon': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-git': 2.0.0-rc.22(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-links-check': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-medium-zoom': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-nprogress': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-palette': 2.0.0-rc.21(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-prismjs': 2.0.0-rc.21(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-seo': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-sitemap': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vuepress/plugin-theme-data': 2.0.0-rc.26(typescript@5.3.3)(vuepress@2.0.0-rc.9)
+ '@vueuse/core': 10.9.0(vue@3.4.26)
+ sass: 1.76.0
+ vue: 3.4.26(typescript@5.3.3)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- '@vue/composition-api'
- - fibers
- - node-sass
- - sass-embedded
- - supports-color
- typescript
- - webpack
dev: true
- /@vuepress/utils@2.0.0-beta.61:
- resolution: {integrity: sha512-W7g6xjrdyOW5E1V1ouyTm5d4+kgSd4KcM80D7K0NNScrhLIW6gpOggVVOVyTH3q2K1GQhzPlUcUe04ZNSo0ilQ==}
+ /@vuepress/utils@2.0.0-rc.2:
+ resolution: {integrity: sha512-g93yFJKtztpdXm4XyOIQ9QcUrKuvuWizvH3qWDQ5/WKlxa6VqE7nVNPlkudgGUIc7Bl4AGrlHcmgvkwaNoMcfA==}
dependencies:
'@types/debug': 4.1.12
'@types/fs-extra': 11.0.4
'@types/hash-sum': 1.0.2
- '@vuepress/shared': 2.0.0-beta.61
+ '@vuepress/shared': 2.0.0-rc.2
debug: 4.3.4(supports-color@8.1.1)
fs-extra: 11.2.0
- globby: 13.2.2
+ globby: 14.0.1
hash-sum: 2.0.0
- ora: 6.3.1
+ ora: 8.0.1
picocolors: 1.0.0
upath: 2.0.1
transitivePeerDependencies:
- supports-color
dev: true
- /@vuepress/utils@2.0.0-beta.62:
- resolution: {integrity: sha512-2hyGGrN1XCUapsSlckHc7FWkklSPZfqcM5eDYjxyIT9XpQrXKYn8r0CUVcveyFdHF76Tw0KyP57JCxUDTxHxVg==}
+ /@vuepress/utils@2.0.0-rc.7:
+ resolution: {integrity: sha512-47c7T72JwOWH1EgG7f/KwWNpIknd9IC5JmrizGI5IVUM4G16Vyj5oPQuXqLobV47m8JOxPW4dLpsglZGVaKQeg==}
dependencies:
'@types/debug': 4.1.12
'@types/fs-extra': 11.0.4
'@types/hash-sum': 1.0.2
- '@vuepress/shared': 2.0.0-beta.62
+ '@vuepress/shared': 2.0.0-rc.7
debug: 4.3.4(supports-color@8.1.1)
fs-extra: 11.2.0
- globby: 13.2.2
+ globby: 14.0.1
hash-sum: 2.0.0
- ora: 6.3.1
+ ora: 8.0.1
picocolors: 1.0.0
upath: 2.0.1
transitivePeerDependencies:
- supports-color
dev: true
- /@vuepress/utils@2.0.0-rc.2:
- resolution: {integrity: sha512-g93yFJKtztpdXm4XyOIQ9QcUrKuvuWizvH3qWDQ5/WKlxa6VqE7nVNPlkudgGUIc7Bl4AGrlHcmgvkwaNoMcfA==}
+ /@vuepress/utils@2.0.0-rc.9:
+ resolution: {integrity: sha512-qk6Pel4JVKYKxp3bWxyvnwchvx3QaCWc7SqUw7L6qUo/um+0U2U45L0anWoAfckw12RXYhoIEbJ9UZpueiKOPg==}
dependencies:
'@types/debug': 4.1.12
'@types/fs-extra': 11.0.4
'@types/hash-sum': 1.0.2
- '@vuepress/shared': 2.0.0-rc.2
+ '@vuepress/shared': 2.0.0-rc.9
debug: 4.3.4(supports-color@8.1.1)
fs-extra: 11.2.0
globby: 14.0.1
@@ -2494,6 +2945,18 @@ packages:
- vue
dev: true
+ /@vueuse/core@10.9.0(vue@3.4.26):
+ resolution: {integrity: sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==}
+ dependencies:
+ '@types/web-bluetooth': 0.0.20
+ '@vueuse/metadata': 10.9.0
+ '@vueuse/shared': 10.9.0(vue@3.4.26)
+ vue-demi: 0.14.7(vue@3.4.26)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: true
+
/@vueuse/metadata@10.9.0:
resolution: {integrity: sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==}
dev: true
@@ -2507,6 +2970,15 @@ packages:
- vue
dev: true
+ /@vueuse/shared@10.9.0(vue@3.4.26):
+ resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==}
+ dependencies:
+ vue-demi: 0.14.7(vue@3.4.26)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: true
+
/JSONStream@1.3.5:
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
hasBin: true
@@ -2877,19 +3349,19 @@ packages:
/async@3.2.5:
resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
- /autoprefixer@10.4.18(postcss@8.4.35):
- resolution: {integrity: sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==}
+ /autoprefixer@10.4.19(postcss@8.4.38):
+ resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==}
engines: {node: ^10 || ^12 || >=14}
hasBin: true
peerDependencies:
postcss: ^8.1.0
dependencies:
browserslist: 4.23.0
- caniuse-lite: 1.0.30001593
+ caniuse-lite: 1.0.30001614
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.0.0
- postcss: 8.4.35
+ postcss: 8.4.38
postcss-value-parser: 4.2.0
dev: true
@@ -2962,6 +3434,7 @@ packages:
/base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+ dev: false
/benchmark@2.1.4:
resolution: {integrity: sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==}
@@ -2983,14 +3456,6 @@ packages:
readable-stream: 3.6.2
dev: false
- /bl@5.1.0:
- resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==}
- dependencies:
- buffer: 6.0.3
- inherits: 2.0.4
- readable-stream: 3.6.2
- dev: true
-
/bluebird@3.7.2:
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
dev: false
@@ -3078,13 +3543,6 @@ packages:
ieee754: 1.2.1
dev: false
- /buffer@6.0.3:
- resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
- dependencies:
- base64-js: 1.5.1
- ieee754: 1.2.1
- dev: true
-
/builtin-status-codes@3.0.0:
resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==}
dev: false
@@ -3265,6 +3723,10 @@ packages:
resolution: {integrity: sha512-UWM1zlo3cZfkpBysd7AS+z+v007q9G1+fLTUU42rQnY6t2axoogPW/xol6T7juU5EUoOhML4WgBIdG+9yYqAjQ==}
dev: true
+ /caniuse-lite@1.0.30001614:
+ resolution: {integrity: sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==}
+ dev: true
+
/capital-case@1.0.4:
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
dependencies:
@@ -3606,6 +4068,7 @@ packages:
/clone@1.0.4:
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
engines: {node: '>=0.8'}
+ dev: false
/cluster-key-slot@1.1.2:
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
@@ -4179,6 +4642,7 @@ packages:
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
dependencies:
clone: 1.0.4
+ dev: false
/defer-to-connect@1.1.3:
resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==}
@@ -4395,11 +4859,6 @@ packages:
strip-ansi: 6.0.1
dev: false
- /entities@3.0.1:
- resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==}
- engines: {node: '>=0.12'}
- dev: true
-
/entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@@ -4495,34 +4954,66 @@ packages:
resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
dev: true
- /esbuild@0.17.19:
- resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
+ /esbuild@0.19.12:
+ resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.19.12
+ '@esbuild/android-arm': 0.19.12
+ '@esbuild/android-arm64': 0.19.12
+ '@esbuild/android-x64': 0.19.12
+ '@esbuild/darwin-arm64': 0.19.12
+ '@esbuild/darwin-x64': 0.19.12
+ '@esbuild/freebsd-arm64': 0.19.12
+ '@esbuild/freebsd-x64': 0.19.12
+ '@esbuild/linux-arm': 0.19.12
+ '@esbuild/linux-arm64': 0.19.12
+ '@esbuild/linux-ia32': 0.19.12
+ '@esbuild/linux-loong64': 0.19.12
+ '@esbuild/linux-mips64el': 0.19.12
+ '@esbuild/linux-ppc64': 0.19.12
+ '@esbuild/linux-riscv64': 0.19.12
+ '@esbuild/linux-s390x': 0.19.12
+ '@esbuild/linux-x64': 0.19.12
+ '@esbuild/netbsd-x64': 0.19.12
+ '@esbuild/openbsd-x64': 0.19.12
+ '@esbuild/sunos-x64': 0.19.12
+ '@esbuild/win32-arm64': 0.19.12
+ '@esbuild/win32-ia32': 0.19.12
+ '@esbuild/win32-x64': 0.19.12
+ dev: true
+
+ /esbuild@0.20.2:
+ resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
optionalDependencies:
- '@esbuild/android-arm': 0.17.19
- '@esbuild/android-arm64': 0.17.19
- '@esbuild/android-x64': 0.17.19
- '@esbuild/darwin-arm64': 0.17.19
- '@esbuild/darwin-x64': 0.17.19
- '@esbuild/freebsd-arm64': 0.17.19
- '@esbuild/freebsd-x64': 0.17.19
- '@esbuild/linux-arm': 0.17.19
- '@esbuild/linux-arm64': 0.17.19
- '@esbuild/linux-ia32': 0.17.19
- '@esbuild/linux-loong64': 0.17.19
- '@esbuild/linux-mips64el': 0.17.19
- '@esbuild/linux-ppc64': 0.17.19
- '@esbuild/linux-riscv64': 0.17.19
- '@esbuild/linux-s390x': 0.17.19
- '@esbuild/linux-x64': 0.17.19
- '@esbuild/netbsd-x64': 0.17.19
- '@esbuild/openbsd-x64': 0.17.19
- '@esbuild/sunos-x64': 0.17.19
- '@esbuild/win32-arm64': 0.17.19
- '@esbuild/win32-ia32': 0.17.19
- '@esbuild/win32-x64': 0.17.19
+ '@esbuild/aix-ppc64': 0.20.2
+ '@esbuild/android-arm': 0.20.2
+ '@esbuild/android-arm64': 0.20.2
+ '@esbuild/android-x64': 0.20.2
+ '@esbuild/darwin-arm64': 0.20.2
+ '@esbuild/darwin-x64': 0.20.2
+ '@esbuild/freebsd-arm64': 0.20.2
+ '@esbuild/freebsd-x64': 0.20.2
+ '@esbuild/linux-arm': 0.20.2
+ '@esbuild/linux-arm64': 0.20.2
+ '@esbuild/linux-ia32': 0.20.2
+ '@esbuild/linux-loong64': 0.20.2
+ '@esbuild/linux-mips64el': 0.20.2
+ '@esbuild/linux-ppc64': 0.20.2
+ '@esbuild/linux-riscv64': 0.20.2
+ '@esbuild/linux-s390x': 0.20.2
+ '@esbuild/linux-x64': 0.20.2
+ '@esbuild/netbsd-x64': 0.20.2
+ '@esbuild/openbsd-x64': 0.20.2
+ '@esbuild/sunos-x64': 0.20.2
+ '@esbuild/win32-arm64': 0.20.2
+ '@esbuild/win32-ia32': 0.20.2
+ '@esbuild/win32-x64': 0.20.2
dev: true
/escalade@3.1.2:
@@ -4821,8 +5312,8 @@ packages:
tmp: 0.0.33
dev: true
- /fflate@0.7.4:
- resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==}
+ /fflate@0.8.2:
+ resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
dev: true
/figures@1.7.0:
@@ -5567,6 +6058,7 @@ packages:
/ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+ dev: false
/ignore-by-default@2.1.0:
resolution: {integrity: sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==}
@@ -6387,12 +6879,6 @@ packages:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true
- /linkify-it@4.0.1:
- resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==}
- dependencies:
- uc.micro: 1.0.6
- dev: true
-
/linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
dependencies:
@@ -6643,14 +7129,6 @@ packages:
chalk: 4.1.2
is-unicode-supported: 0.1.0
- /log-symbols@5.1.0:
- resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==}
- engines: {node: '>=12'}
- dependencies:
- chalk: 5.3.0
- is-unicode-supported: 1.3.0
- dev: true
-
/log-symbols@6.0.0:
resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
engines: {node: '>=18'}
@@ -6738,6 +7216,12 @@ packages:
dependencies:
yallist: 4.0.0
+ /magic-string@0.30.10:
+ resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
/magic-string@0.30.8:
resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
engines: {node: '>=12'}
@@ -6782,51 +7266,48 @@ packages:
resolution: {integrity: sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==}
dev: false
- /markdown-it-anchor@8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.2):
+ /markdown-it-anchor@8.6.7(@types/markdown-it@13.0.7)(markdown-it@14.0.0):
resolution: {integrity: sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==}
peerDependencies:
'@types/markdown-it': '*'
markdown-it: '*'
dependencies:
- '@types/markdown-it': 12.2.3
- markdown-it: 13.0.2
+ '@types/markdown-it': 13.0.7
+ markdown-it: 14.0.0
dev: true
- /markdown-it-anchor@8.6.7(@types/markdown-it@13.0.7)(markdown-it@14.0.0):
+ /markdown-it-anchor@8.6.7(@types/markdown-it@13.0.7)(markdown-it@14.1.0):
resolution: {integrity: sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==}
peerDependencies:
'@types/markdown-it': '*'
markdown-it: '*'
dependencies:
'@types/markdown-it': 13.0.7
- markdown-it: 14.0.0
- dev: true
-
- /markdown-it-container@3.0.0:
- resolution: {integrity: sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==}
+ markdown-it: 14.1.0
dev: true
- /markdown-it-emoji@2.0.2:
- resolution: {integrity: sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ==}
+ /markdown-it-container@4.0.0:
+ resolution: {integrity: sha512-HaNccxUH0l7BNGYbFbjmGpf5aLHAMTinqRZQAEQbMr2cdD3z91Q6kIo1oUn1CQndkT03jat6ckrdRYuwwqLlQw==}
dev: true
/markdown-it-emoji@3.0.0:
resolution: {integrity: sha512-+rUD93bXHubA4arpEZO3q80so0qgoFJEKRkRbjKX8RTdca89v2kfyF+xR3i2sQTwql9tpPZPOQN5B+PunspXRg==}
dev: true
- /markdown-it@13.0.2:
- resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==}
+ /markdown-it@14.0.0:
+ resolution: {integrity: sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==}
hasBin: true
dependencies:
argparse: 2.0.1
- entities: 3.0.1
- linkify-it: 4.0.1
- mdurl: 1.0.1
- uc.micro: 1.0.6
+ entities: 4.5.0
+ linkify-it: 5.0.0
+ mdurl: 2.0.0
+ punycode.js: 2.3.1
+ uc.micro: 2.1.0
dev: true
- /markdown-it@14.0.0:
- resolution: {integrity: sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==}
+ /markdown-it@14.1.0:
+ resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true
dependencies:
argparse: 2.0.1
@@ -6851,10 +7332,6 @@ packages:
blueimp-md5: 2.19.0
dev: true
- /mdurl@1.0.1:
- resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
- dev: true
-
/mdurl@2.0.0:
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
dev: true
@@ -7599,21 +8076,6 @@ packages:
wcwidth: 1.0.1
dev: false
- /ora@6.3.1:
- resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- dependencies:
- chalk: 5.3.0
- cli-cursor: 4.0.0
- cli-spinners: 2.9.2
- is-interactive: 2.0.0
- is-unicode-supported: 1.3.0
- log-symbols: 5.1.0
- stdin-discarder: 0.1.0
- strip-ansi: 7.1.0
- wcwidth: 1.0.1
- dev: true
-
/ora@8.0.1:
resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==}
engines: {node: '>=18'}
@@ -8077,21 +8539,20 @@ packages:
engines: {node: '>= 0.4'}
dev: true
- /postcss-load-config@4.0.2(postcss@8.4.35)(ts-node@10.9.2):
- resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
- engines: {node: '>= 14'}
+ /postcss-load-config@5.0.3(postcss@8.4.38):
+ resolution: {integrity: sha512-90pBBI5apUVruIEdCxZic93Wm+i9fTrp7TXbgdUCH+/L+2WnfpITSpq5dFU/IPvbv7aNiMlQISpUkAm3fEcvgQ==}
+ engines: {node: '>= 18'}
peerDependencies:
+ jiti: '>=1.21.0'
postcss: '>=8.0.9'
- ts-node: '>=9.0.0'
peerDependenciesMeta:
- postcss:
+ jiti:
optional: true
- ts-node:
+ postcss:
optional: true
dependencies:
lilconfig: 3.1.1
- postcss: 8.4.35
- ts-node: 10.9.2(@types/node@18.19.21)(typescript@5.3.3)
+ postcss: 8.4.38
yaml: 2.4.0
dev: true
@@ -8108,6 +8569,15 @@ packages:
source-map-js: 1.0.2
dev: true
+ /postcss@8.4.38:
+ resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.2.0
+ dev: true
+
/preact@10.19.6:
resolution: {integrity: sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw==}
dev: true
@@ -8500,11 +8970,29 @@ packages:
glob: 9.3.5
dev: false
- /rollup@3.29.4:
- resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==}
- engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+ /rollup@4.17.2:
+ resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ dependencies:
+ '@types/estree': 1.0.5
optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.17.2
+ '@rollup/rollup-android-arm64': 4.17.2
+ '@rollup/rollup-darwin-arm64': 4.17.2
+ '@rollup/rollup-darwin-x64': 4.17.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.17.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.17.2
+ '@rollup/rollup-linux-arm64-gnu': 4.17.2
+ '@rollup/rollup-linux-arm64-musl': 4.17.2
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.17.2
+ '@rollup/rollup-linux-s390x-gnu': 4.17.2
+ '@rollup/rollup-linux-x64-gnu': 4.17.2
+ '@rollup/rollup-linux-x64-musl': 4.17.2
+ '@rollup/rollup-win32-arm64-msvc': 4.17.2
+ '@rollup/rollup-win32-ia32-msvc': 4.17.2
+ '@rollup/rollup-win32-x64-msvc': 4.17.2
fsevents: 2.3.3
dev: true
@@ -8562,31 +9050,18 @@ packages:
/safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
- /sass-loader@13.3.3(sass@1.71.1):
- resolution: {integrity: sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==}
- engines: {node: '>= 14.15.0'}
- peerDependencies:
- fibers: '>= 3.1.0'
- node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
- sass: ^1.3.0
- sass-embedded: '*'
- webpack: ^5.0.0
- peerDependenciesMeta:
- fibers:
- optional: true
- node-sass:
- optional: true
- sass:
- optional: true
- sass-embedded:
- optional: true
+ /sass@1.71.1:
+ resolution: {integrity: sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
dependencies:
- neo-async: 2.6.2
- sass: 1.71.1
+ chokidar: 3.6.0
+ immutable: 4.3.5
+ source-map-js: 1.0.2
dev: true
- /sass@1.71.1:
- resolution: {integrity: sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==}
+ /sass@1.76.0:
+ resolution: {integrity: sha512-nc3LeqvF2FNW5xGF1zxZifdW3ffIz5aBb7I7tSvOoNu7z1RQ6pFt9MBuiPtjgaI62YWrM/txjWlOCFiGtf2xpw==}
engines: {node: '>=14.0.0'}
hasBin: true
dependencies:
@@ -8838,6 +9313,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /source-map-js@1.2.0:
+ resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
/source-map-support@0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
dependencies:
@@ -8926,13 +9406,6 @@ packages:
engines: {node: '>= 0.6'}
dev: false
- /stdin-discarder@0.1.0:
- resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- dependencies:
- bl: 5.1.0
- dev: true
-
/stdin-discarder@0.2.2:
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
engines: {node: '>=18'}
@@ -9546,10 +10019,6 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
- /uc.micro@1.0.6:
- resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
- dev: true
-
/uc.micro@2.1.0:
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
dev: true
@@ -9767,13 +10236,14 @@ packages:
builtins: 5.0.1
dev: false
- /vite@4.3.9(@types/node@18.19.21)(sass@1.71.1):
- resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==}
- engines: {node: ^14.18.0 || >=16.0.0}
+ /vite@5.0.13(@types/node@18.19.21)(sass@1.71.1):
+ resolution: {integrity: sha512-/9ovhv2M2dGTuA+dY93B9trfyWMDRQw2jdVBhHNP6wr0oF34wG2i/N55801iZIpgUpnHDm4F/FabGQLyc+eOgg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
- '@types/node': '>= 14'
+ '@types/node': ^18.0.0 || >=20.0.0
less: '*'
+ lightningcss: ^1.21.0
sass: '*'
stylus: '*'
sugarss: '*'
@@ -9783,6 +10253,8 @@ packages:
optional: true
less:
optional: true
+ lightningcss:
+ optional: true
sass:
optional: true
stylus:
@@ -9793,9 +10265,9 @@ packages:
optional: true
dependencies:
'@types/node': 18.19.21
- esbuild: 0.17.19
- postcss: 8.4.35
- rollup: 3.29.4
+ esbuild: 0.19.12
+ postcss: 8.4.38
+ rollup: 4.17.2
sass: 1.71.1
optionalDependencies:
fsevents: 2.3.3
@@ -9816,6 +10288,21 @@ packages:
vue: 3.4.21(typescript@5.3.3)
dev: true
+ /vue-demi@0.14.7(vue@3.4.26):
+ resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ dependencies:
+ vue: 3.4.26(typescript@5.3.3)
+ dev: true
+
/vue-router@4.3.0(vue@3.4.21):
resolution: {integrity: sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ==}
peerDependencies:
@@ -9825,6 +10312,15 @@ packages:
vue: 3.4.21(typescript@5.3.3)
dev: true
+ /vue-router@4.3.0(vue@3.4.26):
+ resolution: {integrity: sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ==}
+ peerDependencies:
+ vue: ^3.2.0
+ dependencies:
+ '@vue/devtools-api': 6.6.1
+ vue: 3.4.26(typescript@5.3.3)
+ dev: true
+
/vue@3.4.21(typescript@5.3.3):
resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==}
peerDependencies:
@@ -9841,29 +10337,34 @@ packages:
typescript: 5.3.3
dev: true
- /vuepress-plugin-sitemap2@2.0.0-beta.205(typescript@5.3.3)(vuepress@2.0.0-beta.62):
- resolution: {integrity: sha512-suYQEYPnH0Ytqytq1oK0YTeh4ZC24FwPCGgMefg/jjXLa5fTSWVvOHzGWqfNCmnYzEiU52Txgju/RAbIFHmeHA==}
- engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'}
+ /vue@3.4.26(typescript@5.3.3):
+ resolution: {integrity: sha512-bUIq/p+VB+0xrJubaemrfhk1/FiW9iX+pDV+62I/XJ6EkspAO9/DXEjbDFoe8pIfOZBqfk45i9BMc41ptP/uRg==}
peerDependencies:
- vuepress: 2.0.0-beta.61
- vuepress-vite: 2.0.0-beta.61
- vuepress-webpack: 2.0.0-beta.61
+ typescript: '*'
peerDependenciesMeta:
- vuepress:
- optional: true
- vuepress-vite:
- optional: true
- vuepress-webpack:
+ typescript:
optional: true
dependencies:
- '@vuepress/shared': 2.0.0-beta.61
- '@vuepress/utils': 2.0.0-beta.61
+ '@vue/compiler-dom': 3.4.26
+ '@vue/compiler-sfc': 3.4.26
+ '@vue/runtime-dom': 3.4.26
+ '@vue/server-renderer': 3.4.26(vue@3.4.26)
+ '@vue/shared': 3.4.26
+ typescript: 5.3.3
+ dev: true
+
+ /vuepress-plugin-sitemap2@2.0.0-rc.16(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-7hGlrwACCSZijuGFyc4Yh+3IXh8f9dFK0iekjlMbC2TxNbDHHmsLHnsGfEmd6H1xsQtaTC1fwXw158jiXwE1fA==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ deprecated: Please use @vuepress/plugin-sitemap@v2 instead
+ peerDependencies:
+ vuepress: 2.0.0-rc.2
+ dependencies:
sitemap: 7.1.1
- vuepress: 2.0.0-beta.62(@types/node@18.19.21)(@vuepress/client@2.0.0-beta.62)(sass@1.71.1)(ts-node@10.9.2)(typescript@5.3.3)(vue@3.4.21)
- vuepress-shared: 2.0.0-beta.205(typescript@5.3.3)(vuepress@2.0.0-beta.62)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
+ vuepress-shared: 2.0.0-rc.16(typescript@5.3.3)(vuepress@2.0.0-rc.9)
transitivePeerDependencies:
- '@vue/composition-api'
- - supports-color
- typescript
dev: true
@@ -9880,101 +10381,60 @@ packages:
- typescript
dev: true
- /vuepress-shared@2.0.0-beta.205(typescript@5.3.3)(vuepress@2.0.0-beta.62):
- resolution: {integrity: sha512-DcfAsWZg9NstiYmagMeLEqqRMYAgSCA3GJtWRN3vVCZDUWRG7j64xKSsO3HlbGOtNST74O3HHEqoGu2pyRGQ1Q==}
- engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'}
+ /vuepress-shared@2.0.0-rc.16(typescript@5.3.3)(vuepress@2.0.0-rc.9):
+ resolution: {integrity: sha512-gsiqo9tr6dHCVQTPw1d+oiJyNGzc6nmrGRBWkLb3ZxD15q1k/iv2flBwPdb1RasU827oMgZ2DuOzbHcGjRKjSA==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
peerDependencies:
- vuepress: 2.0.0-beta.61
- vuepress-vite: 2.0.0-beta.61
- vuepress-webpack: 2.0.0-beta.61
- peerDependenciesMeta:
- vuepress:
- optional: true
- vuepress-vite:
- optional: true
- vuepress-webpack:
- optional: true
+ vuepress: 2.0.0-rc.2
dependencies:
- '@vuepress/client': 2.0.0-beta.61(typescript@5.3.3)
- '@vuepress/shared': 2.0.0-beta.61
- '@vuepress/utils': 2.0.0-beta.61
- '@vueuse/core': 10.9.0(vue@3.4.21)
+ '@vueuse/core': 10.9.0(vue@3.4.26)
cheerio: 1.0.0-rc.12
dayjs: 1.11.10
- execa: 7.2.0
- fflate: 0.7.4
+ execa: 8.0.1
+ fflate: 0.8.2
gray-matter: 4.0.3
semver: 7.6.0
striptags: 3.2.0
- vue: 3.4.21(typescript@5.3.3)
- vue-router: 4.3.0(vue@3.4.21)
- vuepress: 2.0.0-beta.62(@types/node@18.19.21)(@vuepress/client@2.0.0-beta.62)(sass@1.71.1)(ts-node@10.9.2)(typescript@5.3.3)(vue@3.4.21)
+ vue: 3.4.26(typescript@5.3.3)
+ vue-router: 4.3.0(vue@3.4.26)
+ vuepress: 2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21)
transitivePeerDependencies:
- '@vue/composition-api'
- - supports-color
- typescript
dev: true
- /vuepress-vite@2.0.0-beta.62(@types/node@18.19.21)(@vuepress/client@2.0.0-beta.62)(sass@1.71.1)(ts-node@10.9.2)(typescript@5.3.3)(vue@3.4.21):
- resolution: {integrity: sha512-C93T5ZCFMnbdXkZ/R/romtwPPP2zjPN38YZhrM6w6wWjSMDvrG26IFRwluXy+W84O0Pg7xOwqRom0wvO4kCxmA==}
- engines: {node: '>=16.19.0'}
+ /vuepress@2.0.0-rc.9(@vuepress/bundler-vite@2.0.0-rc.7)(typescript@5.3.3)(vue@3.4.21):
+ resolution: {integrity: sha512-jT1ln2lawdph+vVI6n2JfEUhQIcyc1RQWDdQu9DffhJGywJunFcumnUJudpqd1SNIES2Fz1hVCD6gdrE/rVKOQ==}
+ engines: {node: '>=18.16.0'}
hasBin: true
peerDependencies:
- '@vuepress/client': 2.0.0-beta.62
- vue: ^3.3.1
- dependencies:
- '@vuepress/bundler-vite': 2.0.0-beta.62(@types/node@18.19.21)(sass@1.71.1)(ts-node@10.9.2)(typescript@5.3.3)
- '@vuepress/cli': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/client': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/core': 2.0.0-beta.62(typescript@5.3.3)
- '@vuepress/theme-default': 2.0.0-beta.62(typescript@5.3.3)
- vue: 3.4.21(typescript@5.3.3)
- transitivePeerDependencies:
- - '@types/node'
- - '@vue/composition-api'
- - fibers
- - less
- - node-sass
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - ts-node
- - typescript
- - webpack
- dev: true
-
- /vuepress@2.0.0-beta.62(@types/node@18.19.21)(@vuepress/client@2.0.0-beta.62)(sass@1.71.1)(ts-node@10.9.2)(typescript@5.3.3)(vue@3.4.21):
- resolution: {integrity: sha512-kwoC7RA6PGetWSU/NwV6dJ3VItg+R+K2IpAJ4bKsnRueIqGpDZwPr423nRK0VwDhh2sN7lUn6LoyaybPwWrGZg==}
- engines: {node: '>=16.19.0'}
- hasBin: true
+ '@vuepress/bundler-vite': 2.0.0-rc.9
+ '@vuepress/bundler-webpack': 2.0.0-rc.9
+ vue: ^3.4.0
+ peerDependenciesMeta:
+ '@vuepress/bundler-vite':
+ optional: true
+ '@vuepress/bundler-webpack':
+ optional: true
dependencies:
- vuepress-vite: 2.0.0-beta.62(@types/node@18.19.21)(@vuepress/client@2.0.0-beta.62)(sass@1.71.1)(ts-node@10.9.2)(typescript@5.3.3)(vue@3.4.21)
+ '@vuepress/bundler-vite': 2.0.0-rc.7(@types/node@18.19.21)(sass@1.71.1)(typescript@5.3.3)
+ '@vuepress/cli': 2.0.0-rc.9(typescript@5.3.3)
+ '@vuepress/client': 2.0.0-rc.9(typescript@5.3.3)
+ '@vuepress/core': 2.0.0-rc.9(typescript@5.3.3)
+ '@vuepress/markdown': 2.0.0-rc.9
+ '@vuepress/shared': 2.0.0-rc.9
+ '@vuepress/utils': 2.0.0-rc.9
+ vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- - '@types/node'
- - '@vue/composition-api'
- - '@vuepress/client'
- - fibers
- - less
- - node-sass
- - sass
- - sass-embedded
- - stylus
- - sugarss
- supports-color
- - terser
- - ts-node
- typescript
- - vue
- - webpack
dev: true
/wcwidth@1.0.1:
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
dependencies:
defaults: 1.0.4
+ dev: false
/well-known-symbols@2.0.0:
resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==}
diff --git a/src/generator/__tests__/__snapshots__/json-template.test.ts.md b/src/generator/__tests__/__snapshots__/json-template.test.ts.md
new file mode 100644
index 000000000..79c4efd0a
--- /dev/null
+++ b/src/generator/__tests__/__snapshots__/json-template.test.ts.md
@@ -0,0 +1,15 @@
+# Snapshot report for `src/generator/__tests__/json-template.test.ts`
+
+The actual snapshot is saved in `json-template.test.ts.snap`.
+
+Generated by [AVA](https://avajs.dev).
+
+## render
+
+> Snapshot 1
+
+ `{␊
+ "foo": "foo",␊
+ "bar": "bar",␊
+ "outbounds": "new-value"␊
+ }`
diff --git a/src/generator/__tests__/__snapshots__/json-template.test.ts.snap b/src/generator/__tests__/__snapshots__/json-template.test.ts.snap
new file mode 100644
index 000000000..b86ed8d3d
Binary files /dev/null and b/src/generator/__tests__/__snapshots__/json-template.test.ts.snap differ
diff --git a/src/generator/__tests__/json-template.test.ts b/src/generator/__tests__/json-template.test.ts
new file mode 100644
index 000000000..357380888
--- /dev/null
+++ b/src/generator/__tests__/json-template.test.ts
@@ -0,0 +1,207 @@
+import test from 'ava'
+import sinon from 'sinon'
+import fs from 'fs-extra'
+
+import {
+ extendOutbounds,
+ createExtendFunction,
+ combineExtendFunctions,
+ render,
+} from '../json-template'
+
+test.beforeEach(() => {
+ sinon.restore()
+})
+
+test('extendOutbounds - extend string', (t) => {
+ const extend = extendOutbounds('new-value')
+
+ t.deepEqual(
+ extend({
+ foo: 'foo',
+ }),
+ {
+ foo: 'foo',
+ outbounds: 'new-value',
+ },
+ )
+})
+
+test('extendOutbounds - extend object', (t) => {
+ const extend = extendOutbounds({
+ bar: 'bar',
+ })
+
+ t.deepEqual(
+ extend({
+ foo: 'foo',
+ }),
+ {
+ foo: 'foo',
+ outbounds: {
+ bar: 'bar',
+ },
+ },
+ )
+})
+
+test('extendOutbounds - extend array', (t) => {
+ const extendString = extendOutbounds('new-value')
+ t.deepEqual(
+ extendString({
+ foo: 'foo',
+ outbounds: ['old-value'],
+ }),
+ {
+ foo: 'foo',
+ outbounds: ['old-value', 'new-value'],
+ },
+ )
+
+ const extendObject = extendOutbounds({
+ bar: 'bar',
+ })
+ t.deepEqual(
+ extendObject({
+ outbounds: [
+ {
+ foo: 'foo',
+ },
+ ],
+ }),
+ {
+ outbounds: [
+ {
+ foo: 'foo',
+ },
+ {
+ bar: 'bar',
+ },
+ ],
+ },
+ )
+
+ const extendArray = extendOutbounds(['new-value1', 'new-value2'])
+
+ t.deepEqual(extendArray({ outbounds: ['old-value'] }), {
+ outbounds: ['old-value', 'new-value1', 'new-value2'],
+ })
+})
+
+test('extendOutbounds - extend function that returns object', (t) => {
+ const spy = sinon.spy(() => {
+ t.pass()
+ return 'something'
+ })
+ const extend = extendOutbounds(({ getSomething }) => {
+ return {
+ bar: getSomething(),
+ }
+ })
+
+ t.deepEqual(
+ extend(
+ {
+ foo: 'foo',
+ },
+ {
+ getSomething: spy,
+ },
+ ),
+ {
+ foo: 'foo',
+ outbounds: {
+ bar: 'something',
+ },
+ },
+ )
+ t.is(spy.calledOnce, true)
+})
+
+test('createExtendFunction - deep extend', (t) => {
+ const extendFunction = createExtendFunction('foo.bar')
+ const extend = extendFunction({
+ bar: 'bar',
+ })
+
+ t.deepEqual(
+ extend({
+ foo: {
+ baz: 'baz',
+ },
+ }),
+ {
+ foo: {
+ baz: 'baz',
+ bar: {
+ bar: 'bar',
+ },
+ },
+ },
+ )
+})
+
+test('createExtendFunction - deep extend array', (t) => {
+ const extendFunction = createExtendFunction('foo[0]')
+ const extend = extendFunction({
+ bar: 'bar',
+ })
+
+ t.deepEqual(
+ extend({
+ foo: [
+ {
+ baz: 'baz',
+ },
+ ],
+ }),
+ {
+ foo: [
+ {
+ bar: 'bar',
+ },
+ ],
+ },
+ )
+})
+
+test('combineExtendFunctions', (t) => {
+ const extend1 = createExtendFunction('foo')({ bar: 'bar' })
+ const extend2 = createExtendFunction('baz')({ qux: 'qux' })
+
+ const combined = combineExtendFunctions(extend1, extend2)
+
+ t.deepEqual(
+ combined({
+ original: 'original',
+ }),
+ {
+ original: 'original',
+ foo: {
+ bar: 'bar',
+ },
+ baz: {
+ qux: 'qux',
+ },
+ },
+ )
+})
+
+test('render', (t) => {
+ sinon.stub(fs, 'readJsonSync').returns({
+ foo: 'foo',
+ bar: 'bar',
+ })
+
+ const result = render(
+ 'templateDir',
+ 'fileName',
+ extendOutbounds('new-value'),
+ { baz: 'baz' },
+ )
+
+ t.snapshot(result)
+ t.true(
+ (fs.readJsonSync as sinon.SinonStub).calledOnceWith('templateDir/fileName'),
+ )
+})
diff --git a/src/generator/artifact.ts b/src/generator/artifact.ts
index 76adf1aca..0cec6f0c2 100644
--- a/src/generator/artifact.ts
+++ b/src/generator/artifact.ts
@@ -14,6 +14,7 @@ import {
} from '../provider'
import {
ArtifactConfig,
+ ArtifactConfigInput,
CommandConfig,
NodeTypeEnum,
PossibleNodeConfigType,
@@ -47,11 +48,15 @@ import {
toBase64,
toUrlSafeBase64,
getNetworkConcurrency,
+ getSingboxNodeNames,
+ getSingboxNodes,
} from '../utils'
import { resolveDomain } from '../utils/dns'
import { internalFilters, validateFilter } from '../filters'
import { prependFlag, removeFlag } from '../utils/flag'
+import { ArtifactValidator } from '../validators'
import { loadLocalSnippet } from './template'
+import { render as renderJSON } from './json-template'
export interface ArtifactOptions {
readonly remoteSnippetList?: ReadonlyArray
@@ -62,6 +67,7 @@ export type ExtendableRenderContext = Record
export class Artifact extends EventEmitter {
public initProgress = 0
+ public artifact: ArtifactConfig
public providerNameList: ReadonlyArray
public nodeConfigListMap: Map> =
@@ -78,13 +84,15 @@ export class Artifact extends EventEmitter {
constructor(
public surgioConfig: CommandConfig,
- public artifact: ArtifactConfig,
+ artifactConfig: ArtifactConfigInput,
private options: ArtifactOptions = {},
) {
super()
- const mainProviderName = artifact.provider
- const combineProviders = artifact.combineProviders || []
+ this.artifact = ArtifactValidator.parse(artifactConfig)
+
+ const mainProviderName = this.artifact.provider
+ const combineProviders = this.artifact.combineProviders || []
this.providerNameList = [mainProviderName].concat(combineProviders)
}
@@ -129,6 +137,8 @@ export class Artifact extends EventEmitter {
getNodeNames,
getClashNodes,
getClashNodeNames,
+ getSingboxNodes,
+ getSingboxNodeNames,
getSurgeNodes,
getSurgeNodeNames,
getSurgeWireguardNodes,
@@ -221,17 +231,31 @@ export class Artifact extends EventEmitter {
throw new Error('没有可用的 Nunjucks 环境')
}
+ if (
+ this.artifact.templateType === 'json' &&
+ !this.artifact.extendTemplate
+ ) {
+ throw new Error('JSON 模板需要提供 extendTemplate 函数')
+ }
+
const renderContext = this.getRenderContext(extendRenderContext)
- const { templateString, template } = this.artifact
+ const { templateString, template, templateType } = this.artifact
const result = templateString
? targetTemplateEngine.renderString(templateString, {
templateEngine: targetTemplateEngine,
...renderContext,
})
- : targetTemplateEngine.render(`${template}.tpl`, {
+ : templateType === 'default'
+ ? targetTemplateEngine.render(`${template}.tpl`, {
templateEngine: targetTemplateEngine,
...renderContext,
})
+ : renderJSON(
+ this.surgioConfig.templateDir,
+ `${template}.json`,
+ this.artifact.extendTemplate!,
+ renderContext,
+ )
this.emit('renderArtifact', { artifact: this.artifact, result })
@@ -437,7 +461,7 @@ export class Artifact extends EventEmitter {
nodeConfig.underlyingProxy = provider.config.underlyingProxy
}
- // check whether the hostname resolves in case of blocking clash's node heurestic
+ // Check whether the hostname resolves in case of blocking clash's node heurestic
if (
config?.checkHostname &&
'hostname' in nodeConfig &&
diff --git a/src/generator/index.ts b/src/generator/index.ts
index 0c650eec0..cc603747e 100644
--- a/src/generator/index.ts
+++ b/src/generator/index.ts
@@ -1,2 +1,7 @@
export * from './artifact'
export * from './template'
+export {
+ extendOutbounds,
+ createExtendFunction,
+ combineExtendFunctions,
+} from './json-template'
diff --git a/src/generator/json-template.ts b/src/generator/json-template.ts
new file mode 100644
index 000000000..85f1d52b5
--- /dev/null
+++ b/src/generator/json-template.ts
@@ -0,0 +1,90 @@
+import { JsonObject } from 'type-fest'
+import _ from 'lodash'
+import fs from 'fs-extra'
+import { join } from 'path'
+
+type ExtendContext = Record
+
+type PremitiveValue = string | number | boolean
+type ExtendValue =
+ | JsonObject[]
+ | JsonObject
+ | PremitiveValue[]
+ | PremitiveValue
+ | ((
+ extendContext: ExtendContext,
+ ) => JsonObject[] | JsonObject | PremitiveValue[] | PremitiveValue)
+
+type ExtendFunction = (
+ extendValue: ExtendValue,
+) => (jsonInput: JsonObject, extendContext?: ExtendContext) => JsonObject
+
+export const createExtendFunction = (extendKey: string) => {
+ const extendFunction: ExtendFunction = (extendValue) => {
+ return (jsonInput, extendContext = {}) => {
+ const jsonInputCopy = _.cloneDeep(jsonInput)
+ const isExist = _.get(jsonInputCopy, extendKey)
+ const extendValueIsFunction = _.isFunction(extendValue)
+ const valueToExtend = extendValueIsFunction
+ ? extendValue(extendContext)
+ : extendValue
+
+ if (isExist) {
+ if (_.isArray(isExist)) {
+ if (_.isArray(valueToExtend)) {
+ _.set(jsonInputCopy, extendKey, [...isExist, ...valueToExtend])
+ } else {
+ _.set(jsonInputCopy, extendKey, [...isExist, valueToExtend])
+ }
+ } else {
+ _.set(jsonInputCopy, extendKey, valueToExtend)
+ }
+ } else {
+ _.set(jsonInputCopy, extendKey, valueToExtend)
+ }
+
+ return jsonInputCopy
+ }
+ }
+
+ return extendFunction
+}
+
+export const extendOutbounds = createExtendFunction('outbounds')
+
+export const combineExtendFunctions = (
+ ...args: ReturnType[]
+): ReturnType => {
+ return (jsonInput, extendContext = {}) => {
+ return args.reduce((acc, extend) => extend(acc, extendContext), jsonInput)
+ }
+}
+
+export const render = (
+ templateDir: string,
+ fileName: string,
+ extend: (...args: any[]) => any,
+ extendContext: ExtendContext,
+): string => {
+ const templatePath = join(templateDir, fileName)
+ const jsonInput = fs.readJsonSync(templatePath)
+
+ try {
+ const jsonOutput = (extend as ReturnType)(
+ jsonInput,
+ extendContext,
+ )
+
+ return JSON.stringify(jsonOutput, null, 2)
+ } catch (error) {
+ // istanbul ignore next
+ if (error instanceof Error) {
+ throw new Error(
+ `Error when rendering JSON template ${fileName}: ${error.message}`,
+ )
+ }
+
+ // istanbul ignore next
+ throw new Error(`Error when rendering JSON template ${fileName}`)
+ }
+}
diff --git a/src/index.ts b/src/index.ts
index 050375984..fe46ba3fc 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -18,6 +18,7 @@ export type { CommandConfigBeforeNormalize as SurgioConfig } from './types'
export * from './configurables'
export { default as httpClient } from './utils/http-client'
export { unifiedCache as cache } from './utils/cache'
+export { createExtendFunction, extendOutbounds } from './generator'
const { internalFilters, ...filtersUtils } = filters
diff --git a/src/types.ts b/src/types.ts
index f8b34ea50..095461ad1 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -50,9 +50,11 @@ export enum SupportProviderEnum {
Trojan = 'trojan',
}
-export type CommandConfigBeforeNormalize = z.infer
+export type CommandConfigBeforeNormalize = z.input
-export type CommandConfig = CommandConfigBeforeNormalize & {
+export type CommandConfigAfterNormalize = z.infer
+
+export type CommandConfig = CommandConfigAfterNormalize & {
publicUrl: string
output: string
urlBase: string
@@ -70,6 +72,8 @@ export interface RemoteSnippet extends RemoteSnippetConfig {
export type ArtifactConfig = z.infer
+export type ArtifactConfigInput = z.input
+
export type ProviderConfig = z.infer
export interface BlackSSLProviderConfig extends ProviderConfig {
diff --git a/src/utils/__tests__/singbox.test.ts b/src/utils/__tests__/singbox.test.ts
new file mode 100644
index 000000000..570e45158
--- /dev/null
+++ b/src/utils/__tests__/singbox.test.ts
@@ -0,0 +1,1029 @@
+import test from 'ava'
+
+import { NodeTypeEnum, PossibleNodeConfigType } from '../../types'
+import * as singbox from '../singbox'
+
+const nodeList: ReadonlyArray = [
+ {
+ nodeName: 'disabled',
+ type: NodeTypeEnum.Shadowsocks,
+ enable: false,
+ hostname: 'example.com',
+ port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ },
+ {
+ nodeName: 'ss',
+ type: NodeTypeEnum.Shadowsocks,
+ hostname: 'example.com',
+ port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ },
+ {
+ nodeName: 'ss.complex',
+ type: NodeTypeEnum.Shadowsocks,
+ hostname: 'example.com',
+ port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ obfs: 'http',
+ obfsHost: 'example.com',
+ obfsUri: '/obfs',
+ skipCertVerify: true,
+ wsHeaders: {
+ foo: 'bar',
+ },
+ tls13: true,
+ mux: true,
+ multiplex: {
+ protocol: 'smux',
+ maxConnections: 2,
+ minStreams: 1,
+ maxStreams: 0,
+ padding: true,
+ brutal: {
+ upMbps: 100,
+ downMbps: 100,
+ },
+ },
+ tfo: true,
+ mptcp: true,
+ shadowTls: {
+ version: 3,
+ password: 'password',
+ sni: 'example.com',
+ },
+ underlyingProxy: 'vmess.ws',
+ },
+ {
+ nodeName: 'ss.tls',
+ type: NodeTypeEnum.Shadowsocks,
+ hostname: 'example.com',
+ port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ obfs: 'tls',
+ obfsHost: 'example.com',
+ },
+ {
+ nodeName: 'ss.http',
+ type: NodeTypeEnum.Shadowsocks,
+ hostname: 'example.com',
+ port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ obfs: 'http',
+ obfsHost: 'example.com',
+ },
+ {
+ nodeName: 'ss.ws',
+ type: NodeTypeEnum.Shadowsocks,
+ hostname: 'example.com',
+ port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ obfs: 'ws',
+ obfsHost: 'example.com',
+ obfsUri: '/obfs',
+ wsHeaders: {
+ foo: 'bar',
+ },
+ mux: false,
+ },
+ {
+ nodeName: 'ss.wss',
+ type: NodeTypeEnum.Shadowsocks,
+ hostname: 'example.com',
+ port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ obfs: 'wss',
+ obfsHost: 'example.com',
+ obfsUri: '/obfs',
+ wsHeaders: {
+ foo: 'bar',
+ },
+ mux: true,
+ },
+ {
+ nodeName: 'ss.quic',
+ type: NodeTypeEnum.Shadowsocks,
+ hostname: 'example.com',
+ port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ obfs: 'quic',
+ obfsHost: 'example.com',
+ obfsUri: '/obfs',
+ wsHeaders: {
+ foo: 'bar',
+ },
+ mux: true,
+ },
+ {
+ nodeName: 'vmess.tcpNotSupported',
+ type: NodeTypeEnum.Vmess,
+ hostname: 'example.com',
+ port: 443,
+ method: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ alterId: 0,
+ network: 'tcp',
+ },
+ {
+ nodeName: 'vmess.h2NotSupported',
+ type: NodeTypeEnum.Vmess,
+ hostname: 'example.com',
+ port: 443,
+ method: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ alterId: 0,
+ network: 'h2',
+ h2Opts: {
+ path: '/foo',
+ host: ['example.com'],
+ },
+ },
+ {
+ nodeName: 'vmess.complex',
+ type: NodeTypeEnum.Vmess,
+ hostname: 'example.com',
+ port: 443,
+ method: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ alterId: 0,
+ network: 'ws',
+ wsOpts: {
+ path: '/foo',
+ headers: {
+ Host: 'example.com',
+ },
+ },
+ tls: true,
+ sni: 'example.com',
+ tls13: true,
+ skipCertVerify: true,
+ alpn: ['h2', 'http/1.1'],
+ clientFingerprint: 'chrome2',
+ multiplex: {
+ protocol: 'smux',
+ maxConnections: 2,
+ minStreams: 1,
+ maxStreams: 0,
+ padding: true,
+ brutal: {
+ upMbps: 100,
+ downMbps: 100,
+ },
+ },
+ tfo: true,
+ mptcp: true,
+ shadowTls: {
+ version: 3,
+ password: 'password',
+ sni: 'example.com',
+ },
+ underlyingProxy: 'ss',
+ },
+ {
+ nodeName: 'vmess.http',
+ type: NodeTypeEnum.Vmess,
+ hostname: 'example.com',
+ port: 443,
+ method: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ alterId: 0,
+ network: 'http',
+ httpOpts: {
+ path: ['/foo'],
+ headers: {
+ Host: 'example.com',
+ },
+ method: 'POST',
+ },
+ },
+ {
+ nodeName: 'vmess.ws',
+ type: NodeTypeEnum.Vmess,
+ hostname: 'example.com',
+ port: 443,
+ method: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ alterId: 0,
+ network: 'ws',
+ wsOpts: {
+ path: '/foo',
+ headers: {
+ Host: 'example.com',
+ },
+ },
+ },
+ {
+ nodeName: 'vmess.quic',
+ type: NodeTypeEnum.Vmess,
+ hostname: 'example.com',
+ port: 443,
+ method: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ alterId: 0,
+ network: 'quic',
+ },
+ {
+ nodeName: 'vmess.grpc',
+ type: NodeTypeEnum.Vmess,
+ hostname: 'example.com',
+ port: 443,
+ method: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ alterId: 0,
+ network: 'grpc',
+ grpcOpts: {
+ serviceName: 'example',
+ },
+ },
+ {
+ nodeName: 'vmess.httpupgrade',
+ type: NodeTypeEnum.Vmess,
+ hostname: 'example.com',
+ port: 443,
+ method: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ alterId: 0,
+ network: 'httpupgrade',
+ httpUpgradeOpts: {
+ path: '/foo',
+ host: 'example.com',
+ headers: {
+ Host: 'example.com',
+ },
+ },
+ },
+ {
+ nodeName: 'vless.tcpNotSupported',
+ type: NodeTypeEnum.Vless,
+ hostname: 'example.com',
+ port: 443,
+ method: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ realityOpts: {
+ publicKey: 'publicKey',
+ shortId: 'shortId',
+ },
+ clientFingerprint: 'chrome2',
+ network: 'tcp',
+ },
+ {
+ nodeName: 'vless.h2NotSupported',
+ type: NodeTypeEnum.Vless,
+ hostname: 'example.com',
+ port: 443,
+ method: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ realityOpts: {
+ publicKey: 'publicKey',
+ shortId: 'shortId',
+ },
+ clientFingerprint: 'chrome2',
+ network: 'h2',
+ h2Opts: {
+ path: '/foo',
+ host: ['example.com'],
+ },
+ },
+ {
+ nodeName: 'vless.complex',
+ type: NodeTypeEnum.Vless,
+ hostname: 'example.com',
+ port: 443,
+ method: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ realityOpts: {
+ publicKey: 'publicKey',
+ shortId: 'shortId',
+ },
+ clientFingerprint: 'chrome2',
+ network: 'ws',
+ wsOpts: {
+ path: '/foo',
+ headers: {
+ Host: 'example.com',
+ },
+ },
+ sni: 'example.com',
+ tls13: true,
+ skipCertVerify: true,
+ alpn: ['h2', 'http/1.1'],
+ multiplex: {
+ protocol: 'smux',
+ maxConnections: 2,
+ minStreams: 1,
+ maxStreams: 0,
+ padding: true,
+ brutal: {
+ upMbps: 100,
+ downMbps: 100,
+ },
+ },
+ tfo: true,
+ mptcp: true,
+ shadowTls: {
+ version: 3,
+ password: 'password',
+ sni: 'example.com',
+ },
+ underlyingProxy: 'ss',
+ },
+ {
+ nodeName: 'vless.http',
+ type: NodeTypeEnum.Vless,
+ hostname: 'example.com',
+ port: 443,
+ method: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ realityOpts: {
+ publicKey: 'publicKey',
+ shortId: 'shortId',
+ },
+ clientFingerprint: 'chrome2',
+ network: 'http',
+ httpOpts: {
+ path: ['/foo'],
+ headers: {
+ Host: 'example.com',
+ },
+ method: 'POST',
+ },
+ },
+ {
+ nodeName: 'vless.ws',
+ type: NodeTypeEnum.Vless,
+ hostname: 'example.com',
+ port: 443,
+ method: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ realityOpts: {
+ publicKey: 'publicKey',
+ shortId: 'shortId',
+ },
+ clientFingerprint: 'chrome2',
+ network: 'ws',
+ wsOpts: {
+ path: '/foo',
+ headers: {
+ Host: 'example.com',
+ },
+ },
+ },
+ {
+ nodeName: 'vless.quic',
+ type: NodeTypeEnum.Vless,
+ hostname: 'example.com',
+ port: 443,
+ method: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ realityOpts: {
+ publicKey: 'publicKey',
+ shortId: 'shortId',
+ },
+ clientFingerprint: 'chrome2',
+ network: 'quic',
+ },
+ {
+ nodeName: 'vless.grpc',
+ type: NodeTypeEnum.Vless,
+ hostname: 'example.com',
+ port: 443,
+ method: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ realityOpts: {
+ publicKey: 'publicKey',
+ shortId: 'shortId',
+ },
+ clientFingerprint: 'chrome2',
+ network: 'grpc',
+ grpcOpts: {
+ serviceName: 'example',
+ },
+ },
+ {
+ nodeName: 'vless.httpupgrade',
+ type: NodeTypeEnum.Vless,
+ hostname: 'example.com',
+ port: 443,
+ method: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ realityOpts: {
+ publicKey: 'publicKey',
+ shortId: 'shortId',
+ },
+ clientFingerprint: 'chrome2',
+ network: 'httpupgrade',
+ httpUpgradeOpts: {
+ path: '/foo',
+ host: 'example.com',
+ headers: {
+ Host: 'example.com',
+ },
+ },
+ },
+ {
+ nodeName: 'http',
+ type: NodeTypeEnum.HTTP,
+ hostname: 'example.com',
+ port: 80,
+ username: 'username',
+ password: 'password',
+ path: '/foo',
+ headers: {
+ Host: 'example.com',
+ },
+ },
+ {
+ nodeName: 'https',
+ type: NodeTypeEnum.HTTPS,
+ hostname: 'example.com',
+ port: 443,
+ username: 'username',
+ password: 'password',
+ path: '/foo',
+ headers: {
+ Host: 'example.com',
+ },
+ sni: 'example.com',
+ tls13: true,
+ skipCertVerify: true,
+ alpn: ['h2', 'http/1.1'],
+ clientFingerprint: 'chrome2',
+ },
+ {
+ nodeName: 'trojan.tcpNotSupported',
+ type: NodeTypeEnum.Trojan,
+ hostname: 'example.com',
+ port: 443,
+ password: 'password',
+ network: 'tcp',
+ },
+ {
+ nodeName: 'trojan.ws',
+ type: NodeTypeEnum.Trojan,
+ hostname: 'example.com',
+ port: 443,
+ password: 'password',
+ network: 'ws',
+ wsPath: '/foo',
+ wsHeaders: {
+ Host: 'example.com',
+ },
+ sni: 'example.com',
+ tls13: true,
+ skipCertVerify: true,
+ alpn: ['h2', 'http/1.1'],
+ clientFingerprint: 'chrome2',
+ multiplex: {
+ protocol: 'smux',
+ maxConnections: 2,
+ minStreams: 1,
+ maxStreams: 0,
+ padding: true,
+ brutal: {
+ upMbps: 100,
+ downMbps: 100,
+ },
+ },
+ },
+ {
+ nodeName: 'socks',
+ type: NodeTypeEnum.Socks5,
+ hostname: 'example.com',
+ port: 8080,
+ username: 'username',
+ password: 'password',
+ udpRelay: true,
+ tls: true,
+ sni: 'example.com',
+ tls13: true,
+ skipCertVerify: true,
+ alpn: ['h2', 'http/1.1'],
+ clientFingerprint: 'chrome2',
+ },
+ {
+ nodeName: 'tuic.versionNotSupported',
+ type: NodeTypeEnum.Tuic,
+ hostname: 'example.com',
+ port: 443,
+ token: 'token',
+ },
+ {
+ nodeName: 'tuic',
+ type: NodeTypeEnum.Tuic,
+ hostname: 'example.com',
+ port: 443,
+ password: 'password',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ version: 5,
+ sni: 'example.com',
+ tls13: true,
+ skipCertVerify: true,
+ alpn: ['h2', 'http/1.1'],
+ clientFingerprint: 'chrome2',
+ },
+ {
+ nodeName: 'hysteria2',
+ type: NodeTypeEnum.Hysteria2,
+ hostname: 'example.com',
+ port: 443,
+ password: 'password',
+ downloadBandwidth: 100,
+ uploadBandwidth: 100,
+ obfs: 'salamander',
+ obfsPassword: 'password',
+ sni: 'example.com',
+ tls13: true,
+ skipCertVerify: true,
+ alpn: ['h2', 'http/1.1'],
+ clientFingerprint: 'chrome2',
+ },
+ {
+ nodeName: 'wg',
+ type: NodeTypeEnum.Wireguard,
+ selfIp: '10.0.0.1',
+ selfIpV6: '2001:db8:85a3::8a2e:370:7334',
+ privateKey: 'privateKey',
+ mtu: 1420,
+ peers: [
+ {
+ publicKey: 'publicKey1',
+ endpoint: 'wg1.example.com:51820',
+ allowedIps: '0.0.0.0/0, ::/0',
+ presharedKey: 'presharedKey1',
+ reservedBits: [1, 2, 3],
+ },
+ {
+ publicKey: 'publicKey2',
+ endpoint: 'wg2.example.com:51820',
+ allowedIps: '0.0.0.0/0, ::/0',
+ presharedKey: 'presharedKey2',
+ reservedBits: [2, 2, 3],
+ },
+ ],
+ },
+]
+
+const expectedNodes: Record[] = [
+ {
+ type: 'shadowsocks',
+ tag: 'ss',
+ server: 'example.com',
+ server_port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ },
+ {
+ type: 'shadowsocks',
+ tag: 'ss.complex',
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ plugin: 'obfs-local',
+ plugin_opts: 'obfs=http;obfs-host=example.com',
+ tls: { enabled: true, insecure: true, min_version: '1.3' },
+ multiplex: {
+ protocol: 'smux',
+ max_connections: 2,
+ min_streams: 1,
+ max_streams: 0,
+ padding: true,
+ enabled: true,
+ brutal: { up_mbps: 100, down_mbps: 100 },
+ },
+ tcp_fast_open: true,
+ tcp_multi_path: true,
+ detour: 'ss.complex-shadowtls',
+ },
+ {
+ type: 'shadowtls',
+ tag: 'ss.complex-shadowtls',
+ server: 'example.com',
+ server_port: 443,
+ version: 3,
+ password: 'password',
+ tls: { enabled: true, server_name: 'example.com' },
+ },
+ {
+ type: 'shadowsocks',
+ tag: 'ss.tls',
+ server: 'example.com',
+ server_port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ plugin: 'obfs-local',
+ plugin_opts: 'obfs=tls;obfs-host=example.com',
+ },
+ {
+ type: 'shadowsocks',
+ tag: 'ss.http',
+ server: 'example.com',
+ server_port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ plugin: 'obfs-local',
+ plugin_opts: 'obfs=http;obfs-host=example.com',
+ },
+ {
+ type: 'shadowsocks',
+ tag: 'ss.ws',
+ server: 'example.com',
+ server_port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ plugin: 'v2ray-plugin',
+ plugin_opts: 'host=example.com;mode=websocket;mux=0;path=/obfs;tls=false',
+ },
+ {
+ type: 'shadowsocks',
+ tag: 'ss.wss',
+ server: 'example.com',
+ server_port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ plugin: 'v2ray-plugin',
+ plugin_opts: 'host=example.com;mode=websocket;path=/obfs;tls=true',
+ },
+ {
+ type: 'shadowsocks',
+ tag: 'ss.quic',
+ server: 'example.com',
+ server_port: 443,
+ method: 'chacha20-ietf-poly1305',
+ password: 'password',
+ plugin: 'v2ray-plugin',
+ plugin_opts: 'host=example.com;mode=quic;path=/obfs;tls=true',
+ },
+ {
+ type: 'vmess',
+ tag: 'vmess.complex',
+ security: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ transport: { type: 'ws', path: '/foo', headers: { Host: ['example.com'] } },
+ tls: {
+ enabled: true,
+ server_name: 'example.com',
+ insecure: true,
+ alpn: ['h2', 'http/1.1'],
+ min_version: '1.3',
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ },
+ multiplex: {
+ protocol: 'smux',
+ max_connections: 2,
+ min_streams: 1,
+ max_streams: 0,
+ padding: true,
+ enabled: true,
+ brutal: { up_mbps: 100, down_mbps: 100 },
+ },
+ tcp_fast_open: true,
+ tcp_multi_path: true,
+ detour: 'vmess.complex-shadowtls',
+ },
+ {
+ type: 'shadowtls',
+ tag: 'vmess.complex-shadowtls',
+ server: 'example.com',
+ server_port: 443,
+ version: 3,
+ password: 'password',
+ tls: { enabled: true, server_name: 'example.com' },
+ },
+ {
+ type: 'vmess',
+ tag: 'vmess.http',
+ server: 'example.com',
+ server_port: 443,
+ security: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ transport: {
+ type: 'http',
+ path: '/foo',
+ method: 'POST',
+ headers: { Host: ['example.com'] },
+ },
+ },
+ {
+ type: 'vmess',
+ tag: 'vmess.ws',
+ server: 'example.com',
+ server_port: 443,
+ security: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ transport: { type: 'ws', path: '/foo', headers: { Host: ['example.com'] } },
+ },
+ {
+ type: 'vmess',
+ tag: 'vmess.quic',
+ server: 'example.com',
+ server_port: 443,
+ security: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ transport: { type: 'quic' },
+ },
+ {
+ type: 'vmess',
+ tag: 'vmess.grpc',
+ server: 'example.com',
+ server_port: 443,
+ security: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ transport: { type: 'grpc', service_name: 'example' },
+ },
+ {
+ type: 'vmess',
+ tag: 'vmess.httpupgrade',
+ server: 'example.com',
+ server_port: 443,
+ security: 'auto',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ transport: {
+ type: 'httpupgrade',
+ host: 'example.com',
+ path: '/foo',
+ headers: { Host: ['example.com'] },
+ },
+ },
+ {
+ type: 'vless',
+ tag: 'vless.complex',
+ security: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ tls: {
+ enabled: true,
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ reality: { enabled: true, public_key: 'publicKey', short_id: 'shortId' },
+ server_name: 'example.com',
+ insecure: true,
+ alpn: ['h2', 'http/1.1'],
+ min_version: '1.3',
+ },
+ transport: { type: 'ws', path: '/foo', headers: { Host: ['example.com'] } },
+ multiplex: {
+ protocol: 'smux',
+ max_connections: 2,
+ min_streams: 1,
+ max_streams: 0,
+ padding: true,
+ enabled: true,
+ brutal: { up_mbps: 100, down_mbps: 100 },
+ },
+ tcp_fast_open: true,
+ tcp_multi_path: true,
+ detour: 'vless.complex-shadowtls',
+ },
+ {
+ type: 'shadowtls',
+ tag: 'vless.complex-shadowtls',
+ server: 'example.com',
+ server_port: 443,
+ version: 3,
+ password: 'password',
+ tls: { enabled: true, server_name: 'example.com' },
+ },
+ {
+ type: 'vless',
+ tag: 'vless.http',
+ server: 'example.com',
+ server_port: 443,
+ security: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ tls: {
+ enabled: true,
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ reality: { enabled: true, public_key: 'publicKey', short_id: 'shortId' },
+ },
+ transport: {
+ type: 'http',
+ path: '/foo',
+ method: 'POST',
+ headers: { Host: ['example.com'] },
+ },
+ },
+ {
+ type: 'vless',
+ tag: 'vless.ws',
+ server: 'example.com',
+ server_port: 443,
+ security: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ tls: {
+ enabled: true,
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ reality: { enabled: true, public_key: 'publicKey', short_id: 'shortId' },
+ },
+ transport: { type: 'ws', path: '/foo', headers: { Host: ['example.com'] } },
+ },
+ {
+ type: 'vless',
+ tag: 'vless.quic',
+ server: 'example.com',
+ server_port: 443,
+ security: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ tls: {
+ enabled: true,
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ reality: { enabled: true, public_key: 'publicKey', short_id: 'shortId' },
+ },
+ transport: { type: 'quic' },
+ },
+ {
+ type: 'vless',
+ tag: 'vless.grpc',
+ server: 'example.com',
+ server_port: 443,
+ security: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ tls: {
+ enabled: true,
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ reality: { enabled: true, public_key: 'publicKey', short_id: 'shortId' },
+ },
+ transport: { type: 'grpc', service_name: 'example' },
+ },
+ {
+ type: 'vless',
+ tag: 'vless.httpupgrade',
+ server: 'example.com',
+ server_port: 443,
+ security: 'none',
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ flow: 'xtls-rprx-vision',
+ tls: {
+ enabled: true,
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ reality: { enabled: true, public_key: 'publicKey', short_id: 'shortId' },
+ },
+ transport: {
+ type: 'httpupgrade',
+ host: 'example.com',
+ path: '/foo',
+ headers: { Host: ['example.com'] },
+ },
+ },
+ {
+ type: 'http',
+ tag: 'http',
+ server: 'example.com',
+ server_port: 80,
+ username: 'username',
+ password: 'password',
+ path: '/foo',
+ headers: { Host: ['example.com'] },
+ },
+ {
+ type: 'http',
+ tag: 'https',
+ server: 'example.com',
+ server_port: 443,
+ username: 'username',
+ password: 'password',
+ path: '/foo',
+ headers: { Host: ['example.com'] },
+ tls: {
+ enabled: true,
+ server_name: 'example.com',
+ insecure: true,
+ alpn: ['h2', 'http/1.1'],
+ min_version: '1.3',
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ },
+ },
+ {
+ type: 'trojan',
+ tag: 'trojan.ws',
+ server: 'example.com',
+ server_port: 443,
+ password: 'password',
+ transport: { type: 'ws', path: '/foo', headers: { Host: ['example.com'] } },
+ tls: {
+ enabled: true,
+ server_name: 'example.com',
+ insecure: true,
+ alpn: ['h2', 'http/1.1'],
+ min_version: '1.3',
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ },
+ multiplex: {
+ protocol: 'smux',
+ max_connections: 2,
+ min_streams: 1,
+ max_streams: 0,
+ padding: true,
+ enabled: true,
+ brutal: { up_mbps: 100, down_mbps: 100 },
+ },
+ },
+ {
+ type: 'socks',
+ tag: 'socks',
+ server: 'example.com',
+ server_port: 8080,
+ username: 'username',
+ password: 'password',
+ tls: {
+ enabled: true,
+ server_name: 'example.com',
+ insecure: true,
+ alpn: ['h2', 'http/1.1'],
+ min_version: '1.3',
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ },
+ },
+ {
+ type: 'tuic',
+ tag: 'tuic',
+ server: 'example.com',
+ server_port: 443,
+ uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
+ password: 'password',
+ tls: {
+ enabled: true,
+ server_name: 'example.com',
+ insecure: true,
+ alpn: ['h2', 'http/1.1'],
+ min_version: '1.3',
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ },
+ },
+ {
+ type: 'hysteria2',
+ tag: 'hysteria2',
+ server: 'example.com',
+ server_port: 443,
+ up_mbps: 100,
+ down_mbps: 100,
+ obfs: { type: 'salamander', password: 'password' },
+ password: 'password',
+ tls: {
+ enabled: true,
+ server_name: 'example.com',
+ insecure: true,
+ alpn: ['h2', 'http/1.1'],
+ min_version: '1.3',
+ utls: { enabled: true, fingerprint: 'chrome2' },
+ },
+ },
+ {
+ type: 'wireguard',
+ tag: 'wg',
+ local_address: ['10.0.0.1/32', '2001:db8:85a3::8a2e:370:7334/128'],
+ private_key: 'privateKey',
+ peers: [
+ {
+ server: 'wg1.example.com',
+ server_port: 51820,
+ public_key: 'publicKey1',
+ pre_shared_key: 'presharedKey1',
+ allowed_ips: ['0.0.0.0/0', '::/0'],
+ reserved: [1, 2, 3],
+ },
+ {
+ server: 'wg2.example.com',
+ server_port: 51820,
+ public_key: 'publicKey2',
+ pre_shared_key: 'presharedKey2',
+ allowed_ips: ['0.0.0.0/0', '::/0'],
+ reserved: [2, 2, 3],
+ },
+ ],
+ mtu: 1420,
+ },
+]
+
+const expectedNodeNames = expectedNodes
+ .map((node) => node.tag as string)
+ .filter((name) => !['NotSupported', 'disabled'].some((n) => name.includes(n)))
+
+test('getSingboxNodeNames', async (t) => {
+ t.deepEqual(singbox.getSingboxNodeNames(nodeList), expectedNodeNames)
+
+ t.deepEqual(
+ singbox.getSingboxNodeNames(
+ nodeList,
+ (nodeConfig) => nodeConfig.nodeName === 'ss',
+ ),
+ ['ss'],
+ )
+})
diff --git a/src/utils/__tests__/ss.test.ts b/src/utils/__tests__/ss.test.ts
index f583c9ea4..3ea407a0a 100644
--- a/src/utils/__tests__/ss.test.ts
+++ b/src/utils/__tests__/ss.test.ts
@@ -1,7 +1,7 @@
import test from 'ava'
import { NodeTypeEnum } from '../../types'
-import { parseSSUri } from '../ss'
+import { parseSSUri, stringifySip003Options } from '../ss'
test('parseSSUri', (t) => {
t.deepEqual(
@@ -20,3 +20,17 @@ test('parseSSUri', (t) => {
},
)
})
+
+test('stringifySip003Options', (t) => {
+ t.is(
+ stringifySip003Options({
+ a: 123,
+ host: 'https://a.com/foo?bar=baz&q\\q=1&w;w=2',
+ mode: 'quic',
+ tls: true,
+ }),
+ 'a=123;host=https://a.com/foo?bar\\=baz&q\\\\q\\=1&w\\;w\\=2;mode=quic;tls=true',
+ )
+ t.is(stringifySip003Options({}), '')
+ t.is(stringifySip003Options(), '')
+})
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 56b6fe7fd..b6cb7ea91 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -25,6 +25,7 @@ import { applyFilter } from '../filters'
export * from './surge'
export * from './surfboard'
export * from './clash'
+export * from './singbox'
export * from './quantumult'
export * from './loon'
export * from './remote-snippet'
diff --git a/src/utils/singbox.ts b/src/utils/singbox.ts
new file mode 100644
index 000000000..346b5d412
--- /dev/null
+++ b/src/utils/singbox.ts
@@ -0,0 +1,418 @@
+import { createLogger } from '@surgio/logger'
+
+import { ERR_INVALID_FILTER } from '../constant'
+import {
+ NodeFilterType,
+ NodeTypeEnum,
+ PossibleNodeConfigType,
+ SortedNodeFilterType,
+} from '../types'
+import { applyFilter } from '../filters'
+import {
+ checkNotNullish,
+ getHostnameFromHost,
+ getPortFromHost,
+ pickAndFormatKeys,
+} from './'
+import { MultiplexValidator, TlsNodeConfigValidator } from '../validators'
+import { stringifySip003Options } from './ss'
+
+const logger = createLogger({ service: 'surgio:utils:singbox' })
+
+export const getSingboxNodes = function (
+ list: ReadonlyArray,
+ filter?: NodeFilterType | SortedNodeFilterType,
+) {
+ return applyFilter(list, filter)
+ .flatMap(nodeListMapper)
+ .filter((item): item is Record => checkNotNullish(item))
+}
+
+export const getSingboxNodeNames = function (
+ list: ReadonlyArray,
+ filter?: NodeFilterType | SortedNodeFilterType,
+): ReadonlyArray {
+ // istanbul ignore next
+ if (arguments.length === 2 && typeof filter === 'undefined') {
+ throw new Error(ERR_INVALID_FILTER)
+ }
+
+ return getSingboxNodes(list, filter).map((item) => item.tag)
+}
+
+const typeMap = {
+ [NodeTypeEnum.HTTP]: 'http',
+ [NodeTypeEnum.HTTPS]: 'http',
+ [NodeTypeEnum.Shadowsocks]: 'shadowsocks',
+ [NodeTypeEnum.Vmess]: 'vmess',
+ [NodeTypeEnum.Vless]: 'vless',
+ [NodeTypeEnum.Trojan]: 'trojan',
+ [NodeTypeEnum.Socks5]: 'socks',
+ [NodeTypeEnum.Tuic]: 'tuic',
+ [NodeTypeEnum.Wireguard]: 'wireguard',
+ [NodeTypeEnum.Hysteria2]: 'hysteria2',
+} as const
+
+/**
+ * @see https://sing-box.sagernet.org/configuration/outbound/
+ */
+function nodeListMapper(nodeConfig: PossibleNodeConfigType) {
+ if (nodeConfig.type in typeMap === false) {
+ logger.warn(
+ `不支持为 sing-box 生成 ${nodeConfig.type} 的节点,节点 ${nodeConfig.nodeName} 会被忽略`,
+ )
+ return null
+ }
+ const node: Record = {
+ type: typeMap[nodeConfig.type as keyof typeof typeMap],
+ tag: nodeConfig.nodeName,
+ }
+ if ('hostname' in nodeConfig) {
+ node.server = nodeConfig.hostname
+ }
+ if ('port' in nodeConfig) {
+ node.server_port = Number(nodeConfig.port)
+ }
+ if ('udpRelay' in nodeConfig && nodeConfig.udpRelay === false) {
+ node.network = 'tcp'
+ }
+
+ const setTls = (field: string, v: any) => {
+ if (!node.tls) {
+ node.tls = { enabled: true }
+ }
+ node.tls[field] = v
+ }
+
+ switch (nodeConfig.type) {
+ case NodeTypeEnum.Shadowsocks:
+ node.method = nodeConfig.method
+ node.password = nodeConfig.password
+ if (nodeConfig.obfs) {
+ if (['tls', 'http'].includes(nodeConfig.obfs)) {
+ node.plugin = 'obfs-local'
+ node.plugin_opts = stringifySip003Options(
+ prune({
+ obfs: nodeConfig.obfs,
+ 'obfs-host': nodeConfig.obfsHost,
+ }),
+ )
+ }
+ if (['ws', 'wss', 'quic'].includes(nodeConfig.obfs)) {
+ node.plugin = 'v2ray-plugin'
+ node.plugin_opts = stringifySip003Options(
+ prune({
+ mode: nodeConfig.obfs === 'quic' ? 'quic' : 'websocket',
+ tls: ['wss', 'quic'].includes(nodeConfig.obfs),
+ host: nodeConfig.obfsHost,
+ path: nodeConfig.obfsUri,
+ mux: nodeConfig.mux === false ? 0 : null,
+ }),
+ )
+ }
+ }
+ break
+
+ case NodeTypeEnum.Vless:
+ case NodeTypeEnum.Vmess: {
+ node.security = nodeConfig.method
+ node.uuid = nodeConfig.uuid
+ if (nodeConfig.type === NodeTypeEnum.Vmess) {
+ if (nodeConfig.alterId) {
+ node.alter_id = Number(nodeConfig.alterId)
+ }
+ }
+ if (nodeConfig.type === NodeTypeEnum.Vless) {
+ node.flow = nodeConfig.flow
+ if (nodeConfig.realityOpts) {
+ setTls('utls', {
+ enabled: true,
+ fingerprint: nodeConfig.clientFingerprint,
+ })
+ setTls('reality', {
+ enabled: true,
+ public_key: nodeConfig.realityOpts.publicKey,
+ short_id: nodeConfig.realityOpts.shortId,
+ })
+ }
+ }
+
+ switch (nodeConfig.network) {
+ case 'http':
+ node.transport = {
+ type: 'http',
+ // host: [],
+ path: nodeConfig.httpOpts?.path[0],
+ method: nodeConfig.httpOpts?.method,
+ headers: normalizeHeaders(nodeConfig.httpOpts?.headers),
+ // idle_timeout: '15s',
+ // ping_timeout: '15s',
+ }
+ break
+
+ case 'ws':
+ node.transport = {
+ type: 'ws',
+ path: nodeConfig.wsOpts?.path,
+ headers: normalizeHeaders(nodeConfig.wsOpts?.headers),
+ // max_early_data: 0,
+ // early_data_header_name: '',
+ }
+ break
+
+ case 'quic':
+ node.transport = {
+ type: 'quic',
+ }
+ break
+
+ case 'grpc':
+ node.transport = {
+ type: 'grpc',
+ service_name: nodeConfig.grpcOpts?.serviceName,
+ // idle_timeout: '15s',
+ // ping_timeout: '15s',
+ // permit_without_stream: false,
+ }
+ break
+
+ case 'httpupgrade':
+ node.transport = {
+ type: 'httpupgrade',
+ host: nodeConfig.httpUpgradeOpts?.host,
+ path: nodeConfig.httpUpgradeOpts?.path,
+ headers: normalizeHeaders(nodeConfig.httpUpgradeOpts?.headers),
+ }
+ break
+
+ default:
+ logger.warn(
+ `sing-box 的 ${nodeConfig.type} 节点不支持 network=${nodeConfig.network},节点 ${nodeConfig.nodeName} 会被忽略`,
+ )
+ return null
+ }
+ break
+ }
+
+ case NodeTypeEnum.HTTP:
+ case NodeTypeEnum.HTTPS:
+ node.username = nodeConfig.username
+ node.password = nodeConfig.password
+ node.path = nodeConfig.path
+ node.headers = normalizeHeaders(nodeConfig.headers)
+ if (nodeConfig.type === NodeTypeEnum.HTTPS) {
+ setTls('enabled', true)
+ }
+ break
+
+ case NodeTypeEnum.Trojan:
+ node.password = nodeConfig.password
+ if (nodeConfig.network) {
+ switch (nodeConfig.network) {
+ case 'ws':
+ node.transport = {
+ type: 'ws',
+ path: nodeConfig.wsPath,
+ headers: normalizeHeaders(nodeConfig.wsHeaders),
+ // max_early_data: 0,
+ // early_data_header_name: '',
+ }
+ break
+
+ default:
+ logger.warn(
+ `sing-box 的 ${nodeConfig.type} 节点不支持 network=${nodeConfig.network},节点 ${nodeConfig.nodeName} 会被忽略`,
+ )
+ return null
+ }
+ }
+ break
+
+ case NodeTypeEnum.Socks5:
+ node.username = nodeConfig.username
+ node.password = nodeConfig.password
+ break
+
+ case NodeTypeEnum.Tuic:
+ if ('uuid' in nodeConfig === false) {
+ logger.warn(
+ `sing-box 仅支持 tuic v5,节点 ${nodeConfig.nodeName} 会被忽略`,
+ )
+ return null
+ }
+ node.uuid = nodeConfig.uuid
+ node.password = nodeConfig.password
+ // congestion_control: 'cubic',
+ // udp_relay_mode: 'native',
+ // udp_over_stream: false,
+ // zero_rtt_handshake: false,
+ // heartbeat: '10s',
+ break
+
+ case NodeTypeEnum.Hysteria2:
+ node.up_mbps = nodeConfig.uploadBandwidth
+ node.down_mbps = nodeConfig.downloadBandwidth
+ node.obfs = {
+ type: nodeConfig.obfs,
+ password: nodeConfig.obfsPassword,
+ }
+ node.password = nodeConfig.password
+ break
+
+ case NodeTypeEnum.Wireguard:
+ // const sample = {
+ // system_interface: false,
+ // gso: false,
+ // interface_name: 'wg0',
+ // local_address: ['10.0.0.2/32'],
+ // private_key: 'YNXtAzepDqRv9H52osJVDQnznT5AM11eCK3ESpwSt04=',
+ // peers: [
+ // {
+ // server: '127.0.0.1',
+ // server_port: 1080,
+ // public_key: 'Z1XXLsKYkYxuiYjJIkRvtIKFepCYHTgON+GwPq7SOV4=',
+ // pre_shared_key: '31aIhAPwktDGpH4JDhA8GNvjFXEf/a6+UaQRyOAiyfM=',
+ // allowed_ips: ['0.0.0.0/0'],
+ // reserved: [0, 0, 0],
+ // },
+ // ],
+ // peer_public_key: 'Z1XXLsKYkYxuiYjJIkRvtIKFepCYHTgON+GwPq7SOV4=',
+ // pre_shared_key: '31aIhAPwktDGpH4JDhA8GNvjFXEf/a6+UaQRyOAiyfM=',
+ // reserved: [0, 0, 0],
+ // workers: 4,
+ // mtu: 1408,
+ // }
+ node.local_address = [`${nodeConfig.selfIp}/32`]
+ if (nodeConfig.selfIpV6) {
+ node.local_address.push(`${nodeConfig.selfIpV6}/128`)
+ }
+ node.private_key = nodeConfig.privateKey
+ node.peers = nodeConfig.peers.map((peer) => ({
+ server: getHostnameFromHost(peer.endpoint),
+ server_port: getPortFromHost(peer.endpoint),
+ public_key: peer.publicKey,
+ pre_shared_key: peer.presharedKey,
+ allowed_ips: peer.allowedIps?.split(',').map((ip) => ip.trim()),
+ reserved: peer.reservedBits,
+ }))
+ node.mtu = nodeConfig.mtu
+ break
+ }
+
+ if ('tls' in nodeConfig && nodeConfig.tls) {
+ setTls('enabled', true)
+ }
+ const r = TlsNodeConfigValidator.safeParse(nodeConfig)
+ if (r.success) {
+ const tlsConfig = r.data
+ if (tlsConfig.sni) {
+ setTls('server_name', tlsConfig.sni)
+ }
+ if (tlsConfig.skipCertVerify) {
+ setTls('insecure', true)
+ }
+ if (tlsConfig.alpn) {
+ setTls('alpn', tlsConfig.alpn)
+ }
+ if (tlsConfig.tls13) {
+ setTls('min_version', '1.3')
+ }
+ if (tlsConfig.clientFingerprint) {
+ setTls('utls', {
+ enabled: true,
+ fingerprint: tlsConfig.clientFingerprint,
+ })
+ }
+ }
+ if ('multiplex' in nodeConfig) {
+ const r = MultiplexValidator.safeParse(nodeConfig.multiplex)
+ if (r.success) {
+ const multiplexConfig = r.data
+ node.multiplex = pickAndFormatKeys(
+ multiplexConfig,
+ ['protocol', 'maxConnections', 'minStreams', 'maxStreams', 'padding'],
+ { keyFormat: 'snakeCase' },
+ )
+ node.multiplex.enabled = true
+ if (multiplexConfig.brutal) {
+ node.multiplex.brutal = pickAndFormatKeys(
+ multiplexConfig.brutal,
+ ['upMbps', 'downMbps'],
+ { keyFormat: 'snakeCase' },
+ )
+ }
+ }
+ }
+ if (nodeConfig.tfo) {
+ node.tcp_fast_open = true
+ }
+ if (nodeConfig.mptcp) {
+ node.tcp_multi_path = true
+ }
+ if (nodeConfig.underlyingProxy) {
+ node.detour = nodeConfig.underlyingProxy
+ }
+ if (!nodeConfig.shadowTls) {
+ return prune(node)
+ }
+ const { server, server_port, ..._node } = node
+ const tag = `${node.tag}-shadowtls`
+ _node.detour = tag
+ return [
+ prune(_node),
+ prune({
+ type: 'shadowtls',
+ tag: tag,
+ server: server,
+ server_port: server_port,
+ version: nodeConfig.shadowTls.version,
+ password: nodeConfig.shadowTls.password,
+ tls: {
+ enabled: true,
+ server_name: nodeConfig.shadowTls.sni,
+ },
+ }),
+ ]
+}
+
+function normalizeHeaders(headers: Record | undefined) {
+ if (!headers) {
+ return {}
+ }
+ return Object.fromEntries(Object.entries(headers).map(([k, v]) => [k, [v]]))
+}
+
+// delete all undefined / null / [] / {} / '' properties
+function prune(obj: Record): Record {
+ const prunedObj: Record = {}
+
+ for (const key in obj) {
+ const value = obj[key]
+
+ // Check if the property exists and is not null or undefined
+ if (value !== null && value !== undefined) {
+ // Check if the property is an array
+ if (Array.isArray(value)) {
+ // Check if the array is empty
+ if (value.length > 0) {
+ prunedObj[key] = value
+ }
+ } else if (typeof value === 'object') {
+ // Check if the object is empty
+ if (Object.keys(value).length > 0) {
+ prunedObj[key] = prune(value) // Recursively prune the object
+ }
+ } else if (typeof value === 'string') {
+ // Check if the string is not empty
+ if (value.trim().length > 0) {
+ prunedObj[key] = value
+ }
+ } else {
+ // Add non-empty string, number, or boolean values
+ prunedObj[key] = value
+ }
+ }
+ }
+
+ return prunedObj
+}
diff --git a/src/utils/ss.ts b/src/utils/ss.ts
index 70c218833..e82bbc540 100644
--- a/src/utils/ss.ts
+++ b/src/utils/ss.ts
@@ -46,3 +46,23 @@ export const parseSSUri = (str: string): ShadowsocksNodeConfig => {
: null),
}
}
+
+// Marshal SIP003 plugin options in PossibleNodeConfigType to formatted string.
+// An example is 'a=123;host=https://a.com/foo?bar\=baz&q\\q\=1&w\;w\=2;mode=quic;tls=true',
+// where semicolons, equal signs and backslashes MUST be escaped with a backslash.
+export const stringifySip003Options = (args?: Record): string => {
+ if (!args) {
+ return ''
+ }
+
+ const keys = Object.keys(args).sort()
+ const pairs: string[] = []
+ for (const key of keys) {
+ pairs.push(
+ `${key.replace(/([;=\\])/g, '\\$1')}=${args[key]
+ .toString()
+ .replace(/([;=\\])/g, '\\$1')}`,
+ )
+ }
+ return pairs.join(';')
+}
diff --git a/src/validators/artifact.ts b/src/validators/artifact.ts
index c43901aa7..9974a363d 100644
--- a/src/validators/artifact.ts
+++ b/src/validators/artifact.ts
@@ -3,6 +3,14 @@ import { z } from 'zod'
export const ArtifactValidator = z.object({
name: z.string(),
template: z.string(),
+ templateType: z
+ .union([z.literal('default'), z.literal('json')])
+ .default('default'),
+ extendTemplate: z
+ .function()
+ .args(z.unknown())
+ .returns(z.unknown())
+ .optional(),
provider: z.string(),
categories: z.array(z.string()).optional(),
combineProviders: z.array(z.string()).optional(),
diff --git a/src/validators/common.ts b/src/validators/common.ts
index 79d720da7..805e9b638 100644
--- a/src/validators/common.ts
+++ b/src/validators/common.ts
@@ -97,3 +97,17 @@ export const TlsNodeConfigValidator = SimpleNodeConfigValidator.extend({
serverCertFingerprintSha256: z.ostring(),
clientFingerprint: z.ostring(),
})
+
+export const MultiplexValidator = z.object({
+ protocol: z.enum(['smux', 'yamux', 'h2mux']),
+ maxConnections: z.number().optional(),
+ minStreams: z.number().optional(),
+ maxStreams: z.number().optional(),
+ padding: z.boolean().optional(),
+ brutal: z
+ .object({
+ upMbps: z.number(),
+ downMbps: z.number(),
+ })
+ .optional(),
+})
diff --git a/src/validators/http.ts b/src/validators/http.ts
index 903a833d1..88266079c 100644
--- a/src/validators/http.ts
+++ b/src/validators/http.ts
@@ -13,10 +13,14 @@ export const HttpNodeConfigValidator = SimpleNodeConfigValidator.extend({
port: PortValidator,
username: z.string(),
password: z.string(),
+ path: z.string().optional(),
+ headers: z.record(z.string()).optional(),
})
export const HttpsNodeConfigValidator = TlsNodeConfigValidator.extend({
type: z.literal(NodeTypeEnum.HTTPS),
username: z.string(),
password: z.string(),
+ path: z.string().optional(),
+ headers: z.record(z.string()).optional(),
})
diff --git a/src/validators/shadowsocks.ts b/src/validators/shadowsocks.ts
index 90c68f66f..b493f89ba 100644
--- a/src/validators/shadowsocks.ts
+++ b/src/validators/shadowsocks.ts
@@ -1,7 +1,11 @@
import { z } from 'zod'
import { NodeTypeEnum } from '../types'
-import { PortValidator, SimpleNodeConfigValidator } from './common'
+import {
+ MultiplexValidator,
+ PortValidator,
+ SimpleNodeConfigValidator,
+} from './common'
export const ShadowsocksNodeConfigValidator = SimpleNodeConfigValidator.extend({
type: z.literal(NodeTypeEnum.Shadowsocks),
@@ -16,6 +20,7 @@ export const ShadowsocksNodeConfigValidator = SimpleNodeConfigValidator.extend({
z.literal('http'),
z.literal('ws'),
z.literal('wss'),
+ z.literal('quic'),
])
.optional(),
obfsHost: z.ostring(),
@@ -24,4 +29,5 @@ export const ShadowsocksNodeConfigValidator = SimpleNodeConfigValidator.extend({
wsHeaders: z.record(z.string()).optional(),
tls13: z.oboolean(),
mux: z.oboolean(),
+ multiplex: MultiplexValidator.optional(),
})
diff --git a/src/validators/socks5.ts b/src/validators/socks5.ts
index 8c679dccb..613fea6ef 100644
--- a/src/validators/socks5.ts
+++ b/src/validators/socks5.ts
@@ -1,17 +1,13 @@
import { z } from 'zod'
import { NodeTypeEnum } from '../types'
-import { PortValidator, SimpleNodeConfigValidator } from './common'
+import { TlsNodeConfigValidator } from './common'
-export const Socks5NodeConfigValidator = SimpleNodeConfigValidator.extend({
+export const Socks5NodeConfigValidator = TlsNodeConfigValidator.extend({
type: z.literal(NodeTypeEnum.Socks5),
- hostname: z.string(),
- port: PortValidator,
username: z.ostring(),
password: z.ostring(),
udpRelay: z.oboolean(),
tls: z.oboolean(),
- skipCertVerify: z.oboolean(),
- sni: z.ostring(),
clientCert: z.ostring(),
})
diff --git a/src/validators/trojan.ts b/src/validators/trojan.ts
index fe2de5771..e323e5910 100644
--- a/src/validators/trojan.ts
+++ b/src/validators/trojan.ts
@@ -1,7 +1,7 @@
import { z } from 'zod'
import { NodeTypeEnum } from '../types'
-import { TlsNodeConfigValidator } from './common'
+import { MultiplexValidator, TlsNodeConfigValidator } from './common'
export const TrojanNodeConfigValidator = TlsNodeConfigValidator.extend({
type: z.literal(NodeTypeEnum.Trojan),
@@ -10,4 +10,6 @@ export const TrojanNodeConfigValidator = TlsNodeConfigValidator.extend({
network: z.union([z.literal('tcp'), z.literal('ws')]).optional(),
wsPath: z.ostring(),
wsHeaders: z.record(z.string()).optional(),
+
+ multiplex: MultiplexValidator.optional(),
})
diff --git a/src/validators/vless.ts b/src/validators/vless.ts
index 0b4487806..157018a98 100644
--- a/src/validators/vless.ts
+++ b/src/validators/vless.ts
@@ -1,13 +1,19 @@
import { z } from 'zod'
import { NodeTypeEnum } from '../types'
-import { PortValidator, TlsNodeConfigValidator } from './common'
+import {
+ MultiplexValidator,
+ PortValidator,
+ TlsNodeConfigValidator,
+} from './common'
import {
VmessNetworkValidator,
VmessH2OptsValidator,
VmessGRPCOptsValidator,
VmessHttpOptsValidator,
VmessWSOptsValidator,
+ VmessQuicOptsValidator,
+ VmessHttpUpgradeOptsValidator,
} from './vmess'
export const VlessRealityOptsValidator = z.object({
@@ -30,5 +36,9 @@ export const VlessNodeConfigValidator = TlsNodeConfigValidator.extend({
h2Opts: VmessH2OptsValidator.optional(),
httpOpts: VmessHttpOptsValidator.optional(),
grpcOpts: VmessGRPCOptsValidator.optional(),
+ quicOpts: VmessQuicOptsValidator.optional(),
+ httpUpgradeOpts: VmessHttpUpgradeOptsValidator.optional(),
realityOpts: VlessRealityOptsValidator.optional(),
+
+ multiplex: MultiplexValidator.optional(),
})
diff --git a/src/validators/vmess.ts b/src/validators/vmess.ts
index 8f676e55a..9ef8a7999 100644
--- a/src/validators/vmess.ts
+++ b/src/validators/vmess.ts
@@ -5,6 +5,7 @@ import {
PortValidator,
SimpleNodeConfigValidator,
AlterIdValiator,
+ MultiplexValidator,
} from './common'
export const VmessNetworkValidator = z.union([
@@ -13,6 +14,8 @@ export const VmessNetworkValidator = z.union([
z.literal('h2'),
z.literal('http'),
z.literal('grpc'),
+ z.literal('quic'),
+ z.literal('httpupgrade'),
])
export const VmessMethodValidator = z.union([
@@ -42,6 +45,16 @@ export const VmessGRPCOptsValidator = z.object({
serviceName: z.string(),
})
+export const VmessQuicOptsValidator = z.object({
+ // no field now
+})
+
+export const VmessHttpUpgradeOptsValidator = z.object({
+ path: z.string(),
+ host: z.string().optional(),
+ headers: z.record(z.string()).optional(),
+})
+
/**
* @see https://stash.wiki/proxy-protocols/proxy-types#vmess
* @see https://wiki.metacubex.one/config/proxies/vmess/
@@ -60,6 +73,8 @@ export const VmessNodeConfigValidator = SimpleNodeConfigValidator.extend({
h2Opts: VmessH2OptsValidator.optional(),
httpOpts: VmessHttpOptsValidator.optional(),
grpcOpts: VmessGRPCOptsValidator.optional(),
+ quicOpts: VmessQuicOptsValidator.optional(),
+ httpUpgradeOpts: VmessHttpUpgradeOptsValidator.optional(),
tls: z.oboolean(),
sni: z.ostring(),
@@ -69,6 +84,8 @@ export const VmessNodeConfigValidator = SimpleNodeConfigValidator.extend({
alpn: z.array(z.string()).nonempty().optional(),
clientFingerprint: z.ostring(),
+ multiplex: MultiplexValidator.optional(),
+
/**
* @deprecated
*/
diff --git a/test/cli.cli-test.ts b/test/cli.cli-test.ts
index bc3b0b2f0..16cf94646 100644
--- a/test/cli.cli-test.ts
+++ b/test/cli.cli-test.ts
@@ -51,6 +51,12 @@ describe('generate command', () => {
const confString5 = fs.readFileSync(resolve('plain/dist/v2rayn.conf'), {
encoding: 'utf8',
})
+ const singboxConfString = fs.readFileSync(
+ resolve('plain/dist/singbox.json'),
+ {
+ encoding: 'utf8',
+ },
+ )
const conf = ini.decode(confString1)
expect(fs.existsSync(resolve('plain/dist/new_path.conf'))).to.be.true
@@ -59,6 +65,7 @@ describe('generate command', () => {
expect(fs.existsSync(resolve('plain/dist/v2rayn.conf'))).to.be.true
expect(fs.existsSync(resolve('plain/dist/custom.conf'))).to.be.true
expect(fs.existsSync(resolve('plain/dist/ssd.conf'))).to.be.true
+ expect(fs.existsSync(resolve('plain/dist/singbox.json'))).to.be.true
expect(confString1.split('\n')[0]).to.equal(
'#!MANAGED-CONFIG https://example.com/ss_json.conf?access_token=abcd interval=43200 strict=false',
)
@@ -66,6 +73,7 @@ describe('generate command', () => {
expect(Object.keys(conf.Proxy).length).to.be.equal(4)
;(expect(confString3).to as any).matchSnapshot()
;(expect(confString5).to as any).matchSnapshot()
+ ;(expect(singboxConfString).to as any).matchSnapshot()
})
})
diff --git a/test/cli.cli-test.ts.snap b/test/cli.cli-test.ts.snap
index 0f69ebe25..18531083a 100644
--- a/test/cli.cli-test.ts.snap
+++ b/test/cli.cli-test.ts.snap
@@ -228,6 +228,207 @@ DOMAIN,example.com,Proxy
"
`;
+exports[`generate command default runs generate cmd 3`] = `
+"{
+ \\"dns\\": {
+ \\"servers\\": [
+ {
+ \\"tag\\": \\"dnspod-doh\\",
+ \\"address\\": \\"https://1.12.12.12/dns-query\\",
+ \\"detour\\": \\"direct\\"
+ },
+ {
+ \\"tag\\": \\"remote\\",
+ \\"address\\": \\"fakeip\\"
+ },
+ {
+ \\"tag\\": \\"block\\",
+ \\"address\\": \\"rcode://success\\"
+ }
+ ],
+ \\"rules\\": [
+ {
+ \\"rule_set\\": \\"geosite-category-ads-all\\",
+ \\"server\\": \\"block\\"
+ },
+ {
+ \\"outbound\\": \\"any\\",
+ \\"server\\": \\"dnspod-doh\\"
+ },
+ {
+ \\"query_type\\": [
+ \\"A\\",
+ \\"AAAA\\"
+ ],
+ \\"server\\": \\"remote\\"
+ }
+ ],
+ \\"fakeip\\": {
+ \\"enabled\\": true,
+ \\"inet4_range\\": \\"198.18.0.0/15\\",
+ \\"inet6_range\\": \\"fc00::/18\\"
+ },
+ \\"independent_cache\\": true
+ },
+ \\"inbounds\\": [
+ {
+ \\"type\\": \\"tun\\",
+ \\"inet4_address\\": \\"172.19.0.1/30\\",
+ \\"inet6_address\\": \\"fdfe:dcba:9876::1/126\\",
+ \\"auto_route\\": true,
+ \\"strict_route\\": true,
+ \\"sniff\\": true
+ }
+ ],
+ \\"outbounds\\": [
+ {
+ \\"type\\": \\"block\\",
+ \\"tag\\": \\"block\\"
+ },
+ {
+ \\"type\\": \\"dns\\",
+ \\"tag\\": \\"dns\\"
+ },
+ {
+ \\"type\\": \\"direct\\",
+ \\"tag\\": \\"direct\\",
+ \\"tcp_fast_open\\": false,
+ \\"tcp_multi_path\\": true
+ },
+ {
+ \\"type\\": \\"selector\\",
+ \\"tag\\": \\"proxy\\",
+ \\"outbounds\\": [
+ \\"auto\\",
+ \\"🇺🇸US 1\\",
+ \\"🇺🇸US 2\\",
+ \\"🇺🇸US 3\\"
+ ],
+ \\"interrupt_exist_connections\\": false
+ },
+ {
+ \\"type\\": \\"shadowsocks\\",
+ \\"tag\\": \\"🇺🇸US 1\\",
+ \\"server\\": \\"us.example.com\\",
+ \\"server_port\\": 443,
+ \\"method\\": \\"chacha20-ietf-poly1305\\",
+ \\"password\\": \\"password\\",
+ \\"plugin\\": \\"obfs-local\\",
+ \\"plugin_opts\\": \\"obfs=tls;obfs-host=gateway-carry.icloud.com\\",
+ \\"tcp_fast_open\\": true,
+ \\"tcp_multi_path\\": true
+ },
+ {
+ \\"type\\": \\"shadowsocks\\",
+ \\"tag\\": \\"🇺🇸US 2\\",
+ \\"server\\": \\"us.example.com\\",
+ \\"server_port\\": 443,
+ \\"method\\": \\"chacha20-ietf-poly1305\\",
+ \\"password\\": \\"password\\",
+ \\"tcp_fast_open\\": true,
+ \\"tcp_multi_path\\": true
+ },
+ {
+ \\"type\\": \\"shadowsocks\\",
+ \\"tag\\": \\"🇺🇸US 3\\",
+ \\"server\\": \\"us.example.com\\",
+ \\"server_port\\": 443,
+ \\"method\\": \\"chacha20-ietf-poly1305\\",
+ \\"password\\": \\"password\\",
+ \\"plugin\\": \\"v2ray-plugin\\",
+ \\"plugin_opts\\": \\"host=gateway-carry.icloud.com;mode=websocket;tls=true\\",
+ \\"tcp_fast_open\\": true,
+ \\"tcp_multi_path\\": true
+ }
+ ],
+ \\"route\\": {
+ \\"rules\\": [
+ {
+ \\"type\\": \\"logical\\",
+ \\"mode\\": \\"or\\",
+ \\"rules\\": [
+ {
+ \\"protocol\\": \\"dns\\"
+ },
+ {
+ \\"port\\": 53
+ }
+ ],
+ \\"outbound\\": \\"dns\\"
+ },
+ {
+ \\"ip_is_private\\": true,
+ \\"outbound\\": \\"direct\\"
+ },
+ {
+ \\"clash_mode\\": \\"Direct\\",
+ \\"outbound\\": \\"direct\\"
+ },
+ {
+ \\"clash_mode\\": \\"Global\\",
+ \\"outbound\\": \\"proxy\\"
+ },
+ {
+ \\"geosite\\": \\"geosite-category-ads-all\\",
+ \\"outbound\\": \\"block\\"
+ },
+ {
+ \\"type\\": \\"logical\\",
+ \\"mode\\": \\"and\\",
+ \\"rules\\": [
+ {
+ \\"rule_set\\": \\"geosite-geolocation-!cn\\",
+ \\"invert\\": true
+ },
+ {
+ \\"rule_set\\": [
+ \\"geoip-cn\\",
+ \\"geosite-cn\\"
+ ]
+ }
+ ],
+ \\"outbound\\": \\"direct\\"
+ }
+ ],
+ \\"rule_set\\": [
+ {
+ \\"tag\\": \\"geosite-category-ads-all\\",
+ \\"type\\": \\"remote\\",
+ \\"format\\": \\"binary\\",
+ \\"url\\": \\"https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-category-ads-all.srs\\"
+ },
+ {
+ \\"type\\": \\"remote\\",
+ \\"tag\\": \\"geosite-geolocation-!cn\\",
+ \\"format\\": \\"binary\\",
+ \\"url\\": \\"https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-geolocation-!cn.srs\\"
+ },
+ {
+ \\"tag\\": \\"geosite-cn\\",
+ \\"type\\": \\"remote\\",
+ \\"format\\": \\"binary\\",
+ \\"url\\": \\"https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-cn.srs\\"
+ },
+ {
+ \\"tag\\": \\"geoip-cn\\",
+ \\"type\\": \\"remote\\",
+ \\"format\\": \\"binary\\",
+ \\"url\\": \\"https://cdn.jsdelivr.net/gh/SagerNet/sing-geoip@rule-set/geoip-cn.srs\\"
+ }
+ ],
+ \\"auto_detect_interface\\": true
+ },
+ \\"experimental\\": {
+ \\"cache_file\\": {
+ \\"enabled\\": true
+ },
+ \\"clash_api\\": {
+ \\"external_controller\\": \\"127.0.0.1:9090\\"
+ }
+ }
+}"
+`;
+
exports[`generate command v2ray tls options runs generate cmd 1`] = `
"getSurgeNodes
🇺🇸US 1 = ss, us.example.com, 443, encrypt-method=chacha20-ietf-poly1305, password=password, udp-relay=false, obfs=tls, obfs-host=gateway-carry.icloud.com, tls13=false, skip-cert-verify=false
diff --git a/test/fixture/plain/surgio.conf.js b/test/fixture/plain/surgio.conf.js
index 25168d890..6f80025cc 100644
--- a/test/fixture/plain/surgio.conf.js
+++ b/test/fixture/plain/surgio.conf.js
@@ -1,8 +1,9 @@
'use strict'
const path = require('path')
+const { extendOutbounds, defineSurgioConfig } = require('../../../')
-module.exports = {
+module.exports = defineSurgioConfig({
artifacts: [
{
name: 'new_path.conf',
@@ -69,6 +70,29 @@ module.exports = {
},
},
},
+ {
+ name: 'singbox.json',
+ template: 'singbox',
+ templateType: 'json',
+ extendTemplate: extendOutbounds(
+ ({ getSingboxNodes, getSingboxNodeNames, nodeList }) => [
+ {
+ type: 'direct',
+ tag: 'direct',
+ tcp_fast_open: false,
+ tcp_multi_path: true,
+ },
+ {
+ type: 'selector',
+ tag: 'proxy',
+ outbounds: ['auto', ...getSingboxNodeNames(nodeList)],
+ interrupt_exist_connections: false,
+ },
+ ...getSingboxNodes(nodeList),
+ ],
+ ),
+ provider: 'ss',
+ },
],
urlBase: 'https://example.com/',
binPath: {
@@ -95,4 +119,4 @@ module.exports = {
},
proxyTestUrl: 'http://www.google.com/generate_204',
proxyTestInterval: 2400,
-}
+})
diff --git a/test/fixture/plain/template/singbox.json b/test/fixture/plain/template/singbox.json
new file mode 100644
index 000000000..a84b79c82
--- /dev/null
+++ b/test/fixture/plain/template/singbox.json
@@ -0,0 +1,147 @@
+{
+ "dns": {
+ "servers": [
+ {
+ "tag": "dnspod-doh",
+ "address": "https://1.12.12.12/dns-query",
+ "detour": "direct"
+ },
+ {
+ "tag": "remote",
+ "address": "fakeip"
+ },
+ {
+ "tag": "block",
+ "address": "rcode://success"
+ }
+ ],
+ "rules": [
+ {
+ "rule_set": "geosite-category-ads-all",
+ "server": "block"
+ },
+ {
+ "outbound": "any",
+ "server": "dnspod-doh"
+ },
+ {
+ "query_type": [
+ "A",
+ "AAAA"
+ ],
+ "server": "remote"
+ }
+ ],
+ "fakeip": {
+ "enabled": true,
+ "inet4_range": "198.18.0.0/15",
+ "inet6_range": "fc00::/18"
+ },
+ "independent_cache": true
+ },
+ "inbounds": [
+ {
+ "type": "tun",
+ "inet4_address": "172.19.0.1/30",
+ "inet6_address": "fdfe:dcba:9876::1/126",
+ "auto_route": true,
+ "strict_route": true,
+ "sniff": true
+ }
+ ],
+ "outbounds": [
+ {
+ "type": "block",
+ "tag": "block"
+ },
+ {
+ "type": "dns",
+ "tag": "dns"
+ }
+ ],
+ "route": {
+ "rules": [
+ {
+ "type": "logical",
+ "mode": "or",
+ "rules": [
+ {
+ "protocol": "dns"
+ },
+ {
+ "port": 53
+ }
+ ],
+ "outbound": "dns"
+ },
+ {
+ "ip_is_private": true,
+ "outbound": "direct"
+ },
+ {
+ "clash_mode": "Direct",
+ "outbound": "direct"
+ },
+ {
+ "clash_mode": "Global",
+ "outbound": "proxy"
+ },
+ {
+ "geosite": "geosite-category-ads-all",
+ "outbound": "block"
+ },
+ {
+ "type": "logical",
+ "mode": "and",
+ "rules": [
+ {
+ "rule_set": "geosite-geolocation-!cn",
+ "invert": true
+ },
+ {
+ "rule_set": [
+ "geoip-cn",
+ "geosite-cn"
+ ]
+ }
+ ],
+ "outbound": "direct"
+ }
+ ],
+ "rule_set": [
+ {
+ "tag": "geosite-category-ads-all",
+ "type": "remote",
+ "format": "binary",
+ "url": "https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-category-ads-all.srs"
+ },
+ {
+ "type": "remote",
+ "tag": "geosite-geolocation-!cn",
+ "format": "binary",
+ "url": "https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-geolocation-!cn.srs"
+ },
+ {
+ "tag": "geosite-cn",
+ "type": "remote",
+ "format": "binary",
+ "url": "https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-cn.srs"
+ },
+ {
+ "tag": "geoip-cn",
+ "type": "remote",
+ "format": "binary",
+ "url": "https://cdn.jsdelivr.net/gh/SagerNet/sing-geoip@rule-set/geoip-cn.srs"
+ }
+ ],
+ "auto_detect_interface": true
+ },
+ "experimental": {
+ "cache_file": {
+ "enabled": true
+ },
+ "clash_api": {
+ "external_controller": "127.0.0.1:9090"
+ }
+ }
+}
diff --git a/tsconfig.json b/tsconfig.json
index 84b848afc..c11738503 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,4 +1,8 @@
{
+ "ts-node": {
+ "transpileOnly": true,
+ "files": true,
+ },
"compilerOptions": {
// https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping
"target": "ES2022",
@@ -12,16 +16,8 @@
"skipLibCheck": true,
"noEmit": true,
- "strict": true /* Enable all strict type-checking options. */,
/* Strict Type-Checking Options */
- // "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
- // "strictNullChecks": true /* Enable strict null checks. */,
- // "strictFunctionTypes": true /* Enable strict checking of function types. */,
- // "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
- // "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
- // "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
-
- /* Additional Checks */
+ "strict": true /* Enable all strict type-checking options. */,
"noUnusedLocals": false /* Report errors on unused locals. */,
"noUnusedParameters": true /* Report errors on unused parameters. */,
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,