Browse Source

Initial commit

main
少轻狂 GitHub 2 years ago
commit
6502afb992
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 10489 additions and 0 deletions
  1. +9
    -0
      .editorconfig
  2. +3
    -0
      .eslintrc
  3. +1
    -0
      .github/FUNDING.yml
  4. +44
    -0
      .github/workflows/ci.yml
  5. +12
    -0
      .gitignore
  6. +2
    -0
      .npmrc
  7. +13
    -0
      .vscode/extensions.json
  8. +28
    -0
      .vscode/settings.json
  9. +21
    -0
      LICENSE
  10. +241
    -0
      README.md
  11. +9
    -0
      app/api/api.py
  12. +3
    -0
      app/assets/requirements.txt
  13. +10
    -0
      app/config/config.py
  14. +45
    -0
      app/main.py
  15. +141
    -0
      app/spec/getSpec.py
  16. +22
    -0
      index.html
  17. +7
    -0
      locales/README.md
  18. +14
    -0
      locales/en.yml
  19. +14
    -0
      locales/zh-CN.yml
  20. +16
    -0
      netlify.toml
  21. +88
    -0
      package.json
  22. +8341
    -0
      pnpm-lock.yaml
  23. +3
    -0
      public/_headers
  24. +3
    -0
      public/favicon-dark.svg
  25. +3
    -0
      public/favicon.svg
  26. BIN
      public/logo.ico
  27. BIN
      public/pwa-192x192.png
  28. BIN
      public/pwa-512x512.png
  29. +41
    -0
      public/safari-pinned-tab.svg
  30. +26
    -0
      src/App.vue
  31. +560
    -0
      src/auto-imports.d.ts
  32. +17
    -0
      src/components.d.ts
  33. +19
    -0
      src/components/Counter.vue
  34. +33
    -0
      src/components/Footer.vue
  35. +20
    -0
      src/components/Input.vue
  36. +10
    -0
      src/components/README.md
  37. +4
    -0
      src/composables/dark.ts
  38. +19
    -0
      src/layouts/404.vue
  39. +14
    -0
      src/layouts/README.md
  40. +9
    -0
      src/layouts/default.vue
  41. +9
    -0
      src/layouts/home.vue
  42. +24
    -0
      src/main.ts
  43. +11
    -0
      src/modules/README.md
  44. +25
    -0
      src/modules/i18n.ts
  45. +14
    -0
      src/modules/nprogress.ts
  46. +17
    -0
      src/modules/pinia.ts
  47. +12
    -0
      src/modules/pwa.ts
  48. +20
    -0
      src/pages/README.md
  49. +14
    -0
      src/pages/[...all].vue
  50. +21
    -0
      src/pages/about.md
  51. +47
    -0
      src/pages/hi/[name].vue
  52. +73
    -0
      src/pages/index.vue
  53. +16
    -0
      src/shims.d.ts
  54. +34
    -0
      src/store/user.ts
  55. +29
    -0
      src/styles/main.css
  56. +28
    -0
      src/styles/markdown.css
  57. +3
    -0
      src/types.ts
  58. +37
    -0
      tsconfig.json
  59. +38
    -0
      unocss.config.ts
  60. +152
    -0
      vite.config.ts

+ 9
- 0
.editorconfig View File

@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

+ 3
- 0
.eslintrc View File

@@ -0,0 +1,3 @@
{
"extends": "@antfu"
}

+ 1
- 0
.github/FUNDING.yml View File

@@ -0,0 +1 @@
github: antfu

+ 44
- 0
.github/workflows/ci.yml View File

@@ -0,0 +1,44 @@
name: CI

on:
push:
branches:
- main

pull_request:
branches:
- main

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v3
with:
node-version: 16.x
cache: pnpm

- name: Install
run: pnpm install

- name: Lint
run: pnpm run lint

typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v3
with:
node-version: 16.x
cache: pnpm

- name: Install
run: pnpm install

- name: Typecheck
run: pnpm run typecheck


+ 12
- 0
.gitignore View File

@@ -0,0 +1,12 @@
.DS_Store
.vite-ssg-dist
.vite-ssg-temp
*.local
dist
dist-ssr
node_modules
.idea/
*.log
*.spec
__pycache__
.vscode

+ 2
- 0
.npmrc View File

@@ -0,0 +1,2 @@
shamefully-hoist=true
strict-peer-dependencies=false

+ 13
- 0
.vscode/extensions.json View File

@@ -0,0 +1,13 @@
{
"recommendations": [
"antfu.iconify",
"antfu.unocss",
"antfu.vite",
"antfu.goto-alias",
"csstools.postcss",
"dbaeumer.vscode-eslint",
"vue.volar",
"lokalise.i18n-ally",
"streetsidesoftware.code-spell-checker"
]
}

+ 28
- 0
.vscode/settings.json View File

@@ -0,0 +1,28 @@
{
"cSpell.words": [
"demi",
"iconify",
"intlify",
"pinia",
"pnpm",
"pywebview",
"unocss",
"unplugin",
"Vite",
"vitejs",
"Vitesse",
"vueuse"
],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.keystyle": "nested",
"i18n-ally.localesPaths": "locales",
"i18n-ally.sortKeys": true,
"prettier.enable": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"files.associations": {
"*.css": "postcss"
},
"editor.formatOnSave": false
}

+ 21
- 0
LICENSE View File

@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020-2021 Anthony Fu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 241
- 0
README.md View File

@@ -0,0 +1,241 @@
<h1 align='center'>Vitesse-Python</h1>

<p align='center'>
Mocking up web app with <b>Vitesse</b><sup><em>(speed)</em></sup><br>
</p>

<br>


<br>

<p align='center'>
<b>简体中文</b> | <a href="">English</a>
<!-- Contributors: Thanks for getting interested, however we DON'T accept new transitions to the README, thanks. -->
</p>

<br>

## Introduction

### 👀 `Vitesse-Python`

- Vitesse-Python 帮助您构建 windows 平台客户端的应用,不再受pyqt的困扰。
- Vitesse-Python 的视图层采用 HTML+JS+CSS,业务层采用本地 Python。
- Vitesse-Python 采用了 Vite 的开发模式,支持热更新,开发体验更佳。
- Vitesse-Python 采用了 PyInstaller 打包,支持 windows 平台,打包体积更小。
- Vitesse-Python 采用了 pywebview 作为渲染引擎,支持 windows 平台,渲染速度更快。
- Vitesse-Python 采用了 Vue3、Vitesse 作为前端框架,代码编写更优雅从容。

### 📦 适用场景

- 对软件的用户界面有一定美感要求
- 需要用到 Python 中的人工智能等模块
- 考虑搭建本地应用,使用本机计算和存储资源
- 对软件功能要求比较高,需要自己开发

### 👨‍💻 适用人群

- 熟悉 Vue3 和 Python 编程的程序员。
- 熟悉 HTML、CSS、JS 的前端工程师。
- 熟悉 Python 的数据分析师。
- 熟悉 Python 的机器学习工程师。
- 熟悉 Python 的人工智能工程师。
- 熟悉 Python 的软件工程师。

## Features

- ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite 3](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [ESBuild](https://github.com/evanw/esbuild) - born with fastness

- 🗂 [File based routing](./src/pages)

- 📦 [Components auto importing](./src/components)

- 🍍 [State Management via Pinia](https://pinia.vuejs.org/)

- 📑 [Layout system](./src/layouts)

- 📲 [PWA](https://github.com/antfu/vite-plugin-pwa)

- 🎨 [UnoCSS](https://github.com/antfu/unocss) - the instant on-demand atomic CSS engine

- 😃 [Use icons from any icon sets with classes](https://github.com/antfu/unocss/tree/main/packages/preset-icons)

- 🌍 [I18n ready](./locales)

- 🔎 [Component Preview](https://github.com/johnsoncodehk/vite-plugin-vue-component-preview)

- 🗒 [Markdown Support](https://github.com/antfu/vite-plugin-vue-markdown)

- 🔥 Use the [new `<script setup>` syntax](https://github.com/vuejs/rfcs/pull/227)

- 🤙🏻 [Reactivity Transform](https://vuejs.org/guide/extras/reactivity-transform.html) enabled

- 📥 [APIs auto importing](https://github.com/antfu/unplugin-auto-import) - use Composition API and others directly

- 🖨 Static-site generation (SSG) via [vite-ssg](https://github.com/antfu/vite-ssg)

- 🦔 Critical CSS via [critters](https://github.com/GoogleChromeLabs/critters)

- 🦾 TypeScript, of course

- ☁️ Deploy on Netlify, zero-config

- 🎉 <strong>[Pywebview](https://pywebview.flowrl.com/) inside </strong>

<br>


## Try it now!

> Vitesse-Python requires Node >=14.18 & Python >=3.7

```bash

### GitHub Template

[Create a repo from this template on GitHub](https://github.com/MarleneJiang/vitesse-python).

### Clone to local

If you prefer to do it manually with the cleaner git history

```bash
git clone https://github.com/MarleneJiang/vitesse-python.git
cd vitesse-python
pnpm inits # If you don't have pnpm installed, run: npm install -g pnpm
```

## Usage

### 开发前端

```bash
pnpm dev
```

### 开发软件

```bash
pnpm dev:app
```

### 整体开发

```bash
pnpm start
```

### 预打包,带console,方便输出日志信息

```bash
pnpm pre
```

### 预打包,带console,生成文件夹,仅win系统

```bash
pnpm pre:folder
```

### 正式打包,仅win系统

```bash
pnpm build
```

### 正式打包,生成文件夹,仅win系统

```bash
pnpm build:folder
```

## 高级用法

### 客户端引擎介绍

`Vitesse-Python` 基于 [pywebview](https://pywebview.flowrl.com) 构建客户端。而 pywebview 构架构建客户端的原理是利用本地电脑自带的浏览器引擎驱动,模拟生成客户端。本质上还是网页,或者说是一个浏览器,但是感官上和本地客户端没有差别。

那么,基于 pywebview 构架构建客户端的成败或质量,就与本地电脑的浏览器引擎息息相关了。

##### windows 系统

在 windows 系统上,大体上分为两类客户端引擎:正常模式和兼容模式。`Vitesse-Python` 仅支持正常模式。

- 正常模式

正常模式下,按照 edgechromium ,edgehtml, mshtml 的客户端引擎依次检索。如果本地电脑 edge 浏览器支持这些引擎,则客户端可以正常启动。否则,请安装对应的 [EdgeWebView2Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) 浏览器引擎。

- 兼容模式

如果本地电脑 edge 浏览器不支持这些引擎,同时也不想下载 [EdgeWebView2Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) ,那么就可以使用兼容模式。兼容模式的原理就是利用 [CEFPython](https://github.com/cztomczak/cefpython),嵌入 Chromium 的 Web 浏览器控件。也就是只要本地电脑安装了谷歌浏览器 V66 版及其以上版本,即可正常启动客户端。缺点就是生成的安装包体积会增加大约 60M 左右。


### 构建客户端 API

构建客户端的主程序是在 app 文件夹下的 main.py。

main.py 里面主要是依靠 webview.create_window 和 webview.start 这两个 API 来构建客户端。其他的一些 API,可以直接查看 [pywebview 官网](https://pywebview.flowrl.com/guide/api.html) 了解详情。

#### webview.create_window

```
webview.create_window(title, url='', html='', js_api=None, width=800, height=600, \
x=None, y=None, resizable=True, fullscreen=False, \
min_size=(200, 100), hidden=False, frameless=False, \
minimized=False, on_top=False, confirm_close=False, \
background_color='#FFF')
```

创建一个新的 pywebview 窗口,并返回其实例。在开始 GUI 循环之前,窗口不会显示。

- **title** 窗口标题
- **url** 要加载的 URL。如果 URL 没有协议前缀,则将其解析为相对于应用程序入口点的路径。或者,可以传递 WSGI 服务器对象来启动本地 Web 服务器。
- **html** 要加载的 HTML 代码。如果同时指定了 URL 和 HTML,HTML 优先。
- **js_api** 将 python 对象暴露到当前 pywebview 窗口的 DOM 中。js_api 对象的方法可以通过调用 window.pywebview.api.<methodname>(<parameters>)从 Javascript 执行。请注意,调用 Javascript 函数会收到一个包含 python 函数的返回值。只有基本的 Python 对象(如 int、str、dict......)才能返回 Javascript。
- **width** 窗户宽度。默认值为 800px。
- **height** 窗户高度。默认值为 600px。
- **x** 窗口 x 坐标。默认值居中。
- **y** 窗口 y 坐标。默认值居中。
- **resizable** 是否可以调整窗口大小。默认值为 True
- **fullscreen** 从全屏模式开始。默认为 False
- **min_size** 指定最小窗口大小的(宽度、高度)元组。默认值为 200x100
- **hidden** 默认情况下创建一个隐藏的窗口。默认为 False
- **frameless** 创建一个无框窗口。默认值为 False。
- **minimized** 以最小化模式启动
- **on_top** 将窗口设置为始终位于其他窗口的顶部。默认值为 False。
- **confirm_close** 是否显示窗口关闭确认对话框。默认为 False
- **background_color** 加载 WebView 之前显示的窗口的背景颜色。指定为十六进制颜色。默认值为白色。
- **transparent** 创建一个透明的窗口。Windows 不支持。默认值为 False。请注意,此设置不会隐藏或使窗口铬透明。将窗口 chrome setframeless 隐藏为 True。

#### webview.start

```
webview.start(func=None, args=None, localization={}, gui=None, debug=False, http_server=False)
```

启动 GUI 循环并显示之前创建的窗口。此函数必须从主线程调用。

- **func** 启动 GUI 循环时调用的函数。
- **args** 函数参数。可以是单个值,也可以是元组值。
- **localization** 带有本地化字符串的词典。默认字符串及其键在 localization.py 中定义
- **gui** 强制使用特定的 GUI。允许的值是 cef、qt 或 gtk,具体取决于平台。
- **debug** 启用调试模式。
- **http_server** 启用内置 HTTP 服务器。如果启用,本地文件将使用随机端口上的本地 HTTP 服务器提供服务。对于每个窗口,都会生成一个单独的 HTTP 服务器。对于非本地 URL,此选项将被忽略。

### 域间通信

#### 从 Python 调用 Javascript

window.evaluate_js(code, callback=None)允许您使用同步返回的最后一个值执行任意 Javascript 代码。如果提供了回调函数,则解析 promise,并调用回调函数,结果作为参数。Javascript 类型转换为 Python 类型,例如 JS 对象到 Python 字典,数组到列表,未定义为 None。由于实现限制,字符串“null”将被计算为 None。另外,evaluate_js 返回的值限制为 900 个字符内。

#### 从 Javascript 调用 Python

从 Javascript 调用 Python 函数可以通过两种不同的方法完成。

- 通过将 Python 类的实例暴露给 create_window 的 js_api。该类的所有可调用方法都将以 pywebview.api.method_name 的形式公开到 JS 域中。方法名称不得以下划线开头。
- 通过将函数传递给窗口对象的 expose(func)这将以 pywebview.api.func_name 的形式将一个或多个函数公开到 JS 域。与 JS API 不同,expose 也允许在运行时公开函数。如果 JS API 和以这种方式公开的函数之间存在名称冲突,则后者优先。

## THX

- [vue-pywebview-pyinstaller](https://github.com/pangao1990/vue-pywebview-pyinstaller)

+ 9
- 0
app/api/api.py View File

@@ -0,0 +1,9 @@

class API:
'''本地API,供前端JS调用'''
window = None

def getOwner(self):
self.window.evaluate_js('getPythonData()')

return '我是Python'

+ 3
- 0
app/assets/requirements.txt View File

@@ -0,0 +1,3 @@
pywebview==3.7.2
pyinstaller==5.6.2
tinyaes==1.0.4

+ 10
- 0
app/config/config.py View File

@@ -0,0 +1,10 @@
import platform


class Config:
'''配置文件'''

appName = 'Vitesse-Python' # 应用名称
appVersion = "1.0.0" # 应用版本号

appSystem = platform.system() # 本机系统类型

+ 45
- 0
app/main.py View File

@@ -0,0 +1,45 @@
import os
import sys

import webview
import argparse
from api.api import API
from config.config import Config

# 前端页面目录
if sys.flags.dev_mode:
MAIN_DIR = os.path.join("..", "dist") # 开发环境
DEBUG = True
else:
MAIN_DIR = os.path.join(".", "web") # 生产环境
DEBUG = False


def WebViewApp(port,dev=False):
api = API() # 本地接口
cfg = Config() # 配置文件
if(dev):
window = webview.create_window(cfg.appName, 'http://localhost:'+str(port)+'/',js_api=api)
webview.start(debug=DEBUG, http_server=True) # 启动窗口
else:
template = os.path.join(MAIN_DIR, "index.html") # 设置页面,可以指向远程或本地
window = webview.create_window(title=cfg.appName, url=template, js_api=api) # 创建窗口
api.window=window # 本地接口
webview.start(debug=DEBUG, http_server=True) # 启动窗口


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
'--dev',
type=str,
default='False',
help="开发模式")
parser.add_argument(
'--port',
type=str,
default='3333',
help="端口号")
args = parser.parse_args()

WebViewApp(args.port,args.dev=='True')

+ 141
- 0
app/spec/getSpec.py View File

@@ -0,0 +1,141 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))#
from config.config import Config

cfg = Config()

buildPath = 'build' # 存放最终打包成app的相对路径
console = False # 是否展示终端
mainName = 'main.py' # 主程序 main.py
cryptoKey = '0123456789123456' # 对Python字节码加密

appName = cfg.appName # 项目名称
version = cfg.appVersion # 版本号


# spec配置文件 前半部分通用格式
def specFirstPart():
return f'''
# -*- mode: python ; coding: utf-8 -*-

import json
import os
import sys

import PyInstaller.config

# 存放最终打包成app的相对路径
buildPath = '{buildPath}'
PyInstaller.config.CONF['distpath'] = buildPath

# 存放打包成app的中间文件的相对路径
cachePath = os.path.join(buildPath, 'cache')
if not os.path.exists(cachePath):
os.makedirs(cachePath)
PyInstaller.config.CONF['workpath'] = cachePath

# icon相对路径
icoPath = os.path.join('..', '..', 'public', 'logo.ico')

# 项目名称
appName = '{appName}'

# 版本号
version = '{version}'

# 对Python字节码加密
block_cipher = pyi_crypto.PyiBlockCipher(key='{cryptoKey}')


a = Analysis(['../{mainName}'],
pathex=[],
binaries=[],
datas=[('../../dist', 'web')],
hiddenimports=[],
hookspath=[],
hooksconfig={{}},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)

'''

# 打包为一个exe文件
def specPackagePartEXE():
return f'''
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name=appName,
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console={console},
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=icoPath)

'''


# 以文件夹形式存在
def specUnpackagePartEXE():
return f'''
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name=appName,
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console={console},
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=icoPath)
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name=appName)

'''


# 生成 spec 配置文件
specDir = os.path.dirname(__file__)

# windows.spec
with open(os.path.join(specDir, 'windows.spec'), 'w+', encoding='utf-8') as f:
f.write(specFirstPart() + specPackagePartEXE())
# windows-folder.spec
with open(os.path.join(specDir, 'windows-folder.spec'), 'w+', encoding='utf-8') as f:
f.write(specFirstPart() + specUnpackagePartEXE())

console = True # 是否展示终端
# windows-pre.spec 带终端
with open(os.path.join(specDir, 'windows-pre.spec'), 'w+', encoding='utf-8') as f:
f.write(specFirstPart() + specPackagePartEXE())
# windows-folder-pre.spec
with open(os.path.join(specDir, 'windows-folder-pre.spec'), 'w+', encoding='utf-8') as f:
f.write(specFirstPart() + specUnpackagePartEXE())

+ 22
- 0
index.html View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="apple-touch-icon" href="/pwa-192x192.png">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#00aba9">
<meta name="msapplication-TileColor" content="#00aba9">
<script>
(function () {
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
const setting = localStorage.getItem('vueuse-color-scheme') || 'auto'
if (setting === 'dark' || (prefersDark && setting !== 'light'))
document.documentElement.classList.toggle('dark', true)
})()
</script>
</head>
<body class="font-sans">
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

+ 7
- 0
locales/README.md View File

@@ -0,0 +1,7 @@
## i18n

This directory is to serve your locale translation files. YAML under this folder would be loaded automatically and register with their filenames as locale code.

Check out [`vue-i18n`](https://github.com/intlify/vue-i18n-next) for more details.

If you are using VS Code, [`i18n Ally`](https://github.com/lokalise/i18n-ally) is recommended to make the i18n experience better.

+ 14
- 0
locales/en.yml View File

@@ -0,0 +1,14 @@
button:
about: About
back: Back
go: GO
home: Home
toggle_dark: Toggle dark mode
toggle_langs: Change languages
intro:
desc: Opinionated Vite Starter Template
dynamic-route: Demo of dynamic route
hi: Hi, {name}!
aka: Also known as
whats-your-name: What's your name?
not-found: Not found

+ 14
- 0
locales/zh-CN.yml View File

@@ -0,0 +1,14 @@
button:
about: 关于
back: 返回
go: 确定
home: 首页
toggle_dark: 切换深色模式
toggle_langs: 切换语言
intro:
desc: 固执己见的 Vite 项目模板
dynamic-route: 动态路由演示
hi: 你好,{name}
aka: 也叫
whats-your-name: 输入你的名字
not-found: 未找到页面

+ 16
- 0
netlify.toml View File

@@ -0,0 +1,16 @@
[build.environment]
NODE_VERSION = "16"

[build]
publish = "dist"
command = "pnpm run build"

[[redirects]]
from = "/*"
to = "/index.html"
status = 200

[[headers]]
for = "/manifest.webmanifest"
[headers.values]
Content-Type = "application/manifest+json"

+ 88
- 0
package.json View File

@@ -0,0 +1,88 @@
{
"name": "vitesse-python",
"type": "module",
"private": true,
"packageManager": "pnpm@7.8.0",
"description": "基于vitesse,pywebview的python桌面应用",
"author": "Marlene <1677568218@qq.com>",
"scripts": {
"dev": "vite --port 3333 --open ",
"dev:app": "python app\\main.py --port 3333 --dev 'True'",
"lint": "eslint .",
"preview": "vite preview",
"preview-https": "serve dist",
"typecheck": "vue-tsc --noEmit",
"up": "taze major -I",
"inits": "pnpm install && run-script-os",
"inits:windows": "python app\\spec\\getSpec.py && pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r .\\app\\assets\\requirements.txt",
"start": "vite build && run-script-os",
"start:windows": "python -X dev .\\app\\main.py",
"pre": "shx rm -rf build && vite build && run-script-os",
"pre:windows": "pyinstaller --clean .\\app\\spec\\windows-pre.spec",
"pre:folder": "shx rm -rf build && vite build && pyinstaller --clean .\\app\\spec\\windows-folder-pre.spec",
"build": "shx rm -rf build && vite build && run-script-os",
"build:windows": "pyinstaller -w --clean .\\app\\spec\\windows.spec",
"build:folder": "shx rm -rf build && vite build && pyinstaller --clean .\\app\\spec\\windows-folder.spec"
},
"dependencies": {
"@unocss/reset": "^0.46.5",
"@vueuse/core": "^9.5.0",
"@vueuse/head": "^1.0.18",
"nprogress": "^0.2.0",
"pinia": "^2.0.25",
"run-script-os": "^1.1.6",
"shx": "^0.3.4",
"vue": "^3.2.45",
"vue-demi": "^0.13.11",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@antfu/eslint-config": "^0.31.0",
"@iconify-json/carbon": "^1.1.11",
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
"@types/markdown-it-link-attributes": "^3.0.1",
"@types/nprogress": "^0.2.0",
"@vitejs/plugin-vue": "^3.2.0",
"@vue-macros/volar": "^0.5.4",
"@vue/test-utils": "^2.2.4",
"critters": "^0.0.16",
"cross-env": "^7.0.3",
"eslint": "^8.28.0",
"https-localhost": "^4.7.1",
"markdown-it-link-attributes": "^4.0.1",
"markdown-it-shiki": "^0.6.1",
"pnpm": "^7.17.0",
"shiki": "^0.11.1",
"taze": "^0.8.4",
"typescript": "^4.9.3",
"unocss": "^0.46.5",
"unplugin-auto-import": "^0.11.5",
"unplugin-vue-components": "^0.22.11",
"unplugin-vue-macros": "^1.0.0",
"vite": "^3.2.4",
"vite-plugin-inspect": "^0.7.9",
"vite-plugin-pages": "^0.27.1",
"vite-plugin-pwa": "^0.13.3",
"vite-plugin-vue-component-preview": "^0.3.3",
"vite-plugin-vue-layouts": "^0.7.0",
"vite-plugin-vue-markdown": "^0.22.1",
"vite-ssg": "^0.22.0",
"vite-ssg-sitemap": "^0.4.3",
"vue-tsc": "^1.0.9"
},
"version": "1.0.0",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/MarleneJiang/vitesse-python.git"
},
"keywords": [
"qt5"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/MarleneJiang/vitesse-python/issues"
},
"homepage": "https://github.com/MarleneJiang/vitesse-python#readme"
}

+ 8341
- 0
pnpm-lock.yaml
File diff suppressed because it is too large
View File


+ 3
- 0
public/_headers View File

@@ -0,0 +1,3 @@
/assets/*
cache-control: max-age=31536000
cache-control: immutable

+ 3
- 0
public/favicon-dark.svg View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M27.562 26L17.17 8.928l2.366-3.888L17.828 4L16 7.005L14.17 4l-1.708 1.04l2.366 3.888L4.438 26H2v2h28v-2zM16 10.85L25.22 26H17v-8h-2v8H6.78z" fill="white" />
</svg>

+ 3
- 0
public/favicon.svg View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M27.562 26L17.17 8.928l2.366-3.888L17.828 4L16 7.005L14.17 4l-1.708 1.04l2.366 3.888L4.438 26H2v2h28v-2zM16 10.85L25.22 26H17v-8h-2v8H6.78z" fill="#222" />
</svg>

BIN
public/logo.ico View File

Before After

BIN
public/pwa-192x192.png View File

Before After
Width: 192  |  Height: 192  |  Size: 3.9 kB

BIN
public/pwa-512x512.png View File

Before After
Width: 512  |  Height: 512  |  Size: 10 kB

+ 41
- 0
public/safari-pinned-tab.svg View File

@@ -0,0 +1,41 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2916 6015 c-93 -57 -173 -108 -178 -113 -6 -6 7 -36 33 -78 23 -38
86 -141 139 -229 54 -88 135 -221 180 -295 46 -74 94 -155 108 -180 14 -25 29
-52 35 -60 7 -12 -9 -45 -62 -130 -39 -63 -85 -140 -103 -170 -18 -30 -117
-194 -222 -365 -104 -170 -199 -326 -210 -346 -12 -19 -61 -102 -111 -183 -49
-81 -101 -166 -115 -189 -14 -23 -39 -64 -55 -90 -17 -27 -77 -126 -134 -220
-57 -95 -127 -210 -156 -257 -194 -315 -325 -533 -325 -541 0 -5 -4 -9 -10 -9
-5 0 -10 -4 -10 -9 0 -5 -55 -98 -121 -207 -247 -404 -403 -660 -416 -684 -8
-14 -58 -97 -112 -185 l-98 -160 -189 -2 c-104 -1 -225 -2 -269 -2 l-80 -1 1
-210 c0 -116 4 -213 8 -218 11 -11 6107 -9 6114 2 8 13 8 406 0 419 -4 7 -88
10 -265 9 l-259 -2 -50 77 c-27 43 -54 87 -60 98 -6 11 -62 103 -124 205 -62
102 -120 197 -129 212 -9 16 -85 142 -170 280 -85 139 -160 262 -165 273 -6
11 -13 22 -16 25 -3 3 -30 46 -59 95 -30 50 -102 169 -161 265 -59 96 -240
393 -402 660 -163 267 -371 609 -463 760 -92 151 -194 318 -225 370 -31 52
-101 167 -155 255 l-97 160 27 50 c16 27 32 55 36 61 5 5 38 59 74 120 36 60
69 116 74 124 5 8 75 122 155 253 81 131 144 242 141 247 -4 7 -114 76 -183
115 -10 6 -52 32 -95 58 -42 27 -81 46 -87 42 -8 -5 -94 -140 -140 -219 -19
-33 -221 -365 -246 -404 -15 -22 -18 -18 -111 135 -52 87 -123 203 -157 258
-67 108 -67 110 -111 184 -16 28 -34 51 -40 50 -5 0 -86 -47 -179 -104z m739
-1642 c319 -526 519 -854 637 -1046 43 -70 78 -130 78 -133 0 -2 5 -10 10 -17
6 -7 69 -109 140 -227 72 -118 134 -222 139 -230 5 -8 55 -89 111 -180 56 -91
105 -172 110 -180 9 -14 52 -84 270 -445 54 -88 135 -221 180 -295 46 -74 91
-148 100 -165 9 -16 31 -53 48 -81 18 -28 32 -54 32 -57 0 -3 -403 -6 -895 -5
l-895 0 0 81 c-1 45 -1 439 -1 875 l0 792 -37 1 c-57 1 -344 1 -374 0 l-27 -1
0 -832 c0 -458 0 -852 0 -875 l-1 -42 -895 1 c-492 0 -895 3 -895 5 0 9 115
198 122 201 5 2 8 7 8 12 0 5 23 46 51 92 28 46 78 128 112 183 33 55 70 116
82 135 12 19 132 215 265 435 133 220 266 438 295 485 65 105 206 338 220 362
6 10 172 284 370 608 198 325 387 635 420 690 33 55 62 100 65 100 3 0 73
-111 155 -247z"/>
</g>
</svg>

+ 26
- 0
src/App.vue View File

@@ -0,0 +1,26 @@
<script setup lang="ts">
// https://github.com/vueuse/head
// you can use this to manipulate the document head in any components,
// they will be rendered correctly in the html results with vite-ssg
useHead({
title: 'Vitesse',
meta: [
{ name: 'description', content: 'Opinionated Vite Starter Template' },
{
name: 'theme-color',
content: computed(() => isDark.value ? '#00aba9' : '#ffffff'),
},
],
link: [
{
rel: 'icon',
type: 'image/svg+xml',
href: computed(() => preferredDark.value ? '/favicon-dark.svg' : '/favicon.svg'),
},
],
})
</script>

<template>
<RouterView />
</template>

+ 560
- 0
src/auto-imports.d.ts View File

@@ -0,0 +1,560 @@
// Generated by 'unplugin-auto-import'
export {}
declare global {
const $$: typeof import('vue/macros')['$$']
const $: typeof import('vue/macros')['$']
const $computed: typeof import('vue/macros')['$computed']
const $customRef: typeof import('vue/macros')['$customRef']
const $ref: typeof import('vue/macros')['$ref']
const $shallowRef: typeof import('vue/macros')['$shallowRef']
const $toRef: typeof import('vue/macros')['$toRef']
const EffectScope: typeof import('vue')['EffectScope']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
const computedInject: typeof import('@vueuse/core')['computedInject']
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
const createEventHook: typeof import('@vueuse/core')['createEventHook']
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDark: typeof import('./composables/dark')['isDark']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const preferredDark: typeof import('./composables/dark')['preferredDark']
const provide: typeof import('vue')['provide']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
const refDebounced: typeof import('@vueuse/core')['refDebounced']
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveDirective: typeof import('vue')['resolveDirective']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const toggleDark: typeof import('./composables/dark')['toggleDark']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery']
const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter']
const useArrayFind: typeof import('@vueuse/core')['useArrayFind']
const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex']
const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin']
const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
const useArraySome: typeof import('@vueuse/core')['useArraySome']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useCloned: typeof import('@vueuse/core')['useCloned']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useHead: typeof import('@vueuse/head')['useHead']
const useI18n: typeof import('vue-i18n')['useI18n']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLink: typeof import('vue-router')['useLink']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSorted: typeof import('@vueuse/core')['useSorted']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStepper: typeof import('@vueuse/core')['useStepper']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSupported: typeof import('@vueuse/core')['useSupported']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToNumber: typeof import('@vueuse/core')['useToNumber']
const useToString: typeof import('@vueuse/core')['useToString']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useUserStore: typeof import('./store/user')['useUserStore']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watch: typeof import('vue')['watch']
const watchArray: typeof import('@vueuse/core')['watchArray']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
const watchEffect: typeof import('vue')['watchEffect']
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
// for vue template auto import
import { UnwrapRef } from 'vue'
declare module 'vue' {
interface ComponentCustomProperties {
readonly $$: UnwrapRef<typeof import('vue/macros')['$$']>
readonly $: UnwrapRef<typeof import('vue/macros')['$']>
readonly $computed: UnwrapRef<typeof import('vue/macros')['$computed']>
readonly $customRef: UnwrapRef<typeof import('vue/macros')['$customRef']>
readonly $ref: UnwrapRef<typeof import('vue/macros')['$ref']>
readonly $shallowRef: UnwrapRef<typeof import('vue/macros')['$shallowRef']>
readonly $toRef: UnwrapRef<typeof import('vue/macros')['$toRef']>
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
readonly computedInject: UnwrapRef<typeof import('@vueuse/core')['computedInject']>
readonly computedWithControl: UnwrapRef<typeof import('@vueuse/core')['computedWithControl']>
readonly controlledComputed: UnwrapRef<typeof import('@vueuse/core')['controlledComputed']>
readonly controlledRef: UnwrapRef<typeof import('@vueuse/core')['controlledRef']>
readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']>
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']>
readonly createSharedComposable: UnwrapRef<typeof import('@vueuse/core')['createSharedComposable']>
readonly createUnrefFn: UnwrapRef<typeof import('@vueuse/core')['createUnrefFn']>
readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
readonly debouncedRef: UnwrapRef<typeof import('@vueuse/core')['debouncedRef']>
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
readonly h: UnwrapRef<typeof import('vue')['h']>
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
readonly inject: UnwrapRef<typeof import('vue')['inject']>
readonly isDark: UnwrapRef<typeof import('./composables/dark')['isDark']>
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router')['onBeforeRouteLeave']>
readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router')['onBeforeRouteUpdate']>
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']>
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
readonly onKeyStroke: UnwrapRef<typeof import('@vueuse/core')['onKeyStroke']>
readonly onLongPress: UnwrapRef<typeof import('@vueuse/core')['onLongPress']>
readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
readonly onStartTyping: UnwrapRef<typeof import('@vueuse/core')['onStartTyping']>
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
readonly preferredDark: UnwrapRef<typeof import('./composables/dark')['preferredDark']>
readonly provide: UnwrapRef<typeof import('vue')['provide']>
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
readonly reactiveComputed: UnwrapRef<typeof import('@vueuse/core')['reactiveComputed']>
readonly reactiveOmit: UnwrapRef<typeof import('@vueuse/core')['reactiveOmit']>
readonly reactivePick: UnwrapRef<typeof import('@vueuse/core')['reactivePick']>
readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
readonly ref: UnwrapRef<typeof import('vue')['ref']>
readonly refAutoReset: UnwrapRef<typeof import('@vueuse/core')['refAutoReset']>
readonly refDebounced: UnwrapRef<typeof import('@vueuse/core')['refDebounced']>
readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']>
readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']>
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveDirective: UnwrapRef<typeof import('vue')['resolveDirective']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
readonly throttledRef: UnwrapRef<typeof import('@vueuse/core')['throttledRef']>
readonly throttledWatch: UnwrapRef<typeof import('@vueuse/core')['throttledWatch']>
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']>
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
readonly toggleDark: UnwrapRef<typeof import('./composables/dark')['toggleDark']>
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
readonly tryOnMounted: UnwrapRef<typeof import('@vueuse/core')['tryOnMounted']>
readonly tryOnScopeDispose: UnwrapRef<typeof import('@vueuse/core')['tryOnScopeDispose']>
readonly tryOnUnmounted: UnwrapRef<typeof import('@vueuse/core')['tryOnUnmounted']>
readonly unref: UnwrapRef<typeof import('vue')['unref']>
readonly unrefElement: UnwrapRef<typeof import('@vueuse/core')['unrefElement']>
readonly until: UnwrapRef<typeof import('@vueuse/core')['until']>
readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']>
readonly useArrayEvery: UnwrapRef<typeof import('@vueuse/core')['useArrayEvery']>
readonly useArrayFilter: UnwrapRef<typeof import('@vueuse/core')['useArrayFilter']>
readonly useArrayFind: UnwrapRef<typeof import('@vueuse/core')['useArrayFind']>
readonly useArrayFindIndex: UnwrapRef<typeof import('@vueuse/core')['useArrayFindIndex']>
readonly useArrayJoin: UnwrapRef<typeof import('@vueuse/core')['useArrayJoin']>
readonly useArrayMap: UnwrapRef<typeof import('@vueuse/core')['useArrayMap']>
readonly useArrayReduce: UnwrapRef<typeof import('@vueuse/core')['useArrayReduce']>
readonly useArraySome: UnwrapRef<typeof import('@vueuse/core')['useArraySome']>
readonly useAsyncQueue: UnwrapRef<typeof import('@vueuse/core')['useAsyncQueue']>
readonly useAsyncState: UnwrapRef<typeof import('@vueuse/core')['useAsyncState']>
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
readonly useBase64: UnwrapRef<typeof import('@vueuse/core')['useBase64']>
readonly useBattery: UnwrapRef<typeof import('@vueuse/core')['useBattery']>
readonly useBluetooth: UnwrapRef<typeof import('@vueuse/core')['useBluetooth']>
readonly useBreakpoints: UnwrapRef<typeof import('@vueuse/core')['useBreakpoints']>
readonly useBroadcastChannel: UnwrapRef<typeof import('@vueuse/core')['useBroadcastChannel']>
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']>
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']>
readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']>
readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']>
readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']>
readonly useDebounce: UnwrapRef<typeof import('@vueuse/core')['useDebounce']>
readonly useDebounceFn: UnwrapRef<typeof import('@vueuse/core')['useDebounceFn']>
readonly useDebouncedRefHistory: UnwrapRef<typeof import('@vueuse/core')['useDebouncedRefHistory']>
readonly useDeviceMotion: UnwrapRef<typeof import('@vueuse/core')['useDeviceMotion']>
readonly useDeviceOrientation: UnwrapRef<typeof import('@vueuse/core')['useDeviceOrientation']>
readonly useDevicePixelRatio: UnwrapRef<typeof import('@vueuse/core')['useDevicePixelRatio']>
readonly useDevicesList: UnwrapRef<typeof import('@vueuse/core')['useDevicesList']>
readonly useDisplayMedia: UnwrapRef<typeof import('@vueuse/core')['useDisplayMedia']>
readonly useDocumentVisibility: UnwrapRef<typeof import('@vueuse/core')['useDocumentVisibility']>
readonly useDraggable: UnwrapRef<typeof import('@vueuse/core')['useDraggable']>
readonly useDropZone: UnwrapRef<typeof import('@vueuse/core')['useDropZone']>
readonly useElementBounding: UnwrapRef<typeof import('@vueuse/core')['useElementBounding']>
readonly useElementByPoint: UnwrapRef<typeof import('@vueuse/core')['useElementByPoint']>
readonly useElementHover: UnwrapRef<typeof import('@vueuse/core')['useElementHover']>
readonly useElementSize: UnwrapRef<typeof import('@vueuse/core')['useElementSize']>
readonly useElementVisibility: UnwrapRef<typeof import('@vueuse/core')['useElementVisibility']>
readonly useEventBus: UnwrapRef<typeof import('@vueuse/core')['useEventBus']>
readonly useEventListener: UnwrapRef<typeof import('@vueuse/core')['useEventListener']>
readonly useEventSource: UnwrapRef<typeof import('@vueuse/core')['useEventSource']>
readonly useEyeDropper: UnwrapRef<typeof import('@vueuse/core')['useEyeDropper']>
readonly useFavicon: UnwrapRef<typeof import('@vueuse/core')['useFavicon']>
readonly useFetch: UnwrapRef<typeof import('@vueuse/core')['useFetch']>
readonly useFileDialog: UnwrapRef<typeof import('@vueuse/core')['useFileDialog']>
readonly useFileSystemAccess: UnwrapRef<typeof import('@vueuse/core')['useFileSystemAccess']>
readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']>
readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']>
readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']>
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']>
readonly useGeolocation: UnwrapRef<typeof import('@vueuse/core')['useGeolocation']>
readonly useHead: UnwrapRef<typeof import('@vueuse/head')['useHead']>
readonly useI18n: UnwrapRef<typeof import('vue-i18n')['useI18n']>
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']>
readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']>
readonly useLink: UnwrapRef<typeof import('vue-router')['useLink']>
readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']>
readonly useMagicKeys: UnwrapRef<typeof import('@vueuse/core')['useMagicKeys']>
readonly useManualRefHistory: UnwrapRef<typeof import('@vueuse/core')['useManualRefHistory']>
readonly useMediaControls: UnwrapRef<typeof import('@vueuse/core')['useMediaControls']>
readonly useMediaQuery: UnwrapRef<typeof import('@vueuse/core')['useMediaQuery']>
readonly useMemoize: UnwrapRef<typeof import('@vueuse/core')['useMemoize']>
readonly useMemory: UnwrapRef<typeof import('@vueuse/core')['useMemory']>
readonly useMounted: UnwrapRef<typeof import('@vueuse/core')['useMounted']>
readonly useMouse: UnwrapRef<typeof import('@vueuse/core')['useMouse']>
readonly useMouseInElement: UnwrapRef<typeof import('@vueuse/core')['useMouseInElement']>
readonly useMousePressed: UnwrapRef<typeof import('@vueuse/core')['useMousePressed']>
readonly useMutationObserver: UnwrapRef<typeof import('@vueuse/core')['useMutationObserver']>
readonly useNavigatorLanguage: UnwrapRef<typeof import('@vueuse/core')['useNavigatorLanguage']>
readonly useNetwork: UnwrapRef<typeof import('@vueuse/core')['useNetwork']>
readonly useNow: UnwrapRef<typeof import('@vueuse/core')['useNow']>
readonly useObjectUrl: UnwrapRef<typeof import('@vueuse/core')['useObjectUrl']>
readonly useOffsetPagination: UnwrapRef<typeof import('@vueuse/core')['useOffsetPagination']>
readonly useOnline: UnwrapRef<typeof import('@vueuse/core')['useOnline']>
readonly usePageLeave: UnwrapRef<typeof import('@vueuse/core')['usePageLeave']>
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
readonly usePointer: UnwrapRef<typeof import('@vueuse/core')['usePointer']>
readonly usePointerSwipe: UnwrapRef<typeof import('@vueuse/core')['usePointerSwipe']>
readonly usePreferredColorScheme: UnwrapRef<typeof import('@vueuse/core')['usePreferredColorScheme']>
readonly usePreferredContrast: UnwrapRef<typeof import('@vueuse/core')['usePreferredContrast']>
readonly usePreferredDark: UnwrapRef<typeof import('@vueuse/core')['usePreferredDark']>
readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']>
readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']>
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']>
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']>
readonly useScroll: UnwrapRef<typeof import('@vueuse/core')['useScroll']>
readonly useScrollLock: UnwrapRef<typeof import('@vueuse/core')['useScrollLock']>
readonly useSessionStorage: UnwrapRef<typeof import('@vueuse/core')['useSessionStorage']>
readonly useShare: UnwrapRef<typeof import('@vueuse/core')['useShare']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useSorted: UnwrapRef<typeof import('@vueuse/core')['useSorted']>
readonly useSpeechRecognition: UnwrapRef<typeof import('@vueuse/core')['useSpeechRecognition']>
readonly useSpeechSynthesis: UnwrapRef<typeof import('@vueuse/core')['useSpeechSynthesis']>
readonly useStepper: UnwrapRef<typeof import('@vueuse/core')['useStepper']>
readonly useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']>
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']>
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']>
readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']>
readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']>
readonly useTemplateRefsList: UnwrapRef<typeof import('@vueuse/core')['useTemplateRefsList']>
readonly useTextDirection: UnwrapRef<typeof import('@vueuse/core')['useTextDirection']>
readonly useTextSelection: UnwrapRef<typeof import('@vueuse/core')['useTextSelection']>
readonly useTextareaAutosize: UnwrapRef<typeof import('@vueuse/core')['useTextareaAutosize']>
readonly useThrottle: UnwrapRef<typeof import('@vueuse/core')['useThrottle']>
readonly useThrottleFn: UnwrapRef<typeof import('@vueuse/core')['useThrottleFn']>
readonly useThrottledRefHistory: UnwrapRef<typeof import('@vueuse/core')['useThrottledRefHistory']>
readonly useTimeAgo: UnwrapRef<typeof import('@vueuse/core')['useTimeAgo']>
readonly useTimeout: UnwrapRef<typeof import('@vueuse/core')['useTimeout']>
readonly useTimeoutFn: UnwrapRef<typeof import('@vueuse/core')['useTimeoutFn']>
readonly useTimeoutPoll: UnwrapRef<typeof import('@vueuse/core')['useTimeoutPoll']>
readonly useTimestamp: UnwrapRef<typeof import('@vueuse/core')['useTimestamp']>
readonly useTitle: UnwrapRef<typeof import('@vueuse/core')['useTitle']>
readonly useToNumber: UnwrapRef<typeof import('@vueuse/core')['useToNumber']>
readonly useToString: UnwrapRef<typeof import('@vueuse/core')['useToString']>
readonly useToggle: UnwrapRef<typeof import('@vueuse/core')['useToggle']>
readonly useTransition: UnwrapRef<typeof import('@vueuse/core')['useTransition']>
readonly useUrlSearchParams: UnwrapRef<typeof import('@vueuse/core')['useUrlSearchParams']>
readonly useUserMedia: UnwrapRef<typeof import('@vueuse/core')['useUserMedia']>
readonly useUserStore: UnwrapRef<typeof import('./store/user')['useUserStore']>
readonly useVModel: UnwrapRef<typeof import('@vueuse/core')['useVModel']>
readonly useVModels: UnwrapRef<typeof import('@vueuse/core')['useVModels']>
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']>
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']>
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']>
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']>
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']>
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']>
readonly useWebWorkerFn: UnwrapRef<typeof import('@vueuse/core')['useWebWorkerFn']>
readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']>
readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']>
readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']>
readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']>
readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']>
readonly watchDebounced: UnwrapRef<typeof import('@vueuse/core')['watchDebounced']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
readonly watchIgnorable: UnwrapRef<typeof import('@vueuse/core')['watchIgnorable']>
readonly watchOnce: UnwrapRef<typeof import('@vueuse/core')['watchOnce']>
readonly watchPausable: UnwrapRef<typeof import('@vueuse/core')['watchPausable']>
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
readonly watchThrottled: UnwrapRef<typeof import('@vueuse/core')['watchThrottled']>
readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']>
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
}
}

+ 17
- 0
src/components.d.ts View File

@@ -0,0 +1,17 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'

export {}

declare module '@vue/runtime-core' {
export interface GlobalComponents {
Counter: typeof import('./components/Counter.vue')['default']
Footer: typeof import('./components/Footer.vue')['default']
Input: typeof import('./components/Input.vue')['default']
README: typeof import('./components/README.md')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
}

+ 19
- 0
src/components/Counter.vue View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
const props = defineProps<{
initial: number
}>()

const { count, inc, dec } = useCounter(props.initial)
</script>

<template>
<div>
{{ count }}
<button class="inc" @click="inc()">
+
</button>
<button class="dec" @click="dec()">
-
</button>
</div>
</template>

+ 33
- 0
src/components/Footer.vue View File

@@ -0,0 +1,33 @@
<script setup lang="ts">
const { t, availableLocales, locale } = useI18n()

const toggleLocales = () => {
// change to some real logic
const locales = availableLocales
locale.value = locales[(locales.indexOf(locale.value) + 1) % locales.length]
}
</script>

<template>
<nav text-xl mt-6>
<RouterLink class="icon-btn mx-2" to="/" :title="t('button.home')">
<div i-carbon-campsite />
</RouterLink>

<button class="icon-btn mx-2 !outline-none" :title="t('button.toggle_dark')" @click="toggleDark()">
<div i="carbon-sun dark:carbon-moon" />
</button>

<a class="icon-btn mx-2" :title="t('button.toggle_langs')" @click="toggleLocales()">
<div i-carbon-language />
</a>

<RouterLink class="icon-btn mx-2" to="/about" :title="t('button.about')">
<div i-carbon-dicom-overlay />
</RouterLink>

<a class="icon-btn mx-2" rel="noreferrer" href="https://github.com/antfu/vitesse" target="_blank" title="GitHub">
<div i-carbon-logo-github />
</a>
</nav>
</template>

+ 20
- 0
src/components/Input.vue View File

@@ -0,0 +1,20 @@
<script setup lang="ts">
const { modelValue } = defineModel<{
modelValue: string
}>()
</script>

<template>
<input
id="input"
v-model="modelValue"
type="text"
v-bind="$attrs"
p="x-4 y-2"
w="250px"
text="center"
bg="transparent"
border="~ rounded gray-200 dark:gray-700"
outline="none active:none"
>
</template>

+ 10
- 0
src/components/README.md View File

@@ -0,0 +1,10 @@
## Components

Components in this dir will be auto-registered and on-demand, powered by [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components).


### Icons

You can use icons from almost any icon sets by the power of [Iconify](https://iconify.design/).

It will only bundle the icons you use. Check out [`unplugin-icons`](https://github.com/antfu/unplugin-icons) for more details.

+ 4
- 0
src/composables/dark.ts View File

@@ -0,0 +1,4 @@
// these APIs are auto-imported from @vueuse/core
export const isDark = useDark()
export const toggleDark = useToggle(isDark)
export const preferredDark = usePreferredDark()

+ 19
- 0
src/layouts/404.vue View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
const router = useRouter()
const { t } = useI18n()
router.currentRoute.value.path === '/index.html' && router.push('/') // redirect to home page & fix pywebview issue
</script>

<template>
<main p="x4 y10" text="center teal-700 dark:gray-200">
<div text-4xl>
<div i-carbon-warning inline-block />
</div>
<RouterView />
<div>
<button btn text-sm m="3 t8" @click="router.back">
{{ t('button.back') }}
</button>
</div>
</main>
</template>

+ 14
- 0
src/layouts/README.md View File

@@ -0,0 +1,14 @@
## Layouts

Vue components in this dir are used as layouts.

By default, `default.vue` will be used unless an alternative is specified in the route meta.

With [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) and [`vite-plugin-vue-layouts`](https://github.com/JohnCampionJr/vite-plugin-vue-layouts), you can specify the layout in the page's SFCs like this:

```html
<route lang="yaml">
meta:
layout: home
</route>
```

+ 9
- 0
src/layouts/default.vue View File

@@ -0,0 +1,9 @@
<template>
<main class="px-4 py-10 text-center text-gray-700 dark:text-gray-200">
<RouterView />
<Footer />
<div class="mt-5 mx-auto text-center opacity-75 dark:opacity-50 text-sm">
[Default Layout]
</div>
</main>
</template>

+ 9
- 0
src/layouts/home.vue View File

@@ -0,0 +1,9 @@
<template>
<main class="px-4 py-10 text-center text-gray-700 dark:text-gray-200">
<RouterView />
<Footer />
<div class="mt-5 mx-auto text-center opacity-75 dark:opacity-50 text-sm">
[Home Layout]
</div>
</main>
</template>

+ 24
- 0
src/main.ts View File

@@ -0,0 +1,24 @@
import { ViteSSG } from 'vite-ssg'
import { setupLayouts } from 'virtual:generated-layouts'
import Previewer from 'virtual:vue-component-preview'
import App from './App.vue'
import type { UserModule } from './types'
import generatedRoutes from '~pages'

import '@unocss/reset/tailwind.css'
import './styles/main.css'
import 'uno.css'

const routes = setupLayouts(generatedRoutes)

// https://github.com/antfu/vite-ssg
export const createApp = ViteSSG(
App,
{ routes, base: import.meta.env.BASE_URL },
(ctx) => {
// install all modules under `modules/`
Object.values(import.meta.glob<{ install: UserModule }>('./modules/*.ts', { eager: true }))
.forEach(i => i.install?.(ctx))
ctx.app.use(Previewer)
},
)

+ 11
- 0
src/modules/README.md View File

@@ -0,0 +1,11 @@
## Modules

A custom user module system. Place a `.ts` file with the following template, it will be installed automatically.

```ts
import { type UserModule } from '~/types'

export const install: UserModule = ({ app, router, isClient }) => {
// do something
}
```

+ 25
- 0
src/modules/i18n.ts View File

@@ -0,0 +1,25 @@
import { createI18n } from 'vue-i18n'
import { type UserModule } from '~/types'

// Import i18n resources
// https://vitejs.dev/guide/features.html#glob-import
//
// Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
const messages = Object.fromEntries(
Object.entries(
import.meta.glob<{ default: any }>('../../locales/*.y(a)?ml', { eager: true }))
.map(([key, value]) => {
const yaml = key.endsWith('.yaml')
return [key.slice(14, yaml ? -5 : -4), value.default]
}),
)

export const install: UserModule = ({ app }) => {
const i18n = createI18n({
legacy: false,
locale: 'en',
messages,
})

app.use(i18n)
}

+ 14
- 0
src/modules/nprogress.ts View File

@@ -0,0 +1,14 @@
import NProgress from 'nprogress'
import { type UserModule } from '~/types'

export const install: UserModule = ({ isClient, router }) => {
if (isClient) {
router.beforeEach((to, from) => {
if (to.path !== from.path)
NProgress.start()
})
router.afterEach(() => {
NProgress.done()
})
}
}

+ 17
- 0
src/modules/pinia.ts View File

@@ -0,0 +1,17 @@
import { createPinia } from 'pinia'
import { type UserModule } from '~/types'

// Setup Pinia
// https://pinia.vuejs.org/
export const install: UserModule = ({ isClient, initialState, app }) => {
const pinia = createPinia()
app.use(pinia)
// Refer to
// https://github.com/antfu/vite-ssg/blob/main/README.md#state-serialization
// for other serialization strategies.
if (isClient)
pinia.state.value = (initialState.pinia) || {}

else
initialState.pinia = pinia.state.value
}

+ 12
- 0
src/modules/pwa.ts View File

@@ -0,0 +1,12 @@
import { type UserModule } from '~/types'

// https://github.com/antfu/vite-plugin-pwa#automatic-reload-when-new-content-available
export const install: UserModule = ({ isClient, router }) => {
if (!isClient)
return

router.isReady().then(async () => {
const { registerSW } = await import('virtual:pwa-register')
registerSW({ immediate: true })
})
}

+ 20
- 0
src/pages/README.md View File

@@ -0,0 +1,20 @@
## File-based Routing

Routes will be auto-generated for Vue files in this dir with the same file structure.
Check out [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) for more details.

### Path Aliasing

`~/` is aliased to `./src/` folder.

For example, instead of having

```ts
import { isDark } from '../../../../composables'
```

now, you can use

```ts
import { isDark } from '~/composables'
```

+ 14
- 0
src/pages/[...all].vue View File

@@ -0,0 +1,14 @@
<script setup lang="ts">
const { t } = useI18n()
</script>

<template>
<div>
{{ t('not-found') }}
</div>
</template>

<route lang="yaml">
meta:
layout: 404
</route>

+ 21
- 0
src/pages/about.md View File

@@ -0,0 +1,21 @@
---
title: About
---

<div class="text-center">
<!-- You can use Vue components inside markdown -->
<div i-carbon-dicom-overlay class="text-4xl -mb-6 m-auto" />
<h3>About</h3>
</div>

[Vitesse](https://github.com/antfu/vitesse) is an opinionated [Vite](https://github.com/vitejs/vite) starter template made by [@antfu](https://github.com/antfu) for mocking apps swiftly. With **file-based routing**, **components auto importing**, **markdown support**, I18n, PWA and uses **UnoCSS** for styling and icons.

```js
// syntax highlighting example
function vitesse() {
const foo = 'bar'
console.log(foo)
}
```

Check out the [GitHub repo](https://github.com/antfu/vitesse) for more details.

+ 47
- 0
src/pages/hi/[name].vue View File

@@ -0,0 +1,47 @@
<script setup lang="ts">
const props = defineProps<{ name: string }>()
const router = useRouter()
const user = useUserStore()
const { t } = useI18n()

watchEffect(() => {
user.setNewName(props.name)
})
</script>

<template>
<div>
<div text-4xl>
<div i-carbon-pedestrian inline-block />
</div>
<p>
{{ t('intro.hi', { name: props.name }) }}
</p>

<p text-sm opacity-75>
<em>{{ t('intro.dynamic-route') }}</em>
</p>

<template v-if="user.otherNames.length">
<p text-sm mt-4>
<span opacity-75>{{ t('intro.aka') }}:</span>
<ul>
<li v-for="otherName in user.otherNames" :key="otherName">
<router-link :to="`/hi/${otherName}`" replace>
{{ otherName }}
</router-link>
</li>
</ul>
</p>
</template>

<div>
<button
btn m="3 t6" text-sm
@click="router.back()"
>
{{ t('button.back') }}
</button>
</div>
</div>
</template>

+ 73
- 0
src/pages/index.vue View File

@@ -0,0 +1,73 @@
<script setup lang="ts">
defineOptions({
name: 'IndexPage',
})
const user = useUserStore()
const name = $ref(user.savedName)

const router = useRouter()
const go = () => {
if (name)
router.push(`/hi/${encodeURIComponent(name)}`)
}

const pythonName = ref('')
const getOwner = async () => {
pythonName.value = await window.pywebview.api.getOwner() // 前端调用Python暴露的方法
}
getOwner()

const pythonData = ref('')

const getPythonData = () => {
pythonData.value = 'Python调用了此方法'
}

window.getPythonData = getPythonData // 暴露方法给Python调用

const { t } = useI18n()
</script>

<template>
<div>
<div text-4xl>
<div i-carbon-campsite inline-block />
</div>
<p>
<a rel="noreferrer" href="https://github.com/antfu/vitesse" target="_blank">
Vitesse
</a>
</p>
<p>
<em text-sm opacity-75>{{ t('intro.desc') }}</em>
</p>

<div py-4 />
<div>{{ pythonData }}</div>
<div py-4 />

<Input
v-model="name"
placeholder="What's your name?"
autocomplete="false"
:value="pythonName"
@keydown.enter="go"
/>
<label class="hidden" for="input">{{ t('intro.whats-your-name') }}</label>

<div>
<button
btn m-3 text-sm
:disabled="!name"
@click="go"
>
{{ t('button.go') }}
</button>
</div>
</div>
</template>

<route lang="yaml">
meta:
layout: home
</route>

+ 16
- 0
src/shims.d.ts View File

@@ -0,0 +1,16 @@
declare interface Window {
// extend the window
}

// with vite-plugin-vue-markdown, markdown files can be treated as Vue components
declare module '*.md' {
import { type DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

declare module '*.vue' {
import { type DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

+ 34
- 0
src/store/user.ts View File

@@ -0,0 +1,34 @@
import { acceptHMRUpdate, defineStore } from 'pinia'

export const useUserStore = defineStore('user', () => {
/**
* Current name of the user.
*/
const savedName = ref('')
const previousNames = ref(new Set<string>())

const usedNames = computed(() => Array.from(previousNames.value))
const otherNames = computed(() => usedNames.value.filter(name => name !== savedName.value))

/**
* Changes the current name of the user and saves the one that was used
* before.
*
* @param name - new name to set
*/
function setNewName(name: string) {
if (savedName.value)
previousNames.value.add(savedName.value)

savedName.value = name
}

return {
setNewName,
otherNames,
savedName,
}
})

if (import.meta.hot)
import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot))

+ 29
- 0
src/styles/main.css View File

@@ -0,0 +1,29 @@
@import './markdown.css';

html,
body,
#app {
height: 100%;
margin: 0;
padding: 0;
}

html.dark {
background: #121212;
color-scheme: dark;
}

#nprogress {
pointer-events: none;
}

#nprogress .bar {
background: rgb(13,148,136);
opacity: 0.75;
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px;
}

+ 28
- 0
src/styles/markdown.css View File

@@ -0,0 +1,28 @@
.prose pre:not(.shiki) {
padding: 0;
}

.prose .shiki {
font-family: 'DM Mono', monospace;
font-size: 1.2em;
line-height: 1.4;
}

.prose img {
width: 100%;
}

.shiki-light {
background: #f8f8f8 !important;
}
.shiki-dark {
background: #0e0e0e !important;
}

html.dark .shiki-light {
display: none;
}

html:not(.dark) .shiki-dark {
display: none;
}

+ 3
- 0
src/types.ts View File

@@ -0,0 +1,3 @@
import { type ViteSSGContext } from 'vite-ssg'

export type UserModule = (ctx: ViteSSGContext) => void

+ 37
- 0
tsconfig.json View File

@@ -0,0 +1,37 @@
{
"compilerOptions": {
"baseUrl": ".",
"module": "ESNext",
"target": "ESNext",
"lib": ["DOM", "ESNext"],
"strict": true,
"esModuleInterop": true,
"jsx": "preserve",
"skipLibCheck": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"noUnusedLocals": true,
"strictNullChecks": true,
"allowJs": true,
"forceConsistentCasingInFileNames": true,
"types": [
"vite/client",
"vue/ref-macros",
"vite-plugin-pages/client",
"vite-plugin-vue-component-preview/client",
"vite-plugin-vue-layouts/client",
"vite-plugin-pwa/client",
"unplugin-vue-macros/macros-global"
],
"paths": {
"~/*": ["src/*"]
}
},
"vueCompilerOptions": {
"plugins": [
"@vue-macros/volar/define-model",
"@vue-macros/volar/define-slots"
]
},
"exclude": ["dist", "node_modules"]
}

+ 38
- 0
unocss.config.ts View File

@@ -0,0 +1,38 @@
import {
defineConfig,
presetAttributify,
presetIcons,
presetTypography,
presetUno,
presetWebFonts,
transformerDirectives,
transformerVariantGroup,
} from 'unocss'

export default defineConfig({
shortcuts: [
['btn', 'px-4 py-1 rounded inline-block bg-teal-700 text-white cursor-pointer hover:bg-teal-800 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'],
['icon-btn', 'inline-block cursor-pointer select-none opacity-75 transition duration-200 ease-in-out hover:opacity-100 hover:text-teal-600'],
],
presets: [
presetUno(),
presetAttributify(),
presetIcons({
scale: 1.2,
warn: true,
}),
presetTypography(),
presetWebFonts({
fonts: {
sans: 'DM Sans',
serif: 'DM Serif Display',
mono: 'DM Mono',
},
}),
],
transformers: [
transformerDirectives(),
transformerVariantGroup(),
],
safelist: 'prose prose-sm m-auto text-left'.split(' '),
})

+ 152
- 0
vite.config.ts View File

@@ -0,0 +1,152 @@
import path from 'path'
import { defineConfig } from 'vite'
import Preview from 'vite-plugin-vue-component-preview'
import Vue from '@vitejs/plugin-vue'
import Pages from 'vite-plugin-pages'
import generateSitemap from 'vite-ssg-sitemap'
import Layouts from 'vite-plugin-vue-layouts'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import Markdown from 'vite-plugin-vue-markdown'
import { VitePWA } from 'vite-plugin-pwa'
import VueI18n from '@intlify/vite-plugin-vue-i18n'
import Inspect from 'vite-plugin-inspect'
import LinkAttributes from 'markdown-it-link-attributes'
import Unocss from 'unocss/vite'
import Shiki from 'markdown-it-shiki'
import VueMacros from 'unplugin-vue-macros/vite'

export default defineConfig({
resolve: {
alias: {
'~/': `${path.resolve(__dirname, 'src')}/`,
},
},

plugins: [
Preview(),

VueMacros({
plugins: {
vue: Vue({
include: [/\.vue$/, /\.md$/],
reactivityTransform: true,
}),
},
}),

// https://github.com/hannoeru/vite-plugin-pages
Pages({
extensions: ['vue', 'md'],
}),

// https://github.com/JohnCampionJr/vite-plugin-vue-layouts
Layouts(),

// https://github.com/antfu/unplugin-auto-import
AutoImport({
imports: [
'vue',
'vue-router',
'vue-i18n',
'vue/macros',
'@vueuse/head',
'@vueuse/core',
],
dts: 'src/auto-imports.d.ts',
dirs: [
'src/composables',
'src/store',
],
vueTemplate: true,
}),

// https://github.com/antfu/unplugin-vue-components
Components({
// allow auto load markdown components under `./src/components/`
extensions: ['vue', 'md'],
// allow auto import and register components used in markdown
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
dts: 'src/components.d.ts',
}),

// https://github.com/antfu/unocss
// see unocss.config.ts for config
Unocss(),

// https://github.com/antfu/vite-plugin-vue-markdown
// Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
Markdown({
wrapperClasses: 'prose prose-sm m-auto text-left',
headEnabled: true,
markdownItSetup(md) {
// https://prismjs.com/
md.use(Shiki, {
theme: {
light: 'vitesse-light',
dark: 'vitesse-dark',
},
})
md.use(LinkAttributes, {
matcher: (link: string) => /^https?:\/\//.test(link),
attrs: {
target: '_blank',
rel: 'noopener',
},
})
},
}),

// https://github.com/antfu/vite-plugin-pwa
VitePWA({
registerType: 'autoUpdate',
includeAssets: ['favicon.svg', 'safari-pinned-tab.svg'],
manifest: {
name: 'Vitesse',
short_name: 'Vitesse',
theme_color: '#ffffff',
icons: [
{
src: '/pwa-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: '/pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
},
{
src: '/pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable',
},
],
},
}),

// https://github.com/intlify/bundle-tools/tree/main/packages/vite-plugin-vue-i18n
VueI18n({
runtimeOnly: true,
compositionOnly: true,
include: [path.resolve(__dirname, 'locales/**')],
}),

// https://github.com/antfu/vite-plugin-inspect
// Visit http://localhost:3333/__inspect/ to see the inspector
Inspect(),
],

// https://github.com/antfu/vite-ssg
ssgOptions: {
script: 'async',
formatting: 'minify',
onFinished() { generateSitemap() },
},

ssr: {
// TODO: workaround until they support native ESM
noExternal: ['workbox-window', /vue-i18n/],
},
})

Loading…
Cancel
Save