From 71ff127a4cfbf0c7f0271746a1a3ddd55621c8de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 08:18:10 +0000 Subject: [PATCH] Deploy to GitHub pages --- 404.html | 33 +++ About/index.html | 33 +++ Docs/Start.html | 33 +++ Docs/index.html | 33 +++ PluginDocs/Basic/Example.html | 33 +++ PluginDocs/Basic/Format.html | 40 ++++ PluginDocs/Basic/Metadata.html | 76 +++++++ PluginDocs/Basic/Tips.html | 33 +++ PluginDocs/HelloWorld/CSharp.html | 37 ++++ PluginDocs/HelloWorld/Go.html | 179 ++++++++++++++++ PluginDocs/HelloWorld/Python.html | 199 +++++++++++++++++ PluginDocs/HelloWorld/Rust.html | 318 ++++++++++++++++++++++++++++ PluginDocs/Web/Back.html | 58 +++++ PluginDocs/Web/Interaction.html | 44 ++++ PluginDocs/Web/index.html | 172 +++++++++++++++ PluginDocs/index.html | 33 +++ PluginMarket/index.html | 33 +++ assets/404.html-ceb4942b.js | 1 + assets/404.html-f9875e7b.js | 1 + assets/Back.html-42e4d89e.js | 1 + assets/Back.html-df0fa5cb.js | 26 +++ assets/CSharp.html-388a67b2.js | 5 + assets/CSharp.html-3c53f8ae.js | 1 + assets/Example.html-4110fdf6.js | 1 + assets/Example.html-d5941944.js | 1 + assets/Format.html-acc722f4.js | 8 + assets/Format.html-f770cc78.js | 1 + assets/Go.html-3fa1af93.js | 147 +++++++++++++ assets/Go.html-4c263677.js | 1 + assets/Interaction.html-54fa1a8f.js | 12 ++ assets/Interaction.html-b7586d71.js | 1 + assets/Metadata.html-0350df2c.js | 44 ++++ assets/Metadata.html-aa88d8d2.js | 1 + assets/Python.html-0b3dfca9.js | 1 + assets/Python.html-e29369ba.js | 167 +++++++++++++++ assets/Rust.html-b1948268.js | 1 + assets/Rust.html-fd38a2dd.js | 286 +++++++++++++++++++++++++ assets/Start-2-98e843d2.js | 1 + assets/Start.html-50d99452.js | 1 + assets/Start.html-9d4161ee.js | 1 + assets/Tips.html-6b25d762.js | 1 + assets/Tips.html-fd8819f7.js | 1 + assets/app-542dabbe.js | 6 + assets/back-to-top-8efcbe56.svg | 1 + assets/framework-cc651620.js | 5 + assets/index-70769223.js | 1 + assets/index.html-103e28a1.js | 1 + assets/index.html-1f0059e4.js | 1 + assets/index.html-4f366004.js | 1 + assets/index.html-550593ad.js | 1 + assets/index.html-5ff51570.js | 1 + assets/index.html-7b9a0856.js | 1 + assets/index.html-86b4a8cc.js | 1 + assets/index.html-8704499c.js | 1 + assets/index.html-9e9e82fb.js | 1 + assets/index.html-d2bbbcfd.js | 1 + assets/index.html-db82fc2e.js | 1 + assets/index.html-ef97b19a.js | 140 ++++++++++++ assets/search-0782d0d1.svg | 1 + assets/style-0596657c.css | 1 + favicon.ico | Bin 0 -> 4683 bytes file/hl_plugin_python.zip | Bin 0 -> 4767 bytes file/hl_plugin_rust.zip | Bin 0 -> 4104 bytes img/PluginDocs/Example-1.png | Bin 0 -> 42846 bytes img/PluginDocs/Start-1.png | Bin 0 -> 50954 bytes img/PluginDocs/Start-2.png | Bin 0 -> 61174 bytes index.html | 33 +++ logo.svg | 21 ++ service-worker.js | 1 + workbox-d249b2c8.js | 1 + 70 files changed, 2321 insertions(+) create mode 100644 404.html create mode 100644 About/index.html create mode 100644 Docs/Start.html create mode 100644 Docs/index.html create mode 100644 PluginDocs/Basic/Example.html create mode 100644 PluginDocs/Basic/Format.html create mode 100644 PluginDocs/Basic/Metadata.html create mode 100644 PluginDocs/Basic/Tips.html create mode 100644 PluginDocs/HelloWorld/CSharp.html create mode 100644 PluginDocs/HelloWorld/Go.html create mode 100644 PluginDocs/HelloWorld/Python.html create mode 100644 PluginDocs/HelloWorld/Rust.html create mode 100644 PluginDocs/Web/Back.html create mode 100644 PluginDocs/Web/Interaction.html create mode 100644 PluginDocs/Web/index.html create mode 100644 PluginDocs/index.html create mode 100644 PluginMarket/index.html create mode 100644 assets/404.html-ceb4942b.js create mode 100644 assets/404.html-f9875e7b.js create mode 100644 assets/Back.html-42e4d89e.js create mode 100644 assets/Back.html-df0fa5cb.js create mode 100644 assets/CSharp.html-388a67b2.js create mode 100644 assets/CSharp.html-3c53f8ae.js create mode 100644 assets/Example.html-4110fdf6.js create mode 100644 assets/Example.html-d5941944.js create mode 100644 assets/Format.html-acc722f4.js create mode 100644 assets/Format.html-f770cc78.js create mode 100644 assets/Go.html-3fa1af93.js create mode 100644 assets/Go.html-4c263677.js create mode 100644 assets/Interaction.html-54fa1a8f.js create mode 100644 assets/Interaction.html-b7586d71.js create mode 100644 assets/Metadata.html-0350df2c.js create mode 100644 assets/Metadata.html-aa88d8d2.js create mode 100644 assets/Python.html-0b3dfca9.js create mode 100644 assets/Python.html-e29369ba.js create mode 100644 assets/Rust.html-b1948268.js create mode 100644 assets/Rust.html-fd38a2dd.js create mode 100644 assets/Start-2-98e843d2.js create mode 100644 assets/Start.html-50d99452.js create mode 100644 assets/Start.html-9d4161ee.js create mode 100644 assets/Tips.html-6b25d762.js create mode 100644 assets/Tips.html-fd8819f7.js create mode 100644 assets/app-542dabbe.js create mode 100644 assets/back-to-top-8efcbe56.svg create mode 100644 assets/framework-cc651620.js create mode 100644 assets/index-70769223.js create mode 100644 assets/index.html-103e28a1.js create mode 100644 assets/index.html-1f0059e4.js create mode 100644 assets/index.html-4f366004.js create mode 100644 assets/index.html-550593ad.js create mode 100644 assets/index.html-5ff51570.js create mode 100644 assets/index.html-7b9a0856.js create mode 100644 assets/index.html-86b4a8cc.js create mode 100644 assets/index.html-8704499c.js create mode 100644 assets/index.html-9e9e82fb.js create mode 100644 assets/index.html-d2bbbcfd.js create mode 100644 assets/index.html-db82fc2e.js create mode 100644 assets/index.html-ef97b19a.js create mode 100644 assets/search-0782d0d1.svg create mode 100644 assets/style-0596657c.css create mode 100644 favicon.ico create mode 100644 file/hl_plugin_python.zip create mode 100644 file/hl_plugin_rust.zip create mode 100644 img/PluginDocs/Example-1.png create mode 100644 img/PluginDocs/Start-1.png create mode 100644 img/PluginDocs/Start-2.png create mode 100644 index.html create mode 100644 logo.svg create mode 100644 service-worker.js create mode 100644 workbox-d249b2c8.js diff --git a/404.html b/404.html new file mode 100644 index 0000000..8216551 --- /dev/null +++ b/404.html @@ -0,0 +1,33 @@ + + +
+ + + + + +提示
使用文档正在建设中...
command 将会在后面的教程中填写,现在让我们打开 HiperLink,看看插件是否能被识别。
看起来很不错,但是需要注意:该插件还无法启动,因为我们没有编写插件的本体:程序。
现在请看向左侧的“你好,世界!”条目,寻找你所使用的语言。
插件的基本组织形式为文件夹
,一个文件夹即为一个插件。
插件所需要用到的一切都可以放进这个文件夹中。
现在,让我们制作一个名为StudyPlugin
的插件。
首先我们需要一个唯一ID
,这将会成为你插件的标志。在这里我们将StudyPlugin
的唯一ID设定为study_plugin
。
然后我们需要进行三步:
创建一个名为
study_plugin
的文件夹在文件夹中创建
metadata.json
文件将文件夹移动到HiperLink下的plugins文件夹(如果没有就新建)
目录在此时应该是这样的:
│ HiperLink.exe
+├─config
+├─libs
+├─logs
+└─plugins
+ ├─study_plugin
+ ├─metadata.json
+
此时你的插件还无法被识别,因为我们需要编写metadata.json的内容。
metadata.json 的基础模板如下:
{
+ "id": "",
+ "version": "",
+ "name": "",
+ "description": "",
+ "author": [""],
+ "link": "",
+ "dependencies": {
+ },
+ "command": "",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "",
+ "icon": "",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
id
string
ID(即插件 ID)是你插件的“身份证号”。
该值要与文件夹名称保持一致。
HiperLink 使用插件 ID 来区分不同的插件并检查插件间的依赖。 HiperLink 中加载的所有插件都应使用不同的插件 ID。如果新加载的插件具有与现有插件完全相同的插件 ID,则新插件将无法加载
请明智地选择你的插件 ID。强烈建议你在发布插件后不要再更改插件 ID
注意
小心可能的包名冲突。非常不推荐为你的插件取一个与标准库 / 第三方库名相同的 id,如 test,否则 HiperLink 很可能无法正确地加载你的插件
version
string
version 字段代表你的插件版本。它基本上采用了 语义化版本 的格式,不过限制较少,如你可以定义任意长度的版本号
name
string
你的插件名称——给你的插件起一个好听的名字吧
尽量不要使插件名称太长。你可以把插件的详细信息放在 description
之中
description
string
你的插件描述。在这里写下你的插件的功能总结吧
author
string[]
插件作者。该值为数组,可以容纳多个作者
link
string
你的插件的网址。你可以将其指向插件的 github 链接。它的值应为一个可访问的网址
dependencies
dist
该字段描述了你插件的依赖,这是一个例子:
"dependencies": {
+ "HiperLink": ">=0.2.6"
+}
+
键值为依赖的插件ID,HiperLink的ID就是HiperLink。右侧为版本运算符。
运算符详情可见此表格。
运算符 | 示例 | 解释 | 允许的值 | 不允许的值 |
---|---|---|---|---|
>= | >=1.2.3 | 目标版本应大于等于1.2.3 | 1.2.3,1.3.0 | 1.2.0 |
> | >1.2.3 | 目标版本应大于1.2.3 | 1.2.4,1.3.0 | 1.2.0,1.2.3 |
<= | <=1.2.3 | 目标版本应小于等于1.2.3 | 1.2.3,1.1.0 | 1.2.4,2.0.0 |
< | <1.2.3 | 目标版本应小于1.2.3 | 1.1.0 | 1.2.3,1.5 |
= | =1.2.3 | 目标版本应等于1.2.3 | 1.2.3 | 1.2,1.2.4 |
1.2.3 | 目标版本应等于1.2.3 | 1.2.3 | 1.2,1.2.4 | |
^ | ^1.2.3 | 目标版本应大于等于1.2.3,且目标版本的第一个版本分段等于运算版本。 | 1.2.3,1.2.4,1.4.4 | 1.0.0,2.0.0 |
~ | ~1.2.3 | 目标版本应大于等于1.2.3,且目标版本的第一个和第二个版本分段等于运算版本。 | 1.2.3,1.2.4 | 1.0.0,1.4.4,2.0.0 |
command
string
插件的运行指令,如./plugin
,python plugin.py
,java -jar plugin.jar
等。
args
string[]
插件的指令参数
type
string
gRPC
与netRPC
插件与HiperLink通信方式,目前可选的值只有gRPC
与netRPC
root
bool
插件是否需要使用管理员权限运行
color
string
插件图标的颜色,为十六进制颜色码(#FFFFFF)和RGB颜色码()。颜色的选择可以参考中国色
icon
string
插件图标,该值为mdi-
+ Material Design Icons上的所有可选图标代码,如mdi-user-arrow-left-outline
ui
bool
是否显示插件页面
configuration
bool
是否显示配置页面
在本案例中,metadata.json的内容应该是:
{
+ "id": "study_plugin",
+ "version": "0.0.1",
+ "name": "StudyPlugin",
+ "description": "一个基础教程插件",
+ "author": ["天机"],
+ "link": "hiper.ink",
+ "dependencies": {
+ },
+ "command": "",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "#93d5dc",
+ "icon": "mdi-book",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
请打开终端
,然后CD到study_plugin文件夹,输入以下命令生成工程。
cd \HiperLink\plugins\study_plugin
+dotnet new grpc -o StudyPlugin
+cd StudyPlugin
+dotnet dev-certs https --trust
+
让我们打开工程。
由于 HiperLink
就是由 Golang
编写的软件,使用 Golang
开发插件变得极度简单。
在本案例中,我们将会编写一个在加载插件时弹出Hello World!
弹窗的插件。
在 study_plugin
文件夹中进入终端,输入以下命令初始化工程并设置依赖:
go mod init study_plugin
+go get github.com/Hiper-Link/go-plugin
+go get github.com/Hiper-Link/plugin-libs/shared
+
新建 plugin.go
文件,在其中编写以下示例代码
package main
+
+import (
+ "github.com/Hiper-Link/go-plugin"
+ "github.com/Hiper-Link/plugin-libs/shared"
+)
+
+var Handshake = plugin.HandshakeConfig{
+ ProtocolVersion: 1,
+ MagicCookieKey: "study_plugin", // 此处为你的插件ID
+ MagicCookieValue: "Hello, HiperLink",
+}
+
+type API struct{}
+
+// 加载插件
+func (API) OnLoad(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 停用插件
+func (API) OnUnload(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 安装插件
+func (API) OnInstall(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 卸载插件
+func (API) OnUninstall(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// HL 启动
+func (API) OnStart(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// HL 停止
+func (API) OnStop(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 前后端交互
+func (API) Interaction(p string, function string) (string, error) {
+ return function, nil
+}
+
+func main() {
+ plugin.Serve(&plugin.ServeConfig{
+ HandshakeConfig: Handshake,
+ Plugins: map[string]plugin.Plugin{
+ "grpc": &shared.GRPCPlugin{Impl: &API{}},
+ },
+ NetworkType: "tcp",
+ GRPCServer: plugin.DefaultGRPCServer,
+ })
+}
+
你可以随意扩展本代码,HiperLink中的相关操作将会触发类似于OnLoad
的回调事件。
注意
OnInstall
与OnUninstall
暂不可用。
我们将会在import
中引入walk
,在OnLoad
中写入弹窗代码:
- 使用终端命令
go get github.com/lxn/walk
设置依赖- 在
OnLoad
下写入walk.MsgBox(nil, "StudyPlugin", "HelloWorld!", walk.MsgBoxIconInformation)
完整代码如下:
package main
+
+import (
+ "github.com/Hiper-Link/go-plugin"
+ "github.com/Hiper-Link/plugin-libs/shared"
+ "github.com/lxn/walk"
+)
+
+var Handshake = plugin.HandshakeConfig{
+ ProtocolVersion: 1,
+ MagicCookieKey: "study_plugin",
+ MagicCookieValue: "Hello, HiperLink",
+}
+
+type API struct{}
+
+// 加载插件
+func (API) OnLoad(p string) ([]byte, error) {
+ walk.MsgBox(nil, "StudyPlugin", "HelloWorld!", walk.MsgBoxIconInformation)
+ return nil, nil
+}
+
+// 停用插件
+func (API) OnUnload(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 安装插件
+func (API) OnInstall(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 卸载插件
+func (API) OnUninstall(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// HL 启动
+func (API) OnStart(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// HL 停止
+func (API) OnStop(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 前后端交互
+func (API) Interaction(p string, function string) (string, error) {
+ return function, nil
+}
+
+func main() {
+ plugin.Serve(&plugin.ServeConfig{
+ HandshakeConfig: Handshake,
+ Plugins: map[string]plugin.Plugin{
+ "grpc": &shared.GRPCPlugin{Impl: &API{}},
+ },
+ NetworkType: "tcp",
+ GRPCServer: plugin.DefaultGRPCServer,
+ })
+}
+
最后,我们编译该代码:
go build plugin.go
+
在study_plugin文件夹下将会生成一个名为plugin的二进制可执行文件。
让我们打开metadata.json
进行最后的编写:
{
+ "id": "study_plugin",
+ "version": "0.0.1",
+ "name": "StudyPlugin",
+ "description": "一个基础教程插件",
+ "author": ["天机"],
+ "link": "hiper.ink",
+ "dependencies": {
+ },
+ "command": "./plugin",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "#93d5dc",
+ "icon": "mdi-book",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
以上所有东西您都能改!我们写入了软件的启动命令./plugin
。
回到HiperLink,查看并开启我们的插件。
提示
笔者使用的Python版本为3.10.9
,因此一切操作均以此为准。
版本要求 Python 3.5
或更高版本。
在本案例中,我们将会编写一个在加载插件时弹出Hello World!
弹窗的插件。
让我们进入终端,输入以下命令来设置依赖:
pip install grpcio
+pip install grpcio-tools
+
Python插件开发需要模板,请点击此处下载模板,然后将模板解压至study_plugin
文件夹。
此时study_plugin
的内部文件结构如下:
└─study_plugin
+ health_pb2.py
+ health_pb2_grpc.py
+ hiperlink_pb2.py
+ hiperlink_pb2_grpc.py
+ metadata.json
+ plugin.py
+
我们开发的核心工作主要集中在plugin.py
,在此基础上你可以加入任何文件到此文件夹。
plugin.py
的内部代码如下:
# 本模板由天机Ceyase编写,基于MIT许可证开源
+import hiperlink_pb2
+import hiperlink_pb2_grpc
+import health_pb2_grpc
+import grpc
+import concurrent.futures as futures
+import sys
+import time
+import random
+import socket
+
+class HiperLinkServicer(hiperlink_pb2_grpc.PluginServicer):
+
+ # 加载插件
+ def OnLoad(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 停用插件
+ def OnUnload(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 安装插件
+ def OnInstall(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 卸载插件
+ def OnUninstall(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # HL 启动
+ def OnStart(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # HL 停止
+ def OnStop(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 前后端交互
+ def Interaction(self, request, context):
+ return hiperlink_pb2.InteractionResponse()
+
+def get_free_port():
+ while True:
+ port = random.randint(32768, 61000)
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if not (sock.connect_ex(('127.0.0.1', port)) == 0):
+ return port
+
+if __name__ == '__main__':
+ health = health_pb2_grpc.HealthServicer()
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ hiperlink_pb2_grpc.add_PluginServicer_to_server(HiperLinkServicer(), server)
+ health_pb2_grpc.add_HealthServicer_to_server(health, server)
+ port = get_free_port()
+ server.add_insecure_port(f'127.0.0.1:{port}')
+ server.start()
+ print(f"1|1|tcp|127.0.0.1:{port}|grpc")
+ sys.stdout.flush()
+ try:
+ while True:
+ time.sleep(60 * 60 * 24)
+ except KeyboardInterrupt:
+ server.stop(0)
+
你可以随意扩展本代码,HiperLink中的相关操作将会触发类似于OnLoad
的回调事件。
注意
OnInstall
与OnUninstall
暂不可用。
本教程中,我们将会引入winapi
,在OnLoad
中写入弹窗代码:
- 使用终端命令
pip install pywin32
设置依赖- 写入
import win32api,win32con
,在OnLoad
下写入win32api.MessageBox(0,"HelloWorld!","StudyPlugin",win32con.MB_OK)
完整代码如下:
# 本模板由天机Ceyase编写,基于MIT许可证开源
+import hiperlink_pb2
+import hiperlink_pb2_grpc
+import health_pb2_grpc
+import grpc
+import concurrent.futures as futures
+import sys
+import time
+import random
+import socket
+import win32api,win32con
+
+class HiperLinkServicer(hiperlink_pb2_grpc.PluginServicer):
+
+ # 加载插件
+ def OnLoad(self, request, context):
+ win32api.MessageBox(0,"HelloWorld!","StudyPlugin",win32con.MB_OK)
+ return hiperlink_pb2.EventsResponse()
+
+ # 停用插件
+ def OnUnload(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 安装插件
+ def OnInstall(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 卸载插件
+ def OnUninstall(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # HL 启动
+ def OnStart(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # HL 停止
+ def OnStop(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 前后端交互
+ def Interaction(self, request, context):
+ return hiperlink_pb2.InteractionResponse()
+
+def get_free_port():
+ while True:
+ port = random.randint(32768, 61000)
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if not (sock.connect_ex(('127.0.0.1', port)) == 0):
+ return port
+
+if __name__ == '__main__':
+ health = health_pb2_grpc.HealthServicer()
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ hiperlink_pb2_grpc.add_PluginServicer_to_server(HiperLinkServicer(), server)
+ health_pb2_grpc.add_HealthServicer_to_server(health, server)
+ port = get_free_port()
+ server.add_insecure_port(f'127.0.0.1:{port}')
+ server.start()
+ print(f"1|1|tcp|127.0.0.1:{port}|grpc")
+ sys.stdout.flush()
+ try:
+ while True:
+ time.sleep(60 * 60 * 24)
+ except KeyboardInterrupt:
+ server.stop(0)
+
让我们使用python plugin.py
命令运行此py文件。
如果出现了1|1|tcp|127.0.0.1:xxxxx|grpc
的输出,并且程序一直保持运行,那么该插件就可以进行下一步了。
为了照顾没有python
的用户,你应该打包此插件!
目前尚不支持pyinstaller
打包,我们推荐你使用cxfreeze
打包。
在study_plugin
文件夹下输入此终端命令:
pip install cx_Freeze
+cxfreeze plugin.py
+
等待片刻,study_plugin
文件夹下将会生成build
文件夹,将其中的可执行文件移动到study_plugin
文件夹(当然,你可以删除一些冗余文件)
最终study_plugin
文件夹的目录结构如下:
└─study_plugin
+ │ metadata.json
+ │ plugin.exe
+ │ plugin.py
+ │ python3.dll
+ │ python310.dll
+ └─lib
+
让我们打开metadata.json
进行最后的编写:
{
+ "id": "study_plugin",
+ "version": "0.0.1",
+ "name": "StudyPlugin",
+ "description": "一个基础教程插件",
+ "author": ["天机"],
+ "link": "hiper.ink",
+ "dependencies": {
+ },
+ "command": "./plugin",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "#93d5dc",
+ "icon": "mdi-book",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
以上所有东西您都能改!我们写入了软件的启动命令./plugin
。
回到HiperLink,查看并开启我们的插件。
提示
笔者使用的rustc版本为1.66.0
,因此一切操作均以此为准。
版本要求 Rust 1.39
或更高版本。
在本案例中,我们将会编写一个在加载插件时弹出Hello World!
弹窗的插件。
让我们进入终端,输入以下命令来设置依赖:
rustup update
+rustup component add rustfmt
+
Rust插件开发需要模板,请点击此处下载模板,然后将模板解压至study_plugin
文件夹。
此时study_plugin
的内部文件结构如下:
└─study_plugin
+ metadata.json
+ Cargo.toml
+ └─src
+ main.rs
+ proto.rs
+
我们开发的入口点在main.rs
,在此基础上你可以进行任何开发。
main.rs
的内部代码如下:
// 本模板由天机Ceyase编写,基于MIT许可证开源
+use tonic::{transport::Server, Request, Response, Status};
+use std::net::TcpListener;
+
+use hiper_link::plugin_server::{Plugin, PluginServer};
+use hiper_link::{EventsRequest, EventsResponse, InteractionRequest, InteractionResponse};
+
+pub mod hiper_link {
+ include!("proto.rs");
+}
+
+#[derive(Debug, Default)]
+pub struct API {}
+
+#[tonic::async_trait]
+impl Plugin for API {
+
+ // 加载插件
+ async fn on_load(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 停用插件
+ async fn on_unload(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 安装插件
+ async fn on_install(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 卸载插件
+ async fn on_uninstall(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // HL 启动
+ async fn on_start(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // HL 停止
+ async fn on_stop(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 前后端交互
+ async fn interaction(
+ &self,
+ _request: Request<InteractionRequest>,
+ ) -> Result<Response<InteractionResponse>, Status> {
+
+ let reply = hiper_link::InteractionResponse {value : "1".into()};
+ Ok(Response::new(reply))
+ }
+}
+
+fn listen_available_port() -> Option<TcpListener> {
+ for port in 32768..61000 {
+ match TcpListener::bind(("127.0.0.1", port)) {
+ Ok(l) => return Some(l),
+ _ => {}
+ }
+ }
+ None
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+
+ let addr_str = listen_available_port().unwrap().local_addr().unwrap().to_string();
+
+ let addr = addr_str.parse()?;
+ let plugin = API::default();
+
+ println!("1|1|tcp|{addr_str}|grpc");
+ Server::builder()
+ .add_service(PluginServer::new(plugin))
+ .serve(addr)
+ .await?;
+ Ok(())
+}
+
你可以随意扩展本代码,HiperLink中的相关操作将会触发类似于on_load
的回调事件。
注意
on_install
与on_uninstall
暂不可用。
提示
请记得在Cargo.toml
中更改您的项目名称!
本教程中,我们将会引入user32
,使用MessageBoxW
函数进行弹窗:
- 在
Cargo.toml
的最后一行添加user32-sys = "0.2.0"
- 写入
use user32::MessageBoxW;
,在on_load
下写入以下几行:
let lp_text: Vec<u16> = "Hello world!\0".encode_utf16().collect();
+let lp_caption: Vec<u16> = "StudyPlugin\0".encode_utf16().collect();
+
+unsafe {
+ MessageBoxW(
+ std::ptr::null_mut(),
+ lp_text.as_ptr(),
+ lp_caption.as_ptr(),
+ 0
+ );
+ }
+
完整代码如下:
// 本模板由天机Ceyase编写,基于MIT许可证开源
+use tonic::{transport::Server, Request, Response, Status};
+use std::net::TcpListener;
+
+use hiper_link::plugin_server::{Plugin, PluginServer};
+use hiper_link::{EventsRequest, EventsResponse, InteractionRequest, InteractionResponse};
+
+use user32::MessageBoxW;
+pub mod hiper_link {
+ include!("proto.rs");
+}
+
+#[derive(Debug, Default)]
+pub struct API {}
+
+#[tonic::async_trait]
+impl Plugin for API {
+
+ // 加载插件
+ async fn on_load(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ let lp_text: Vec<u16> = "Hello world!\0".encode_utf16().collect();
+ let lp_caption: Vec<u16> = "StudyPlugin\0".encode_utf16().collect();
+
+ unsafe {
+ MessageBoxW(
+ std::ptr::null_mut(),
+ lp_text.as_ptr(),
+ lp_caption.as_ptr(),
+ 0
+ );
+ }
+ Ok(Response::new(reply))
+ }
+
+ // 停用插件
+ async fn on_unload(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 安装插件
+ async fn on_install(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 卸载插件
+ async fn on_uninstall(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // HL 启动
+ async fn on_start(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // HL 停止
+ async fn on_stop(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 前后端交互
+ async fn interaction(
+ &self,
+ _request: Request<InteractionRequest>,
+ ) -> Result<Response<InteractionResponse>, Status> {
+
+ let reply = hiper_link::InteractionResponse {value : "1".into()};
+ Ok(Response::new(reply))
+ }
+}
+
+fn listen_available_port() -> Option<TcpListener> {
+ for port in 32768..61000 {
+ match TcpListener::bind(("127.0.0.1", port)) {
+ Ok(l) => return Some(l),
+ _ => {}
+ }
+ }
+ None
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+
+ let addr_str = listen_available_port().unwrap().local_addr().unwrap().to_string();
+
+ let addr = addr_str.parse()?;
+ let plugin = API::default();
+
+ println!("1|1|tcp|{addr_str}|grpc");
+ Server::builder()
+ .add_service(PluginServer::new(plugin))
+ .serve(addr)
+ .await?;
+ Ok(())
+}
+
让我们使用cargo run
命令运行此工程。
如果出现了1|1|tcp|127.0.0.1:xxxxx|grpc
的输出,并且程序一直保持运行,那么该插件就可以进行下一步了。
使用cargo build --release
命令打包工程。
等待片刻,\study_plugin\target\release
文件夹下将会生成可执行文件,将其中的可执行文件
重命名为plugin.exe
并移动到study_plugin
文件夹(当然,你可以删除一些冗余文件)
最终study_plugin
文件夹的目录结构如下:
└─study_plugin
+ │ src
+ │ target
+ │ Cargo.lock
+ │ Cargo.toml
+ │ metadata.json
+ │ plugin.exe
+ └─lib
+
让我们打开metadata.json
进行最后的编写:
{
+ "id": "study_plugin",
+ "version": "0.0.1",
+ "name": "StudyPlugin",
+ "description": "一个基础教程插件",
+ "author": ["天机"],
+ "link": "hiper.ink",
+ "dependencies": {
+ },
+ "command": "./plugin",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "#93d5dc",
+ "icon": "mdi-book",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
以上所有东西您都能改!我们写入了软件的启动命令./plugin
。
回到HiperLink,查看并开启我们的插件。
无论是使用哪种语言编写的插件,都存在有Interaction事件。
该事件接收了上文所阐述的"function"字段,依据此字段可以进行交互。
其中json_text为返回的JSON文本。
func (API) Interaction(p string, function string) (string, error) {
+ var json_text = "";
+ switch function {
+ case "xxx":
+ //todo
+ }
+ return json_text, nil
+}
+
async fn interaction(
+ &self,
+ _request: Request<InteractionRequest>,
+) -> Result<Response<InteractionResponse>, Status> {
+ let mut json_text = "".to_string();
+
+ match &function as &str{
+ "xxx" => {
+ // todo
+ },
+
+ _ => {}
+ }
+
+ let reply = hiper_link::InteractionResponse {value : json_text.into()};
+ Ok(Response::new(reply))
+}
+
前文的HTML
中可以加入JavaScript
,HiperLink
添加了 HLInteraction
方法来进行后端与前端的交互。
HLInteraction 用法如下
HLInteraction("插件ID","方法名")
+
使用案例:
<script type="text/javascript">
+ var PluginID = 'study_plugin'
+ function init() {
+ HLInteraction(PluginID, 'something').then((result) => {
+ const obj = JSON.parse(result)
+ // 其中obj即为方法返回的json对象。
+ })
+ }
+ window.onload = init()
+</script>
+
对于每个插件,在其文件夹下都有src
子文件夹,此文件夹内部有两个文件:index.html
与config.html
。
编写插件页面需要你有基本的HTML
与JavaScript
知识,HiperLink内置了Vuetify 框架,因此您可以直接开始!
以下是一个用于范例的index.html
页面代码:
<div class="v-container">
+ <div class="v-row">
+ <div class="v-col-sm-7 v-col-12">
+ <div class="v-card v-card--flat v-theme--light v-card--density-default v-card--variant-elevated" style="background-color: rgb(242, 245, 254); border-radius: 12px; margin-top: -8px;">
+ <div class="v-card-title" style="margin-top: 12px;">
+ <strong>这是一个卡片</strong>
+ <div class="v-card-text">
+ <div style="overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 7; -webkit-box-orient: vertical;">
+ <div class="v-input v-input--horizontal v-input--density-default v-text-field">
+ <div class="v-input__control">
+ <div class="v-field v-field--active v-field--has-background v-field--variant-filled v-theme--light" role="textbox" style="background-color: rgb(242, 245, 254);">
+ <div class="v-field__overlay">
+ </div>
+ <div class="v-field__loader">
+ <div class="v-progress-linear v-theme--light" role="progressbar" aria-hidden="true" aria-valuemin="0" aria-valuemax="100" style="height: 0px; --v-progress-linear-height:2px;">
+ <div class="v-progress-linear__background bg-info" style="width: 100%;">
+ </div>
+ <div class="v-progress-linear__indeterminate">
+ <div class="v-progress-linear__indeterminate long bg-info">
+ </div>
+ <div class="v-progress-linear__indeterminate short bg-info">
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="v-field__field" data-no-activator="">
+ <label class="v-label v-field-label v-field-label--floating" aria-hidden="true" for="input-887">这是一个输入框</label>
+ <input size="1" type="text" id="otherip" class="v-field__input">
+ </div>
+ <div class="v-field__outline">
+ </div>
+ </div>
+ </div>
+ <div class="v-input__details">
+ <div class="v-messages">
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="v-card-actions" style="margin-top: -24px;">
+ <div style="float: right;">
+ <button type="button" onclick="" class="v-btn v-theme--light text-info v-btn--density-default v-btn--size-default v-btn--variant-text" style="font-size: 16px;">
+ <span class="v-btn__overlay">
+ </span>
+ <span class="v-btn__underlay">
+ </span>
+ <span class="v-btn__content" data-no-activator="">一个小按钮</span>
+ </button>
+ </div>
+ </div>
+ <span class="v-card__underlay">
+ </span>
+ </div>
+ </div>
+ </div>
+ <div class="v-col-sm-5 v-col-12">
+ <div class="v-card v-card--flat v-theme--light v-card--density-default v-card--variant-elevated" style="background-color: rgb(242, 245, 254); border-radius: 12px; margin-top: -8px;">
+ <div class="v-card__loader">
+ <div class="v-progress-linear v-theme--light" role="progressbar" aria-hidden="true" aria-valuemin="0" aria-valuemax="100" style="height: 0px; --v-progress-linear-height:2px;">
+ <div class="v-progress-linear__background" style="width: 100%;">
+ </div>
+ <div class="v-progress-linear__indeterminate">
+ <div class="v-progress-linear__indeterminate long">
+ </div>
+ <div class="v-progress-linear__indeterminate short">
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="v-card-title" style="margin-top: 12px;">
+ <strong>这是另一个卡片</strong>
+ <div style="margin-top: 4px;font-size: 1px;">一些简单的注释,下面是一个列表</div>
+ </div>
+ <div class="v-card-text">
+ <div class="v-table v-theme--light v-table--density-compact">
+ <div class="v-table__wrapper">
+ <table>
+ <tbody>
+ <tr>
+ <td>1</td>
+ <td>
+ <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="version-rustdesk">1
+ <span class="v-chip__underlay"></span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td>11</td>
+ <td>
+ <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="ip">2
+ <span class="v-chip__underlay"></span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td>111</td>
+ <td>
+ <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="password">3
+ <span class="v-chip__underlay"></span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td>1111</td>
+ <td>
+ <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="password">4
+ <span class="v-chip__underlay"></span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td>1111</td>
+ <td>
+ <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="password">5
+ <span class="v-chip__underlay"></span>
+ </span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <span class="v-card__underlay">
+ </span>
+ </div>
+ <a class="v-btn v-btn--block v-theme--light v-btn--density-default rounded-xl v-btn--size-x-large v-btn--variant-tonal" style="color: rgb(106, 164, 255); caret-color: rgb(106, 164, 255); margin-top: 16px;" onclick="" id="actionButton">
+ <span class="v-btn__overlay">
+ </span>
+ <span class="v-btn__underlay">
+ </span>
+ <span class="v-btn__content" data-no-activator="">
+ <strong id="action">一个大按钮</strong>
+ </span>
+ </a>
+ </div>
+ </div>
+</div>
+
效果如下:
注意
HiperLink仍然在测试阶段,此文档可能随时变更。
HiperLink插件(以下简称插件)可以使用任何支持netRPC或gRPC通讯的语言编写。
我们建议你使用Golang
进行插件开发。
提示
net/rpc
只有Golang
支持,所以本文档会优先注重多语言支持的gRPC
库。
gRPC
在理论上支持C/C++
、C#
、Dart
、Go
、Java
、Kotlin
、Node.js
、Objective-C
、PHP
、Python
、Ruby
等语言。
HiperLink 需要支持多平台
,你所选用的语言应该尽可能的支持更多平台,因此Objective-C
,PHP
等选项被不幸的排除在外了。
如果你准备好了,那让我们开始吧!
无论是使用哪种语言编写的插件,都存在有Interaction事件。
该事件接收了上文所阐述的"function"字段,依据此字段可以进行交互。
其中json_text为返回的JSON文本。
func (API) Interaction(p string, function string) (string, error) {
+ var json_text = "";
+ switch function {
+ case "xxx":
+ //todo
+ }
+ return json_text, nil
+}
+
async fn interaction(
+ &self,
+ _request: Request<InteractionRequest>,
+) -> Result<Response<InteractionResponse>, Status> {
+ let mut json_text = "".to_string();
+
+ match &function as &str{
+ "xxx" => {
+ // todo
+ },
+
+ _ => {}
+ }
+
+ let reply = hiper_link::InteractionResponse {value : json_text.into()};
+ Ok(Response::new(reply))
+}
+
插件的基本组织形式为文件夹
,一个文件夹即为一个插件。
插件所需要用到的一切都可以放进这个文件夹中。
现在,让我们制作一个名为StudyPlugin
的插件。
首先我们需要一个唯一ID
,这将会成为你插件的标志。在这里我们将StudyPlugin
的唯一ID设定为study_plugin
。
然后我们需要进行三步:
创建一个名为
study_plugin
的文件夹在文件夹中创建
metadata.json
文件将文件夹移动到HiperLink下的plugins文件夹(如果没有就新建)
目录在此时应该是这样的:
│ HiperLink.exe
+├─config
+├─libs
+├─logs
+└─plugins
+ ├─study_plugin
+ ├─metadata.json
+
由于 HiperLink
就是由 Golang
编写的软件,使用 Golang
开发插件变得极度简单。
在本案例中,我们将会编写一个在加载插件时弹出Hello World!
弹窗的插件。
在 study_plugin
文件夹中进入终端,输入以下命令初始化工程并设置依赖:
go mod init study_plugin
+go get github.com/Hiper-Link/go-plugin
+go get github.com/Hiper-Link/plugin-libs/shared
+
新建 plugin.go
文件,在其中编写以下示例代码
package main
+
+import (
+ "github.com/Hiper-Link/go-plugin"
+ "github.com/Hiper-Link/plugin-libs/shared"
+)
+
+var Handshake = plugin.HandshakeConfig{
+ ProtocolVersion: 1,
+ MagicCookieKey: "study_plugin", // 此处为你的插件ID
+ MagicCookieValue: "Hello, HiperLink",
+}
+
+type API struct{}
+
+// 加载插件
+func (API) OnLoad(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 停用插件
+func (API) OnUnload(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 安装插件
+func (API) OnInstall(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 卸载插件
+func (API) OnUninstall(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// HL 启动
+func (API) OnStart(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// HL 停止
+func (API) OnStop(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 前后端交互
+func (API) Interaction(p string, function string) (string, error) {
+ return function, nil
+}
+
+func main() {
+ plugin.Serve(&plugin.ServeConfig{
+ HandshakeConfig: Handshake,
+ Plugins: map[string]plugin.Plugin{
+ "grpc": &shared.GRPCPlugin{Impl: &API{}},
+ },
+ NetworkType: "tcp",
+ GRPCServer: plugin.DefaultGRPCServer,
+ })
+}
+
你可以随意扩展本代码,HiperLink中的相关操作将会触发类似于OnLoad
的回调事件。
注意
OnInstall
与OnUninstall
暂不可用。
我们将会在import
中引入walk
,在OnLoad
中写入弹窗代码:
- 使用终端命令
go get github.com/lxn/walk
设置依赖- 在
OnLoad
下写入walk.MsgBox(nil, "StudyPlugin", "HelloWorld!", walk.MsgBoxIconInformation)
完整代码如下:
package main
+
+import (
+ "github.com/Hiper-Link/go-plugin"
+ "github.com/Hiper-Link/plugin-libs/shared"
+ "github.com/lxn/walk"
+)
+
+var Handshake = plugin.HandshakeConfig{
+ ProtocolVersion: 1,
+ MagicCookieKey: "study_plugin",
+ MagicCookieValue: "Hello, HiperLink",
+}
+
+type API struct{}
+
+// 加载插件
+func (API) OnLoad(p string) ([]byte, error) {
+ walk.MsgBox(nil, "StudyPlugin", "HelloWorld!", walk.MsgBoxIconInformation)
+ return nil, nil
+}
+
+// 停用插件
+func (API) OnUnload(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 安装插件
+func (API) OnInstall(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 卸载插件
+func (API) OnUninstall(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// HL 启动
+func (API) OnStart(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// HL 停止
+func (API) OnStop(p string) ([]byte, error) {
+ return nil, nil
+}
+
+// 前后端交互
+func (API) Interaction(p string, function string) (string, error) {
+ return function, nil
+}
+
+func main() {
+ plugin.Serve(&plugin.ServeConfig{
+ HandshakeConfig: Handshake,
+ Plugins: map[string]plugin.Plugin{
+ "grpc": &shared.GRPCPlugin{Impl: &API{}},
+ },
+ NetworkType: "tcp",
+ GRPCServer: plugin.DefaultGRPCServer,
+ })
+}
+
最后,我们编译该代码:
go build plugin.go
+
在study_plugin文件夹下将会生成一个名为plugin的二进制可执行文件。
让我们打开metadata.json
进行最后的编写:
{
+ "id": "study_plugin",
+ "version": "0.0.1",
+ "name": "StudyPlugin",
+ "description": "一个基础教程插件",
+ "author": ["天机"],
+ "link": "hiper.ink",
+ "dependencies": {
+ },
+ "command": "./plugin",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "#93d5dc",
+ "icon": "mdi-book",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
以上所有东西您都能改!我们写入了软件的启动命令./plugin
。
回到HiperLink,查看并开启我们的插件。
',21),e=[c];function u(l,i){return a(),t("div",null,e)}const d=s(o,[["render",u],["__file","Go.html.vue"]]);export{d as default}; diff --git a/assets/Go.html-4c263677.js b/assets/Go.html-4c263677.js new file mode 100644 index 0000000..fc8725e --- /dev/null +++ b/assets/Go.html-4c263677.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-391dc22c","path":"/PluginDocs/HelloWorld/Go.html","title":"Golang","lang":"zh-CN","frontmatter":{},"headers":[],"git":{"updatedTime":1675256121000,"contributors":[{"name":"Harry-zklcdc","email":"1269158832@qq.com","commits":2},{"name":"Ceyase","email":"jjcyf@foxmail.com","commits":1}]},"filePathRelative":"PluginDocs/HelloWorld/Go.md"}');export{e as data}; diff --git a/assets/Interaction.html-54fa1a8f.js b/assets/Interaction.html-54fa1a8f.js new file mode 100644 index 0000000..4e39b4e --- /dev/null +++ b/assets/Interaction.html-54fa1a8f.js @@ -0,0 +1,12 @@ +import{_ as n,p as a,q as s,a1 as t}from"./framework-cc651620.js";const p={},o=t(`前文的HTML
中可以加入JavaScript
,HiperLink
添加了 HLInteraction
方法来进行后端与前端的交互。
HLInteraction 用法如下
HLInteraction("插件ID","方法名")
+
使用案例:
<script type="text/javascript">
+ var PluginID = 'study_plugin'
+ function init() {
+ HLInteraction(PluginID, 'something').then((result) => {
+ const obj = JSON.parse(result)
+ // 其中obj即为方法返回的json对象。
+ })
+ }
+ window.onload = init()
+</script>
+
此时你的插件还无法被识别,因为我们需要编写metadata.json的内容。
metadata.json 的基础模板如下:
{
+ "id": "",
+ "version": "",
+ "name": "",
+ "description": "",
+ "author": [""],
+ "link": "",
+ "dependencies": {
+ },
+ "command": "",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "",
+ "icon": "",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
id
string
ID(即插件 ID)是你插件的“身份证号”。
该值要与文件夹名称保持一致。
HiperLink 使用插件 ID 来区分不同的插件并检查插件间的依赖。 HiperLink 中加载的所有插件都应使用不同的插件 ID。如果新加载的插件具有与现有插件完全相同的插件 ID,则新插件将无法加载
请明智地选择你的插件 ID。强烈建议你在发布插件后不要再更改插件 ID
注意
小心可能的包名冲突。非常不推荐为你的插件取一个与标准库 / 第三方库名相同的 id,如 test,否则 HiperLink 很可能无法正确地加载你的插件
version
string
name
string
你的插件名称——给你的插件起一个好听的名字吧
尽量不要使插件名称太长。你可以把插件的详细信息放在 description
之中
description
string
你的插件描述。在这里写下你的插件的功能总结吧
author
string[]
插件作者。该值为数组,可以容纳多个作者
link
string
你的插件的网址。你可以将其指向插件的 github 链接。它的值应为一个可访问的网址
dependencies
dist
该字段描述了你插件的依赖,这是一个例子:
"dependencies": {
+ "HiperLink": ">=0.2.6"
+}
+
键值为依赖的插件ID,HiperLink的ID就是HiperLink。右侧为版本运算符。
运算符详情可见此表格。
运算符 | 示例 | 解释 | 允许的值 | 不允许的值 |
---|---|---|---|---|
>= | >=1.2.3 | 目标版本应大于等于1.2.3 | 1.2.3,1.3.0 | 1.2.0 |
> | >1.2.3 | 目标版本应大于1.2.3 | 1.2.4,1.3.0 | 1.2.0,1.2.3 |
<= | <=1.2.3 | 目标版本应小于等于1.2.3 | 1.2.3,1.1.0 | 1.2.4,2.0.0 |
< | <1.2.3 | 目标版本应小于1.2.3 | 1.1.0 | 1.2.3,1.5 |
= | =1.2.3 | 目标版本应等于1.2.3 | 1.2.3 | 1.2,1.2.4 |
1.2.3 | 目标版本应等于1.2.3 | 1.2.3 | 1.2,1.2.4 | |
^ | ^1.2.3 | 目标版本应大于等于1.2.3,且目标版本的第一个版本分段等于运算版本。 | 1.2.3,1.2.4,1.4.4 | 1.0.0,2.0.0 |
~ | ~1.2.3 | 目标版本应大于等于1.2.3,且目标版本的第一个和第二个版本分段等于运算版本。 | 1.2.3,1.2.4 | 1.0.0,1.4.4,2.0.0 |
command
string
插件的运行指令,如./plugin
,python plugin.py
,java -jar plugin.jar
等。
args
string[]
插件的指令参数
type
string
gRPC
与netRPC
插件与HiperLink通信方式,目前可选的值只有gRPC
与netRPC
root
bool
插件是否需要使用管理员权限运行
color
string
ui
bool
是否显示插件页面
configuration
bool
是否显示配置页面
在本案例中,metadata.json的内容应该是:
{
+ "id": "study_plugin",
+ "version": "0.0.1",
+ "name": "StudyPlugin",
+ "description": "一个基础教程插件",
+ "author": ["天机"],
+ "link": "hiper.ink",
+ "dependencies": {
+ },
+ "command": "",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "#93d5dc",
+ "icon": "mdi-book",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
提示
笔者使用的Python版本为3.10.9
,因此一切操作均以此为准。
版本要求 Python 3.5
或更高版本。
在本案例中,我们将会编写一个在加载插件时弹出Hello World!
弹窗的插件。
让我们进入终端,输入以下命令来设置依赖:
pip install grpcio
+pip install grpcio-tools
+
Python插件开发需要模板,请点击此处下载模板,然后将模板解压至study_plugin
文件夹。
此时study_plugin
的内部文件结构如下:
└─study_plugin
+ health_pb2.py
+ health_pb2_grpc.py
+ hiperlink_pb2.py
+ hiperlink_pb2_grpc.py
+ metadata.json
+ plugin.py
+
我们开发的核心工作主要集中在plugin.py
,在此基础上你可以加入任何文件到此文件夹。
plugin.py
的内部代码如下:
# 本模板由天机Ceyase编写,基于MIT许可证开源
+import hiperlink_pb2
+import hiperlink_pb2_grpc
+import health_pb2_grpc
+import grpc
+import concurrent.futures as futures
+import sys
+import time
+import random
+import socket
+
+class HiperLinkServicer(hiperlink_pb2_grpc.PluginServicer):
+
+ # 加载插件
+ def OnLoad(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 停用插件
+ def OnUnload(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 安装插件
+ def OnInstall(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 卸载插件
+ def OnUninstall(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # HL 启动
+ def OnStart(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # HL 停止
+ def OnStop(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 前后端交互
+ def Interaction(self, request, context):
+ return hiperlink_pb2.InteractionResponse()
+
+def get_free_port():
+ while True:
+ port = random.randint(32768, 61000)
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if not (sock.connect_ex(('127.0.0.1', port)) == 0):
+ return port
+
+if __name__ == '__main__':
+ health = health_pb2_grpc.HealthServicer()
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ hiperlink_pb2_grpc.add_PluginServicer_to_server(HiperLinkServicer(), server)
+ health_pb2_grpc.add_HealthServicer_to_server(health, server)
+ port = get_free_port()
+ server.add_insecure_port(f'127.0.0.1:{port}')
+ server.start()
+ print(f"1|1|tcp|127.0.0.1:{port}|grpc")
+ sys.stdout.flush()
+ try:
+ while True:
+ time.sleep(60 * 60 * 24)
+ except KeyboardInterrupt:
+ server.stop(0)
+
你可以随意扩展本代码,HiperLink中的相关操作将会触发类似于OnLoad
的回调事件。
注意
OnInstall
与OnUninstall
暂不可用。
本教程中,我们将会引入winapi
,在OnLoad
中写入弹窗代码:
- 使用终端命令
pip install pywin32
设置依赖- 写入
import win32api,win32con
,在OnLoad
下写入win32api.MessageBox(0,"HelloWorld!","StudyPlugin",win32con.MB_OK)
完整代码如下:
# 本模板由天机Ceyase编写,基于MIT许可证开源
+import hiperlink_pb2
+import hiperlink_pb2_grpc
+import health_pb2_grpc
+import grpc
+import concurrent.futures as futures
+import sys
+import time
+import random
+import socket
+import win32api,win32con
+
+class HiperLinkServicer(hiperlink_pb2_grpc.PluginServicer):
+
+ # 加载插件
+ def OnLoad(self, request, context):
+ win32api.MessageBox(0,"HelloWorld!","StudyPlugin",win32con.MB_OK)
+ return hiperlink_pb2.EventsResponse()
+
+ # 停用插件
+ def OnUnload(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 安装插件
+ def OnInstall(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 卸载插件
+ def OnUninstall(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # HL 启动
+ def OnStart(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # HL 停止
+ def OnStop(self, request, context):
+ return hiperlink_pb2.EventsResponse()
+
+ # 前后端交互
+ def Interaction(self, request, context):
+ return hiperlink_pb2.InteractionResponse()
+
+def get_free_port():
+ while True:
+ port = random.randint(32768, 61000)
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if not (sock.connect_ex(('127.0.0.1', port)) == 0):
+ return port
+
+if __name__ == '__main__':
+ health = health_pb2_grpc.HealthServicer()
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ hiperlink_pb2_grpc.add_PluginServicer_to_server(HiperLinkServicer(), server)
+ health_pb2_grpc.add_HealthServicer_to_server(health, server)
+ port = get_free_port()
+ server.add_insecure_port(f'127.0.0.1:{port}')
+ server.start()
+ print(f"1|1|tcp|127.0.0.1:{port}|grpc")
+ sys.stdout.flush()
+ try:
+ while True:
+ time.sleep(60 * 60 * 24)
+ except KeyboardInterrupt:
+ server.stop(0)
+
让我们使用python plugin.py
命令运行此py文件。
如果出现了1|1|tcp|127.0.0.1:xxxxx|grpc
的输出,并且程序一直保持运行,那么该插件就可以进行下一步了。
为了照顾没有python
的用户,你应该打包此插件!
目前尚不支持pyinstaller
打包,我们推荐你使用cxfreeze
打包。
在study_plugin
文件夹下输入此终端命令:
pip install cx_Freeze
+cxfreeze plugin.py
+
等待片刻,study_plugin
文件夹下将会生成build
文件夹,将其中的可执行文件移动到study_plugin
文件夹(当然,你可以删除一些冗余文件)
最终study_plugin
文件夹的目录结构如下:
└─study_plugin
+ │ metadata.json
+ │ plugin.exe
+ │ plugin.py
+ │ python3.dll
+ │ python310.dll
+ └─lib
+
让我们打开metadata.json
进行最后的编写:
{
+ "id": "study_plugin",
+ "version": "0.0.1",
+ "name": "StudyPlugin",
+ "description": "一个基础教程插件",
+ "author": ["天机"],
+ "link": "hiper.ink",
+ "dependencies": {
+ },
+ "command": "./plugin",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "#93d5dc",
+ "icon": "mdi-book",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
以上所有东西您都能改!我们写入了软件的启动命令./plugin
。
回到HiperLink,查看并开启我们的插件。
',31),c=[e];function u(l,k){return a(),p("div",null,c)}const d=s(o,[["render",u],["__file","Python.html.vue"]]);export{d as default}; diff --git a/assets/Rust.html-b1948268.js b/assets/Rust.html-b1948268.js new file mode 100644 index 0000000..84793c6 --- /dev/null +++ b/assets/Rust.html-b1948268.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-26ef11a4","path":"/PluginDocs/HelloWorld/Rust.html","title":"Rust","lang":"zh-CN","frontmatter":{},"headers":[],"git":{"updatedTime":1675256121000,"contributors":[{"name":"Ceyase","email":"jjcyf@foxmail.com","commits":2}]},"filePathRelative":"PluginDocs/HelloWorld/Rust.md"}');export{t as data}; diff --git a/assets/Rust.html-fd38a2dd.js b/assets/Rust.html-fd38a2dd.js new file mode 100644 index 0000000..9cf707c --- /dev/null +++ b/assets/Rust.html-fd38a2dd.js @@ -0,0 +1,286 @@ +import{_ as n}from"./Start-2-98e843d2.js";import{_ as s,p as a,q as p,a1 as t}from"./framework-cc651620.js";const o={},e=t(`提示
笔者使用的rustc版本为1.66.0
,因此一切操作均以此为准。
版本要求 Rust 1.39
或更高版本。
在本案例中,我们将会编写一个在加载插件时弹出Hello World!
弹窗的插件。
让我们进入终端,输入以下命令来设置依赖:
rustup update
+rustup component add rustfmt
+
Rust插件开发需要模板,请点击此处下载模板,然后将模板解压至study_plugin
文件夹。
此时study_plugin
的内部文件结构如下:
└─study_plugin
+ metadata.json
+ Cargo.toml
+ └─src
+ main.rs
+ proto.rs
+
我们开发的入口点在main.rs
,在此基础上你可以进行任何开发。
main.rs
的内部代码如下:
// 本模板由天机Ceyase编写,基于MIT许可证开源
+use tonic::{transport::Server, Request, Response, Status};
+use std::net::TcpListener;
+
+use hiper_link::plugin_server::{Plugin, PluginServer};
+use hiper_link::{EventsRequest, EventsResponse, InteractionRequest, InteractionResponse};
+
+pub mod hiper_link {
+ include!("proto.rs");
+}
+
+#[derive(Debug, Default)]
+pub struct API {}
+
+#[tonic::async_trait]
+impl Plugin for API {
+
+ // 加载插件
+ async fn on_load(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 停用插件
+ async fn on_unload(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 安装插件
+ async fn on_install(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 卸载插件
+ async fn on_uninstall(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // HL 启动
+ async fn on_start(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // HL 停止
+ async fn on_stop(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 前后端交互
+ async fn interaction(
+ &self,
+ _request: Request<InteractionRequest>,
+ ) -> Result<Response<InteractionResponse>, Status> {
+
+ let reply = hiper_link::InteractionResponse {value : "1".into()};
+ Ok(Response::new(reply))
+ }
+}
+
+fn listen_available_port() -> Option<TcpListener> {
+ for port in 32768..61000 {
+ match TcpListener::bind(("127.0.0.1", port)) {
+ Ok(l) => return Some(l),
+ _ => {}
+ }
+ }
+ None
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+
+ let addr_str = listen_available_port().unwrap().local_addr().unwrap().to_string();
+
+ let addr = addr_str.parse()?;
+ let plugin = API::default();
+
+ println!("1|1|tcp|{addr_str}|grpc");
+ Server::builder()
+ .add_service(PluginServer::new(plugin))
+ .serve(addr)
+ .await?;
+ Ok(())
+}
+
你可以随意扩展本代码,HiperLink中的相关操作将会触发类似于on_load
的回调事件。
注意
on_install
与on_uninstall
暂不可用。
提示
请记得在Cargo.toml
中更改您的项目名称!
本教程中,我们将会引入user32
,使用MessageBoxW
函数进行弹窗:
- 在
Cargo.toml
的最后一行添加user32-sys = "0.2.0"
- 写入
use user32::MessageBoxW;
,在on_load
下写入以下几行:
let lp_text: Vec<u16> = "Hello world!\\0".encode_utf16().collect();
+let lp_caption: Vec<u16> = "StudyPlugin\\0".encode_utf16().collect();
+
+unsafe {
+ MessageBoxW(
+ std::ptr::null_mut(),
+ lp_text.as_ptr(),
+ lp_caption.as_ptr(),
+ 0
+ );
+ }
+
完整代码如下:
// 本模板由天机Ceyase编写,基于MIT许可证开源
+use tonic::{transport::Server, Request, Response, Status};
+use std::net::TcpListener;
+
+use hiper_link::plugin_server::{Plugin, PluginServer};
+use hiper_link::{EventsRequest, EventsResponse, InteractionRequest, InteractionResponse};
+
+use user32::MessageBoxW;
+pub mod hiper_link {
+ include!("proto.rs");
+}
+
+#[derive(Debug, Default)]
+pub struct API {}
+
+#[tonic::async_trait]
+impl Plugin for API {
+
+ // 加载插件
+ async fn on_load(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ let lp_text: Vec<u16> = "Hello world!\\0".encode_utf16().collect();
+ let lp_caption: Vec<u16> = "StudyPlugin\\0".encode_utf16().collect();
+
+ unsafe {
+ MessageBoxW(
+ std::ptr::null_mut(),
+ lp_text.as_ptr(),
+ lp_caption.as_ptr(),
+ 0
+ );
+ }
+ Ok(Response::new(reply))
+ }
+
+ // 停用插件
+ async fn on_unload(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 安装插件
+ async fn on_install(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 卸载插件
+ async fn on_uninstall(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // HL 启动
+ async fn on_start(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // HL 停止
+ async fn on_stop(
+ &self,
+ _request: Request<EventsRequest>,
+ ) -> Result<Response<EventsResponse>, Status> {
+ let reply = hiper_link::EventsResponse {value : "1".into()};
+
+ Ok(Response::new(reply))
+ }
+
+ // 前后端交互
+ async fn interaction(
+ &self,
+ _request: Request<InteractionRequest>,
+ ) -> Result<Response<InteractionResponse>, Status> {
+
+ let reply = hiper_link::InteractionResponse {value : "1".into()};
+ Ok(Response::new(reply))
+ }
+}
+
+fn listen_available_port() -> Option<TcpListener> {
+ for port in 32768..61000 {
+ match TcpListener::bind(("127.0.0.1", port)) {
+ Ok(l) => return Some(l),
+ _ => {}
+ }
+ }
+ None
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+
+ let addr_str = listen_available_port().unwrap().local_addr().unwrap().to_string();
+
+ let addr = addr_str.parse()?;
+ let plugin = API::default();
+
+ println!("1|1|tcp|{addr_str}|grpc");
+ Server::builder()
+ .add_service(PluginServer::new(plugin))
+ .serve(addr)
+ .await?;
+ Ok(())
+}
+
让我们使用cargo run
命令运行此工程。
如果出现了1|1|tcp|127.0.0.1:xxxxx|grpc
的输出,并且程序一直保持运行,那么该插件就可以进行下一步了。
使用cargo build --release
命令打包工程。
等待片刻,\\study_plugin\\target\\release
文件夹下将会生成可执行文件,将其中的可执行文件
重命名为plugin.exe
并移动到study_plugin
文件夹(当然,你可以删除一些冗余文件)
最终study_plugin
文件夹的目录结构如下:
└─study_plugin
+ │ src
+ │ target
+ │ Cargo.lock
+ │ Cargo.toml
+ │ metadata.json
+ │ plugin.exe
+ └─lib
+
让我们打开metadata.json
进行最后的编写:
{
+ "id": "study_plugin",
+ "version": "0.0.1",
+ "name": "StudyPlugin",
+ "description": "一个基础教程插件",
+ "author": ["天机"],
+ "link": "hiper.ink",
+ "dependencies": {
+ },
+ "command": "./plugin",
+ "args": [],
+ "type": "gRPC",
+ "root": false,
+ "color": "#93d5dc",
+ "icon": "mdi-book",
+ "frontend": {
+ "ui": true,
+ "configuration": true
+ }
+}
+
以上所有东西您都能改!我们写入了软件的启动命令./plugin
。
回到HiperLink,查看并开启我们的插件。
',30),c=[e];function l(u,k){return a(),p("div",null,c)}const d=s(o,[["render",l],["__file","Rust.html.vue"]]);export{d as default}; diff --git a/assets/Start-2-98e843d2.js b/assets/Start-2-98e843d2.js new file mode 100644 index 0000000..dfe116a --- /dev/null +++ b/assets/Start-2-98e843d2.js @@ -0,0 +1 @@ +const t="/img/PluginDocs/Start-2.png";export{t as _}; diff --git a/assets/Start.html-50d99452.js b/assets/Start.html-50d99452.js new file mode 100644 index 0000000..5b863d2 --- /dev/null +++ b/assets/Start.html-50d99452.js @@ -0,0 +1 @@ +import{_ as t,p as a,q as s,R as e,t as c}from"./framework-cc651620.js";const o={},n=e("h1",{id:"📖-快速上手",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#📖-快速上手","aria-hidden":"true"},"#"),c(" 📖 快速上手")],-1),r=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"提示"),e("p",null,"使用文档正在建设中...")],-1),_=[n,r];function i(d,l){return a(),s("div",null,_)}const u=t(o,[["render",i],["__file","Start.html.vue"]]);export{u as default}; diff --git a/assets/Start.html-9d4161ee.js b/assets/Start.html-9d4161ee.js new file mode 100644 index 0000000..bc7b04f --- /dev/null +++ b/assets/Start.html-9d4161ee.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-791cb41c","path":"/Docs/Start.html","title":"📖 快速上手","lang":"zh-CN","frontmatter":{},"headers":[],"git":{"updatedTime":1673158677000,"contributors":[{"name":"Harry-zklcdc","email":"1269158832@qq.com","commits":1}]},"filePathRelative":"Docs/Start.md"}');export{t as data}; diff --git a/assets/Tips.html-6b25d762.js b/assets/Tips.html-6b25d762.js new file mode 100644 index 0000000..38c4de5 --- /dev/null +++ b/assets/Tips.html-6b25d762.js @@ -0,0 +1 @@ +import{_ as s,M as r,p as i,q as a,R as e,t,N as o}from"./framework-cc651620.js";const c={},l=e("h1",{id:"一些提示",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#一些提示","aria-hidden":"true"},"#"),t(" 一些提示")],-1),p={class:"custom-container tip"},_=e("p",{class:"custom-container-title"},"提示",-1),h=e("p",null,[t("如果您是 "),e("code",null,"Golang"),t(" 的使用者,我们推荐您下载插件模板:")],-1),d={href:"https://gitee.com/HiperLink/example-plugins",target:"_blank",rel:"noopener noreferrer"},u={href:"https://github.com/Hiper-Link/example-plugins",target:"_blank",rel:"noopener noreferrer"};function m(f,g){const n=r("ExternalLinkIcon");return i(),a("div",null,[l,e("div",p,[_,h,e("p",null,[t("Gitee: "),e("a",d,[t("https://gitee.com/HiperLink/example-plugins"),o(n)])]),e("p",null,[t("Github: "),e("a",u,[t("https://github.com/Hiper-Link/example-plugins"),o(n)])])])])}const k=s(c,[["render",m],["__file","Tips.html.vue"]]);export{k as default}; diff --git a/assets/Tips.html-fd8819f7.js b/assets/Tips.html-fd8819f7.js new file mode 100644 index 0000000..de01be1 --- /dev/null +++ b/assets/Tips.html-fd8819f7.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-d3fda4d0","path":"/PluginDocs/Basic/Tips.html","title":"一些提示","lang":"zh-CN","frontmatter":{},"headers":[],"git":{"updatedTime":1673830380000,"contributors":[{"name":"Harry-zklcdc","email":"1269158832@qq.com","commits":1}]},"filePathRelative":"PluginDocs/Basic/Tips.md"}');export{t as data}; diff --git a/assets/app-542dabbe.js b/assets/app-542dabbe.js new file mode 100644 index 0000000..bfb4b0b --- /dev/null +++ b/assets/app-542dabbe.js @@ -0,0 +1,6 @@ +import{d as q,r as C,a as go,b as _o,c as I,i as oe,e as Re,f as bo,g as Ot,o as Z,h,j as P,k as re,l as Pe,m as xt,u as he,n as Qe,p,q as b,s as A,t as ye,v as V,w as ne,x as It,_ as z,y as yo,z as m,A as we,B as wo,C as Lo,D as ko,E as Ye,F as Eo,G as Po,H as $t,I as Ne,J as So,K as Je,L as ve,M as ce,N as R,O as ee,P as me,Q as M,R as $,S as ze,T as U,U as Q,V as lt,W as Do,X as To,Y as Be,Z as Ie,$ as $e,a0 as Ct,a1 as Oo,a2 as xo,a3 as Io,a4 as $o,a5 as Co,a6 as Ao,a7 as Ho}from"./framework-cc651620.js";const Ro="modulepreload",No=function(e){return"/"+e},it={},E=function(t,o,n){if(!o||o.length===0)return t();const r=document.getElementsByTagName("link");return Promise.all(o.map(s=>{if(s=No(s),s in it)return;it[s]=!0;const l=s.endsWith(".css"),a=l?'[rel="stylesheet"]':"";if(!!n)for(let u=r.length-1;u>=0;u--){const v=r[u];if(v.href===s&&(!l||v.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${s}"]${a}`))return;const c=document.createElement("link");if(c.rel=l?"stylesheet":Ro,l||(c.as="script",c.crossOrigin=""),c.href=s,document.head.appendChild(c),l)return new Promise((u,v)=>{c.addEventListener("load",u),c.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${s}`)))})})).then(()=>t())},zo={"v-8daa1a0e":()=>E(()=>import("./index.html-8704499c.js"),[]).then(({data:e})=>e),"v-3e214e9b":()=>E(()=>import("./index.html-d2bbbcfd.js"),[]).then(({data:e})=>e),"v-6bc6c5b0":()=>E(()=>import("./index.html-db82fc2e.js"),[]).then(({data:e})=>e),"v-12b535db":()=>E(()=>import("./index.html-4f366004.js"),[]).then(({data:e})=>e),"v-791cb41c":()=>E(()=>import("./Start.html-9d4161ee.js"),[]).then(({data:e})=>e),"v-7a6ec647":()=>E(()=>import("./index.html-103e28a1.js"),[]).then(({data:e})=>e),"v-2dc44d58":()=>E(()=>import("./Example.html-d5941944.js"),[]).then(({data:e})=>e),"v-03604679":()=>E(()=>import("./Format.html-f770cc78.js"),[]).then(({data:e})=>e),"v-09a21481":()=>E(()=>import("./Metadata.html-aa88d8d2.js"),[]).then(({data:e})=>e),"v-d3fda4d0":()=>E(()=>import("./Tips.html-fd8819f7.js"),[]).then(({data:e})=>e),"v-792a752a":()=>E(()=>import("./CSharp.html-3c53f8ae.js"),[]).then(({data:e})=>e),"v-391dc22c":()=>E(()=>import("./Go.html-4c263677.js"),[]).then(({data:e})=>e),"v-83a0a214":()=>E(()=>import("./Python.html-0b3dfca9.js"),[]).then(({data:e})=>e),"v-26ef11a4":()=>E(()=>import("./Rust.html-b1948268.js"),[]).then(({data:e})=>e),"v-f0b20222":()=>E(()=>import("./Back.html-42e4d89e.js"),[]).then(({data:e})=>e),"v-02e2dca3":()=>E(()=>import("./index.html-1f0059e4.js"),[]).then(({data:e})=>e),"v-7fade8ca":()=>E(()=>import("./Interaction.html-b7586d71.js"),[]).then(({data:e})=>e),"v-3706649a":()=>E(()=>import("./404.html-f9875e7b.js"),[]).then(({data:e})=>e)},Bo=JSON.parse('{"base":"/","lang":"zh-CN","title":"HiperLink","description":"🌈 HiperLink | 🔗 嗨皮立刻 - 📆 使用文档","head":[["link",{"rel":"icon","href":"favicon.ico"}]],"locales":{}}'),At={"v-8daa1a0e":q(()=>E(()=>import("./index.html-7b9a0856.js"),["assets/index.html-7b9a0856.js","assets/framework-cc651620.js"])),"v-3e214e9b":q(()=>E(()=>import("./index.html-550593ad.js"),["assets/index.html-550593ad.js","assets/framework-cc651620.js"])),"v-6bc6c5b0":q(()=>E(()=>import("./index.html-9e9e82fb.js"),["assets/index.html-9e9e82fb.js","assets/framework-cc651620.js"])),"v-12b535db":q(()=>E(()=>import("./index.html-5ff51570.js"),["assets/index.html-5ff51570.js","assets/framework-cc651620.js"])),"v-791cb41c":q(()=>E(()=>import("./Start.html-50d99452.js"),["assets/Start.html-50d99452.js","assets/framework-cc651620.js"])),"v-7a6ec647":q(()=>E(()=>import("./index.html-86b4a8cc.js"),["assets/index.html-86b4a8cc.js","assets/framework-cc651620.js"])),"v-2dc44d58":q(()=>E(()=>import("./Example.html-4110fdf6.js"),["assets/Example.html-4110fdf6.js","assets/framework-cc651620.js"])),"v-03604679":q(()=>E(()=>import("./Format.html-acc722f4.js"),["assets/Format.html-acc722f4.js","assets/framework-cc651620.js"])),"v-09a21481":q(()=>E(()=>import("./Metadata.html-0350df2c.js"),["assets/Metadata.html-0350df2c.js","assets/framework-cc651620.js"])),"v-d3fda4d0":q(()=>E(()=>import("./Tips.html-6b25d762.js"),["assets/Tips.html-6b25d762.js","assets/framework-cc651620.js"])),"v-792a752a":q(()=>E(()=>import("./CSharp.html-388a67b2.js"),["assets/CSharp.html-388a67b2.js","assets/framework-cc651620.js"])),"v-391dc22c":q(()=>E(()=>import("./Go.html-3fa1af93.js"),["assets/Go.html-3fa1af93.js","assets/Start-2-98e843d2.js","assets/framework-cc651620.js"])),"v-83a0a214":q(()=>E(()=>import("./Python.html-e29369ba.js"),["assets/Python.html-e29369ba.js","assets/Start-2-98e843d2.js","assets/framework-cc651620.js"])),"v-26ef11a4":q(()=>E(()=>import("./Rust.html-fd38a2dd.js"),["assets/Rust.html-fd38a2dd.js","assets/Start-2-98e843d2.js","assets/framework-cc651620.js"])),"v-f0b20222":q(()=>E(()=>import("./Back.html-df0fa5cb.js"),["assets/Back.html-df0fa5cb.js","assets/framework-cc651620.js"])),"v-02e2dca3":q(()=>E(()=>import("./index.html-ef97b19a.js"),["assets/index.html-ef97b19a.js","assets/framework-cc651620.js"])),"v-7fade8ca":q(()=>E(()=>import("./Interaction.html-54fa1a8f.js"),["assets/Interaction.html-54fa1a8f.js","assets/framework-cc651620.js"])),"v-3706649a":q(()=>E(()=>import("./404.html-ceb4942b.js"),["assets/404.html-ceb4942b.js","assets/framework-cc651620.js"]))};var Mo=Symbol(""),Fo=C(zo),Ht=go({key:"",path:"",title:"",lang:"",frontmatter:{},headers:[]}),de=C(Ht),fe=()=>de,Rt=Symbol(""),le=()=>{const e=re(Rt);if(!e)throw new Error("usePageFrontmatter() is called without provider.");return e},Nt=Symbol(""),Wo=()=>{const e=re(Nt);if(!e)throw new Error("usePageHead() is called without provider.");return e},Vo=Symbol(""),zt=Symbol(""),jo=()=>{const e=re(zt);if(!e)throw new Error("usePageLang() is called without provider.");return e},Bt=Symbol(""),qo=()=>{const e=re(Bt);if(!e)throw new Error("usePageLayout() is called without provider.");return e},Ze=Symbol(""),Le=()=>{const e=re(Ze);if(!e)throw new Error("useRouteLocale() is called without provider.");return e},be=C(Bo),Uo=()=>be,Mt=Symbol(""),Xe=()=>{const e=re(Mt);if(!e)throw new Error("useSiteLocaleData() is called without provider.");return e},Go=Symbol(""),Ko="Layout",Qo="NotFound",se=_o({resolveLayouts:e=>e.reduce((t,o)=>({...t,...o.layouts}),{}),resolvePageData:async e=>{const t=Fo.value[e];return await(t==null?void 0:t())??Ht},resolvePageFrontmatter:e=>e.frontmatter,resolvePageHead:(e,t,o)=>{const n=oe(t.description)?t.description:o.description,r=[...Re(t.head)?t.head:[],...o.head,["title",{},e],["meta",{name:"description",content:n}]];return bo(r)},resolvePageHeadTitle:(e,t)=>[e.title,t.title].filter(o=>!!o).join(" | "),resolvePageLang:e=>e.lang||"en",resolvePageLayout:(e,t)=>{let o;if(e.path){const n=e.frontmatter.layout;oe(n)?o=n:o=Ko}else o=Qo;return t[o]},resolveRouteLocale:(e,t)=>Ot(e,t),resolveSiteLocaleData:(e,t)=>({...e,...e.locales[t]})}),et=I({name:"ClientOnly",setup(e,t){const o=C(!1);return Z(()=>{o.value=!0}),()=>{var n,r;return o.value?(r=(n=t.slots).default)==null?void 0:r.call(n):null}}}),Yo=I({name:"Content",props:{pageKey:{type:String,required:!1,default:""}},setup(e){const t=fe(),o=h(()=>At[e.pageKey||t.value.key]);return()=>o.value?P(o.value):P("div","404 Not Found")}}),ae=(e={})=>e,Me=e=>Pe(e)?e:`/${xt(e)}`;function Ft(e,t,o){var n,r,s;t===void 0&&(t=50),o===void 0&&(o={});var l=(n=o.isImmediate)!=null&&n,a=(r=o.callback)!=null&&r,i=o.maxWait,c=Date.now(),u=[];function v(){if(i!==void 0){var _=Date.now()-c;if(_+t>=i)return i-_}return t}var f=function(){var _=[].slice.call(arguments),y=this;return new Promise(function(L,w){var D=l&&s===void 0;if(s!==void 0&&clearTimeout(s),s=setTimeout(function(){if(s=void 0,c=Date.now(),!l){var O=e.apply(y,_);a&&a(O),u.forEach(function(j){return(0,j.resolve)(O)}),u=[]}},v()),D){var H=e.apply(y,_);return a&&a(H),L(H)}u.push({resolve:L,reject:w})})};return f.cancel=function(_){s!==void 0&&clearTimeout(s),u.forEach(function(y){return(0,y.reject)(_)}),u=[]},f}const Jo=({headerLinkSelector:e,headerAnchorSelector:t,delay:o,offset:n=5})=>{const r=he(),l=Ft(()=>{var L,w;const a=Math.max(window.scrollY,document.documentElement.scrollTop,document.body.scrollTop);if(Math.abs(a-0){const{slotScopeIds:z}=_;z&&(U=U?U.concat(z):z);const S=o(g),q=y(i(g),_,S,P,$,U,J);return q&&dn(q)&&q.data==="]"?i(_.anchor=q):(Je=!0,c(_.anchor=a("]"),S,q),q)},A=(g,_,P,$,U,J)=>{if(Je=!0,_.el=null,J){const q=k(g);for(;;){const K=i(g);if(K&&K!==q)l(K);else break}}const z=i(g),S=o(g);return l(g),n(null,_,S,z,P,$,an(S),U),z},k=g=>{let _=0;for(;g;)if(g=i(g),g&&dn(g)&&(g.data==="["&&_++,g.data==="]")){if(_===0)return i(g);_--}return g};return[f,h]}const Ce=ci;function Ol(e){return Sl(e,Tl)}function Sl(e,t){const n=io();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:o,createText:l,createComment:c,setText:a,setElementText:f,parentNode:h,nextSibling:p,setScopeId:y=He,insertStaticContent:C}=e,A=(u,d,m,b=null,E=null,R=null,M=!1,w=null,T=!!d.dynamicChildren)=>{if(u===d)return;u&&!dt(u,d)&&(b=O(u),Ee(u,E,R,!0),u=null),d.patchFlag===-2&&(T=!1,d.dynamicChildren=null);const{type:x,ref:j,shapeFlag:N}=d;switch(x){case Ot:k(u,d,m,b);break;case Pe:g(u,d,m,b);break;case Kt:u==null&&_(d,m,b,M);break;case xe:F(u,d,m,b,E,R,M,w,T);break;default:N&1?U(u,d,m,b,E,R,M,w,T):N&6?Q(u,d,m,b,E,R,M,w,T):(N&64||N&128)&&x.process(u,d,m,b,E,R,M,w,T,ee)}j!=null&&E&&Cn(j,u&&u.ref,R,d||u,!d)},k=(u,d,m,b)=>{if(u==null)s(d.el=l(d.children),m,b);else{const E=d.el=u.el;d.children!==u.children&&a(E,d.children)}},g=(u,d,m,b)=>{u==null?s(d.el=c(d.children||""),m,b):d.el=u.el},_=(u,d,m,b)=>{[u.el,u.anchor]=C(u.children,d,m,b,u.el,u.anchor)},P=({el:u,anchor:d},m,b)=>{let E;for(;u&&u!==d;)E=p(u),s(u,m,b),u=E;s(d,m,b)},$=({el:u,anchor:d})=>{let m;for(;u&&u!==d;)m=p(u),r(u),u=m;r(d)},U=(u,d,m,b,E,R,M,w,T)=>{M=M||d.type==="svg",u==null?J(d,m,b,E,R,M,w,T):q(u,d,E,R,M,w,T)},J=(u,d,m,b,E,R,M,w)=>{let T,x;const{type:j,props:N,shapeFlag:B,transition:W,dirs:X}=u;if(T=u.el=o(u.type,R,N&&N.is,N),B&8?f(T,u.children):B&16&&S(u.children,T,null,b,E,R&&j!=="foreignObject",M,w),X&&Ue(u,null,b,"created"),N){for(const ie in N)ie!=="value"&&!Dt(ie)&&i(T,ie,null,N[ie],R,u.children,b,E,I);"value"in N&&i(T,"value",null,N.value),(x=N.onVnodeBeforeMount)&&Oe(x,b,u)}z(T,u,u.scopeId,M,b),X&&Ue(u,null,b,"beforeMount");const le=(!E||E&&!E.pendingBranch)&&W&&!W.persisted;le&&W.beforeEnter(T),s(T,d,m),((x=N&&N.onVnodeMounted)||le||X)&&Ce(()=>{x&&Oe(x,b,u),le&&W.enter(T),X&&Ue(u,null,b,"mounted")},E)},z=(u,d,m,b,E)=>{if(m&&y(u,m),b)for(let R=0;R{for(let x=T;x {const w=d.el=u.el;let{patchFlag:T,dynamicChildren:x,dirs:j}=d;T|=u.patchFlag&16;const N=u.props||ce,B=d.props||ce;let W;m&<(m,!1),(W=B.onVnodeBeforeUpdate)&&Oe(W,m,d,u),j&&Ue(d,u,m,"beforeUpdate"),m&<(m,!0);const X=E&&d.type!=="foreignObject";if(x?K(u.dynamicChildren,x,w,m,b,X,R):M||re(u,d,w,null,m,b,X,R,!1),T>0){if(T&16)Z(w,d,N,B,m,b,E);else if(T&2&&N.class!==B.class&&i(w,"class",null,B.class,E),T&4&&i(w,"style",N.style,B.style,E),T&8){const le=d.dynamicProps;for(let ie=0;ie {W&&Oe(W,m,d,u),j&&Ue(d,u,m,"updated")},b)},K=(u,d,m,b,E,R,M)=>{for(let w=0;w {if(m!==b){if(m!==ce)for(const w in m)!Dt(w)&&!(w in b)&&i(u,w,m[w],null,M,d.children,E,R,I);for(const w in b){if(Dt(w))continue;const T=b[w],x=m[w];T!==x&&w!=="value"&&i(u,w,x,T,M,d.children,E,R,I)}"value"in b&&i(u,"value",m.value,b.value)}},F=(u,d,m,b,E,R,M,w,T)=>{const x=d.el=u?u.el:l(""),j=d.anchor=u?u.anchor:l("");let{patchFlag:N,dynamicChildren:B,slotScopeIds:W}=d;W&&(w=w?w.concat(W):W),u==null?(s(x,m,b),s(j,m,b),S(d.children,m,j,E,R,M,w,T)):N>0&&N&64&&B&&u.dynamicChildren?(K(u.dynamicChildren,B,m,E,R,M,w),(d.key!=null||E&&d===E.subTree)&&Pi(u,d,!0)):re(u,d,m,j,E,R,M,w,T)},Q=(u,d,m,b,E,R,M,w,T)=>{d.slotScopeIds=w,u==null?d.shapeFlag&512?E.ctx.activate(d,m,b,M,T):L(d,m,b,E,R,M,T):_e(u,d,T)},L=(u,d,m,b,E,R,M)=>{const w=u.component=jl(u,b,E);if(nn(u)&&(w.ctx.renderer=ee),Dl(w),w.asyncDep){if(E&&E.registerDep(w,G),!u.el){const T=w.subTree=ae(Pe);g(null,T,d,m)}return}G(w,u,d,m,E,R,M)},_e=(u,d,m)=>{const b=d.component=u.component;if(Xo(u,d,m))if(b.asyncDep&&!b.asyncResolved){oe(b,d,m);return}else b.next=d,Wo(b.update),b.update();else d.el=u.el,b.vnode=d},G=(u,d,m,b,E,R,M)=>{const w=()=>{if(u.isMounted){let{next:j,bu:N,u:B,parent:W,vnode:X}=u,le=j,ie;lt(u,!1),j?(j.el=X.el,oe(u,j,M)):j=X,N&&$n(N),(ie=j.props&&j.props.onVnodeBeforeUpdate)&&Oe(ie,W,j,X),lt(u,!0);const de=Hn(u),Ne=u.subTree;u.subTree=de,A(Ne,de,h(Ne.el),O(Ne),u,E,R),j.el=de.el,le===null&&Zo(u,de.el),B&&Ce(B,E),(ie=j.props&&j.props.onVnodeUpdated)&&Ce(()=>Oe(ie,W,j,X),E)}else{let j;const{el:N,props:B}=d,{bm:W,m:X,parent:le}=u,ie=At(d);if(lt(u,!1),W&&$n(W),!ie&&(j=B&&B.onVnodeBeforeMount)&&Oe(j,le,d),lt(u,!0),N&&Y){const de=()=>{u.subTree=Hn(u),Y(N,u.subTree,u,E,null)};ie?d.type.__asyncLoader().then(()=>!u.isUnmounted&&de()):de()}else{const de=u.subTree=Hn(u);A(null,de,m,b,u,E,R),d.el=de.el}if(X&&Ce(X,E),!ie&&(j=B&&B.onVnodeMounted)){const de=d;Ce(()=>Oe(j,le,de),E)}(d.shapeFlag&256||le&&At(le.vnode)&&le.vnode.shapeFlag&256)&&u.a&&Ce(u.a,E),u.isMounted=!0,d=m=b=null}},T=u.effect=new bs(w,()=>On(x),u.scope),x=u.update=()=>T.run();x.id=u.uid,lt(u,!0),x()},oe=(u,d,m)=>{d.component=u;const b=u.vnode.props;u.vnode=d,u.next=null,Cl(u,d.props,b,m),Rl(u,d.children,m),Nt(),qs(),Lt()},re=(u,d,m,b,E,R,M,w,T=!1)=>{const x=u&&u.children,j=u?u.shapeFlag:0,N=d.children,{patchFlag:B,shapeFlag:W}=d;if(B>0){if(B&128){ot(x,N,m,b,E,R,M,w,T);return}else if(B&256){Ie(x,N,m,b,E,R,M,w,T);return}}W&8?(j&16&&I(x,E,R),N!==x&&f(m,N)):j&16?W&16?ot(x,N,m,b,E,R,M,w,T):I(x,E,R,!0):(j&8&&f(m,""),W&16&&S(N,m,b,E,R,M,w,T))},Ie=(u,d,m,b,E,R,M,w,T)=>{u=u||Ct,d=d||Ct;const x=u.length,j=d.length,N=Math.min(x,j);let B;for(B=0;B j?I(u,E,R,!0,!1,N):S(d,m,b,E,R,M,w,T,N)},ot=(u,d,m,b,E,R,M,w,T)=>{let x=0;const j=d.length;let N=u.length-1,B=j-1;for(;x<=N&&x<=B;){const W=u[x],X=d[x]=T?et(d[x]):Le(d[x]);if(dt(W,X))A(W,X,m,null,E,R,M,w,T);else break;x++}for(;x<=N&&x<=B;){const W=u[N],X=d[B]=T?et(d[B]):Le(d[B]);if(dt(W,X))A(W,X,m,null,E,R,M,w,T);else break;N--,B--}if(x>N){if(x<=B){const W=B+1,X=W B)for(;x<=N;)Ee(u[x],E,R,!0),x++;else{const W=x,X=x,le=new Map;for(x=X;x<=B;x++){const we=d[x]=T?et(d[x]):Le(d[x]);we.key!=null&&le.set(we.key,x)}let ie,de=0;const Ne=B-X+1;let bt=!1,Ns=0;const kt=new Array(Ne);for(x=0;x =Ne){Ee(we,E,R,!0);continue}let De;if(we.key!=null)De=le.get(we.key);else for(ie=X;ie<=B;ie++)if(kt[ie-X]===0&&dt(we,d[ie])){De=ie;break}De===void 0?Ee(we,E,R,!0):(kt[De-X]=x+1,De>=Ns?Ns=De:bt=!0,A(we,d[De],m,null,E,R,M,w,T),de++)}const Ls=bt?Ml(kt):Ct;for(ie=Ls.length-1,x=Ne-1;x>=0;x--){const we=X+x,De=d[we],ks=we+1 {const{el:R,type:M,transition:w,children:T,shapeFlag:x}=u;if(x&6){Fe(u.component.subTree,d,m,b);return}if(x&128){u.suspense.move(d,m,b);return}if(x&64){M.move(u,d,m,ee);return}if(M===xe){s(R,d,m);for(let N=0;N w.enter(R),E);else{const{leave:N,delayLeave:B,afterLeave:W}=w,X=()=>s(R,d,m),le=()=>{N(R,()=>{X(),W&&W()})};B?B(R,X,le):le()}else s(R,d,m)},Ee=(u,d,m,b=!1,E=!1)=>{const{type:R,props:M,ref:w,children:T,dynamicChildren:x,shapeFlag:j,patchFlag:N,dirs:B}=u;if(w!=null&&Cn(w,null,m,u,!0),j&256){d.ctx.deactivate(u);return}const W=j&1&&B,X=!At(u);let le;if(X&&(le=M&&M.onVnodeBeforeUnmount)&&Oe(le,d,u),j&6)v(u.component,m,b);else{if(j&128){u.suspense.unmount(m,b);return}W&&Ue(u,null,d,"beforeUnmount"),j&64?u.type.remove(u,d,m,E,ee,b):x&&(R!==xe||N>0&&N&64)?I(x,d,m,!1,!0):(R===xe&&N&384||!E&&j&16)&&I(T,d,m),b&&_t(u)}(X&&(le=M&&M.onVnodeUnmounted)||W)&&Ce(()=>{le&&Oe(le,d,u),W&&Ue(u,null,d,"unmounted")},m)},_t=u=>{const{type:d,el:m,anchor:b,transition:E}=u;if(d===xe){sn(m,b);return}if(d===Kt){$(u);return}const R=()=>{r(m),E&&!E.persisted&&E.afterLeave&&E.afterLeave()};if(u.shapeFlag&1&&E&&!E.persisted){const{leave:M,delayLeave:w}=E,T=()=>M(m,R);w?w(u.el,R,T):T()}else R()},sn=(u,d)=>{let m;for(;u!==d;)m=p(u),r(u),u=m;r(d)},v=(u,d,m)=>{const{bum:b,scope:E,update:R,subTree:M,um:w}=u;b&&$n(b),E.stop(),R&&(R.active=!1,Ee(M,u,d,m)),w&&Ce(w,d),Ce(()=>{u.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},I=(u,d,m,b=!1,E=!1,R=0)=>{for(let M=R;M u.shapeFlag&6?O(u.component.subTree):u.shapeFlag&128?u.suspense.next():p(u.anchor||u.el),H=(u,d,m)=>{u==null?d._vnode&&Ee(d._vnode,null,null,!0):A(d._vnode||null,u,d,null,null,null,m),qs(),bn(),d._vnode=u},ee={p:A,um:Ee,m:Fe,r:_t,mt:L,mc:S,pc:re,pbc:K,n:O,o:e};let fe,Y;return t&&([fe,Y]=t(ee)),{render:H,hydrate:fe,createApp:Al(H,fe)}}function lt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Pi(e,t,n=!1){const s=e.children,r=t.children;if(D(s)&&D(r))for(let i=0;i >1,e[n[l]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,o=n[i-1];i-- >0;)n[i]=o,o=t[o];return n}const Il=e=>e.__isTeleport,xe=Symbol(void 0),Ot=Symbol(void 0),Pe=Symbol(void 0),Kt=Symbol(void 0),Wt=[];let $e=null;function Ai(e=!1){Wt.push($e=e?null:[])}function Fl(){Wt.pop(),$e=Wt[Wt.length-1]||null}let Xt=1;function tr(e){Xt+=e}function Ti(e){return e.dynamicChildren=Xt>0?$e||Ct:null,Fl(),Xt>0&&$e&&$e.push(e),e}function Nu(e,t,n,s,r,i){return Ti(Mi(e,t,n,s,r,i,!0))}function Oi(e,t,n,s,r){return Ti(ae(e,t,n,s,r,!0))}function xn(e){return e?e.__v_isVNode===!0:!1}function dt(e,t){return e.type===t.type&&e.key===t.key}const In="__vInternal",Si=({key:e})=>e??null,mn=({ref:e,ref_key:t,ref_for:n})=>e!=null?pe(e)||ge(e)||V(e)?{i:me,r:e,k:t,f:!!n}:e:null;function Mi(e,t=null,n=null,s=0,r=null,i=e===xe?0:1,o=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Si(t),ref:t&&mn(t),scopeId:li,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:me};return l?(Ss(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=pe(n)?8:16),Xt>0&&!o&&$e&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&$e.push(c),c}const ae=Nl;function Nl(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===hl)&&(e=Pe),xn(e)){const l=it(e,t,!0);return n&&Ss(l,n),Xt>0&&!i&&$e&&(l.shapeFlag&6?$e[$e.indexOf(e)]=l:$e.push(l)),l.patchFlag|=-2,l}if(Vl(e)&&(e=e.__vccOpts),t){t=Ll(t);let{class:l,style:c}=t;l&&!pe(l)&&(t.class=ds(l)),ue(c)&&(Yr(c)&&!D(c)&&(c=ye({},c)),t.style=as(c))}const o=pe(e)?1:Go(e)?128:Il(e)?64:ue(e)?4:V(e)?2:0;return Mi(e,t,n,s,r,o,i,!0)}function Ll(e){return e?Yr(e)||In in e?ye({},e):e:null}function it(e,t,n=!1){const{props:s,ref:r,patchFlag:i,children:o}=e,l=t?kl(s||{},t):s;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&Si(l),ref:t&&t.ref?n&&r?D(r)?r.concat(mn(t)):[r,mn(t)]:mn(t):r,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==xe?i===-1?16:i|16:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&it(e.ssContent),ssFallback:e.ssFallback&&it(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx}}function Ii(e=" ",t=0){return ae(Ot,null,e,t)}function Lu(e,t){const n=ae(Kt,null,e);return n.staticCount=t,n}function ku(e="",t=!1){return t?(Ai(),Oi(Pe,null,e)):ae(Pe,null,e)}function Le(e){return e==null||typeof e=="boolean"?ae(Pe):D(e)?ae(xe,null,e.slice()):typeof e=="object"?et(e):ae(Ot,null,String(e))}function et(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:it(e)}function Ss(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(D(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),Ss(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!(In in t)?t._ctx=me:r===3&&me&&(me.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else V(t)?(t={default:t,_ctx:me},n=32):(t=String(t),s&64?(n=16,t=[Ii(t)]):n=8);e.children=t,e.shapeFlag|=n}function kl(...e){const t={};for(let n=0;n he||me,St=e=>{he=e,e.scope.on()},mt=()=>{he&&he.scope.off(),he=null};function Fi(e){return e.vnode.shapeFlag&4}let Mt=!1;function Dl(e,t=!1){Mt=t;const{props:n,children:s}=e.vnode,r=Fi(e);El(e,n,r,t),wl(e,s);const i=r?Ul(e,t):void 0;return Mt=!1,i}function Ul(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Jr(new Proxy(e.ctx,gl));const{setup:s}=n;if(s){const r=e.setupContext=s.length>1?Wl(e):null;St(e),Nt();const i=st(s,e,0,[e.props,r]);if(Lt(),mt(),Lr(i)){if(i.then(mt,mt),t)return i.then(o=>{nr(e,o,t)}).catch(o=>{tn(o,e,0)});e.asyncDep=i}else nr(e,i,t)}else Ni(e,t)}function nr(e,t,n){V(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ue(t)&&(e.setupState=ei(t)),Ni(e,n)}let sr;function Ni(e,t,n){const s=e.type;if(!e.render){if(!t&&sr&&!s.render){const r=s.template||Ts(e).template;if(r){const{isCustomElement:i,compilerOptions:o}=e.appContext.config,{delimiters:l,compilerOptions:c}=s,a=ye(ye({isCustomElement:i,delimiters:l},o),c);s.render=sr(r,a)}}e.render=s.render||He}St(e),Nt(),ml(e),Lt(),mt()}function Kl(e){return new Proxy(e.attrs,{get(t,n){return Ae(e,"get","$attrs"),t[n]}})}function Wl(e){const t=s=>{e.exposed=s||{}};let n;return{get attrs(){return n||(n=Kl(e))},slots:e.slots,emit:e.emit,expose:t}}function Fn(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(ei(Jr(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Ut)return Ut[n](e)},has(t,n){return n in t||n in Ut}}))}function ql(e,t=!0){return V(e)?e.displayName||e.name:e.name||t&&e.__name}function Vl(e){return V(e)&&"__vccOpts"in e}const Se=(e,t)=>Do(e,t,Mt);function Ms(e,t,n){const s=arguments.length;return s===2?ue(t)&&!D(t)?xn(t)?ae(e,null,[t]):ae(e,t):ae(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&xn(n)&&(n=[n]),ae(e,t,n))}const zl=Symbol(""),Ql=()=>je(zl),Yl="3.2.45",Jl="http://www.w3.org/2000/svg",ht=typeof document<"u"?document:null,rr=ht&&ht.createElement("template"),Xl={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t?ht.createElementNS(Jl,e):ht.createElement(e,n?{is:n}:void 0);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>ht.createTextNode(e),createComment:e=>ht.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>ht.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const o=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{rr.innerHTML=s?``:e;const l=rr.content;if(s){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}};function Zl(e,t,n){const s=e._vtc;s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}function Gl(e,t,n){const s=e.style,r=pe(n);if(n&&!r){for(const i in n)os(s,i,n[i]);if(t&&!pe(t))for(const i in t)n[i]==null&&os(s,i,"")}else{const i=s.display;r?t!==n&&(s.cssText=n):t&&e.removeAttribute("style"),"_vod"in e&&(s.display=i)}}const ir=/\s*!important$/;function os(e,t,n){if(D(n))n.forEach(s=>os(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=ec(e,t);ir.test(n)?e.setProperty(yt(s),n.replace(ir,""),"important"):e[s]=n}}const or=["Webkit","Moz","ms"],Un={};function ec(e,t){const n=Un[t];if(n)return n;let s=We(t);if(s!=="filter"&&s in e)return Un[t]=s;s=An(s);for(let r=0;r Kn||(lc.then(()=>Kn=0),Kn=Date.now());function uc(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;Me(fc(s,n.value),t,5,[s])};return n.value=e,n.attached=cc(),n}function fc(e,t){if(D(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const ur=/^on[a-z]/,ac=(e,t,n,s,r=!1,i,o,l,c)=>{t==="class"?Zl(e,s,r):t==="style"?Gl(e,n,s):Gt(t)?hs(t)||ic(e,t,n,s,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):dc(e,t,s,r))?nc(e,t,s,i,o,l,c):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),tc(e,t,s,r))};function dc(e,t,n,s){return s?!!(t==="innerHTML"||t==="textContent"||t in e&&ur.test(t)&&V(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||ur.test(t)&&pe(n)?!1:t in e}const Xe="transition",$t="animation",Li=(e,{slots:t})=>Ms(fi,hc(e),t);Li.displayName="Transition";const ki={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};Li.props=ye({},fi.props,ki);const ct=(e,t=[])=>{D(e)?e.forEach(n=>n(...t)):e&&e(...t)},fr=e=>e?D(e)?e.some(t=>t.length>1):e.length>1:!1;function hc(e){const t={};for(const F in e)F in ki||(t[F]=e[F]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:a=o,appearToClass:f=l,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:y=`${n}-leave-to`}=e,C=pc(r),A=C&&C[0],k=C&&C[1],{onBeforeEnter:g,onEnter:_,onEnterCancelled:P,onLeave:$,onLeaveCancelled:U,onBeforeAppear:J=g,onAppear:z=_,onAppearCancelled:S=P}=t,q=(F,Q,L)=>{ut(F,Q?f:l),ut(F,Q?a:o),L&&L()},K=(F,Q)=>{F._isLeaving=!1,ut(F,h),ut(F,y),ut(F,p),Q&&Q()},Z=F=>(Q,L)=>{const _e=F?z:_,G=()=>q(Q,F,L);ct(_e,[Q,G]),ar(()=>{ut(Q,F?c:i),Ze(Q,F?f:l),fr(_e)||dr(Q,s,A,G)})};return ye(t,{onBeforeEnter(F){ct(g,[F]),Ze(F,i),Ze(F,o)},onBeforeAppear(F){ct(J,[F]),Ze(F,c),Ze(F,a)},onEnter:Z(!1),onAppear:Z(!0),onLeave(F,Q){F._isLeaving=!0;const L=()=>K(F,Q);Ze(F,h),yc(),Ze(F,p),ar(()=>{F._isLeaving&&(ut(F,h),Ze(F,y),fr($)||dr(F,s,k,L))}),ct($,[F,L])},onEnterCancelled(F){q(F,!1),ct(P,[F])},onAppearCancelled(F){q(F,!0),ct(S,[F])},onLeaveCancelled(F){K(F),ct(U,[F])}})}function pc(e){if(e==null)return null;if(ue(e))return[Wn(e.enter),Wn(e.leave)];{const t=Wn(e);return[t,t]}}function Wn(e){return ys(e)}function Ze(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e._vtc||(e._vtc=new Set)).add(t)}function ut(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const{_vtc:n}=e;n&&(n.delete(t),n.size||(e._vtc=void 0))}function ar(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let gc=0;function dr(e,t,n,s){const r=e._endId=++gc,i=()=>{r===e._endId&&s()};if(n)return setTimeout(i,n);const{type:o,timeout:l,propCount:c}=mc(e,t);if(!o)return s();const a=o+"end";let f=0;const h=()=>{e.removeEventListener(a,p),i()},p=y=>{y.target===e&&++f>=c&&h()};setTimeout(()=>{f (n[C]||"").split(", "),r=s(`${Xe}Delay`),i=s(`${Xe}Duration`),o=hr(r,i),l=s(`${$t}Delay`),c=s(`${$t}Duration`),a=hr(l,c);let f=null,h=0,p=0;t===Xe?o>0&&(f=Xe,h=o,p=i.length):t===$t?a>0&&(f=$t,h=a,p=c.length):(h=Math.max(o,a),f=h>0?o>a?Xe:$t:null,p=f?f===Xe?i.length:c.length:0);const y=f===Xe&&/\b(transform|all)(,|$)/.test(s(`${Xe}Property`).toString());return{type:f,timeout:h,propCount:p,hasTransform:y}}function hr(e,t){for(;e.length pr(n)+pr(e[s])))}function pr(e){return Number(e.slice(0,-1).replace(",","."))*1e3}function yc(){return document.body.offsetHeight}const _c={esc:"escape",space:" ",up:"arrow-up",left:"arrow-left",right:"arrow-right",down:"arrow-down",delete:"backspace"},$u=(e,t)=>n=>{if(!("key"in n))return;const s=yt(n.key);if(t.some(r=>r===s||_c[r]===s))return e(n)},Hu={beforeMount(e,{value:t},{transition:n}){e._vod=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):Ht(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:s}){!t!=!n&&(s?t?(s.beforeEnter(e),Ht(e,!0),s.enter(e)):s.leave(e,()=>{Ht(e,!1)}):Ht(e,t))},beforeUnmount(e,{value:t}){Ht(e,t)}};function Ht(e,t){e.style.display=t?e._vod:"none"}const bc=ye({patchProp:ac},Xl);let qn,gr=!1;function vc(){return qn=gr?qn:Ol(bc),gr=!0,qn}const ju=(...e)=>{const t=vc().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Ec(s);if(r)return n(r,!0,r instanceof SVGElement)},t};function Ec(e){return pe(e)?document.querySelector(e):e}var Cc=([e,t,n])=>e==="meta"&&t.name?`${e}.${t.name}`:["title","base"].includes(e)?e:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,t,n]),Bu=e=>{const t=new Set,n=[];return e.forEach(s=>{const r=Cc(s);t.has(r)||(t.add(r),n.push(s))}),n},Du=e=>/^(https?:)?\/\//.test(e),Uu=e=>/^mailto:/.test(e),Ku=e=>/^tel:/.test(e),Wu=e=>Object.prototype.toString.call(e)==="[object Object]",qu=e=>e.replace(/\/$/,""),Vu=e=>e.replace(/^\//,""),zu=(e,t)=>{const n=Object.keys(e).sort((s,r)=>{const i=r.split("/").length-s.split("/").length;return i!==0?i:r.length-s.length});for(const s of n)if(t.startsWith(s))return s;return"/"};/*! + * vue-router v4.1.6 + * (c) 2022 Eduardo San Martin Morote + * @license MIT + */const Et=typeof window<"u";function xc(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const se=Object.assign;function Vn(e,t){const n={};for(const s in t){const r=t[s];n[s]=Be(r)?r.map(e):e(r)}return n}const qt=()=>{},Be=Array.isArray,wc=/\/$/,Rc=e=>e.replace(wc,"");function zn(e,t,n="/"){let s,r={},i="",o="";const l=t.indexOf("#");let c=t.indexOf("?");return l =0&&(c=-1),c>-1&&(s=t.slice(0,c),i=t.slice(c+1,l>-1?l:t.length),r=e(i)),l>-1&&(s=s||t.slice(0,l),o=t.slice(l,t.length)),s=Oc(s??t,n),{fullPath:s+(i&&"?")+i+o,path:s,query:r,hash:o}}function Pc(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function mr(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Ac(e,t,n){const s=t.matched.length-1,r=n.matched.length-1;return s>-1&&s===r&&It(t.matched[s],n.matched[r])&&$i(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function It(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function $i(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!Tc(e[n],t[n]))return!1;return!0}function Tc(e,t){return Be(e)?yr(e,t):Be(t)?yr(t,e):e===t}function yr(e,t){return Be(t)?e.length===t.length&&e.every((n,s)=>n===t[s]):e.length===1&&e[0]===t}function Oc(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),s=e.split("/");let r=n.length-1,i,o;for(i=0;i 1&&r--;else break;return n.slice(0,r).join("/")+"/"+s.slice(i-(i===s.length?1:0)).join("/")}var Zt;(function(e){e.pop="pop",e.push="push"})(Zt||(Zt={}));var Vt;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Vt||(Vt={}));function Sc(e){if(!e)if(Et){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),Rc(e)}const Mc=/^[^#]+#/;function Ic(e,t){return e.replace(Mc,"#")+t}function Fc(e,t){const n=document.documentElement.getBoundingClientRect(),s=e.getBoundingClientRect();return{behavior:t.behavior,left:s.left-n.left-(t.left||0),top:s.top-n.top-(t.top||0)}}const Nn=()=>({left:window.pageXOffset,top:window.pageYOffset});function Nc(e){let t;if("el"in e){const n=e.el,s=typeof n=="string"&&n.startsWith("#"),r=typeof n=="string"?s?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!r)return;t=Fc(r,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.pageXOffset,t.top!=null?t.top:window.pageYOffset)}function _r(e,t){return(history.state?history.state.position-t:-1)+e}const ls=new Map;function Lc(e,t){ls.set(e,t)}function kc(e){const t=ls.get(e);return ls.delete(e),t}let $c=()=>location.protocol+"//"+location.host;function Hi(e,t){const{pathname:n,search:s,hash:r}=t,i=e.indexOf("#");if(i>-1){let l=r.includes(e.slice(i))?e.slice(i).length:1,c=r.slice(l);return c[0]!=="/"&&(c="/"+c),mr(c,"")}return mr(n,e)+s+r}function Hc(e,t,n,s){let r=[],i=[],o=null;const l=({state:p})=>{const y=Hi(e,location),C=n.value,A=t.value;let k=0;if(p){if(n.value=y,t.value=p,o&&o===C){o=null;return}k=A?p.position-A.position:0}else s(y);r.forEach(g=>{g(n.value,C,{delta:k,type:Zt.pop,direction:k?k>0?Vt.forward:Vt.back:Vt.unknown})})};function c(){o=n.value}function a(p){r.push(p);const y=()=>{const C=r.indexOf(p);C>-1&&r.splice(C,1)};return i.push(y),y}function f(){const{history:p}=window;p.state&&p.replaceState(se({},p.state,{scroll:Nn()}),"")}function h(){for(const p of i)p();i=[],window.removeEventListener("popstate",l),window.removeEventListener("beforeunload",f)}return window.addEventListener("popstate",l),window.addEventListener("beforeunload",f),{pauseListeners:c,listen:a,destroy:h}}function br(e,t,n,s=!1,r=!1){return{back:e,current:t,forward:n,replaced:s,position:window.history.length,scroll:r?Nn():null}}function jc(e){const{history:t,location:n}=window,s={value:Hi(e,n)},r={value:t.state};r.value||i(s.value,{back:null,current:s.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(c,a,f){const h=e.indexOf("#"),p=h>-1?(n.host&&document.querySelector("base")?e:e.slice(h))+c:$c()+e+c;try{t[f?"replaceState":"pushState"](a,"",p),r.value=a}catch(y){console.error(y),n[f?"replace":"assign"](p)}}function o(c,a){const f=se({},t.state,br(r.value.back,c,r.value.forward,!0),a,{position:r.value.position});i(c,f,!0),s.value=c}function l(c,a){const f=se({},r.value,t.state,{forward:c,scroll:Nn()});i(f.current,f,!0);const h=se({},br(s.value,c,null),{position:f.position+1},a);i(c,h,!1),s.value=c}return{location:s,state:r,push:l,replace:o}}function Qu(e){e=Sc(e);const t=jc(e),n=Hc(e,t.state,t.location,t.replace);function s(i,o=!0){o||n.pauseListeners(),history.go(i)}const r=se({location:"",base:e,go:s,createHref:Ic.bind(null,e)},t,n);return Object.defineProperty(r,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(r,"state",{enumerable:!0,get:()=>t.state.value}),r}function Bc(e){return typeof e=="string"||e&&typeof e=="object"}function ji(e){return typeof e=="string"||typeof e=="symbol"}const Ge={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},Bi=Symbol("");var vr;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(vr||(vr={}));function Ft(e,t){return se(new Error,{type:e,[Bi]:!0},t)}function qe(e,t){return e instanceof Error&&Bi in e&&(t==null||!!(e.type&t))}const Er="[^/]+?",Dc={sensitive:!1,strict:!1,start:!0,end:!0},Uc=/[.+*?^${}()[\]/\\]/g;function Kc(e,t){const n=se({},Dc,t),s=[];let r=n.start?"^":"";const i=[];for(const a of e){const f=a.length?[]:[90];n.strict&&!a.length&&(r+="/");for(let h=0;h t.length?t.length===1&&t[0]===40+40?1:-1:0}function qc(e,t){let n=0;const s=e.score,r=t.score;for(;n 0&&t[t.length-1]<0}const Vc={type:0,value:""},zc=/[a-zA-Z0-9_]/;function Qc(e){if(!e)return[[]];if(e==="/")return[[Vc]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(y){throw new Error(`ERR (${n})/"${a}": ${y}`)}let n=0,s=n;const r=[];let i;function o(){i&&r.push(i),i=[]}let l=0,c,a="",f="";function h(){a&&(n===0?i.push({type:0,value:a}):n===1||n===2||n===3?(i.length>1&&(c==="*"||c==="+")&&t(`A repeatable param (${a}) must be alone in its segment. eg: '/:ids+.`),i.push({type:1,value:a,regexp:f,repeatable:c==="*"||c==="+",optional:c==="*"||c==="?"})):t("Invalid state to consume buffer"),a="")}function p(){a+=c}for(;l {o(_)}:qt}function o(f){if(ji(f)){const h=s.get(f);h&&(s.delete(f),n.splice(n.indexOf(h),1),h.children.forEach(o),h.alias.forEach(o))}else{const h=n.indexOf(f);h>-1&&(n.splice(h,1),f.record.name&&s.delete(f.record.name),f.children.forEach(o),f.alias.forEach(o))}}function l(){return n}function c(f){let h=0;for(;h =0&&(f.record.path!==n[h].record.path||!Di(f,n[h]));)h++;n.splice(h,0,f),f.record.name&&!wr(f)&&s.set(f.record.name,f)}function a(f,h){let p,y={},C,A;if("name"in f&&f.name){if(p=s.get(f.name),!p)throw Ft(1,{location:f});A=p.record.name,y=se(xr(h.params,p.keys.filter(_=>!_.optional).map(_=>_.name)),f.params&&xr(f.params,p.keys.map(_=>_.name))),C=p.stringify(y)}else if("path"in f)C=f.path,p=n.find(_=>_.re.test(C)),p&&(y=p.parse(C),A=p.record.name);else{if(p=h.name?s.get(h.name):n.find(_=>_.re.test(h.path)),!p)throw Ft(1,{location:f,currentLocation:h});A=p.record.name,y=se({},h.params,f.params),C=p.stringify(y)}const k=[];let g=p;for(;g;)k.unshift(g.record),g=g.parent;return{name:A,path:C,params:y,matched:k,meta:Gc(k)}}return e.forEach(f=>i(f)),{addRoute:i,resolve:a,removeRoute:o,getRoutes:l,getRecordMatcher:r}}function xr(e,t){const n={};for(const s of t)s in e&&(n[s]=e[s]);return n}function Xc(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:Zc(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}}}function Zc(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const s in e.components)t[s]=typeof n=="boolean"?n:n[s];return t}function wr(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function Gc(e){return e.reduce((t,n)=>se(t,n.meta),{})}function Rr(e,t){const n={};for(const s in e)n[s]=s in t?t[s]:e[s];return n}function Di(e,t){return t.children.some(n=>n===e||Di(e,n))}const Ui=/#/g,eu=/&/g,tu=/\//g,nu=/=/g,su=/\?/g,Ki=/\+/g,ru=/%5B/g,iu=/%5D/g,Wi=/%5E/g,ou=/%60/g,qi=/%7B/g,lu=/%7C/g,Vi=/%7D/g,cu=/%20/g;function Is(e){return encodeURI(""+e).replace(lu,"|").replace(ru,"[").replace(iu,"]")}function uu(e){return Is(e).replace(qi,"{").replace(Vi,"}").replace(Wi,"^")}function cs(e){return Is(e).replace(Ki,"%2B").replace(cu,"+").replace(Ui,"%23").replace(eu,"%26").replace(ou,"`").replace(qi,"{").replace(Vi,"}").replace(Wi,"^")}function fu(e){return cs(e).replace(nu,"%3D")}function au(e){return Is(e).replace(Ui,"%23").replace(su,"%3F")}function du(e){return e==null?"":au(e).replace(tu,"%2F")}function wn(e){try{return decodeURIComponent(""+e)}catch{}return""+e}function hu(e){const t={};if(e===""||e==="?")return t;const s=(e[0]==="?"?e.slice(1):e).split("&");for(let r=0;r i&&cs(i)):[s&&cs(s)]).forEach(i=>{i!==void 0&&(t+=(t.length?"&":"")+n,i!=null&&(t+="="+i))})}return t}function pu(e){const t={};for(const n in e){const s=e[n];s!==void 0&&(t[n]=Be(s)?s.map(r=>r==null?null:""+r):s==null?s:""+s)}return t}const gu=Symbol(""),Ar=Symbol(""),Ln=Symbol(""),Fs=Symbol(""),us=Symbol("");function jt(){let e=[];function t(s){return e.push(s),()=>{const r=e.indexOf(s);r>-1&&e.splice(r,1)}}function n(){e=[]}return{add:t,list:()=>e,reset:n}}function tt(e,t,n,s,r){const i=s&&(s.enterCallbacks[r]=s.enterCallbacks[r]||[]);return()=>new Promise((o,l)=>{const c=h=>{h===!1?l(Ft(4,{from:n,to:t})):h instanceof Error?l(h):Bc(h)?l(Ft(2,{from:t,to:h})):(i&&s.enterCallbacks[r]===i&&typeof h=="function"&&i.push(h),o())},a=e.call(s&&s.instances[r],t,n,c);let f=Promise.resolve(a);e.length<3&&(f=f.then(c)),f.catch(h=>l(h))})}function Qn(e,t,n,s){const r=[];for(const i of e)for(const o in i.components){let l=i.components[o];if(!(t!=="beforeRouteEnter"&&!i.instances[o]))if(mu(l)){const a=(l.__vccOpts||l)[t];a&&r.push(tt(a,n,s,i,o))}else{let c=l();r.push(()=>c.then(a=>{if(!a)return Promise.reject(new Error(`Couldn't resolve component "${o}" at "${i.path}"`));const f=xc(a)?a.default:a;i.components[o]=f;const p=(f.__vccOpts||f)[t];return p&&tt(p,n,s,i,o)()}))}}return r}function mu(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function Tr(e){const t=je(Ln),n=je(Fs),s=Se(()=>t.resolve(Rt(e.to))),r=Se(()=>{const{matched:c}=s.value,{length:a}=c,f=c[a-1],h=n.matched;if(!f||!h.length)return-1;const p=h.findIndex(It.bind(null,f));if(p>-1)return p;const y=Or(c[a-2]);return a>1&&Or(f)===y&&h[h.length-1].path!==y?h.findIndex(It.bind(null,c[a-2])):p}),i=Se(()=>r.value>-1&&vu(n.params,s.value.params)),o=Se(()=>r.value>-1&&r.value===n.matched.length-1&&$i(n.params,s.value.params));function l(c={}){return bu(c)?t[Rt(e.replace)?"replace":"push"](Rt(e.to)).catch(qt):Promise.resolve()}return{route:s,href:Se(()=>s.value.href),isActive:i,isExactActive:o,navigate:l}}const yu=As({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:Tr,setup(e,{slots:t}){const n=en(Tr(e)),{options:s}=je(Ln),r=Se(()=>({[Sr(e.activeClass,s.linkActiveClass,"router-link-active")]:n.isActive,[Sr(e.exactActiveClass,s.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const i=t.default&&t.default(n);return e.custom?i:Ms("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:r.value},i)}}}),_u=yu;function bu(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function vu(e,t){for(const n in t){const s=t[n],r=e[n];if(typeof s=="string"){if(s!==r)return!1}else if(!Be(r)||r.length!==s.length||s.some((i,o)=>i!==r[o]))return!1}return!0}function Or(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Sr=(e,t,n)=>e??t??n,Eu=As({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const s=je(us),r=Se(()=>e.route||s.value),i=je(Ar,0),o=Se(()=>{let a=Rt(i);const{matched:f}=r.value;let h;for(;(h=f[a])&&!h.components;)a++;return a}),l=Se(()=>r.value.matched[o.value]);pn(Ar,Se(()=>o.value+1)),pn(gu,l),pn(us,r);const c=hn();return gn(()=>[c.value,l.value,e.name],([a,f,h],[p,y,C])=>{f&&(f.instances[h]=a,y&&y!==f&&a&&a===p&&(f.leaveGuards.size||(f.leaveGuards=y.leaveGuards),f.updateGuards.size||(f.updateGuards=y.updateGuards))),a&&f&&(!y||!It(f,y)||!p)&&(f.enterCallbacks[h]||[]).forEach(A=>A(a))},{flush:"post"}),()=>{const a=r.value,f=e.name,h=l.value,p=h&&h.components[f];if(!p)return Mr(n.default,{Component:p,route:a});const y=h.props[f],C=y?y===!0?a.params:typeof y=="function"?y(a):y:null,k=Ms(p,se({},C,t,{onVnodeUnmounted:g=>{g.component.isUnmounted&&(h.instances[f]=null)},ref:c}));return Mr(n.default,{Component:k,route:a})||k}}});function Mr(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const Cu=Eu;function Yu(e){const t=Jc(e.routes,e),n=e.parseQuery||hu,s=e.stringifyQuery||Pr,r=e.history,i=jt(),o=jt(),l=jt(),c=Lo(Ge);let a=Ge;Et&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const f=Vn.bind(null,v=>""+v),h=Vn.bind(null,du),p=Vn.bind(null,wn);function y(v,I){let O,H;return ji(v)?(O=t.getRecordMatcher(v),H=I):H=v,t.addRoute(H,O)}function C(v){const I=t.getRecordMatcher(v);I&&t.removeRoute(I)}function A(){return t.getRoutes().map(v=>v.record)}function k(v){return!!t.getRecordMatcher(v)}function g(v,I){if(I=se({},I||c.value),typeof v=="string"){const u=zn(n,v,I.path),d=t.resolve({path:u.path},I),m=r.createHref(u.fullPath);return se(u,d,{params:p(d.params),hash:wn(u.hash),redirectedFrom:void 0,href:m})}let O;if("path"in v)O=se({},v,{path:zn(n,v.path,I.path).path});else{const u=se({},v.params);for(const d in u)u[d]==null&&delete u[d];O=se({},v,{params:h(v.params)}),I.params=h(I.params)}const H=t.resolve(O,I),ee=v.hash||"";H.params=f(p(H.params));const fe=Pc(s,se({},v,{hash:uu(ee),path:H.path})),Y=r.createHref(fe);return se({fullPath:fe,hash:ee,query:s===Pr?pu(v.query):v.query||{}},H,{redirectedFrom:void 0,href:Y})}function _(v){return typeof v=="string"?zn(n,v,c.value.path):se({},v)}function P(v,I){if(a!==v)return Ft(8,{from:I,to:v})}function $(v){return z(v)}function U(v){return $(se(_(v),{replace:!0}))}function J(v){const I=v.matched[v.matched.length-1];if(I&&I.redirect){const{redirect:O}=I;let H=typeof O=="function"?O(v):O;return typeof H=="string"&&(H=H.includes("?")||H.includes("#")?H=_(H):{path:H},H.params={}),se({query:v.query,hash:v.hash,params:"path"in H?{}:v.params},H)}}function z(v,I){const O=a=g(v),H=c.value,ee=v.state,fe=v.force,Y=v.replace===!0,u=J(O);if(u)return z(se(_(u),{state:typeof u=="object"?se({},ee,u.state):ee,force:fe,replace:Y}),I||O);const d=O;d.redirectedFrom=I;let m;return!fe&&Ac(s,H,O)&&(m=Ft(16,{to:d,from:H}),ot(H,H,!0,!1)),(m?Promise.resolve(m):q(d,H)).catch(b=>qe(b)?qe(b,2)?b:Ie(b):oe(b,d,H)).then(b=>{if(b){if(qe(b,2))return z(se({replace:Y},_(b.to),{state:typeof b.to=="object"?se({},ee,b.to.state):ee,force:fe}),I||d)}else b=Z(d,H,!0,Y,ee);return K(d,H,b),b})}function S(v,I){const O=P(v,I);return O?Promise.reject(O):Promise.resolve()}function q(v,I){let O;const[H,ee,fe]=xu(v,I);O=Qn(H.reverse(),"beforeRouteLeave",v,I);for(const u of H)u.leaveGuards.forEach(d=>{O.push(tt(d,v,I))});const Y=S.bind(null,v,I);return O.push(Y),vt(O).then(()=>{O=[];for(const u of i.list())O.push(tt(u,v,I));return O.push(Y),vt(O)}).then(()=>{O=Qn(ee,"beforeRouteUpdate",v,I);for(const u of ee)u.updateGuards.forEach(d=>{O.push(tt(d,v,I))});return O.push(Y),vt(O)}).then(()=>{O=[];for(const u of v.matched)if(u.beforeEnter&&!I.matched.includes(u))if(Be(u.beforeEnter))for(const d of u.beforeEnter)O.push(tt(d,v,I));else O.push(tt(u.beforeEnter,v,I));return O.push(Y),vt(O)}).then(()=>(v.matched.forEach(u=>u.enterCallbacks={}),O=Qn(fe,"beforeRouteEnter",v,I),O.push(Y),vt(O))).then(()=>{O=[];for(const u of o.list())O.push(tt(u,v,I));return O.push(Y),vt(O)}).catch(u=>qe(u,8)?u:Promise.reject(u))}function K(v,I,O){for(const H of l.list())H(v,I,O)}function Z(v,I,O,H,ee){const fe=P(v,I);if(fe)return fe;const Y=I===Ge,u=Et?history.state:{};O&&(H||Y?r.replace(v.fullPath,se({scroll:Y&&u&&u.scroll},ee)):r.push(v.fullPath,ee)),c.value=v,ot(v,I,O,Y),Ie()}let F;function Q(){F||(F=r.listen((v,I,O)=>{if(!sn.listening)return;const H=g(v),ee=J(H);if(ee){z(se(ee,{replace:!0}),H).catch(qt);return}a=H;const fe=c.value;Et&&Lc(_r(fe.fullPath,O.delta),Nn()),q(H,fe).catch(Y=>qe(Y,12)?Y:qe(Y,2)?(z(Y.to,H).then(u=>{qe(u,20)&&!O.delta&&O.type===Zt.pop&&r.go(-1,!1)}).catch(qt),Promise.reject()):(O.delta&&r.go(-O.delta,!1),oe(Y,H,fe))).then(Y=>{Y=Y||Z(H,fe,!1),Y&&(O.delta&&!qe(Y,8)?r.go(-O.delta,!1):O.type===Zt.pop&&qe(Y,20)&&r.go(-1,!1)),K(H,fe,Y)}).catch(qt)}))}let L=jt(),_e=jt(),G;function oe(v,I,O){Ie(v);const H=_e.list();return H.length?H.forEach(ee=>ee(v,I,O)):console.error(v),Promise.reject(v)}function re(){return G&&c.value!==Ge?Promise.resolve():new Promise((v,I)=>{L.add([v,I])})}function Ie(v){return G||(G=!v,Q(),L.list().forEach(([I,O])=>v?O(v):I()),L.reset()),v}function ot(v,I,O,H){const{scrollBehavior:ee}=e;if(!Et||!ee)return Promise.resolve();const fe=!O&&kc(_r(v.fullPath,0))||(H||!O)&&history.state&&history.state.scroll||null;return si().then(()=>ee(v,I,fe)).then(Y=>Y&&Nc(Y)).catch(Y=>oe(Y,v,I))}const Fe=v=>r.go(v);let Ee;const _t=new Set,sn={currentRoute:c,listening:!0,addRoute:y,removeRoute:C,hasRoute:k,getRoutes:A,resolve:g,options:e,push:$,replace:U,go:Fe,back:()=>Fe(-1),forward:()=>Fe(1),beforeEach:i.add,beforeResolve:o.add,afterEach:l.add,onError:_e.add,isReady:re,install(v){const I=this;v.component("RouterLink",_u),v.component("RouterView",Cu),v.config.globalProperties.$router=I,Object.defineProperty(v.config.globalProperties,"$route",{enumerable:!0,get:()=>Rt(c)}),Et&&!Ee&&c.value===Ge&&(Ee=!0,$(r.location).catch(ee=>{}));const O={};for(const ee in Ge)O[ee]=Se(()=>c.value[ee]);v.provide(Ln,I),v.provide(Fs,en(O)),v.provide(us,c);const H=v.unmount;_t.add(v),v.unmount=function(){_t.delete(v),_t.size<1&&(a=Ge,F&&F(),F=null,c.value=Ge,Ee=!1,G=!1),H()}}};return sn}function vt(e){return e.reduce((t,n)=>t.then(()=>n()),Promise.resolve())}function xu(e,t){const n=[],s=[],r=[],i=Math.max(t.matched.length,e.matched.length);for(let o=0;oIt(a,l))?s.push(l):n.push(l));const c=e.matched[o];c&&(t.matched.find(a=>It(a,c))||r.push(c))}return[n,s,r]}function Ju(){return je(Ln)}function Xu(){return je(Fs)}const Zu=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n};export{Hu as $,gn as A,Ru as B,Pu as C,Bl as D,si as E,Lo as F,Tu as G,mi as H,pn as I,V as J,Wu as K,Xu as L,Mu as M,ae as N,xe as O,Iu as P,ku as Q,Mi as R,Au as S,Oi as T,Qo as U,kl as V,Uu as W,Ku as X,Li as Y,Su as Z,Zu as _,Qr as a,qu as a0,Lu as a1,$u as a2,ju as a3,Cu as a4,Yu as a5,Ge as a6,Qu as a7,en as b,As as c,Ou as d,D as e,Bu as f,zu as g,Se as h,pe as i,Ms as j,je as k,Du as l,Vu as m,gi as n,pi as o,Ai as p,Nu as q,hn as r,Fu as s,Ii as t,Ju as u,wu as v,ds as w,as as x,ge as y,Rt as z}; diff --git a/assets/index-70769223.js b/assets/index-70769223.js new file mode 100644 index 0000000..6d142a2 --- /dev/null +++ b/assets/index-70769223.js @@ -0,0 +1 @@ +var v=function(){return Boolean(window.location.hostname==="localhost"||window.location.hostname==="[::1]"||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/))},c;typeof window<"u"&&(typeof Promise<"u"?c=new Promise(function(t){return window.addEventListener("load",t)}):c={then:function(t){return window.addEventListener("load",t)}});function s(t,n){n===void 0&&(n={});var i=n.registrationOptions;i===void 0&&(i={}),delete n.registrationOptions;var e=function(r){for(var f=[],a=arguments.length-1;a-- >0;)f[a]=arguments[a+1];n&&n[r]&&n[r].apply(n,f)};"serviceWorker"in navigator&&c.then(function(){v()?(l(t,e,i),navigator.serviceWorker.ready.then(function(r){e("ready",r)}).catch(function(r){return o(e,r)})):(u(t,e,i),navigator.serviceWorker.ready.then(function(r){e("ready",r)}).catch(function(r){return o(e,r)}))})}function o(t,n){navigator.onLine||t("offline"),t("error",n)}function u(t,n,i){navigator.serviceWorker.register(t,i).then(function(e){if(n("registered",e),e.waiting){n("updated",e);return}e.onupdatefound=function(){n("updatefound",e);var r=e.installing;r.onstatechange=function(){r.state==="installed"&&(navigator.serviceWorker.controller?n("updated",e):n("cached",e))}}}).catch(function(e){return o(n,e)})}function l(t,n,i){fetch(t).then(function(e){e.status===404?(n("error",new Error("Service worker not found at "+t)),d()):e.headers.get("content-type").indexOf("javascript")===-1?(n("error",new Error("Expected "+t+" to have javascript content-type, but received "+e.headers.get("content-type"))),d()):u(t,n,i)}).catch(function(e){return o(n,e)})}function d(){"serviceWorker"in navigator&&navigator.serviceWorker.ready.then(function(t){t.unregister()}).catch(function(t){return o(emit,t)})}export{s as register,d as unregister}; diff --git a/assets/index.html-103e28a1.js b/assets/index.html-103e28a1.js new file mode 100644 index 0000000..9c8f3c0 --- /dev/null +++ b/assets/index.html-103e28a1.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-7a6ec647","path":"/PluginMarket/","title":"","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"插件市场","slug":"插件市场","link":"#插件市场","children":[]}],"git":{"updatedTime":1673106873000,"contributors":[{"name":"Harry-zklcdc","email":"1269158832@qq.com","commits":1}]},"filePathRelative":"PluginMarket/README.md"}');export{e as data}; diff --git a/assets/index.html-1f0059e4.js b/assets/index.html-1f0059e4.js new file mode 100644 index 0000000..bdb8a31 --- /dev/null +++ b/assets/index.html-1f0059e4.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-02e2dca3","path":"/PluginDocs/Web/","title":"前端","lang":"zh-CN","frontmatter":{},"headers":[],"git":{"updatedTime":1675256121000,"contributors":[{"name":"Ceyase","email":"jjcyf@foxmail.com","commits":1}]},"filePathRelative":"PluginDocs/Web/Index.md"}');export{e as data}; diff --git a/assets/index.html-4f366004.js b/assets/index.html-4f366004.js new file mode 100644 index 0000000..78ea700 --- /dev/null +++ b/assets/index.html-4f366004.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-12b535db","path":"/Docs/","title":"✨ 简介","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"🚧 | 简介","slug":"🚧-简介","link":"#🚧-简介","children":[]},{"level":2,"title":"🎉 | 特性","slug":"🎉-特性","link":"#🎉-特性","children":[]}],"git":{"updatedTime":1673158677000,"contributors":[{"name":"Harry-zklcdc","email":"1269158832@qq.com","commits":2}]},"filePathRelative":"Docs/README.md"}');export{e as data}; diff --git a/assets/index.html-550593ad.js b/assets/index.html-550593ad.js new file mode 100644 index 0000000..80793ae --- /dev/null +++ b/assets/index.html-550593ad.js @@ -0,0 +1 @@ +import{_ as t,p as s,q as c,R as e,t as a}from"./framework-cc651620.js";const n={},o=e("h2",{id:"关于我们",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#关于我们","aria-hidden":"true"},"#"),a(" 关于我们")],-1),r=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"提示"),e("p",null,"关于我们正在建设中...")],-1),i=[o,r];function _(d,l){return s(),c("div",null,i)}const u=t(n,[["render",_],["__file","index.html.vue"]]);export{u as default}; diff --git a/assets/index.html-5ff51570.js b/assets/index.html-5ff51570.js new file mode 100644 index 0000000..9f97b1c --- /dev/null +++ b/assets/index.html-5ff51570.js @@ -0,0 +1 @@ +import{_ as l,M as n,p as i,q as o,R as e,t,N as r,a1 as s}from"./framework-cc651620.js";const d={},h=s(' # ✨ 简介
# Hello 🌈 HiperLink 你好 🔗 嗨皮立刻
# 🚧 | 简介
',5),c=e("code",null,"Golang",-1),u=e("code",null,"Vue",-1),_={href:"https://www.the.bb/",target:"_blank",rel:"noopener noreferrer"},p=e("h2",{id:"🎉-特性",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#🎉-特性","aria-hidden":"true"},"#"),t(" 🎉 | 特性")],-1),f=e("ul",null,[e("li",null,"✅ 全平台"),e("li",null,"✅ 轻量化"),e("li",null,"✅ 插件化"),e("li",null,"✅ 高性能"),e("li",null,"✅ 易用性")],-1);function m(b,g){const a=n("ExternalLinkIcon");return i(),o("div",null,[h,e("p",null,[t("采用 "),c,t(" + "),u,t(" 技术栈, 基于 "),e("a",_,[t("Hiper"),r(a)]),t(" 的插件化、轻量化互联互通平台 🎉")]),p,f])}const k=l(d,[["render",m],["__file","index.html.vue"]]);export{k as default}; diff --git a/assets/index.html-7b9a0856.js b/assets/index.html-7b9a0856.js new file mode 100644 index 0000000..e6cb3a7 --- /dev/null +++ b/assets/index.html-7b9a0856.js @@ -0,0 +1 @@ +import{_ as e,p as t,q as c}from"./framework-cc651620.js";const n={};function _(r,o){return t(),c("div")}const a=e(n,[["render",_],["__file","index.html.vue"]]);export{a as default}; diff --git a/assets/index.html-86b4a8cc.js b/assets/index.html-86b4a8cc.js new file mode 100644 index 0000000..d5a4013 --- /dev/null +++ b/assets/index.html-86b4a8cc.js @@ -0,0 +1 @@ +import{_ as t,p as s,q as c,R as e,t as a}from"./framework-cc651620.js";const n={},o=e("h2",{id:"插件市场",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#插件市场","aria-hidden":"true"},"#"),a(" 插件市场")],-1),r=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"提示"),e("p",null,"插件市场正在建设中...")],-1),i=[o,r];function _(d,l){return s(),c("div",null,i)}const u=t(n,[["render",_],["__file","index.html.vue"]]);export{u as default}; diff --git a/assets/index.html-8704499c.js b/assets/index.html-8704499c.js new file mode 100644 index 0000000..922e6d2 --- /dev/null +++ b/assets/index.html-8704499c.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-8daa1a0e","path":"/","title":"","lang":"zh-CN","frontmatter":{"externalLinkIcon":false,"home":true,"heroImage":"favicon.ico","heroHeight":260,"heroText":"🌈 HiperLink | 嗨皮立刻 🔗","tagline":"基于 Hiper 的插件化、轻量化互联互通平台 🎉","actions":[{"text":"立即下载","link":"https://github.com/Hiper-Link/HiperLink-core/releases","type":"secondary"},{"text":"快速上手","link":"/Docs/Start.html","type":"primary"}],"features":[{"title":"全平台","details":"无论使用 Windows 或是 macOS,亦或是 Linux,皆可立地腾飞,让你能做的更多,做什么都更快,工作娱乐全放得开"},{"title":"插件化","details":"别看轻,别轻看,万物皆可插件化,互联只需一键,体验由你决定"},{"title":"高性能","details":"采用 Golang + Vue 技术栈,轻快如风,快接快传,好快意"}],"footer":"Copyright © 2022-present HiperLink Team"},"headers":[],"git":{"updatedTime":1673159058000,"contributors":[{"name":"Harry-zklcdc","email":"1269158832@qq.com","commits":4}]},"filePathRelative":"README.md"}');export{e as data}; diff --git a/assets/index.html-9e9e82fb.js b/assets/index.html-9e9e82fb.js new file mode 100644 index 0000000..847feb1 --- /dev/null +++ b/assets/index.html-9e9e82fb.js @@ -0,0 +1 @@ +import{_ as e,p as c,q as o,a1 as d}from"./framework-cc651620.js";const t={},n=d('嗨皮立刻, 英文名: HiperLink
# 简介
注意
HiperLink仍然在测试阶段,此文档可能随时变更。
HiperLink插件(以下简称插件)可以使用任何支持netRPC或gRPC通讯的语言编写。
我们建议你使用
Golang
进行插件开发。提示
net/rpc
只有Golang
支持,所以本文档会优先注重多语言支持的gRPC
库。
gRPC
在理论上支持C/C++
、C#
、Dart
、Go
、Java
、Kotlin
、Node.js
、Objective-C
、PHP
、Python
、Ruby
等语言。HiperLink 需要支持
多平台
,你所选用的语言应该尽可能的支持更多平台,因此Objective-C
,PHP
等选项被不幸的排除在外了。如果你准备好了,那让我们开始吧!
',6),i=[n];function a(s,p){return c(),o("div",null,i)}const l=e(t,[["render",a],["__file","index.html.vue"]]);export{l as default}; diff --git a/assets/index.html-d2bbbcfd.js b/assets/index.html-d2bbbcfd.js new file mode 100644 index 0000000..e670989 --- /dev/null +++ b/assets/index.html-d2bbbcfd.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-3e214e9b","path":"/About/","title":"","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"关于我们","slug":"关于我们","link":"#关于我们","children":[]}],"git":{"updatedTime":1673106873000,"contributors":[{"name":"Harry-zklcdc","email":"1269158832@qq.com","commits":1}]},"filePathRelative":"About/README.md"}');export{e as data}; diff --git a/assets/index.html-db82fc2e.js b/assets/index.html-db82fc2e.js new file mode 100644 index 0000000..a9503ac --- /dev/null +++ b/assets/index.html-db82fc2e.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-6bc6c5b0","path":"/PluginDocs/","title":"简介","lang":"zh-CN","frontmatter":{},"headers":[],"git":{"updatedTime":1673830380000,"contributors":[{"name":"Harry-zklcdc","email":"1269158832@qq.com","commits":3},{"name":"Ceyase","email":"jjcyf@foxmail.com","commits":1}]},"filePathRelative":"PluginDocs/README.md"}');export{e as data}; diff --git a/assets/index.html-ef97b19a.js b/assets/index.html-ef97b19a.js new file mode 100644 index 0000000..a9b9325 --- /dev/null +++ b/assets/index.html-ef97b19a.js @@ -0,0 +1,140 @@ +import{_ as p,M as o,p as c,q as e,R as n,t as a,N as l,a1 as s}from"./framework-cc651620.js";const u="/img/PluginDocs/Example-1.png",k={},i=s('# 前端
对于每个插件,在其文件夹下都有
src
子文件夹,此文件夹内部有两个文件:index.html
与config.html
。',3),r=n("code",null,"HTML",-1),g=n("code",null,"JavaScript",-1),v={href:"https://vuetify.cn/zh-Hans/",target:"_blank",rel:"noopener noreferrer"},q=s(`
- index.html 为插件页面的入口点
- config.html 为插件的配置页面
以下是一个用于范例的
index.html
页面代码:<div class="v-container"> + <div class="v-row"> + <div class="v-col-sm-7 v-col-12"> + <div class="v-card v-card--flat v-theme--light v-card--density-default v-card--variant-elevated" style="background-color: rgb(242, 245, 254); border-radius: 12px; margin-top: -8px;"> + <div class="v-card-title" style="margin-top: 12px;"> + <strong>这是一个卡片</strong> + <div class="v-card-text"> + <div style="overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 7; -webkit-box-orient: vertical;"> + <div class="v-input v-input--horizontal v-input--density-default v-text-field"> + <div class="v-input__control"> + <div class="v-field v-field--active v-field--has-background v-field--variant-filled v-theme--light" role="textbox" style="background-color: rgb(242, 245, 254);"> + <div class="v-field__overlay"> + </div> + <div class="v-field__loader"> + <div class="v-progress-linear v-theme--light" role="progressbar" aria-hidden="true" aria-valuemin="0" aria-valuemax="100" style="height: 0px; --v-progress-linear-height:2px;"> + <div class="v-progress-linear__background bg-info" style="width: 100%;"> + </div> + <div class="v-progress-linear__indeterminate"> + <div class="v-progress-linear__indeterminate long bg-info"> + </div> + <div class="v-progress-linear__indeterminate short bg-info"> + </div> + </div> + </div> + </div> + <div class="v-field__field" data-no-activator=""> + <label class="v-label v-field-label v-field-label--floating" aria-hidden="true" for="input-887">这是一个输入框</label> + <input size="1" type="text" id="otherip" class="v-field__input"> + </div> + <div class="v-field__outline"> + </div> + </div> + </div> + <div class="v-input__details"> + <div class="v-messages"> + </div> + </div> + </div> + </div> + </div> + <div class="v-card-actions" style="margin-top: -24px;"> + <div style="float: right;"> + <button type="button" onclick="" class="v-btn v-theme--light text-info v-btn--density-default v-btn--size-default v-btn--variant-text" style="font-size: 16px;"> + <span class="v-btn__overlay"> + </span> + <span class="v-btn__underlay"> + </span> + <span class="v-btn__content" data-no-activator="">一个小按钮</span> + </button> + </div> + </div> + <span class="v-card__underlay"> + </span> + </div> + </div> + </div> + <div class="v-col-sm-5 v-col-12"> + <div class="v-card v-card--flat v-theme--light v-card--density-default v-card--variant-elevated" style="background-color: rgb(242, 245, 254); border-radius: 12px; margin-top: -8px;"> + <div class="v-card__loader"> + <div class="v-progress-linear v-theme--light" role="progressbar" aria-hidden="true" aria-valuemin="0" aria-valuemax="100" style="height: 0px; --v-progress-linear-height:2px;"> + <div class="v-progress-linear__background" style="width: 100%;"> + </div> + <div class="v-progress-linear__indeterminate"> + <div class="v-progress-linear__indeterminate long"> + </div> + <div class="v-progress-linear__indeterminate short"> + </div> + </div> + </div> + </div> + <div class="v-card-title" style="margin-top: 12px;"> + <strong>这是另一个卡片</strong> + <div style="margin-top: 4px;font-size: 1px;">一些简单的注释,下面是一个列表</div> + </div> + <div class="v-card-text"> + <div class="v-table v-theme--light v-table--density-compact"> + <div class="v-table__wrapper"> + <table> + <tbody> + <tr> + <td>1</td> + <td> + <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="version-rustdesk">1 + <span class="v-chip__underlay"></span> + </span> + </td> + </tr> + <tr> + <td>11</td> + <td> + <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="ip">2 + <span class="v-chip__underlay"></span> + </span> + </td> + </tr> + <tr> + <td>111</td> + <td> + <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="password">3 + <span class="v-chip__underlay"></span> + </span> + </td> + </tr> + <tr> + <td>1111</td> + <td> + <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="password">4 + <span class="v-chip__underlay"></span> + </span> + </td> + </tr> + <tr> + <td>1111</td> + <td> + <span class="v-chip v-theme--light text-info v-chip--density-default v-chip--size-x-small v-chip--variant-tonal" draggable="false" id="password">5 + <span class="v-chip__underlay"></span> + </span> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <span class="v-card__underlay"> + </span> + </div> + <a class="v-btn v-btn--block v-theme--light v-btn--density-default rounded-xl v-btn--size-x-large v-btn--variant-tonal" style="color: rgb(106, 164, 255); caret-color: rgb(106, 164, 255); margin-top: 16px;" onclick="" id="actionButton"> + <span class="v-btn__overlay"> + </span> + <span class="v-btn__underlay"> + </span> + <span class="v-btn__content" data-no-activator=""> + <strong id="action">一个大按钮</strong> + </span> + </a> + </div> + </div> +</div> +
效果如下:
',3);function d(m,h){const t=o("ExternalLinkIcon");return c(),e("div",null,[i,n("p",null,[a("编写插件页面需要你有基本的"),r,a("与"),g,a("知识,HiperLink内置了"),n("a",v,[a("Vuetify"),l(t)]),a(" 框架,因此您可以直接开始!")]),q])}const y=p(k,[["render",d],["__file","index.html.vue"]]);export{y as default}; diff --git a/assets/search-0782d0d1.svg b/assets/search-0782d0d1.svg new file mode 100644 index 0000000..03d8391 --- /dev/null +++ b/assets/search-0782d0d1.svg @@ -0,0 +1 @@ + diff --git a/assets/style-0596657c.css b/assets/style-0596657c.css new file mode 100644 index 0000000..7f83c24 --- /dev/null +++ b/assets/style-0596657c.css @@ -0,0 +1 @@ +:root{--external-link-icon-color: #aaa}.external-link-icon{position:relative;display:inline-block;color:var(--external-link-icon-color);vertical-align:middle;top:-1px}@media print{.external-link-icon{display:none}}.external-link-icon-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}:root{--medium-zoom-z-index: 100;--medium-zoom-bg-color: #ffffff;--medium-zoom-opacity: 1}.medium-zoom-overlay{background-color:var(--medium-zoom-bg-color)!important;z-index:var(--medium-zoom-z-index)}.medium-zoom-overlay~img{z-index:calc(var(--medium-zoom-z-index) + 1)}.medium-zoom--opened .medium-zoom-overlay{opacity:var(--medium-zoom-opacity)}:root{--nprogress-color: #29d;--nprogress-z-index: 1031}#nprogress{pointer-events:none}#nprogress .bar{background:var(--nprogress-color);position:fixed;z-index:var(--nprogress-z-index);top:0;left:0;width:100%;height:2px}:root{--c-brand: #3eaf7c;--c-brand-light: #4abf8a;--c-bg: #ffffff;--c-bg-light: #f3f4f5;--c-bg-lighter: #eeeeee;--c-bg-dark: #ebebec;--c-bg-darker: #e6e6e6;--c-bg-navbar: var(--c-bg);--c-bg-sidebar: var(--c-bg);--c-bg-arrow: #cccccc;--c-text: #2c3e50;--c-text-accent: var(--c-brand);--c-text-light: #3a5169;--c-text-lighter: #4e6e8e;--c-text-lightest: #6a8bad;--c-text-quote: #999999;--c-border: #eaecef;--c-border-dark: #dfe2e5;--c-tip: #42b983;--c-tip-bg: var(--c-bg-light);--c-tip-title: var(--c-text);--c-tip-text: var(--c-text);--c-tip-text-accent: var(--c-text-accent);--c-warning: #ffc310;--c-warning-bg: #fffae3;--c-warning-bg-light: #fff3ba;--c-warning-bg-lighter: #fff0b0;--c-warning-border-dark: #f7dc91;--c-warning-details-bg: #fff5ca;--c-warning-title: #f1b300;--c-warning-text: #746000;--c-warning-text-accent: #edb100;--c-warning-text-light: #c1971c;--c-warning-text-quote: #ccab49;--c-danger: #f11e37;--c-danger-bg: #ffe0e0;--c-danger-bg-light: #ffcfde;--c-danger-bg-lighter: #ffc9c9;--c-danger-border-dark: #f1abab;--c-danger-details-bg: #ffd4d4;--c-danger-title: #ed1e2c;--c-danger-text: #660000;--c-danger-text-accent: #bd1a1a;--c-danger-text-light: #b5474d;--c-danger-text-quote: #c15b5b;--c-details-bg: #eeeeee;--c-badge-tip: var(--c-tip);--c-badge-warning: #ecc808;--c-badge-warning-text: var(--c-bg);--c-badge-danger: #dc2626;--c-badge-danger-text: var(--c-bg);--t-color: .3s ease;--t-transform: .3s ease;--code-bg-color: #282c34;--code-hl-bg-color: rgba(0, 0, 0, .66);--code-ln-color: #9e9e9e;--code-ln-wrapper-width: 3.5rem;--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;--font-family-code: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;--navbar-height: 3.6rem;--navbar-padding-v: .7rem;--navbar-padding-h: 1.5rem;--sidebar-width: 20rem;--sidebar-width-mobile: calc(var(--sidebar-width) * .82);--content-width: 740px;--homepage-width: 960px}.back-to-top{--back-to-top-color: var(--c-brand);--back-to-top-color-hover: var(--c-brand-light)}.DocSearch{--docsearch-primary-color: var(--c-brand);--docsearch-text-color: var(--c-text);--docsearch-highlight-color: var(--c-brand);--docsearch-muted-color: var(--c-text-quote);--docsearch-container-background: rgba(9, 10, 17, .8);--docsearch-modal-background: var(--c-bg-light);--docsearch-searchbox-background: var(--c-bg-lighter);--docsearch-searchbox-focus-background: var(--c-bg);--docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand);--docsearch-hit-color: var(--c-text-light);--docsearch-hit-active-color: var(--c-bg);--docsearch-hit-background: var(--c-bg);--docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark);--docsearch-footer-background: var(--c-bg)}.external-link-icon{--external-link-icon-color: var(--c-text-quote)}.medium-zoom-overlay{--medium-zoom-bg-color: var(--c-bg)}#nprogress{--nprogress-color: var(--c-brand)}.pwa-popup{--pwa-popup-text-color: var(--c-text);--pwa-popup-bg-color: var(--c-bg);--pwa-popup-border-color: var(--c-brand);--pwa-popup-shadow: 0 4px 16px var(--c-brand);--pwa-popup-btn-text-color: var(--c-bg);--pwa-popup-btn-bg-color: var(--c-brand);--pwa-popup-btn-hover-bg-color: var(--c-brand-light)}.search-box{--search-bg-color: var(--c-bg);--search-accent-color: var(--c-brand);--search-text-color: var(--c-text);--search-border-color: var(--c-border);--search-item-text-color: var(--c-text-lighter);--search-item-focus-bg-color: var(--c-bg-light)}html.dark{--c-brand: #3aa675;--c-brand-light: #349469;--c-bg: #22272e;--c-bg-light: #2b313a;--c-bg-lighter: #262c34;--c-bg-dark: #343b44;--c-bg-darker: #37404c;--c-text: #adbac7;--c-text-light: #96a7b7;--c-text-lighter: #8b9eb0;--c-text-lightest: #8094a8;--c-border: #3e4c5a;--c-border-dark: #34404c;--c-tip: #318a62;--c-warning: #e0ad15;--c-warning-bg: #2d2f2d;--c-warning-bg-light: #423e2a;--c-warning-bg-lighter: #44442f;--c-warning-border-dark: #957c35;--c-warning-details-bg: #39392d;--c-warning-title: #fdca31;--c-warning-text: #d8d96d;--c-warning-text-accent: #ffbf00;--c-warning-text-light: #ddb84b;--c-warning-text-quote: #ccab49;--c-danger: #fc1e38;--c-danger-bg: #39232c;--c-danger-bg-light: #4b2b35;--c-danger-bg-lighter: #553040;--c-danger-border-dark: #a25151;--c-danger-details-bg: #482936;--c-danger-title: #fc2d3b;--c-danger-text: #ea9ca0;--c-danger-text-accent: #fd3636;--c-danger-text-light: #d9777c;--c-danger-text-quote: #d56b6b;--c-details-bg: #323843;--c-badge-warning: var(--c-warning);--c-badge-warning-text: #3c2e05;--c-badge-danger: var(--c-danger);--c-badge-danger-text: #401416;--code-hl-bg-color: #363b46}html.dark .DocSearch{--docsearch-logo-color: var(--c-text);--docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;--docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 0 2px 2px 0 rgba(3, 4, 9, .3);--docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21);--docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, .5), 0 -4px 8px 0 rgba(0, 0, 0, .2)}html,body{padding:0;margin:0;background-color:var(--c-bg);transition:background-color var(--t-color)}html.dark{color-scheme:dark}html{font-size:16px}body{font-family:var(--font-family);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:1rem;color:var(--c-text)}a{font-weight:500;color:var(--c-text-accent);text-decoration:none;overflow-wrap:break-word}p a code{font-weight:400;color:var(--c-text-accent)}kbd{font-family:var(--font-family-code);color:var(--c-text);background:var(--c-bg-lighter);border:solid .15rem var(--c-border-dark);border-bottom:solid .25rem var(--c-border-dark);border-radius:.15rem;padding:0 .15em}code{font-family:var(--font-family-code);color:var(--c-text-lighter);padding:.25rem .5rem;margin:0;font-size:.85em;background-color:var(--c-bg-light);border-radius:3px;overflow-wrap:break-word;transition:background-color var(--t-color)}blockquote{font-size:1rem;color:var(--c-text-quote);border-left:.2rem solid var(--c-border-dark);margin:1rem 0;padding:.25rem 0 .25rem 1rem;overflow-wrap:break-word}blockquote>p{margin:0}ul,ol{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25;overflow-wrap:break-word}h1:focus-visible,h2:focus-visible,h3:focus-visible,h4:focus-visible,h5:focus-visible,h6:focus-visible{outline:none}h1:hover .header-anchor,h2:hover .header-anchor,h3:hover .header-anchor,h4:hover .header-anchor,h5:hover .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid var(--c-border);transition:border-color var(--t-color)}h3{font-size:1.35rem}h4{font-size:1.15rem}h5{font-size:1.05rem}h6{font-size:1rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}@media print{a.header-anchor{display:none}}a.header-anchor:hover{text-decoration:none}a.header-anchor:focus-visible{opacity:1}@media print{a[href^="http://"]:after,a[href^="https://"]:after{content:" (" attr(href) ") "}}p,ul,ol{line-height:1.7;overflow-wrap:break-word}hr{border:0;border-top:1px solid var(--c-border)}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto;transition:border-color var(--t-color)}tr{border-top:1px solid var(--c-border-dark);transition:border-color var(--t-color)}tr:nth-child(2n){background-color:var(--c-bg-light);transition:background-color var(--t-color)}tr:nth-child(2n) code{background-color:var(--c-bg-dark)}th,td{padding:.6em 1em;border:1px solid var(--c-border-dark);transition:border-color var(--t-color)}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:6px solid var(--c-bg-arrow)}.arrow.down{border-left:4px solid transparent;border-right:4px solid transparent;border-top:6px solid var(--c-bg-arrow)}.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:6px solid var(--c-bg-arrow)}.arrow.left{border-top:4px solid transparent;border-bottom:4px solid transparent;border-right:6px solid var(--c-bg-arrow)}.badge{display:inline-block;font-size:14px;font-weight:600;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:var(--c-bg);vertical-align:top;transition:color var(--t-color),background-color var(--t-color)}.badge.tip{background-color:var(--c-badge-tip)}.badge.warning{background-color:var(--c-badge-warning);color:var(--c-badge-warning-text)}.badge.danger{background-color:var(--c-badge-danger);color:var(--c-badge-danger-text)}.badge+.badge{margin-left:5px}code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:var(--font-family-code);font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.comment,.token.block-comment,.token.prolog,.token.doctype,.token.cdata{color:#999}.token.punctuation{color:#ccc}.token.tag,.token.attr-name,.token.namespace,.token.deleted{color:#ec5975}.token.function-name{color:#6196cc}.token.boolean,.token.number,.token.function{color:#f08d49}.token.property,.token.class-name,.token.constant,.token.symbol{color:#f8c555}.token.selector,.token.important,.token.atrule,.token.keyword,.token.builtin{color:#cc99cd}.token.string,.token.char,.token.attr-value,.token.regex,.token.variable{color:#7ec699}.token.operator,.token.entity,.token.url{color:#67cdcc}.token.important,.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.375;padding:1.3rem 1.5rem;margin:.85rem 0;border-radius:6px;overflow:auto}.theme-default-content pre code,.theme-default-content pre[class*=language-] code{color:#fff;padding:0;background-color:transparent!important;border-radius:0;overflow-wrap:unset;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.theme-default-content .line-number{font-family:var(--font-family-code)}div[class*=language-]{position:relative;background-color:var(--code-bg-color);border-radius:6px}div[class*=language-]:before{content:attr(data-ext);position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:var(--code-ln-color)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent!important;position:relative;z-index:1}div[class*=language-] .highlight-lines{-webkit-user-select:none;-moz-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.375}div[class*=language-] .highlight-lines .highlight-line{background-color:var(--code-hl-bg-color)}div[class*=language-]:not(.line-numbers-mode) .line-numbers{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlight-line{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlight-line:before{content:" ";position:absolute;z-index:2;left:0;top:0;display:block;width:var(--code-ln-wrapper-width);height:100%}div[class*=language-].line-numbers-mode pre{margin-left:var(--code-ln-wrapper-width);padding-left:1rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers{position:absolute;top:0;width:var(--code-ln-wrapper-width);text-align:center;color:var(--code-ln-color);padding-top:1.25rem;line-height:1.375;counter-reset:line-number}div[class*=language-].line-numbers-mode .line-numbers .line-number{position:relative;z-index:3;-webkit-user-select:none;-moz-user-select:none;user-select:none;height:1.375em}div[class*=language-].line-numbers-mode .line-numbers .line-number:before{counter-increment:line-number;content:counter(line-number);font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;top:0;left:0;width:var(--code-ln-wrapper-width);height:100%;border-radius:6px 0 0 6px;border-right:1px solid var(--code-hl-bg-color)}@media (max-width: 419px){.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.code-group__nav{margin-top:.85rem;margin-bottom:calc(-1.7rem - 6px);padding-bottom:calc(1.7rem - 6px);padding-left:10px;padding-top:10px;border-top-left-radius:6px;border-top-right-radius:6px;background-color:var(--code-bg-color)}.code-group__ul{margin:auto 0;padding-left:0;display:inline-flex;list-style:none}.code-group__nav-tab{border:0;padding:5px;cursor:pointer;background-color:transparent;font-size:.85em;line-height:1.4;color:#ffffffe6;font-weight:600}.code-group__nav-tab:focus{outline:none}.code-group__nav-tab:focus-visible{outline:1px solid rgba(255,255,255,.9)}.code-group__nav-tab-active{border-bottom:var(--c-brand) 1px solid}@media (max-width: 419px){.code-group__nav{margin-left:-1.5rem;margin-right:-1.5rem;border-radius:0}}.code-group-item{display:none}.code-group-item__active{display:block}.code-group-item>pre{background-color:orange}.custom-container{transition:color var(--t-color),border-color var(--t-color),background-color var(--t-color)}.custom-container .custom-container-title{font-weight:600}.custom-container .custom-container-title:not(:only-child){margin-bottom:-.4rem}.custom-container.tip,.custom-container.warning,.custom-container.danger{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-container.tip{border-color:var(--c-tip);background-color:var(--c-tip-bg);color:var(--c-tip-text)}.custom-container.tip .custom-container-title{color:var(--c-tip-title)}.custom-container.tip a{color:var(--c-tip-text-accent)}.custom-container.tip code{background-color:var(--c-bg-dark)}.custom-container.warning{border-color:var(--c-warning);background-color:var(--c-warning-bg);color:var(--c-warning-text)}.custom-container.warning .custom-container-title{color:var(--c-warning-title)}.custom-container.warning a{color:var(--c-warning-text-accent)}.custom-container.warning blockquote{border-left-color:var(--c-warning-border-dark);color:var(--c-warning-text-quote)}.custom-container.warning code{color:var(--c-warning-text-light);background-color:var(--c-warning-bg-light)}.custom-container.warning details{background-color:var(--c-warning-details-bg)}.custom-container.warning details code{background-color:var(--c-warning-bg-lighter)}.custom-container.warning .external-link-icon{--external-link-icon-color: var(--c-warning-text-quote)}.custom-container.danger{border-color:var(--c-danger);background-color:var(--c-danger-bg);color:var(--c-danger-text)}.custom-container.danger .custom-container-title{color:var(--c-danger-title)}.custom-container.danger a{color:var(--c-danger-text-accent)}.custom-container.danger blockquote{border-left-color:var(--c-danger-border-dark);color:var(--c-danger-text-quote)}.custom-container.danger code{color:var(--c-danger-text-light);background-color:var(--c-danger-bg-light)}.custom-container.danger details{background-color:var(--c-danger-details-bg)}.custom-container.danger details code{background-color:var(--c-danger-bg-lighter)}.custom-container.danger .external-link-icon{--external-link-icon-color: var(--c-danger-text-quote)}.custom-container.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:var(--c-details-bg)}.custom-container.details code{background-color:var(--c-bg-darker)}.custom-container.details h4{margin-top:0}.custom-container.details figure:last-child,.custom-container.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-container.details summary{outline:none;cursor:pointer}.home{padding:var(--navbar-height) 2rem 0;max-width:var(--homepage-width);margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero h1,.home .hero .description,.home .hero .actions{margin:1.8rem auto}.home .hero .actions{display:flex;flex-wrap:wrap;gap:1rem;justify-content:center}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:var(--c-text-lightest)}.home .hero .action-button{display:inline-block;font-size:1.2rem;padding:.8rem 1.6rem;border-width:2px;border-style:solid;border-radius:4px;transition:background-color var(--t-color);box-sizing:border-box}.home .hero .action-button.primary{color:var(--c-bg);background-color:var(--c-brand);border-color:var(--c-brand)}.home .hero .action-button.primary:hover{background-color:var(--c-brand-light)}.home .hero .action-button.secondary{color:var(--c-brand);background-color:var(--c-bg);border-color:var(--c-brand)}.home .hero .action-button.secondary:hover{color:var(--c-bg);background-color:var(--c-brand-light)}.home .features{border-top:1px solid var(--c-border);transition:border-color var(--t-color);padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:var(--c-text-light)}.home .feature p{color:var(--c-text-lighter)}.home .theme-default-content{padding:0;margin:0}.home .footer{padding:2.5rem;border-top:1px solid var(--c-border);text-align:center;color:var(--c-text-lighter);transition:border-color var(--t-color)}@media (max-width: 719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width: 419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero h1,.home .hero .description,.home .hero .actions{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.page{padding-top:var(--navbar-height);padding-left:var(--sidebar-width)}.navbar{position:fixed;z-index:20;top:0;left:0;right:0;height:var(--navbar-height);box-sizing:border-box;border-bottom:1px solid var(--c-border);background-color:var(--c-bg-navbar);transition:background-color var(--t-color),border-color var(--t-color)}.sidebar{font-size:16px;width:var(--sidebar-width);position:fixed;z-index:10;margin:0;top:var(--navbar-height);left:0;bottom:0;box-sizing:border-box;border-right:1px solid var(--c-border);overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--c-brand) var(--c-border);background-color:var(--c-bg-sidebar);transition:transform var(--t-transform),background-color var(--t-color),border-color var(--t-color)}.sidebar::-webkit-scrollbar{width:7px}.sidebar::-webkit-scrollbar-track{background-color:var(--c-border)}.sidebar::-webkit-scrollbar-thumb{background-color:var(--c-brand)}.sidebar-mask{position:fixed;z-index:9;top:0;left:0;width:100vw;height:100vh;display:none}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(1){transform:rotate(45deg) translate3d(5.5px,5.5px,0)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(2){transform:scale3d(0,1,1)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(3){transform:rotate(-45deg) translate3d(6px,-6px,0)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(1),.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(3){transform-origin:center}.theme-container.no-navbar .theme-default-content h1,.theme-container.no-navbar .theme-default-content h2,.theme-container.no-navbar .theme-default-content h3,.theme-container.no-navbar .theme-default-content h4,.theme-container.no-navbar .theme-default-content h5,.theme-container.no-navbar .theme-default-content h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .page{padding-top:0}.theme-container.no-navbar .sidebar{top:0}.theme-container.no-sidebar .sidebar{display:none}@media (max-width: 719px){.theme-container.no-sidebar .sidebar{display:block}}.theme-container.no-sidebar .page{padding-left:0}.theme-default-content a:hover{text-decoration:underline}.theme-default-content img{max-width:100%}.theme-default-content h1,.theme-default-content h2,.theme-default-content h3,.theme-default-content h4,.theme-default-content h5,.theme-default-content h6{margin-top:calc(.5rem - var(--navbar-height));padding-top:calc(1rem + var(--navbar-height));margin-bottom:0}.theme-default-content h1:first-child,.theme-default-content h2:first-child,.theme-default-content h3:first-child,.theme-default-content h4:first-child,.theme-default-content h5:first-child,.theme-default-content h6:first-child{margin-bottom:1rem}.theme-default-content h1:first-child+p,.theme-default-content h1:first-child+pre,.theme-default-content h1:first-child+.custom-container,.theme-default-content h2:first-child+p,.theme-default-content h2:first-child+pre,.theme-default-content h2:first-child+.custom-container,.theme-default-content h3:first-child+p,.theme-default-content h3:first-child+pre,.theme-default-content h3:first-child+.custom-container,.theme-default-content h4:first-child+p,.theme-default-content h4:first-child+pre,.theme-default-content h4:first-child+.custom-container,.theme-default-content h5:first-child+p,.theme-default-content h5:first-child+pre,.theme-default-content h5:first-child+.custom-container,.theme-default-content h6:first-child+p,.theme-default-content h6:first-child+pre,.theme-default-content h6:first-child+.custom-container{margin-top:2rem}@media (max-width: 959px){.sidebar{font-size:15px;width:var(--sidebar-width-mobile)}.page{padding-left:var(--sidebar-width-mobile)}}@media (max-width: 719px){.sidebar{top:0;padding-top:var(--navbar-height);transform:translate(-100%)}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translate(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width: 419px){h1{font-size:1.9rem}}.navbar{--navbar-line-height: calc( var(--navbar-height) - 2 * var(--navbar-padding-v) );padding:var(--navbar-padding-v) var(--navbar-padding-h);line-height:var(--navbar-line-height)}.navbar .logo{height:var(--navbar-line-height);margin-right:var(--navbar-padding-v);vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:var(--c-text);position:relative}.navbar .navbar-items-wrapper{display:flex;position:absolute;box-sizing:border-box;top:var(--navbar-padding-v);right:var(--navbar-padding-h);height:var(--navbar-line-height);padding-left:var(--navbar-padding-h);white-space:nowrap;font-size:.9rem}.navbar .navbar-items-wrapper .search-box{flex:0 0 auto;vertical-align:top}@media screen and (max-width: 719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.navbar-items{display:inline-block}@media print{.navbar-items{display:none}}.navbar-items a{display:inline-block;line-height:1.4rem;color:inherit}.navbar-items a:hover,.navbar-items a.router-link-active{color:var(--c-text)}.navbar-items .navbar-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:var(--navbar-line-height)}.navbar-items .navbar-item:first-child{margin-left:0}.navbar-items .navbar-item>a:hover,.navbar-items .navbar-item>a.router-link-active{margin-bottom:-2px;border-bottom:2px solid var(--c-text-accent)}@media (max-width: 719px){.navbar-items .navbar-item{margin-left:0}.navbar-items .navbar-item>a:hover,.navbar-items .navbar-item>a.router-link-active{margin-bottom:0;border-bottom:none}.navbar-items a:hover,.navbar-items a.router-link-active{color:var(--c-text-accent)}}.toggle-sidebar-button{position:absolute;top:.6rem;left:1rem;display:none;padding:.6rem;cursor:pointer}.toggle-sidebar-button .icon{display:flex;flex-direction:column;justify-content:center;align-items:center;width:1.25rem;height:1.25rem;cursor:inherit}.toggle-sidebar-button .icon span{display:inline-block;width:100%;height:2px;border-radius:2px;background-color:var(--c-text);transition:transform var(--t-transform)}.toggle-sidebar-button .icon span:nth-child(2){margin:6px 0}@media screen and (max-width: 719px){.toggle-sidebar-button{display:block}}.toggle-color-mode-button{display:flex;margin:auto;margin-left:1rem;border:0;background:none;color:var(--c-text);opacity:.8;cursor:pointer}@media print{.toggle-color-mode-button{display:none}}.toggle-color-mode-button:hover{opacity:1}.toggle-color-mode-button .icon{width:1.25rem;height:1.25rem}.DocSearch{transition:background-color var(--t-color)}.navbar-dropdown-wrapper{cursor:pointer}.navbar-dropdown-wrapper .navbar-dropdown-title,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:transparent;border:none;font-weight:500;color:var(--c-text)}.navbar-dropdown-wrapper .navbar-dropdown-title:hover,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile:hover{border-color:transparent}.navbar-dropdown-wrapper .navbar-dropdown-title .arrow,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:none;font-weight:600;font-size:inherit}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile:hover{color:var(--c-text-accent)}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item{color:inherit;line-height:1.7rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle{margin:.45rem 0 0;border-top:1px solid var(--c-border);padding:1rem 0 .45rem;font-size:.9rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>span{padding:0 1.5rem 0 1.25rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>a{font-weight:inherit}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>a.router-link-active:after{display:none}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem-wrapper{padding:0;list-style:none}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem-wrapper .navbar-dropdown-subitem{font-size:.9em}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a:hover,.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active{color:var(--c-text-accent)}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid var(--c-text-accent);border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item:first-child .navbar-dropdown-subtitle{margin-top:0;padding-top:0;border-top:0}.navbar-dropdown-wrapper.mobile.open .navbar-dropdown-title,.navbar-dropdown-wrapper.mobile.open .navbar-dropdown-title-mobile{margin-bottom:.5rem}.navbar-dropdown-wrapper.mobile .navbar-dropdown-title,.navbar-dropdown-wrapper.mobile .navbar-dropdown-title-mobile{display:none}.navbar-dropdown-wrapper.mobile .navbar-dropdown-title-mobile{display:block}.navbar-dropdown-wrapper.mobile .navbar-dropdown{transition:height .1s ease-out;overflow:hidden}.navbar-dropdown-wrapper.mobile .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle{border-top:0;margin-top:0;padding-top:0;padding-bottom:0}.navbar-dropdown-wrapper.mobile .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle,.navbar-dropdown-wrapper.mobile .navbar-dropdown .navbar-dropdown-item>a{font-size:15px;line-height:2rem}.navbar-dropdown-wrapper.mobile .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem{font-size:14px;padding-left:1rem}.navbar-dropdown-wrapper:not(.mobile){height:1.8rem}.navbar-dropdown-wrapper:not(.mobile):hover .navbar-dropdown,.navbar-dropdown-wrapper:not(.mobile).open .navbar-dropdown{display:block!important}.navbar-dropdown-wrapper:not(.mobile).open:blur{display:none}.navbar-dropdown-wrapper:not(.mobile) .navbar-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:var(--c-bg-navbar);padding:.6rem 0;border:1px solid var(--c-border);border-bottom-color:var(--c-border-dark);text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}.page{padding-bottom:2rem;display:block}.page .theme-default-content{max-width:var(--content-width);margin:0 auto;padding:2rem 2.5rem;padding-top:0}@media (max-width: 959px){.page .theme-default-content{padding:2rem}}@media (max-width: 419px){.page .theme-default-content{padding:1.5rem}}.page-meta{max-width:var(--content-width);margin:0 auto;padding:1rem 2.5rem;overflow:auto}@media (max-width: 959px){.page-meta{padding:2rem}}@media (max-width: 419px){.page-meta{padding:1.5rem}}.page-meta .meta-item{cursor:default;margin-top:.8rem}.page-meta .meta-item .meta-item-label{font-weight:500;color:var(--c-text-lighter)}.page-meta .meta-item .meta-item-info{font-weight:400;color:var(--c-text-quote)}.page-meta .edit-link{display:inline-block;margin-right:.25rem}@media print{.page-meta .edit-link{display:none}}.page-meta .last-updated{float:right}@media (max-width: 719px){.page-meta .last-updated{font-size:.8em;float:none}.page-meta .contributors{font-size:.8em}}.page-nav{max-width:var(--content-width);margin:0 auto;padding:1rem 2.5rem 2rem;padding-bottom:0}@media (max-width: 959px){.page-nav{padding:2rem}}@media (max-width: 419px){.page-nav{padding:1.5rem}}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid var(--c-border);transition:border-color var(--t-color);padding-top:1rem;overflow:auto}.page-nav .prev a:before{content:"\2190"}.page-nav .next{float:right}.page-nav .next a:after{content:"\2192"}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .navbar-items{display:none;border-bottom:1px solid var(--c-border);transition:border-color var(--t-color);padding:.5rem 0 .75rem}.sidebar .navbar-items a{font-weight:600}.sidebar .navbar-items .navbar-item{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar .sidebar-items{padding:1.5rem 0}@media (max-width: 719px){.sidebar .navbar-items{display:block}.sidebar .navbar-items .navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar .sidebar-items{padding:1rem 0}}.sidebar-item{cursor:default;border-left:.25rem solid transparent;color:var(--c-text)}.sidebar-item:focus-visible{outline-width:1px;outline-offset:-1px}.sidebar-item.active:not(p.sidebar-heading){font-weight:600;color:var(--c-text-accent);border-left-color:var(--c-text-accent)}.sidebar-item.sidebar-heading{transition:color .15s ease;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0}.sidebar-item.sidebar-heading+.sidebar-item-children{transition:height .1s ease-out;overflow:hidden;margin-bottom:.75rem}.sidebar-item.collapsible{cursor:pointer}.sidebar-item.collapsible .arrow{position:relative;top:-.12em;left:.5em}.sidebar-item:not(.sidebar-heading){font-size:1em;font-weight:400;display:inline-block;margin:0;padding:.35rem 1rem .35rem 2rem;line-height:1.4;width:100%;box-sizing:border-box}.sidebar-item:not(.sidebar-heading)+.sidebar-item-children{padding-left:1rem;font-size:.95em}.sidebar-item-children .sidebar-item-children .sidebar-item:not(.sidebar-heading){padding:.25rem 1rem .25rem 1.75rem}.sidebar-item-children .sidebar-item-children .sidebar-item:not(.sidebar-heading).active{font-weight:500;border-left-color:transparent}a.sidebar-heading+.sidebar-item-children .sidebar-item:not(.sidebar-heading).active{border-left-color:transparent}a.sidebar-item{cursor:pointer}a.sidebar-item:hover{color:var(--c-text-accent)}.table-of-contents .badge{vertical-align:middle}.dropdown-enter-from,.dropdown-leave-to{height:0!important}.fade-slide-y-enter-active{transition:all .2s ease}.fade-slide-y-leave-active{transition:all .2s cubic-bezier(1,.5,.8,1)}.fade-slide-y-enter-from,.fade-slide-y-leave-to{transform:translateY(10px);opacity:0}:root{--back-to-top-z-index: 5;--back-to-top-color: #3eaf7c;--back-to-top-color-hover: #71cda3}.back-to-top{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;height:1.2rem;background-color:var(--back-to-top-color);-webkit-mask:url(/assets/back-to-top-8efcbe56.svg) no-repeat;mask:url(/assets/back-to-top-8efcbe56.svg) no-repeat;z-index:var(--back-to-top-z-index)}.back-to-top:hover{background-color:var(--back-to-top-color-hover)}@media (max-width: 959px){.back-to-top{display:none}}@media print{.back-to-top{display:none}}.back-to-top-enter-active,.back-to-top-leave-active{transition:opacity .3s}.back-to-top-enter-from,.back-to-top-leave-to{opacity:0}:root{--search-bg-color: #ffffff;--search-accent-color: #3eaf7c;--search-text-color: #2c3e50;--search-border-color: #eaecef;--search-item-text-color: #5d81a5;--search-item-focus-bg-color: #f3f4f5;--search-input-width: 8rem;--search-result-width: 20rem}.search-box{display:inline-block;position:relative;margin-left:1rem}@media print{.search-box{display:none}}.search-box input{-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:text;width:var(--search-input-width);height:2rem;color:var(--search-text-color);display:inline-block;border:1px solid var(--search-border-color);border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all ease .3s;background:var(--search-bg-color) url(/assets/search-0782d0d1.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:var(--search-accent-color)}.search-box .suggestions{background:var(--search-bg-color);width:var(--search-result-width);position:absolute;top:2rem;right:0;border:1px solid var(--search-border-color);border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion.focus{background-color:var(--search-item-focus-bg-color)}.search-box .suggestion.focus a{color:var(--search-accent-color)}.search-box .suggestion a{white-space:normal;color:var(--search-item-text-color)}.search-box .suggestion .page-title{font-weight:600}.search-box .suggestion .page-header{font-size:.9em;margin-left:.25em}@media (max-width: 719px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (max-width: 419px){.search-box input:focus{width:8rem}.search-box .suggestions{width:calc(100vw - 4rem);right:-.5rem}}:root{--pwa-popup-z-index: 10;--pwa-popup-text-color: #2c3e50;--pwa-popup-bg-color: #ffffff;--pwa-popup-border-color: #3eaf7c;--pwa-popup-shadow: 0 4px 16px var(--pwa-popup-border-color);--pwa-popup-btn-text-color: #ffffff;--pwa-popup-btn-bg-color: #3eaf7c;--pwa-popup-btn-hover-bg-color: #4abf8a}.pwa-popup{position:fixed;right:1em;bottom:1em;padding:1em;border:1px solid var(--pwa-popup-border-color);border-radius:3px;background-color:var(--pwa-popup-bg-color);box-shadow:var(--pwa-popup-shadow);text-align:center;z-index:var(--pwa-popup-z-index)}@media print{.pwa-popup{display:none}}.pwa-popup>button{cursor:pointer;margin-top:.5em;padding:.25em 2em;border:none;color:var(--pwa-popup-btn-text-color);background-color:var(--pwa-popup-btn-bg-color)}.pwa-popup>button:hover{background-color:var(--pwa-popup-btn-hover-bg-color)}.pwa-popup-enter-active,.pwa-popup-leave-active{transition:opacity .3s,transform .3s}.pwa-popup-enter-from,.pwa-popup-leave-to{opacity:0;transform:translateY(50%) scale(.5)} diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..89cc6fa54f43fbbef2878742cb82b7b9afb9dfac GIT binary patch literal 4683 zcmcII`9G9h^miVEu|-lLF!Xg`w3^Q zO!&A(xtU$QGp2?%tXbBJ;9vr`z)D{h<{xNf2OBC0$p>KX(iy{3cA;Yng<%0% RDz{FHr+wGe%TK=D`kk$+q?k39QY@8Lwr9}P)rS3*?&x2L zdtTMkh4PX~t`7m^g310H&V8pYPWqT17nc&A{wQd|;=w!VS-qKp&B(zp{mHzcWzIhB zrJ1m(qLA?Hp@?_^1H_R#|MtO|OAEq!<)rm_=nCZLge^jVPgP(;U`}9>ntNUu?Euur zOO7I6_bIV?=JqVYW2-Gt)1bGuME{-ahAN@MEZL^wm!nJO9 S2xP?5p)SW zgjln (?5R5?lSSIP0 zr-&fTR-#8m-hMSU!2<6`A&R_r;5JIz1A1rg?EwNgUAURN__%X4#( kJovQYF$w*Wfsi>O?3sc5s9;1I0 z`OZ0&k4Jg*U*VGGni8cfvt8)EOUT4^>^IFD-ag95ovP}~_j+&GF>Gc9-QHr3{e(9$ zs6lx)3!a{czo$wEk&lcc%qI{?A3nVP2P}y6EnTg~rDD=SjVGTzw#xJR KQ)na wxI`b=k(G6okIL;Zv*#QTM!whMn|4U8quo zRM@be=Qz8*9*5*2qXmA5bveB=)!@a35bKP9mWk7vMAsF{S4nL9MP4xEOv1&ixr0r1 z$^-G_KZXh`%7x zy}NbX#EZES3Gj*fV`In#lTp<3NYAWptE Zh`2JHe^Ojh;=1q;z4>TV z;n$^9)0X{AD)`g`;Go+R8naoo9m8EL$Qlx`fYA;@yE`(m-JSj)5flQ}GA^c(LE1y2 z6f-rMDFkl*{85Eshr*xg?yWqV;&`8HVq=Omb9i7tZ~|}rbcub3(GfmFoiV$Ft1=Z` zAMP+wl29-q7@JpaC~`@BE}{fwz2S>nYc>Q3q`vO;#t<*ngvO@6mGGz|$)y}+2Qgdr z!!NIx(6~!Chf-wdMl9nxSydiahyD8YNWdhOZoF&K|ET+E4biNPja%~xZ6dV-2fLn8 zl{$P&t!z^}>N`C+dd8J^W~;Yr3ZncanKs=z0&MM)lap;69gj6NHH~_u42k) b{WeG-}q~w>fxi^;NrfW6O5CKo`*NSTCn8{ocqcr|SM>6hnw30Pcwg#Jmw9MX_KvDJ`igS3+yxOuaN{j7_NoR5!> z^P329rm6_!L+EUZo34!&vCTT4g8n40IKtmI|FPV(HOWAu$Hm@WW@KbUEoAW<+8gb+ zI@4$4=60WTtb5A=$xRcr($EnQ{0ZZ%cl%Ce&J$&WptqVv+qAWz{#A1S_WiAbOCQUb z#=wGa0`{ L-Z;n*SEPR}x|~rT{<3$h-gV{&*$7c=-7~3hcztBW zIjW|djTuo>jw?$#LfM34u4NZ*CkYMko|((6u5bJ0=bVOFh8Ootj!GX6pFQ!MV?Cr< z7{TNlCB#T!JHPd1Ujj)&O)4f0)Awofg8f!E+8pTwsq{n}=u8w<_e4M5CTU$orGNgQ z#gufphT6Qq-#@_E?ju=eV^%&b)YsES(Pxk+AQji=hci<2)SGfSFF4TV|Mbn_bI$yp zN$H+tdM 98GwZtNNvALL@Q;R>HlItF8!biAQYIbxQ(1g0$+HMYqJv%)% z@VY2ZKu4jF(XvTQj5d!uz|c*ww2S@7zZdJ#gTG `u-i^* zft!k>6`GQg9XGQ2w(3%iG4w|kYqPT`(ogB7g fto-N!)dlaA8Um)D6ueU-39 z5K2itElFG{4VIKder>cUQdeoH^t9C~8?R%7?tMaS-mzQSYUX^w NL-uPH$yT3=RQ7z zs9PVa)qcbf6DRNUe~y|WCh40(KhnD%JZiN%=c?|8rrWJ-<_sPVF>5SCqiX*MU@akP zkK`unq|9ej*Ux)SChA{gQ3z*Y7RJt>5qwXY+%i|B?+EEbb*><`iRvHy%>I_v?+$7# z3ai8=q T3I7(1PRNc+Nj0Zz6x_3!nM9&VMK0u>H(zAw#oWc_5V^l5D@2Q7 zHg=ki#mfUw7!qMkmR3FWo8zbUV_)GU3!0xEMLXRqF#%yx*jp0p@0%o3WhXk*`w}tk zkZ`6EEcXWV;5sXeG2&dFWzmqz6)68W&EkV^5`kdm2%-LhxovD8B9nZkeY%Gq-ae0W zYiu;&XcxkYsNQ46en6{So$Tn Gq4`e=uX8FGl?RQQyyPJo3>-Q0UkktSZ)zh^a1 zX(Wph>Bke<*jD^hMluAwU Pc?y+ygDHV0L(t>H zJq@u3y*op9Nj#Cc4dMQ|B#E5>uV?;kPrGDB=JbamDz>f%@qW12=ACTj?d^?gA&QJT z5Lfc1HQprw0qi ZX!4Yglf<*#gxuJ_Kb&(F*$D);tM^RbsUIGpSxZ6|a0F$yQpAD8p# z7H|5bPNf0n<}WRCx%-}sG+bCF1&X|!i9aXe5)?aM_Ui5@x1x 7WalNQ7kE$bKYOhSY+_?Ue*#A+x|Go^1L;ge*x3t;E4_r-4@(oMcvRWIb2$$^I zaY_4&Xc{vw^p9PmdorDH`f;!s91B)cHgfSoHWkdW0zkY>y?1LPz?>0a-YA&>z?k5F zU9syC%qi}v4aetC7`EQig3F=}@-M#Ri!s+M$DD1kq_?chwZMs4*ne`X`?Ms+j=s3a z3kyYI^Ma#Hv$3s$%Si#!Vww1L`Im^PC>=C*7Wbs!S}a&BR|O~i@&dE@pxnv`i&zj! zn6}#4Qo`DhHTa+@S!RXYWh!IH8kcs3FYA#7n4=<;#P)9oU=i+NcUhJ50iTxIo+4?m zCP!iyW$#kIB|keR3EsqNaAPY<0p2qM$c63$QzAhTc!u>}OmtaVJgiq+0ySMNfJujU zKB+3Z0RpXJhley_!oD9)0Bygx{hN$FUwg1siN8GrUTBJ49XFlZ{#Gt6QN?U)v9^ zuz{IuM)S{A{2>@`kb;pn>_QHImTR@{c7^HG8X-`W2RZ-CZm_`}#H*DRa Rv zWFhLa`gkTL%9#ao;6WNe`!e^4?m^1al%Bp^H2@U3sr{mRiidvLD%EvT+ta#)9k`(% z>K|80zb2CbQ3q!I9t-^Li#TmA;AH9IzFdptM__7iXWruE=|V7JxiBOmRh36-a8RFl zi4x+9_{-Ta7HaX$2#lII5UnMsBG1_nfWo$O>3gsKd{xx%8uL7>R6_;xAXpABdylkq z3Tl@BOH{Pjl@c %9#EiQSL+%C_QVyj?Jan2VRJdlHuyvxSnC?QI(B|^ zfpH{mDH%aDe&RD|AjR1t2a3+kb%>q0`p?aCT9KKr*D>%S+o&mx*J?iejvT2{#ME^T zA0z1(Mw{ ubFo@hvaME56L5mN(>)cI4v sjC4&$IVdS3<`i0RR9%K&&Gd$Yq6!Bl8{rFmoRO zz`xtIFg1cWS{Ojz@jipTFV|YIO?^q|vH7$if_*{T56?M0)P$` |m?3a%&1ye7FCc;`ED>Be=0ec*Rk!y4a~^PG#o zbTaOHQ?_7((8a1f>Nx3AnKu!e^`a7@TN)Z#LdLI%VZytL&2HS?t|)s#ns2DF#2ic8 zAsXbpUcJkJQ`u}Z3Yu#?g9Ut@s}|IC+PNY#AqvfvST x z)_&2n?r-04e8EWaHgt-2!Ta1Av(tgFh6N-43$~d9-FxpoO?|68*Atp;$22Tw5Qk#2 zk&;{ AV**nhd+``?d~HJc14Ox$L8{Qk z@t6z}km%Pi%?pyK94(zMu8(oH$FZQ!Lbf&qG1IfA^Z7M2Qh)}zyADM6*u#C@^{6@w zWdmhj=Yu!H%TlKeUty6HPUvatE%I#JeADZ!n9}8{VW+nK+Ux8=rGILDbn`%}im)Kq zj_JbrX0bVE?&QRrxNp(4dh7J6a!XLn0IHrpYdzhnoyPBUYOBP716B=HoJ){2ugiX8 z!po2d40MoX$g?ksE9@P>NfU~F;;q`kU9hy<3o#n81@%SN8^PI0$EW40)A>Xwcd%YE z96dqS(q=ie@^czTZUuV+8`NiB%}ZpdA*|t=ZZ>;x8EVw68UpU1Lvfwk*V*&Pve53D zqj7QEIIA1Ub`syI{zoKlxpRTS;q@&l=m5Yo0sw&czarVd90oPM3+FwMQsgu@VaKKp z9@K(8fL@qU``rwudNAjVEzu&!TyjI;mj?~#93OATKC7k_j7q(ybzLLuJrd$O6B-vg z#2}^G=k{9{Xu|KlguMv7s9&(a4472KP4}BvklL`w8W^tEVoQ? ~EG?_b$cbNOAEe5osjj45spHm|%~!!dJ!0ABH&z^~7sYVC20_jmeO=#kHX+Q(?$4 ztCq}Y#ebSW;Jsj`&6&%3Y_?o{>#{y%T9#O;(X`S7++qkPpPC=y{ZtoqQ; qi%0kKvpRY zD(!#X_(;4;cX8&Z+Lj=Z9P9UkAlSrH?ZFR+01OMDqP)7u&xxc<%nd8f@YOFl#!}`K zZUo?H->C@8^o}GIu8naP@>uvg*o)ox;R*ZX1y`t#))=pPin47e&7d&t&TJMbpZ**F zWanvTuXkaB21K^SNA@R~DIQiiA> lp-f$~&|dmJ*Tw z{FcP&ScIfDsKa|dQQDc~t+pSskmr$=wR|~sNmua2PW7wp51K^6#dR24jaI`|tu#Lj zA @S_BH;R``Lk$07`yR|B;+euAhZ5R#lUdo!t{kCJ%d*Ls7(j9L%UNxk^l( zhVH9Up!Q`Ktu7=lKz(UDcbOmCa)=ExR_FWRdY$4ytvOUMvmpK1A*%HDu^yUi6GBp= z2$?n9f;0=qx^>im*W|h;orFs(Q;cj8t|^P9SO#FRW_aN;veC#`LQj&;THQQ7^S5do zeIE^;r zYP) z0(xBWkDSWKeUvRv!hmJ+{=VdSkFXUnb)K)0VE#t)5UoHvMV(REU+zJQ@S~bn#s?2| zna5@1?{D!a1ZQDi*=&GwL8aPXr1fQ#)hVi%pVqCpD=4g>`y_MAV)T$Om&V~@7Wm68 zcN1T%pK2iA&=FCFFlo0{L2T8WF4#8fYCzRO*T<%$(4AMhD*&aKtMhjg6)02=xo0;M z5&H_>0QbrV$!PqZiDwcx6Ng=P5%OVtB|BNZO9Re!=E&mBk(aFo*7*W R7|K0rGRLpROZ8ZAOMLDb#ts|6se=&DShCQR Pn=;W zV#TkfJOn|bl-B@#I_QwkzCr+-2f0m@4%yaF3_+KqJxI09F{!jl{UASnILq?6$CI)J zPL|fwqPWkcQ%)zvy_doyWpJMgu5stF6 =M9(ZTR-{W#I- EaWPs3?LNR@@fp2cD@pZ(rr)>1E4 zF~hfSEhk-9;kBuHcDu@8uJRd3de+QD!VE&Q1I+TVT=R3vf^9>+<0W?|omzxICA{=F z$i~`b>5{nIHBMu7II1wu=qLK0QIEW{91{#G hY0 zY$Y$aV?-X(smQlU@-u;%x>ek*hd^1P^YhL-Gd~dGDABKdhu?;2Q#g=5ReNdE`*U7f znS2@9E^(T&c;S;fWXYVesgd7#QkGK6m*v@wWSEFag40c~wdGm11CI#XFTBm@5-g6* zTHIH~JuV&7xQFl=pUb6`*b!1P%UG8%XtR~%FY_R&O=Q51@fDf ;LVIHSqr6Y{tCD;d ~A6S1u~hUaTtW $LBzcia$kvEVlFLyN8qa0k3~$6!JmbOQJbrBq3I)r>`xEs+)L^pn{E} zo5CJVdf!CK2%7XI_7j5&Q2|>DHlMhDCM)w7gBSwHZpGrXh@^R^%DJm*aL}o@Dmsk% zJ;5dk4TGDY3Ph3Gil7K@V0bG^xKA7D9p3f+wr6f%Ynh7i0m&lnH+Tz0n+~2hDgKMy zL>(Ue{khAh3skJBeC}x(7xhRTo)#1phKgkGn{UIG^8=6hoQCodJ%pP+F28jeok9&g zq}(7`x{X`HnG?j1bjqdOyIAWKfjdqS(Wf|^N7ePBy>bJy6F@j6FLUk$PR8r@@09T& zb-)s>Q=dA|g>#j&&jGTSK>i{78D+GJfD7$!>k%XL7BJG;72yLSUrji<|5uNwgSkNL zz~pAh@d?;4|B&0`LrF6g8MKI?+`+<&H6%ZufzH9?j5`%bly%QV6^!EG9y+M_rex1v zG! at+T6gm^y5L+>lqYR#X)L65@x_yUd23>eULQ<4&?(^16n@ty7x|wNG6U zsOU-KmekEtZp09#iqcFQ#;3^-nCr|ytIvM-pjDe9KT}W2tap1|ERWFEz@AtawCDHS zuHR~TMZmba3JxS@l@96T35CxYA!ONCrf}TDoO^X)Zbt&aY6D<5^4W~2_LH+IF;Dtw z)Pe7%*!7ddRySn=%~k1}+GDS^A6S11%y|(P=r*?O2jb3FJ+J@(>^p&hLY&MkZSP9i zdToRvwIoRgxqFZ#SB+kG%-0;*fdKgs$?|toC?kY8PiSiT-bfh>f53-H-`8G*Y$UHQ zHv{s^vxV;30j^jT*qqMRu3F7+bEQ+t^sVL_X$N9UBWbnMMGHS?+kbrZIB#`1>k+@5 zvS}dCuHfBz+i7pme(i8Q@3FLB7YV}6zgdrWTij_pTSSo~&IZ@~HR`d~i{5>GsnRpw zceXKtsC5mUe^ZB1GWc}xA}O0l$$=F!^r>l(7zxE|N*seAaM`1Fhg=+Kzmf#il4!cg z1|Kz5WmSuUA&NK0HF`vFQlEVaDs{Hx${Jfyy+DD(sLggLQy)K!;KhlZZA*V)x`BkB z2!?=o^NTXFS})mNF~F=wXH83^Z1YxUW7DT1y3xE-^B9KCY|5Hx#U Z=hLskG-0$vr>LnI?FWg?^SvmcA-uff`uw&9@#S7P_vlPTZ z=BobZn_I2@n`}4Om#g`mx^c0+>5o Zl3t@dTVpe}(2tCGqpTi8rqPxRKxUPYmmu z8k)jF^TU63?*M%@ %yQ)g>9 zFT*(NaVXqw*uqLnjEvH7R=dvvVU1U5HERn!5f3*8{PDG#u3q>s2Y9HmX|onxiZYmW z+)wGjjxVvoKOk =mbLWoz*`TEBy2;aT1rQP3okwbDZ(O4Lx(!NQ_hgYR-_l2x)Rzw3Bdn1qhPwrgWn(e|9k&sVuADTZ8QJ{V4HlTv6K~#_V06le15(D z?~UWH*ALyL-k$@J{}}qO7-MDBE_MHa@%Q@pSBzJ8gO|Tn%fBMfhxTU`{{zC`Ymr|O z#P5{jzYzWxk=4x}`+p+xcSZUYCgW~=^oKtE%D~lzS%39^GQhm!4gg@@t F@$%>6$F8lfrL&up zt+|_%m%W3FIn>L;Q$X|241548Mo9m0N*iVC)t^`x008qpWXM`V?OpjjU7elu5 8 zt6(`0m+dzS3Nz+CF@U|ZrL7A~+|?*_Z-NvsuQFxp($+3a^w?=svx5D~guahTP*2D? z28e#3xwSpMxK??aI5ONlO;!j-4co9t`sgm7Y? GovSGoRY#gwK-CwpQ@5< z>_0rUS+&0}@AH}SLW!pg4jbz&OZEyXqB*_9_$eF!2)PpeXO;d~X#YXD2h{qPa-Cfj zIJX?~OcM(LFe3s0SpFr;+0wy dxnSGQ3q;B z@OW0eET{1LhLht1ti$^`U1nVJ 2sLelQnZ$&En1R@lgkIwnMh~q^Tl1|@?Iy4lYoZ{ zc3E!J`K3xtt#vRr`5WHU)Gc{y4C{m) EVB)B>?}UsDU`NESpvu{krzWPbQ_rOJ zC<-D6^ylAq 8 ztZ{=@Z8a00(`6_IxsoUs{_+^we3~Ux`Z!z~m|+gnPa~Cd{?;INXk2>12>F(OMs_`Y zZwFf%{FS} ^CR%C%Cii)9K}+j3(VFb0BtglZF@mL`Ubo)zCuVTD}HLM-^#L z4$+E$X^RP$2`?!LNmpX?>!?(TSa3(ZX~CrMN0XiNf==@DCyg!MRb?XO4N$wBIl>Ul zoJEN4Cw$oAnVxzXL?j^GE%S1Q8cv(#Z}o%_U2ci&hKa1Wf9|(K*6yxm_-Y^8`D({s z rSd|B-_z)P&OW^DeoV-UNc$4az+uu47iW_wkz>?2iEv0g4eSuE6F7c| z`@Xh3MO$9`G8C5(h(1h`0Ud02XbA-qk`G?DPhB4rYcl&dPO#Q|o2QC?GbM5KDLAnm zsU3xbKQwyND>j`ElzfXTeFnMeb<^c&lz@#+yl+O{KZwgE_KOkXN0Tzu=!LW2K-xT-UjC+`C_ zoo(3e)}^8H2sIhL%Vt-O%B86JZovb8{y==8xU?^gEIMIltEq#&i``^z_n)oYgcVNi zy<8AEu>W%5%ik-RlTyPwyE;cf`LeCU91Mr fPgfPl>9e~6Gb`+DF4B FCF5S@J7jSocPdy#9NLpo-BkQXcJ)cskvzjq{BH$lNk1>$htpz9|HD~uTOv$-4D zta7a}BUDZr?M@}F5hF1=6c}7`>2w?~eNN;gtE;z_Gg<`rNM{lvw1VWY8IQz3HUxtK z{Ye01F`-G^TX1$RGvB*(4PX`V`>nwsO&av+YsRT1Mga=add+sh8$>5DvwAP9G>W*g zfy{3B*9bdMbf3iUzlb2f$tUp#E#4KAx_1*JBgw?+*kUmPfW6-?Z=i@@A`y4u23v4o z(F+Rdp|#D6?;K?mCN^01&0c4!6{vdZ+oz79=J_yBB|!WujVOeNISFdbj8rN8)F5+0 z>p@49UpkBnzds-c-^vOlopi^$L?#|*C5JUVM=)J$p&*wx_1OzFEirtx0ahB&L+#dI z=d$ik(+b&Z3Cx` |JFh9-Z7%J1?LGTGsWX!>ivj4IYdHE$=r%I$Vkm1) {oIlo(sM_J2#+)I+oSMO{U4TZzj0hiS+Wk9LDR4Q>!UU zV+Qp&8D=AN>UUlxmNmb0go}wIGK%uDS}Ph{GN-xA)tU=zD0HMe2|@h)-~{bq2vI|N zE*DctY?9*^eW4*{`i|3X13GW&rjkSW^IS- hma4vOw=`;ri?w(c*OpzsFrJ_ z*Mq?wu-h{`M<(wX<+BKZg{pOvL93{H- qNK0a?jp*G211I{9#H>P%n z8oVkJ1>Ycx7n<~#T;>KQT0OKkQ`+O&v*k=W2YK!zjz;}riX`*L+)F!S2Uma+(POKA zbaB$;Ta!2E)`^8zxeH 6t&iG!;iS3-o|`xQaF17)luOeGV+Pfk;z{V{ Tnz38xBx8IR!iK{pYzO8D3Ka8EJvhgHm`1{W?a{ z{KNeG=*7VAN*6Jo#58RC(k-<58@b>PFAhL6pn-6-C6{Rdp;5!f?2?oDHB62n=2?w# zr{=es`hI9d9SzYtc?-|5DQp6L9dbE#`h`aWmEFr8zTfe~OF7^z)%?mpPmBv`-O}R- z$#OV62WxiVY8~TI9whLs%;Nce@C^`NM;B}@sbX6 zwh&-o%Ln1>K#lYa`X8Q>g*sSQKY}X}+0iMPIbsMP3YcZ@3mZC@SfS7DJSsAZW+7B> z9XiqW?U%k42Rt8Umc11&wY!(lqcbZaYL_6yYmAAuU>0jtZ>wkXcD-iMoU^JX4(C&I z3;!U~8nJtRpy0T^VWU{T HqlH~graiS` z0cH-OO~^g{xkKBf>X-*0DK$Z4=8)Zua#s=FJOoui!A Uat9`W^r19pR+p7IBeo;c3Xr5tu3C1r5&I`c6*x3OpCE$`DRYA zAH|e@j(#GMzqo3MKj!05>*LJ%*jF64cllTf&2>t;``W)2GY(Ja-Ll6NRIGc{Ct)wD z5dB$y$Eq+>jW4se&>CG%R7UWjj?v)2gGireBk$`mr?{{bQmKUMIM$EU9Uf}LBO4Z# zM_0QH!Pz+=328v8u~wq}fmPWmf|2mP5;XIo0LLBP3+9Be*GBS89cIlj;@K0 %wQkWfH 8vbMU!Qbd#CxdD~-&Uv87&(ye~&OcU<4i|(Ke8(5DHso=O_j+v5S*3e! zUS^GRd8C 8`6&mSL{;Ts0_LnH&5OMfT#}xQ-fZ4 z?42H@$#`rKiQaowTB@9jH*;(H&G@5h6agz)NJ)P`wo5G5K!!;+_%rIg tT>E4L$Ks=4dNa_*ZYD!*KTAklkS=w;Ot$_cHLsHK^mw!(|$ zscS6GrEew?%611V;%y<8hOeSz(X-^z4D+j9Q!8Yw#23^AZ+O18+LMt6aAsEcJ_cy2 zU|>oC{>jkYxEgYP1o?lL-`YFEKSm({00Te^U mthbo?{v;L0v!-@S$N&`0MYX2W)fA?!YNk5cX{tM|( z_x3BW!~edj?*9S)eJ1@CxP|@C(tb{;zY>o(D-Ps;OT@vwIzIsC>SD(P00v2ZeEkOj Cmk%NU literal 0 HcmV?d00001 diff --git a/img/PluginDocs/Example-1.png b/img/PluginDocs/Example-1.png new file mode 100644 index 0000000000000000000000000000000000000000..031aef420b0a71eb6a5c0820ce27bd28df8f59c9 GIT binary patch literal 42846 zcmeFZg;QM1);>G~6P#cnSdat{mf+5i-~@NK;O-8CC%6+F0tq3wI}8K~PH=a3w*lri zx%ZxPa^9-%KlrM4)$H2R-Fx-wB~L$VJ}SyfVq=hE0001NX(=&f004wIMbbn=Li{*8 zA-ezoQ~+r)QB@D%ekQsPf$41zy_~%T(DKojN6b0nf#R_*&@cj@M(8|x6!U22kr;4> zFi}mgT`g9`Y2T>Ubd@QewdI?AMZVBmm4qZh14jDuSP`XqA=ucf9}hr}{p0umvH% UIcY~0ANF2k=nQ={n^bi8nGK|=Jl<7P@W;70FhADISivGxUp*l z@Qq9)neNZN0{HQGJ$H|zLt>(9tAIK8BDdT7dSMX}d#VjGMx=n3ip1jolFGx2*x9WR zQx0zmrCC7yrGN2OU >F!77y4m!D?R!>>OY$Y;vav2#<69Q30pevPB%n^VU(F1 zE=kUcy#EYb{sn!-@rP`|5WH7U;F=!W%__P0Wj~u6EhER)!7{NnfZPxVvE#w{w(*&t z;9U;W=l|*f2R&n^@%?xwTgKDIi>~3P=k}YNe6je-_Qcm=mq#q~^zS2yJrXvvM4S{F zkf`zu|1H4XD9GTE|EZzThHeDg$OmhmN~d-?=mmGT&8I&k3IWj|aUW1N`AK5AP7@Tf z(2@dXPv6`AsV+3jB*2hMw#=J6C)QYVuEqg5WGF2K-M_R4qJW-gtH(QYGC-M*{mOHw z&XkmASO`FhZ0h=dnhN0P+9IQ;|CY$-zWdI2totRp>&MSPMItX|*?&!ks04%+EXr;8 zB;{YD-F*W=0qbp7F#jQ506K^Sp_2dq!~c`X|EDylDp^Ccl0itx5cz_!Jr}%d1^R6y zbr}qa-;&qHeT5k~!~AK$EKlpsLg@>t>#^q^klBnDScYctz$1?gEpjx>1<*mtK1*4^ z@l;{R9 wW2I3JG+p 0eNs?H;2^x)62NOZ7;H$B z6Z7H2=UvK3YROcDk>Gp**}-YaDdJ3xqDzoa`>ye0tAwAZJ022)ZgI*pBm@wqpjAJT zM2Z`KxR*+oi$hE@JMdk|a@@86`c3l%xz6M}q(j_qYfJT)On^=QhlRTv$sw_+`wgvy zLF9}t>{*~@I!MDesiAxCsF+8H4&OurC_b7!?;zR(_$-Fb4|Y6$L>tg}7X@?hqGHfe z-d?5wh^Tr!fVM`ItPr+|5+53bM`=s8e5S6GRU8G{eFNQVb0h`0whvVXya6=%A&Woh z6a6i?05R}cPu?aW3O-BU8>DtgXp@NafgXgDerkD|gLSugdR3gL@Ery!(x>RvRFRce zBm2|{sS$yWJ&M`)s`<$hhjrLOA>vZd0#GxI495kT>htN;Cyt{gfFv^XQN}Cj4o|qz zsES*{?}gAz1qq{hjB@cg#{^H wcC}=kmLgc^Z0(9cH3K764ZTh-!-X>zsz~-LT z%Y#nA<$JlGdSW8+W?Vs7dymW!sYU&|9;NX^V$AR6c4Hu+IMUcf-$f{FQbBK`5G{RL zu>gRTLL0HZkbJN5!36h*mBw7t!nLWy{i;|f1M~#kpNTxAXUP44V0JA`$yrZFfWL*` z`cp+BnIaqqnkEvdFb!AnOG8JcSNLfBNcwk1p?SdN&3d JzO}d~WfA0J<@W(%%P* zxT6B;6`rM}OHfQyR+=l7lze+?PV dcmTYt96jp wPsXRkwrdvguJ?7SD`x=3{)8DfrO&=oN1F&QswQ6So+A zr!^W|_6wCeeMO@i#8=1#GT{au4~$Pz!UZ{QD*Cna4NIV $lfSP*y}Wnc*
PTO(5h9$Myytk%I- wAgJj{FF~J*nDc{!`8%6p-E_%-L!SBRmaQm;K)K%Ov`Dvu@S~+R z`y2mcD*WV+Ykd$svwsC5!Sq0XGC+FU-Cd7wleMX@8tk! D|`t_puM0 z-MUJI_D8qM)|qZ3ISOspr^OOcq_QW9W9Gvd>U%H1WBKdda%t0Q8=JI|Vck(J%zN?# z{qXy=L^*!3pP4TP-u@+7gottNKzFtPFf0sPk!j +msEe8>_A^^s{cMx{s6fl{)*`FbHL`h;{oz+{ zsAy`Dn)>=U{|Jx*9B7y6k)f(i9n~;_J2X>M_Fc2blzfb_$h>}%4VE6z19xZ)ng|-$ z<{i{Tq@ud++5i*2BQKec@#Tfv5xrYMJv$EfgYYr^2^yWvBR4nsZ|oxfn%ETyr~)gv z8}6ZD9H;t|Q5)<& zTqv|xB2o2xL&1=B8}@gP&ERa@Il|!~EX%n!c;{L1vb89q^N%?CcT5d|fvR}`ZWM*_ z>1{P{*VpdX)@93(BNX%kD}S&>F*LCc@5yM!{-HF8*bVHB3^to(Rx0>-$)<)zw*0-w z;Af)sl{diK=Va~5Y=-JzqqUHRhM|DZBucr7b(=l#%pay*#f6c++2%2o9?cUK()Y=; zF2QQ`xb@>9D4-!qKC5?f6|Lxv6277FK_PQI6t-M8iW2Xlf}zd4&JM7cE?kz)%E*D_ zj}$+z`@2o|aKdlKD#NbiOImV%Ikb*bnMKII`v%<9U1=(E%aC|uT+sfOoxrN>BOk(v zbVNcM^4icCzvFxxUHz })r;>wq?9jdqe z>LqF+SS?a6o>N0d!x_RsrFs*>_h|#xCdMXj%hElfbbd8zjhQhoOd79#_m7b+%k9Sq zwXM31(bNpITT1onmz|NXo(b$C3EFD-xEVLm)a~NNQMNS`UF^vYyOA?)@EhY9Qo8qZ zRo~eWDjP^+p%WgRVL>*$il?}WxPcAM^V8F7DHW|uf88nju;@9%fieP6gcu of&WcGuwS`q-zz~T}mc<$9KZ)Jt)^>p>r?WVGPdWJw#OHobY5C zlc c;Crz9^<~?kl#d*%1QSF=Bw#K(5 zp4EeZ3HXnzB_UY<3e&|e j_=t2g@9;7w( B8M)aGbp-$(rnZ zOJ&HQ%Wi8Ipy{aWq>P@wczu_EIm=9vQW!f^VrD=#v&NMaxwgd1+1NcFCqp5Dh=gOo zEFkT5VeXCl3l(nTp^YTdg_QYv^Z5*gqKGHii5=Ev(Sny>jRzZs6J#GW&jRM`Z((eg z8mz+V8ZR>L_EYz_rkGyr2a)jMZ0cuPP+GSL*KOrZO&+?&e-l5Cb9K%(FuyUAmXTp? zU%S0PAO2F76}J|8WE!=3mes~_bVK?&88gfkr-wQ6IZyzJloasPzlwAsy;k#CB%Zsq zgepgWGURfH{8)ur1EA|u#o|9!KzS7zxkow$THPj7CpGDpJL#5bXWmyy!P&ilS*ueY zjG7I?w&ouWc;*mp@b37>A*I_ t3tUlr9>zsu z o&dCdVUkB!{&L`X6ynI2)GVi2{m&v8?`23NG)+?jBRk9)puLgxBU0Vj-SBGp> z?jKm_aIzoTS(c)n-R@HOv &&Q=jYYhH`L5&3nGmn+KB!ivXF5HGM2w UKVf(bzIsZ4(F&6wi76lb45giIx!rwi{cv^JOVG2C zVc=T oS&_x}&&yIM!;P3<6tEE*khN35$9JWbT1kl9Zo~~Fc zUGRSM3jiV7EHBU>lsf!HE>IDjm34P*a;(ZlY+SCXchBc;c(7XI?Xa+y)w`e^%=t?Y z>qCsuQarkUDvQ@^^fv{PPot0Go{d@dUEj5zVT8mVRE0&qG-y1oV0N|F=DNu&HW3rh zlIE?oys2D^dP10azf$hvdfv~I@}%F{Mvfncbb6+j4ny1$<#+y<4eo9kW|33a%?vR; zG8htin0{Y_T53z$I#u3NbqsZ7pQ3zU9Bq@vee&yyIayBmFw#6MzXq2g{iZ8g+FCZ4 z+M4b$Yj)*nNV{#)k^n0#Md+d>#oqGp6K!{ILhW+iREp;2M;q~I?Wa+WYV~e2d$q3; z!~F8RYN|I@;0VkOj15`)GU>S;U%8a9${N@GrYs_HHN9u*P;7nkSoEII?cTxP#n>mK z;k5D$dsVyzzDn!(vG?;Kb!*3R5oT!-zwa&Qo#(4Te?xfd^e0UlirBNaDk=1v0`5B) zU!D EfJXy~TL*YOV^!u>3FC zU!ez8Uv+#uLKk?9RM{rB_Q(@bco&xUdL@h$q{tUunVuS`OAVjr&-0D-xIAqWTos7P z;@cXzC+Jk$> #`Z?xdlksZSYG9$c)!%q&hi(z=?>a&=OfaYp#n zSj$&nq!l@;uf9jjAHn^LKO~m}nhfXX6RujWRhOQsvxc&a=~rC8Sad(?TxprelG5vL z(RB_g3$!R93&DK2STE ZmwDU%&KkL~|pG5zB+lc3#h`~^W3pef7 zMnhQ4<4m0UCXa>0+=B40FI(NMEV;SyV)nF88RB_b`K Qr4OfAmdj& zx?BJkKv?Lm>(uwMz+d=wLS^*Z{A}g$Qe$Kp46XeP)fpat$yWW+mbk3UVurWWF;eT> zZSm^9g2Y?PhKfmb2W7>Oc0fui(4Y9j4Xo+thMI2KzOiAcFn%@L|DkYlRT*VQ9!kr3 zJ!s&IzD3y-1#&x)IiQrzE`~XbEL`!PJy9lnJNn@4 v_4+pj4+erC+w{Zf`C|Ka88cskIVK0 XVud6Cc!ICgcsd>?N-D@2!<@)t;nh=@JcZd1F4SqW3f&B)_FfDbI@H!Ss zZ=IEL5*7N*Y68A#c{O#6wf9MCsp1xM?qWxYq^}VMTLXkN4sf8Yl(3w>z-;sPcrZMq zob`WaoIk=UO+;J#QpELDH-M6AEoAa5$FXy{`_BsNHpjJYL>AlRAStS*X6o|pUHnD@ z{NgKJie??2?9Ixw$<|z+3sBjP5b_ppmzm#X#O@3*@G&uk9z9Zn8`%NEhAeSPB;Q zIi|ti0 ($2)`qJO}lpTyd`r7Zrq4U`L;JJ@UwPuqH2+> z{L!R3Z~3Lcm_uR~XDSWNMn{T^ly 83%(R+o= zItRtVgHDBsU2FMAj8*69o;_4yzR<@#ke9Nr-u+IPWspLhZ*+3@bVNP|b%FbzbErR2 z_yiE?W{IF|t~p-eQ{neLS@kxSxitxzNYUvMvlo^dW1+~hdzy3~ZF8jISe22%lIyy4 zp6@)DA_TuHZqA#W9?CP&c}dDgKPl|a(F}Jqtn^T~TuPZ_wG}=@w|rCJ&_&?xS83MS z&nA*=B%r2Ms!Z~&q3`=UJUTb!*MMiyz!IfkA|p8}A8g2l=U(|9ksti{u6 Q;R2T1TZX;eY8zf068!;xgPRdO$8P>v=tS zbmSbV9`&ogN^7f@jePgea+2$N$J=Jxh|g@ol~(ZH1&S;Vb02rLDjGW5pW_oGJHs*F zjKiZ%vit>g1i?bdtW)2{N+O +$cVE>MV(2AxUPH6hL{r z74_`(-0Q|kVn@IHqh9ho+gbnJ*h0(#EEyHoQ-uN2Hsh{|v9HbLs ^6krc(a=+;W|UlnyX0ALA*hBI9}2y7hS_(Q)5?aThhXw+>sx>6 zOp535RU6BXqkd0$wYVlZnem{(^rg7nlUU{scdM|bfX1{<&_wLvXU##V2+zSuYhft{ z&HH%)Z`;Ynn=!LzeV(3)*R=GmGo_JXWx;~}vyImd4~p%Vwv}oo8kWY|1z69{+i`xw z0Gep;=bPSlwFJ&)eS6xVqCro8Z@FzeXX)KSK|Ukv>DB(Rh9IBOIY!BB_}a%ver>fy z;Bi)&(&e)Lo|Bl&O6^^m^rX+~6ThlPp$=nqi8evs9@_-}zASd{-Ex R!0z>-*RJLt**~#oMN`HTP_=M-4Z%7YSXpK_r)U&JP^{>ygEr<_bUFUtOH$P!$Du+88DSJD V_uj|G25%C*R)X CZDAUT z0{CRZ6&5|l24!C7oUA|=B^VYnO4L7Z$wQ)gK3`d6|a9GbRoV?20out+&A z2Gh7kFE>i{npVYf6ek}JG^h2F*ULO%$X$=8qJ|aHMlCj J_VNEZkEzCtB Wv7s7@Y zdFQu3+ij#nV2J~%zT2U>R~JK44woK08BDdxuCsC#uMJu+r^U@bJ)!!&w0Q5%6zcX& z92Wgms}&bHTV=l8zW&~PTCn)Fa+BO8j1-N?k2l$X&~c^ja))IU#!L1xqxmL@3R;J{ zhko1=aEjgID@jDPeN~_Uk4Ap`#VhC5WK(~%mi9ug#_!pA>eY$l)^KK5G2DI0PC=$s zmG7R-@{WK`F0>Hfj1<2NP%NaFMm}u}uo`rWYr8v**xns0GqC#3Tj+DV-0lyDEwy-E zVGlO=Hw`hd4e!q!Zw6{?&Q01Tc)3_tnCd*2AJ;nBz7P9OzaS7fTj}~q^U$R|EoR7- zbVR7+<9TphOKA5_kyZICa_aXkJ Yf;Wn?Zp zPkw~0zvribnqOZK*~D*#{bwWO9n{0_sGBgtd`REkQML1#WL@#N?HuND?J^IXy?z@w zSI9e9X)t|zk7;a;Dx#wuI}eYRXDKGVi2gDaO&Ehk+T^eolsVq{vAY?DUK2dKI+~`F z )ixLt(!=Uhv;!V@}N$yqjR7JPILxTYP>koCg23>+DwaJ-N!IcuA)(04>p> zSL^u~Tjdo|T;4Pu*vIA>jw*?0|MPZHt^tUUz@*IScmK87))?e33W-4=DFo=ANW@BV znX)7Bow8ntnS(jyP*2!xKQf9o(BtJ$xo-mEZjzn%B1YRYUHI&|T$$X_rS4+9w^)nd zuUqiF(b%rqr8z9$6z9lRsWp9LXeOa3xcus3{(03U)z`ViC|Q#SsK#7bmas!BGKE zLw&F3_~tBBc1$Hi?p20NZE 6;t8Uw;skd^y-nsBEm#gIP^#%cY zjqLvS*#mnH&vR0N$Je%_$um>{_tk5A7HTo)FE3iz`#ujGuqTqT)pnOI(JUza4outB z4-78n+G&Ko%Sct*wIn4vbsEa(E8niP;;{J-teRv|^xYog<(W#7XWYg#_*ilQZoDrJ z&rZUulgh5*En6FxDV>P fBC*i@w?v87K
S==^3wx!lu$a^ggAKUDvB~* zzvKfMhKP29H1i^LLDNEU^DN(0j7u#kp!Vq(_{nB~< cXR zp8}w7wLpVd5URl7D;?=kbqurSJ)Xx2bxFLp29ef=tsdX2iL*ow-BDF8c&_@B&)(wI zd6SekZ)iOJnTi*?dAdQoK^pk1kQ8!aNQC1~#aKBhQ)-nRZ3|Gm^1j^vxB&fziiyOe zUW`V00KZGtBA{bS1RQF%_^3=$uVoXzcs5L7;7lPtQn1-v{o=W)$?CCDD#jAo+m-Kd zDI86s1OLTV>id95tB`u%!)@T@(UMF#i_RRj7Fe&FbI 2R{@WzvQuP@dh1Tz;LfY=K?v zIXRrsJufL-jp$Jp{_3prqx4R$;PF%1bBaYKH3k+luByrHV2_0x?JnQ-E=!XN 1$` zW<}I{oAL?wYHoM#`?j7!DA<%4Zo0dB6D=q>j`PTnD_e1TsiOGM_>N|-ezW0(XmN?$ zfsf8TE-{RZ)74YBCIY-?cSE#ir(ZBs;+gyL0;ERe={^B@cXFp T0+gdU!_=T@Ui`XfFYy+ocyIAO3IV4G;1E|qr6b0W^D&Ff~X}ss(9_1fI$5h zG+XZsgoMpjf(SIo3Bx1GscrN0B%1oyPwcS>f~nIt<+H;E+XF{-K2E3*sK `3Q0&D6D@iYe3QY{s4S%euqAN*iZG{P)Kr(w0 zSP0 8L#4H%g;rz20B61R5QkGIEHU zKYzZH6(S2e$l~^VzDQncmh3~--cd27Gv!ny`(oVh^t*c~y1jyjlaYR$jW<+7oj--3 zzu}}KIxI|^h&GYdyQXD+@r4o{sy=V7?b2(7nNId6tmzECLg)wd!igqZoA3L(;L^}H zRDsW=sP@sSkA!o4orVS`IGj{eDht}KZu$z2dJiWj9Vc7qKII!N9LwwGDdxryZfUdA zi(G)WssqME9{BB7BB)VKYii`7 `Qh`eh |x_<# u*N%m!)(SoOQr$)__9!G$O(@;dpqw3ZM2 6bZusB=6!xHyQXY#tTEfeNAI?ky*XXpRr1Puek406fh(BW*y@aWGZ zi5MidY3OQ~`{66Ik7`eERnS_U!*2q)iZDCtVz_n$EpjB&3k5y#G%ed3qdxjN&(2=d zHR4nfpE^oUSYkbT4OI9|Xab!WszYK&)IU5)Xc>ZJc}>Ve_Af4Bz%4BpImhp&%Jq*ue+0ph3BhXf>l*C-=Y2$5 zIezE}AkyH$Ci9PW5!xUFL4g=JR=xgL6W MZgwU+ZmuhqYXLxqOs@F0SQ^6|x=oSayQI^shu z#N#jiWSGW+adC5ixS$|0ynjgr%!C+a^^0Dw|JyQxQyM7x`NN+S0-78`gjBTS-V6Qf zDlQ1oAE=#5N$l^B{CzSK4!{PKNL5n&>na)&qQ5}HScVsWZK*?=Ko~?Wx~e$?y7k`% zSKpX|e$e0^BAN__kwYJT6AXUux*6g!=<_%R S!t!1sojhYbn5__3m#xE3LSIiq# z9sLV93l{^%OQyIEOpLA}{%$6d?ot7x!bL54^V6b!RgOvJf*?G#<&h0;cDGyyQEW)< ztwrRF)c6@Z?qXgzoj$;jDu)16Wq3n~HL5Iu2$Ghc=ZvA7IUj%6W0KA_7{blUTG0FA z$IzqGctkozA{}B)S4 i)8}&-Vb&gDKaQuOFO6cf}hX)GPl^(M1YmllqH_;Fv8CS#w=4Y0TFzKU+VwH z#tN}n9VQ0*+!g1^t(5!lW BF?uzFHb z|Fo*8icz9-a{Z3`%tjPzJ#u)Xa-st3CJiy)1_WmJq6&cUHfhN1@X>Y-rHmT{gcJiI zi6JWPI=e9@OPhHse($#$nQ9y??mnQ|AUXb!tBgaael$xBjw9z3(13jQCr&9G=@8kY z|NdZ1(Qkf7rhY)uWq|)xJ3%Z;SEi@=!cYlVLyZ4 *}p);CdL>T{+E?fe^E6h}^$+QH#%?rux97u^}Vs^*(= zu8%|S5Oi3G!K 8;-wNI?2uaKYA*BI`h^-&TeA6_ECh0pQNGLUk;q#V;g}rEf zr+L%)%Qd7SFPj&`oS69$TA&>Ha8v8r?JnPu=M@wEr?bum|DCg+R@P8%QM(G<^77+e zmTby2YB|FnjvJr48n!p7{qbq>Qjlma2veu3H8o9)7p e#KT6SS%dQ>*p}RTAjv&^ z9| d{9+>q|Uw={)-gJ|VjbyGrwosEqVKcp*orh@1ZfScxIxs zVgR(U-t)~ZS(sZpRh1U$s*CU>kiC2M&du=CLF&oP^IvdO&&m96sY2=s&!yj$0(c*5 zv~(iuG|~Rw+^{# c#w2xiucRb8jcYe`UUQexBfbin=--ZD+sk+&>Q zjkc^^#VZ@xBqv&taz &uJPInd>j5O;8F03 (0L7XfO;K=bLV^_JJu0=|2_8_RF+wC##U#Vl%2tTmm#- zR`16p=|YxgDrKR)xo+G5&Z(^s`lq#;V`df?X2wO%N*BAqt_JL8?ULjzGnF;a7a^ua z5IH&b*z(B_=TCd3Q!(9Lfx+C_THHKS+G2f>8`qHPmmy-kw(@c>d&3!Q>Kq>M=r362 za;^rp>CYP)qG;*WMV`s3!W5s&x#;iyf>*IHI_K*x#HwqS%(ty*X1x|hR5w5+4YgSQ zb^~M}Rr6vsYTG2nt?QmPqllV2oCIVF-j|dXH{oa2`y9}w`|0Vfknl?SQxSq&k%f0s zq$XUls+Rz?M{|$gJ rzC zIx%ROXLg3ZjTo{2o+jz-y3-*Z6tbeDl3aoxJe21RK_^L_OG%;*cTBR7l1oAmg}DLC z{O7}^F*X5M@}@C{qW|;d>d8nu)_3f%mmVdr5$^h5bpRCj-&Pout+nWx0GCO;sc=?Y zt3#k7xBI?BR#%)JubXDQsbVF2?{i(B;t8t(^Rfi|^{TrPZ$P3sBz%t8s%S9RtLDRQ z^l+Um(o=&-s;ujegILPwO5{D~UQL0|BGRMwOY+qX7S@>Q@9Ha=nAJ%Jf`rz@;FNoh zLA;nNHj0ka?TUxMZ!jtkHDqi+S$PHS-_y?xVwTA-`d(}vB%@{J)$l>)y(EobrS`&^ zWR3P5W9p<3AUP=1ru2+JBRt)GWp2!0kz+?3G-} J7&F4lMNhQ>kwF@M#!8ZAeL=% Urx(% zCylG Clwv-VFZ21b`ajUkfgz7Yjt5E zblSh--}az=lnUsj*u?ZGoL9Irni%0XZEF;W1P0ZNN;gtIP?vLgXXT`3mYx{)2DF z@&5}Uks=WFJWx^`83H6w4nL2z-%P8o$j|Q%uuBd921jI7bAggZ$2Gcyhs#9esj}kY zf#Icna!_JO@)FnH?ZI3f9WCvgnvRkd9wj{~Vf+dZbESci?afE{_Kz$3!J#-?!o ^0d3?FgF|; ?|oy;V#vHG_&uO@ zzX0NXw+%lX9l`pQU|QSR+Mr7~g1@vbjwQAzv@R?_Eoqm6NK*s6XqF4TAskA`h;oW| zs@(}-O}yiC`wSGY<^o0T%na52n?T?)?=RL8fJ;lMPD#~KUqxayJh)R#%d}_wfi28m zeHJiRyJ0X}oSGr3HUBztRfpUE%lE V3&_vQTqUUDs^Avs|7W=~c>De>B*C;ID`ng)lHK&Kf|r)ALro+Z1z#g>BoM<70h zXK?INF$7NK#7SJvUVh^2=$I#+Age3YMe|q09RNWjH&ljUp@EN>0)TZ(Ko }bAng@Z-8Q*R6j#l fsBcMZ;`l|M#|{GE!Qssk@^pb*iSqEeYU9T4 lIE}4F*FP$KX$-7y0JsO5USB!6EiU}F~ywRSQ +jx66HssMl%6MF0SD9I6V*< z81NW2J2Yi`XN+uIP6d%IMyHC2{8E3t-WW5P#p{UlI{sLYST*#=fAb{-yv2;5xd7DE z)Rt`emzpi98NfH&vnAf|^F?N{HMgHISEGZ)A5Qy+O-$Bq=jU ehwaQtIG|3&nZ?G-iXak{(fMNhRHw+nv8z`GZO;+tmOy73^(iHmH z*GNHzuDT?boZ(YApV=t&v-0mG@quRf%mmEz@@1{f1HL3iUrR@A7ln|0cyu%ZGNuY> z#6_z%*~xc5q@&~RXupf!YSBB&`9O_wcs 9B#Ew^3a4f1$z(%TH!-r>JEoOBoZa|vD37z3m>g&o^Scv4&Llinjjg-lS zXECf}?u4jL>WKPHP;cb|^!3T`*j;0heq4A3Ez5CV(phCbqOFlV9X4Hw4vfQ@KSPvt zND6VvTRHZ&J#B6@JRIGyH+S2O{Di3Ifeozp=whC&o@?Est~U<-P!+*lCW@z|szOH? zo*cU6LZ{{8DxXDu>K`8X2q+-yAqqAE;Pro)N3ex1@5?2Vq+mrHcD+N=Qc|jN7jN_P zPh@49^MrDqKo#|cy*H~7#Xj${Z(`I-$`t8dKSKjuhde>c1Ct=)4y05_L0>>sE5fKn zVy#IdKnagqo
3(W+SZA&5&u|P2GTz=a|F;@sZsKSb^TUIPTm9}y zyn)mOTDBY_iw8aWPrI3`f3~Z;Hs#xX>4cb!+$#x#WCA_|h|@U~W8;-(_9mzvmd zVRf?lM8kK-z_dSCRODk>Fw@_Jw2l?swLydOZ^QzMZsAFTV4vK>F8!__NO@}f(XrX{ z&@evNix`Rig1c=2H*j2h&5^)6ZHH-YngkBX0VjWJ= FJV11?Ut=f*p+Hv;P z)Lq%n-Xe)4-O<_VCX XK}5K=bu zMtMm-!rBrr-W68BYT803E}%iFy4q2 $ds?kG>Ro4!+!%W%l=3YuK;&TOzzsnu8#n0H}Q*SkEY=6 z>TP^`lo1bgyMs+m_6L4HqR6;?*F3CZ1)|vh!(jLu7aC^^IOYP(YXM`2& 9^+z#tv4odH0HK$i4puK_f?6u?Fy39rp P+p}ftn7NaU) z|GRSPKPNzW#5MtBKt9v)wqOm)u!dMnk42(A^FJZf+QWn^2ILxw@RfhO6CexjzXE{l z*ceIviVXj2&>$hdAy1jlzt H%Gj+&!wZIWT2a9S`^7X^h}A#= zKwyABem!EqvZr=S{Rc?9Q-E6F_kADOkkI?`i@9wU<0vd*bkF!=vtBAQYlz{2l29}U zs7N_JL-$YT!JNQv4+Yq7LX?zYrW*$P9IUtoMo)&+KIL6B(!E9+1c)qQayH#zWeomi zhyV8ge;{Be!k15c(^ZyxRdh+>8B1_;b3%`Z#vk$rYyZ~U`4@_J?Vny#K50ryN=1qU zRNstk)D%6)6vkz9L-0S8{on-n$bGu_9|VRlWMVmnqT1SZZJVB|p{dBhknNkb+)Fm; zXk~`}7=J_+_%V)o?VG;}td>y%)~tK-H{97~xp{h`1_tmwK+9K07r!;qj#ChG6o5AD zXkPX|G?0o4opV@Em9x|t94?V-MGIl{neu}-O&RRp*xfMF6Xr4#0W->f@us0by1`oH ze|;%}S3wWVxZWvVD`;grXjom9$bC9ECXPL1W!6jtvLZoYvwDyBm#_aFlD(pVoIPY- zG+Itw5B?w(9PQI; N?x_u={`CM$zwbbCzav)OQXB59XFajw0uVeT-PQXNxGY%&BGUPqW zYUeCaQ25^o96J4T0>MbR3ILUBIpY>b&>Kd1IPBm70Rr%h+kE&(qY=z%-TWSIK(&A3 zYL7k02XoGbd(UN2Gr(_8gzPjBT#voyee^JlDZ~69y*MPOcV1pNG&hsSNAp1%+00vW zMW}WO47hxSGfX*j5A%HI`n%$OBL9~K=Sq)F2kLX6*XM@P0#Qp^vb|r)5R0jua@B$u zs3Z|yE|JJA_llowMclk431m+Kl7aHUXXJ6P^CR|`rhy}}~34|=#bE>Z(*JP8n-9v)6Yj{V@ zI6`%IDffZIz__?LFCo8g(P7))s&xK0GYC@t_7!%XD|VN1^kj}nWLOPHQypmcJwWpb zyf3^DV>@sW1L~9u23!In!FPsQRQxab+1bO*zzmU0u)oa?ZaAo!6OePPrb_yfiD~7C zAY5~r-X49q``as3bu|P(N?fwb0rf-OGp*=ZzHUswJ7FqxwwnP3kCs z44 ? zDEr$mAWjf}Az+RINc6vRD6ntA)+pz~dizUJDf+(S*Ds$2gK}(&jlcgE0!;~tf*3IV z@b;YI*tV|o-~}N{wI~_1E=Nn?_mqGr0)B+ypk^s1egFkRptQX#zAwKtp#TK^d9RMf z;?P$5XvqL !VQH=OvNh zTh%W=q 7f8l))09Kp!&Hf`%C;?I_7GPjpT~*yfnd~ec zd;oG#am34UdpGc(O7j0sQ|t5PS->~^debqU`5%qyRWlaF7}iMpg8!JiaY~>D3Ro?P zM|-xx*_>X^Bi}uS^;#5=a@dKuRjZ2wYHq686; uvd%ltIpgff9r?vb3;yaQ?*T}ywXw41GUct!3-^|>h{qQ<2!nT;xI89bqpl= z!nbcR!>H%nkC;1Uy7uAeX0JS)1vhS+W4_cpzPb8|dMI=naWS~{yW+MQ#n`<_I%>5} z&*xfqb+QBdsqnq2!e8co9u0iK#z-Kam^Q42Mu>4h`D`GNILIUa1&-6{nmLlZ2H@Rh zIdN1nB6B;K^c_CTL{x1n*lMjsZ741o_#dd5uLUR%%lj4@T-siX4(SPCI;MV_M!PX0 zeCN6Ok&$gEw*SqP|N08v>6a(v5vlOqJw#Dhbw5Ezijh-L$T3=_^ Q4QFsH$v<{C-VeXt#^<=le0Xhr;C(bb zA+o NM~HmC|o{7-zLoZq99F&4}1gnUeor&i7X4B)*$%qvtWI1sp*s_I&rQST{%y zkapkAveX+FFNC{KDq?mbVgP64cXe*lapf=G^t?Q|ML8=b+5GSSnV`udbx}ro%6l07 zqKqf+WYdgIUTU$>H4g(xfY5+fHU3(LzqE6(sn(8tp@l$0tQ~B?=v@n^k%8n-L>2WJ z&)lif$M>r1i=G-yOmhO0JM~#Py1-bu$31}oB*+K;Kg>O=%$h+bxQE`dwFTT@izUMV zKC8s=-})aI3{bsmGDm-NDWYFaK&&o`aQo;TCh#iRWm70FL?kBN8SeHXPt`@R4m7QF zGVw(P8M=oIeog&wwUwRhVk|uzx?j_6@j1d9D6NePZg=$eWu~J;SrlNC_m#*>7jZd; zIGF-cDphbBLzNjGcIYXkcbmpf^4Hhv{~vpA;T6^Qy^qffU4pcPfFd9WNH+{1ph!yR zs7Oml_Y5IO2~rYL(%s!6Al)GyN_W@Hd xpB>T;5)XH31ZP>H&R|l1l=HeJcCE3GeQ6`b2;^sryIQ} zLDjoIhRs41mn&=#&bN*M`jh!*eP4D`zZ)6B)H5|HQqUx}TM@v{8RTXhPg62$&E-C6 z$1zP7@`GFr2-f{v2faCzp%>1~Z@~+Xt_k-zpG!XZf>}KM(nNWjfaW{5|1V2IpN@Tn zZTxPK(K)VatnA4I6P-0kgYJU-0h!2!;hjgHg3j1j=StHZZRmK)@`7-KN@Yn 53ltAMUiwCyzw~kj-2WGfV=Bl5NxNwLaTn6uAM4W5p;f4PgMeAlr zYvr?nI}4fYl^9J70>UkP!v-W)dLEq?ks$p=U6VbcMjJYgFWGI`SnqRKJ8QVt%rrCR z<-(=aV}XVffFUvRSg{QCzoyHO2<6jbq{TIYoK`93TBvAeE=s$MO?NAG$k<8wc-8Os zvV`Jfr&LwK><#L<0U!ivik-rNb3IepR f2|5NluYF_YM2|aAic01tN zjaIPm^l;mK@HhMnx _gA&)=EJCT%IIapPeXbB=AJdE9Oe%nJ5FXHg6hZ)^A}8iBOr7dVEtA%K^!YT zf~njhqtHj!!d5!iHtm+l8_6r9eRwnVEJiaUOPt1rafMFd2d9UX&RSdWJ|@6dvYcev z0qe`yi=M^S3^}(*0F8SL2lOfK)72Le3NAkwMx1u&=)zy}TU}m`L&D&8r_7(I{4%5C z3_>*FOfruirC0_-Am&-{r_UIOpL~P8-u`wgS0Glz)AY}QIkpx^gRW8UY|L0S7a_6G zm45qtOI^!eE!3X$mfDO9yx`D8e@(1<`>WvCQW|AXwe;G@%(IN8vwLzLuR-mFfCm_l zS8hHDaDQny_vWRcE=_n_ Y?dh)SJDNRDN!iLpveZ8mSK=!WAc3=@ZcRxzfJDw9-?FY50S1 zGhTO*OAFHE3TR^!-uew!P f&_$UcG7LHpn$)GGuX}nT}o%9IgAc_RVk^!VN5{= OCdI6r6aL>3JL z^z4SF-bHhO_Wi_@@Kh8TR=D|~LHyagPH4qkVb1~sFj1+#;`DDzENmfA>=zs2jnIXF zXP*!!Q(GvMG$1D@G?Td{aPzy$yPM65WPJ#Ux5 Girt1>WvqD zZ8{fQ``NOr`_&p{cO (p+L2=lulmYnF1H z)jM}=)!sVM85~(dzoRuV%#^#h|MYnvVf&71qJ)*FiMPP~61=yyahx0>&BP!kFVFhj zaMHPG{j=5A{e?Gi$1<*p*N;jG2b>W0ems#M+u{Of5#=)njimIpNAjhdB0i%ElXxmr zRaGbO=G~u6NNE!_Z;>_*BV(=m1&$QL3 ^n2dh1h@fsAiv82QQfgq_K%ZKzft`LTvCYuhx2s77PBE# zMO=5NaQ&iI(kq_;qP~lcz+}OLfLv(9G XS2mD8QnqwI>wre@s$y8QVZh)#g z-Cum@e?at;iV`9UNvPHZrpXdsX%%EB2^GF_*HCpUm$@zU{!ctQ5CJ&6@E;WJ7I{P~ zfGOB+_MLabPO^FQHXw)c{p+xhAfFZgVBOe9pbBE5M5yiEw=0!)X0zR_AEhsvMr(7J z?z4GG*Pa1a5`ef(z7<4k^Hn6HY#LRrHW@QsupT`wS30qbRNi1ZiQ*C~-eS`EavTNZ zhU`TvK_?Ub?~KB$ZGnvsvd%eD{h-RF%Jm|*7NcDdqmH!N)fR6-7WeqQ%Uy}`UBXb% z@}$fbWI8(GEN9ius0^s?e4?3;RCGzH=pw&N&(FS3(5u!+VrhF`!(BMQ4TqeTJ*ifJ zY&FjDIdgbKNX%l3WDnCp$oUAMHXg WM#=fC4|aFYXnTO7Q{Fh2x**#@coqfYR5-A6N4cF zWPRJ9jsC9kHF2>v6~)&_!3zwSn8KS3{-Gt+B~nLPvAhZF>y1aG^j~*|zAN06B;stt zJ^N>QZh?|+0ah!sdt_E~S=n4URK884i?3t%UA7d?Jv_QNNizRgSEn%0mPdOsnk(NG z M z^x&7tS2%H+!S;0bg>xwviX?^6dOwZOn`|?4Un>E^mQ#mh*6*^h-eqMwd;icX;O--f z)~^!0&`+nGp-Z>JR_`ylNlH{4kNU4JtZ8(gP?cDxykvd1F0NZhQ)R&HdNDDDW*sc! z-fX4b^B6@oNu{7l*;q?LP<^+uLs4Y$SpiOk@e%6`iccU245)q7A-kSdd_zT5hrw10 zrgbP?Omuu9D`T`R;W2lt(IMFu1FM_Pm6`^B`pKAO3;_I!rW( z1@q)6K2px3&urr(q$-sS=1Z`pWU0hbxfplo(f&ipqH_Q_wE$7HKDS_m$5_;%vLs%` zk`sQ;SkxsCnh$)UQl#!bpmJ9^zk7J|w0Wt+j?nKJ7FsH2myxSq_h%YI+~sGo8@C~e zE}$G^W|+&sKxx-~J_!2*w^MD1vL=`1_qLy7sGK}CRS}NRZiD)A?GMqCe<(!nX66(T zSIslUqLSu^fa(V+T*H8DjsbtNMl&F|P4VVyQ(xgv^J^xqqpwxA>4*{$3o9h!FWt@O z8cKB`Jaw&uV7^FKRP#xqQuMC8kod#i;T0>XdZkDw)FHkfHBk8kaCMfVhekgw8w@X? z03~@bj0T7Q&Ldj?aCPp&qblY(I|Q(mjo4$HkB1czz=XGew(P=c|M-YsS*M^-6e|g) zzS;Hn@bQ=16K70mVR{~x&L*&i&ty>ZB>Uk;ZjV&P6VtIhBGoXWF{sHKv|^oiK@a8D z{mc@D_@&+jHrveI*49JLWTIbtPSij|#ORl=0F*to!5X!}Oa?hObB%h#;EuiOh8VYj z^+!NoOzA#)YzmAwz7&YIjb4H~Jp^}pxo+I0aS=;-^miBp{r^x7@FA9L0#!GI{8<`` zKoSf%1Ljom-FbVol%8}E8x+t9YW9$jNR 9i?5>#i4Das z{jh+su1#99pNhBzg1&~`54uZtd#UeFI0TFMMG(~c4;3kB_`ksU#6lMTb$!tzJCc?9 zl{Vvip5sS6*_l9G&nL#{708G6gAZ3J-KGK61Ye3THo1QhH{cl@Qs_gI9;`NtBhm+t z^;A+~=Ih_-TDPBtz%C}69)R*OezT`90iSY$1a)po{_M9&ql_h3z-+dHB``c}OS_JB zyyXF`URMOXP!JZG1pC&u&U+l6;XACZw|+haeO?K3N5$mNQb@b@m*_x~Y^F_GGM} S6r zI(JI`;8%NZ^>1dkGctexQ$iOnwTp3&aGwULPRxM~KUud)K#O>6)Gs@UGL@f*n*)>k zhLk+jYD+YHd*SE{V4eN~ehpa~;`C0$!XUro|$WaiC9}}Q- zDQZBb`od0l-LSJ=ia`cY72py%@CZLg)z}mz&(%*#JYe=%!*k(*L-VO->$`2m(a4!x z$p#i9G5VBHyep*jG)2@bMyE9bU`4%yB>HJ@|#t sX zmna<~i!p!n_gOv%L?t+w=4Qh$>_>d6*{4|v_Ks~7=SV`nW6nY)J(N`(P`Xb?VrwKn z) #9)de*SQpOLRgPEC=4deg;=@7%Rgolrbo+(@z4BL;e7HkqQH8nl| zP?=D*p9`z~_6@afKiKZu@3R725cxdIdgp7KVt_$6gJ=5R!n4)n`aZfH3+NddA7(ey zQUT=f-3ls^FBg%+d`M6Gg`WMPV1ZXFvu@)9V_Jr^)D&TesE^TzdSrm|oX(l!?Bv8L z=1FLx!$yjP-TmgY4>z)V2o9G=DEqh7$M@xA9 I^ zVt4Lrt~e;7QbBC0@-J5oNjki0EPtF%?NC3V1|t%13ISs_x^0wv)3`k{u=!db3n~*5 zHivB{2q%m)2b@~X`_!hEvMxB(n37Da+C*v_e5%z`QEA mqDYhlyD7t~!6>fLtD0{JbO~7M;M6xCy&WXf>PGo(*^R%iE6Icm>F|IoQ?D4qoZ| za)$MDerk9zsIrg^jQJ`rH@D|v4wuv+@%!)yuJl>N$K QPrQOgIq((DRoLn$1{5XU zdyempkFFwt{v5428A}{q!5=32t+NKHD`}pPs)PxXO#29hA1)=)o 1D~~LOry;tV*2C9anuL1^vrIR3X6xadRtC*w^AM zagp2D=(eI*PKQ!8$|2+_KiL$4em8$n;Dr0TNSD!0fQm%RXsgn5M>}L8==J5+^uaQ! z54f}ZUFxgEf^*k52f3ED^$i7PBaxi49be@?&vNe~$RKdoH=(>SBQ&%-0tN0A8)(}O zjGqq7><$D$UmYlD3`^E}xdOSad@#`s^j$!?C}s{kpw$dZk}h>xAcVZ)vYTq1qY6$R zLittgsHlh`KN6^t({|C6!bU+S5i{1 #%~u!0_TXSAVUvJ zK3oiZKrJ~@o6$=?ah~H{?* KhuGY*IjzF6j!jHD>wHWV`ngyB6nMdS@x1lI ^N4mPrfySu?79MilcH~Lb}^;O4pVy4vHX>Cxgt|hS-PWR(bJxt$zw1N5F-N z|4)exSTaS40~}xPdY@G|)4Z&^FZm4a!z_1B&l8kFAH-IhrbuKhYP%Ys*K~*$I^FBG zaE6AYBULsVLFZ%x=V%14G*6lSU{6f_{xsTQbrQ{cI zc&T{T{fkS7jbXYAV0?vHpnoxlo|;%0z9d0FLj82=-OVudSgfJ7&)7yhd%ntz=pqXR zZ;MV{jeNsk)rFdo2_23k3V#m-uPiI03Nr;gDZilR+6(;I1vlf4zLGrxTz+VhmsN}i z7EnV|^Y_f%CsNwKbJ-Uiu62-l9nZfoyUX5iHwKilxFlymY%QUsA6??n7u 3pB7X$$uAy(#F=fMlnRDz)+r~B z6jL^weJ0 L%(0$bU6 zj~ts(#;d;jeUpWJ2nCI=dqKiNH#-$K&-m$dZJw2NcZgm<3n7>un_0fW2t-u`Nt4u+ zQ-`XqqSc>V0NwBeR8bE$Zx}z{`yX7RKt3i^87>N5STGP#=M>$O>;2((>SmZxbpJ-t zV|p`e7YhKY_o>*rUgF5f1a_I`4MAH(%~p~G?L^rUT|dHc<+zur;)LSPFNXJ9$er7c z(Q#-20Bh=LQSZBi_x{GY^xnG+Dp_QJ=fW=sAiNeva|t2s%Hx+Oy>EH;g6618?QI$? z%{JJI-iHRuvHdj8kk~;TTsUibC03CaBClPV?5bEo0Cut@!DSNvK!Tc)D31nOlUmfT zR;N-)s7B3FUhlrQ02t;s$Y3bnnU#Adh;JVRdQ)G&7O+!U=w`LuNIRE(1K`wg!*zEs zuTCGb;||qmGfGcDk4RHgTthA~JutcAf4yN0S81jGK0bbe-e3U$zRAo7JJ0CMSsHEJ z)3pw