texlite 0.7.8 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.zh-CN.md CHANGED
@@ -1,46 +1,59 @@
1
- # texLite
1
+ # TexLite
2
2
 
3
- texLite 是一个轻量、以本机为中心的 LaTeX 网页工作区,用于编写、编译、预览和讨论 LaTeX 文档。它面向同一台服务器上的少量可信用户。texLite 使用服务器已经安装的 LaTeX 环境,不打包 LaTeX 镜像;其余技术栈也尽量保持简单。
4
-
5
- **文档:** [English](README.md) · [Design(英文)](DESIGN.md) · 简体中文(当前文件)
3
+ 面向*小型、可信*研究团队的轻量自托管 Overleaf 替代方案。直接使用现有的 LaTeX
4
+ 发行版,无需沉重的服务栈。
6
5
 
7
6
  [![CI](https://github.com/SWUFE-DB-Group/TexLite/actions/workflows/ci.yml/badge.svg)](https://github.com/SWUFE-DB-Group/TexLite/actions/workflows/ci.yml)
8
7
  [![npm version](https://img.shields.io/npm/v/texlite?logo=npm&label=npm)](https://www.npmjs.com/package/texlite)
9
8
 
10
- ![texLite 预览](preview.png)
9
+ **文档:** [English](README.md) · [运维指南(英文)](OPERATIONS.md) · [设计文档(英文)](DESIGN.md) · 简体中文(当前文件)
11
10
 
12
- 设计目标、技术架构、协作与编译模型、历史与诊断、GitHub 备份以及数据管理
13
- 请参阅英文文档 [DESIGN.md](DESIGN.md)。
11
+ **网站:** [TexLite GitHub Pages](https://swufe-db-group.github.io/TexLite/)
14
12
 
15
- ## 环境要求
13
+ ![TexLite 预览](preview.png)
16
14
 
17
- - Node.js 24 或更高版本
18
- - npm
19
- - git(可选;仅项目所有者使用 Git/GitHub 集成时需要)
20
- - latexmk
21
- - 至少一个配置好的引擎:pdflatex、xelatex 或 lualatex
15
+ ## 为什么选择 TexLite
22
16
 
23
- 初始化前可以检查:
17
+ - **掌控写作环境。** 直接使用宿主机 TeX 环境,并将源码、历史版本和编译产物保存在
18
+ 一个本地数据目录中。
19
+ - **无需庞大服务栈即可协作。** 默认部署只有一个 Node.js 进程、SQLite 和本地文件,
20
+ 同时提供实时编辑和源码级批注,适合少量可信协作者。
24
21
 
25
- ~~~bash
26
- node --version
27
- npm --version
28
- latexmk --version
29
- xelatex --version
30
- # 可选,仅在需要 Git/GitHub 集成时检查:
31
- git --version
32
- ~~~
22
+ ## 与 Overleaf 的实际区别
33
23
 
34
- npm run init 和应用启动会检查 latexmk 以及 latex.allowedEngines 中列出的每个引擎。Git 不参与这项核心检查,因此未安装 Git 的宿主机仍可正常初始化并运行 TexLite。项目所有者打开 Git 面板或执行 Git/GitHub 操作时,TexLite 才会按需检查 git.binary;如果 Git 不可用,界面会给出可操作的错误提示。
24
+ [Overleaf](https://www.overleaf.com/about/features-overview) 在团队需要其托管产品或更完整生态时
25
+ 仍然是很好的选择。TexLite 面向的是更窄的自托管场景:
35
26
 
36
- 格式化功能同样是可选的,并直接在浏览器中运行。TexLite 内置 [npm 包 `tex-fmt`](https://www.npmjs.com/package/tex-fmt)(WASM 版本)格式化 `.tex`、`.cls` 和 `.sty`,并在浏览器中使用 `bibtex-tidy` 格式化 `.bib`。编辑器设置中可以为当前用户和项目填写 `tex-fmt` 的 TOML 参数;不需要在宿主机安装格式化命令,也不需要配置 PATH。
27
+ - 共享托管服务在使用高峰期可能排队、变慢或出现编译超时。
28
+ - Overleaf 开源 [Community Edition](https://github.com/overleaf/overleaf) 的
29
+ [Docker 部署路径](https://docs.overleaf.com/on-premises/getting-started/what-is-the-overleaf-toolkit) 更复杂,且
30
+ [源码批注仅限 Server Pro](https://docs.overleaf.com/on-premises/user-and-project-management/roles-and-permissions)。
31
+ - TexLite 直接使用服务器已有的 TeX 环境,以较小的单机栈运行,同时提供实时源码批注
32
+ 与回复。
37
33
 
38
- ## 快速开始
34
+ 自托管并不保证每份文档都编译得更快,速度仍取决于宿主机和文档本身;它带来的是对容量、
35
+ TeX 更新、数据位置与协作工作流的掌控。
36
+
37
+ 若是以个人、本地桌面工作流为主,建议优先考虑
38
+ [VS Code + LaTeX Workshop](https://github.com/James-Yu/LaTeX-Workshop) 或
39
+ [TeXstudio](https://texstudio.org/)。TexLite 的目标是浏览器中的共同写作,而不是取代个人 IDE。
40
+
41
+ ## 核心写作工作流
42
+
43
+ - 项目支持文件夹、ZIP 导入/导出、标签、分享、所有权转让、归档和私有的个人引用库。
44
+ - 基于 CodeMirror 的编辑器提供 LaTeX/BibTeX 高亮、折叠、补全、可选 Vim 模式、格式化、
45
+ 拼写/语法辅助、搜索替换及源码/PDF SyncTeX 跳转。
46
+ - 基于 Yjs 的协同源码编辑支持活动会话、源码锚定批注、回复、解决状态,以及让审阅者
47
+ 可批注但不能修改源码的权限模型。
48
+ - 使用 `latexmk` 和可选择引擎进行编译,提供项目设置、结构化诊断、缓存的成功 PDF、
49
+ 可下载产物以及可选的项目级 `latexmkrc`。
50
+ - 每个项目拥有历史版本和仅所有者可用的 Git/GitHub 备份;Git 是可选依赖,仅在使用
51
+ 集成时才检查。
39
52
 
40
- ### 全局 npm 安装
53
+ ## 快速开始
41
54
 
42
- 发布后的 npm 包提供 `texlite` 命令,配置和项目数据不会写入全局 npm
43
- 安装目录:
55
+ 安装 Node.js 24 或更高版本、`latexmk`,以及至少一个 TeX 引擎,例如 `pdflatex`、
56
+ `xelatex` 或 `lualatex`。只有使用可选 Git/GitHub 集成时才需要 Git。
44
57
 
45
58
  ~~~bash
46
59
  npm install --global texlite
@@ -49,319 +62,37 @@ texlite start
49
62
  texlite status
50
63
  ~~~
51
64
 
52
- 打开 http://127.0.0.1:3000。可以从任意工作目录管理服务:
53
-
54
- ~~~bash
55
- texlite stop
56
- texlite restart
57
- texlite logs
58
- ~~~
59
-
60
- 默认配置文件为
61
- `$XDG_CONFIG_HOME/texlite/texlite.config.json`;如果没有设置
62
- `XDG_CONFIG_HOME`,则为 `~/.config/texlite/texlite.config.json`。默认数据目录为
63
- `$XDG_DATA_HOME/texlite`;如果没有设置 `XDG_DATA_HOME`,则为
64
- `~/.local/share/texlite`。可以使用 `--config PATH` 或 `TEXLITE_CONFIG`
65
- 指定其他配置文件。
65
+ 访问 <http://127.0.0.1:3000>。`texlite init` 会创建配置并建立第一个管理员;TexLite
66
+ 不开放公众注册。
66
67
 
67
- `texlite serve` 以前台方式运行,适合 Docker、systemd 和调试。
68
- `start`、`status`、`stop`、`restart` 和 `logs` 使用 npm 包内置的 PM2。后台启动会
69
- 等待 HTTP 健康检查真正就绪;如果 PM2 进程存在但没有实际提供 TexLite 服务,
70
- `status` 会显示 `unhealthy`。`restart` 会重新创建 PM2 条目,确保 npm 升级后使用
71
- 当前版本的包路径和环境变量。启动失败的重试次数是有限的,不会进入无限重启循环。
72
-
73
- 升级时可以执行:
68
+ 升级与日常管理:
74
69
 
75
70
  ~~~bash
76
71
  npm update --global texlite
77
72
  texlite restart
78
- ~~~
79
-
80
- 卸载 npm 包不会删除配置和项目数据:
81
-
82
- ~~~bash
83
- npm uninstall --global texlite
84
- ~~~
85
-
86
- ### 从仓库/源码运行
87
-
88
- ~~~bash
89
- npm ci
90
- cp texlite.config.example.json texlite.config.json
91
- export TEXLITE_CONFIG="$PWD/texlite.config.json"
92
- # 按需要编辑 texlite.config.json
93
- npm run init
94
- npm run build
95
- npm start
96
- ~~~
97
-
98
- 默认只监听 localhost,也不开放公众注册。初始化命令会要求创建第一个
99
- 管理员;没有有效管理员时服务不会启动。
100
-
101
- 如果需要非交互初始化,可以只为该命令设置以下环境变量:
102
-
103
- ~~~bash
104
- TEXLITE_INIT_USERNAME=admin \
105
- TEXLITE_INIT_DISPLAY_NAME=Administrator \
106
- TEXLITE_INIT_PASSWORD='至少 8 个字符的密码' \
107
- npm run init
108
- ~~~
109
-
110
- 在共享机器上不要让密码进入 shell 历史记录。
111
-
112
- ## 开发和验证
113
-
114
- 在两个终端分别运行 API/server 和 Vite:
115
-
116
- ~~~bash
117
- npm run dev # API/server:http://127.0.0.1:3000
118
- npm run dev:web # Vite 界面:http://127.0.0.1:5173
119
- ~~~
120
-
121
- Vite 会把 /api 请求代理到后端。生产式运行前可以执行:
122
-
123
- ~~~bash
124
- npm run typecheck
125
- npm test
126
- npm run build
127
- npm start
128
- ~~~
129
-
130
- ## 配置
131
-
132
- 配置文件路径优先级如下:
133
-
134
- 1. `texlite --config PATH`;
135
- 2. `TEXLITE_CONFIG`;
136
- 3. `$XDG_CONFIG_HOME/texlite/texlite.config.json`;
137
- 4. `~/.config/texlite/texlite.config.json`。
138
-
139
- 配置中的相对路径以配置文件所在目录为基准。`storage.dataDir` 默认使用
140
- `$XDG_DATA_HOME/texlite`;未设置时使用 `~/.local/share/texlite`。可以在配置中
141
- 设置 `storage.dataDir`,或使用 `TEXLITE_DATA_DIR` 指定其他数据目录。生产环境
142
- 的前端资源默认定位到 npm 包内部的 `dist/client`,开发或自定义部署可以用
143
- `TEXLITE_CLIENT_DIR` 覆盖。
144
-
145
- 示例配置:
146
-
147
- ~~~json
148
- {
149
- "siteName": "TexLite",
150
- "adminEmail": "admin@example.com",
151
- "sessionDays": 14,
152
- "server": { "host": "127.0.0.1", "port": 3000 },
153
- "storage": { "dataDir": ".texlite" },
154
- "uploads": { "maxFileSizeMB": 50 },
155
- "history": { "maxVersions": 200, "maxStorageMB": 128 },
156
- "git": {
157
- "binary": "git",
158
- "operationTimeoutSeconds": 120,
159
- "githubApiBaseUrl": "https://api.github.com"
160
- },
161
- "latex": {
162
- "latexmk": "latexmk",
163
- "defaultEngine": "xelatex",
164
- "allowedEngines": ["pdflatex", "xelatex", "lualatex"],
165
- "extraArgs": [],
166
- "allowProjectLatexmkrc": true,
167
- "compileTimeoutSeconds": 600,
168
- "maxCompileJobs": 10
169
- }
170
- }
171
- ~~~
172
-
173
- 仓库中的示例为了方便源码开发,显式使用 `.texlite`。`texlite init` 自动生成
174
- 的 npm 配置则使用前面所述的 XDG 数据目录默认值。
175
-
176
- 重要配置:
177
-
178
- - server.host、server.port:监听地址和端口。除非已经准备好安全部署,否则保持 127.0.0.1。
179
- - storage.dataDir:SQLite 数据库、项目源码、编译输出和 Git token 加密密钥的位置。
180
- - uploads.maxFileSizeMB:项目上传、ZIP 条目、项目文件和资源的最大大小,默认 50 MB。
181
- - history.maxVersions:每个项目最多保留的普通、未标记版本数;初始版本和已标记版本受保护。
182
- - history.maxStorageMB:每个项目去重历史对象的软上限。超过后优先删除最旧的普通版本;受保护版本和当前内部基线可使实际用量超过上限。
183
- - latex.defaultEngine、latex.allowedEngines、latex.extraArgs:界面中可选择的编译方式。
184
- - latex.compileTimeoutSeconds:单次编译超时时间。
185
- - latex.maxCompileJobs:全局 LaTeX 进程并发上限。同一项目的同一主文档串行编译;多个源码版本排队时只保留最新请求。不同主文档使用独立工作区,可在该全局上限内并行编译。
186
- - latex.allowProjectLatexmkrc:是否允许项目提供多行 latexmkrc。该文件是可执行的 Perl 配置,只建议对可信用户开启。
187
-
188
- ### 生效默认值和启动校验
189
-
190
- 如果没有设置某项,texLite 使用以下内置默认值(自动生成的示例配置
191
- 可以显式写出例如管理员邮箱这样的值):
192
-
193
- | 配置项 | 生效默认值 |
194
- | --- | --- |
195
- | `siteName` | `TexLite` |
196
- | `adminEmail` | 空 |
197
- | `server.host` / `server.port` | `127.0.0.1` / `3000` |
198
- | `storage.dataDir` | `$XDG_DATA_HOME/texlite` 或 `~/.local/share/texlite` |
199
- | `clientDir` | npm 包内部的 `dist/client` |
200
- | `sessionDays` | `14` 天 |
201
- | `uploads.maxFileSizeMB` | `50` MB |
202
- | `history.maxVersions` | 每项目 `200` 个普通版本 |
203
- | `history.maxStorageMB` | 每项目 `128` MB(软上限) |
204
- | `latex.latexmk` | `latexmk` |
205
- | `latex.defaultEngine` | `xelatex` |
206
- | `latex.allowedEngines` | `pdflatex`、`xelatex`、`lualatex` |
207
- | `latex.extraArgs` | `[]` |
208
- | `latex.allowProjectLatexmkrc` | `true` |
209
- | `latex.compileTimeoutSeconds` | `600` 秒 |
210
- | `latex.maxCompileJobs` | `10` |
211
- | `git.binary` / `git.operationTimeoutSeconds` | `git` / `120` 秒 |
212
- | `git.githubApiBaseUrl` | `https://api.github.com` |
213
-
214
- 配置会在环境检查、打开数据库和启动 HTTP 监听之前完成校验。显式设置的
215
- 非法值不会静默回退到默认值。允许范围为:端口 `1–65535`,会话有效期
216
- `1–3650` 天,单文件大小 `1–2048` MB,历史版本数 `10–5000`,历史存储
217
- `16–102400` MB,编译超时 `1–3600` 秒,编译并发数 `1–32`,Git 超时
218
- `1–3600` 秒。引擎名称必须受支持且不能重复;允许引擎
219
- 列表必须包含选中的默认引擎。数据目录和项目目录不能指向文件,数据目录
220
- 不能是文件系统根目录;数据目录不存在时,其父目录必须已经存在且可写。
221
- GitHub API 地址必须是 `http://` 或 `https://` URL。
222
-
223
- JSON 类型错误、必填字符串为空、整数格式错误(包括带小数或非数字的环境
224
- 变量)、不支持的引擎、非法 URL 和不可用路径都会停止启动,并显示配置项、
225
- 期望格式及修复提示。`npm run init` 也执行同样的校验,因此可以在创建第一个
226
- 管理员前先发现配置问题。
227
-
228
- 环境变量会覆盖配置文件中的对应值:
229
-
230
- ~~~text
231
- TEXLITE_CONFIG
232
- XDG_CONFIG_HOME XDG_DATA_HOME
233
- TEXLITE_SITE_NAME TEXLITE_ADMIN_EMAIL
234
- TEXLITE_HOST TEXLITE_PORT
235
- TEXLITE_DATA_DIR TEXLITE_CLIENT_DIR
236
- TEXLITE_SESSION_DAYS TEXLITE_MAX_UPLOAD_SIZE_MB
237
- TEXLITE_HISTORY_MAX_VERSIONS TEXLITE_HISTORY_MAX_STORAGE_MB
238
- TEXLITE_LATEXMK TEXLITE_DEFAULT_ENGINE
239
- TEXLITE_COMPILE_TIMEOUT TEXLITE_MAX_COMPILE_JOBS
240
- TEXLITE_GIT TEXLITE_GIT_TIMEOUT
241
- TEXLITE_GITHUB_API_URL
242
- ~~~
243
-
244
- texLite 不执行 tlmgr,也不会自动安装缺失宏包。宿主机更新 TeX Live 后,下一次编译会直接使用新环境。
245
-
246
- ## 服务管理
247
-
248
- 通过全局 npm 安装时,生命周期命令使用包内置的 PM2,不需要额外全局安装:
249
-
250
- ~~~bash
251
- texlite start
252
- texlite status
253
73
  texlite logs
254
- texlite restart
255
- texlite stop
256
74
  ~~~
257
75
 
258
- `texlite status` 默认使用带颜色的 systemctl 风格终端视图;脚本或监控集成可使用
259
- `texlite status --json` 获取结构化输出。
260
-
261
- `texlite doctor` 会校验配置、路径、LaTeX 和管理员;使用 `--git` 可以额外
262
- 检查可选的 Git 集成。`texlite config` 显示生效的配置和路径。
263
- `texlite serve` 以前台方式运行,不启动 PM2。
76
+ `texlite serve` 会以前台方式运行,适合调试、Docker 或 systemd。`start`、`stop`、
77
+ `restart`、`status`、`logs` 使用 npm 包内置的 PM2 运行时;完整命令请执行
78
+ `texlite help`。
264
79
 
265
- <details>
266
- <summary>从仓库部署并单独安装 PM2</summary>
80
+ ## 文档导航
267
81
 
268
- 从仓库运行时仍可以使用 `ecosystem.config.cjs` 和 npm PM2 快捷命令。
269
- 该配置明确使用一个 fork 实例(`instances: 1`)。不支持 cluster 模式,因为
270
- 协作状态、编译队列、SQLite 连接和项目文件系统都属于单个进程。
271
-
272
- 在服务器上安装一次 PM2,构建后启动:
273
-
274
- ~~~bash
275
- npm install --global pm2
276
- npm run build
277
- pm2 start ecosystem.config.cjs
278
- pm2 status
279
- pm2 logs texlite
280
- ~~~
281
-
282
- 对应的 npm 快捷命令是 npm run pm2:start、npm run pm2:restart、npm run pm2:stop、npm run pm2:delete、npm run pm2:logs 和 npm run pm2:save。
283
-
284
- 发布新代码后:
285
-
286
- ~~~bash
287
- npm run build
288
- pm2 restart texlite --update-env
289
- ~~~
290
-
291
- 如果需要开机自动恢复,执行 pm2 startup 输出的命令,然后保存进程列表:
292
-
293
- ~~~bash
294
- pm2 save
295
- ~~~
296
-
297
- 常用命令还有 pm2 stop texlite、pm2 restart texlite、pm2 delete texlite 和 pm2 monit。
298
-
299
- </details>
300
-
301
- ## 协作和编译模型
302
-
303
- 编辑器使用 Yjs CRDT 支持并发编辑。项目顶部显示活动浏览器会话,远程光标使用不同颜色;单个项目的目标规模约为 10 个活动会话。只有服务端确认源码已经持久化后,保存状态才会显示“已保存”。尚未同步的更新也会保留在浏览器 IndexedDB 中,并在临时断线后恢复;恢复历史版本或 Git checkout 会轮换协作 epoch,避免旧的本地草稿覆盖刚恢复的源码树。删除或移动文件后,其他会话仍绑定旧编辑器时产生的迟到修改会被拒绝。
304
-
305
- 项目设置中保存的主文档是默认主文档。用户打开另一个包含 `\documentclass` 的 `.tex` 文件后,该文件仅在当前浏览器会话中成为编译主文档;打开被引用的普通片段不会切换主文档。系统只编译当前主文档。编译状态、日志、保留的 PDF、编译产物、大纲和 SyncTeX 均按主文档隔离,因此查看不同主文档的协作者不会看到彼此的编译提示,也不会覆盖彼此的 PDF。
306
-
307
- 编译与编辑相互隔离:
308
-
309
- 1. 服务端捕获不可变源码快照。
310
- 2. 将有变化的文件增量同步到按项目、主文档和编译设置区分的持久编译工作区。
311
- 3. latexmk 复用依赖数据库和辅助文件;同一主文档的任务仍然串行执行。
312
- 4. 将 PDF、日志、SyncTeX 和其他产物复制到不可变的运行快照。
313
- 5. 编译成功后,以原子方式发布最新产物快照。
314
-
315
- 同一主文档的可变缓存不会被并发使用,不同主文档使用独立缓存,已经发布的产物也不会被原地修改。编译时仍可查看旧 PDF;BibTeX 文档所需的多轮编译由 latexmk 自动处理,参考文献输入未变化时不会重复运行 BibTeX。编译响应提供 Server-Timing 响应头,可以分别查看快照、缓存同步、latexmk、产物复制和请求总耗时。TexLite 不保留可浏览的编译历史:仅按主文档保存最近一次尝试的状态,以及仍用于 PDF 预览的最近成功结果(如果需要)。更早的数据库记录和不可变产物包会自动清理。
316
-
317
- ## 历史、导航和诊断
318
-
319
- 自动历史会记录源码/文件操作、编译器设置、Git 操作、恢复操作和服务端确认的协作保存。协作保存采用固定的两分钟版本窗口,因此连续编辑仍会形成有用的恢复点,同时不会按每次按键记录。TexLite 默认保留最近 200 个普通版本,以及全部已标记版本和初始版本。文件内容以完整的 SHA-256 对象保存:未变化内容会复用,变化文件则产生一个新的完整对象。默认每个项目设置 128 MB 软上限,超过后优先删除最旧的普通版本;受保护版本和当前内部基线可能使实际用量超过上限。项目所有者可以查看历史存储用量、删除单个版本或清空全部历史,而不会改变当前项目文件。不再被引用的对象会被清理。历史功能适合修正写作误操作,但不能替代对完整数据目录的备份。
320
-
321
- Ctrl/Cmd+P 用于快速打开项目文件,Ctrl/Cmd+Shift+F 用于全项目纯文本搜索和替换。全项目替换按一次操作暂存,并自动创建历史版本。大纲从主文档开始跟随 `\\input`、`\\include` 和 `\\subfile`。结构化警告/错误会解析项目内文件名,点击后直接跳到源码行;完整 latexmk 原始日志仍然保留。
322
-
323
- 管理员可在项目列表打开“系统状态”。指标只包含数量和耗时,绝不包含源码、密码、Git token 或批注;也可通过需要管理员登录的 `GET /api/health/metrics` 获取。
324
-
325
- ## GitHub 备份
326
-
327
- Git 面板仅对项目所有者显示。GitHub personal access token 按项目配置并加密保存到 SQLite。本地仓库位于项目源码目录;每次命令临时使用以下身份:
328
-
329
- ~~~text
330
- user.name = 项目所有者 username
331
- user.email = <username>@texlite.com
332
- ~~~
333
-
334
- 对于 fine-grained token,在可信用户部署中建议授予仓库 Administration 和 Contents 的读写权限,并选择 All repositories。配置 token 时远程仓库可能还不存在,之后也可能创建新仓库。token 不会出现在远程 URL 或命令行参数中。
335
-
336
- 普通 checkout 遵循 Git 的默认保留行为,冲突时拒绝操作。只有在确认框中明确选择强制选项,才会丢弃已跟踪、未跟踪和 ignored 的工作区文件。checkout 历史版本后,需要先返回默认分支才能提交或 push。
337
-
338
- ## 数据、备份和删除
339
-
340
- 默认数据目录:
341
-
342
- ~~~text
343
- .texlite/
344
- ├── texlite.db
345
- ├── texlite.db-wal
346
- ├── texlite.db-shm
347
- ├── git-token.key
348
- └── projects/
349
- └── <project-id>/
350
- ├── source/
351
- └── output/
352
- └── .texlite/ # 编译缓存/运行和历史对象
353
- ~~~
354
-
355
- 请同时备份 texlite.db、git-token.key 和 projects/。恢复已保存的 GitHub token 必须保留加密密钥。在线备份 SQLite 文件时也要包含 WAL 文件,或者使用 SQLite 感知的备份方式。
356
-
357
- 删除用户会删除其成员关系,但既有批注仍会保留,并显示为“已删除用户”。根据管理员选择,该用户拥有的项目可以转移给当前管理员,也可以连同文件一起删除。最后一个有效管理员不能被删除、禁用或降级。
358
-
359
- ## 安全边界
82
+ | 需要了解 | 阅读 |
83
+ | --- | --- |
84
+ | 安装、配置路径、生效默认值、环境变量、服务管理、备份与安全边界 | [运维指南(英文)](OPERATIONS.md) |
85
+ | 协作、源码持久化、编译隔离、历史版本和设计权衡 | [设计文档(英文)](DESIGN.md) |
86
+ | 发布前测试 npm 包 | [NPM 测试指南(英文)](NPM_TESTING.md) |
87
+ | 完整配置起点 | [texlite.config.example.json](texlite.config.example.json) |
360
88
 
361
- texLite 面向 localhost 上的可信用户。默认编译关闭 shell escape、不通过 shell 拼接命令,并限制编译超时和并发数量。但 LaTeX 本身以及项目 latexmkrc 不能视为安全沙箱。如果将来需要对不可信网络开放或允许公众注册,应增加独立的编译沙箱和合适的认证/反向代理层。
89
+ ## 范围与安全
362
90
 
363
- ## 许可证和状态说明
91
+ TexLite 是一个面向可信用户的单宿主机应用,并非 LaTeX 编译沙箱:LaTeX 本身以及启用的
92
+ 项目 `latexmkrc` 都可能执行强大的本机行为。除非已配备适合不可信环境的认证、网络控制和
93
+ 独立编译沙箱,否则请保持默认的 `127.0.0.1` 监听地址。
364
94
 
365
- texLite 使用 GNU Affero General Public License v3.0,详见 [LICENSE](LICENSE)。如果需要闭源修改,或需要不同于 AGPL-3.0 的商业条款,请联系版权所有者获取单独的商业许可证。
95
+ ## 许可证
366
96
 
367
- 这是一个早期的单机应用,不是 Overleaf 的直接替代品。请根据实际运行环境审核并调整部署、备份和安全配置。
97
+ TexLite 使用 GNU Affero General Public License v3.0,详见 [LICENSE](LICENSE)。如需
98
+ 闭源修改,或需要不同于 AGPL-3.0 的商业条款,请联系版权所有者。
@@ -1,3 +1,3 @@
1
- import{u as ye,r as n,j as e}from"./react-BoEjKzFZ.js";import{j as u,M as H,L as p,G as q,K as ke,C as ie,k as ne,T as be,l as ve,P as Ce,a as l}from"./index-B9n8hfV0.js";import{M as Ne,a as we}from"./minus-BwzSZenU.js";const ze=u("CloudUpload",[["path",{d:"M12 13v8",key:"1l5pq0"}],["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242",key:"1pljnt"}],["path",{d:"m8 17 4-4 4 4",key:"1quai1"}]]);const ae=u("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);const G=u("Eye",[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);const oe=u("GitCommitHorizontal",[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["line",{x1:"3",x2:"9",y1:"12",y2:"12",key:"1dyftd"}],["line",{x1:"15",x2:"21",y1:"12",y2:"12",key:"oup4p8"}]]);const W=u("Github",[["path",{d:"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4",key:"tonef"}],["path",{d:"M9 18c-4.51 2-5-2-7-2",key:"9comsn"}]]);const Se=u("Minimize2",[["polyline",{points:"4 14 10 14 10 20",key:"11kfnr"}],["polyline",{points:"20 10 14 10 14 4",key:"rlmsce"}],["line",{x1:"14",x2:"21",y1:"10",y2:"3",key:"o5lafz"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14",key:"1atl0r"}]]);const Ee=u("RefreshCcw",[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"14sxne"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16",key:"1hlbsb"}],["path",{d:"M16 16h5v5",key:"ccwih5"}]]);const Te=u("Undo2",[["path",{d:"M9 14 4 9l5-5",key:"102s5s"}],["path",{d:"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11",key:"f3b9sd"}]]);function $e({open:h,project:o,onOpenChange:y,onBeforeMutation:r}){const{t:s,i18n:E}=ye(),[i,m]=n.useState(null),[J,K]=n.useState([]),[T,k]=n.useState(""),[F,V]=n.useState(()=>re(o.name)),[_,ce]=n.useState(!0),[D,Z]=n.useState(""),[b,M]=n.useState(null),[f,j]=n.useState(null),[U,$]=n.useState(!1),[le,v]=n.useState(!1),[R,L]=n.useState(!0),[P,A]=n.useState(!0),[a,C]=n.useState(""),[Q,N]=n.useState(""),[X,B]=n.useState(""),[g,x]=n.useState(!1),[w,Y]=n.useState(10),O=n.useRef(null),z=async(t=!1)=>{const c=await l(`/api/projects/${o.id}/git`);if(m(c.status),t&&(L(!c.status.tokenConfigured),A(!c.status.remoteUrl)),c.status.initialized&&c.status.latestCommit){const S=await l(`/api/projects/${o.id}/git/history`);K(S.commits)}else K([])};n.useEffect(()=>{if(!h){document.fullscreenElement&&document.exitFullscreen().catch(()=>{}),x(!1),k("");return}N(""),B(""),M(null),x(!1),V(re(o.name)),C("load"),r().then(()=>z(!0)).catch(t=>N(t instanceof Error?t.message:s("errors.generic"))).finally(()=>C(""))},[h,o.id]),n.useEffect(()=>{const t=()=>x(document.fullscreenElement===O.current);return document.addEventListener("fullscreenchange",t),()=>document.removeEventListener("fullscreenchange",t)},[]),n.useEffect(()=>{if(!g)return;const t=c=>{c.key==="Escape"&&!document.fullscreenElement&&x(!1)};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[g]);const d=async(t,c,S,ee)=>{C(t),N(""),B("");try{await c(),S&&B(S)}catch(se){const te=se instanceof Error?se.message:s("errors.generic");N(ee?`${ee}: ${te}`:te)}finally{C("")}},de=()=>d("token",async()=>{const t=await l(`/api/projects/${o.id}/git/token`,{method:"PUT",body:JSON.stringify({token:T})});m(t.status),k(""),L(!1)},s("git.tokenSaved")),he=()=>d("remove-token",async()=>{const t=await l(`/api/projects/${o.id}/git/token`,{method:"DELETE"});m(t.status),k("")},s("git.tokenRemoved")),ge=()=>d("repository",async()=>{const t=await l(`/api/projects/${o.id}/git/repository`,{method:"POST",body:JSON.stringify({name:F,private:_})});m(t.status),A(!1)},s("git.repositoryCreated")),ue=()=>d("commit",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));const t=await l(`/api/projects/${o.id}/git/commit`,{method:"POST",body:JSON.stringify({message:D})});m(t.status),Z(""),M(null),await z()},s("git.committed")),me=()=>d("push",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));const t=await l(`/api/projects/${o.id}/git/push`,{method:"POST"});m(t.status),await z()},s("git.pushed"),s("git.pushFailed")),I=t=>d("diff",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));const c=t?`?revision=${encodeURIComponent(t)}`:"";M(await l(`/api/projects/${o.id}/git/diff${c}`))}),fe=async()=>{if(g){document.fullscreenElement&&await document.exitFullscreen().catch(()=>{}),x(!1);return}const t=O.current;if(t?.requestFullscreen)try{await t.requestFullscreen()}catch{}x(!0)},xe=()=>{const t=f;t&&(j(null),d("checkout",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));await l(`/api/projects/${o.id}/git/checkout`,{method:"POST",body:JSON.stringify({revision:t==="branch"?null:t.sha,force:U})}),window.location.reload()}))},pe=()=>{v(!1),d("discard",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));await l(`/api/projects/${o.id}/git/discard`,{method:"POST"}),window.location.reload()})},je=a==="load"&&!i;return e.jsxs(e.Fragment,{children:[e.jsx(H,{open:h,extraWide:!0,className:g?"git-dialog-modal-fullscreen":void 0,title:s("git.title"),description:s("git.description"),onOpenChange:y,footer:e.jsx("button",{onClick:()=>y(!1),children:s("common.close")}),children:e.jsxs("div",{className:"git-dialog",children:[je&&e.jsxs("div",{className:"git-loading",children:[e.jsx(p,{className:"spin",size:22}),s("common.loading")]}),Q&&e.jsx("p",{className:"git-message error",children:Q}),X&&e.jsxs("p",{className:"git-message success",children:[e.jsx(q,{size:14}),X]}),i&&e.jsxs(e.Fragment,{children:[e.jsxs("section",{className:"git-section",children:[e.jsxs("button",{className:"git-section-toggle",type:"button","aria-expanded":R,onClick:()=>L(t=>!t),children:[e.jsxs("span",{className:"git-section-heading",children:[e.jsx(ke,{size:16}),e.jsxs("span",{children:[e.jsx("strong",{children:s("git.authentication")}),e.jsx("small",{children:i.tokenConfigured?s("git.connectedAs",{login:i.githubLogin}):s("git.authenticationHint")})]})]}),R?e.jsx(ie,{size:16}):e.jsx(ne,{size:16})]}),R&&e.jsxs("div",{className:"git-section-content",children:[e.jsxs("div",{className:"git-token-guidance",children:[e.jsx("strong",{children:s("git.recommendedAccessTitle")}),e.jsx("span",{children:s("git.recommendedAccess")})]}),i.tokenConfigured&&e.jsxs("div",{className:"git-account",children:[e.jsx(W,{size:17}),e.jsx("span",{children:s("git.connectedAs",{login:i.githubLogin})}),e.jsxs("button",{className:"danger-text",disabled:!!a,onClick:he,children:[e.jsx(be,{size:14}),s("git.removeToken")]})]}),e.jsxs("label",{className:"form-field",children:[i.tokenConfigured?s("git.replaceToken"):s("git.token"),e.jsx("input",{type:"password",autoComplete:"new-password",spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",value:T,placeholder:s("git.tokenPlaceholder"),onChange:t=>k(t.target.value)})]}),e.jsxs("div",{className:"git-inline-actions",children:[e.jsxs("a",{href:"https://github.com/settings/personal-access-tokens/new",target:"_blank",rel:"noreferrer",children:[s("git.createToken"),e.jsx(ae,{size:12})]}),e.jsxs("button",{disabled:!!a||T.trim().length<20,onClick:de,children:[a==="token"&&e.jsx(p,{className:"spin",size:13}),s("git.saveToken")]})]})]})]}),e.jsxs("section",{className:"git-section",children:[e.jsxs("button",{className:"git-section-toggle",type:"button","aria-expanded":P,onClick:()=>A(t=>!t),children:[e.jsxs("span",{className:"git-section-heading",children:[e.jsx(W,{size:16}),e.jsxs("span",{children:[e.jsx("strong",{children:s("git.repository")}),e.jsx("small",{children:i.remoteUrl?i.repositoryName??i.remoteUrl:i.initialized?s("git.localReady"):s("git.localPending")})]})]}),P?e.jsx(ie,{size:16}):e.jsx(ne,{size:16})]}),P&&e.jsx("div",{className:"git-section-content",children:i.remoteUrl?e.jsxs("div",{className:"git-repository-card",children:[e.jsxs("div",{children:[e.jsx("strong",{children:i.repositoryName??s("git.origin")}),e.jsxs("small",{children:[i.branch??s("git.detachedAt",{revision:i.latestCommit?.shortSha??"HEAD"})," · ",i.dirty?s("git.changedFiles",{count:i.changedFiles}):s("git.clean")]})]}),i.repositoryHtmlUrl&&e.jsxs("a",{href:i.repositoryHtmlUrl,target:"_blank",rel:"noreferrer",children:[e.jsx(ae,{size:14}),s("git.openGitHub")]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"form-field",children:[s("git.repositoryName"),e.jsx("input",{value:F,onChange:t=>V(t.target.value)})]}),e.jsxs("label",{className:"checkbox-field",children:[e.jsx("input",{type:"checkbox",checked:_,onChange:t=>ce(t.target.checked)}),s("git.privateRepository")]}),e.jsxs("button",{className:"git-primary-action",disabled:!!a||!i.tokenConfigured||!F.trim(),onClick:ge,children:[a==="repository"?e.jsx(p,{className:"spin",size:14}):e.jsx(W,{size:14}),s("git.createRepository")]})]})})]}),i.initialized&&e.jsxs("section",{className:"git-section",children:[e.jsxs("div",{className:"git-section-heading",children:[e.jsx(oe,{size:16}),e.jsxs("div",{children:[e.jsx("strong",{children:s("git.commitAndPush")}),e.jsx("small",{children:i.branch?s("git.identity",{username:o.ownerUsername}):s("git.detachedHead")})]})]}),e.jsxs("label",{className:"form-field",children:[s("git.commitMessage"),e.jsx("textarea",{rows:3,value:D,placeholder:s("git.commitPlaceholder"),onChange:t=>Z(t.target.value)})]}),e.jsxs("div",{className:"git-action-row",children:[e.jsxs("button",{title:i.dirty?void 0:s("git.noChangesToCommit"),disabled:!!a||!i.branch||!i.dirty||!D.trim(),onClick:ue,children:[a==="commit"?e.jsx(p,{className:"spin",size:14}):e.jsx(oe,{size:14}),s("git.commit")]}),e.jsxs("button",{disabled:!!a||!i.branch||!i.tokenConfigured||!i.remoteUrl||!i.latestCommit,onClick:me,children:[a==="push"?e.jsx(p,{className:"spin",size:14}):e.jsx(ze,{size:14}),s("git.push"),i.ahead>0&&e.jsx("span",{className:"git-count",children:i.ahead})]}),e.jsxs("button",{disabled:!!a||!i.latestCommit,onClick:()=>{I()},children:[a==="diff"?e.jsx(p,{className:"spin",size:14}):e.jsx(G,{size:14}),s("git.workingDiff")]}),e.jsxs("button",{className:"git-discard-button",title:i.restorable?s("git.discardChanges"):s("git.noChangesToDiscard"),disabled:!!a||!i.latestCommit||!i.restorable,onClick:()=>v(!0),children:[e.jsx(ve,{size:14}),s("git.discardChanges")]}),!i.branch&&e.jsxs("button",{disabled:!!a,onClick:()=>{$(!1),j("branch")},children:[e.jsx(q,{size:14}),s("git.returnToBranch",{branch:i.defaultBranch})]}),e.jsxs("button",{disabled:!!a,onClick:()=>{d("refresh",z)},children:[e.jsx(Ee,{className:a==="refresh"?"spin":"",size:14}),s("git.refresh")]})]})]}),b&&e.jsxs("section",{ref:O,className:`git-section git-diff-section${g?" is-fullscreen":""}`,children:[e.jsxs("div",{className:"git-diff-heading",children:[e.jsxs("div",{className:"git-section-heading",children:[e.jsx(G,{size:16}),e.jsxs("div",{children:[e.jsx("strong",{children:s("git.diffTitle")}),e.jsxs("small",{children:[b.title,b.truncated?` · ${s("git.diffTruncated")}`:""]})]})]}),e.jsxs("div",{className:"git-diff-controls",children:[e.jsxs("div",{className:"git-diff-font-controls",role:"group","aria-label":s("git.diffFontSize"),children:[e.jsx("button",{type:"button",className:"git-diff-font-button",disabled:w<=8,title:s("git.diffFontDecrease"),"aria-label":s("git.diffFontDecrease"),onClick:()=>Y(t=>Math.max(8,t-1)),children:e.jsx(Ne,{size:14})}),e.jsxs("span",{className:"git-diff-font-value","aria-live":"polite",children:[w,"px"]}),e.jsx("button",{type:"button",className:"git-diff-font-button",disabled:w>=24,title:s("git.diffFontIncrease"),"aria-label":s("git.diffFontIncrease"),onClick:()=>Y(t=>Math.min(24,t+1)),children:e.jsx(Ce,{size:14})})]}),e.jsx("button",{type:"button",className:"git-diff-fullscreen",title:s(g?"git.exitFullscreenDiff":"git.fullscreenDiff"),"aria-label":s(g?"git.exitFullscreenDiff":"git.fullscreenDiff"),onClick:()=>{fe()},children:g?e.jsx(Se,{size:15}):e.jsx(we,{size:15})})]})]}),e.jsx(Fe,{content:b.diff,empty:s("git.noChanges"),fontSize:w})]}),i.initialized&&e.jsxs("section",{className:"git-section",children:[e.jsxs("div",{className:"git-section-heading",children:[e.jsx(q,{size:16}),e.jsxs("div",{children:[e.jsx("strong",{children:s("git.history")}),e.jsx("small",{children:s("git.historyHint")})]})]}),e.jsxs("div",{className:"git-history",children:[J.map(t=>e.jsxs("article",{children:[e.jsx("code",{children:t.shortSha}),e.jsxs("div",{children:[e.jsx("strong",{children:t.message}),e.jsxs("small",{children:[t.authorName," · ",new Date(t.authoredAt).toLocaleString(E.resolvedLanguage)]})]}),e.jsxs("span",{children:[e.jsx("button",{title:s("git.viewCommitDiff"),disabled:!!a,onClick:()=>{I(t.sha)},children:e.jsx(G,{size:14})}),e.jsx("button",{title:s("git.checkoutVersion"),disabled:!!a,onClick:()=>{$(!1),j(t)},children:e.jsx(Te,{size:14})})]})]},t.sha)),J.length===0&&e.jsx("p",{className:"muted",children:s("git.noCommits")})]})]})]})]})}),e.jsx(H,{open:!!f,title:s(f==="branch"?"git.returnTitle":"git.checkoutTitle"),description:f==="branch"?s("git.returnDescription",{branch:i?.defaultBranch??"main"}):s("git.checkoutDescription",{revision:f?.shortSha??"",message:f?.message??""}),onOpenChange:t=>{t||j(null)},footer:e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>j(null),children:s("common.cancel")}),e.jsx("button",{className:U?"danger":"primary",onClick:xe,children:s("git.checkout")})]}),children:e.jsxs("label",{className:"git-force-checkout",children:[e.jsx("input",{type:"checkbox",checked:U,onChange:t=>$(t.target.checked)}),e.jsxs("span",{children:[e.jsx("strong",{children:s("git.forceCheckout")}),e.jsx("small",{children:s("git.forceCheckoutDescription")})]})]})}),e.jsx(H,{open:le,title:s("git.discardTitle"),description:s("git.discardDescription"),onOpenChange:v,footer:e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>v(!1),children:s("common.cancel")}),e.jsx("button",{className:"danger",onClick:pe,children:s("git.discardConfirm")})]}),children:e.jsx(e.Fragment,{})})]})}function Fe({content:h,empty:o,fontSize:y}){return h.trim()?e.jsx("pre",{className:"git-diff",style:{fontSize:`${y}px`},children:h.split(`
1
+ import{u as ye,r as n,j as e}from"./react-BoEjKzFZ.js";import{j as u,M as H,L as p,G as q,K as ke,C as ie,k as ne,T as be,l as ve,P as Ce,a as l}from"./index-vpWlpUOr.js";import{M as Ne,a as we}from"./minus-DR-ttrx3.js";const ze=u("CloudUpload",[["path",{d:"M12 13v8",key:"1l5pq0"}],["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242",key:"1pljnt"}],["path",{d:"m8 17 4-4 4 4",key:"1quai1"}]]);const ae=u("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);const G=u("Eye",[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);const oe=u("GitCommitHorizontal",[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["line",{x1:"3",x2:"9",y1:"12",y2:"12",key:"1dyftd"}],["line",{x1:"15",x2:"21",y1:"12",y2:"12",key:"oup4p8"}]]);const W=u("Github",[["path",{d:"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4",key:"tonef"}],["path",{d:"M9 18c-4.51 2-5-2-7-2",key:"9comsn"}]]);const Se=u("Minimize2",[["polyline",{points:"4 14 10 14 10 20",key:"11kfnr"}],["polyline",{points:"20 10 14 10 14 4",key:"rlmsce"}],["line",{x1:"14",x2:"21",y1:"10",y2:"3",key:"o5lafz"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14",key:"1atl0r"}]]);const Ee=u("RefreshCcw",[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"14sxne"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16",key:"1hlbsb"}],["path",{d:"M16 16h5v5",key:"ccwih5"}]]);const Te=u("Undo2",[["path",{d:"M9 14 4 9l5-5",key:"102s5s"}],["path",{d:"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11",key:"f3b9sd"}]]);function $e({open:h,project:o,onOpenChange:y,onBeforeMutation:r}){const{t:s,i18n:E}=ye(),[i,m]=n.useState(null),[J,K]=n.useState([]),[T,k]=n.useState(""),[F,V]=n.useState(()=>re(o.name)),[_,ce]=n.useState(!0),[D,Z]=n.useState(""),[b,M]=n.useState(null),[f,j]=n.useState(null),[U,$]=n.useState(!1),[le,v]=n.useState(!1),[R,L]=n.useState(!0),[P,A]=n.useState(!0),[a,C]=n.useState(""),[Q,N]=n.useState(""),[X,B]=n.useState(""),[g,x]=n.useState(!1),[w,Y]=n.useState(10),O=n.useRef(null),z=async(t=!1)=>{const c=await l(`/api/projects/${o.id}/git`);if(m(c.status),t&&(L(!c.status.tokenConfigured),A(!c.status.remoteUrl)),c.status.initialized&&c.status.latestCommit){const S=await l(`/api/projects/${o.id}/git/history`);K(S.commits)}else K([])};n.useEffect(()=>{if(!h){document.fullscreenElement&&document.exitFullscreen().catch(()=>{}),x(!1),k("");return}N(""),B(""),M(null),x(!1),V(re(o.name)),C("load"),r().then(()=>z(!0)).catch(t=>N(t instanceof Error?t.message:s("errors.generic"))).finally(()=>C(""))},[h,o.id]),n.useEffect(()=>{const t=()=>x(document.fullscreenElement===O.current);return document.addEventListener("fullscreenchange",t),()=>document.removeEventListener("fullscreenchange",t)},[]),n.useEffect(()=>{if(!g)return;const t=c=>{c.key==="Escape"&&!document.fullscreenElement&&x(!1)};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[g]);const d=async(t,c,S,ee)=>{C(t),N(""),B("");try{await c(),S&&B(S)}catch(se){const te=se instanceof Error?se.message:s("errors.generic");N(ee?`${ee}: ${te}`:te)}finally{C("")}},de=()=>d("token",async()=>{const t=await l(`/api/projects/${o.id}/git/token`,{method:"PUT",body:JSON.stringify({token:T})});m(t.status),k(""),L(!1)},s("git.tokenSaved")),he=()=>d("remove-token",async()=>{const t=await l(`/api/projects/${o.id}/git/token`,{method:"DELETE"});m(t.status),k("")},s("git.tokenRemoved")),ge=()=>d("repository",async()=>{const t=await l(`/api/projects/${o.id}/git/repository`,{method:"POST",body:JSON.stringify({name:F,private:_})});m(t.status),A(!1)},s("git.repositoryCreated")),ue=()=>d("commit",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));const t=await l(`/api/projects/${o.id}/git/commit`,{method:"POST",body:JSON.stringify({message:D})});m(t.status),Z(""),M(null),await z()},s("git.committed")),me=()=>d("push",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));const t=await l(`/api/projects/${o.id}/git/push`,{method:"POST"});m(t.status),await z()},s("git.pushed"),s("git.pushFailed")),I=t=>d("diff",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));const c=t?`?revision=${encodeURIComponent(t)}`:"";M(await l(`/api/projects/${o.id}/git/diff${c}`))}),fe=async()=>{if(g){document.fullscreenElement&&await document.exitFullscreen().catch(()=>{}),x(!1);return}const t=O.current;if(t?.requestFullscreen)try{await t.requestFullscreen()}catch{}x(!0)},xe=()=>{const t=f;t&&(j(null),d("checkout",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));await l(`/api/projects/${o.id}/git/checkout`,{method:"POST",body:JSON.stringify({revision:t==="branch"?null:t.sha,force:U})}),window.location.reload()}))},pe=()=>{v(!1),d("discard",async()=>{if(!await r())throw new Error(s("errors.collaborationUnavailable"));await l(`/api/projects/${o.id}/git/discard`,{method:"POST"}),window.location.reload()})},je=a==="load"&&!i;return e.jsxs(e.Fragment,{children:[e.jsx(H,{open:h,extraWide:!0,className:g?"git-dialog-modal-fullscreen":void 0,title:s("git.title"),description:s("git.description"),onOpenChange:y,footer:e.jsx("button",{onClick:()=>y(!1),children:s("common.close")}),children:e.jsxs("div",{className:"git-dialog",children:[je&&e.jsxs("div",{className:"git-loading",children:[e.jsx(p,{className:"spin",size:22}),s("common.loading")]}),Q&&e.jsx("p",{className:"git-message error",children:Q}),X&&e.jsxs("p",{className:"git-message success",children:[e.jsx(q,{size:14}),X]}),i&&e.jsxs(e.Fragment,{children:[e.jsxs("section",{className:"git-section",children:[e.jsxs("button",{className:"git-section-toggle",type:"button","aria-expanded":R,onClick:()=>L(t=>!t),children:[e.jsxs("span",{className:"git-section-heading",children:[e.jsx(ke,{size:16}),e.jsxs("span",{children:[e.jsx("strong",{children:s("git.authentication")}),e.jsx("small",{children:i.tokenConfigured?s("git.connectedAs",{login:i.githubLogin}):s("git.authenticationHint")})]})]}),R?e.jsx(ie,{size:16}):e.jsx(ne,{size:16})]}),R&&e.jsxs("div",{className:"git-section-content",children:[e.jsxs("div",{className:"git-token-guidance",children:[e.jsx("strong",{children:s("git.recommendedAccessTitle")}),e.jsx("span",{children:s("git.recommendedAccess")})]}),i.tokenConfigured&&e.jsxs("div",{className:"git-account",children:[e.jsx(W,{size:17}),e.jsx("span",{children:s("git.connectedAs",{login:i.githubLogin})}),e.jsxs("button",{className:"danger-text",disabled:!!a,onClick:he,children:[e.jsx(be,{size:14}),s("git.removeToken")]})]}),e.jsxs("label",{className:"form-field",children:[i.tokenConfigured?s("git.replaceToken"):s("git.token"),e.jsx("input",{type:"password",autoComplete:"new-password",spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",value:T,placeholder:s("git.tokenPlaceholder"),onChange:t=>k(t.target.value)})]}),e.jsxs("div",{className:"git-inline-actions",children:[e.jsxs("a",{href:"https://github.com/settings/personal-access-tokens/new",target:"_blank",rel:"noreferrer",children:[s("git.createToken"),e.jsx(ae,{size:12})]}),e.jsxs("button",{disabled:!!a||T.trim().length<20,onClick:de,children:[a==="token"&&e.jsx(p,{className:"spin",size:13}),s("git.saveToken")]})]})]})]}),e.jsxs("section",{className:"git-section",children:[e.jsxs("button",{className:"git-section-toggle",type:"button","aria-expanded":P,onClick:()=>A(t=>!t),children:[e.jsxs("span",{className:"git-section-heading",children:[e.jsx(W,{size:16}),e.jsxs("span",{children:[e.jsx("strong",{children:s("git.repository")}),e.jsx("small",{children:i.remoteUrl?i.repositoryName??i.remoteUrl:i.initialized?s("git.localReady"):s("git.localPending")})]})]}),P?e.jsx(ie,{size:16}):e.jsx(ne,{size:16})]}),P&&e.jsx("div",{className:"git-section-content",children:i.remoteUrl?e.jsxs("div",{className:"git-repository-card",children:[e.jsxs("div",{children:[e.jsx("strong",{children:i.repositoryName??s("git.origin")}),e.jsxs("small",{children:[i.branch??s("git.detachedAt",{revision:i.latestCommit?.shortSha??"HEAD"})," · ",i.dirty?s("git.changedFiles",{count:i.changedFiles}):s("git.clean")]})]}),i.repositoryHtmlUrl&&e.jsxs("a",{href:i.repositoryHtmlUrl,target:"_blank",rel:"noreferrer",children:[e.jsx(ae,{size:14}),s("git.openGitHub")]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"form-field",children:[s("git.repositoryName"),e.jsx("input",{value:F,onChange:t=>V(t.target.value)})]}),e.jsxs("label",{className:"checkbox-field",children:[e.jsx("input",{type:"checkbox",checked:_,onChange:t=>ce(t.target.checked)}),s("git.privateRepository")]}),e.jsxs("button",{className:"git-primary-action",disabled:!!a||!i.tokenConfigured||!F.trim(),onClick:ge,children:[a==="repository"?e.jsx(p,{className:"spin",size:14}):e.jsx(W,{size:14}),s("git.createRepository")]})]})})]}),i.initialized&&e.jsxs("section",{className:"git-section",children:[e.jsxs("div",{className:"git-section-heading",children:[e.jsx(oe,{size:16}),e.jsxs("div",{children:[e.jsx("strong",{children:s("git.commitAndPush")}),e.jsx("small",{children:i.branch?s("git.identity",{username:o.ownerUsername}):s("git.detachedHead")})]})]}),e.jsxs("label",{className:"form-field",children:[s("git.commitMessage"),e.jsx("textarea",{rows:3,value:D,placeholder:s("git.commitPlaceholder"),onChange:t=>Z(t.target.value)})]}),e.jsxs("div",{className:"git-action-row",children:[e.jsxs("button",{title:i.dirty?void 0:s("git.noChangesToCommit"),disabled:!!a||!i.branch||!i.dirty||!D.trim(),onClick:ue,children:[a==="commit"?e.jsx(p,{className:"spin",size:14}):e.jsx(oe,{size:14}),s("git.commit")]}),e.jsxs("button",{disabled:!!a||!i.branch||!i.tokenConfigured||!i.remoteUrl||!i.latestCommit,onClick:me,children:[a==="push"?e.jsx(p,{className:"spin",size:14}):e.jsx(ze,{size:14}),s("git.push"),i.ahead>0&&e.jsx("span",{className:"git-count",children:i.ahead})]}),e.jsxs("button",{disabled:!!a||!i.latestCommit,onClick:()=>{I()},children:[a==="diff"?e.jsx(p,{className:"spin",size:14}):e.jsx(G,{size:14}),s("git.workingDiff")]}),e.jsxs("button",{className:"git-discard-button",title:i.restorable?s("git.discardChanges"):s("git.noChangesToDiscard"),disabled:!!a||!i.latestCommit||!i.restorable,onClick:()=>v(!0),children:[e.jsx(ve,{size:14}),s("git.discardChanges")]}),!i.branch&&e.jsxs("button",{disabled:!!a,onClick:()=>{$(!1),j("branch")},children:[e.jsx(q,{size:14}),s("git.returnToBranch",{branch:i.defaultBranch})]}),e.jsxs("button",{disabled:!!a,onClick:()=>{d("refresh",z)},children:[e.jsx(Ee,{className:a==="refresh"?"spin":"",size:14}),s("git.refresh")]})]})]}),b&&e.jsxs("section",{ref:O,className:`git-section git-diff-section${g?" is-fullscreen":""}`,children:[e.jsxs("div",{className:"git-diff-heading",children:[e.jsxs("div",{className:"git-section-heading",children:[e.jsx(G,{size:16}),e.jsxs("div",{children:[e.jsx("strong",{children:s("git.diffTitle")}),e.jsxs("small",{children:[b.title,b.truncated?` · ${s("git.diffTruncated")}`:""]})]})]}),e.jsxs("div",{className:"git-diff-controls",children:[e.jsxs("div",{className:"git-diff-font-controls",role:"group","aria-label":s("git.diffFontSize"),children:[e.jsx("button",{type:"button",className:"git-diff-font-button",disabled:w<=8,title:s("git.diffFontDecrease"),"aria-label":s("git.diffFontDecrease"),onClick:()=>Y(t=>Math.max(8,t-1)),children:e.jsx(Ne,{size:14})}),e.jsxs("span",{className:"git-diff-font-value","aria-live":"polite",children:[w,"px"]}),e.jsx("button",{type:"button",className:"git-diff-font-button",disabled:w>=24,title:s("git.diffFontIncrease"),"aria-label":s("git.diffFontIncrease"),onClick:()=>Y(t=>Math.min(24,t+1)),children:e.jsx(Ce,{size:14})})]}),e.jsx("button",{type:"button",className:"git-diff-fullscreen",title:s(g?"git.exitFullscreenDiff":"git.fullscreenDiff"),"aria-label":s(g?"git.exitFullscreenDiff":"git.fullscreenDiff"),onClick:()=>{fe()},children:g?e.jsx(Se,{size:15}):e.jsx(we,{size:15})})]})]}),e.jsx(Fe,{content:b.diff,empty:s("git.noChanges"),fontSize:w})]}),i.initialized&&e.jsxs("section",{className:"git-section",children:[e.jsxs("div",{className:"git-section-heading",children:[e.jsx(q,{size:16}),e.jsxs("div",{children:[e.jsx("strong",{children:s("git.history")}),e.jsx("small",{children:s("git.historyHint")})]})]}),e.jsxs("div",{className:"git-history",children:[J.map(t=>e.jsxs("article",{children:[e.jsx("code",{children:t.shortSha}),e.jsxs("div",{children:[e.jsx("strong",{children:t.message}),e.jsxs("small",{children:[t.authorName," · ",new Date(t.authoredAt).toLocaleString(E.resolvedLanguage)]})]}),e.jsxs("span",{children:[e.jsx("button",{title:s("git.viewCommitDiff"),disabled:!!a,onClick:()=>{I(t.sha)},children:e.jsx(G,{size:14})}),e.jsx("button",{title:s("git.checkoutVersion"),disabled:!!a,onClick:()=>{$(!1),j(t)},children:e.jsx(Te,{size:14})})]})]},t.sha)),J.length===0&&e.jsx("p",{className:"muted",children:s("git.noCommits")})]})]})]})]})}),e.jsx(H,{open:!!f,title:s(f==="branch"?"git.returnTitle":"git.checkoutTitle"),description:f==="branch"?s("git.returnDescription",{branch:i?.defaultBranch??"main"}):s("git.checkoutDescription",{revision:f?.shortSha??"",message:f?.message??""}),onOpenChange:t=>{t||j(null)},footer:e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>j(null),children:s("common.cancel")}),e.jsx("button",{className:U?"danger":"primary",onClick:xe,children:s("git.checkout")})]}),children:e.jsxs("label",{className:"git-force-checkout",children:[e.jsx("input",{type:"checkbox",checked:U,onChange:t=>$(t.target.checked)}),e.jsxs("span",{children:[e.jsx("strong",{children:s("git.forceCheckout")}),e.jsx("small",{children:s("git.forceCheckoutDescription")})]})]})}),e.jsx(H,{open:le,title:s("git.discardTitle"),description:s("git.discardDescription"),onOpenChange:v,footer:e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>v(!1),children:s("common.cancel")}),e.jsx("button",{className:"danger",onClick:pe,children:s("git.discardConfirm")})]}),children:e.jsx(e.Fragment,{})})]})}function Fe({content:h,empty:o,fontSize:y}){return h.trim()?e.jsx("pre",{className:"git-diff",style:{fontSize:`${y}px`},children:h.split(`
2
2
  `).map((r,s)=>{const E=r.startsWith("+")&&!r.startsWith("+++")?"addition":r.startsWith("-")&&!r.startsWith("---")?"deletion":r.startsWith("@@")?"hunk":r.startsWith("diff ")?"header":"";return e.jsxs("span",{className:E,children:[r,`
3
3
  `]},s)})}):e.jsx("div",{className:"git-diff-empty",children:o})}function re(h){return h.trim().replace(/\s+/g,"-").replace(/[^A-Za-z0-9._-]/g,"-").replace(/-+/g,"-").replace(/^[.-]+|[.-]+$/g,"").slice(0,100)||"texlite-project"}export{$e as GitDialog};
@@ -1,4 +1,4 @@
1
- import{g as re,u as ne,r as I,j as u}from"./react-BoEjKzFZ.js";import{j as z,a as R,M as ie,L as O,T as J,l as Q,S as se,F as ae,n as G}from"./index-B9n8hfV0.js";const te=z("Clock3",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["polyline",{points:"12 6 12 12 16.5 12",key:"1aq6pp"}]]);const V=z("FileClock",[["path",{d:"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3",key:"37hlfg"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["circle",{cx:"8",cy:"16",r:"6",key:"10v15b"}],["path",{d:"M9.5 17.5 8 16.25V14",key:"1o80t2"}]]);const le=z("HardDrive",[["line",{x1:"22",x2:"2",y1:"12",y2:"12",key:"1y58io"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"oot6mr"}],["line",{x1:"6",x2:"6.01",y1:"16",y2:"16",key:"sgf278"}],["line",{x1:"10",x2:"10.01",y1:"16",y2:"16",key:"1l4acy"}]]);const he=z("Tag",[["path",{d:"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z",key:"vktsd0"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor",key:"kqv944"}]]);var H={exports:{}},K;function oe(){return K||(K=1,(function(C){var o=function(){this.Diff_Timeout=1,this.Diff_EditCost=4,this.Match_Threshold=.5,this.Match_Distance=1e3,this.Patch_DeleteThreshold=.5,this.Patch_Margin=4,this.Match_MaxBits=32},k=-1,A=1,f=0;o.Diff=function(e,r){return[e,r]},o.prototype.diff_main=function(e,r,n,s){typeof s>"u"&&(this.Diff_Timeout<=0?s=Number.MAX_VALUE:s=new Date().getTime()+this.Diff_Timeout*1e3);var a=s;if(e==null||r==null)throw new Error("Null input. (diff_main)");if(e==r)return e?[new o.Diff(f,e)]:[];typeof n>"u"&&(n=!0);var i=n,t=this.diff_commonPrefix(e,r),l=e.substring(0,t);e=e.substring(t),r=r.substring(t),t=this.diff_commonSuffix(e,r);var h=e.substring(e.length-t);e=e.substring(0,e.length-t),r=r.substring(0,r.length-t);var g=this.diff_compute_(e,r,i,a);return l&&g.unshift(new o.Diff(f,l)),h&&g.push(new o.Diff(f,h)),this.diff_cleanupMerge(g),g},o.prototype.diff_compute_=function(e,r,n,s){var a;if(!e)return[new o.Diff(A,r)];if(!r)return[new o.Diff(k,e)];var i=e.length>r.length?e:r,t=e.length>r.length?r:e,l=i.indexOf(t);if(l!=-1)return a=[new o.Diff(A,i.substring(0,l)),new o.Diff(f,t),new o.Diff(A,i.substring(l+t.length))],e.length>r.length&&(a[0][0]=a[2][0]=k),a;if(t.length==1)return[new o.Diff(k,e),new o.Diff(A,r)];var h=this.diff_halfMatch_(e,r);if(h){var g=h[0],c=h[1],v=h[2],m=h[3],b=h[4],p=this.diff_main(g,v,n,s),M=this.diff_main(c,m,n,s);return p.concat([new o.Diff(f,b)],M)}return n&&e.length>100&&r.length>100?this.diff_lineMode_(e,r,s):this.diff_bisect_(e,r,s)},o.prototype.diff_lineMode_=function(e,r,n){var s=this.diff_linesToChars_(e,r);e=s.chars1,r=s.chars2;var a=s.lineArray,i=this.diff_main(e,r,!1,n);this.diff_charsToLines_(i,a),this.diff_cleanupSemantic(i),i.push(new o.Diff(f,""));for(var t=0,l=0,h=0,g="",c="";t<i.length;){switch(i[t][0]){case A:h++,c+=i[t][1];break;case k:l++,g+=i[t][1];break;case f:if(l>=1&&h>=1){i.splice(t-l-h,l+h),t=t-l-h;for(var v=this.diff_main(g,c,!1,n),m=v.length-1;m>=0;m--)i.splice(t,0,v[m]);t=t+v.length}h=0,l=0,g="",c="";break}t++}return i.pop(),i},o.prototype.diff_bisect_=function(e,r,n){for(var s=e.length,a=r.length,i=Math.ceil((s+a)/2),t=i,l=2*i,h=new Array(l),g=new Array(l),c=0;c<l;c++)h[c]=-1,g[c]=-1;h[t+1]=0,g[t+1]=0;for(var v=s-a,m=v%2!=0,b=0,p=0,M=0,E=0,_=0;_<i&&!(new Date().getTime()>n);_++){for(var S=-_+b;S<=_-p;S+=2){var D=t+S,w;S==-_||S!=_&&h[D-1]<h[D+1]?w=h[D+1]:w=h[D-1]+1;for(var N=w-S;w<s&&N<a&&e.charAt(w)==r.charAt(N);)w++,N++;if(h[D]=w,w>s)p+=2;else if(N>a)b+=2;else if(m){var j=t+v-S;if(j>=0&&j<l&&g[j]!=-1){var T=s-g[j];if(w>=T)return this.diff_bisectSplit_(e,r,w,N,n)}}}for(var P=-_+M;P<=_-E;P+=2){var j=t+P,T;P==-_||P!=_&&g[j-1]<g[j+1]?T=g[j+1]:T=g[j-1]+1;for(var B=T-P;T<s&&B<a&&e.charAt(s-T-1)==r.charAt(a-B-1);)T++,B++;if(g[j]=T,T>s)E+=2;else if(B>a)M+=2;else if(!m){var D=t+v-P;if(D>=0&&D<l&&h[D]!=-1){var w=h[D],N=t+w-D;if(T=s-T,w>=T)return this.diff_bisectSplit_(e,r,w,N,n)}}}}return[new o.Diff(k,e),new o.Diff(A,r)]},o.prototype.diff_bisectSplit_=function(e,r,n,s,a){var i=e.substring(0,n),t=r.substring(0,s),l=e.substring(n),h=r.substring(s),g=this.diff_main(i,t,!1,a),c=this.diff_main(l,h,!1,a);return g.concat(c)},o.prototype.diff_linesToChars_=function(e,r){var n=[],s={};n[0]="";function a(h){for(var g="",c=0,v=-1,m=n.length;v<h.length-1;){v=h.indexOf(`
1
+ import{g as re,u as ne,r as I,j as u}from"./react-BoEjKzFZ.js";import{j as z,a as R,M as ie,L as O,T as J,l as Q,S as se,F as ae,n as G}from"./index-vpWlpUOr.js";const te=z("Clock3",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["polyline",{points:"12 6 12 12 16.5 12",key:"1aq6pp"}]]);const V=z("FileClock",[["path",{d:"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3",key:"37hlfg"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["circle",{cx:"8",cy:"16",r:"6",key:"10v15b"}],["path",{d:"M9.5 17.5 8 16.25V14",key:"1o80t2"}]]);const le=z("HardDrive",[["line",{x1:"22",x2:"2",y1:"12",y2:"12",key:"1y58io"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"oot6mr"}],["line",{x1:"6",x2:"6.01",y1:"16",y2:"16",key:"sgf278"}],["line",{x1:"10",x2:"10.01",y1:"16",y2:"16",key:"1l4acy"}]]);const he=z("Tag",[["path",{d:"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z",key:"vktsd0"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor",key:"kqv944"}]]);var H={exports:{}},K;function oe(){return K||(K=1,(function(C){var o=function(){this.Diff_Timeout=1,this.Diff_EditCost=4,this.Match_Threshold=.5,this.Match_Distance=1e3,this.Patch_DeleteThreshold=.5,this.Patch_Margin=4,this.Match_MaxBits=32},k=-1,A=1,f=0;o.Diff=function(e,r){return[e,r]},o.prototype.diff_main=function(e,r,n,s){typeof s>"u"&&(this.Diff_Timeout<=0?s=Number.MAX_VALUE:s=new Date().getTime()+this.Diff_Timeout*1e3);var a=s;if(e==null||r==null)throw new Error("Null input. (diff_main)");if(e==r)return e?[new o.Diff(f,e)]:[];typeof n>"u"&&(n=!0);var i=n,t=this.diff_commonPrefix(e,r),l=e.substring(0,t);e=e.substring(t),r=r.substring(t),t=this.diff_commonSuffix(e,r);var h=e.substring(e.length-t);e=e.substring(0,e.length-t),r=r.substring(0,r.length-t);var g=this.diff_compute_(e,r,i,a);return l&&g.unshift(new o.Diff(f,l)),h&&g.push(new o.Diff(f,h)),this.diff_cleanupMerge(g),g},o.prototype.diff_compute_=function(e,r,n,s){var a;if(!e)return[new o.Diff(A,r)];if(!r)return[new o.Diff(k,e)];var i=e.length>r.length?e:r,t=e.length>r.length?r:e,l=i.indexOf(t);if(l!=-1)return a=[new o.Diff(A,i.substring(0,l)),new o.Diff(f,t),new o.Diff(A,i.substring(l+t.length))],e.length>r.length&&(a[0][0]=a[2][0]=k),a;if(t.length==1)return[new o.Diff(k,e),new o.Diff(A,r)];var h=this.diff_halfMatch_(e,r);if(h){var g=h[0],c=h[1],v=h[2],m=h[3],b=h[4],p=this.diff_main(g,v,n,s),M=this.diff_main(c,m,n,s);return p.concat([new o.Diff(f,b)],M)}return n&&e.length>100&&r.length>100?this.diff_lineMode_(e,r,s):this.diff_bisect_(e,r,s)},o.prototype.diff_lineMode_=function(e,r,n){var s=this.diff_linesToChars_(e,r);e=s.chars1,r=s.chars2;var a=s.lineArray,i=this.diff_main(e,r,!1,n);this.diff_charsToLines_(i,a),this.diff_cleanupSemantic(i),i.push(new o.Diff(f,""));for(var t=0,l=0,h=0,g="",c="";t<i.length;){switch(i[t][0]){case A:h++,c+=i[t][1];break;case k:l++,g+=i[t][1];break;case f:if(l>=1&&h>=1){i.splice(t-l-h,l+h),t=t-l-h;for(var v=this.diff_main(g,c,!1,n),m=v.length-1;m>=0;m--)i.splice(t,0,v[m]);t=t+v.length}h=0,l=0,g="",c="";break}t++}return i.pop(),i},o.prototype.diff_bisect_=function(e,r,n){for(var s=e.length,a=r.length,i=Math.ceil((s+a)/2),t=i,l=2*i,h=new Array(l),g=new Array(l),c=0;c<l;c++)h[c]=-1,g[c]=-1;h[t+1]=0,g[t+1]=0;for(var v=s-a,m=v%2!=0,b=0,p=0,M=0,E=0,_=0;_<i&&!(new Date().getTime()>n);_++){for(var S=-_+b;S<=_-p;S+=2){var D=t+S,w;S==-_||S!=_&&h[D-1]<h[D+1]?w=h[D+1]:w=h[D-1]+1;for(var N=w-S;w<s&&N<a&&e.charAt(w)==r.charAt(N);)w++,N++;if(h[D]=w,w>s)p+=2;else if(N>a)b+=2;else if(m){var j=t+v-S;if(j>=0&&j<l&&g[j]!=-1){var T=s-g[j];if(w>=T)return this.diff_bisectSplit_(e,r,w,N,n)}}}for(var P=-_+M;P<=_-E;P+=2){var j=t+P,T;P==-_||P!=_&&g[j-1]<g[j+1]?T=g[j+1]:T=g[j-1]+1;for(var B=T-P;T<s&&B<a&&e.charAt(s-T-1)==r.charAt(a-B-1);)T++,B++;if(g[j]=T,T>s)E+=2;else if(B>a)M+=2;else if(!m){var D=t+v-P;if(D>=0&&D<l&&h[D]!=-1){var w=h[D],N=t+w-D;if(T=s-T,w>=T)return this.diff_bisectSplit_(e,r,w,N,n)}}}}return[new o.Diff(k,e),new o.Diff(A,r)]},o.prototype.diff_bisectSplit_=function(e,r,n,s,a){var i=e.substring(0,n),t=r.substring(0,s),l=e.substring(n),h=r.substring(s),g=this.diff_main(i,t,!1,a),c=this.diff_main(l,h,!1,a);return g.concat(c)},o.prototype.diff_linesToChars_=function(e,r){var n=[],s={};n[0]="";function a(h){for(var g="",c=0,v=-1,m=n.length;v<h.length-1;){v=h.indexOf(`
2
2
  `,c),v==-1&&(v=h.length-1);var b=h.substring(c,v+1);(s.hasOwnProperty?s.hasOwnProperty(b):s[b]!==void 0)?g+=String.fromCharCode(s[b]):(m==i&&(b=h.substring(c),v=h.length),g+=String.fromCharCode(m),s[b]=m,n[m++]=b),c=v+1}return g}var i=4e4,t=a(e);i=65535;var l=a(r);return{chars1:t,chars2:l,lineArray:n}},o.prototype.diff_charsToLines_=function(e,r){for(var n=0;n<e.length;n++){for(var s=e[n][1],a=[],i=0;i<s.length;i++)a[i]=r[s.charCodeAt(i)];e[n][1]=a.join("")}},o.prototype.diff_commonPrefix=function(e,r){if(!e||!r||e.charAt(0)!=r.charAt(0))return 0;for(var n=0,s=Math.min(e.length,r.length),a=s,i=0;n<a;)e.substring(i,a)==r.substring(i,a)?(n=a,i=n):s=a,a=Math.floor((s-n)/2+n);return a},o.prototype.diff_commonSuffix=function(e,r){if(!e||!r||e.charAt(e.length-1)!=r.charAt(r.length-1))return 0;for(var n=0,s=Math.min(e.length,r.length),a=s,i=0;n<a;)e.substring(e.length-a,e.length-i)==r.substring(r.length-a,r.length-i)?(n=a,i=n):s=a,a=Math.floor((s-n)/2+n);return a},o.prototype.diff_commonOverlap_=function(e,r){var n=e.length,s=r.length;if(n==0||s==0)return 0;n>s?e=e.substring(n-s):n<s&&(r=r.substring(0,n));var a=Math.min(n,s);if(e==r)return a;for(var i=0,t=1;;){var l=e.substring(a-t),h=r.indexOf(l);if(h==-1)return i;t+=h,(h==0||e.substring(a-t)==r.substring(0,t))&&(i=t,t++)}},o.prototype.diff_halfMatch_=function(e,r){if(this.Diff_Timeout<=0)return null;var n=e.length>r.length?e:r,s=e.length>r.length?r:e;if(n.length<4||s.length*2<n.length)return null;var a=this;function i(p,M,E){for(var _=p.substring(E,E+Math.floor(p.length/4)),S=-1,D="",w,N,j,T;(S=M.indexOf(_,S+1))!=-1;){var P=a.diff_commonPrefix(p.substring(E),M.substring(S)),B=a.diff_commonSuffix(p.substring(0,E),M.substring(0,S));D.length<B+P&&(D=M.substring(S-B,S)+M.substring(S,S+P),w=p.substring(0,E-B),N=p.substring(E+P),j=M.substring(0,S-B),T=M.substring(S+P))}return D.length*2>=p.length?[w,N,j,T,D]:null}var t=i(n,s,Math.ceil(n.length/4)),l=i(n,s,Math.ceil(n.length/2)),h;if(!t&&!l)return null;l?t?h=t[4].length>l[4].length?t:l:h=l:h=t;var g,c,v,m;e.length>r.length?(g=h[0],c=h[1],v=h[2],m=h[3]):(v=h[0],m=h[1],g=h[2],c=h[3]);var b=h[4];return[g,c,v,m,b]},o.prototype.diff_cleanupSemantic=function(e){for(var r=!1,n=[],s=0,a=null,i=0,t=0,l=0,h=0,g=0;i<e.length;)e[i][0]==f?(n[s++]=i,t=h,l=g,h=0,g=0,a=e[i][1]):(e[i][0]==A?h+=e[i][1].length:g+=e[i][1].length,a&&a.length<=Math.max(t,l)&&a.length<=Math.max(h,g)&&(e.splice(n[s-1],0,new o.Diff(k,a)),e[n[s-1]+1][0]=A,s--,s--,i=s>0?n[s-1]:-1,t=0,l=0,h=0,g=0,a=null,r=!0)),i++;for(r&&this.diff_cleanupMerge(e),this.diff_cleanupSemanticLossless(e),i=1;i<e.length;){if(e[i-1][0]==k&&e[i][0]==A){var c=e[i-1][1],v=e[i][1],m=this.diff_commonOverlap_(c,v),b=this.diff_commonOverlap_(v,c);m>=b?(m>=c.length/2||m>=v.length/2)&&(e.splice(i,0,new o.Diff(f,v.substring(0,m))),e[i-1][1]=c.substring(0,c.length-m),e[i+1][1]=v.substring(m),i++):(b>=c.length/2||b>=v.length/2)&&(e.splice(i,0,new o.Diff(f,c.substring(0,b))),e[i-1][0]=A,e[i-1][1]=v.substring(0,v.length-b),e[i+1][0]=k,e[i+1][1]=c.substring(b),i++),i++}i++}},o.prototype.diff_cleanupSemanticLossless=function(e){function r(b,p){if(!b||!p)return 6;var M=b.charAt(b.length-1),E=p.charAt(0),_=M.match(o.nonAlphaNumericRegex_),S=E.match(o.nonAlphaNumericRegex_),D=_&&M.match(o.whitespaceRegex_),w=S&&E.match(o.whitespaceRegex_),N=D&&M.match(o.linebreakRegex_),j=w&&E.match(o.linebreakRegex_),T=N&&b.match(o.blanklineEndRegex_),P=j&&p.match(o.blanklineStartRegex_);return T||P?5:N||j?4:_&&!D&&w?3:D||w?2:_||S?1:0}for(var n=1;n<e.length-1;){if(e[n-1][0]==f&&e[n+1][0]==f){var s=e[n-1][1],a=e[n][1],i=e[n+1][1],t=this.diff_commonSuffix(s,a);if(t){var l=a.substring(a.length-t);s=s.substring(0,s.length-t),a=l+a.substring(0,a.length-t),i=l+i}for(var h=s,g=a,c=i,v=r(s,a)+r(a,i);a.charAt(0)===i.charAt(0);){s+=a.charAt(0),a=a.substring(1)+i.charAt(0),i=i.substring(1);var m=r(s,a)+r(a,i);m>=v&&(v=m,h=s,g=a,c=i)}e[n-1][1]!=h&&(h?e[n-1][1]=h:(e.splice(n-1,1),n--),e[n][1]=g,c?e[n+1][1]=c:(e.splice(n+1,1),n--))}n++}},o.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/,o.whitespaceRegex_=/\s/,o.linebreakRegex_=/[\r\n]/,o.blanklineEndRegex_=/\n\r?\n$/,o.blanklineStartRegex_=/^\r?\n\r?\n/,o.prototype.diff_cleanupEfficiency=function(e){for(var r=!1,n=[],s=0,a=null,i=0,t=!1,l=!1,h=!1,g=!1;i<e.length;)e[i][0]==f?(e[i][1].length<this.Diff_EditCost&&(h||g)?(n[s++]=i,t=h,l=g,a=e[i][1]):(s=0,a=null),h=g=!1):(e[i][0]==k?g=!0:h=!0,a&&(t&&l&&h&&g||a.length<this.Diff_EditCost/2&&t+l+h+g==3)&&(e.splice(n[s-1],0,new o.Diff(k,a)),e[n[s-1]+1][0]=A,s--,a=null,t&&l?(h=g=!0,s=0):(s--,i=s>0?n[s-1]:-1,h=g=!1),r=!0)),i++;r&&this.diff_cleanupMerge(e)},o.prototype.diff_cleanupMerge=function(e){e.push(new o.Diff(f,""));for(var r=0,n=0,s=0,a="",i="",t;r<e.length;)switch(e[r][0]){case A:s++,i+=e[r][1],r++;break;case k:n++,a+=e[r][1],r++;break;case f:n+s>1?(n!==0&&s!==0&&(t=this.diff_commonPrefix(i,a),t!==0&&(r-n-s>0&&e[r-n-s-1][0]==f?e[r-n-s-1][1]+=i.substring(0,t):(e.splice(0,0,new o.Diff(f,i.substring(0,t))),r++),i=i.substring(t),a=a.substring(t)),t=this.diff_commonSuffix(i,a),t!==0&&(e[r][1]=i.substring(i.length-t)+e[r][1],i=i.substring(0,i.length-t),a=a.substring(0,a.length-t))),r-=n+s,e.splice(r,n+s),a.length&&(e.splice(r,0,new o.Diff(k,a)),r++),i.length&&(e.splice(r,0,new o.Diff(A,i)),r++),r++):r!==0&&e[r-1][0]==f?(e[r-1][1]+=e[r][1],e.splice(r,1)):r++,s=0,n=0,a="",i="";break}e[e.length-1][1]===""&&e.pop();var l=!1;for(r=1;r<e.length-1;)e[r-1][0]==f&&e[r+1][0]==f&&(e[r][1].substring(e[r][1].length-e[r-1][1].length)==e[r-1][1]?(e[r][1]=e[r-1][1]+e[r][1].substring(0,e[r][1].length-e[r-1][1].length),e[r+1][1]=e[r-1][1]+e[r+1][1],e.splice(r-1,1),l=!0):e[r][1].substring(0,e[r+1][1].length)==e[r+1][1]&&(e[r-1][1]+=e[r+1][1],e[r][1]=e[r][1].substring(e[r+1][1].length)+e[r+1][1],e.splice(r+1,1),l=!0)),r++;l&&this.diff_cleanupMerge(e)},o.prototype.diff_xIndex=function(e,r){var n=0,s=0,a=0,i=0,t;for(t=0;t<e.length&&(e[t][0]!==A&&(n+=e[t][1].length),e[t][0]!==k&&(s+=e[t][1].length),!(n>r));t++)a=n,i=s;return e.length!=t&&e[t][0]===k?i:i+(r-a)},o.prototype.diff_prettyHtml=function(e){for(var r=[],n=/&/g,s=/</g,a=/>/g,i=/\n/g,t=0;t<e.length;t++){var l=e[t][0],h=e[t][1],g=h.replace(n,"&amp;").replace(s,"&lt;").replace(a,"&gt;").replace(i,"&para;<br>");switch(l){case A:r[t]='<ins style="background:#e6ffe6;">'+g+"</ins>";break;case k:r[t]='<del style="background:#ffe6e6;">'+g+"</del>";break;case f:r[t]="<span>"+g+"</span>";break}}return r.join("")},o.prototype.diff_text1=function(e){for(var r=[],n=0;n<e.length;n++)e[n][0]!==A&&(r[n]=e[n][1]);return r.join("")},o.prototype.diff_text2=function(e){for(var r=[],n=0;n<e.length;n++)e[n][0]!==k&&(r[n]=e[n][1]);return r.join("")},o.prototype.diff_levenshtein=function(e){for(var r=0,n=0,s=0,a=0;a<e.length;a++){var i=e[a][0],t=e[a][1];switch(i){case A:n+=t.length;break;case k:s+=t.length;break;case f:r+=Math.max(n,s),n=0,s=0;break}}return r+=Math.max(n,s),r},o.prototype.diff_toDelta=function(e){for(var r=[],n=0;n<e.length;n++)switch(e[n][0]){case A:r[n]="+"+encodeURI(e[n][1]);break;case k:r[n]="-"+e[n][1].length;break;case f:r[n]="="+e[n][1].length;break}return r.join(" ").replace(/%20/g," ")},o.prototype.diff_fromDelta=function(e,r){for(var n=[],s=0,a=0,i=r.split(/\t/g),t=0;t<i.length;t++){var l=i[t].substring(1);switch(i[t].charAt(0)){case"+":try{n[s++]=new o.Diff(A,decodeURI(l))}catch{throw new Error("Illegal escape in diff_fromDelta: "+l)}break;case"-":case"=":var h=parseInt(l,10);if(isNaN(h)||h<0)throw new Error("Invalid number in diff_fromDelta: "+l);var g=e.substring(a,a+=h);i[t].charAt(0)=="="?n[s++]=new o.Diff(f,g):n[s++]=new o.Diff(k,g);break;default:if(i[t])throw new Error("Invalid diff operation in diff_fromDelta: "+i[t])}}if(a!=e.length)throw new Error("Delta length ("+a+") does not equal source text length ("+e.length+").");return n},o.prototype.match_main=function(e,r,n){if(e==null||r==null||n==null)throw new Error("Null input. (match_main)");return n=Math.max(0,Math.min(n,e.length)),e==r?0:e.length?e.substring(n,n+r.length)==r?n:this.match_bitap_(e,r,n):-1},o.prototype.match_bitap_=function(e,r,n){if(r.length>this.Match_MaxBits)throw new Error("Pattern too long for this browser.");var s=this.match_alphabet_(r),a=this;function i(w,N){var j=w/r.length,T=Math.abs(n-N);return a.Match_Distance?j+T/a.Match_Distance:T?1:j}var t=this.Match_Threshold,l=e.indexOf(r,n);l!=-1&&(t=Math.min(i(0,l),t),l=e.lastIndexOf(r,n+r.length),l!=-1&&(t=Math.min(i(0,l),t)));var h=1<<r.length-1;l=-1;for(var g,c,v=r.length+e.length,m,b=0;b<r.length;b++){for(g=0,c=v;g<c;)i(b,n+c)<=t?g=c:v=c,c=Math.floor((v-g)/2+g);v=c;var p=Math.max(1,n-c+1),M=Math.min(n+c,e.length)+r.length,E=Array(M+2);E[M+1]=(1<<b)-1;for(var _=M;_>=p;_--){var S=s[e.charAt(_-1)];if(b===0?E[_]=(E[_+1]<<1|1)&S:E[_]=(E[_+1]<<1|1)&S|((m[_+1]|m[_])<<1|1)|m[_+1],E[_]&h){var D=i(b,_-1);if(D<=t)if(t=D,l=_-1,l>n)p=Math.max(1,2*n-l);else break}}if(i(b+1,n)>t)break;m=E}return l},o.prototype.match_alphabet_=function(e){for(var r={},n=0;n<e.length;n++)r[e.charAt(n)]=0;for(var n=0;n<e.length;n++)r[e.charAt(n)]|=1<<e.length-n-1;return r},o.prototype.patch_addContext_=function(e,r){if(r.length!=0){if(e.start2===null)throw Error("patch not initialized");for(var n=r.substring(e.start2,e.start2+e.length1),s=0;r.indexOf(n)!=r.lastIndexOf(n)&&n.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)s+=this.Patch_Margin,n=r.substring(e.start2-s,e.start2+e.length1+s);s+=this.Patch_Margin;var a=r.substring(e.start2-s,e.start2);a&&e.diffs.unshift(new o.Diff(f,a));var i=r.substring(e.start2+e.length1,e.start2+e.length1+s);i&&e.diffs.push(new o.Diff(f,i)),e.start1-=a.length,e.start2-=a.length,e.length1+=a.length+i.length,e.length2+=a.length+i.length}},o.prototype.patch_make=function(e,r,n){var s,a;if(typeof e=="string"&&typeof r=="string"&&typeof n>"u")s=e,a=this.diff_main(s,r,!0),a.length>2&&(this.diff_cleanupSemantic(a),this.diff_cleanupEfficiency(a));else if(e&&typeof e=="object"&&typeof r>"u"&&typeof n>"u")a=e,s=this.diff_text1(a);else if(typeof e=="string"&&r&&typeof r=="object"&&typeof n>"u")s=e,a=r;else if(typeof e=="string"&&typeof r=="string"&&n&&typeof n=="object")s=e,a=n;else throw new Error("Unknown call format to patch_make.");if(a.length===0)return[];for(var i=[],t=new o.patch_obj,l=0,h=0,g=0,c=s,v=s,m=0;m<a.length;m++){var b=a[m][0],p=a[m][1];switch(!l&&b!==f&&(t.start1=h,t.start2=g),b){case A:t.diffs[l++]=a[m],t.length2+=p.length,v=v.substring(0,g)+p+v.substring(g);break;case k:t.length1+=p.length,t.diffs[l++]=a[m],v=v.substring(0,g)+v.substring(g+p.length);break;case f:p.length<=2*this.Patch_Margin&&l&&a.length!=m+1?(t.diffs[l++]=a[m],t.length1+=p.length,t.length2+=p.length):p.length>=2*this.Patch_Margin&&l&&(this.patch_addContext_(t,c),i.push(t),t=new o.patch_obj,l=0,c=v,h=g);break}b!==A&&(h+=p.length),b!==k&&(g+=p.length)}return l&&(this.patch_addContext_(t,c),i.push(t)),i},o.prototype.patch_deepCopy=function(e){for(var r=[],n=0;n<e.length;n++){var s=e[n],a=new o.patch_obj;a.diffs=[];for(var i=0;i<s.diffs.length;i++)a.diffs[i]=new o.Diff(s.diffs[i][0],s.diffs[i][1]);a.start1=s.start1,a.start2=s.start2,a.length1=s.length1,a.length2=s.length2,r[n]=a}return r},o.prototype.patch_apply=function(e,r){if(e.length==0)return[r,[]];e=this.patch_deepCopy(e);var n=this.patch_addPadding(e);r=n+r+n,this.patch_splitMax(e);for(var s=0,a=[],i=0;i<e.length;i++){var t=e[i].start2+s,l=this.diff_text1(e[i].diffs),h,g=-1;if(l.length>this.Match_MaxBits?(h=this.match_main(r,l.substring(0,this.Match_MaxBits),t),h!=-1&&(g=this.match_main(r,l.substring(l.length-this.Match_MaxBits),t+l.length-this.Match_MaxBits),(g==-1||h>=g)&&(h=-1))):h=this.match_main(r,l,t),h==-1)a[i]=!1,s-=e[i].length2-e[i].length1;else{a[i]=!0,s=h-t;var c;if(g==-1?c=r.substring(h,h+l.length):c=r.substring(h,g+this.Match_MaxBits),l==c)r=r.substring(0,h)+this.diff_text2(e[i].diffs)+r.substring(h+l.length);else{var v=this.diff_main(l,c,!1);if(l.length>this.Match_MaxBits&&this.diff_levenshtein(v)/l.length>this.Patch_DeleteThreshold)a[i]=!1;else{this.diff_cleanupSemanticLossless(v);for(var m=0,b,p=0;p<e[i].diffs.length;p++){var M=e[i].diffs[p];M[0]!==f&&(b=this.diff_xIndex(v,m)),M[0]===A?r=r.substring(0,h+b)+M[1]+r.substring(h+b):M[0]===k&&(r=r.substring(0,h+b)+r.substring(h+this.diff_xIndex(v,m+M[1].length))),M[0]!==k&&(m+=M[1].length)}}}}}return r=r.substring(n.length,r.length-n.length),[r,a]},o.prototype.patch_addPadding=function(e){for(var r=this.Patch_Margin,n="",s=1;s<=r;s++)n+=String.fromCharCode(s);for(var s=0;s<e.length;s++)e[s].start1+=r,e[s].start2+=r;var a=e[0],i=a.diffs;if(i.length==0||i[0][0]!=f)i.unshift(new o.Diff(f,n)),a.start1-=r,a.start2-=r,a.length1+=r,a.length2+=r;else if(r>i[0][1].length){var t=r-i[0][1].length;i[0][1]=n.substring(i[0][1].length)+i[0][1],a.start1-=t,a.start2-=t,a.length1+=t,a.length2+=t}if(a=e[e.length-1],i=a.diffs,i.length==0||i[i.length-1][0]!=f)i.push(new o.Diff(f,n)),a.length1+=r,a.length2+=r;else if(r>i[i.length-1][1].length){var t=r-i[i.length-1][1].length;i[i.length-1][1]+=n.substring(0,t),a.length1+=t,a.length2+=t}return n},o.prototype.patch_splitMax=function(e){for(var r=this.Match_MaxBits,n=0;n<e.length;n++)if(!(e[n].length1<=r)){var s=e[n];e.splice(n--,1);for(var a=s.start1,i=s.start2,t="";s.diffs.length!==0;){var l=new o.patch_obj,h=!0;for(l.start1=a-t.length,l.start2=i-t.length,t!==""&&(l.length1=l.length2=t.length,l.diffs.push(new o.Diff(f,t)));s.diffs.length!==0&&l.length1<r-this.Patch_Margin;){var g=s.diffs[0][0],c=s.diffs[0][1];g===A?(l.length2+=c.length,i+=c.length,l.diffs.push(s.diffs.shift()),h=!1):g===k&&l.diffs.length==1&&l.diffs[0][0]==f&&c.length>2*r?(l.length1+=c.length,a+=c.length,h=!1,l.diffs.push(new o.Diff(g,c)),s.diffs.shift()):(c=c.substring(0,r-l.length1-this.Patch_Margin),l.length1+=c.length,a+=c.length,g===f?(l.length2+=c.length,i+=c.length):h=!1,l.diffs.push(new o.Diff(g,c)),c==s.diffs[0][1]?s.diffs.shift():s.diffs[0][1]=s.diffs[0][1].substring(c.length))}t=this.diff_text2(l.diffs),t=t.substring(t.length-this.Patch_Margin);var v=this.diff_text1(s.diffs).substring(0,this.Patch_Margin);v!==""&&(l.length1+=v.length,l.length2+=v.length,l.diffs.length!==0&&l.diffs[l.diffs.length-1][0]===f?l.diffs[l.diffs.length-1][1]+=v:l.diffs.push(new o.Diff(f,v))),h||e.splice(++n,0,l)}}},o.prototype.patch_toText=function(e){for(var r=[],n=0;n<e.length;n++)r[n]=e[n];return r.join("")},o.prototype.patch_fromText=function(e){var r=[];if(!e)return r;for(var n=e.split(`
3
3
  `),s=0,a=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;s<n.length;){var i=n[s].match(a);if(!i)throw new Error("Invalid patch string: "+n[s]);var t=new o.patch_obj;for(r.push(t),t.start1=parseInt(i[1],10),i[2]===""?(t.start1--,t.length1=1):i[2]=="0"?t.length1=0:(t.start1--,t.length1=parseInt(i[2],10)),t.start2=parseInt(i[3],10),i[4]===""?(t.start2--,t.length2=1):i[4]=="0"?t.length2=0:(t.start2--,t.length2=parseInt(i[4],10)),s++;s<n.length;){var l=n[s].charAt(0);try{var h=decodeURI(n[s].substring(1))}catch{throw new Error("Illegal escape in patch_fromText: "+h)}if(l=="-")t.diffs.push(new o.Diff(k,h));else if(l=="+")t.diffs.push(new o.Diff(A,h));else if(l==" ")t.diffs.push(new o.Diff(f,h));else{if(l=="@")break;if(l!=="")throw new Error('Invalid patch mode "'+l+'" in: '+h)}s++}}return r},o.patch_obj=function(){this.diffs=[],this.start1=null,this.start2=null,this.length1=0,this.length2=0},o.patch_obj.prototype.toString=function(){var e,r;this.length1===0?e=this.start1+",0":this.length1==1?e=this.start1+1:e=this.start1+1+","+this.length1,this.length2===0?r=this.start2+",0":this.length2==1?r=this.start2+1:r=this.start2+1+","+this.length2;for(var n=["@@ -"+e+" +"+r+` @@
4
4
  `],s,a=0;a<this.diffs.length;a++){switch(this.diffs[a][0]){case A:s="+";break;case k:s="-";break;case f:s=" ";break}n[a+1]=s+encodeURI(this.diffs[a][1])+`