129 Commits
v1.0.0 ... docs

Author SHA1 Message Date
28072c7f90 📝 Update document 2025-11-18 18:46:27 +08:00
991a89147e 🎨 Optimize code 2025-11-17 23:14:58 +08:00
a08c0d8448 🎨 Modify code block logic 2025-11-17 22:11:16 +08:00
59db8dd177 Added Monocraft font 2025-11-16 22:04:02 +08:00
29693f1baf 💄 Modify some styles 2025-11-16 21:23:59 +08:00
5d6f157ae1 🎨 Update initial code block definition
Some checks failed
Build and Release Voidraft / prepare (push) Failing after 2s
Build and Release Voidraft / build (push) Has been cancelled
Build and Release Voidraft / release (push) Has been cancelled
2025-11-16 17:49:19 +08:00
afda3d5301 Merge remote-tracking branch 'github/dependabot/npm_and_yarn/frontend/js-yaml-4.1.1' 2025-11-16 15:44:58 +08:00
5d4ba757aa Optimize HTTP client 2025-11-16 15:41:16 +08:00
d12d58b15a 🐛 Fixed markdown preview issue 2025-11-16 15:22:49 +08:00
627c3dc71f 🐛 Fixed markdown preview issue 2025-11-16 15:16:49 +08:00
26c7a3241c 🐛 Fixed module path issues 2025-11-16 02:42:59 +08:00
46c5e3dd1a Added markdown and mermaid preview 2025-11-16 02:42:01 +08:00
dependabot[bot]
92a6c6bfdb ⬆️ Bump js-yaml from 4.1.0 to 4.1.1 in /frontend
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.1.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-15 18:38:56 +00:00
031aa49f9f Added markdown and mermaid preview 2025-11-16 02:37:30 +08:00
1d7aee4cea 🐛 Fixed data migration issues 2025-11-14 20:16:16 +08:00
dec3ef5ef4 Added cursor protection extension 2025-11-13 21:00:35 +08:00
d42f913250 Added editor cursor state persistence 2025-11-13 20:44:47 +08:00
bae4e663fb ⬆️ Upgrade dependencies 2025-11-13 20:02:22 +08:00
a17e060d16 ⬆️ Upgrade dependencies 2025-11-13 19:36:11 +08:00
71946965eb 🐛 Fixed database constraint issues 2025-11-08 17:35:29 +08:00
d4cd22d234 🚀 Update build and release workflows 2025-11-08 17:17:07 +08:00
05f2f7d46d 🚀 Update build and release workflows 2025-11-08 17:05:31 +08:00
9deb2744a9 🚀 Update build and release workflows 2025-11-08 16:24:22 +08:00
6fac7c42d6 🚀 Update build and release workflows 2025-11-08 16:03:26 +08:00
3393bc84e3 🚀 Add build and release workflows 2025-11-08 15:50:30 +08:00
286b0159d7 🎨 Optimize update services
Some checks failed
Deploy VitePress site to Pages / build (push) Has been cancelled
Deploy VitePress site to Pages / Deploy (push) Has been cancelled
2025-11-08 00:00:08 +08:00
cc98e556c6 ♻️ Optimize code
Some checks failed
Deploy VitePress site to Pages / build (push) Has been cancelled
Deploy VitePress site to Pages / Deploy (push) Has been cancelled
2025-11-07 22:34:12 +08:00
5902f482d9 ♻️ Refactor configuration change notification service 2025-11-07 00:35:11 +08:00
551e7e2cfd Optimize hotkey service 2025-11-06 22:42:44 +08:00
e0179b5838 🎨 Optimize hotkey service 2025-11-06 00:08:26 +08:00
df79267e16 Optimize multi-window services 2025-11-05 22:07:43 +08:00
1f0254822f 🎨 Optimize multi-window services 2025-11-05 00:10:26 +08:00
e9b6fef3cd Added mermaid language support 2025-11-04 22:58:36 +08:00
689b0d5d14 🚀 Fixed resource path issues 2025-11-04 01:21:10 +08:00
a058e62595 🚀 Fixed resource path issues 2025-11-04 01:07:28 +08:00
8571fc0f5c 🚀 Fixed resource path issues 2025-11-04 00:57:49 +08:00
4dad0a86b3 🚀 Improve deployment scripts 2025-11-04 00:36:32 +08:00
3168b7ff43 🚀 Modify deployment command 2025-11-04 00:27:34 +08:00
d002a5be5a 🚀 Adjust base path 2025-11-04 00:16:39 +08:00
24a550463c 🚀 Remove dead links 2025-11-03 23:58:27 +08:00
14ae3e80c4 Beautify style and add automatic deployment scripts 2025-11-03 23:38:15 +08:00
e4d3969e95 📝 Build document directory structure 2025-11-03 22:49:38 +08:00
0b16d1d4ac Merge branch 'master' into docs 2025-11-03 22:18:06 +08:00
300514531d Improve HTTP client function 2025-11-03 22:15:45 +08:00
6a4780b002 📝 Replace official website framework 2025-11-02 22:48:33 +08:00
5688304817 🎨 Add variable support for http client 2025-11-02 17:20:22 +08:00
4380ad010c 🎨 Supports file upload 2025-11-02 01:53:11 +08:00
4fa6bb42e3 ⬆️ Upgrade dependencies 2025-11-02 00:16:57 +08:00
7aa3a7e37f 🚧 Improve HTTP language parser 2025-11-02 00:01:16 +08:00
94306497a9 🚧 Improve HTTP language parser 2025-11-01 21:40:51 +08:00
93c85b800b 🚧 Optimized HTTP language parser 2025-11-01 17:42:22 +08:00
8ac78e39f1 🚧 Added HTTP language parser 2025-10-31 19:39:44 +08:00
61a23fe7f2 🐛 Fixed tab and multi-window issues 2025-10-23 19:07:11 +08:00
87fea58102 Merge pull request #6 from landaiqing/dependabot/npm_and_yarn/frontend/vite-7.1.11
⬆️ Bump vite from 7.1.10 to 7.1.11 in /frontend
2025-10-21 10:25:54 +08:00
dependabot[bot]
edeac01bee ⬆️ Bump vite from 7.1.10 to 7.1.11 in /frontend
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.10 to 7.1.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.11
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-21 01:50:20 +00:00
852424356a 🐛 Fixed startup failure issue 2025-10-20 23:07:29 +08:00
b704dd2438 🎨 Optimize code 2025-10-20 23:00:04 +08:00
aa8139884b 🎨 Optimize preset theme code 2025-10-20 21:58:37 +08:00
9a15df01ee Added preset theme 2025-10-19 23:57:03 +08:00
03780b5bc7 ⬆️ Upgrade dependencies 2025-10-10 23:40:23 +08:00
b5d90cc59a Added the ability to automatically scroll to active tabs 2025-10-05 18:53:49 +08:00
d49ffc20df 🎨 Refactor and optimize code 2025-10-05 00:58:27 +08:00
c22e349181 🐛 Fixed tab switch issue 2025-10-04 14:31:06 +08:00
45968cd353 Added tab functionality and optimized related configurations 2025-10-04 02:27:32 +08:00
2d02bf7f1f 🚧 Optimize 2025-10-01 22:32:57 +08:00
1216b0b67c 🚧 Optimize 2025-10-01 18:15:22 +08:00
cf8bf688bf 🚧 Optimize 2025-09-30 00:28:15 +08:00
4d6a4ff79f 🐛 Fixed SQLite time field issue 2025-09-29 00:59:59 +08:00
3077d5a7c5 ♻️ Refactor document selector and cache management logic 2025-09-29 00:26:05 +08:00
bc0569af93 🎨 Optimize code structure 2025-09-28 01:09:20 +08:00
0188b618f2 🐛 Fixed docker prettier plugin issue 2025-09-27 20:11:31 +08:00
08860e9a5c ⬆️ Update dependencies 2025-09-24 23:57:22 +08:00
a56d4ef379 Adds multiple code block language support 2025-09-24 23:05:21 +08:00
f5bfff80b7 🚨 Format code 2025-09-24 21:44:42 +08:00
1462d8a753 🐛 Fixed docker prettier plugin issue 2025-09-24 19:14:10 +08:00
39ee2d14f3 Optimize font size and add more fonts 2025-09-24 00:44:41 +08:00
e536cdd9ba 🐛 Fixed docker、shell prettier plugin issue 2025-09-23 19:43:26 +08:00
dc4b73406d 🐛 Fixed prettier plugin parser configuration issue 2025-09-21 23:23:43 +08:00
0012a5dc19 Added loading animation switch 2025-09-21 22:17:41 +08:00
3cda88371e 🐛 Fixed manual Chunks issue 2025-09-21 21:54:39 +08:00
0338351680 Improve app launch speed 2025-09-21 03:04:23 +08:00
e372a0dd7c 🎨 Modify the rendering logic of the checkbox 2025-09-21 01:14:33 +08:00
d597f379ff 🚚 Refactor directory structure 2025-09-21 00:11:40 +08:00
9222a52d91 Modified sql prettier plugin 2025-09-20 19:18:33 +08:00
c3670bb8cd Added dockerfile、lua prettier plugin 2025-09-20 01:30:16 +08:00
2ea3456ff7 Added dart prettier plugin 2025-09-19 19:41:48 +08:00
c9379f0edb Added python prettier plugin 2025-09-19 19:35:48 +08:00
f72010bd69 Added clang prettier plugin 2025-09-19 19:17:13 +08:00
cd027097f8 🐛 Fixed golang prettier plugin issue 2025-09-19 18:39:41 +08:00
9cbbf729c0 🔥 Remove powershell prettier plugin 2025-09-18 00:13:07 +08:00
landaiqing
c26c11e253 🐛 Fixed build issue 2025-09-17 09:54:43 +08:00
338ac358db 🚧 Modify toml,powershell prettier plugin(beta) 2025-09-17 00:12:39 +08:00
a83c7139c9 Added scala、powershell、groovy prettier plugin 2025-09-14 23:45:01 +08:00
42c7d11c09 📦 Optimized packaging 2025-09-13 20:25:19 +08:00
5ca5aa64c7 Added shell prettier plugin 2025-09-13 19:21:06 +08:00
eda7ef771e Added rust prettier plugin 2025-09-13 00:02:17 +08:00
593c4d7783 Added java prettier plugin 2025-09-12 23:01:19 +08:00
d24a522b32 Added php prettier plugin 2025-09-12 20:15:56 +08:00
41afb834ae Added sql prettier plugin 2025-09-12 00:52:19 +08:00
b745329e26 Added golang prettier plugin 2025-09-11 20:42:39 +08:00
1fb4f64cb3 Add update notifications 2025-09-06 01:21:02 +08:00
1f8e8981ce 🐛 Fixed version generation issues 2025-09-05 22:40:09 +08:00
a257d30dba 🎨 Modify configuration migration policy 2025-09-05 22:07:00 +08:00
97ee3b0667 🐛 Fixed configuration merge override issue 2025-09-05 00:36:33 +08:00
8e2bafba5f Optimize window snapping performance 2025-09-04 00:20:30 +08:00
6149bc133d 🐛 Fixed window pinning issue 2025-09-02 23:59:04 +08:00
5f22ee3b1f ♻️ Refactoring configuration migration service 2025-08-31 17:48:41 +08:00
fa72ff8061 Merge remote-tracking branch 'github/dependabot/go_modules/github.com/ulikunitz/xz-0.5.14' 2025-08-30 19:00:36 +08:00
65f24860e6 Added window snapping function toggle 2025-08-30 00:18:29 +08:00
dependabot[bot]
4881233211 ⬆️ Bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14
Bumps [github.com/ulikunitz/xz](https://github.com/ulikunitz/xz) from 0.5.12 to 0.5.14.
- [Commits](https://github.com/ulikunitz/xz/compare/v0.5.12...v0.5.14)

---
updated-dependencies:
- dependency-name: github.com/ulikunitz/xz
  dependency-version: 0.5.14
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-28 19:44:41 +00:00
bc01fdf362 Added window snapping feature 2025-08-24 16:07:48 +08:00
709998ff9c 🐛 Fixed hotkey crashes 2025-08-19 22:26:55 +08:00
6adeadeed4 🐛 Fixed document deadlock issue 2025-08-19 00:24:51 +08:00
7b70a39b23 🐛 Fixed hotkey service issues 2025-08-19 00:08:50 +08:00
873a3c0e60 Modify the theme storage schema 2025-08-17 19:34:35 +08:00
5b88efcfbe 🐛 Fixed the window toggle maximise issue 2025-08-17 14:51:39 +08:00
f37c659c89 🐛 Adjusted error message and icon clearing logic 2025-07-17 11:03:42 +08:00
9fff7bcfca Added the backup feature 2025-07-17 00:12:00 +08:00
b4b0ad9bba 🎨 Optimize storage logic 2025-07-13 22:32:58 +08:00
6d8fdf62f1 💡 Update docs 2025-07-13 11:58:53 +08:00
9f53d7421d Merge remote-tracking branch 'github/master' 2025-07-12 23:56:43 +08:00
80c8ecb4cf 💡 Update docs 2025-07-12 23:56:04 +08:00
d10059a82d Create CNAME 2025-07-12 22:25:19 +08:00
737f83cd5f 💡 Add docs 2025-07-12 22:14:35 +08:00
a720a4cfb8 Complete the custom editor theme 2025-07-11 23:03:28 +08:00
b5510d605c Add multi-window document functionality 2025-07-10 18:45:51 +08:00
4d62da912a ⬆️ Upgrade wails v3 from Alpha 9 to Alpha 10 2025-07-10 10:01:52 +08:00
b52e067d50 🍎 Fix build issues 2025-07-08 17:36:45 +08:00
8dce06c30e 🐛 Fixed the reboot issue on different platforms 2025-07-08 12:41:30 +08:00
721 changed files with 75110 additions and 10468 deletions

325
.github/workflows/build-release.yml vendored Normal file
View File

@@ -0,0 +1,325 @@
name: Build and Release Voidraft
on:
# 推送标签时触发(用于正式发布)
push:
tags:
- 'v*' # 触发条件:推送 v 开头的标签,如 v1.0.0
branches:
- main # 仅当标签在 main 分支时触发
# 手动触发(用于测试)
workflow_dispatch:
inputs:
release:
description: '是否创建 Release测试时选 false'
required: true
type: boolean
default: false
platforms:
description: '要构建的平台用逗号分隔windows,linux,macos-intel,macos-arm'
required: true
type: string
default: 'windows,linux'
env:
NODE_OPTIONS: "--max-old-space-size=4096" # 防止 Node.js 内存溢出
jobs:
# 准备构建配置
prepare:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
should_release: ${{ steps.check-release.outputs.should_release }}
steps:
- name: 确定构建平台
id: set-matrix
run: |
# 如果是手动触发,根据输入决定平台
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
PLATFORMS="${{ github.event.inputs.platforms }}"
else
# 标签触发,构建所有平台
PLATFORMS="windows,linux,macos-intel,macos-arm"
fi
echo "构建平台: $PLATFORMS"
# 构建矩阵 JSON
MATRIX='{"include":[]}'
if [[ "$PLATFORMS" == *"windows"* ]]; then
MATRIX=$(echo "$MATRIX" | jq -c '.include += [{"platform":"windows-latest","os":"windows","arch":"amd64","platform_dir":"windows","id":"windows"}]')
fi
if [[ "$PLATFORMS" == *"linux"* ]]; then
MATRIX=$(echo "$MATRIX" | jq -c '.include += [{"platform":"ubuntu-22.04","os":"linux","arch":"amd64","platform_dir":"linux","id":"linux"}]')
fi
if [[ "$PLATFORMS" == *"macos-intel"* ]]; then
MATRIX=$(echo "$MATRIX" | jq -c '.include += [{"platform":"macos-latest","os":"darwin","arch":"amd64","platform_dir":"darwin","id":"macos-intel"}]')
fi
if [[ "$PLATFORMS" == *"macos-arm"* ]]; then
MATRIX=$(echo "$MATRIX" | jq -c '.include += [{"platform":"macos-latest","os":"darwin","arch":"arm64","platform_dir":"darwin","id":"macos-arm"}]')
fi
# 使用 -c 确保输出紧凑的单行 JSON符合 GitHub Actions 输出格式
echo "matrix=$(echo "$MATRIX" | jq -c .)" >> $GITHUB_OUTPUT
# 输出美化的 JSON 用于日志查看
echo "生成的矩阵:"
echo "$MATRIX" | jq .
- name: 检查是否创建 Release
id: check-release
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
# 手动触发,根据输入决定
echo "should_release=${{ github.event.inputs.release }}" >> $GITHUB_OUTPUT
else
# 标签触发,自动创建 Release
echo "should_release=true" >> $GITHUB_OUTPUT
fi
build:
needs: prepare
if: ${{ fromJson(needs.prepare.outputs.matrix).include[0] != null }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare.outputs.matrix) }}
runs-on: ${{ matrix.platform }}
steps:
- name: 检出代码
uses: actions/checkout@v4
with:
submodules: recursive
- name: 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.21'
cache: true
- name: 设置 Node.js 环境
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
# Linux 平台依赖
- name: 安装 Linux 依赖
if: matrix.os == 'linux'
run: |
sudo apt-get update
# Wails 3 + 项目特定依赖
sudo apt-get install -y \
build-essential \
pkg-config \
libgtk-3-dev \
libwebkit2gtk-4.1-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
patchelf \
libx11-dev \
rpm \
fuse \
file
# 依赖说明:
# - build-essential: C/C++ 编译工具链
# - pkg-config: 包配置工具
# - libgtk-3-dev: GTK3 GUI 框架
# - libwebkit2gtk-4.1-dev: WebKit2GTK 4.1 (Wails 3 要求)
# - libayatana-appindicator3-dev: 系统托盘支持
# - librsvg2-dev: SVG 图标支持
# - patchelf: 修改 ELF 二进制文件
# - libx11-dev: X11 库 (热键服务依赖)
# - rpm: RPM 打包工具
# - fuse: AppImage 运行依赖
# - file: 文件类型检测工具
# Windows 平台依赖
- name: 设置 Windows 构建环境
if: matrix.os == 'windows'
run: |
# 安装 NSIS (用于创建安装程序)
choco install nsis -y
# 将 NSIS 添加到 PATH
echo "C:\Program Files (x86)\NSIS" >> $GITHUB_PATH
shell: bash
# macOS 平台依赖
- name: 设置 macOS 构建环境
if: matrix.os == 'darwin'
run: |
# Xcode 命令行工具通常已安装
xcode-select --install 2>/dev/null || true
# 安装 Wails CLI
- name: 安装 Wails CLI
run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest
# 安装前端依赖
- name: 安装前端依赖
working-directory: frontend
run: npm ci
# 构建前端
- name: 构建前端
working-directory: frontend
run: npm run build
# 使用 Wails Task 构建和打包应用
- name: 构建和打包 Wails 应用
run: wails3 task ${{ matrix.id }}:package PRODUCTION=true ARCH=${{ matrix.arch }}
env:
CGO_ENABLED: 1
APP_NAME: voidraft
BIN_DIR: bin
ROOT_DIR: .
shell: bash
# 整理构建产物
- name: 整理构建产物
id: organize_artifacts
run: |
echo "=== 构建产物列表 ==="
ls -lhR bin/ || echo "bin 目录不存在"
# 创建输出目录
mkdir -p artifacts
# 根据平台复制产物
if [ "${{ matrix.os }}" = "windows" ]; then
echo "Windows 平台:查找 NSIS 安装程序"
find . -name "*.exe" -type f
cp bin/*.exe artifacts/ 2>/dev/null || echo "未找到 .exe 文件"
elif [ "${{ matrix.os }}" = "linux" ]; then
echo "Linux 平台:查找 AppImage, deb, rpm, archlinux 包"
find bin -type f
cp bin/*.AppImage artifacts/ 2>/dev/null || echo "未找到 AppImage"
cp bin/*.deb artifacts/ 2>/dev/null || echo "未找到 deb"
cp bin/*.rpm artifacts/ 2>/dev/null || echo "未找到 rpm"
cp bin/*.pkg.tar.zst artifacts/ 2>/dev/null || echo "未找到 archlinux 包"
elif [ "${{ matrix.os }}" = "darwin" ]; then
echo "macOS 平台:查找 .app bundle"
find bin -name "*.app" -type d
# macOS: .app bundle打包成 zip
if [ -d "bin/voidraft.app" ]; then
cd bin
zip -r ../artifacts/voidraft-darwin-${{ matrix.arch }}.app.zip voidraft.app
cd ..
else
echo "未找到 .app bundle"
fi
fi
echo "=== 最终产物 ==="
ls -lh artifacts/ || echo "artifacts 目录为空"
shell: bash
# 上传构建产物到 Artifacts
- name: 上传构建产物
uses: actions/upload-artifact@v4
with:
name: voidraft-${{ matrix.id }}
path: artifacts/*
if-no-files-found: warn
# 创建 GitHub Release 并上传所有构建产物
release:
needs: [prepare, build]
if: ${{ needs.prepare.outputs.should_release == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 下载所有构建产物
uses: actions/download-artifact@v4
with:
path: artifacts
- name: 显示下载的文件
run: |
echo "下载的构建产物:"
ls -R artifacts/
- name: 准备 Release 文件
run: |
mkdir -p release
find artifacts -type f -exec cp {} release/ \;
ls -lh release/
- name: 生成 Release 说明
id: release_notes
run: |
# 获取版本号
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.sha }}"
VERSION_NAME="测试构建 ${VERSION:0:7}"
else
VERSION="${{ github.ref_name }}"
VERSION_NAME="${VERSION}"
fi
cat > release_notes.md << EOF
## Voidraft ${VERSION_NAME}
### 📦 下载
根据你的操作系统选择对应的版本:
- **Windows (64位)**: \`voidraft-windows-amd64.exe\`
- **Linux (64位)**: \`voidraft-linux-amd64\`
- **macOS (Intel)**: \`voidraft-darwin-amd64.zip\`
- **macOS (Apple Silicon)**: \`voidraft-darwin-arm64.zip\`
### 📝 更新内容
请查看 [提交历史](../../commits/${{ github.ref_name }}) 了解本次更新的详细内容。
### 💡 使用说明
#### Windows
1. 下载 `voidraft-windows-amd64.exe`
2. 直接运行即可
#### Linux
1. 下载 `voidraft-linux-amd64`
2. 添加执行权限:`chmod +x voidraft-linux-amd64`
3. 运行:`./voidraft-linux-amd64`
#### macOS
1. 下载对应架构的 zip 文件
2. 解压后运行
3. 如果提示无法打开,请在 系统偏好设置 > 安全性与隐私 中允许运行
---
构建时间: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
EOF
- name: 创建 GitHub Release
uses: softprops/action-gh-release@v2
with:
files: release/*
body_path: release_notes.md
draft: false
prerelease: ${{ github.event_name == 'workflow_dispatch' }}
tag_name: ${{ github.event_name == 'workflow_dispatch' && format('test-{0}', github.sha) || github.ref_name }}
name: ${{ github.event_name == 'workflow_dispatch' && format('测试构建 {0}', github.sha) || github.ref_name }}
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

67
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,67 @@
# 构建 VitePress 站点并将其部署到 GitHub Pages 的示例工作流程
#
name: Deploy VitePress site to Pages
on:
# 在针对 `main` 分支的推送上运行。如果你
# 使用 `master` 分支作为默认分支,请将其更改为 `master`
push:
branches: [master]
# 允许你从 Actions 选项卡手动运行此工作流程
workflow_dispatch:
# 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# 只允许同时进行一次部署,跳过正在运行和最新队列之间的运行队列
# 但是,不要取消正在进行的运行,因为我们希望允许这些生产部署完成
concurrency:
group: pages
cancel-in-progress: false
jobs:
# 构建工作
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # 如果未启用 lastUpdated则不需要
# - uses: pnpm/action-setup@v3 # 如果使用 pnpm请取消此区域注释
# with:
# version: 9
# - uses: oven-sh/setup-bun@v1 # 如果使用 Bun请取消注释
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: frontend/package-lock.json
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies
run: cd frontend && npm ci
- name: Build with VitePress
run: cd frontend && npm run docs:build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: frontend/docs/.vitepress/dist
# 部署工作
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
name: Deploy
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

4
.gitignore vendored
View File

@@ -4,4 +4,6 @@ frontend/dist
frontend/node_modules
build/linux/appimage/build
build/windows/nsis/MicrosoftEdgeWebview2Setup.exe
.idea
.idea
frontend/docs/.vitepress/cache/
frontend/docs/.vitepress/dist/

View File

@@ -1,10 +1,10 @@
# <img src="./frontend/public/appicon.png" alt="VoidRaft Logo" width="32" height="32" style="vertical-align: middle;"> VoidRaft
# <img src="./frontend/public/appicon.png" alt="voidraft Logo" width="32" height="32" style="vertical-align: middle;"> voidraft
[中文](README_ZH.md) | **English**
> *An elegant text snippet recording tool designed for developers.*
VoidRaft is a modern developer-focused text editor that allows you to record, organize, and manage various text snippets anytime, anywhere. Whether it's temporary code snippets, API responses, meeting notes, or daily to-do lists, VoidRaft provides a smooth and elegant editing experience.
voidraft is a modern developer-focused text editor that allows you to record, organize, and manage various text snippets anytime, anywhere. Whether it's temporary code snippets, API responses, meeting notes, or daily to-do lists, voidraft provides a smooth and elegant editing experience.
## Core Features
@@ -14,6 +14,8 @@ VoidRaft is a modern developer-focused text editor that allows you to record, or
- Smart language detection - Automatically recognizes code block language types
- Code formatting - Built-in Prettier support for one-click code beautification
- Block editing mode - Split content into independent code blocks, each with different language settings
- Multi-window support - edit multiple documents at the same time
- Support for custom themes - Custom editor themes
### Modern Interface
@@ -53,6 +55,7 @@ cd voidraft
# Install frontend dependencies
cd frontend
npm install
npm run build
cd ..
# Start development server
@@ -84,7 +87,7 @@ After building, the executable will be generated in the `bin` directory.
## Project Structure
```
Voidraft/
voidraft/
├── frontend/ # Vue 3 frontend application
│ ├── src/
│ │ ├── views/editor/ # Editor core views
@@ -116,24 +119,21 @@ Voidraft/
| Linux | Planned | Future versions |
### Planned Features
- [ ] Custom themes - Customize editor themes
- [ ] Multi-window support - Support editing multiple documents simultaneously
- Custom themes - Customize editor themes
- Multi-window support - Support editing multiple documents simultaneously
- ✅ Data synchronization - Cloud backup for documents
- [ ] Enhanced clipboard - Monitor and manage clipboard history
- Automatic text content saving
- Image content support
- History management
- [ ] Data synchronization - Cloud backup for configurations and documents
- [ ] Extension system - Support for custom plugins
## Acknowledgments
> Standing on the shoulders of giants, paying tribute to the open source spirit
The birth of VoidRaft is inseparable from the following excellent open source projects:
The birth of voidraft is inseparable from the following excellent open source projects:
### Special Thanks
- **[Heynote](https://github.com/heyman/heynote/)** - VoidRaft is a feature-enhanced version based on Heynote's concept
- **[Heynote](https://github.com/heyman/heynote/)** - voidraft is a feature-enhanced version based on Heynote's concept
- Inherits Heynote's elegant block editing philosophy
- Adds more practical features on the original foundation
- Rebuilt with modern technology stack
@@ -157,7 +157,7 @@ This project is open source under the [MIT License](LICENSE).
Welcome to Fork, Star, and contribute code.
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub stars](https://img.shields.io/github/stars/landaiqing/Voidraft.svg?style=social&label=Star)](https://github.com/yourusername/Voidraft)
[![GitHub forks](https://img.shields.io/github/forks/landaiqing/Voidraft.svg?style=social&label=Fork)](https://github.com/yourusername/Voidraft)
[![GitHub stars](https://img.shields.io/github/stars/landaiqing/voidraft.svg?style=social&label=Star)](https://github.com/yourusername/voidraft)
[![GitHub forks](https://img.shields.io/github/forks/landaiqing/voidraft.svg?style=social&label=Fork)](https://github.com/yourusername/voidraft)
*Made with ❤️ by landaiqing*

View File

@@ -1,10 +1,10 @@
# <img src="./frontend/public/appicon.png" alt="Voidraft Logo" width="32" height="32" style="vertical-align: middle;"> Voidraft
# <img src="./frontend/public/appicon.png" alt="voidraft Logo" width="32" height="32" style="vertical-align: middle;"> voidraft
**中文** | [English](README.md)
> *一个专为开发者打造的优雅文本片段记录工具。*
Voidraft 是一个现代化的开发者专用文本编辑器让你能够随时随地记录、整理和管理各种文本片段。无论是临时的代码片段、API 响应、会议笔记,还是日常的待办事项,Voidraft 都能为你提供流畅而优雅的编辑体验。
voidraft 是一个现代化的开发者专用文本编辑器让你能够随时随地记录、整理和管理各种文本片段。无论是临时的代码片段、API 响应、会议笔记,还是日常的待办事项,voidraft 都能为你提供流畅而优雅的编辑体验。
## 核心特性
@@ -14,6 +14,8 @@ Voidraft 是一个现代化的开发者专用文本编辑器,让你能够随
- 智能语言检测 - 自动识别代码块语言类型
- 代码格式化 - 内置 Prettier 支持,一键美化代码
- 块状编辑模式 - 将内容分割为独立的代码块,每个块可设置不同语言
- 支持多窗口 - 同时编辑多个文档
- 支持自定义主题 - 自定义编辑器主题
### 现代化界面
@@ -54,6 +56,7 @@ cd voidraft
# 安装前端依赖
cd frontend
npm install
npm run build
cd ..
# 启动开发服务器
@@ -85,7 +88,7 @@ wails3 package
## 项目结构
```
Voidraft/
voidraft/
├── frontend/ # Vue 3 前端应用
│ ├── src/
│ │ ├── views/editor/ # 编辑器核心视图
@@ -117,13 +120,10 @@ Voidraft/
| Linux | 计划中 | 后续版本 |
### 计划添加的功能
- [ ] 自定义主题 - 自定义编辑器主题
- [ ] 多窗口支持 - 支持同时编辑多个文档
- 自定义主题 - 自定义编辑器主题
- 多窗口支持 - 支持同时编辑多个文档
- ✅ 数据同步 - 文档云端备份
- [ ] 剪切板增强 - 监听和管理剪切板历史
- 文本内容自动保存
- 图片内容支持
- 历史记录管理
- [ ] 数据同步 - 配置和文档云端备份
- [ ] 扩展系统 - 支持自定义插件
@@ -131,11 +131,11 @@ Voidraft/
> 站在巨人的肩膀上,致敬开源精神
Voidraft 的诞生离不开以下优秀的开源项目:
voidraft 的诞生离不开以下优秀的开源项目:
### 特别感谢
- **[Heynote](https://github.com/heyman/heynote/)** - Voidraft 是基于 Heynote 概念的功能增强版本
- **[Heynote](https://github.com/heyman/heynote/)** - voidraft 是基于 Heynote 概念的功能增强版本
- 继承了 Heynote 优雅的块状编辑理念
- 在原有基础上增加了更多实用功能
- 采用现代化技术栈重新构建
@@ -159,7 +159,7 @@ Voidraft 的诞生离不开以下优秀的开源项目:
欢迎 Fork、Star 和贡献代码。
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub stars](https://img.shields.io/github/stars/landaiqing/Voidraft.svg?style=social&label=Star)](https://github.com/yourusername/Voidraft)
[![GitHub forks](https://img.shields.io/github/forks/landaiqing/Voidraft.svg?style=social&label=Fork)](https://github.com/yourusername/Voidraft)
[![GitHub stars](https://img.shields.io/github/stars/landaiqing/voidraft.svg?style=social&label=Star)](https://github.com/yourusername/voidraft)
[![GitHub forks](https://img.shields.io/github/forks/landaiqing/voidraft.svg?style=social&label=Fork)](https://github.com/yourusername/voidraft)
*Made with ❤️ by landaiqing*

293
build/COMMANDS.md Normal file
View File

@@ -0,0 +1,293 @@
# Wails 3 命令参考表
本文档列出了 Voidraft 项目中使用的所有 Wails 3 命令和参数。
## 📋 命令总览
| 类别 | 命令 | 用途 |
|------|------|------|
| 生成工具 | `wails3 generate` | 生成项目所需的各种资源文件 |
| 打包工具 | `wails3 tool package` | 使用 nfpm 打包应用程序 |
| 任务执行 | `wails3 task` | 执行 Taskfile.yml 中定义的任务 |
---
## 🔧 详细命令参数
### 1. `wails3 generate bindings`
**生成 TypeScript 绑定文件**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-f` | 构建标志 | `''` (空字符串) |
| `-clean` | 清理旧绑定 | `true` |
| `-ts` | 生成 TypeScript | 无需值 |
**使用位置:** `build/Taskfile.yml:53`
**完整命令:**
```bash
wails3 generate bindings -f '' -clean=true -ts
```
---
### 2. `wails3 generate icons`
**从单个图片生成多平台图标**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-input` | 输入图片路径 | `appicon.png` |
| `-macfilename` | macOS 图标输出路径 | `darwin/icons.icns` |
| `-windowsfilename` | Windows 图标输出路径 | `windows/icons.ico` |
**使用位置:** `build/Taskfile.yml:64`
**完整命令:**
```bash
wails3 generate icons \
-input appicon.png \
-macfilename darwin/icons.icns \
-windowsfilename windows/icons.ico
```
---
### 3. `wails3 generate syso`
**生成 Windows .syso 资源文件**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-arch` | 目标架构 | `amd64` / `arm64` |
| `-icon` | 图标文件 | `windows/icon.ico` |
| `-manifest` | 清单文件 | `windows/wails.exe.manifest` |
| `-info` | 应用信息 JSON | `windows/info.json` |
| `-out` | 输出文件路径 | `../wails_windows_amd64.syso` |
**使用位置:** `build/windows/Taskfile.yml:42`
**完整命令:**
```bash
wails3 generate syso \
-arch amd64 \
-icon windows/icon.ico \
-manifest windows/wails.exe.manifest \
-info windows/info.json \
-out ../wails_windows_amd64.syso
```
---
### 4. `wails3 generate webview2bootstrapper`
**生成 Windows WebView2 引导程序**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-dir` | 输出目录 | `build/windows/nsis` |
**使用位置:** `build/windows/Taskfile.yml:55`
**完整命令:**
```bash
wails3 generate webview2bootstrapper -dir "build/windows/nsis"
```
**说明:** 下载 Microsoft Edge WebView2 运行时安装程序,用于 NSIS 打包。
---
### 5. `wails3 generate .desktop`
**生成 Linux .desktop 桌面文件**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-name` | 应用名称 | `voidraft` |
| `-exec` | 可执行文件名 | `voidraft` |
| `-icon` | 图标名称 | `appicon` |
| `-outputfile` | 输出文件路径 | `build/linux/voidraft.desktop` |
| `-categories` | 应用分类 | `Development;` |
**使用位置:** `build/linux/Taskfile.yml:107`
**完整命令:**
```bash
wails3 generate .desktop \
-name "voidraft" \
-exec "voidraft" \
-icon "appicon" \
-outputfile build/linux/voidraft.desktop \
-categories "Development;"
```
---
### 6. `wails3 generate appimage`
**生成 Linux AppImage 包**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-binary` | 二进制文件名 | `voidraft` |
| `-icon` | 图标文件路径 | `../../appicon.png` |
| `-desktopfile` | .desktop 文件路径 | `../voidraft.desktop` |
| `-outputdir` | 输出目录 | `../../../bin` |
| `-builddir` | 构建临时目录 | `build/linux/appimage/build` |
**使用位置:** `build/linux/Taskfile.yml:49`
**完整命令:**
```bash
wails3 generate appimage \
-binary voidraft \
-icon ../../appicon.png \
-desktopfile ../voidraft.desktop \
-outputdir ../../../bin \
-builddir build/linux/appimage/build
```
**说明:** 自动下载 linuxdeploy 工具并创建 AppImage。
---
### 7. `wails3 tool package` (deb)
**创建 Debian/Ubuntu .deb 包**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-name` | 包名称 | `voidraft` |
| `-format` | 包格式 | `deb` |
| `-config` | nfpm 配置文件 | `./build/linux/nfpm/nfpm.yaml` |
| `-out` | 输出目录 | `./bin` |
**使用位置:** `build/linux/Taskfile.yml:90`
**完整命令:**
```bash
wails3 tool package \
-name voidraft \
-format deb \
-config ./build/linux/nfpm/nfpm.yaml \
-out ./bin
```
---
### 8. `wails3 tool package` (rpm)
**创建 RedHat/CentOS/Fedora .rpm 包**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-name` | 包名称 | `voidraft` |
| `-format` | 包格式 | `rpm` |
| `-config` | nfpm 配置文件 | `./build/linux/nfpm/nfpm.yaml` |
| `-out` | 输出目录 | `./bin` |
**使用位置:** `build/linux/Taskfile.yml:95`
**完整命令:**
```bash
wails3 tool package \
-name voidraft \
-format rpm \
-config ./build/linux/nfpm/nfpm.yaml \
-out ./bin
```
---
### 9. `wails3 tool package` (archlinux)
**创建 Arch Linux .pkg.tar.zst 包**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `-name` | 包名称 | `voidraft` |
| `-format` | 包格式 | `archlinux` |
| `-config` | nfpm 配置文件 | `./build/linux/nfpm/nfpm.yaml` |
| `-out` | 输出目录 | `./bin` |
**使用位置:** `build/linux/Taskfile.yml:100`
**完整命令:**
```bash
wails3 tool package \
-name voidraft \
-format archlinux \
-config ./build/linux/nfpm/nfpm.yaml \
-out ./bin
```
---
### 10. `wails3 task`
**执行 Taskfile.yml 中定义的任务**
| 参数 | 说明 | 示例值 |
|------|------|--------|
| `[taskname]` | 任务名称 | `build`, `package`, `run` |
| `[VAR=value]` | 变量赋值 | `PRODUCTION=true`, `ARCH=amd64` |
**常用任务:**
| 任务 | 说明 | 命令 |
|------|------|------|
| `build` | 构建应用 | `wails3 task build PRODUCTION=true` |
| `package` | 打包应用 | `wails3 task package` |
| `run` | 运行应用 | `wails3 task run` |
**使用位置:** `build/config.yml`
---
## 📊 平台对应命令表
| 平台 | 主要命令 | 产物 |
|------|----------|------|
| **Windows** | `generate syso`<br>`generate webview2bootstrapper` | `.syso` 资源文件<br>NSIS 安装程序 |
| **Linux** | `generate .desktop`<br>`generate appimage`<br>`tool package -format deb/rpm/archlinux` | `.desktop` 文件<br>`.AppImage`<br>`.deb` / `.rpm` / `.pkg.tar.zst` |
| **macOS** | `generate icons` | `.icns` 图标<br>`.app` 应用包 |
| **通用** | `generate bindings`<br>`generate icons` | TypeScript 绑定<br>多平台图标 |
---
## 🚀 快速参考
### 完整构建流程
```bash
# 1. 生成绑定和图标
wails3 task common:generate:bindings
wails3 task common:generate:icons
# 2. 构建前端
cd frontend
npm install
npm run build
cd ..
# 3. 构建应用(各平台)
cd build/windows && wails3 task build PRODUCTION=true # Windows
cd build/linux && wails3 task build PRODUCTION=true # Linux
cd build/darwin && wails3 task build PRODUCTION=true # macOS
# 4. 打包应用(各平台)
cd build/windows && wails3 task package # NSIS 安装程序
cd build/linux && wails3 task package # AppImage + deb + rpm + archlinux
cd build/darwin && wails3 task package # .app bundle
```
---
## 📝 注意事项
1. **变量传递:** Task 命令支持通过 `VAR=value` 格式传递变量
2. **路径问题:** 相对路径基于 Taskfile.yml 所在目录
3. **依赖顺序:** 某些任务有依赖关系(通过 `deps:` 定义)
4. **环境变量:** 使用 `env:` 定义的环境变量会自动设置
---
## 🔗 相关文档
- [Wails 3 官方文档](https://v3alpha.wails.io/)
- [Taskfile 语法](https://taskfile.dev/)
- [nfpm 打包工具](https://nfpm.goreleaser.com/)

View File

@@ -5,12 +5,12 @@ version: '3'
# This information is used to generate the build assets.
info:
companyName: "Voidraft" # The name of the company
productName: "Voidraft" # The name of the application
companyName: "voidraft" # The name of the company
productName: "voidraft" # The name of the application
productIdentifier: "landaiqing" # The unique product identifier
description: "Voidraft" # The application description
copyright: "© 2025 Voidraft. All rights reserved." # Copyright text
comments: "Voidraft" # Comments
description: "voidraft" # The application description
copyright: "© 2025 voidraft. All rights reserved." # Copyright text
comments: "voidraft" # Comments
version: "0.0.1.0" # The application version
# Dev mode configuration

View File

@@ -4,15 +4,15 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleName</key>
<string>Voidraft</string>
<string>voidraft</string>
<key>CFBundleExecutable</key>
<string>Voidraft</string>
<string>voidraft</string>
<key>CFBundleIdentifier</key>
<string>landaiqing</string>
<key>CFBundleVersion</key>
<string>0.0.1.0</string>
<key>CFBundleGetInfoString</key>
<string>Voidraft</string>
<string>voidraft</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1.0</string>
<key>CFBundleIconFile</key>
@@ -22,7 +22,7 @@
<key>NSHighResolutionCapable</key>
<string>true</string>
<key>NSHumanReadableCopyright</key>
<string>© 2025 Voidraft. All rights reserved.</string>
<string>© 2025 voidraft. All rights reserved.</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>

View File

@@ -4,15 +4,15 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleName</key>
<string>Voidraft</string>
<string>voidraft</string>
<key>CFBundleExecutable</key>
<string>Voidraft</string>
<string>voidraft</string>
<key>CFBundleIdentifier</key>
<string>landaiqing</string>
<key>CFBundleVersion</key>
<string>0.0.1.0</string>
<key>CFBundleGetInfoString</key>
<string>Voidraft</string>
<string>voidraft</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1.0</string>
<key>CFBundleIconFile</key>
@@ -22,6 +22,6 @@
<key>NSHighResolutionCapable</key>
<string>true</string>
<key>NSHumanReadableCopyright</key>
<string>© 2025 Voidraft. All rights reserved.</string>
<string>© 2025 voidraft. All rights reserved.</string>
</dict>
</plist>

View File

@@ -11,9 +11,12 @@ tasks:
- task: common:build:frontend
- task: common:generate:icons
cmds:
- go build {{.BUILD_FLAGS}} -o {{.OUTPUT}}
- go build {{.BUILD_FLAGS}} -ldflags="{{.LDFLAGS}} {{.VERSION_FLAGS}}" -o {{.OUTPUT}}
vars:
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
LDFLAGS: '{{if eq .PRODUCTION "true"}}-w -s{{else}}{{end}}'
VERSION_FLAGS:
sh: 'grep "VERSION=" version.txt | cut -d"=" -f2 | xargs -I {} echo "-X voidraft/internal/version.Version={}"'
DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}'
OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}'
env:

View File

@@ -11,9 +11,12 @@ tasks:
- task: common:build:frontend
- task: common:generate:icons
cmds:
- go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}
- go build {{.BUILD_FLAGS}} -ldflags="{{.LDFLAGS}} {{.VERSION_FLAGS}}" -o {{.BIN_DIR}}/{{.APP_NAME}}
vars:
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
LDFLAGS: '{{if eq .PRODUCTION "true"}}-w -s{{else}}{{end}}'
VERSION_FLAGS:
sh: 'grep "VERSION=" version.txt | cut -d"=" -f2 | xargs -I {} echo "-X voidraft/internal/version.Version={}"'
env:
GOOS: linux
CGO_ENABLED: 1

View File

@@ -3,26 +3,26 @@
#
# The lines below are called `modelines`. See `:help modeline`
name: "Voidraft"
name: "voidraft"
arch: ${GOARCH}
platform: "linux"
version: "0.0.1.0"
section: "default"
priority: "extra"
maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}>
description: "Voidraft"
vendor: "Voidraft"
homepage: "https://wails.io"
description: "voidraft"
vendor: "voidraft"
homepage: "https://voidraft.landaiqing.cn"
license: "MIT"
release: "1"
contents:
- src: "./bin/Voidraft"
dst: "/usr/local/bin/Voidraft"
- src: "./bin/voidraft"
dst: "/usr/local/bin/voidraft"
- src: "./build/appicon.png"
dst: "/usr/share/icons/hicolor/128x128/apps/Voidraft.png"
- src: "./build/linux/Voidraft.desktop"
dst: "/usr/share/applications/Voidraft.desktop"
dst: "/usr/share/icons/hicolor/128x128/apps/voidraft.png"
- src: "./build/linux/voidraft.desktop"
dst: "/usr/share/applications/voidraft.desktop"
depends:
- gtk3

View File

@@ -14,13 +14,16 @@ tasks:
- task: common:generate:icons
cmds:
- task: generate:syso
- go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe
- go build {{.BUILD_FLAGS}} -ldflags="{{.LDFLAGS}} {{.VERSION_FLAGS}}" -o {{.BIN_DIR}}/{{.APP_NAME}}.exe
- cmd: powershell Remove-item *.syso
platforms: [windows]
- cmd: rm -f *.syso
platforms: [linux, darwin]
vars:
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
LDFLAGS: '{{if eq .PRODUCTION "true"}}-w -s -H windowsgui{{else}}{{end}}'
VERSION_FLAGS:
sh: 'powershell -Command "(Get-Content version.txt) -replace ''VERSION='', ''-X voidraft/internal/version.Version=''"'
env:
GOOS: windows
CGO_ENABLED: 1

View File

@@ -5,11 +5,11 @@
"info": {
"0000": {
"ProductVersion": "0.0.1.0",
"CompanyName": "Voidraft",
"FileDescription": "Voidraft",
"LegalCopyright": "© 2025 Voidraft. All rights reserved.",
"ProductName": "Voidraft",
"Comments": "Voidraft"
"CompanyName": "voidraft",
"FileDescription": "voidraft",
"LegalCopyright": "© 2025 voidraft. All rights reserved.",
"ProductName": "voidraft",
"Comments": "voidraft"
}
}
}

View File

@@ -5,19 +5,19 @@
!include "FileFunc.nsh"
!ifndef INFO_PROJECTNAME
!define INFO_PROJECTNAME "Voidraft"
!define INFO_PROJECTNAME "voidraft"
!endif
!ifndef INFO_COMPANYNAME
!define INFO_COMPANYNAME "Voidraft"
!define INFO_COMPANYNAME "voidraft"
!endif
!ifndef INFO_PRODUCTNAME
!define INFO_PRODUCTNAME "Voidraft"
!define INFO_PRODUCTNAME "voidraft"
!endif
!ifndef INFO_PRODUCTVERSION
!define INFO_PRODUCTVERSION "0.0.1.0"
!endif
!ifndef INFO_COPYRIGHT
!define INFO_COPYRIGHT "© 2025 Voidraft. All rights reserved."
!define INFO_COPYRIGHT "© 2025 voidraft. All rights reserved."
!endif
!ifndef PRODUCT_EXECUTABLE
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"

View File

@@ -1,37 +0,0 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
/**
* DB is a database handle representing a pool of zero or more
* underlying connections. It's safe for concurrent use by multiple
* goroutines.
*
* The sql package creates and frees connections automatically; it
* also maintains a free pool of idle connections. If the database has
* a concept of per-connection state, such state can be reliably observed
* within a transaction ([Tx]) or connection ([Conn]). Once [DB.Begin] is called, the
* returned [Tx] is bound to a single connection. Once [Tx.Commit] or
* [Tx.Rollback] is called on the transaction, that transaction's
* connection is returned to [DB]'s idle connection pool. The pool size
* can be controlled with [DB.SetMaxIdleConns].
*/
export class DB {
/** Creates a new DB instance. */
constructor($$source: Partial<DB> = {}) {
Object.assign(this, $$source);
}
/**
* Creates a new DB instance from a string or object.
*/
static createFrom($$source: any = {}): DB {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new DB($$parsedSource as Partial<DB>);
}
}

View File

@@ -5,82 +5,61 @@
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as slog$0 from "../../../../../../log/slog/models.js";
export class App {
/**
* ServiceOptions provides optional parameters for calls to [NewService].
*/
export class ServiceOptions {
/**
* The main application menu
* Name can be set to override the name of the service
* for logging and debugging purposes.
*
* If empty, it will default
* either to the value obtained through the [ServiceName] interface,
* or to the type name.
*/
"ApplicationMenu": Menu | null;
"Logger": slog$0.Logger | null;
"Name": string;
/** Creates a new App instance. */
constructor($$source: Partial<App> = {}) {
if (!("ApplicationMenu" in $$source)) {
this["ApplicationMenu"] = null;
/**
* If the service instance implements [http.Handler],
* it will be mounted on the internal asset server
* at the prefix specified by Route.
*/
"Route": string;
/**
* MarshalError will be called if non-nil
* to marshal to JSON the error values returned by this service's methods.
*
* MarshalError is not allowed to fail,
* but it may return a nil slice to fall back
* to the globally configured error handler.
*
* If the returned slice is not nil, it must contain valid JSON.
*/
"MarshalError": any;
/** Creates a new ServiceOptions instance. */
constructor($$source: Partial<ServiceOptions> = {}) {
if (!("Name" in $$source)) {
this["Name"] = "";
}
if (!("Logger" in $$source)) {
this["Logger"] = null;
if (!("Route" in $$source)) {
this["Route"] = "";
}
if (!("MarshalError" in $$source)) {
this["MarshalError"] = null;
}
Object.assign(this, $$source);
}
/**
* Creates a new App instance from a string or object.
* Creates a new ServiceOptions instance from a string or object.
*/
static createFrom($$source: any = {}): App {
const $$createField0_0 = $$createType1;
const $$createField1_0 = $$createType3;
static createFrom($$source: any = {}): ServiceOptions {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("ApplicationMenu" in $$parsedSource) {
$$parsedSource["ApplicationMenu"] = $$createField0_0($$parsedSource["ApplicationMenu"]);
}
if ("Logger" in $$parsedSource) {
$$parsedSource["Logger"] = $$createField1_0($$parsedSource["Logger"]);
}
return new App($$parsedSource as Partial<App>);
return new ServiceOptions($$parsedSource as Partial<ServiceOptions>);
}
}
export class Menu {
/** Creates a new Menu instance. */
constructor($$source: Partial<Menu> = {}) {
Object.assign(this, $$source);
}
/**
* Creates a new Menu instance from a string or object.
*/
static createFrom($$source: any = {}): Menu {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new Menu($$parsedSource as Partial<Menu>);
}
}
export class WebviewWindow {
/** Creates a new WebviewWindow instance. */
constructor($$source: Partial<WebviewWindow> = {}) {
Object.assign(this, $$source);
}
/**
* Creates a new WebviewWindow instance from a string or object.
*/
static createFrom($$source: any = {}): WebviewWindow {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new WebviewWindow($$parsedSource as Partial<WebviewWindow>);
}
}
// Private type creation functions
const $$createType0 = Menu.createFrom;
const $$createType1 = $Create.Nullable($$createType0);
const $$createType2 = slog$0.Logger.createFrom;
const $$createType3 = $Create.Nullable($$createType2);
export type Window = any;

View File

@@ -0,0 +1,83 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* Service represents the dock service
* @module
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../application/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as $models from "./models.js";
/**
* HideAppIcon hides the app icon in the dock/taskbar.
*/
export function HideAppIcon(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3413658144) as any;
return $resultPromise;
}
/**
* RemoveBadge removes the badge label from the application icon.
*/
export function RemoveBadge(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2752757297) as any;
return $resultPromise;
}
/**
* ServiceName returns the name of the service.
*/
export function ServiceName(): Promise<string> & { cancel(): void } {
let $resultPromise = $Call.ByID(2949906614) as any;
return $resultPromise;
}
/**
* ServiceShutdown is called when the service is unloaded.
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(307064411) as any;
return $resultPromise;
}
/**
* ServiceStartup is called when the service is loaded.
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1350118426, options) as any;
return $resultPromise;
}
/**
* SetBadge sets the badge label on the application icon.
*/
export function SetBadge(label: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1717705661, label) as any;
return $resultPromise;
}
/**
* SetCustomBadge sets the badge label on the application icon with custom options.
*/
export function SetCustomBadge(label: string, options: $models.BadgeOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2730169760, label, options) as any;
return $resultPromise;
}
/**
* ShowAppIcon shows the app icon in the dock/taskbar.
*/
export function ShowAppIcon(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3409697379) as any;
return $resultPromise;
}

View File

@@ -0,0 +1,9 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import * as DockService from "./dockservice.js";
export {
DockService
};
export * from "./models.js";

View File

@@ -0,0 +1,61 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as color$0 from "../../../../../../../image/color/models.js";
/**
* BadgeOptions represents options for customizing badge appearance
*/
export class BadgeOptions {
"TextColour": color$0.RGBA;
"BackgroundColour": color$0.RGBA;
"FontName": string;
"FontSize": number;
"SmallFontSize": number;
/** Creates a new BadgeOptions instance. */
constructor($$source: Partial<BadgeOptions> = {}) {
if (!("TextColour" in $$source)) {
this["TextColour"] = (new color$0.RGBA());
}
if (!("BackgroundColour" in $$source)) {
this["BackgroundColour"] = (new color$0.RGBA());
}
if (!("FontName" in $$source)) {
this["FontName"] = "";
}
if (!("FontSize" in $$source)) {
this["FontSize"] = 0;
}
if (!("SmallFontSize" in $$source)) {
this["SmallFontSize"] = 0;
}
Object.assign(this, $$source);
}
/**
* Creates a new BadgeOptions instance from a string or object.
*/
static createFrom($$source: any = {}): BadgeOptions {
const $$createField0_0 = $$createType0;
const $$createField1_0 = $$createType0;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("TextColour" in $$parsedSource) {
$$parsedSource["TextColour"] = $$createField0_0($$parsedSource["TextColour"]);
}
if ("BackgroundColour" in $$parsedSource) {
$$parsedSource["BackgroundColour"] = $$createField1_0($$parsedSource["BackgroundColour"]);
}
return new BadgeOptions($$parsedSource as Partial<BadgeOptions>);
}
}
// Private type creation functions
const $$createType0 = color$0.RGBA.createFrom;

View File

@@ -0,0 +1,9 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import * as NotificationService from "./notificationservice.js";
export {
NotificationService
};
export * from "./models.js";

View File

@@ -0,0 +1,107 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
/**
* NotificationAction represents an action button for a notification.
*/
export class NotificationAction {
"id"?: string;
"title"?: string;
/**
* (macOS-specific)
*/
"destructive"?: boolean;
/** Creates a new NotificationAction instance. */
constructor($$source: Partial<NotificationAction> = {}) {
Object.assign(this, $$source);
}
/**
* Creates a new NotificationAction instance from a string or object.
*/
static createFrom($$source: any = {}): NotificationAction {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new NotificationAction($$parsedSource as Partial<NotificationAction>);
}
}
/**
* NotificationCategory groups actions for notifications.
*/
export class NotificationCategory {
"id"?: string;
"actions"?: NotificationAction[];
"hasReplyField"?: boolean;
"replyPlaceholder"?: string;
"replyButtonTitle"?: string;
/** Creates a new NotificationCategory instance. */
constructor($$source: Partial<NotificationCategory> = {}) {
Object.assign(this, $$source);
}
/**
* Creates a new NotificationCategory instance from a string or object.
*/
static createFrom($$source: any = {}): NotificationCategory {
const $$createField1_0 = $$createType1;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("actions" in $$parsedSource) {
$$parsedSource["actions"] = $$createField1_0($$parsedSource["actions"]);
}
return new NotificationCategory($$parsedSource as Partial<NotificationCategory>);
}
}
/**
* NotificationOptions contains configuration for a notification
*/
export class NotificationOptions {
"id": string;
"title": string;
/**
* (macOS and Linux only)
*/
"subtitle"?: string;
"body"?: string;
"categoryId"?: string;
"data"?: { [_: string]: any };
/** Creates a new NotificationOptions instance. */
constructor($$source: Partial<NotificationOptions> = {}) {
if (!("id" in $$source)) {
this["id"] = "";
}
if (!("title" in $$source)) {
this["title"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new NotificationOptions instance from a string or object.
*/
static createFrom($$source: any = {}): NotificationOptions {
const $$createField5_0 = $$createType2;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("data" in $$parsedSource) {
$$parsedSource["data"] = $$createField5_0($$parsedSource["data"]);
}
return new NotificationOptions($$parsedSource as Partial<NotificationOptions>);
}
}
// Private type creation functions
const $$createType0 = NotificationAction.createFrom;
const $$createType1 = $Create.Array($$createType0);
const $$createType2 = $Create.Map($Create.Any, $Create.Any);

View File

@@ -0,0 +1,110 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* Service represents the notifications service
* @module
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../application/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as $models from "./models.js";
export function CheckNotificationAuthorization(): Promise<boolean> & { cancel(): void } {
let $resultPromise = $Call.ByID(2216952893) as any;
return $resultPromise;
}
/**
* OnNotificationResponse registers a callback function that will be called when
* a notification response is received from the user.
*/
export function OnNotificationResponse(callback: any): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1642697808, callback) as any;
return $resultPromise;
}
export function RegisterNotificationCategory(category: $models.NotificationCategory): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2917562919, category) as any;
return $resultPromise;
}
export function RemoveAllDeliveredNotifications(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3956282340) as any;
return $resultPromise;
}
export function RemoveAllPendingNotifications(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(108821341) as any;
return $resultPromise;
}
export function RemoveDeliveredNotification(identifier: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(975691940, identifier) as any;
return $resultPromise;
}
export function RemoveNotification(identifier: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3966653866, identifier) as any;
return $resultPromise;
}
export function RemoveNotificationCategory(categoryID: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2032615554, categoryID) as any;
return $resultPromise;
}
export function RemovePendingNotification(identifier: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3729049703, identifier) as any;
return $resultPromise;
}
/**
* Public methods that delegate to the implementation.
*/
export function RequestNotificationAuthorization(): Promise<boolean> & { cancel(): void } {
let $resultPromise = $Call.ByID(3933442950) as any;
return $resultPromise;
}
export function SendNotification(options: $models.NotificationOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3968228732, options) as any;
return $resultPromise;
}
export function SendNotificationWithActions(options: $models.NotificationOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1886542847, options) as any;
return $resultPromise;
}
/**
* ServiceName returns the name of the service.
*/
export function ServiceName(): Promise<string> & { cancel(): void } {
let $resultPromise = $Call.ByID(2704532675) as any;
return $resultPromise;
}
/**
* ServiceShutdown is called when the service is unloaded.
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2550195434) as any;
return $resultPromise;
}
/**
* ServiceStartup is called when the service is loaded.
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(4047820929, options) as any;
return $resultPromise;
}

View File

@@ -0,0 +1,46 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
/**
* RGBA represents a traditional 32-bit alpha-premultiplied color, having 8
* bits for each of red, green, blue and alpha.
*
* An alpha-premultiplied color component C has been scaled by alpha (A), so
* has valid values 0 <= C <= A.
*/
export class RGBA {
"R": number;
"G": number;
"B": number;
"A": number;
/** Creates a new RGBA instance. */
constructor($$source: Partial<RGBA> = {}) {
if (!("R" in $$source)) {
this["R"] = 0;
}
if (!("G" in $$source)) {
this["G"] = 0;
}
if (!("B" in $$source)) {
this["B"] = 0;
}
if (!("A" in $$source)) {
this["A"] = 0;
}
Object.assign(this, $$source);
}
/**
* Creates a new RGBA instance from a string or object.
*/
static createFrom($$source: any = {}): RGBA {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new RGBA($$parsedSource as Partial<RGBA>);
}
}

View File

@@ -1,31 +0,0 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
/**
* A Logger records structured information about each call to its
* Log, Debug, Info, Warn, and Error methods.
* For each call, it creates a [Record] and passes it to a [Handler].
*
* To create a new Logger, call [New] or a Logger method
* that begins "With".
*/
export class Logger {
/** Creates a new Logger instance. */
constructor($$source: Partial<Logger> = {}) {
Object.assign(this, $$source);
}
/**
* Creates a new Logger instance from a string or object.
*/
static createFrom($$source: any = {}): Logger {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new Logger($$parsedSource as Partial<Logger>);
}
}

View File

@@ -0,0 +1,14 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
/**
* A Header represents the key-value pairs in an HTTP header.
*
* The keys should be in canonical form, as returned by
* [CanonicalHeaderKey].
*/
export type Header = { [_: string]: string[] };

View File

@@ -68,4 +68,9 @@ export enum TranslatorType {
* DeeplTranslatorType DeepL翻译器
*/
DeeplTranslatorType = "deepl",
/**
* TartuNLPTranslatorType TartuNLP翻译器
*/
TartuNLPTranslatorType = "tartunlp",
};

View File

@@ -5,10 +5,6 @@
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as time$0 from "../../../time/models.js";
/**
* AppConfig 应用配置 - 按照前端设置页面分类组织
*/
@@ -33,6 +29,11 @@ export class AppConfig {
*/
"updates": UpdatesConfig;
/**
* Git备份设置
*/
"backup": GitBackupConfig;
/**
* 配置元数据
*/
@@ -52,6 +53,9 @@ export class AppConfig {
if (!("updates" in $$source)) {
this["updates"] = (new UpdatesConfig());
}
if (!("backup" in $$source)) {
this["backup"] = (new GitBackupConfig());
}
if (!("metadata" in $$source)) {
this["metadata"] = (new ConfigMetadata());
}
@@ -68,6 +72,7 @@ export class AppConfig {
const $$createField2_0 = $$createType2;
const $$createField3_0 = $$createType3;
const $$createField4_0 = $$createType4;
const $$createField5_0 = $$createType5;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("general" in $$parsedSource) {
$$parsedSource["general"] = $$createField0_0($$parsedSource["general"]);
@@ -81,8 +86,11 @@ export class AppConfig {
if ("updates" in $$parsedSource) {
$$parsedSource["updates"] = $$createField3_0($$parsedSource["updates"]);
}
if ("backup" in $$parsedSource) {
$$parsedSource["backup"] = $$createField4_0($$parsedSource["backup"]);
}
if ("metadata" in $$parsedSource) {
$$parsedSource["metadata"] = $$createField4_0($$parsedSource["metadata"]);
$$parsedSource["metadata"] = $$createField5_0($$parsedSource["metadata"]);
}
return new AppConfig($$parsedSource as Partial<AppConfig>);
}
@@ -102,6 +110,11 @@ export class AppearanceConfig {
*/
"systemTheme": SystemThemeType;
/**
* 当前选择的预设主题名称
*/
"currentTheme": string;
/** Creates a new AppearanceConfig instance. */
constructor($$source: Partial<AppearanceConfig> = {}) {
if (!("language" in $$source)) {
@@ -110,6 +123,9 @@ export class AppearanceConfig {
if (!("systemTheme" in $$source)) {
this["systemTheme"] = ("" as SystemThemeType);
}
if (!("currentTheme" in $$source)) {
this["currentTheme"] = "";
}
Object.assign(this, $$source);
}
@@ -123,6 +139,25 @@ export class AppearanceConfig {
}
}
/**
* Git备份相关类型定义
*
* AuthMethod 定义Git认证方式
*/
export enum AuthMethod {
/**
* The Go zero value for the underlying type of the enum.
*/
$zero = "",
/**
* 认证方式
*/
Token = "token",
SSHKey = "ssh_key",
UserPass = "user_pass",
};
/**
* ConfigMetadata 配置元数据
*/
@@ -165,10 +200,15 @@ export class Document {
"id": number;
"title": string;
"content": string;
"createdAt": time$0.Time;
"updatedAt": time$0.Time;
"createdAt": string;
"updatedAt": string;
"is_deleted": boolean;
/**
* 锁定标志,锁定的文档无法被删除
*/
"is_locked": boolean;
/** Creates a new Document instance. */
constructor($$source: Partial<Document> = {}) {
if (!("id" in $$source)) {
@@ -181,14 +221,17 @@ export class Document {
this["content"] = "";
}
if (!("createdAt" in $$source)) {
this["createdAt"] = null;
this["createdAt"] = "";
}
if (!("updatedAt" in $$source)) {
this["updatedAt"] = null;
this["updatedAt"] = "";
}
if (!("is_deleted" in $$source)) {
this["is_deleted"] = false;
}
if (!("is_locked" in $$source)) {
this["is_locked"] = false;
}
Object.assign(this, $$source);
}
@@ -334,7 +377,7 @@ export class Extension {
* Creates a new Extension instance from a string or object.
*/
static createFrom($$source: any = {}): Extension {
const $$createField3_0 = $$createType5;
const $$createField3_0 = $$createType6;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("config" in $$parsedSource) {
$$parsedSource["config"] = $$createField3_0($$parsedSource["config"]);
@@ -428,6 +471,12 @@ export class GeneralConfig {
*/
"startAtLogin": boolean;
/**
* 窗口吸附设置
* 是否启用窗口吸附功能(阈值现在是自适应的)
*/
"enableWindowSnap": boolean;
/**
* 全局热键设置
* 是否启用全局热键
@@ -439,6 +488,17 @@ export class GeneralConfig {
*/
"globalHotkey": HotkeyCombo;
/**
* 界面设置
* 是否启用加载动画
*/
"enableLoadingAnimation": boolean;
/**
* 是否启用标签页模式
*/
"enableTabs": boolean;
/** Creates a new GeneralConfig instance. */
constructor($$source: Partial<GeneralConfig> = {}) {
if (!("alwaysOnTop" in $$source)) {
@@ -453,12 +513,21 @@ export class GeneralConfig {
if (!("startAtLogin" in $$source)) {
this["startAtLogin"] = false;
}
if (!("enableWindowSnap" in $$source)) {
this["enableWindowSnap"] = false;
}
if (!("enableGlobalHotkey" in $$source)) {
this["enableGlobalHotkey"] = false;
}
if (!("globalHotkey" in $$source)) {
this["globalHotkey"] = (new HotkeyCombo());
}
if (!("enableLoadingAnimation" in $$source)) {
this["enableLoadingAnimation"] = false;
}
if (!("enableTabs" in $$source)) {
this["enableTabs"] = false;
}
Object.assign(this, $$source);
}
@@ -467,15 +536,64 @@ export class GeneralConfig {
* Creates a new GeneralConfig instance from a string or object.
*/
static createFrom($$source: any = {}): GeneralConfig {
const $$createField5_0 = $$createType7;
const $$createField6_0 = $$createType8;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("globalHotkey" in $$parsedSource) {
$$parsedSource["globalHotkey"] = $$createField5_0($$parsedSource["globalHotkey"]);
$$parsedSource["globalHotkey"] = $$createField6_0($$parsedSource["globalHotkey"]);
}
return new GeneralConfig($$parsedSource as Partial<GeneralConfig>);
}
}
/**
* GitBackupConfig Git备份配置
*/
export class GitBackupConfig {
"enabled": boolean;
"repo_url": string;
"auth_method": AuthMethod;
"username"?: string;
"password"?: string;
"token"?: string;
"ssh_key_path"?: string;
"ssh_key_passphrase"?: string;
/**
* 分钟
*/
"backup_interval": number;
"auto_backup": boolean;
/** Creates a new GitBackupConfig instance. */
constructor($$source: Partial<GitBackupConfig> = {}) {
if (!("enabled" in $$source)) {
this["enabled"] = false;
}
if (!("repo_url" in $$source)) {
this["repo_url"] = "";
}
if (!("auth_method" in $$source)) {
this["auth_method"] = ("" as AuthMethod);
}
if (!("backup_interval" in $$source)) {
this["backup_interval"] = 0;
}
if (!("auto_backup" in $$source)) {
this["auto_backup"] = false;
}
Object.assign(this, $$source);
}
/**
* Creates a new GitBackupConfig instance from a string or object.
*/
static createFrom($$source: any = {}): GitBackupConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new GitBackupConfig($$parsedSource as Partial<GitBackupConfig>);
}
}
/**
* GiteaConfig Gitea配置
*/
@@ -963,84 +1081,6 @@ export enum KeyBindingCommand {
TextHighlightToggleCommand = "textHighlightToggle",
};
/**
* KeyBindingConfig 快捷键配置
*/
export class KeyBindingConfig {
/**
* 快捷键列表
*/
"keyBindings": KeyBinding[];
/**
* 配置元数据
*/
"metadata": KeyBindingMetadata;
/** Creates a new KeyBindingConfig instance. */
constructor($$source: Partial<KeyBindingConfig> = {}) {
if (!("keyBindings" in $$source)) {
this["keyBindings"] = [];
}
if (!("metadata" in $$source)) {
this["metadata"] = (new KeyBindingMetadata());
}
Object.assign(this, $$source);
}
/**
* Creates a new KeyBindingConfig instance from a string or object.
*/
static createFrom($$source: any = {}): KeyBindingConfig {
const $$createField0_0 = $$createType9;
const $$createField1_0 = $$createType10;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("keyBindings" in $$parsedSource) {
$$parsedSource["keyBindings"] = $$createField0_0($$parsedSource["keyBindings"]);
}
if ("metadata" in $$parsedSource) {
$$parsedSource["metadata"] = $$createField1_0($$parsedSource["metadata"]);
}
return new KeyBindingConfig($$parsedSource as Partial<KeyBindingConfig>);
}
}
/**
* KeyBindingMetadata 快捷键配置元数据
*/
export class KeyBindingMetadata {
/**
* 配置版本
*/
"version": string;
/**
* 最后更新时间
*/
"lastUpdated": string;
/** Creates a new KeyBindingMetadata instance. */
constructor($$source: Partial<KeyBindingMetadata> = {}) {
if (!("version" in $$source)) {
this["version"] = "";
}
if (!("lastUpdated" in $$source)) {
this["lastUpdated"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new KeyBindingMetadata instance from a string or object.
*/
static createFrom($$source: any = {}): KeyBindingMetadata {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new KeyBindingMetadata($$parsedSource as Partial<KeyBindingMetadata>);
}
}
/**
* LanguageType 语言类型定义
*/
@@ -1106,6 +1146,370 @@ export enum TabType {
TabTypeTab = "tab",
};
/**
* Theme 主题数据库模型
*/
export class Theme {
"id": number;
"name": string;
"type": ThemeType;
"colors": ThemeColorConfig;
"isDefault": boolean;
"createdAt": string;
"updatedAt": string;
/** Creates a new Theme instance. */
constructor($$source: Partial<Theme> = {}) {
if (!("id" in $$source)) {
this["id"] = 0;
}
if (!("name" in $$source)) {
this["name"] = "";
}
if (!("type" in $$source)) {
this["type"] = ("" as ThemeType);
}
if (!("colors" in $$source)) {
this["colors"] = (new ThemeColorConfig());
}
if (!("isDefault" in $$source)) {
this["isDefault"] = false;
}
if (!("createdAt" in $$source)) {
this["createdAt"] = "";
}
if (!("updatedAt" in $$source)) {
this["updatedAt"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new Theme instance from a string or object.
*/
static createFrom($$source: any = {}): Theme {
const $$createField3_0 = $$createType9;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("colors" in $$parsedSource) {
$$parsedSource["colors"] = $$createField3_0($$parsedSource["colors"]);
}
return new Theme($$parsedSource as Partial<Theme>);
}
}
/**
* ThemeColorConfig 主题颜色配置(与前端 ThemeColors 接口保持一致)
*/
export class ThemeColorConfig {
/**
* 主题基本信息
* 主题名称
*/
"name": string;
/**
* 是否为深色主题
*/
"dark": boolean;
/**
* 基础色调
* 主背景色
*/
"background": string;
/**
* 次要背景色(用于代码块交替背景)
*/
"backgroundSecondary": string;
/**
* 面板背景
*/
"surface": string;
/**
* 下拉菜单背景
*/
"dropdownBackground": string;
/**
* 下拉菜单边框
*/
"dropdownBorder": string;
/**
* 文本颜色
* 主文本色
*/
"foreground": string;
/**
* 次要文本色
*/
"foregroundSecondary": string;
/**
* 注释色
*/
"comment": string;
/**
* 语法高亮色 - 核心
* 关键字
*/
"keyword": string;
/**
* 字符串
*/
"string": string;
/**
* 函数名
*/
"function": string;
/**
* 数字
*/
"number": string;
/**
* 操作符
*/
"operator": string;
/**
* 变量
*/
"variable": string;
/**
* 类型
*/
"type": string;
/**
* 语法高亮色 - 扩展
* 常量
*/
"constant": string;
/**
* 存储类型(如 static, const
*/
"storage": string;
/**
* 参数
*/
"parameter": string;
/**
* 类名
*/
"class": string;
/**
* 标题Markdown等
*/
"heading": string;
/**
* 无效内容/错误
*/
"invalid": string;
/**
* 正则表达式
*/
"regexp": string;
/**
* 界面元素
* 光标
*/
"cursor": string;
/**
* 选中背景
*/
"selection": string;
/**
* 失焦选中背景
*/
"selectionBlur": string;
/**
* 当前行高亮
*/
"activeLine": string;
/**
* 行号
*/
"lineNumber": string;
/**
* 活动行号颜色
*/
"activeLineNumber": string;
/**
* 边框和分割线
* 边框色
*/
"borderColor": string;
/**
* 浅色边框
*/
"borderLight": string;
/**
* 搜索和匹配
* 搜索匹配
*/
"searchMatch": string;
/**
* 匹配括号
*/
"matchingBracket": string;
/** Creates a new ThemeColorConfig instance. */
constructor($$source: Partial<ThemeColorConfig> = {}) {
if (!("name" in $$source)) {
this["name"] = "";
}
if (!("dark" in $$source)) {
this["dark"] = false;
}
if (!("background" in $$source)) {
this["background"] = "";
}
if (!("backgroundSecondary" in $$source)) {
this["backgroundSecondary"] = "";
}
if (!("surface" in $$source)) {
this["surface"] = "";
}
if (!("dropdownBackground" in $$source)) {
this["dropdownBackground"] = "";
}
if (!("dropdownBorder" in $$source)) {
this["dropdownBorder"] = "";
}
if (!("foreground" in $$source)) {
this["foreground"] = "";
}
if (!("foregroundSecondary" in $$source)) {
this["foregroundSecondary"] = "";
}
if (!("comment" in $$source)) {
this["comment"] = "";
}
if (!("keyword" in $$source)) {
this["keyword"] = "";
}
if (!("string" in $$source)) {
this["string"] = "";
}
if (!("function" in $$source)) {
this["function"] = "";
}
if (!("number" in $$source)) {
this["number"] = "";
}
if (!("operator" in $$source)) {
this["operator"] = "";
}
if (!("variable" in $$source)) {
this["variable"] = "";
}
if (!("type" in $$source)) {
this["type"] = "";
}
if (!("constant" in $$source)) {
this["constant"] = "";
}
if (!("storage" in $$source)) {
this["storage"] = "";
}
if (!("parameter" in $$source)) {
this["parameter"] = "";
}
if (!("class" in $$source)) {
this["class"] = "";
}
if (!("heading" in $$source)) {
this["heading"] = "";
}
if (!("invalid" in $$source)) {
this["invalid"] = "";
}
if (!("regexp" in $$source)) {
this["regexp"] = "";
}
if (!("cursor" in $$source)) {
this["cursor"] = "";
}
if (!("selection" in $$source)) {
this["selection"] = "";
}
if (!("selectionBlur" in $$source)) {
this["selectionBlur"] = "";
}
if (!("activeLine" in $$source)) {
this["activeLine"] = "";
}
if (!("lineNumber" in $$source)) {
this["lineNumber"] = "";
}
if (!("activeLineNumber" in $$source)) {
this["activeLineNumber"] = "";
}
if (!("borderColor" in $$source)) {
this["borderColor"] = "";
}
if (!("borderLight" in $$source)) {
this["borderLight"] = "";
}
if (!("searchMatch" in $$source)) {
this["searchMatch"] = "";
}
if (!("matchingBracket" in $$source)) {
this["matchingBracket"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new ThemeColorConfig instance from a string or object.
*/
static createFrom($$source: any = {}): ThemeColorConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new ThemeColorConfig($$parsedSource as Partial<ThemeColorConfig>);
}
}
/**
* ThemeType 主题类型枚举
*/
export enum ThemeType {
/**
* The Go zero value for the underlying type of the enum.
*/
$zero = "",
ThemeTypeDark = "dark",
ThemeTypeLight = "light",
};
/**
* UpdateSourceType 更新源类型
*/
@@ -1204,8 +1608,8 @@ export class UpdatesConfig {
* Creates a new UpdatesConfig instance from a string or object.
*/
static createFrom($$source: any = {}): UpdatesConfig {
const $$createField6_0 = $$createType11;
const $$createField7_0 = $$createType12;
const $$createField6_0 = $$createType10;
const $$createField7_0 = $$createType11;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("github" in $$parsedSource) {
$$parsedSource["github"] = $$createField6_0($$parsedSource["github"]);
@@ -1222,17 +1626,16 @@ const $$createType0 = GeneralConfig.createFrom;
const $$createType1 = EditingConfig.createFrom;
const $$createType2 = AppearanceConfig.createFrom;
const $$createType3 = UpdatesConfig.createFrom;
const $$createType4 = ConfigMetadata.createFrom;
var $$createType5 = (function $$initCreateType5(...args): any {
if ($$createType5 === $$initCreateType5) {
$$createType5 = $$createType6;
const $$createType4 = GitBackupConfig.createFrom;
const $$createType5 = ConfigMetadata.createFrom;
var $$createType6 = (function $$initCreateType6(...args): any {
if ($$createType6 === $$initCreateType6) {
$$createType6 = $$createType7;
}
return $$createType5(...args);
return $$createType6(...args);
});
const $$createType6 = $Create.Map($Create.Any, $Create.Any);
const $$createType7 = HotkeyCombo.createFrom;
const $$createType8 = KeyBinding.createFrom;
const $$createType9 = $Create.Array($$createType8);
const $$createType10 = KeyBindingMetadata.createFrom;
const $$createType11 = GithubConfig.createFrom;
const $$createType12 = GiteaConfig.createFrom;
const $$createType7 = $Create.Map($Create.Any, $Create.Any);
const $$createType8 = HotkeyCombo.createFrom;
const $$createType9 = ThemeColorConfig.createFrom;
const $$createType10 = GithubConfig.createFrom;
const $$createType11 = GiteaConfig.createFrom;

View File

@@ -0,0 +1,79 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* BackupService 提供基于Git的备份功能
* @module
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as models$0 from "../models/models.js";
/**
* HandleConfigChange 处理备份配置变更
*/
export function HandleConfigChange(config: models$0.GitBackupConfig | null): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(395287784, config) as any;
return $resultPromise;
}
/**
* Initialize 初始化备份服务
*/
export function Initialize(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1052437974) as any;
return $resultPromise;
}
/**
* PushToRemote 推送本地更改到远程仓库
*/
export function PushToRemote(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(262644139) as any;
return $resultPromise;
}
/**
* Reinitialize 重新初始化备份服务,用于响应配置变更
*/
export function Reinitialize(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(301562543) as any;
return $resultPromise;
}
/**
* ServiceShutdown 服务关闭时的清理工作
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(422131801) as any;
return $resultPromise;
}
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2900331732, options) as any;
return $resultPromise;
}
/**
* StartAutoBackup 启动自动备份定时器
*/
export function StartAutoBackup(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3035755449) as any;
return $resultPromise;
}
/**
* StopAutoBackup 停止自动备份
*/
export function StopAutoBackup(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2641894021) as any;
return $resultPromise;
}

View File

@@ -10,10 +10,17 @@
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as models$0 from "../models/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as $models from "./models.js";
/**
* Get 获取配置项
*/
@@ -34,6 +41,14 @@ export function GetConfig(): Promise<models$0.AppConfig | null> & { cancel(): vo
return $typingPromise;
}
/**
* MigrateConfig 执行配置迁移
*/
export function MigrateConfig(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(434292783) as any;
return $resultPromise;
}
/**
* ResetConfig 强制重置所有配置为默认值
*/
@@ -42,6 +57,22 @@ export function ResetConfig(): Promise<void> & { cancel(): void } {
return $resultPromise;
}
/**
* ServiceShutdown 关闭服务
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3963562361) as any;
return $resultPromise;
}
/**
* ServiceStartup initializes the service when the application starts
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3311949428, options) as any;
return $resultPromise;
}
/**
* Set 设置配置项
*/
@@ -51,18 +82,18 @@ export function Set(key: string, value: any): Promise<void> & { cancel(): void }
}
/**
* SetDataPathChangeCallback 设置数据路径配置变更回调
* Watch 注册配置变更监听器
*/
export function SetDataPathChangeCallback(callback: any): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(393017412, callback) as any;
export function Watch(path: string, callback: $models.ObserverCallback): Promise<$models.CancelFunc> & { cancel(): void } {
let $resultPromise = $Call.ByID(1143583035, path, callback) as any;
return $resultPromise;
}
/**
* SetHotkeyChangeCallback 设置热键配置变更回调
* WatchWithContext 使用 Context 注册监听器
*/
export function SetHotkeyChangeCallback(callback: any): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(283872321, callback) as any;
export function WatchWithContext(path: string, callback: $models.ObserverCallback): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1454973098, path, callback) as any;
return $resultPromise;
}

View File

@@ -12,28 +12,28 @@ import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as sql$0 from "../../../database/sql/models.js";
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
/**
* GetDB returns the database connection
* RegisterModel 注册模型与表的映射关系
*/
export function GetDB(): Promise<sql$0.DB | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(228760371) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType1($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* OnDataPathChanged handles data path changes
*/
export function OnDataPathChanged(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3652863491) as any;
export function RegisterModel(tableName: string, model: any): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(175397515, tableName, model) as any;
return $resultPromise;
}
// Private type creation functions
const $$createType0 = sql$0.DB.createFrom;
const $$createType1 = $Create.Nullable($$createType0);
/**
* ServiceShutdown shuts down the service when the application closes
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3907893632) as any;
return $resultPromise;
}
/**
* ServiceStartup initializes the service when the application starts
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2067840771, options) as any;
return $resultPromise;
}

View File

@@ -10,10 +10,6 @@
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
/**
* SelectDirectory 打开目录选择对话框
*/
@@ -23,9 +19,9 @@ export function SelectDirectory(): Promise<string> & { cancel(): void } {
}
/**
* SetWindow 设置绑定的窗口
* SelectFile 打开文件选择对话框
*/
export function SetWindow(window: application$0.WebviewWindow | null): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(968177170, window) as any;
export function SelectFile(): Promise<string> & { cancel(): void } {
let $resultPromise = $Call.ByID(37302920) as any;
return $resultPromise;
}

View File

@@ -10,6 +10,9 @@
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as models$0 from "../models/models.js";
@@ -46,14 +49,6 @@ export function GetDocumentByID(id: number): Promise<models$0.Document | null> &
return $typingPromise;
}
/**
* GetFirstDocumentID gets the first active document's ID for frontend initialization
*/
export function GetFirstDocumentID(): Promise<number> & { cancel(): void } {
let $resultPromise = $Call.ByID(2970773833) as any;
return $resultPromise;
}
/**
* ListAllDocumentsMeta lists all active (non-deleted) document metadata
*/
@@ -78,6 +73,14 @@ export function ListDeletedDocumentsMeta(): Promise<(models$0.Document | null)[]
return $typingPromise;
}
/**
* LockDocument 锁定文档,防止删除
*/
export function LockDocument(id: number): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1889494473, id) as any;
return $resultPromise;
}
/**
* RestoreDocument restores a deleted document
*/
@@ -86,6 +89,22 @@ export function RestoreDocument(id: number): Promise<void> & { cancel(): void }
return $resultPromise;
}
/**
* ServiceStartup initializes the service when the application starts
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1474135487, options) as any;
return $resultPromise;
}
/**
* UnlockDocument 解锁文档
*/
export function UnlockDocument(id: number): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(222307930, id) as any;
return $resultPromise;
}
/**
* UpdateDocumentContent updates the content of a document
*/

View File

@@ -10,6 +10,9 @@
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as models$0 from "../models/models.js";
@@ -42,6 +45,14 @@ export function ResetExtensionToDefault(id: models$0.ExtensionID): Promise<void>
return $resultPromise;
}
/**
* ServiceStartup 启动时调用
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(40324057, options) as any;
return $resultPromise;
}
/**
* UpdateExtensionEnabled 更新扩展启用状态
*/

View File

@@ -2,7 +2,7 @@
// This file is automatically generated. DO NOT EDIT
/**
* HotkeyService Windows全局热键服务
* HotkeyService 全局热键服务
* @module
*/
@@ -32,8 +32,8 @@ export function GetCurrentHotkey(): Promise<models$0.HotkeyCombo | null> & { can
/**
* Initialize 初始化热键服务
*/
export function Initialize(app: application$0.App | null): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3671360458, app) as any;
export function Initialize(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3671360458) as any;
return $resultPromise;
}
@@ -48,19 +48,27 @@ export function IsRegistered(): Promise<boolean> & { cancel(): void } {
/**
* RegisterHotkey 注册全局热键
*/
export function RegisterHotkey(hotkey: models$0.HotkeyCombo | null): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1103945691, hotkey) as any;
export function RegisterHotkey(combo: models$0.HotkeyCombo | null): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1103945691, combo) as any;
return $resultPromise;
}
/**
* OnShutdown 关闭服务
* ServiceShutdown 关闭服务
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(157291181) as any;
return $resultPromise;
}
/**
* ServiceStartup 服务启动时初始化
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3079990808, options) as any;
return $resultPromise;
}
/**
* UnregisterHotkey 取消注册全局热键
*/
@@ -72,8 +80,8 @@ export function UnregisterHotkey(): Promise<void> & { cancel(): void } {
/**
* UpdateHotkey 更新热键配置
*/
export function UpdateHotkey(enable: boolean, hotkey: models$0.HotkeyCombo | null): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(823285555, enable, hotkey) as any;
export function UpdateHotkey(enable: boolean, combo: models$0.HotkeyCombo | null): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(823285555, enable, combo) as any;
return $resultPromise;
}

View File

@@ -0,0 +1,31 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* HttpClientService HTTP客户端服务
* @module
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as $models from "./models.js";
/**
* ExecuteRequest 执行HTTP请求
*/
export function ExecuteRequest(request: $models.HttpRequest | null): Promise<$models.HttpResponse | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(3143343977, request) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType1($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
// Private type creation functions
const $$createType0 = $models.HttpResponse.createFrom;
const $$createType1 = $Create.Nullable($$createType0);

View File

@@ -1,33 +1,43 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import * as BackupService from "./backupservice.js";
import * as ConfigService from "./configservice.js";
import * as DatabaseService from "./databaseservice.js";
import * as DialogService from "./dialogservice.js";
import * as DocumentService from "./documentservice.js";
import * as ExtensionService from "./extensionservice.js";
import * as HotkeyService from "./hotkeyservice.js";
import * as HttpClientService from "./httpclientservice.js";
import * as KeyBindingService from "./keybindingservice.js";
import * as MigrationService from "./migrationservice.js";
import * as SelfUpdateService from "./selfupdateservice.js";
import * as StartupService from "./startupservice.js";
import * as SystemService from "./systemservice.js";
import * as TestService from "./testservice.js";
import * as ThemeService from "./themeservice.js";
import * as TranslationService from "./translationservice.js";
import * as TrayService from "./trayservice.js";
import * as WindowService from "./windowservice.js";
export {
BackupService,
ConfigService,
DatabaseService,
DialogService,
DocumentService,
ExtensionService,
HotkeyService,
HttpClientService,
KeyBindingService,
MigrationService,
SelfUpdateService,
StartupService,
SystemService,
TestService,
ThemeService,
TranslationService,
TrayService
TrayService,
WindowService
};
export * from "./models.js";

View File

@@ -10,6 +10,9 @@
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as models$0 from "../models/models.js";
@@ -27,19 +30,13 @@ export function GetAllKeyBindings(): Promise<models$0.KeyBinding[]> & { cancel()
}
/**
* GetKeyBindingConfig 获取完整快捷键配置
* ServiceStartup 启动时调用
*/
export function GetKeyBindingConfig(): Promise<models$0.KeyBindingConfig | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(3804318356) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType3($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2057121990, options) as any;
return $resultPromise;
}
// Private type creation functions
const $$createType0 = models$0.KeyBinding.createFrom;
const $$createType1 = $Create.Array($$createType0);
const $$createType2 = models$0.KeyBindingConfig.createFrom;
const $$createType3 = $Create.Nullable($$createType2);

View File

@@ -42,5 +42,13 @@ export function MigrateDirectory(srcPath: string, dstPath: string): Promise<void
return $resultPromise;
}
/**
* ServiceShutdown 服务关闭
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3472042605) as any;
return $resultPromise;
}
// Private type creation functions
const $$createType0 = $models.MigrationProgress.createFrom;

View File

@@ -5,6 +5,121 @@
// @ts-ignore: Unused imports
import {Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as http$0 from "../../../net/http/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as time$0 from "../../../time/models.js";
/**
* CancelFunc 取消订阅函数
* 调用此函数可以取消对配置的监听
*/
export type CancelFunc = any;
/**
* HttpRequest HTTP请求结构
*/
export class HttpRequest {
"method": string;
"url": string;
"headers": { [_: string]: string };
/**
* json, formdata, urlencoded, text, params, xml, html, javascript, binary
*/
"bodyType"?: string;
"body"?: any;
/** Creates a new HttpRequest instance. */
constructor($$source: Partial<HttpRequest> = {}) {
if (!("method" in $$source)) {
this["method"] = "";
}
if (!("url" in $$source)) {
this["url"] = "";
}
if (!("headers" in $$source)) {
this["headers"] = {};
}
Object.assign(this, $$source);
}
/**
* Creates a new HttpRequest instance from a string or object.
*/
static createFrom($$source: any = {}): HttpRequest {
const $$createField2_0 = $$createType0;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("headers" in $$parsedSource) {
$$parsedSource["headers"] = $$createField2_0($$parsedSource["headers"]);
}
return new HttpRequest($$parsedSource as Partial<HttpRequest>);
}
}
/**
* HttpResponse HTTP响应结构
*/
export class HttpResponse {
/**
* 使用resp.Status()返回完整状态如"200 OK"
*/
"status": string;
/**
* 响应时间(毫秒)
*/
"time": number;
/**
* 请求大小
*/
"requestSize": string;
"body": any;
"headers": http$0.Header;
"timestamp": time$0.Time;
"error"?: any;
/** Creates a new HttpResponse instance. */
constructor($$source: Partial<HttpResponse> = {}) {
if (!("status" in $$source)) {
this["status"] = "";
}
if (!("time" in $$source)) {
this["time"] = 0;
}
if (!("requestSize" in $$source)) {
this["requestSize"] = "";
}
if (!("body" in $$source)) {
this["body"] = null;
}
if (!("headers" in $$source)) {
this["headers"] = ({} as http$0.Header);
}
if (!("timestamp" in $$source)) {
this["timestamp"] = null;
}
Object.assign(this, $$source);
}
/**
* Creates a new HttpResponse instance from a string or object.
*/
static createFrom($$source: any = {}): HttpResponse {
const $$createField4_0 = $$createType1;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("headers" in $$parsedSource) {
$$parsedSource["headers"] = $$createField4_0($$parsedSource["headers"]);
}
return new HttpResponse($$parsedSource as Partial<HttpResponse>);
}
}
/**
* MemoryStats 内存统计信息
*/
@@ -115,6 +230,47 @@ export enum MigrationStatus {
MigrationStatusFailed = "failed",
};
/**
* OSInfo 操作系统信息
*/
export class OSInfo {
"id": string;
"name": string;
"version": string;
"branding": string;
/** Creates a new OSInfo instance. */
constructor($$source: Partial<OSInfo> = {}) {
if (!("id" in $$source)) {
this["id"] = "";
}
if (!("name" in $$source)) {
this["name"] = "";
}
if (!("version" in $$source)) {
this["version"] = "";
}
if (!("branding" in $$source)) {
this["branding"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new OSInfo instance from a string or object.
*/
static createFrom($$source: any = {}): OSInfo {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new OSInfo($$parsedSource as Partial<OSInfo>);
}
}
/**
* ObserverCallback 观察者回调函数
*/
export type ObserverCallback = any;
/**
* SelfUpdateResult 自我更新结果
*/
@@ -197,3 +353,65 @@ export class SelfUpdateResult {
return new SelfUpdateResult($$parsedSource as Partial<SelfUpdateResult>);
}
}
/**
* SystemInfo 系统信息
*/
export class SystemInfo {
"os": string;
"arch": string;
"debug": boolean;
"osInfo": OSInfo | null;
"platformInfo": { [_: string]: any };
/** Creates a new SystemInfo instance. */
constructor($$source: Partial<SystemInfo> = {}) {
if (!("os" in $$source)) {
this["os"] = "";
}
if (!("arch" in $$source)) {
this["arch"] = "";
}
if (!("debug" in $$source)) {
this["debug"] = false;
}
if (!("osInfo" in $$source)) {
this["osInfo"] = null;
}
if (!("platformInfo" in $$source)) {
this["platformInfo"] = {};
}
Object.assign(this, $$source);
}
/**
* Creates a new SystemInfo instance from a string or object.
*/
static createFrom($$source: any = {}): SystemInfo {
const $$createField3_0 = $$createType5;
const $$createField4_0 = $$createType6;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("osInfo" in $$parsedSource) {
$$parsedSource["osInfo"] = $$createField3_0($$parsedSource["osInfo"]);
}
if ("platformInfo" in $$parsedSource) {
$$parsedSource["platformInfo"] = $$createField4_0($$parsedSource["platformInfo"]);
}
return new SystemInfo($$parsedSource as Partial<SystemInfo>);
}
}
// Private type creation functions
const $$createType0 = $Create.Map($Create.Any, $Create.Any);
var $$createType1 = (function $$initCreateType1(...args): any {
if ($$createType1 === $$initCreateType1) {
$$createType1 = $$createType3;
}
return $$createType1(...args);
});
const $$createType2 = $Create.Array($Create.Any);
const $$createType3 = $Create.Map($Create.Any, $$createType2);
const $$createType4 = OSInfo.createFrom;
const $$createType5 = $Create.Nullable($$createType4);
const $$createType6 = $Create.Map($Create.Any, $Create.Any);

View File

@@ -34,6 +34,18 @@ export function GetMemoryStats(): Promise<$models.MemoryStats> & { cancel(): voi
return $typingPromise;
}
/**
* GetSystemInfo 获取系统环境信息
*/
export function GetSystemInfo(): Promise<$models.SystemInfo | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(2629436820) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType2($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* TriggerGC 手动触发垃圾回收
*/
@@ -44,3 +56,5 @@ export function TriggerGC(): Promise<void> & { cancel(): void } {
// Private type creation functions
const $$createType0 = $models.MemoryStats.createFrom;
const $$createType1 = $models.SystemInfo.createFrom;
const $$createType2 = $Create.Nullable($$createType1);

View File

@@ -0,0 +1,55 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* TestService 测试服务 - 仅在开发环境使用
* @module
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
/**
* ClearAll 清除所有测试状态
*/
export function ClearAll(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2179720854) as any;
return $resultPromise;
}
/**
* ServiceStartup 服务启动时调用
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(617408198, options) as any;
return $resultPromise;
}
/**
* TestBadge 测试Badge功能
*/
export function TestBadge(text: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(4242952145, text) as any;
return $resultPromise;
}
/**
* TestNotification 测试通知功能
*/
export function TestNotification(title: string, subtitle: string, body: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1697553289, title, subtitle, body) as any;
return $resultPromise;
}
/**
* TestUpdateNotification 测试更新通知
*/
export function TestUpdateNotification(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3091730060) as any;
return $resultPromise;
}

View File

@@ -0,0 +1,80 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* ThemeService 主题服务
* @module
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as models$0 from "../models/models.js";
/**
* GetAllThemes 获取所有主题
*/
export function GetAllThemes(): Promise<(models$0.Theme | null)[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(2425053076) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType2($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetThemeByID 根据ID或名称获取主题
* 如果 id > 0按ID查询如果 id = 0按名称查询
*/
export function GetThemeByIdOrName(id: number, ...name: string[]): Promise<models$0.Theme | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(127385338, id, name) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType1($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* ResetTheme 重置主题为预设配置
*/
export function ResetTheme(id: number, ...name: string[]): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1806334457, id, name) as any;
return $resultPromise;
}
/**
* ServiceShutdown 服务关闭
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1676749034) as any;
return $resultPromise;
}
/**
* ServiceStartup 服务启动时初始化
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2915959937, options) as any;
return $resultPromise;
}
/**
* UpdateTheme 更新主题
*/
export function UpdateTheme(id: number, colors: models$0.ThemeColorConfig): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(70189749, id, colors) as any;
return $resultPromise;
}
// Private type creation functions
const $$createType0 = models$0.Theme.createFrom;
const $$createType1 = $Create.Nullable($$createType0);
const $$createType2 = $Create.Array($$createType1);

View File

@@ -14,27 +14,6 @@ import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// @ts-ignore: Unused imports
import * as translator$0 from "../common/translator/models.js";
/**
* GetAvailableTranslators 获取所有可用翻译器类型
* @returns {[]string} 翻译器类型列表
*/
export function GetAvailableTranslators(): Promise<string[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(1186597995) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType0($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetStandardLanguageCode 获取标准化的语言代码
*/
export function GetStandardLanguageCode(translatorType: translator$0.TranslatorType, languageCode: string): Promise<string> & { cancel(): void } {
let $resultPromise = $Call.ByID(1158131995, translatorType, languageCode) as any;
return $resultPromise;
}
/**
* GetTranslatorLanguages 获取翻译器的语言列表
* @param {string} translatorType - 翻译器类型 ("google", "bing", "youdao", "deepl")
@@ -43,6 +22,19 @@ export function GetStandardLanguageCode(translatorType: translator$0.TranslatorT
*/
export function GetTranslatorLanguages(translatorType: translator$0.TranslatorType): Promise<{ [_: string]: translator$0.LanguageInfo }> & { cancel(): void } {
let $resultPromise = $Call.ByID(3976114458, translatorType) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType1($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetTranslators 获取所有可用翻译器类型
* @returns {[]string} 翻译器类型列表
*/
export function GetTranslators(): Promise<string[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(3720069432) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType2($result);
}) as any;
@@ -73,6 +65,6 @@ export function TranslateWith(text: string, $from: string, to: string, translato
}
// Private type creation functions
const $$createType0 = $Create.Array($Create.Any);
const $$createType1 = translator$0.LanguageInfo.createFrom;
const $$createType2 = $Create.Map($Create.Any, $$createType1);
const $$createType0 = translator$0.LanguageInfo.createFrom;
const $$createType1 = $Create.Map($Create.Any, $$createType0);
const $$createType2 = $Create.Array($Create.Any);

View File

@@ -10,9 +10,13 @@
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
/**
* AutoShowHide 自动显示/隐藏主窗口
*/
export function AutoShowHide(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(4044219428) as any;
return $resultPromise;
}
/**
* HandleWindowClose 处理窗口关闭事件
@@ -38,14 +42,6 @@ export function MinimizeButtonClicked(): Promise<void> & { cancel(): void } {
return $resultPromise;
}
/**
* SetAppReferences 设置应用引用
*/
export function SetAppReferences(app: application$0.App | null, mainWindow: application$0.WebviewWindow | null): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3544515719, app, mainWindow) as any;
return $resultPromise;
}
/**
* ShouldMinimizeToTray 检查是否应该最小化到托盘
*/

View File

@@ -0,0 +1,62 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* WindowService 窗口管理服务
* @module
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
/**
* GetOpenWindows 获取所有打开的文档窗口
*/
export function GetOpenWindows(): Promise<application$0.Window[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(1464997251) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType0($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* IsDocumentWindowOpen 检查指定文档的窗口是否已打开
*/
export function IsDocumentWindowOpen(documentID: number): Promise<boolean> & { cancel(): void } {
let $resultPromise = $Call.ByID(1735611839, documentID) as any;
return $resultPromise;
}
/**
* OpenDocumentWindow 为指定文档ID打开新窗口
*/
export function OpenDocumentWindow(documentID: number): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(494716471, documentID) as any;
return $resultPromise;
}
/**
* ServiceShutdown 实现服务关闭接口
*/
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(202192783) as any;
return $resultPromise;
}
/**
* ServiceStartup 服务启动时初始化
*/
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2432987694, options) as any;
return $resultPromise;
}
// Private type creation functions
const $$createType0 = $Create.Array($Create.Any);

View File

@@ -1,8 +1,11 @@
/* eslint-disable */
// @ts-nocheck
// biome-ignore lint: disable
// oxlint-disable
// ------
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}
/* prettier-ignore */
@@ -11,10 +14,14 @@ declare module 'vue' {
BlockLanguageSelector: typeof import('./src/components/toolbar/BlockLanguageSelector.vue')['default']
DocumentSelector: typeof import('./src/components/toolbar/DocumentSelector.vue')['default']
LinuxTitleBar: typeof import('./src/components/titlebar/LinuxTitleBar.vue')['default']
LoadingScreen: typeof import('./src/components/loading/LoadingScreen.vue')['default']
MacOSTitleBar: typeof import('./src/components/titlebar/MacOSTitleBar.vue')['default']
MemoryMonitor: typeof import('./src/components/monitor/MemoryMonitor.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
TabContainer: typeof import('./src/components/tabs/TabContainer.vue')['default']
TabContextMenu: typeof import('./src/components/tabs/TabContextMenu.vue')['default']
TabItem: typeof import('./src/components/tabs/TabItem.vue')['default']
Toolbar: typeof import('./src/components/toolbar/Toolbar.vue')['default']
WindowsTitleBar: typeof import('./src/components/titlebar/WindowsTitleBar.vue')['default']
WindowTitleBar: typeof import('./src/components/titlebar/WindowTitleBar.vue')['default']

View File

@@ -0,0 +1,149 @@
import {defineConfig} from 'vitepress'
const base = '/'
// https://vitepress.dev/reference/site-config
export default defineConfig({
base: base,
title: "voidraft",
description: "An elegant text snippet recording tool designed for developers.",
srcDir: 'src',
assetsDir: 'assets',
cacheDir: './.vitepress/cache',
outDir: './.vitepress/dist',
srcExclude: [],
ignoreDeadLinks: false,
head: [
["link", {rel: "icon", type: "image/png", href: "/icon/favicon-96x96.png", sizes: "96x96"}],
["link", {rel: "icon", type: "image/svg+xml", href: "/icon/favicon.svg"}],
["link", {rel: "shortcut icon", href: "/icon/favicon.ico"}],
["link", {rel: "apple-touch-icon", sizes: "180x180", href: "/icon/apple-touch-icon.png"}],
["meta", {name: "apple-mobile-web-app-title", content: "voidraft"}],
["link", {rel: "manifest", href: "/icon/site.webmanifest"}],
['meta', {name: 'viewport', content: 'width=device-width,initial-scale=1'}]
],
// 国际化配置
locales: {
root: {
label: 'English',
lang: 'en-US',
description: 'An elegant text snippet recording tool designed for developers.',
themeConfig: {
logo: '/icon/logo.png',
siteTitle: 'voidraft',
nav: [
{text: 'Home', link: '/'},
{text: 'Guide', link: '/guide/introduction'}
],
sidebar: {
'/guide/': [
{
text: 'Getting Started',
items: [
{text: 'Introduction', link: '/guide/introduction'},
{text: 'Installation', link: '/guide/installation'},
{text: 'Quick Start', link: '/guide/getting-started'}
]
},
{
text: 'Features',
items: [
{text: 'Overview', link: '/guide/features'}
]
}
]
},
socialLinks: [
{icon: 'github', link: 'https://github.com/landaiqing/voidraft'}
],
outline: {
label: 'On this page'
},
lastUpdated: {
text: 'Last updated'
},
docFooter: {
prev: 'Previous',
next: 'Next'
},
darkModeSwitchLabel: 'Appearance',
sidebarMenuLabel: 'Menu',
returnToTopLabel: 'Return to top',
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2025-present landaiqing'
}
}
},
zh: {
label: '简体中文',
lang: 'zh-CN',
link: '/zh/',
description: '一个为开发者设计的优雅文本片段记录工具',
themeConfig: {
logo: '/icon/logo.png',
siteTitle: 'voidraft',
nav: [
{text: '首页', link: '/zh/'},
{text: '指南', link: '/zh/guide/introduction'}
],
sidebar: {
'/zh/guide/': [
{
text: '开始使用',
items: [
{text: '简介', link: '/zh/guide/introduction'},
{text: '安装', link: '/zh/guide/installation'},
{text: '快速开始', link: '/zh/guide/getting-started'},
{text: '界面总览', link: '/zh/guide/ui-overview'},
{text: '块语法与结构', link: '/zh/guide/block-syntax'}
]
},
{
text: '编辑与效率',
items: [
{text: '键盘快捷键', link: '/zh/guide/keyboard-shortcuts'},
{text: '多窗口与标签页', link: '/zh/guide/multiwindow-tabs'},
{text: '扩展与插件', link: '/zh/guide/extensions'},
{text: 'HTTP 客户端', link: '/zh/guide/http-client'}
]
},
{
text: '个性化与数据',
items: [
{text: '设置与配置', link: '/zh/guide/settings'},
{text: '主题与外观', link: '/zh/guide/themes'},
{text: '备份与更新', link: '/zh/guide/backup-update'}
]
},
{
text: '问题处理',
items: [
{text: '常见问题与故障排查', link: '/zh/guide/troubleshooting'}
]
}
]
},
socialLinks: [
{icon: 'github', link: 'https://github.com/landaiqing/voidraft'}
],
outline: {
label: '本页目录'
},
lastUpdated: {
text: '最后更新'
},
docFooter: {
prev: '上一页',
next: '下一页'
},
darkModeSwitchLabel: '外观',
sidebarMenuLabel: '菜单',
returnToTopLabel: '返回顶部',
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2025-present landaiqing'
}
}
}
}
})

View File

@@ -0,0 +1,6 @@
@import "style/var.css";
@import "style/blur.css";
@import "style/badge.css";
@import "style/grid.css";

View File

@@ -0,0 +1,17 @@
// https://vitepress.dev/guide/custom-theme
import { h } from 'vue'
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import './index.css'
export default {
extends: DefaultTheme,
Layout: () => {
return h(DefaultTheme.Layout, null, {
// https://vitepress.dev/guide/extending-default-theme#layout-slots
})
},
enhanceApp({ app, router, siteData }) {
// ...
}
} satisfies Theme

View File

@@ -0,0 +1,21 @@
/* 提示框背景颜色 */
:root {
--vp-custom-block-tip-bg: var(--vp-c-green-soft);
}
/* 提示框 */
.custom-block.tip {
border-color: var(--vp-c-green-2);
}
/* 警告框 */
.custom-block.warning {
/* border-color: #d97706; */
border-color: var(--vp-c-yellow-2);
}
/* 危险框 */
.custom-block.danger {
/* border-color: #f43f5e; */
border-color: var(--vp-c-red-2);
}

View File

@@ -0,0 +1,73 @@
/* .vitepress/theme/style/blur.css */
:root {
/* 首页导航 */
.VPNavBar {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
/* 文档页导航两侧 */
.VPNavBar:not(.home) {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
@media (min-width: 960px) {
/* 文档页导航两侧 */
.VPNavBar:not(.home) {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
/* 首页下滑后导航两侧 */
.VPNavBar:not(.has-sidebar):not(.home.top) {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
}
@media (min-width: 960px) {
/* 文档页导航中间 */
.VPNavBar:not(.home.top) .content-body {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
/* 首页下滑后导航中间 */
.VPNavBar:not(.has-sidebar):not(.home.top) .content-body {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
}
/* 分割线 */
@media (min-width: 960px) {
/* 文档页分割线 */
.VPNavBar:not(.home.top) .divider-line {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
/* 首页分割线 */
.VPNavBar:not(.has-sidebar):not(.home.top) .divider {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
}
/* 搜索框 VPNavBarSearchButton.vue */
.DocSearch-Button {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
}
/* 移动端大纲栏 */
.VPLocalNav {
background-color: rgba(255, 255, 255, 0);
backdrop-filter: blur(10px);
/* 隐藏分割线 */
/* border-bottom: 5px solid var(--vp-c-gutter); */
border-bottom: 0px;
}
}

View File

@@ -0,0 +1,40 @@
/**
* Grid Background
* 网格背景样式 - 为文档页面添加简约的网格背景
* -------------------------------------------------------------------------- */
.VPDoc,
.VPHome {
position: relative;
}
.VPDoc::before,
.VPHome::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
pointer-events: none;
}
/* 亮色模式网格 */
:root:not(.dark) .VPDoc::before,
:root:not(.dark) .VPHome::before {
background-image:
linear-gradient(rgba(0, 0, 0, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px);
background-size: 60px 60px;
}
/* 暗色模式网格 */
.dark .VPDoc::before,
.dark .VPHome::before {
background-image:
linear-gradient(rgba(255, 255, 255, 0.06) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.06) 1px, transparent 1px);
background-size: 60px 60px;
}

View File

@@ -0,0 +1,137 @@
/**
* Customize default theme styling by overriding CSS variables:
* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
*/
/**
* Colors
*
* Each colors have exact same color scale system with 3 levels of solid
* colors with different brightness, and 1 soft color.
*
* - `XXX-1`: The most solid color used mainly for colored text. It must
* satisfy the contrast ratio against when used on top of `XXX-soft`.
*
* - `XXX-2`: The color used mainly for hover state of the button.
*
* - `XXX-3`: The color for solid background, such as bg color of the button.
* It must satisfy the contrast ratio with pure white (#ffffff) text on
* top of it.
*
* - `XXX-soft`: The color used for subtle background such as custom container
* or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
* on top of it.
*
* The soft color must be semi transparent alpha channel. This is crucial
* because it allows adding multiple "soft" colors on top of each other
* to create an accent, such as when having inline code block inside
* custom containers.
*
* - `default`: The color used purely for subtle indication without any
* special meanings attached to it such as bg color for menu hover state.
*
* - `brand`: Used for primary brand colors, such as link text, button with
* brand theme, etc.
*
* - `tip`: Used to indicate useful information. The default theme uses the
* brand color for this by default.
*
* - `warning`: Used to indicate warning to the users. Used in custom
* container, badges, etc.
*
* - `danger`: Used to show error, or dangerous message to the users. Used
* in custom container, badges, etc.
* -------------------------------------------------------------------------- */
:root {
--vp-c-default-1: var(--vp-c-gray-1);
--vp-c-default-2: var(--vp-c-gray-2);
--vp-c-default-3: var(--vp-c-gray-3);
--vp-c-default-soft: var(--vp-c-gray-soft);
--vp-c-brand-1: var(--vp-c-indigo-1);
--vp-c-brand-2: var(--vp-c-indigo-2);
--vp-c-brand-3: var(--vp-c-indigo-3);
--vp-c-brand-soft: var(--vp-c-indigo-soft);
--vp-c-tip-1: var(--vp-c-brand-1);
--vp-c-tip-2: var(--vp-c-brand-2);
--vp-c-tip-3: var(--vp-c-brand-3);
--vp-c-tip-soft: var(--vp-c-brand-soft);
--vp-c-warning-1: var(--vp-c-yellow-1);
--vp-c-warning-2: var(--vp-c-yellow-2);
--vp-c-warning-3: var(--vp-c-yellow-3);
--vp-c-warning-soft: var(--vp-c-yellow-soft);
--vp-c-danger-1: var(--vp-c-red-1);
--vp-c-danger-2: var(--vp-c-red-2);
--vp-c-danger-3: var(--vp-c-red-3);
--vp-c-danger-soft: var(--vp-c-red-soft);
}
/**
* Component: Button
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: transparent;
--vp-button-brand-text: var(--vp-c-white);
--vp-button-brand-bg: var(--vp-c-brand-3);
--vp-button-brand-hover-border: transparent;
--vp-button-brand-hover-text: var(--vp-c-white);
--vp-button-brand-hover-bg: var(--vp-c-brand-2);
--vp-button-brand-active-border: transparent;
--vp-button-brand-active-text: var(--vp-c-white);
--vp-button-brand-active-bg: var(--vp-c-brand-1);
}
/**
* Component: Home
* -------------------------------------------------------------------------- */
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(
120deg,
#bd34fe 30%,
#41d1ff
);
--vp-home-hero-image-background-image: linear-gradient(
-45deg,
#bd34fe 50%,
#47caff 50%
);
--vp-home-hero-image-filter: blur(44px);
}
@media (min-width: 640px) {
:root {
--vp-home-hero-image-filter: blur(56px);
}
}
@media (min-width: 960px) {
:root {
--vp-home-hero-image-filter: blur(68px);
}
}
/**
* Component: Custom Block
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-tip-border: transparent;
--vp-custom-block-tip-text: var(--vp-c-text-1);
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
}
/**
* Component: Algolia
* -------------------------------------------------------------------------- */
.DocSearch {
--docsearch-primary-color: var(--vp-c-brand-1) !important;
}

View File

@@ -0,0 +1,163 @@
# Features
Explore the powerful features that make voidraft a great tool for developers.
## Block-Based Editing
voidraft's core feature is its block-based editing system:
- Each block can have a different programming language
- Blocks are separated by delimiters (`∞∞∞language`)
- Navigate quickly between blocks
- Format each block independently
## Syntax Highlighting
Professional syntax highlighting for 30+ languages:
- Automatic language detection
- Customizable color schemes
- Support for nested languages
- Code folding support
## HTTP Client
Built-in HTTP client for API testing:
### Request Types
- GET, POST, PUT, DELETE, PATCH
- Custom headers
- Multiple body formats: JSON, FormData, URL-encoded, XML, Text
### Request Variables
Define and reuse variables:
```http
@var {
baseUrl: "https://api.example.com",
token: "your-api-token"
}
GET "{{baseUrl}}/users" {
authorization: "Bearer {{token}}"
}
```
### Response Handling
- View formatted JSON responses
- See response time and size
- Inspect headers
- Save responses for later
## Code Formatting
Integrated Prettier support:
- Format on save (optional)
- Format selection or entire block
- Supports JavaScript, TypeScript, CSS, HTML, JSON, and more
- Customizable formatting rules
## Editor Extensions
### VSCode-Style Search
- Find and replace with regex support
- Case-sensitive and whole word options
- Search across all blocks
### Minimap
- Bird's-eye view of your document
- Quick navigation
- Customizable size and position
### Rainbow Brackets
- Color-coded bracket pairs
- Easier to match brackets
- Customizable colors
### Color Picker
- Visual color selection
- Supports hex, RGB, HSL
- Live preview
### Translation Tool
- Translate selected text
- Multiple language support
- Quick keyboard access
### Text Highlighting
- Highlight important text
- Multiple highlight colors
- Persistent highlights
## Multi-Window Support
Work efficiently with multiple windows:
- Each window is independent
- Separate documents
- Synchronized settings
- Window state persistence
## Theme Customization
Full control over editor appearance:
### Built-in Themes
- Dark mode
- Light mode
- Auto-switch based on system
### Custom Themes
- Create your own themes
- Customize every color
- Save and share themes
- Import community themes
## Auto-Update System
Stay current with automatic updates:
- Background update checks
- Notification of new versions
- One-click update
- Update history
- Support for multiple update sources (GitHub, Gitea)
## Data Backup
Secure your data with Git-based backup:
- Automatic backups
- Manual backup triggers
- Support for GitHub and Gitea
- Multiple authentication methods (SSH, Token, Password)
- Configurable backup intervals
## Keyboard Shortcuts
Extensive keyboard support:
- Customizable shortcuts
- Vim/Emacs keybindings (planned)
- Quick command palette
- Context-aware shortcuts
## Performance
Built for speed:
- Fast startup time
- Smooth scrolling
- Efficient memory usage
- Large file support
## Privacy & Security
Your data is safe:
- Local-first storage
- Optional cloud backup
- No telemetry or tracking
- Open source codebase

View File

@@ -0,0 +1,107 @@
# Getting Started
Learn the basics of using voidraft and create your first document.
## The Editor Interface
When you open voidraft, you'll see:
- **Main Editor**: The central area where you write and edit
- **Toolbar**: Quick access to common actions
- **Status Bar**: Shows current block language and other info
## Creating Code Blocks
voidraft uses a block-based editing system. Each block can have a different language:
1. Press `Ctrl+Enter` to create a new block
2. Type `∞∞∞` followed by a language name (e.g., `∞∞∞javascript`)
3. Start coding in that block
### Supported Languages
voidraft supports 30+ programming languages including:
- JavaScript, TypeScript
- Python, Go, Rust
- HTML, CSS, Sass
- SQL, YAML, JSON
- And many more...
## Basic Operations
### Navigation
- `Ctrl+Up/Down`: Move between blocks
- `Ctrl+Home/End`: Jump to first/last block
- `Ctrl+F`: Search within document
### Editing
- `Ctrl+D`: Duplicate current line
- `Ctrl+/`: Toggle comment
- `Alt+Up/Down`: Move line up/down
- `Ctrl+Shift+F`: Format code (if language supports Prettier)
### Block Management
- `Ctrl+Enter`: Create new block
- `Ctrl+Shift+Enter`: Create block above
- `Alt+Delete`: Delete current block
## Using the HTTP Client
voidraft includes a built-in HTTP client for testing APIs:
1. Create a block with HTTP language
2. Write your HTTP request:
```http
POST "https://api.example.com/users" {
content-type: "application/json"
@json {
name: "John Doe",
email: "john@example.com"
}
}
```
3. Click the run button to execute the request
4. View the response inline
## Multi-Window Support
Work on multiple documents simultaneously:
1. Go to `File > New Window` (or `Ctrl+Shift+N`)
2. Each window is independent
3. Changes are saved automatically
## Customizing Themes
Personalize your editor:
1. Open Settings (`Ctrl+,`)
2. Go to Appearance
3. Choose a theme or create your own
4. Customize colors to your preference
## Keyboard Shortcuts
Learn essential shortcuts:
| Action | Shortcut |
|--------|----------|
| New Window | `Ctrl+Shift+N` |
| Search | `Ctrl+F` |
| Replace | `Ctrl+H` |
| Format Code | `Ctrl+Shift+F` |
| Toggle Theme | `Ctrl+Shift+T` |
| Command Palette | `Ctrl+Shift+P` |
## Next Steps
Now that you know the basics:
- Explore [Features](/guide/features) in detail

View File

@@ -0,0 +1,63 @@
# Installation
This guide will help you install voidraft on your system.
## System Requirements
- **Operating System**: Windows 10 or later (macOS and Linux support planned)
- **RAM**: 4GB minimum, 8GB recommended
- **Disk Space**: 200MB free space
## Download
Visit the [releases page](https://github.com/landaiqing/voidraft/releases) and download the latest version for your platform:
- **Windows**: `voidraft-windows-amd64-installer.exe`
## Installation Steps
### Windows
1. Download the installer from the releases page
2. Run the `voidraft-windows-amd64-installer.exe` file
3. Follow the installation wizard
4. Launch voidraft from the Start menu or desktop shortcut
## First Launch
When you first launch voidraft:
1. The application will create a data directory to store your documents
2. You'll see the main editor interface with a welcome block
3. Start typing or create your first code block!
## Configuration
voidraft stores its configuration and data in:
- **Windows**: `%APPDATA%/voidraft/`
You can customize various settings including:
- Editor theme (dark/light mode)
- Code formatting preferences
- Backup settings
- Keyboard shortcuts
## Updating
voidraft includes an auto-update feature that will notify you when new versions are available. You can:
- Check for updates manually from the settings
- Enable automatic updates
- Choose your preferred update source
## Troubleshooting
If you encounter any issues during installation:
1. Make sure you have administrator privileges
2. Check that your antivirus isn't blocking the installation
3. Visit our [GitHub issues](https://github.com/landaiqing/voidraft/issues) page for help
Next: [Getting Started →](/guide/getting-started)

View File

@@ -0,0 +1,50 @@
# Introduction
Welcome to voidraft - an elegant text snippet recording tool designed specifically for developers.
## What is voidraft?
voidraft is a modern desktop application that helps developers manage text snippets, code blocks, API responses, meeting notes, and daily to-do lists. It provides a smooth and elegant editing experience with powerful features tailored for development workflows.
## Key Features
### Block-Based Editing
voidraft uses a unique block-based editing system inspired by Heynote. You can split your content into independent code blocks, each with:
- Different programming language settings
- Syntax highlighting
- Independent formatting
- Easy navigation between blocks
### Developer Tools
- **HTTP Client**: Test APIs directly within the editor
- **Code Formatting**: Built-in Prettier support for multiple languages
- **Syntax Highlighting**: Support for 30+ programming languages
- **Auto Language Detection**: Automatically recognizes code block language types
### Customization
- **Custom Themes**: Create and save your own editor themes
- **Extensions**: Rich set of editor extensions including minimap, rainbow brackets, color picker, and more
- **Multi-Window**: Work on multiple documents simultaneously
### Data Management
- **Git-Based Backup**: Automatic backup using Git repositories
- **Cloud Sync**: Sync your data across devices
- **Auto-Update**: Stay up-to-date with the latest features
## Why voidraft?
- **Developer-Focused**: Built with developers' needs in mind
- **Modern Stack**: Uses cutting-edge technologies (Wails3, Vue 3, CodeMirror 6)
- **Cross-Platform**: Works on Windows (macOS and Linux support planned)
- **Open Source**: MIT licensed, community-driven development
## Getting Started
Ready to start? Download the latest version from our [releases page](https://github.com/landaiqing/voidraft/releases) or continue reading the documentation to learn more.
Next: [Installation →](/guide/installation)

View File

@@ -0,0 +1,56 @@
---
layout: home
hero:
name: "voidraft"
text: "An elegant text snippet recording tool"
tagline: Designed for developers, built with modern technology
image:
src: /img/hero.png
alt: "voidraft"
actions:
- theme: brand
text: Get Started
link: https://github.com/landaiqing/voidraft/releases
- theme: alt
text: Documentation
link: /guide/introduction
features:
- icon: 📝
title: Block-Based Editing
details: Split your content into independent code blocks, each with different language settings. Inspired by Heynote's innovative design philosophy.
- icon: 🎨
title: Syntax Highlighting
details: Built-in support for 30+ programming languages with automatic language detection and Prettier integration for code formatting.
- icon: 🌐
title: HTTP Client
details: Integrated HTTP client with support for multiple request formats including JSON, FormData, XML, and more. Test APIs directly within the editor.
- icon: 🎯
title: Multi-Window Support
details: Work on multiple documents simultaneously with independent windows. Each window maintains its own state and configuration.
- icon: 🎭
title: Customizable Themes
details: Full theme customization support with dark/light modes. Create and save your own editor themes to match your preferences.
- icon: 🔧
title: Rich Extensions
details: VSCode-style search and replace, rainbow brackets, minimap, color picker, translation tool, text highlighting, and more.
- icon: 🔄
title: Auto-Update System
details: Built-in self-update mechanism with support for multiple update sources. Stay up-to-date with the latest features and improvements.
- icon: ☁️
title: Git-Based Backup
details: Automatic data backup using Git repositories. Supports GitHub, Gitea, with multiple authentication methods including SSH and tokens.
- icon: ⚡
title: Modern Architecture
details: Built with Wails3, Vue 3, and CodeMirror 6. Cross-platform desktop application with native performance and modern UI.
---

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@@ -0,0 +1,21 @@
{
"name": "voidraft",
"short_name": "voidraft",
"icons": [
{
"src": "/img/web-app-manifest-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/img/web-app-manifest-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,60 @@
# 备份与更新
![备份更新占位](/img/placeholder-backup.png)
> 替换为备份设置、推送状态、更新提示的截图。
## Git 备份
`BackupService``dataPath` 转化为 Git 仓库,并提供自动/手动推送。
### 初始化
1. 在设置 > 备份中开启「启用备份」。
2. 填写远程仓库 URLHTTPS 或 SSH
3. 选择认证方式:
- **Token**:适用于 GitHub/Gitea https 仓库。
- **SSH Key**:指定私钥路径和 passphrase。
- **用户名/密码**:适合自建 HTTP 仓库。
4. 点击“测试连接”(按钮在计划中,可先在终端测试)。
### 自动备份
- 勾选 “自动备份” + 设置 `BackupInterval`(分钟)。
- 服务会创建 ticker 定时 `git add -> commit -> push`
- Commit 消息形如 `Auto backup <timestamp>`,包含 `voidraft.db`, `extensions.json`, `config.json`, `voidraft_data.bin`
### 手动推送
- 打开工具栏消息中心或设置页点击“立即推送”。
- `backupStore.pushToRemote` 会显示状态气泡(成功/失败提示 3~5 秒)。
### 常见问题
| 提示 | 解决 |
| --- | --- |
| `repository not found` | 检查 Repo URL 与权限,必要时创建空仓库 |
| `authentication required` | 选择正确认证方式,确认 token scope需 repo 权限) |
| `auto backup stopped` | 查看日志,可能是网络不通或凭据失效;修改配置后服务会自动重启 |
## 自动更新
`SelfUpdateService` 负责检测、下载、应用新版。
### 检查更新
- 启动时若勾选 “自动更新” 会自动检查。
- 也可在设置 > 更新点击 “检查更新” 或在工具栏更新图标处触发。
- 服务优先访问 `primarySource`,失败时回退 `backupSource`
### 下载与应用
1. 检测到更新后,界面提示版本号与变更信息(从 Release Notes 获取)。
2. 点击 “下载并安装” 后,后台执行下载,完成后提示“准备重启”。
3. 选择 “立即重启” 将调用 `RestartApplication`,自动重新打开上次的文档。
4. 若启用了 “更新前备份”,在下载前会触发一次 Git push。
### 失败处理
| 场景 | 建议 |
| --- | --- |
| 下载失败 | 检查网络/代理,切换至备用源 |
| 校验失败 | 删除 `%LOCALAPPDATA%/voidraft/update-cache` 再重试 |
| 应用后无法启动 | 从 Git 备份回滚数据,下载旧版本安装包覆盖 |
## 发布渠道
- 官方 GitHub Releases`https://github.com/landaiqing/voidraft/releases`
- 自建 Gitea`https://git.landaiqing.cn/landaiqing/voidraft`
- 可在设置中替换 Owner/Repo/BaseURL以指向企业私有镜像。
> 建议将备份仓库设为私有,并在更新前后验证数据完整性。若要接入 S3/OSS 等备份方式,可关注 roadmap 或自行扩展。

View File

@@ -0,0 +1,78 @@
# 块语法与结构
![块语法占位](/img/placeholder-block-flow.png)
> 替换为展示分隔符(`∞∞∞language`)、块内容、语言标签的截图。
## 结构定义
每个块都由 **分隔符 + 内容** 组成:
```
∞∞∞language[-a]\n
<内容>
```
- `language``lang-parser/languages.ts` 中的 token例如 `text``javascript``python``md``http``math``sql`
- `-a`:可选自动检测后缀,表示忽略显式语言,由 `lang-detect/autodetect.ts` 根据内容猜测。
- 内容允许空行;块之间无需额外空格。
`parser.ts` 会将块解析为:
```ts
{
language: { name: "javascript", auto: false },
delimiter: { from, to },
content: { from, to },
range: { from, to }
}
```
这些字段供格式化、HTTP 运行、块操作等扩展示例使用。
## 快捷命令
| 命令 | 默认快捷键 | 说明 |
| --- | --- | --- |
| blockAddAfterCurrent | `Ctrl+Enter` | 插入新块(下方) |
| blockAddBeforeCurrent | `Ctrl+Shift+Enter` | 插入新块(上方) |
| blockGotoPrevious/Next | `Alt+↑ / Alt+↓` | 在块之间跳转 |
| blockSelectAll | `Ctrl+Shift+A` | 选中当前块(含分隔符) |
| blockDelete | `Alt+Delete` | 删除整个块 |
| blockMoveUp/Down | `Ctrl+Shift+↑ / Ctrl+Shift+↓` | 重排块顺序 |
| blockFormat | `Ctrl+Shift+F` | 针对当前块执行 Prettier |
## 语言与能力矩阵
| 语言 | 适配特性 |
| --- | --- |
| `text`/`note` | 基础文本,没有特殊扩展 |
| `md` | Markdown 预览、checkbox、高亮 |
| `javascript`/`typescript`/`json` | Prettier 格式化、彩虹括号、折叠、颜色选择 |
| `go`/`rust`/`python`/`java` | 高亮、折叠、自动缩进、语法跳转 |
| `http` | HTTP DSL、变量、响应插入详见 [HTTP 客户端](/zh/guide/http-client)|
| `math` | `mathBlock` 运行器,支持 `prev` 引用上一次结果 |
| `sql`/`yaml`/`toml` | 语法高亮、格式化(由 Prettier/插件支持) |
> 若需要不在列表中的语言,可先使用 `text` 块输入,再在工具栏搜索语言名;也可以在 `lang-parser/languages.ts` 中添加条目。
## 自动检测策略
- 当分隔符以 `∞∞∞text-a` 写成时,`AUTO_DETECT_SUFFIX` 生效,`lang-detect` 会基于内容统计 + Levenshtein 距离预测语言。
- 自动结果会写入块状态,但不会覆盖分隔符原文,因此可通过工具栏明确指定。
## 特殊块
### HTTP 块
- 语法位于 `extensions/httpclient/language`,支持 `@var/@json/@form/@multipart` 等指令。
- 运行器会在块尾生成 `### Response`包含状态码、耗时、headers、body。
### 数学块
- 语言设为 `math`,逐行计算。
- `prev` 变量表示上一行结果,可完成链式运算。
- 结果挂件可点击复制,或显示格式化/定点值。
### Markdown 块
- 工具栏中的 Preview 按钮会调用 `toggleMarkdownPreview`,右侧打开面板。
- 预览状态按文档隔离,不会影响其他文档。
## 分隔符校验
- `parser.ts` 暴露 `isValidDelimiter` 方法,格式错误时分隔符会以红色底纹标记。
- 复制/剪切操作会自动扩选到整个块,确保分隔符完整。
## 维护建议
- 保持每个逻辑主题占用一个块,并用 `md` 块写标题。
- 大量多语言内容时,可用 `text` + 自动检测,待语言确定后再改分隔符。
- 若文档出现“无法解析块”提示,可运行 `格式化文档` 或在命令面板触发“重建语法树”。

View File

@@ -0,0 +1,42 @@
# 扩展与插件
![扩展占位](/img/placeholder-extensions.png)
> 替换为展示扩展设置面板或功能合集(小地图、搜索、翻译)的截图。
voidraft 的扩展系统由 `internal/models/extensions.go` + 前端 `ExtensionManager` 驱动。扩展配置存储在 `%USERPROFILE%/.voidraft/data/extensions.json`,可在设置页面勾选启用或调整参数。
## 核心扩展
| 扩展 ID | 功能 | 关键文件 |
| --- | --- | --- |
| `editor` | 基础 CodeMirror 行为、光标保护、滚轮缩放 | `frontend/src/views/editor/basic/*` |
| `codeblock` | 块解析、拖拽、复制、格式化、数学、HTTP DSL | `extensions/codeblock` |
| `vscodeSearch` | VSCode 风格搜索替换面板 | `extensions/vscodeSearch` |
| `markdownPreview` | Markdown 实时预览 | `extensions/markdownPreview` |
## 编辑增强
- **Rainbow Brackets (`rainbowBrackets`)**:彩虹色括号匹配。
- **Fold (`fold`)**:代码折叠/展开,支持 `Ctrl+Alt+[`/`]`
- **Hyperlink (`hyperlink`)**:识别 URL/邮箱,`Ctrl+Click` 打开。
- **Color Selector (`colorSelector`)**:悬浮配色器,支持 HEX/RGB/HSL。
- **Checkbox (`checkbox`)**Markdown 任务列表交互式勾选。
- **Text Highlight (`textHighlight`)**`Mod+Shift+H` 快速标记重点,可自定义颜色/透明度。
## 工具扩展
- **Translator (`translator`)**:选区翻译;配置项包括默认翻译器、最短/最长字符数。后端集成 Bing/Google/Youdao/DeepL/TartuNLP。
- **Minimap (`minimap`)**:右侧迷你地图,支持悬浮/常驻、显示字符/块,突出当前选区。
- **Search (`search`)**:补充 VSCode 风格搜索,暴露命令给快捷键系统。
- **HTTP Client (`httpclient`)**DSL + 运行器,详见 [HTTP 客户端](/zh/guide/http-client)。
## 未来扩展(欢迎参与)
- Vim / Emacs 键位层(正在计划)。
- 自定义命令面板Command Palette
- 代码片段/模板库扩展。
- AI 助手(文生代码/注释)。
## 开发者指南概述
1. **注册扩展**:在 `extensionManager.registerFactory` 中添加自定义扩展工厂。
2. **配置项**:在 `extensions.json` 中声明默认配置,并在设置面板暴露 UIVue 组件)。
3. **热更新**:调用 `manager.updateExtensionImmediate(id, enabled, config)` 实时切换,无需刷新窗口。
4. **后端交互**:通过 `ExtensionService.UpdateExtensionState` 将配置写入 SQLite。
> 如果需要编写自用扩展,可 fork 项目在 `frontend/src/views/editor/extensions` 中添加文件,再通过 PR 贡献给社区。

View File

@@ -0,0 +1,86 @@
# 功能特性
![扩展能力占位](/img/placeholder-extensions.png)
> 替换为展示彩虹括号、小地图、搜索工具条等扩展组合的截图。
## 1. 编辑体验
### 块状编辑全流程
- `∞∞∞language[-a]` 语法由 `codeblock/lang-parser` 解析,支持自动检测、分隔符校验、块范围缓存。
- `blockState` 暴露 API`getActiveBlock/getFirstBlock/getLastBlock`供格式化、重排、复制、HTTP 执行等插件共享。
- `mathBlock` 可在块尾展示计算结果,点击可复制;`CURRENCIES_LOADED` 注解在汇率更新时刷新缓存。
### 语言支持
- 内建 30+ 语言模版(`lang-parser/languages.ts`),覆盖 JS/TS/HTML/CSS/Go/Rust/Python/SQL/YAML/HTTP/Markdown/Plain/Text/Math。
- 语言切换下拉实时更新分隔符;支持自定义别名(例如 `∞∞∞shell`)。
### 语法高亮与主题
- `rainbowBracket``fold``hyperlink``colorSelector` 等扩展组合提供接近 VSCode 的体验。
- `ThemeService` 预置 12+ 暗/亮主题,可在设置中克隆、修改 JSON 色板,并立即生效。
### 文本统计与滚轮缩放
- `statsExtension` 实时统计行数、字符数和选区,展示在状态栏。
- `wheelZoomExtension``Ctrl + 鼠标滚轮` 调整字体大小,同时同步 `configStore`
## 2. 高效工具箱
### VSCode 式搜索替换
- `extensions/vscodeSearch` 提供悬浮面板,支持大小写/整词/正则、向上/向下跳转、批量替换。
- 对应快捷键:`Ctrl+F``Ctrl+H``Alt+Enter`(替换全部)。
### Markdown 预览
- `panelStore` 为每个文档维护预览状态,保证不同文档互不影响。
- 选中 Markdown 块后点击工具栏预览按钮即可在右侧展开实时渲染面板。
### HTTP 客户端
- Request DSL + 运行器在 [专章](/zh/guide/http-client) 详细说明。
- 支持变量、响应插入、多种请求体、定制 header、复制 cURL。
### 翻译助手
- `translator` 扩展监听选区,符合长度阈值后显示按钮;由 `TranslationService` 调用 Bing/Google/Youdao/DeepL/TartuNLP。
- 支持语种缓存、复制译文、切换译文方向。
### 颜色与高亮
- `colorSelector` 识别 `#fff/rgba/hsl`、打开取色器;`textHighlight``Mod+Shift+H` 标记重要行。
## 3. 复杂布局能力
### 多窗口
- `WindowService` 允许为任意文档创建独立 WebViewURL 自动携带 `?documentId=`
- `WindowSnapService` 根据主窗口位置吸附子窗口(上下左右+四角),并缓存尺寸、位置。
- 支持全局热键(默认 `Alt+X`)一键显示或隐藏所有窗口。
### 标签页
- `tabStore` 通过 `enableTabs` 控制;支持拖拽排序、关闭其他/左侧/右侧标签。
- 与多窗口互斥:当文档被新窗口接管后会从标签栏移除,避免重复。
### 系统托盘与置顶
- `TrayService` 控制关闭时隐藏到托盘或直接退出。
- 工具栏提供图钉按钮,可即时切换 `AlwaysOnTop`(支持临时置顶和永久置顶)。
## 4. 数据守护
### SQLite + 自动迁移
- `DatabaseService` 启动时执行 PRAGMA + 表结构校验,缺失字段自动 `ALTER TABLE`
- 默认生成 `documents/extensions/key_bindings/themes` 等表,支持软删除与锁定。
### Git 备份
- `BackupService``dataPath` 初始化为 Git 仓库,支持 Token/SSHKey/用户名密码三种方式。
- 自动任务按分钟运行(`BackupInterval`),包括 add/commit/push也可从 UI 触发一次性 push。
### 配置快照
- 所有设置存于 `config.json`,包含 `metadata.version/lastUpdated`,方便手工回滚。
- `ConfigService.Watch` 为窗口吸附、托盘、热键等服务提供实时响应。
### 自动更新
- `SelfUpdateService` 先检查主源Gitea失败再回退到 GitHub下载完成后可一键「重启并更新」。
- 更新前可选自动触发 Git 备份(`backupBeforeUpdate`)。
## 5. 自动化与集成
- **启动时动作**:可开启开机自启(`StartupService`)、默认最小化至托盘。
- **HTTP 运行挂钩**`response-inserter` 可在响应块尾部插入 `// @timestamp` 等自定义标记。
- **Math/汇率**`mathBlock` 可引用上一次结果 (`prev`),配合 `CURRENCIES_LOADED` 注解支撑货币换算。
- **系统信息**`SystemService` 暴露内存、GC、Goroutine 数量,可在调试面板查看。
## 6. 可配置的快捷键
- 详见 [键盘快捷键](/zh/guide/keyboard-shortcuts)。默认绑定定义在 `internal/models/key_bindings.go`,前端设置页可逐项修改、禁用。
## 7. 文档 & 帮助
- 文档站以 VitePress 构建(`frontend/docs`),内置中英双语导航,可一键部署到 GitHub Pages。
- `README` 与本文档同步介绍核心功能;建议将常用工作流截图补充到每个「图片占位」中。

View File

@@ -0,0 +1,82 @@
# 快速开始
![块结构流程占位](/img/placeholder-block-flow.png)
> 替换为展示块分隔符、语言标签、内容的截图,帮助读者直观理解 `∞∞∞language` 结构。
## 5 分钟上手流程
1. **启动应用**:等待加载动画结束,默认会打开 `default` 文档。
2. **新建文档**:点击工具栏的文档列表按钮,输入标题后创建;也可在设置里开启标签页,以便同时挂载多个文档。
3. **创建首个块**
- 在空白处输入 `∞∞∞javascript` 并回车。
- 输入代码或文本,`CodeBlockExtension` 会自动匹配语法高亮。
4. **格式化与预览**
- 选中块后点击工具栏的「Format」或使用 `Ctrl+Shift+F`
- 如果块语言是 `md`可点击「Preview」按钮开启 Markdown 侧栏。
5. **运行 HTTP 请求**:创建 `∞∞∞http` 块,填写请求,再点击行号旁的 Run 按钮即可获取响应。
6. **打开第二窗口**:在文档列表中右键文档 -> “在新窗口中打开”。`WindowService` 会创建无边框窗口并自动贴靠主窗口。
## 界面导览
- **主编辑区**CodeMirror 视图,支持鼠标滚轮 + `Ctrl` 缩放(`wheelZoomExtension`)。
- **右侧小地图**`extensions/minimap` 提供鸟瞰和选区同步。
- **底部状态**`editorStore.documentStats` 实时展示行数/字符/选区。
- **工具栏**`Toolbar.vue`包含文档切换、块语言下拉、窗口置顶、格式化、Markdown 预览、更新提示、进入设置等。
## 块的基本操作
| 操作 | 快捷键 | 说明 |
| --- | --- | --- |
| 新建块(下方) | `Ctrl+Enter` | 在当前块后插入 `∞∞∞text-a` 分隔符 |
| 新建块(上方) | `Ctrl+Shift+Enter` | 在当前块前插入 |
| 跳到上/下一个块 | `Alt+Up / Alt+Down` | 通过 `blockGotoPrevious/Next` 命令 |
| 删除块 | `Alt+Delete` | 仅删除块内容,不影响其他块 |
| 块排序 | `Ctrl+Shift+↑/↓` | `moveLines` 结合块范围移动 |
| 复制块 | `Ctrl+C`(光标在块上即可) | `copyPaste.ts` 自动扩展选区至整个块 |
## 自动语言与格式化
- 当分隔符写成 `∞∞∞text-a` 时,会触发语言自动检测(`lang-detect/autodetect.ts`),常用于粘贴未知代码。
- `formatCode.ts` 调用 Prettier自动选择 parser若语言不支持会提示不可格式化。
- 块语言可在工具栏下拉中修改,列表由 `lang-parser/languages.ts` 提供。
## Markdown / 待办
1. 使用 `∞∞∞md` 分隔符。
2. 在块内写 Markdown点击工具栏预览按钮。
3. 勾选/取消 Checkbox`extensions/checkbox`)即可同步更新文本。
## 翻译与文本标注
- 选中文本后会浮现翻译入口(`translator` 扩展),点击即可在块内查看结果、复制、切换目标语言。
- `textHighlight` 扩展提供 `Mod+Shift+H` 高亮当前选区,颜色可在扩展设置中调整。
## HTTP 客户端概览
```http
http
@var {
baseUrl: "https://api.example.com",
token: "{{secrets.token}}"
}
POST "{{baseUrl}}/users" {
authorization: "Bearer {{token}}"
content-type: "application/json"
@json {
name: "voidraft",
role: "developer"
}
}
```
- `parser/request-parser.ts` 会将变量与请求体解析为结构化对象。
- 点击 gutter Run 获取响应,`response-inserter.ts` 会将结果写入 `### Response` 区块。
## 自动保存与版本安全
- `editorStore` 为每个文档维护 `autoSaveTimer`,默认 2000 ms可在设置 > 编辑 调整。
- `documentStates` 记录每个文档的光标位置,切换文档或重启应用都会恢复。
- 若开启 Git 备份,可在工具栏或设置中查看最近一次 `push` 是否成功。
## 最佳实践
- 使用 Markdown 块为每组代码加标题/注释,便于导航。
- 重要文档启用“锁定”以避免被删除(文档右键菜单)。
- 多窗口 + 吸附用于常驻参考资料,标签页用于在一个窗口内快速切换。
- 善用「窗口置顶」图钉,让 voidraft 叠放在 VSCode/浏览器之上。
接下来:
- [界面总览](/zh/guide/ui-overview)
- [块语法与结构](/zh/guide/block-syntax)

View File

@@ -0,0 +1,72 @@
# HTTP 客户端
![HTTP 客户端占位](/img/placeholder-http.png)
> 替换为 HTTP 块 + 响应卡片的截图。
voidraft 将 HTTP 测试写成块(`∞∞∞http`),语法与 JetBrains Http Client 类似。解析与执行由 `frontend/src/views/editor/extensions/httpclient` 完成。
## 基本语法
```http
http
GET "https://api.example.com/users" {
accept: "application/json"
}
```
- 方法 + URL 必须用双引号包裹。
- Header 以 `key: "value"` 格式编写。
- 请求体使用内联指令(见下文)。
## 变量与环境
```http
@var {
baseUrl: "https://api.example.com",
token: "{{secrets.token}}"
}
GET "{{baseUrl}}/users" {
authorization: "Bearer {{token}}"
}
```
- `@var` 块使用 JSON 语法。
- 变量在任意请求中以 `{{name}}` 引用。
- `variable-resolver.ts` 支持嵌套、默认值、外部 secrets 映射。
## 请求体助手
| 指令 | 示例 | 说明 |
| --- | --- | --- |
| `@json` | `@json { "name": "voidraft" }` | 自动 `content-type: application/json` 并格式化 |
| `@form` | `@form { username: "demo" }` | 转为 `application/x-www-form-urlencoded` |
| `@multipart` | `@multipart { file: @"C:\tmp\a.txt" }` | 读取文件、多段表单 |
| `@text` | `@text <raw body>` | 自由文本 |
## 运行与响应
1. 将光标置于 HTTP 块内。
2. 点击行号左侧的 Run三角形图标或按下自定义快捷键。
3. 运行结果会插入到块尾的 `### Response` 中,包含:
- 状态行 + 响应时间 + 体积。
- Headers可折叠
- 响应体(自动格式化 JSON / XML / HTML / Text
- 复制、另存为、再次发送等快捷按钮。
## 多请求文档
- 每个 `∞∞∞http` 块被视为独立请求。
- `request-parser.ts` 会解析同一块内的多个请求(以 `###` 分隔)。
- 使用 Markdown 块写注释或分组标题。
## 变量注入顺序
1. 块内 `@var`
2. 文档级变量(计划中)。
3. 环境变量(`EnvironmentService` 预留)。
## 调试技巧
- 运行器会在控制台打印完整请求信息,可通过 `wails3 dev` 查看。
- 如果响应过大,可右键响应块选择“折叠正文”或“导出到文件”。
- 网络错误会在响应卡片顶部以红条展示,内容来自 `HttpClientService`
- 需要代理时确保系统代理已设置voidraft 会自动继承。
## 与其他功能配合
- 运行结果可直接与 Markdown/代码块混排,形成 API 使用手册。
- 配合 Git 备份可版本化 API 调试记录。
- 可将响应复制到其他块(例如 JSON → Prettier 之后用于 mock
> 欢迎在 Issue 中提交你希望支持的额外 DSL 指令(例如 GraphQL、WebSocket、gRPC

View File

@@ -0,0 +1,77 @@
# 安装
![安装流程占位](/img/placeholder-settings.png)
> 替换为安装向导或设置页截图,展示关键开关(置顶、数据目录、自动更新等)。
## 系统要求2025.11
| 项目 | 最低配置 | 推荐配置 |
| --- | --- | --- |
| 操作系统 | Windows 10 19045 / Windows 11 21H2 | Windows 11 23H2macOS/Linux 版本开发中) |
| CPU | x86_64 双核 | 4 核以上 |
| 内存 | 4 GB | ≥ 8 GB |
| 磁盘空间 | 200 MB含 SQLite 数据) | 1 GB 以上以保存附件/备份 |
| 运行环境 | Go 1.21+, Node.js 18+(仅开发者编译时需要) | 同左 + pnpm 8 用于前端 |
## 获取发行版
1. 打开 [GitHub Releases](https://github.com/landaiqing/voidraft/releases) 或自建 Gitea 镜像。
2. 下载 `voidraft-windows-amd64-installer.exe`(安装版)或 `voidraft-portable.zip`(绿色版)。
3. (可选)验证 SHA256
```powershell
Get-FileHash .\voidraft-windows-amd64-installer.exe -Algorithm SHA256
```
4. 双击安装包,按向导完成安装;或解压绿色版至任意目录并创建快捷方式。
## 首次启动流程
1. 启动后将创建数据目录:`%USERPROFILE%\.voidraft\data`(含 `voidraft.db`、`config.json`、`extensions.json`)。
2. 默认会生成 `default` 文档和一段示例块 `∞∞∞text-a`。
3. 若检测到旧版本数据,`ConfigMigrationService` 会自动迁移字段;`DataMigrationService` 确保表结构一致。
4. 首次运行建议立刻打开「设置 > 备份」配置远程 Git 仓库。
## 开发者手动构建
```bash
# 克隆项目
git clone https://github.com/landaiqing/voidraft.git
cd voidraft
# 安装前端依赖
cd frontend
npm install
npm run build
cd ..
# 构建/运行桌面应用
wails3 dev # 启动调试
wails3 package # 生成安装包(输出位于 bin/
```
> 若遇到 `wails3` 未找到,请先执行 `go install github.com/wailsapp/wails/v3/cmd/wails3@latest`。
## 数据目录与可执行文件
| 类型 | 默认位置 | 说明 |
| --- | --- | --- |
| 安装目录 | `C:\Program Files\voidraft` | 包含主程序与嵌入式前端资源 |
| 数据目录 | `C:\Users\<you>\.voidraft\data` | 可在设置 > 通用修改 `dataPath`,修改后需重启 |
| 备份仓库 | `dataPath/.git` | `BackupService` 初始化或使用现有仓库 |
| 日志 | `%LOCALAPPDATA%/voidraft/logs/*.log` | 通过 Wails `application.Log` 输出 |
## 常用 CLI 检查
```powershell
# 查看版本
& "C:\Program Files\voidraft\voidraft.exe" --version
# 清理缓存(若前端异常)
Remove-Item "$env:APPDATA\voidraft\Cache" -Recurse -Force
```
## 防火墙与代理
- voidraft 仅在使用 HTTP 客户端、更新检测、REST 翻译器时发起网络请求。
- 若处于企业代理,请在系统代理中放行 `voidraft.exe` 或设置环境变量 `HTTP(S)_PROXY`HTTP 客户端会继承系统代理。
## 常见安装问题
| 症状 | 处理方案 |
| --- | --- |
| 安装向导被安全策略阻止 | 使用签名哈希进行白名单设置或改用便携版 |
| 启动后白屏 | 删除 `%APPDATA%/voidraft/Cache`,确保显卡驱动支持 WebView2 |
| `wails3 dev` 报错缺少 WebView2 | 安装 [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) |
| 便携版无法写入 | 检查解压目录是否具有写权限,或在设置内切换 `dataPath` 至可写分区 |
> 继续阅读:[快速开始](/zh/guide/getting-started)

View File

@@ -0,0 +1,73 @@
# 简介
> voidraft 是一款面向开发者的「块式工作台」,用 CodeMirror 6 打造 Heynote 风格的体验,并结合 Wails3 + Go 后端提供系统托盘、全局热键、自动备份等桌面级能力。
![主界面总览占位](/img/placeholder-main-ui.png)
> 将 `/img/placeholder-main-ui.png` 替换为真实的应用主界面截图,演示数据面板、工具栏和右侧小地图。
## 产品定位
- **核心诉求**:在一处快速记录代码/配置/API 响应/待办清单,并能随时重排、格式化、运行或搜索。
- **目标用户**需要跨项目管理零碎文本的开发者、DevOps、测试或产品技术写作者。
- **设计理念**:所有内容都拆成可重排的块(`∞∞∞language`);每个块拥有独立语言、格式化器与扩展;多窗口/多标签保证同一份数据的不同视角。
## 面向场景
1. **临时代码/脚本草稿**:支持 30+ 语言高亮、Prettier 格式化、彩虹括号、文本高亮。
2. **API 调试台**HTTP 块内置运行器、变量解析、响应插入;请求和响应始终和文档共存。
3. **会议 & 需求记录**Markdown 块 + Checkbox 扩展 + 颜色标注快速整理想法。
4. **翻译与研究**:选中文本即可调 Bing/Google/DeepL/TartuNLP/有道翻译,结果内联呈现。
5. **多窗口资料墙**重要文档可弹出独立无边框窗口依附Snap在主窗口侧边。
## 核心概念
### 块式编辑器
- 解析器位于 `frontend/src/views/editor/extensions/codeblock`,依赖自研 Lezer 语法树确保 `∞∞∞` 分隔符稳定。
- 块结构(语言、是否自动检测、正文范围)存入 `blockState`供格式化、移动、复制、HTTP 执行等扩展复用。
- `math` 块使用 `math.js` 运行器,`http` 块调用 request parser + gutter run widget。
### 扩展驱动
- 后端通过 `internal/models/extensions.go` 定义扩展 ID/配置,`ExtensionService` 负责持久化。
- 前端 `ExtensionManager` 根据扩展配置动态拼装 CodeMirror Extension pipeline小地图、VSCode Search、Translator、Color Picker 等)。
- 所有扩展都可在设置页热切换,立即同步到当前与所有已打开的编辑器实例。
### 数据与安全
- SQLite 数据保存在 `%USERPROFILE%/.voidraft/data/voidraft.db`(可在设置中自定义 dataPath
- `DatabaseService` 自动迁移表结构,`DocumentService` 提供软删除/锁定机制避免误删默认草稿。
- `BackupService` 基于 go-gitSSH/Token/用户名密码)把 dataPath git 化,可按分钟全量提交、推送到 GitHub/Gitea 等。
- `SelfUpdateService` 同时轮询 GitHub/Gitea Release支持自动下载 + 一键重启。
## 系统架构概览
| 层级 | 说明 | 关键路径 |
| --- | --- | --- |
| 桌面容器 | Wails3 + Go 1.21,负责窗口、托盘、热键、服务注入 | `main.go`, `internal/services` |
| 后端服务 | Config/Document/Extension/Theme/Backup/Window/Hotkey/Translation 等 | `internal/services/*.go` |
| 数据模型 | Document、Theme、KeyBinding、GitBackup、Config | `internal/models` |
| 前端应用 | Vue 3 + Vite + Pinia + vue-router | `frontend/src` |
| 编辑器内核 | CodeMirror 6 扩展及自研块解析、HTTP DSL、Markdown 预览 | `frontend/src/views/editor` |
| 文档站点 | VitePress多语言导航 | `frontend/docs` |
## 模块速览
- **文档存储**`DocumentService` 支持创建/重命名/软删除/恢复、多窗口并发打开同一文档。
- **编辑器实例管理**`editorStore` 使用 LRU 缓存 + 自动保存计时器,确保在多文档切换时保留光标位置、未保存内容。
- **HTTP 客户端**`extensions/httpclient` 包括 Lezer 语法、变量解析、响应插入与运行 gutter支持 JSON/FormData/GraphQL 等多体格式。
- **Markdown 预览**`panelStore` 管理逐文档的预览状态,可随块实时刷新。
- **多窗口/吸附**`WindowService` + `WindowSnapService` 根据主窗口位置智能吸附子窗口、自动记忆尺寸。
- **全局热键**`HotkeyService` 监听系统级组合键,切换窗口显隐(默认 Alt+X可配置
- **系统托盘**`systray.SetupSystemTray` 注入显示/隐藏、退出、开机启动等操作。
- **翻译生态**`TranslationService` 聚合 Bing/Google/Youdao/DeepL/TartuNLP前端 `translator` 扩展提供 Tooltip + 复制。
- **主题与外观**`ThemeService` 预置 12+ 主题,可重置/克隆;前端 `createThemeExtension` 即时应用。
## 数据流(从键盘到持久化)
1. 用户按键 -> CodeMirror extensions 更新文档。
2. `contentChangeExtension` 记录脏状态并刷新 `documentStats`(行数、字符数、选区字符数)。
3. 触发自动保存计时器(默认 2s -> `DocumentService.UpdateDocumentContent` 写入 SQLite。
4. 若开启 Git 自动备份,每次 Commit 会序列化数据库 + 附带 `voidraft_data.bin`
5. 配置变更Pinia store通过 `ConfigService.Set` 传回 Go并触发观察者如 WindowSnap/Hotkey/Backup
## 版本节奏与路线图
- ✅ 当前实现多窗口、标签页、HTTP 客户端、Markdown Preview、数学块、彩虹括号、翻译、Git 备份、自动更新。
- 🚧 进行中自定义扩展导入、键位模版、Linux/macOS 原生打包。
- 🗺️ 规划中:剪贴板历史、团队同步、云端模板市场。
## 下一步
- [安装 voidraft](/zh/guide/installation)
- [界面总览](/zh/guide/ui-overview)
- [快速开始](/zh/guide/getting-started)

View File

@@ -0,0 +1,74 @@
# 键盘快捷键
![快捷键占位](/img/placeholder-shortcuts.png)
> 替换为展示快捷键设置界面或常用快捷键速查表的截图。
快捷键定义源自 `internal/models/key_bindings.go`,在设置 > 键位 中可以启用/禁用或改写。下表列出常用组合:
## 块管理
| 功能 | 默认快捷键 | 备注 |
| --- | --- | --- |
| 新建块(下方) | `Ctrl+Enter` | `blockAddAfterCurrent` |
| 新建块(上方) | `Ctrl+Shift+Enter` | `blockAddBeforeCurrent` |
| 跳到上/下一个块 | `Alt+↑ / Alt+↓` | `blockGotoPrevious/Next` |
| 选择当前块 | `Ctrl+Shift+A` | `blockSelectAll` |
| 删除块 | `Alt+Delete` | `blockDelete` |
| 块上移/下移 | `Ctrl+Shift+↑ / Ctrl+Shift+↓` | `blockMoveUp/Down` |
| 复制块 | `Ctrl+C`(块获得焦点) | `blockCopy` |
| 剪切块 | `Ctrl+X` | `blockCut` |
| 粘贴块 | `Ctrl+V` | `blockPaste` |
## 行与文本编辑
| 功能 | 快捷键 |
| --- | --- |
| 行复制(上/下) | `Shift+Alt+↑ / Shift+Alt+↓` |
| 行移动(上/下) | `Alt+↑ / Alt+↓`(在块内部) |
| 插入空行 | `Ctrl+Enter`(块尾后仍可插入) |
| 选择整行 | `Alt+L` |
| 语法级跳转 | `Ctrl+Alt+Left / Ctrl+Alt+Right` |
| 匹配括号 | `Shift+Ctrl+\` |
| 注释/块注释 | `Ctrl+/` / `Shift+Alt+A` |
| Tab 缩进/反向缩进 | `Ctrl+]` / `Ctrl+[` |
| 删除单词(向前/向后) | `Ctrl+Backspace` / `Ctrl+Delete` |
## 搜索与替换
| 功能 | 快捷键 | 描述 |
| --- | --- | --- |
| 打开搜索 | `Ctrl+F` | `showSearch` |
| 打开替换 | `Ctrl+H` | `searchShowReplace` |
| 切换大小写/整词/正则 | `Alt+C / Alt+W / Alt+R` | `searchToggleCase/Word/Regex` |
| 替换全部 | `Alt+Enter` | `searchReplaceAll` |
## Markdown/预览/格式化
| 功能 | 快捷键 |
| --- | --- |
| 格式化块 | `Ctrl+Shift+F` |
| 打开 Markdown 预览 | 工具栏按钮(建议映射到 `Ctrl+Shift+M` |
| 高亮文本 | `Mod+Shift+H` |
## 窗口与系统
| 功能 | 快捷键 |
| --- | --- |
| 新建窗口 | `Ctrl+Shift+N`(命令面板) |
| 全局显示/隐藏所有窗口 | 默认 `Alt+X`(可在设置 > 通用 > 全局热键中修改) |
| 打开设置 | `Ctrl+,` |
| 切换主题 | `Ctrl+Shift+T`(可自定义) |
## HTTP 客户端
| 功能 | 快捷键 |
| --- | --- |
| 运行请求 | 点击行号旁 Run 或自定义 `Ctrl+Alt+R` |
| 复制响应正文 | `Ctrl+Alt+C`(响应块聚焦时) |
## 翻译工具
| 功能 | 快捷键 |
| --- | --- |
| 显示翻译浮层 | 选中 ≥ `minSelectionLength` 的文本后按 `Ctrl+'`(可自定义) |
| 复制译文 | 在浮层中按 `Ctrl+C` |
## 自定义与导出
1. 打开设置 > 键位,列表会加载来自 `ExtensionService.GetAllKeyBindings()` 的数据。
2. 可单独禁用某个绑定或录入新组合;存储在 `%USERPROFILE%/.voidraft/data/key_bindings.json`
3. 需要与系统级快捷键冲突时,可勾选“忽略系统修饰键”。
> 建议将以上表格打印贴在工作区,或在文档中保留常用组合,方便新同事查阅。

View File

@@ -0,0 +1,67 @@
# 多窗口与标签页
![多窗口占位](/img/placeholder-multiwindow.png)
> 替换为展示主窗口 + 侧边浮窗(子窗口)或标签页齐开的截图。
## 多窗口工作流
- `WindowService.OpenDocumentWindow` 会根据文档 ID 创建新 WebView 窗口URL 自动附加 `?documentId=<id>`
- `windowStore` 通过查询字符串判断当前是否为子窗口(非主窗口)。
- 子窗口具备:
- 独立的 CodeMirror 实例与扩展栈。
- 与主窗口共享的 Document/Config Store因此编辑内容实时同步SQLite 数据库为唯一来源)。
- `WindowSnapService` 提供吸附:拖动靠近主窗口边缘时自动贴靠;支持上下左右以及四个角。
- 关闭时自动注销吸附状态,避免悬挂引用。
### 操作步骤
1. 打开文档列表(工具栏图标或 `Ctrl+Shift+O`)。
2. 右键目标文档 → 选择 “在新窗口中打开”。
3. 若文档已在标签页打开,会自动从标签栏移除,防止重复。
4. 关闭窗口:
- 点击自定义标题栏关闭按钮。
- 系统托盘菜单选择退出。
### 使用建议
- 将参考资料或检查清单放在子窗口中,配合“窗口置顶”保持常驻。
- 通过 Windows Snap + voidraft Snap 组合,可快速排版 2-4 个窗口。
- 若想在多窗口之间同步滚动,可尝试启用“共享视图状态”扩展(计划中)。
## 标签页模式
- 在设置 > 通用中开启“启用标签页”(`config.general.enableTabs`)。
- `tabStore` 维护 `tabsMap` + `tabOrder`,支持:
- 拖拽排序(拖动标签即可)。
- 关闭单个/其他/左侧/右侧标签。
- 检测当前文档是否已存在标签。
- 标签栏位于主窗口顶部,紧贴工具栏下方。
### 常用操作
| 操作 | 方法 |
| --- | --- |
| 关闭标签 | 点击标签上的叉号或中键 |
| 关闭其他 | 右键标签 → “关闭其他标签” |
| 关闭右侧/左侧 | 右键标签 → 选择对应菜单 |
| 固定标签(计划中) | 将在后续版本中提供 pin 功能 |
### Tabs vs 窗口
| 项目 | 标签页 | 新窗口 |
| --- | --- | --- |
| UI 占用 | 集成在一个窗口中 | 独立操作系统窗口 |
| 跨屏 | 不方便 | 可拖到其他显示器 |
| 独立置顶 | 不可单独置顶 | 每个窗口可单独置顶 |
| 推荐场景 | 同一背景的多个文档 | 跨项目/跨显示器对比 |
## 系统托盘与热键
- 勾选 “启用系统托盘” 后,关闭窗口默认隐藏至托盘。
- 全局热键(默认 `Alt+X`)由 `HotkeyService` 控制:
- 若 main window 可见 → 隐藏所有 voidraft 窗口。
- 若 main window 隐藏 → Show + Restore + Focus。
- `TrayService` 还提供“最小化到托盘”“显示主窗口”等菜单项。
## 常见问题
| 问题 | 原因 | 解决 |
| --- | --- | --- |
| 新窗口无法打开 | 文档 ID 不存在或被锁定 | 在文档列表确认状态,必要时解锁 |
| 子窗口未吸附 | WindowSnap 未启用 | 设置 > 通用 → 勾选“窗口吸附” |
| 关闭窗口直接退出应用 | 未启用托盘模式 | 设置 > 通用 → 启用系统托盘 |
| 标签页切换慢 | 同时开启标签 + 多窗口导致资源占用 | 关闭暂不需要的窗口或减少标签 |
> 如果需要更复杂的布局(如平铺窗口、快捷布局),欢迎在 Issue 中提出建议。

View File

@@ -0,0 +1,71 @@
# 设置与配置
![设置占位](/img/placeholder-settings.png)
> 替换为设置页截图,突出通用/编辑/外观/更新/备份等分栏。
所有设置都映射到 `internal/models/config.go`,持久化文件位于 `%USERPROFILE%/.voidraft/data/config.json`。前端 `configStore` 负责与后端 `ConfigService` 同步。
## 通用General
| 选项 | 说明 | 后端键 |
| --- | --- | --- |
| 窗口置顶 (`alwaysOnTop`) | 永久置顶主窗口 | `general.alwaysOnTop` |
| 数据目录 (`dataPath`) | SQLite + 备份所在目录,修改后需重启 | `general.dataPath` |
| 系统托盘 (`enableSystemTray`) | 关闭窗口后隐藏到托盘而非退出 | `general.enableSystemTray` |
| 开机自启 (`startAtLogin`) | 调用 `StartupService` 注册 | `general.startAtLogin` |
| 窗口吸附 (`enableWindowSnap`) | `WindowSnapService` 是否启用 | `general.enableWindowSnap` |
| 全局热键 (`enableGlobalHotkey` + `globalHotkey`) | 默认 Alt+X控制显隐 | `general.globalHotkey` |
| 标签页 (`enableTabs`) | 启用多标签界面 | `general.enableTabs` |
| 加载动画 (`enableLoadingAnimation`) | 切换文档时显示动画 | `general.enableLoadingAnimation` |
## 编辑Editing
| 选项 | 说明 |
| --- | --- |
| Font Size/Family/Weight/Line Height | 立即作用于所有编辑器实例 |
| Tab Size/Tab Type/Enable Tab Indent | 映射 `tabExtension` 行为 |
| Auto Save Delay | ms影响 `editorStore` 自动保存周期 |
## 外观Appearance
| 选项 | 说明 |
| --- | --- |
| Language | UI 语言(`zh-CN`/`en-US` |
| System Theme | 深色/浅色/跟随系统 |
| Current Theme | 选择预设或自定义主题(详见 [主题与外观](/zh/guide/themes) |
## 更新Updates
| 选项 | 说明 |
| --- | --- |
| Auto Update | 启动时自动检查更新 |
| Primary/Backup Source | `github``gitea`,对应 `UpdatesConfig` |
| Backup Before Update | 下载更新前执行 Git 备份 |
| Update Timeout | HTTP 请求超时 |
| GitHub/Gitea 仓库 | owner/repo/baseURL可指向自建镜像 |
## 备份Backup
| 选项 | 说明 |
| --- | --- |
| Enabled | 开关 Git 备份 |
| Repo URL | 远程仓库地址HTTPS 或 SSH |
| Auth Method | `token` / `ssh_key` / `user_pass` |
| Username/Password/Token/SSH Key Path | 根据认证方式填写 |
| Backup Interval | 自动备份间隔(分钟) |
| Auto Backup | 是否按间隔自动推送 |
## 键位Key Bindings
- 列表由 `ExtensionService.GetAllKeyBindings()` 提供。可搜索命令 ID 或组合。
- 允许将命令禁用(关闭开关)或录入新组合。
- 更改立即影响所有编辑器实例。
## 扩展Extensions
- 显示 `ExtensionSettings` 中的所有扩展。
- 每项可开关并展示 JSON 配置(背景色、最小选区、最小化提示等)。
- 修改后调用 `ExtensionService.UpdateExtensionState` 并通知 `ExtensionManager` 热更新。
## 配置文件备份
- 每次修改配置都会更新 `metadata.lastUpdated`,可用 Git 备份追踪历史。
- 若出现配置损坏,可删除 `config.json`,应用会写入 `NewDefaultAppConfig`
## 导入/导出(建议)
- 目前可手动复制 `config.json`/`extensions.json`/`key_bindings.json`
- 计划提供 UI 层面的导入导出按钮,便于跨设备同步。
> 修改高级选项(如 dataPath后建议重启以确保后台服务数据库、备份、窗口吸附等读取到最新配置。

View File

@@ -0,0 +1,44 @@
# 主题与外观
![主题占位](/img/placeholder-themes.png)
> 替换为主题切换界面或自定义主题编辑器的截图。
voidraft 的主题由后端 `ThemeService` 管理,存储在 `themes` 表。前端通过 `themeStore` + `createThemeExtension` 应用色板。
## 预设主题
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| default-dark | Dark | 默认暗色,适合低光环境 |
| default-light | Light | 默认亮色 |
| dracula | Dark | 高对比度紫色系 |
| aura | Dark | 柔和霓虹风 |
| github-dark / github-light | Dark/Light | 与 GitHub 主题接近 |
| material-dark / light | Dark/Light | Material Design 色板 |
| one-dark | Dark | VSCode 经典主题 |
| solarized-dark / light | Dark/Light | Solarized 配色 |
| tokyo-night / storm / day | Dark/Light | Tokyo Night 三件套 |
## 自定义主题
1. 打开设置 > 外观,选择「创建主题」。
2. 颜色字段对应 `ThemeColorConfig`,包含 `editor.background`, `editor.foreground`, `gutter`, `selection`, `bracket`, `keyword`, `string`, `comment`, `accent` 等。
3. 保存后立即写入数据库,可通过 `Reset` 按钮恢复为预设值。
4. 前端 `themeExtension` 会向 CodeMirror 注入新的 `EditorView.theme`
## 动态切换
- 切换主题会立即影响所有已打开的编辑器实例;`updateEditorTheme` 逐个更新 `EditorView`
- `SystemTheme` 设为 `auto`voidraft 会监听操作系统深浅模式并自动切换到 `default-dark``default-light`
## 字体与行高
- 字体配置来自设置 > 编辑,`createFontExtensionFromBackend` 会同步 `fontFamily/fontSize/fontWeight/lineHeight`
- 可在通用设置中的“滚轮缩放”手势下临时调整字号。
## 小地图/装饰色
- `minimap` 扩展读取主题中的 `accent` 颜色,用于高亮当前视区。
- `textHighlight` 扩展的默认背景色可在扩展设置中配置。
## 截图建议
- 展示暗/亮主题对比。
- 展示主题编辑对话框,标出关键字段。
- 展示自定义主题应用后的编辑器界面。
> 如果希望导入 VSCode `.json` 主题,可将颜色映射到 `ThemeColorConfig` 后写入数据库,或等待官方导入工具上线。

View File

@@ -0,0 +1,53 @@
# 常见问题与故障排查
![故障排查占位](/img/placeholder-troubleshooting.png)
> 替换为错误提示或日志查看界面的截图。
## 安装与启动
| 问题 | 可能原因 | 解决步骤 |
| --- | --- | --- |
| 启动白屏 | WebView2 缺失或缓存损坏 | 安装 WebView2 Runtime删除 `%APPDATA%/voidraft/Cache` 后重启 |
| 双击无反应 | 被安全策略拦截 | 以管理员运行或使用便携版;验证 SHA256 后加入白名单 |
| `wails3 dev` 报错 | Go/Node 版本不符或缺少 WebView2 | 确保 Go 1.21+、Node 18+,安装 WebView2 |
## 编辑器
| 问题 | 原因 | 解决 |
| --- | --- | --- |
| 格式化按钮灰色 | 当前块语言无对应 Prettier parser | 更换语言或安装支持的语言扩展(未来版本) |
| 块解析错误 | 分隔符格式不正确 | 确认 `∞∞∞language` 后跟换行;可用自动重建语法树命令 |
| 翻译浮层不出现 | 选区过短或超过最大长度 | 在设置 > 扩展 > translator 中调整阈值 |
| 小地图不同步 | 编辑器实例未刷新 | 切换文档或重开应用,检查扩展是否被禁用 |
## 窗口与多实例
| 问题 | 原因 | 解决 |
| --- | --- | --- |
| 子窗口未吸附 | WindowSnap 未启用 | 设置 > 通用 → 勾选“窗口吸附” |
| 全局热键无效 | 与系统/其他软件冲突 | 在设置 > 通用改用非系统占用组合,比如 `Ctrl+Alt+Space` |
| 关闭窗口直接退出 | 未启用托盘模式 | 设置 > 通用 → 启用系统托盘 |
## HTTP 客户端
| 问题 | 可能原因 | 解决 |
| --- | --- | --- |
| 发送失败,提示 `proxy` | 系统代理配置异常 | 在系统代理或环境变量中设置 HTTP(S)_PROXY或关闭代理再试 |
| 响应乱码 | 服务器未声明编码 | 手动在请求头中加 `accept-charset: utf-8`,或在响应视图切换编码(计划) |
| 变量未替换 | 变量名拼写或作用域错误 | 确认 `@var` 定义位置,使用 `{{name}}` 语法 |
## 数据与备份
| 问题 | 可能原因 | 解决 |
| --- | --- | --- |
| 自动备份停在 “未初始化” | Repo URL/认证缺失 | 补全备份配置或关闭自动备份 |
| Push 失败 | Token 权限不足或网络问题 | 为 Token 开启 `repo` scope检查代理稍后再试 |
| 数据目录迁移后文件缺失 | 未重启或权限不足 | 修改 `dataPath` 后重启应用;确保目标目录可写 |
## 更新
| 问题 | 原因 | 解决 |
| --- | --- | --- |
| 检查更新超时 | 主源不可达 | 切换到备用源或关闭代理重试 |
| 下载完成但未重启 | 权限或文件被占用 | 以管理员运行,关闭杀毒软件后重试 |
## 收集日志
- Wails 日志:`%LOCALAPPDATA%/voidraft/logs/*.log`
- 终端调试:运行 `wails3 dev` 并观察控制台输出。
- 若提交 Issue请附上系统版本、voidraft 版本、日志片段、复现步骤。
> 仍未解决?请到 GitHub Issues 提交反馈,并尽可能附上截图和日志。

View File

@@ -0,0 +1,46 @@
# 界面总览
![界面截图占位](/img/placeholder-main-ui.png)
> 替换为包含顶部工具栏、块区域、右侧小地图、底部状态栏的完整截图。
voidraft 的主窗口由四个区域组成:
| 区域 | 位置 | 作用 | 相关代码 |
| --- | --- | --- | --- |
| 工具栏 | 顶部浮层 | 文档切换、块语言选择、格式化、Markdown 预览、窗口置顶、更新提示、进入设置 | `frontend/src/components/toolbar/Toolbar.vue` |
| 编辑器主体 | 中央 | CodeMirror 6 视图承载块编辑、HTTP 运行器、翻译按钮等 | `frontend/src/views/editor/Editor.vue` + `extensions` |
| 导航辅助 | 右侧 | 小地图、滚动条、块徽标、HTTP 运行按钮 | `extensions/minimap`, `codeblock/decorations.ts` |
| 底部状态 | 左下角 | 行数、字符数、选区统计、文档脏状态 | `editorStore.documentStats` |
## 工具栏详解
| 项 | 说明 | 快捷入口 |
| --- | --- | --- |
| 文档切换器 | 展开后列出全部文档,支持搜索、创建、在新窗口打开 | 同步 `DocumentService.ListAllDocumentsMeta` |
| 块语言下拉 | 当前块语言,列表取自 `lang-parser/languages.ts`,支持搜索 | 鼠标选择或输入语言 token |
| Pin窗口置顶 | 临时 / 永久置顶切换,调用 `SystemService.SetWindowOnTop``config.general.alwaysOnTop` | Alt+Space自定义 |
| Format / Preview | 对当前块执行 Prettier 或打开 Markdown 预览 | `Ctrl+Shift+F` / 工具栏按钮 |
| 更新提示 | 轮询 `SelfUpdateService`,有更新时显示小点,可直接“检查/下载/重启” | 设置 > 更新 |
| 设置入口 | 跳转到 Vue Router 的 `/settings` 页面 | `Ctrl+,` |
## 多文档视图
- **标签页(可选)**:在设置 > 通用中启用“标签页模式”,`tabStore` 将当前文档加入 tab bar支持拖拽、批量关闭。
- **多窗口**:以文档列表右键「在新窗口中打开」或命令面板为入口。`WindowService` 会根据文档 ID 命名窗口,`WindowSnapService` 自动吸附。
- **系统托盘**:关闭窗口时默认最小化到托盘,可在托盘图标中重新唤醒或彻底退出。
## 面板与浮层
- **Markdown 预览**:针对选中的 Markdown 块,面板会贴在右侧,支持实时滚动同步、关闭动画。
- **HTTP 响应**:运行后在块底部自动插入 `### Response`,可展开查看头部/体/耗时。
- **翻译浮层**:选中文本后自动出现按钮,点击后显示结果卡片,附带复制、语种切换。
## 快捷状态
- **底部统计**
- `Ln`:当前块内行号。
- `Ch`:字符数。
- `Sel`:选区字符数。
- **右上角加载动画**:当编辑器实例加载或切换文档时显示,遵循 `enableLoadingAnimation` 设置。
## 建议截图
1. 默认深色主题 + 多块示例。
2. 打开 Markdown 预览 + 小地图。
3. 展示 HTTP 块运行按钮与响应卡片。
4. 展示标签页或多窗口。

View File

@@ -0,0 +1,56 @@
---
layout: home
hero:
name: "voidraft"
text: "优雅的文本片段记录工具"
tagline: 为开发者设计,用现代技术打造
image:
src: /img/hero.png
alt: "voidraft"
actions:
- theme: brand
text: 开始使用
link: https://github.com/landaiqing/voidraft/releases
- theme: alt
text: 使用文档
link: /zh/guide/introduction
features:
- icon: 📝
title: 块状编辑模式
details: 将内容分割为独立的代码块,每个块可设置不同语言。继承了 Heynote 优雅的块状编辑理念。
- icon: 🎨
title: 语法高亮
details: 内置支持 30+ 种编程语言的语法高亮,自动语言检测,集成 Prettier 代码格式化工具。
- icon: 🌐
title: HTTP 客户端
details: 集成 HTTP 客户端,支持 JSON、FormData、XML 等多种请求格式。直接在编辑器中测试 API。
- icon: 🎯
title: 多窗口支持
details: 同时编辑多个文档,每个窗口独立维护自己的状态和配置。
- icon: 🎭
title: 主题自定义
details: 完整的主题自定义支持,支持深色/浅色模式。创建并保存你自己的编辑器主题。
- icon: 🔧
title: 丰富的扩展
details: VSCode 风格搜索替换、彩虹括号、小地图、颜色选择器、翻译工具、文本高亮等实用扩展。
- icon: 🔄
title: 自动更新系统
details: 内置自我更新机制,支持多个更新源。及时获取最新功能和改进。
- icon: ☁️
title: Git 备份
details: 基于 Git 的自动数据备份。支持 GitHub、Gitea提供 SSH、Token 等多种认证方式。
- icon: ⚡
title: 现代化架构
details: 采用 Wails3、Vue 3 和 CodeMirror 6 构建。跨平台桌面应用,原生性能,现代化界面。
---

View File

@@ -50,7 +50,11 @@ export default defineConfig([
'.local',
'/bin',
'Dockerfile',
'**/bindings/'
'**/bindings/',
'*.js',
'**/*.js',
'**/*.cjs',
'**/*.mjs',
],
}
]);

View File

@@ -9,5 +9,6 @@
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<script src="/math.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -5,77 +5,106 @@
"type": "module",
"scripts": {
"dev": "vite --host --mode development",
"build:dev": "vue-tsc && vite build --minify false --mode development",
"build": "vue-tsc && vite build --mode production",
"build:dev": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" vue-tsc && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" vite build --minify false --mode development",
"build": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" vue-tsc && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" vite build --mode production",
"preview": "vite preview",
"lint": "eslint",
"lint:fix": "eslint --fix"
"lint:fix": "eslint --fix",
"build:lang-parser": "node src/views/editor/extensions/codeblock/lang-parser/build-parser.js",
"build:mermaid-parser": "node src/views/editor/language/mermaid/build-parsers.js",
"test": "vitest",
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:preview": "vitepress preview docs",
"app:dev": "cd .. &&wails3 dev",
"app:build": "cd .. && wails3 task build",
"app:package": "cd .. && wails3 package",
"app:generate": "cd .. && wails3 generate bindings -ts"
},
"dependencies": {
"@codemirror/autocomplete": "^6.18.6",
"@codemirror/commands": "^6.8.1",
"@codemirror/autocomplete": "^6.19.1",
"@codemirror/commands": "^6.10.0",
"@codemirror/lang-angular": "^0.1.4",
"@codemirror/lang-cpp": "^6.0.3",
"@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-go": "^6.0.1",
"@codemirror/lang-html": "^6.4.9",
"@codemirror/lang-html": "^6.4.11",
"@codemirror/lang-java": "^6.0.2",
"@codemirror/lang-javascript": "^6.2.4",
"@codemirror/lang-json": "^6.0.2",
"@codemirror/lang-less": "^6.0.2",
"@codemirror/lang-lezer": "^6.0.2",
"@codemirror/lang-liquid": "^6.2.3",
"@codemirror/lang-markdown": "^6.3.3",
"@codemirror/lang-liquid": "^6.3.0",
"@codemirror/lang-markdown": "^6.5.0",
"@codemirror/lang-php": "^6.0.2",
"@codemirror/lang-python": "^6.2.1",
"@codemirror/lang-rust": "^6.0.2",
"@codemirror/lang-sass": "^6.0.2",
"@codemirror/lang-sql": "^6.9.0",
"@codemirror/lang-sql": "^6.10.0",
"@codemirror/lang-vue": "^0.1.3",
"@codemirror/lang-wast": "^6.0.2",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/lang-yaml": "^6.1.2",
"@codemirror/language": "^6.11.2",
"@codemirror/language-data": "^6.5.1",
"@codemirror/legacy-modes": "^6.5.1",
"@codemirror/lint": "^6.8.5",
"@codemirror/language": "^6.11.3",
"@codemirror/language-data": "^6.5.2",
"@codemirror/legacy-modes": "^6.5.2",
"@codemirror/lint": "^6.9.2",
"@codemirror/search": "^6.5.11",
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.38.0",
"@lezer/highlight": "^1.2.1",
"@lezer/lr": "^1.4.2",
"@codemirror/view": "^6.38.6",
"@cospaia/prettier-plugin-clojure": "^0.0.2",
"@lezer/highlight": "^1.2.3",
"@lezer/lr": "^1.4.3",
"@mdit/plugin-katex": "^0.23.2",
"@mdit/plugin-tasklist": "^0.22.2",
"@prettier/plugin-xml": "^3.4.2",
"@replit/codemirror-lang-svelte": "^6.0.0",
"@toml-tools/lexer": "^1.0.0",
"@toml-tools/parser": "^1.0.0",
"@types/markdown-it": "^14.1.2",
"codemirror": "^6.0.2",
"codemirror-lang-elixir": "^4.0.0",
"colors-named": "^1.0.2",
"colors-named-hex": "^1.0.2",
"franc-min": "^6.2.0",
"groovy-beautify": "^0.0.17",
"highlight.js": "^11.11.1",
"hsl-matcher": "^1.2.4",
"lezer": "^0.13.5",
"pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.4.1",
"java-parser": "^3.0.1",
"linguist-languages": "^9.1.0",
"markdown-it": "^14.1.0",
"mermaid": "^11.12.1",
"npm": "^11.6.2",
"php-parser": "^3.2.5",
"pinia": "^3.0.4",
"pinia-plugin-persistedstate": "^4.7.1",
"prettier": "^3.6.2",
"remarkable": "^2.0.1",
"sass": "^1.89.2",
"vue": "^3.5.17",
"vue-i18n": "^11.1.9",
"vue-router": "^4.5.1"
"sass": "^1.94.0",
"vue": "^3.5.24",
"vue-i18n": "^11.1.12",
"vue-pick-colors": "^1.8.0",
"vue-router": "^4.6.3"
},
"devDependencies": {
"@eslint/js": "^9.30.1",
"@eslint/js": "^9.39.1",
"@lezer/generator": "^1.8.0",
"@types/lodash": "^4.17.20",
"@types/node": "^24.0.10",
"@types/remarkable": "^2.0.8",
"@vitejs/plugin-vue": "^6.0.0",
"@types/node": "^24.9.2",
"@vitejs/plugin-vue": "^6.0.1",
"@wailsio/runtime": "latest",
"eslint": "^9.30.1",
"eslint-plugin-vue": "^10.3.0",
"globals": "^16.3.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.35.1",
"unplugin-vue-components": "^28.8.0",
"vite": "^7.0.2",
"cross-env": "^10.1.0",
"eslint": "^9.39.1",
"eslint-plugin-vue": "^10.5.1",
"globals": "^16.5.0",
"happy-dom": "^20.0.10",
"typescript": "^5.9.3",
"typescript-eslint": "^8.46.4",
"unplugin-vue-components": "^30.0.0",
"vite": "npm:rolldown-vite@latest",
"vite-plugin-node-polyfills": "^0.24.0",
"vitepress": "^2.0.0-alpha.12",
"vitest": "^4.0.8",
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^3.0.1"
"vue-tsc": "^3.1.3"
},
"overrides": {
"vite": "npm:rolldown-vite@latest"
}
}

View File

@@ -1,7 +1,5 @@
importScripts("guesslang.min.js")
const LANGUAGES = ["json", "py", "html", "sql", "md", "java", "php", "css", "xml", "cpp", "rs", "cs", "rb", "sh", "yaml", "toml", "go", "clj", "ex", "erl", "js", "ts", "swift", "kt", "groovy", "ps1", "dart", "scala"]
const guessLang = new self.GuessLang()
function sendResult(language, confidence, idx) {
@@ -27,20 +25,13 @@ onmessage = (event) => {
guessLang.runModel(content).then((result) => {
if (result.length > 0) {
const lang = result[0]
if (LANGUAGES.includes(lang.languageId) && lang.confidence > 0.15) {
sendResult(lang.languageId, lang.confidence, idx)
// 返回置信度最高的结果
const bestResult = result[0]
if (bestResult.confidence > 0.15) {
sendResult(bestResult.languageId, bestResult.confidence, idx)
return
}
}
for (let lang of result) {
if (LANGUAGES.includes(lang.languageId) && lang.confidence > 0.5) {
sendResult(lang.languageId, lang.confidence, idx)
return
}
}
sendResult("text", 0.0, idx)
}).catch(() => {
sendResult("text", 0.0, idx)

Some files were not shown because too many files have changed in this diff Show More