@akairos/typeset-studio 0.2.6 → 0.2.7
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.md +51 -15
- package/dist/assets/{index-X9ezH_RG.js → index-CVzTRIjV.js} +2 -2
- package/dist/index.html +1 -1
- package/dist/lib/adapter.js +1 -1
- package/dist/lib/{canvas-renderer-4jg80agt.js → canvas-renderer-wce6xgb2.js} +1 -1
- package/dist/lib/{index-bf1zs3mv.js → index-697fkv5y.js} +3 -3
- package/dist/lib/{index-p8ttqbs6.js → index-dkwbnaj7.js} +2 -2
- package/dist/lib/{index-hegsbxc0.js → index-qszn98j2.js} +3 -3
- package/dist/lib/index.js +3 -3
- package/dist/lib/{render-3043w6s6.js → render-064weavx.js} +2 -2
- package/package.json +1 -1
- package/src/adapter.test.ts +3 -1
- package/src/core/canvas-renderer.test.ts +4 -1
- package/src/core/geometry.ts +4 -3
- package/src/server/index.ts +1 -1
- package/src/server/routes/slots.test.ts +2 -0
- package/src/server/routes/templates.ts +2 -2
- package/src/web/components/Header.tsx +2 -2
- package/src/web/components/SaveTemplateModal.tsx +1 -1
package/README.md
CHANGED
|
@@ -20,13 +20,24 @@
|
|
|
20
20
|
|
|
21
21
|
</div>
|
|
22
22
|
|
|
23
|
+
## 生态与使用者
|
|
24
|
+
|
|
25
|
+
| 项目 | 与 Typeset Studio 的关系 |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| [zzhub-pipeline](https://github.com/k7airos/zzhub-pipeline) · [`@akairos/pipeline`](https://www.npmjs.com/package/@akairos/pipeline) | 当前图片插件消费方,通过 `@akairos/typeset-studio/adapter` 生成文章封面和贴图页面;负责状态机、素材上传与草稿发布 |
|
|
28
|
+
| [myno](https://github.com/k7airos/myno) | 配套正文编辑与排版工作台;生成可复制的微信 HTML 和样式 JSON,与本包的 PNG 渲染职责互补,互不依赖 |
|
|
29
|
+
| [Obsidian 微信发布插件](https://github.com/k7airos/obsidian-wechat-publish) | 通过本机 Pipeline 间接使用已配置的图片渲染器,不直接依赖本包 |
|
|
30
|
+
| [Kairos Skills](https://github.com/k7airos/kairos-skills) | 指导 Agent 选择模板、准备正文与素材,再调用 Pipeline 渲染 |
|
|
31
|
+
|
|
32
|
+
本包直接使用 `@chenglou/pretext` 和 `@napi-rs/canvas` 排版与出图;React/Vite 提供交互工作台,Hono/Bun 提供独立 HTTP 服务。自有程序也可直接调用包 API,无需 Pipeline 或任何私有应用。仅渲染 PNG 不需要 Chrome;Pipeline 的微信正文 HTML 导出仍需要浏览器。
|
|
33
|
+
|
|
23
34
|
## 📖 定位与核心哲学
|
|
24
35
|
|
|
25
36
|
在内容自动化分发、微信公众号文章与小红书图文制作中,传统的卡片出图方案普遍依赖 **Chrome Headless (Puppeteer / Playwright)**。为了获取最佳排版效果,往往需要在浏览器实例中多次反复渲染、测量高度、试探字号并进行 CDP 通信截屏。这种方式**速度缓慢(单次耗时数秒)、内存占用高、排版结果难以量化微调**。
|
|
26
37
|
|
|
27
38
|
**Typeset Studio** 采取了完全不同的技术路线:**以确定性纯数学几何排版与服务端原生渲染为核心**。
|
|
28
39
|
|
|
29
|
-
-
|
|
40
|
+
- **原生 PNG 渲染**:底层依托 `@chenglou/pretext` 与 `@napi-rs/canvas`,不使用无头浏览器截图。字体和素材来自渲染机器;性能和最终外观取决于文本长度、页面数量、素材与字体,不承诺跨机器像素一致。
|
|
30
41
|
- **🧩 双模态运行形态**:
|
|
31
42
|
1. **独立可视化排版工作台 (Standalone Visual Studio)**:具备类 Vercel 极简黑白美学的 Web 设计器,支持多图瀑布流全景平铺、单图聚焦微调、四大标准出版比例切换、模板持久化与一键直接服务端渲染高清下载。
|
|
32
43
|
2. **自动化发布流水线插件 (Pipeline Image Renderer Plugin)**:作为标准图像渲染插件,可无缝插拔接入 `zzhub-pipeline` 或任意 CI/CD 内容分发系统,直接通过原生 Canvas 生成图片,彻底替代笨重的 Chrome 截屏方案。
|
|
@@ -36,13 +47,13 @@
|
|
|
36
47
|
## ✨ 特性亮点
|
|
37
48
|
|
|
38
49
|
### 1. 📐 四大标准卡片出版规格
|
|
39
|
-
-
|
|
50
|
+
- **微信封面原图 (3.35:1)**:`3350 × 1000px`,左侧 `2350 × 1000px` 裁为大封面,右侧 `1000 × 1000px` 裁为小封面。保留 `wechat-cover-2.35` 配置标识以兼容已有模板。
|
|
40
51
|
- **通用长图文 / 小红书 (3:4)**:`1080 × 1440px`,支持多页流式/显式切分、智能避让多图与目标填充率二分逼近。
|
|
41
52
|
- **通用宽屏 (16:9)**:`1920 × 1080px`,适用于技术博客 Banner、横版社交媒体卡片。
|
|
42
53
|
- **通用正方形 (1:1)**:`1200 × 1200px`,适用于金句摘录、名言卡片、社媒方图。
|
|
43
54
|
|
|
44
55
|
### 2. 🌊 8 大流式排版预设与自由图层 (Absolute Layer)
|
|
45
|
-
- **8
|
|
56
|
+
- **8 种流式避让预设**:自适应 (`auto`)、居左浮动 (`mid-left`)、居右浮动 (`mid-right`)、居中横幅 (`center`)、交错排版 (`staggered`)、角落软着陆 (`corner-soft`)、填充 (`fill`) 与自定义坐标 (`custom`)。
|
|
46
57
|
- **自由图层穿透**:一键将配图转为绝对定位自由图层,正文自动穿透排版流动,支持任意 `x/y`、宽高、`z-index`、旋转角度(`0~360°`)与透明度。
|
|
47
58
|
|
|
48
59
|
### 3. 🖼️ 多图瀑布流全景平铺与单图聚焦
|
|
@@ -57,10 +68,10 @@
|
|
|
57
68
|
|
|
58
69
|
### 5. 💾 模板槽位体系与交集应用逻辑
|
|
59
70
|
- **三大标准模板槽位**:
|
|
60
|
-
- `article_cover
|
|
71
|
+
- `article_cover`(文章封面原图,默认 3.35:1)
|
|
61
72
|
- `newspic_cover`(贴图封面,默认 3:4)
|
|
62
73
|
- `newspic_content`(贴图内容,默认 3:4 多页)
|
|
63
|
-
-
|
|
74
|
+
- **账号槽位与默认模板**:各账号可独立配置槽位;未配置时按全局默认和算法默认回退。显式选择不存在的模板、素材缺失或无法满足分页约束时会报错。
|
|
64
75
|
- **数量不匹配交集算法**:模板配图数与文章实际配图数不一致时安全应用交集(如 1 对多仅覆盖第 1 张,其余保留用户参数;2 对 1 忽略超出项)。
|
|
65
76
|
|
|
66
77
|
---
|
|
@@ -68,8 +79,8 @@
|
|
|
68
79
|
## 🛠️ 运行环境与依赖要求
|
|
69
80
|
|
|
70
81
|
### 1. 核心运行时
|
|
71
|
-
- **推荐运行环境**:[Bun](https://bun.sh/) `>= 1.2
|
|
72
|
-
-
|
|
82
|
+
- **推荐运行环境**:[Bun](https://bun.sh/) `>= 1.2`,支持 TypeScript 与 Watch 模式
|
|
83
|
+
- **Node.js 调用**:核心库与 npm 构建提供 Node 入口;独立 HTTP 服务使用 `hono/bun`,按下文使用 Bun 启动。
|
|
73
84
|
|
|
74
85
|
### 2. 底层关键依赖
|
|
75
86
|
| 依赖包 | 版本 | 角色与用途 |
|
|
@@ -100,9 +111,12 @@ bun install
|
|
|
100
111
|
单进程同时托管后端 API 与前端 Web 工作台:
|
|
101
112
|
|
|
102
113
|
```bash
|
|
114
|
+
bun run build
|
|
103
115
|
bun run server
|
|
104
116
|
```
|
|
105
117
|
|
|
118
|
+
首次从源码启动或更新前端后,先构建 `dist/`;服务端托管的是构建后的工作台。
|
|
119
|
+
|
|
106
120
|
服务启动后输出端口信息,管理员密钥保存在环境变量或 `.env` 中:
|
|
107
121
|
```text
|
|
108
122
|
┌────────────────────────────────────────────────────────┐
|
|
@@ -149,9 +163,31 @@ npm install @akairos/typeset-studio
|
|
|
149
163
|
|
|
150
164
|
源码联调也可将 `imageRenderer` 指向本项目的 `src/adapter.ts` 或构建后的 `dist/lib/adapter.js`。
|
|
151
165
|
|
|
152
|
-
|
|
166
|
+
Pipeline 使用 npm 插件的本地原生 Canvas 方法,不需要另启 HTTP 服务,也不需要管理员密钥。建议通过对象配置指定包目录之外的持久化数据目录,并让独立编辑器使用同一目录:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"plugins": {
|
|
171
|
+
"imageRenderer": {
|
|
172
|
+
"module": "@akairos/typeset-studio/adapter",
|
|
173
|
+
"options": { "dataDir": "/absolute/path/typeset-data" }
|
|
174
|
+
},
|
|
175
|
+
"markdownRenderer": { "module": "@akairos/myno/adapter", "options": {} }
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`markdownRenderer` 是可选的配套正文插件;只需要出图时不必启用。Pipeline 将 `options.dataDir` 传为插件子进程的 `TYPESET_DATA_DIR`,已有非空环境变量优先。Pipeline 会屏蔽适配器的远程服务地址和密钥,确保走本地 npm 执行。
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# 在本仓库运行编辑器,与插件共享模板和 uploads
|
|
184
|
+
TYPESET_DATA_DIR=/absolute/path/typeset-data bun run server
|
|
185
|
+
# 在已有发布任务中渲染;下一步由 status 决定
|
|
186
|
+
zzp status --state ./workflow-state.json --view agent
|
|
187
|
+
zzp render --state ./workflow-state.json
|
|
188
|
+
```
|
|
153
189
|
|
|
154
|
-
|
|
190
|
+
没有 `zzp run` 命令。完整发布流程见 [Pipeline README](https://github.com/k7airos/zzhub-pipeline#readme)。本包不负责微信上传或草稿创建。
|
|
155
191
|
|
|
156
192
|
---
|
|
157
193
|
|
|
@@ -180,7 +216,7 @@ curl -X POST http://localhost:4890/api/render \
|
|
|
180
216
|
```
|
|
181
217
|
|
|
182
218
|
### 3. 服务端原生 Canvas 生成 PNG (`POST /api/render/png`)
|
|
183
|
-
直接返回二进制
|
|
219
|
+
直接返回二进制 `image/png` 数据流,使用原生 Canvas 渲染:
|
|
184
220
|
```bash
|
|
185
221
|
curl -X POST http://localhost:4890/api/render/png \
|
|
186
222
|
-H "Content-Type: application/json" \
|
|
@@ -235,7 +271,7 @@ typeset-studio/
|
|
|
235
271
|
│ │ ├── image-layout.ts # 预设布局坐标计算 (computeSafePresetY) 与边界保护
|
|
236
272
|
│ │ ├── typography.ts # 跨平台字体回退映射与多阶字号行高计算
|
|
237
273
|
│ │ ├── template.ts # 模板持久化应用与数量不匹配时的交集算法
|
|
238
|
-
│ │ ├── geometry.ts # 4 大标准画布比例几何计算 (
|
|
274
|
+
│ │ ├── geometry.ts # 4 大标准画布比例几何计算 (3.35:1, 3:4, 16:9, 1:1)
|
|
239
275
|
│ │ └── types.ts # 完整 TypeScript 类型契约
|
|
240
276
|
│ │
|
|
241
277
|
│ ├── server/ # Hono 后端服务(运行于 Bun,提供持久化与无头渲染 API)
|
|
@@ -284,7 +320,7 @@ bun run build
|
|
|
284
320
|
- `src/core/template.test.ts`:模板持久化、配图数量交集应用逻辑验证
|
|
285
321
|
- `src/core/image-layout.test.ts`:流式排版预设坐标、Page 2 边界安全与陈旧坐标免疫验证
|
|
286
322
|
- `src/server/routes/slots.test.ts`:三大默认模板槽位、账号配置隔离与回退容错验证
|
|
287
|
-
-
|
|
323
|
+
- 测试数量与结果以本次执行输出为准;此处不将历史统计作为当前验收结论。
|
|
288
324
|
|
|
289
325
|
---
|
|
290
326
|
|
|
@@ -296,7 +332,7 @@ bun run build
|
|
|
296
332
|
|
|
297
333
|
业务 API(模板、上传、排版)均要求 `X-Admin-Key`。本机编辑器通过真实回环连接自动领取密钥;远程编辑器需在设置中填写密钥。密钥来自 `TYPESET_ADMIN_KEY` 或服务目录的 `.env`,跨域网页不能自动领取。反向代理应使用业务域名,并保留原始 Host。
|
|
298
334
|
|
|
299
|
-
|
|
335
|
+
仅直接使用本包适配器的远程模式时才设置 `TYPESET_STUDIO_URL` 与 `TYPESET_ADMIN_KEY`;Pipeline 调用会屏蔽这两个参数。远程模式传输任务本地图片字节,`/uploads/` 表示远端文件。`TYPESET_DATA_DIR` 统一控制模板、默认配置和上传文件目录。
|
|
300
336
|
|
|
301
337
|
插件的模板选择顺序为:`studioTemplates.cover/content` → 旧调用中的具体 `template` 名称 → 当前账号的用途槽位默认模板。`wechat-cover-split`、`poster-3-4`、`longform-3-4` 只表示 pipeline 渲染模式,不作为 Studio 模板名查询。未知模板会报错。
|
|
302
338
|
|
|
@@ -351,7 +387,7 @@ templateImageOverrides: {
|
|
|
351
387
|
},
|
|
352
388
|
```
|
|
353
389
|
|
|
354
|
-
对应的
|
|
390
|
+
对应的 Pipeline 命令(当前 npm 0.19.0 已支持):
|
|
355
391
|
|
|
356
392
|
```bash
|
|
357
393
|
zzp render --state /absolute/path/workflow-state.json \
|
|
@@ -373,4 +409,4 @@ zzp render --state /absolute/path/workflow-state.json \
|
|
|
373
409
|
|
|
374
410
|
模板只保存文件或 URL 引用,不嵌入、不自动打包迁移。`/uploads/...` 由实际渲染方的 `TYPESET_DATA_DIR` 解析,本地插件和编辑器应使用同一目录;远程模式使用服务端目录。模板中的绝对路径必须在渲染机器存在,HTTP URL 必须可访问。远程调用会传输任务替换中本地文件的字节,但不会复制原模板素材。缺失固定素材、未知替换标识或重复标识会明确报错,终止出图。
|
|
375
411
|
|
|
376
|
-
|
|
412
|
+
固定素材和模板优先渲染从 `@akairos/typeset-studio@0.2.5` 起提供,Pipeline 0.19.0 固定依赖 0.2.6。正式 Pipeline 使用 npm 入口;本地源码入口仅用于联调。运行时模板和上传图片不打进 npm 包,应通过 Pipeline 的 `typeset-assets-sync` 打包,或自行同步目录与素材;说明见 [运行时配置指南](https://github.com/k7airos/zzhub-pipeline/blob/main/docs/visual-studio-and-config-sync.md)。
|
|
@@ -286,10 +286,10 @@ Error generating stack: `+n.message+`
|
|
|
286
286
|
*
|
|
287
287
|
* This source code is licensed under the ISC license.
|
|
288
288
|
* See the LICENSE file in the root directory of this source tree.
|
|
289
|
-
*/const Th={name:"zoom-out",size:24,node:[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]};Th.node;const Bp=we(Th),zp=({isOpen:u,onClose:r,currentKey:s,onSaveKey:c,isVerified:d})=>{const[x,g]=fe.useState(s),[v,N]=fe.useState(null);if(!u)return null;const m=()=>{c(x.trim()),N("密钥已更新并保存至本地存储"),setTimeout(()=>{r()},800)};return f.jsx("div",{className:"fixed inset-0 z-50 bg-black/50 dark:bg-black/70 backdrop-blur-sm flex items-center justify-center p-4",children:f.jsxs("div",{className:"bg-white dark:bg-[#0f0f0f] border border-[#eaeaea] dark:border-[#262626] rounded-xl w-full max-w-md flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-150 transition-colors",children:[f.jsxs("div",{className:"flex items-center justify-between px-5 py-3.5 border-b border-[#eaeaea] dark:border-[#222222]",children:[f.jsxs("div",{className:"flex items-center gap-2 font-semibold text-sm text-[#171717] dark:text-white",children:[f.jsx(eh,{className:"w-4 h-4 text-amber-500 dark:text-amber-400"}),f.jsx("span",{children:"超管密钥授权"})]}),f.jsx("button",{onClick:r,className:"text-[#888888] hover:text-black dark:hover:text-white p-1 rounded-md hover:bg-[#f5f5f5] dark:hover:bg-[#1a1a1a]",children:f.jsx(jo,{className:"w-4 h-4"})})]}),f.jsxs("div",{className:"p-5 flex flex-col gap-4",children:[f.jsxs("div",{className:"text-xs text-[#666666] dark:text-[#888888] leading-relaxed",children:["服务端默认通过 ",f.jsx("code",{className:"text-black dark:text-[#ededed] font-mono font-semibold",children:"TYPESET_ADMIN_KEY"})," 保护模板持久化、图片上传和无头出图 API。请填入服务启动时控制台打印的管理员密钥。"]}),f.jsxs("div",{className:"flex flex-col gap-1.5",children:[f.jsx("label",{className:"text-[11px] font-mono text-[#888888] dark:text-[#666666]",children:"X-Admin-Key"}),f.jsx("input",{type:"password",value:x,onChange:y=>g(y.target.value),placeholder:"tsk_...",className:"bg-[#fafafa] dark:bg-[#0a0a0a] border border-[#d4d4d4] dark:border-[#2a2a2a] rounded-lg px-3 py-2 text-xs font-mono text-black dark:text-white focus:outline-none focus:border-black dark:focus:border-[#444444]"})]}),v?f.jsxs("div",{className:"text-xs text-emerald-700 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/20 px-3 py-2 rounded-lg flex items-center gap-2 font-medium",children:[f.jsx(Qx,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:v})]}):d?f.jsxs("div",{className:"text-xs text-emerald-700 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/20 px-3 py-2 rounded-lg flex items-center gap-2 font-medium",children:[f.jsx(Cp,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"密钥已通过验证,拥有超管权限"})]}):f.jsx("div",{className:"text-xs text-amber-700 dark:text-amber-400 bg-amber-50 dark:bg-amber-500/10 border border-amber-200 dark:border-amber-500/20 px-3 py-2 rounded-lg",children:"当前密钥未验证或已失效,请检查后端 .env 配置"}),f.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[f.jsx("button",{onClick:r,className:"px-3 py-1.5 rounded-lg border border-[#eaeaea] dark:border-[#262626] text-xs text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white hover:bg-[#f5f5f5] dark:hover:bg-[#161616]",children:"取消"}),f.jsx("button",{onClick:m,className:"px-4 py-1.5 bg-black text-white hover:bg-[#262626] dark:bg-white dark:text-black dark:hover:bg-[#eaeaea] text-xs font-semibold rounded-lg transition-all btn-vercel",children:"保存并授权"})]})]})]})})},vx={"wechat-cover-2.35":{id:"wechat-cover-2.35",name:"微信文章封面",ratio:2.35,width:2350,height:1e3,description:"微信公众号官方推荐大图封面 (2.35:1),适合主标题视觉张力、副标题与装饰图层",defaultSafeArea:{top:120,right:140,bottom:120,left:140}},"longform-3-4":{id:"longform-3-4",name:"通用长图文",ratio:3/4,width:1080,height:1440,description:"3:4 手机端阅读长文/图文卡片,支持多页分页、矩形图片绕排、目标填充率优化",defaultSafeArea:{top:96,right:88,bottom:96,left:88}},"wide-16-9":{id:"wide-16-9",name:"通用宽屏",ratio:16/9,width:1920,height:1080,description:"16:9 横版宽屏,适合推特/X 动态配图、技术博客 Banner、视频封面与分栏排版",defaultSafeArea:{top:100,right:120,bottom:100,left:120}},"square-1-1":{id:"square-1-1",name:"通用正方形",ratio:1,width:1200,height:1200,description:"1:1 正方形卡片,适合金句名言卡、公众号次条、小红书方图与社交媒体方版海报",defaultSafeArea:{top:100,right:100,bottom:100,left:100}}};function Tl(u){return vx[u]??vx["longform-3-4"]}function zn(u,r,s=20){const c=Math.max(100,u.width-r.left-r.right),d=Math.max(100,u.height-r.top-r.bottom-s);return{stageWidth:c,stageHeight:d,stageX:r.left,stageY:r.top}}const _p={pattern:"none",color:"#527561",opacity:.12,size:56},Rp={style:"none",color:"#527561",endColor:"#d7ad72",width:3,inset:32,radius:24,opacity:.8},Fh={none:"无花纹",lines:"横线",grid:"网格",dots:"圆点",diagonal:"斜线",waves:"波浪",rings:"同心圆",burst:"放射线",checker:"棋盘格",grain:"纸张颗粒"},jh={none:"无边框",solid:"实线",dashed:"虚线",double:"双线",corners:"四角装饰",gradient:"渐变描边"};function Dh(u){if(u===void 0)return;if(!u||typeof u!="object"||Array.isArray(u))throw new RangeError("无效的背景与边框配置");const r=c=>{if(typeof c!="string"||!/^#[0-9a-f]{6}$/i.test(c))throw new RangeError("背景装饰颜色必须是六位十六进制颜色")},s=(c,d,x)=>{if(!Number.isFinite(c)||c<d||c>x)throw new RangeError(`背景装饰参数必须在 ${d} 到 ${x} 之间`)};if(u.fill){const c=u.fill;if(c.type==="solid")r(c.color);else{if(c.type==="linear")s(c.angle,0,360);else if(c.type==="radial")s(c.position?.x,0,100),s(c.position?.y,0,100);else throw new RangeError("未知背景类型");if(!Array.isArray(c.stops)||c.stops.length<2||c.stops.length>8)throw new RangeError("渐变需要 2 到 8 个颜色节点");for(const d of c.stops){if(!d)throw new RangeError("无效的渐变节点");r(d.color),s(d.offset,0,100)}}}if(u.pattern){const c=u.pattern;if(!Object.hasOwn(Fh,c.pattern))throw new RangeError("未知背景花纹");r(c.color),s(c.opacity,0,1),s(c.size,16,240)}if(u.border){const c=u.border;if(!Object.hasOwn(jh,c.style))throw new RangeError("未知边框样式");r(c.color),r(c.endColor),s(c.width,1,24),s(c.inset,0,200),s(c.radius,0,200),s(c.opacity,0,1)}}function Lp(u,r,s){if(u.save(),s.type==="solid")u.fillStyle=s.color;else{let c;if(s.type==="linear"){const d=s.angle*Math.PI/180,x=Math.abs(Math.cos(d))*r.width/2+Math.abs(Math.sin(d))*r.height/2,g=Math.cos(d)*x,v=Math.sin(d)*x;c=u.createLinearGradient(r.width/2-g,r.height/2-v,r.width/2+g,r.height/2+v)}else{const d=r.width*s.position.x/100,x=r.height*s.position.y/100,g=Math.hypot(Math.max(d,r.width-d),Math.max(x,r.height-x));c=u.createRadialGradient(d,x,0,d,x,g)}for(const d of s.stops)c.addColorStop(d.offset/100,d.color);u.fillStyle=c}u.fillRect(0,0,r.width,r.height),u.restore()}function Hp(u,r,s){if(s.pattern==="none"||s.opacity===0)return;const{width:c,height:d}=r,x=Math.max(16,s.size);switch(u.save(),u.strokeStyle=u.fillStyle=s.color,u.globalAlpha=s.opacity,u.lineWidth=1.5,u.beginPath(),s.pattern){case"grid":case"lines":if(s.pattern==="grid")for(let g=x/2;g<c;g+=x)u.moveTo(g,0),u.lineTo(g,d);for(let g=x/2;g<d;g+=x)u.moveTo(0,g),u.lineTo(c,g);break;case"dots":for(let g=x/2;g<c;g+=x)for(let v=x/2;v<d;v+=x)u.moveTo(g+2,v),u.arc(g,v,2,0,Math.PI*2);break;case"diagonal":for(let g=-d;g<c;g+=x)u.moveTo(g,0),u.lineTo(g+d,d);break;case"waves":for(let g=-x;g<d+x;g+=x){u.moveTo(0,g);for(let v=0;v<c;v+=x*2)u.bezierCurveTo(v+x*.5,g-x*.45,v+x*1.5,g+x*.45,v+x*2,g)}break;case"rings":for(let g=x;g<Math.hypot(c,d);g+=x)u.moveTo(c*.82+g,d*.18),u.arc(c*.82,d*.18,g,0,Math.PI*2);break;case"burst":for(let g=0;g<Math.PI*2;g+=Math.PI/Math.max(8,Math.round(x/3)))u.moveTo(c*.8,d*.2),u.lineTo(c*.8+Math.cos(g)*c*2,d*.2+Math.sin(g)*d*2);break;case"checker":for(let g=0;g<c;g+=x)for(let v=0;v<d;v+=x)(Math.round(g/x)+Math.round(v/x))%2===0&&u.rect(g,v,x,x);break;case"grain":{let g=42;const v=()=>(g=Math.imul(g,1664525)+1013904223>>>0,g/4294967296);for(let N=0;N<c*d/(x*3);N++){const m=v()*c,y=v()*d;u.rect(m,y,.6+v()*1.2,.6+v()*1.2)}break}}["dots","checker","grain"].includes(s.pattern)?u.fill():u.stroke(),u.restore()}function Up(u,r,s){if(!s||s.style==="none"||s.opacity===0)return;const c=Math.min(s.inset+s.width/2,Math.min(r.width,r.height)/2-1),d=r.width-c*2,x=r.height-c*2;if(u.save(),u.globalAlpha=s.opacity,u.lineWidth=s.width,u.strokeStyle=s.color,s.style==="gradient"){const v=u.createLinearGradient(0,0,r.width,r.height);v.addColorStop(0,s.color),v.addColorStop(1,s.endColor),u.strokeStyle=v}s.style==="dashed"&&u.setLineDash([s.width*4,s.width*3]);const g=v=>{u.beginPath(),u.roundRect(c+v,c+v,d-v*2,x-v*2,Math.max(0,s.radius-v)),u.stroke()};if(s.style==="corners"){const v=Math.min(d,x)*.12;for(const N of[c,r.width-c])for(const m of[c,r.height-c]){const y=N===c?1:-1,p=m===c?1:-1;u.beginPath(),u.moveTo(N+y*v,m),u.lineTo(N,m),u.lineTo(N,m+p*v),u.stroke()}}else g(0),s.style==="double"&&g(s.width*3+4);u.restore()}function Gp(u,r=!1){const c=((u||"").split(",")[0]||"").replace(/["'\\]/g,"").trim();return c.includes("Noto Sans")?r?'"Hiragino Sans GB", sans-serif':'"Noto Sans SC", "PingFang SC", sans-serif':c.includes("PingFang")?r?'"Hiragino Sans GB", sans-serif':'"PingFang SC", "Noto Sans SC", sans-serif':c.includes("Noto Serif")?r?'"Songti SC", serif':'"Noto Serif SC", "Songti SC", serif':c.includes("Songti")||c==="STSong"?r?'"Songti SC", serif':'"Songti SC", "Noto Serif SC", serif':c.includes("Kai")||c.includes("WenKai")?r?'"STKaiti", "Kaiti SC", "Songti SC", serif':'"LXGW WenKai GB Screen", "LXGW WenKai Screen", "Kaiti SC", "STKaiti", serif':c.includes("Yuan")?r?'"STYuanti", "Yuanti SC", "Hiragino Sans GB", sans-serif':'"Yuanti SC", "STYuanti", "PingFang SC", sans-serif':c.includes("Inter")?r?'Inter, "Hiragino Sans GB", sans-serif':'Inter, "PingFang SC", sans-serif':c.includes("Georgia")?'Georgia, "Songti SC", serif':c.toLowerCase().includes("serif")||c.includes("Song")?`"${c}", "Songti SC", serif`:r?`"${c}", "Hiragino Sans GB", "PingFang SC", sans-serif`:`"${c}", "PingFang SC", sans-serif`}function ja(u,r=!1){if(!u)return'16px "PingFang SC", sans-serif';const s=u.match(/^(.*?)([\d.]+(?:px|pt|em|rem))\s+(.+)$/);if(!s)return u;const c=s[1],d=s[2],x=s[3];return`${c}${d} ${Gp(x,r)}`}async function qp(u,r){const{page:s,spec:c,config:d,totalPageCount:x=1,getImage:g,isServer:v=!1}=r,{algorithm:N,theme:m,chrome:y}=d;Dh(d.canvasStyle),u.save(),u.fillStyle=m.bgColor,u.fillRect(0,0,c.width,c.height),u.restore(),d.canvasStyle?.fill&&Lp(u,c,d.canvasStyle.fill);const p=d.coverTheme,b=async G=>{if(!G)return;const S=await g(G.src);if(!S)throw new Error("Failed to load cover theme image");const q=G.fit==="contain"?Math.min(c.width/S.width,c.height/S.height):Math.max(c.width/S.width,c.height/S.height),_=G.fit==="fill"?c.width:S.width*q,te=G.fit==="fill"?c.height:S.height*q;u.save(),u.globalAlpha=G.opacity,u.drawImage(S,(c.width-_)*G.position.x/100,(c.height-te)*G.position.y/100,_,te),u.restore()};if(p){if(!d.canvasStyle?.fill){const S=p.background.fill;if(u.save(),S.type==="solid")u.fillStyle=S.color;else{let q;if(S.type==="linear"){const _=S.angle*Math.PI/180,te=Math.cos(_)*c.width/2,ne=Math.sin(_)*c.height/2;q=u.createLinearGradient(c.width/2-te,c.height/2-ne,c.width/2+te,c.height/2+ne)}else{const _=c.width*S.position.x/100,te=c.height*S.position.y/100;q=u.createRadialGradient(_,te,0,_,te,Math.hypot(c.width,c.height))}for(const _ of S.stops)q.addColorStop(_.offset/100,_.color);u.fillStyle=q}u.fillRect(0,0,c.width,c.height),u.restore()}await b(p.background.image),p.background.overlay&&(u.save(),u.fillStyle=p.background.overlay.color,u.globalAlpha=p.background.overlay.opacity,u.fillRect(0,0,c.width,c.height),u.restore());const G=p.decoration;if(!d.canvasStyle?.pattern){u.save(),u.strokeStyle=u.fillStyle=G.color,u.globalAlpha=G.opacity;const S=Math.max(8,G.size);if(u.beginPath(),["lines","grid","dots"].includes(G.pattern)){for(let q=0;q<c.width;q+=S)if(G.pattern==="grid"&&(u.moveTo(q,0),u.lineTo(q,c.height)),G.pattern==="dots")for(let _=0;_<c.height;_+=S)u.moveTo(q+2,_),u.arc(q,_,2,0,Math.PI*2);if(G.pattern!=="dots")for(let q=0;q<c.height;q+=S)u.moveTo(0,q),u.lineTo(c.width,q)}else if(G.pattern==="rings")for(let q=S;q<Math.hypot(c.width,c.height);q+=S)u.moveTo(c.width/2+q,c.height/2),u.arc(c.width/2,c.height/2,q,0,Math.PI*2);else if(G.pattern==="burst")for(let q=0;q<Math.PI*2;q+=Math.PI/Math.max(8,Math.round(S/3)))u.moveTo(c.width/2,c.height/2),u.lineTo(c.width/2+Math.cos(q)*c.width,c.height/2+Math.sin(q)*c.height);G.pattern==="dots"?u.fill():u.stroke(),u.restore()}await b(G.image)}d.canvasStyle?.pattern&&Hp(u,c,d.canvasStyle.pattern);const{stageX:w,stageY:M}=zn(c,N.safeArea,N.contentBottomGap),Q=d.aspectRatio==="wechat-cover-2.35",B=y?.showHeader??!Q,L=(y?.showWatermark??!Q)&&!!d.watermarkText?.trim(),$=(y?.showPageNumber??(!Q&&x>1))&&x>1;if(B&&(L||$)){const G=Math.max(24,Math.floor(N.safeArea.top*.45));if(L&&(u.save(),u.font=ja("600 14px PingFang SC",v),u.fillStyle=m.watermarkColor,u.globalAlpha=.45,u.textBaseline="middle",u.textAlign="left",u.fillText(d.watermarkText.toUpperCase(),N.safeArea.left,G),u.restore()),$){u.save();const S=`P.${String(s.pageNumber).padStart(2,"0")}`;u.font='500 12px "SF Mono", Monaco, Menlo, Consolas, monospace',u.textBaseline="middle",u.textAlign="left";const _=u.measureText(S).width+16,te=24,ne=c.width-N.safeArea.right-_,he=G-te/2;u.strokeStyle=m.textColor,u.globalAlpha=.4,u.lineWidth=1,u.beginPath(),u.roundRect(ne,he,_,te,12),u.stroke(),u.fillStyle=m.textColor,u.fillText(S,ne+8,G),u.restore()}}const ee=[...s.images||[]].sort((G,S)=>{const q=G.zIndex??(G.isAbsolute?20:5),_=S.zIndex??(S.isAbsolute?20:5);return q-_}),ce=async G=>{for(const S of G){let q;try{q=await g(S.src)}catch(D){throw S.templateAssetKey?new Error(`模板素材 ${S.templateAssetKey} 加载失败:${D instanceof Error?D.message:String(D)}`):D}if(!q&&S.templateAssetKey)throw new Error(`模板素材 ${S.templateAssetKey} 加载失败:图片不存在或无法读取`);const _=w+S.x,te=M+S.y,ne=_+S.width/2,he=te+S.height/2;u.save(),u.translate(ne,he),S.rotate&&u.rotate(S.rotate*Math.PI/180),u.globalAlpha=S.opacity??1;const Y=S.width,O=S.height,k=Math.min(S.borderRadius??12,Y/2,O/2);if(u.beginPath(),u.roundRect(-Y/2,-O/2,Y,O,k),u.clip(),q?u.drawImage(q,-Y/2,-O/2,Y,O):(u.fillStyle=m.cardBg||"#222222",u.fillRect(-Y/2,-O/2,Y,O)),u.restore(),S.caption?.trim()){u.save();const D=Math.max(14,Math.round(N.baseFontSize*.45));u.font=ja(`400 ${D}px PingFang SC`,v),u.fillStyle=m.captionColor,u.textBaseline="top",u.textAlign="center",u.fillText(S.caption,ne,te+O+12),u.restore()}}};await ce(ee.filter(G=>(G.zIndex??(G.isAbsolute?20:5))<10));for(const G of s.lines){const S=w+G.x,q=M+G.y;if(G.className==="body-quote"){u.save(),u.fillStyle=m.accentColor,u.globalAlpha=.85,u.beginPath();const te=Math.max(1,G.lineHeight-8);typeof u.roundRect=="function"?u.roundRect(w,q+4,3.5,te,2):u.rect(w,q+4,3.5,te),u.fill(),u.restore()}if(G.bullet&&G.bulletX!==void 0){if(u.save(),u.fillStyle=m.accentColor,G.bullet==="•"){const te=Math.max(3,Math.round(N.baseFontSize*.08)),ne=w+G.bulletX+8,he=q+Math.round(G.lineHeight*.42);u.beginPath(),u.arc(ne,he,te,0,Math.PI*2),u.fill()}else u.font=ja(G.font,v),u.textBaseline="top",u.textAlign="left",u.fillText(G.bullet,w+G.bulletX,q);u.restore()}let _=S;for(const te of G.fragments){const ne=te.font||G.font,he=ja(ne,v);u.font=he,u.textBaseline="top",u.textAlign="left",te.highlight?u.fillStyle=m.accentColor:G.className.includes("heading")?u.fillStyle=m.headingColor||m.textColor:G.className.includes("quote")?u.fillStyle=m.quoteColor||m.textColor:u.fillStyle=m.textColor,u.letterSpacing=`${te.letterSpacing||0}px`,u.fillText(te.text,_,q);const Y=te.letterSpacing?te.occupiedWidth:u.measureText(te.text).width;_+=Y+(te.gapBefore||0)}}await ce(ee.filter(G=>(G.zIndex??(G.isAbsolute?20:5))>=10)),u.letterSpacing="0px";const ue=y?.showFooter??!Q,H=y?.showFooterDivider??(!Q&&!!d.footerText?.trim()),V=(y?.showFooterText??!Q)&&!!d.footerText?.trim();if(ue){const G=c.height-Math.max(24,Math.floor(N.safeArea.bottom*.45));if(H&&(u.save(),u.strokeStyle=m.borderSubtle||"#e5e5e5",u.lineWidth=1,u.beginPath(),u.moveTo(N.safeArea.left,G-14),u.lineTo(c.width-N.safeArea.right,G-14),u.stroke(),u.restore()),y?.showFillRatio&&(u.save(),u.font=ja("500 13px PingFang SC",v),u.fillStyle=m.captionColor,u.textBaseline="middle",u.textAlign="right",u.fillText(`填充率 ${Math.round(s.fillRatio*100)}%`,c.width-N.safeArea.right,G),u.restore()),V){u.save();const S=p?.typography.footer;u.font=ja(S?`${S.fontWeight} ${S.fontSize}px "${S.fontFamily}"`:"500 13px PingFang SC",v),u.letterSpacing=`${S?.letterSpacing||0}px`,u.fillStyle=m.watermarkColor||m.captionColor,u.globalAlpha=.6,u.textBaseline="middle",u.textAlign="left",u.fillText(d.footerText,N.safeArea.left,G),u.restore()}}Up(u,c,d.canvasStyle?.border)}const Yp=({page:u,spec:r,config:s,totalPageCount:c,zoom:d})=>{const x=fe.useRef(null),[g,v]=fe.useState(null);return fe.useEffect(()=>{const N=x.current;if(!N)return;const m=N.getContext("2d");if(!m)return;N.dataset.renderState="loading",v(null);let y=!1;const p=new AbortController,b=M=>M?new Promise(Q=>{const B=new Image;let L;const $=ce=>{p.signal.removeEventListener("abort",ee),B.onload=B.onerror=null,L&&(L.onload=L.onerror=null),Q(ce)},ee=()=>$(null);if(p.signal.aborted){$(null);return}p.signal.addEventListener("abort",ee,{once:!0}),B.crossOrigin="anonymous",B.onload=()=>$(B),B.onerror=()=>{L=new Image,L.onload=()=>$(L),L.onerror=()=>$(null),L.src=M},B.src=M}):Promise.resolve(null);return(async()=>{const M=document.createElement("canvas");M.width=r.width,M.height=r.height;const Q=M.getContext("2d");Q&&(await qp(Q,{page:u,spec:r,config:s,totalPageCount:c,getImage:b,isServer:!1}),y||(m.clearRect(0,0,r.width,r.height),m.drawImage(M,0,0),N.dataset.renderState="ready"))})().catch(M=>{y||(N.dataset.renderState="error",m.clearRect(0,0,r.width,r.height),v(M instanceof Error?M.message:"画布绘制失败"))}),()=>{y=!0,p.abort()}},[u,r,s,c]),f.jsxs(f.Fragment,{children:[f.jsx("canvas",{id:`typeset-page-${u.pageNumber}`,ref:x,width:r.width,height:r.height,className:"typeset-page absolute top-0 left-0 border border-[#e0e0e0] dark:border-[#222222] shadow-sm select-none",style:{width:r.width*d,height:r.height*d,backgroundColor:s.theme.bgColor}}),g&&f.jsx("div",{role:"alert",className:"absolute inset-0 flex items-center justify-center bg-white/90 p-4 text-sm text-red-600",children:g})]})},Xp=({result:u,zoom:r,viewportRef:s,onAutoFit:c,isAutoFit:d,viewMode:x="grid",onToggleViewMode:g,onFocusPage:v})=>{const{pages:N,canvasSpec:m,config:y}=u;return f.jsxs("main",{ref:s,className:"flex-1 min-w-0 overflow-auto bg-[#f5f5f5] dark:bg-[#050505] bg-grid flex flex-col p-6 select-none relative transition-colors",children:[f.jsxs("div",{className:"sticky top-0 z-20 self-center mb-6 px-3.5 py-1.5 rounded-full bg-white/90 dark:bg-[#111111]/90 backdrop-blur border border-[#eaeaea] dark:border-[#222222] text-[11px] font-mono text-[#666666] dark:text-[#888888] flex items-center gap-2.5 shadow-sm",children:[f.jsx("span",{className:"text-[#171717] dark:text-white font-semibold",children:m.name}),f.jsx("span",{children:"•"}),f.jsxs("span",{children:[m.width," × ",m.height,"px"]}),f.jsx("span",{children:"•"}),f.jsxs("span",{className:"text-black dark:text-white font-medium",children:[N.length," 张图片"]}),N.length>1&&g&&f.jsxs(f.Fragment,{children:[f.jsx("span",{children:"•"}),f.jsxs("div",{className:"flex items-center bg-[#eaeaea] dark:bg-[#1a1a1a] rounded-md p-0.5 border border-[#dfdfdf] dark:border-[#262626]",children:[f.jsxs("button",{onClick:()=>g("grid"),className:`flex items-center gap-1 px-2 py-0.5 rounded text-[10px] font-medium transition-all ${x==="grid"?"bg-white dark:bg-[#2b2b2b] text-black dark:text-white shadow-xs font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,title:"多图瀑布流平铺全览",children:[f.jsx(bp,{className:"w-3 h-3"}),f.jsx("span",{children:"多图平铺"})]}),f.jsxs("button",{onClick:()=>g("stack"),className:`flex items-center gap-1 px-2 py-0.5 rounded text-[10px] font-medium transition-all ${x==="stack"?"bg-white dark:bg-[#2b2b2b] text-black dark:text-white shadow-xs font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,title:"单列纵向逐页滚动",children:[f.jsx(Ap,{className:"w-3 h-3"}),f.jsx("span",{children:"纵向单列"})]})]})]}),c&&f.jsxs(f.Fragment,{children:[f.jsx("span",{children:"•"}),f.jsx("button",{onClick:c,className:`hover:text-black dark:hover:text-white transition-colors underline underline-offset-2 ${d?"text-emerald-600 dark:text-emerald-400 font-semibold":""}`,title:N.length>1?"缩放至视口内完整排列多张图片":"自适应画布比例",children:d?N.length>1?"已平铺适配":"已自适应":N.length>1?"平铺适配":"自适应"})]})]}),f.jsx("div",{className:"min-w-fit w-full flex-1 flex flex-col items-center justify-start pb-32",children:f.jsx("div",{className:`flex items-start justify-center gap-7 transition-all duration-300 ${x==="grid"?"flex-wrap max-w-full":"flex-col items-center"}`,children:N.map(p=>f.jsxs("div",{className:"flex flex-col items-center",children:[N.length>1&&f.jsxs("div",{className:"mb-2 px-2.5 py-1 rounded-md bg-white/90 dark:bg-[#181818]/90 border border-[#eaeaea] dark:border-[#262626] text-[11px] font-mono text-[#666666] dark:text-[#888888] shadow-xs flex items-center justify-between transition-colors",style:{width:m.width*r},children:[f.jsxs("div",{className:"flex items-center gap-1.5 truncate",children:[f.jsxs("span",{className:"font-semibold text-[#171717] dark:text-white",children:["第 ",p.pageNumber," / ",N.length," 页"]}),f.jsx("span",{children:"•"}),f.jsx("span",{className:"truncate",children:m.name})]}),v&&f.jsxs("button",{onClick:b=>{b.stopPropagation(),v(p.pageNumber)},className:"shrink-0 text-[10px] px-1.5 py-0.5 rounded bg-[#f5f5f5] dark:bg-[#242424] hover:bg-[#eaeaea] dark:hover:bg-[#333333] text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 font-medium transition-colors flex items-center gap-1 cursor-pointer",title:"放大聚焦此页",children:[f.jsx(kh,{className:"w-2.5 h-2.5"}),f.jsx("span",{children:"聚焦单图"})]})]}),f.jsx("div",{onDoubleClick:()=>v?.(p.pageNumber),className:"relative shrink-0 shadow-xl dark:shadow-2xl rounded-sm transition-shadow hover:shadow-2xl cursor-pointer",title:N.length>1?"双击放大聚焦此页":void 0,style:{width:m.width*r,height:m.height*r},children:f.jsx(Yp,{page:p,spec:m,config:y,totalPageCount:N.length,zoom:r})})]},p.pageNumber))})})]})},Qp=({markdown:u,onMarkdownChange:r,images:s,onAddImage:c,onToggleBackground:d,onResetImageLayout:x,backgroundImageIds:g,onUpdateImage:v,onRemoveImage:N,onMoveImage:m,pageCount:y=1,highlightWords:p,onHighlightWordsChange:b,adminKey:w})=>{const[M,Q]=fe.useState("text"),[B,L]=fe.useState(""),$=fe.useRef(null),[ee,ce]=fe.useState(!1),ue=S=>{r(u?`${u}
|
|
289
|
+
*/const Th={name:"zoom-out",size:24,node:[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]};Th.node;const Bp=we(Th),zp=({isOpen:u,onClose:r,currentKey:s,onSaveKey:c,isVerified:d})=>{const[x,g]=fe.useState(s),[v,N]=fe.useState(null);if(!u)return null;const m=()=>{c(x.trim()),N("密钥已更新并保存至本地存储"),setTimeout(()=>{r()},800)};return f.jsx("div",{className:"fixed inset-0 z-50 bg-black/50 dark:bg-black/70 backdrop-blur-sm flex items-center justify-center p-4",children:f.jsxs("div",{className:"bg-white dark:bg-[#0f0f0f] border border-[#eaeaea] dark:border-[#262626] rounded-xl w-full max-w-md flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-150 transition-colors",children:[f.jsxs("div",{className:"flex items-center justify-between px-5 py-3.5 border-b border-[#eaeaea] dark:border-[#222222]",children:[f.jsxs("div",{className:"flex items-center gap-2 font-semibold text-sm text-[#171717] dark:text-white",children:[f.jsx(eh,{className:"w-4 h-4 text-amber-500 dark:text-amber-400"}),f.jsx("span",{children:"超管密钥授权"})]}),f.jsx("button",{onClick:r,className:"text-[#888888] hover:text-black dark:hover:text-white p-1 rounded-md hover:bg-[#f5f5f5] dark:hover:bg-[#1a1a1a]",children:f.jsx(jo,{className:"w-4 h-4"})})]}),f.jsxs("div",{className:"p-5 flex flex-col gap-4",children:[f.jsxs("div",{className:"text-xs text-[#666666] dark:text-[#888888] leading-relaxed",children:["服务端默认通过 ",f.jsx("code",{className:"text-black dark:text-[#ededed] font-mono font-semibold",children:"TYPESET_ADMIN_KEY"})," 保护模板持久化、图片上传和无头出图 API。请填入服务启动时控制台打印的管理员密钥。"]}),f.jsxs("div",{className:"flex flex-col gap-1.5",children:[f.jsx("label",{className:"text-[11px] font-mono text-[#888888] dark:text-[#666666]",children:"X-Admin-Key"}),f.jsx("input",{type:"password",value:x,onChange:y=>g(y.target.value),placeholder:"tsk_...",className:"bg-[#fafafa] dark:bg-[#0a0a0a] border border-[#d4d4d4] dark:border-[#2a2a2a] rounded-lg px-3 py-2 text-xs font-mono text-black dark:text-white focus:outline-none focus:border-black dark:focus:border-[#444444]"})]}),v?f.jsxs("div",{className:"text-xs text-emerald-700 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/20 px-3 py-2 rounded-lg flex items-center gap-2 font-medium",children:[f.jsx(Qx,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:v})]}):d?f.jsxs("div",{className:"text-xs text-emerald-700 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/20 px-3 py-2 rounded-lg flex items-center gap-2 font-medium",children:[f.jsx(Cp,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"密钥已通过验证,拥有超管权限"})]}):f.jsx("div",{className:"text-xs text-amber-700 dark:text-amber-400 bg-amber-50 dark:bg-amber-500/10 border border-amber-200 dark:border-amber-500/20 px-3 py-2 rounded-lg",children:"当前密钥未验证或已失效,请检查后端 .env 配置"}),f.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[f.jsx("button",{onClick:r,className:"px-3 py-1.5 rounded-lg border border-[#eaeaea] dark:border-[#262626] text-xs text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white hover:bg-[#f5f5f5] dark:hover:bg-[#161616]",children:"取消"}),f.jsx("button",{onClick:m,className:"px-4 py-1.5 bg-black text-white hover:bg-[#262626] dark:bg-white dark:text-black dark:hover:bg-[#eaeaea] text-xs font-semibold rounded-lg transition-all btn-vercel",children:"保存并授权"})]})]})]})})},vx={"wechat-cover-2.35":{id:"wechat-cover-2.35",name:"微信文章封面",ratio:3.35,width:3350,height:1e3,description:"微信文章封面原图 (3.35:1):左侧 2.35:1 大图,右侧 1:1 小图",defaultSafeArea:{top:120,right:140,bottom:120,left:140}},"longform-3-4":{id:"longform-3-4",name:"通用长图文",ratio:3/4,width:1080,height:1440,description:"3:4 手机端阅读长文/图文卡片,支持多页分页、矩形图片绕排、目标填充率优化",defaultSafeArea:{top:96,right:88,bottom:96,left:88}},"wide-16-9":{id:"wide-16-9",name:"通用宽屏",ratio:16/9,width:1920,height:1080,description:"16:9 横版宽屏,适合推特/X 动态配图、技术博客 Banner、视频封面与分栏排版",defaultSafeArea:{top:100,right:120,bottom:100,left:120}},"square-1-1":{id:"square-1-1",name:"通用正方形",ratio:1,width:1200,height:1200,description:"1:1 正方形卡片,适合金句名言卡、公众号次条、小红书方图与社交媒体方版海报",defaultSafeArea:{top:100,right:100,bottom:100,left:100}}};function Tl(u){return vx[u]??vx["longform-3-4"]}function zn(u,r,s=20){const c=Math.max(100,u.width-r.left-r.right),d=Math.max(100,u.height-r.top-r.bottom-s);return{stageWidth:c,stageHeight:d,stageX:r.left,stageY:r.top}}const _p={pattern:"none",color:"#527561",opacity:.12,size:56},Rp={style:"none",color:"#527561",endColor:"#d7ad72",width:3,inset:32,radius:24,opacity:.8},Fh={none:"无花纹",lines:"横线",grid:"网格",dots:"圆点",diagonal:"斜线",waves:"波浪",rings:"同心圆",burst:"放射线",checker:"棋盘格",grain:"纸张颗粒"},jh={none:"无边框",solid:"实线",dashed:"虚线",double:"双线",corners:"四角装饰",gradient:"渐变描边"};function Dh(u){if(u===void 0)return;if(!u||typeof u!="object"||Array.isArray(u))throw new RangeError("无效的背景与边框配置");const r=c=>{if(typeof c!="string"||!/^#[0-9a-f]{6}$/i.test(c))throw new RangeError("背景装饰颜色必须是六位十六进制颜色")},s=(c,d,x)=>{if(!Number.isFinite(c)||c<d||c>x)throw new RangeError(`背景装饰参数必须在 ${d} 到 ${x} 之间`)};if(u.fill){const c=u.fill;if(c.type==="solid")r(c.color);else{if(c.type==="linear")s(c.angle,0,360);else if(c.type==="radial")s(c.position?.x,0,100),s(c.position?.y,0,100);else throw new RangeError("未知背景类型");if(!Array.isArray(c.stops)||c.stops.length<2||c.stops.length>8)throw new RangeError("渐变需要 2 到 8 个颜色节点");for(const d of c.stops){if(!d)throw new RangeError("无效的渐变节点");r(d.color),s(d.offset,0,100)}}}if(u.pattern){const c=u.pattern;if(!Object.hasOwn(Fh,c.pattern))throw new RangeError("未知背景花纹");r(c.color),s(c.opacity,0,1),s(c.size,16,240)}if(u.border){const c=u.border;if(!Object.hasOwn(jh,c.style))throw new RangeError("未知边框样式");r(c.color),r(c.endColor),s(c.width,1,24),s(c.inset,0,200),s(c.radius,0,200),s(c.opacity,0,1)}}function Lp(u,r,s){if(u.save(),s.type==="solid")u.fillStyle=s.color;else{let c;if(s.type==="linear"){const d=s.angle*Math.PI/180,x=Math.abs(Math.cos(d))*r.width/2+Math.abs(Math.sin(d))*r.height/2,g=Math.cos(d)*x,v=Math.sin(d)*x;c=u.createLinearGradient(r.width/2-g,r.height/2-v,r.width/2+g,r.height/2+v)}else{const d=r.width*s.position.x/100,x=r.height*s.position.y/100,g=Math.hypot(Math.max(d,r.width-d),Math.max(x,r.height-x));c=u.createRadialGradient(d,x,0,d,x,g)}for(const d of s.stops)c.addColorStop(d.offset/100,d.color);u.fillStyle=c}u.fillRect(0,0,r.width,r.height),u.restore()}function Hp(u,r,s){if(s.pattern==="none"||s.opacity===0)return;const{width:c,height:d}=r,x=Math.max(16,s.size);switch(u.save(),u.strokeStyle=u.fillStyle=s.color,u.globalAlpha=s.opacity,u.lineWidth=1.5,u.beginPath(),s.pattern){case"grid":case"lines":if(s.pattern==="grid")for(let g=x/2;g<c;g+=x)u.moveTo(g,0),u.lineTo(g,d);for(let g=x/2;g<d;g+=x)u.moveTo(0,g),u.lineTo(c,g);break;case"dots":for(let g=x/2;g<c;g+=x)for(let v=x/2;v<d;v+=x)u.moveTo(g+2,v),u.arc(g,v,2,0,Math.PI*2);break;case"diagonal":for(let g=-d;g<c;g+=x)u.moveTo(g,0),u.lineTo(g+d,d);break;case"waves":for(let g=-x;g<d+x;g+=x){u.moveTo(0,g);for(let v=0;v<c;v+=x*2)u.bezierCurveTo(v+x*.5,g-x*.45,v+x*1.5,g+x*.45,v+x*2,g)}break;case"rings":for(let g=x;g<Math.hypot(c,d);g+=x)u.moveTo(c*.82+g,d*.18),u.arc(c*.82,d*.18,g,0,Math.PI*2);break;case"burst":for(let g=0;g<Math.PI*2;g+=Math.PI/Math.max(8,Math.round(x/3)))u.moveTo(c*.8,d*.2),u.lineTo(c*.8+Math.cos(g)*c*2,d*.2+Math.sin(g)*d*2);break;case"checker":for(let g=0;g<c;g+=x)for(let v=0;v<d;v+=x)(Math.round(g/x)+Math.round(v/x))%2===0&&u.rect(g,v,x,x);break;case"grain":{let g=42;const v=()=>(g=Math.imul(g,1664525)+1013904223>>>0,g/4294967296);for(let N=0;N<c*d/(x*3);N++){const m=v()*c,y=v()*d;u.rect(m,y,.6+v()*1.2,.6+v()*1.2)}break}}["dots","checker","grain"].includes(s.pattern)?u.fill():u.stroke(),u.restore()}function Up(u,r,s){if(!s||s.style==="none"||s.opacity===0)return;const c=Math.min(s.inset+s.width/2,Math.min(r.width,r.height)/2-1),d=r.width-c*2,x=r.height-c*2;if(u.save(),u.globalAlpha=s.opacity,u.lineWidth=s.width,u.strokeStyle=s.color,s.style==="gradient"){const v=u.createLinearGradient(0,0,r.width,r.height);v.addColorStop(0,s.color),v.addColorStop(1,s.endColor),u.strokeStyle=v}s.style==="dashed"&&u.setLineDash([s.width*4,s.width*3]);const g=v=>{u.beginPath(),u.roundRect(c+v,c+v,d-v*2,x-v*2,Math.max(0,s.radius-v)),u.stroke()};if(s.style==="corners"){const v=Math.min(d,x)*.12;for(const N of[c,r.width-c])for(const m of[c,r.height-c]){const y=N===c?1:-1,p=m===c?1:-1;u.beginPath(),u.moveTo(N+y*v,m),u.lineTo(N,m),u.lineTo(N,m+p*v),u.stroke()}}else g(0),s.style==="double"&&g(s.width*3+4);u.restore()}function Gp(u,r=!1){const c=((u||"").split(",")[0]||"").replace(/["'\\]/g,"").trim();return c.includes("Noto Sans")?r?'"Hiragino Sans GB", sans-serif':'"Noto Sans SC", "PingFang SC", sans-serif':c.includes("PingFang")?r?'"Hiragino Sans GB", sans-serif':'"PingFang SC", "Noto Sans SC", sans-serif':c.includes("Noto Serif")?r?'"Songti SC", serif':'"Noto Serif SC", "Songti SC", serif':c.includes("Songti")||c==="STSong"?r?'"Songti SC", serif':'"Songti SC", "Noto Serif SC", serif':c.includes("Kai")||c.includes("WenKai")?r?'"STKaiti", "Kaiti SC", "Songti SC", serif':'"LXGW WenKai GB Screen", "LXGW WenKai Screen", "Kaiti SC", "STKaiti", serif':c.includes("Yuan")?r?'"STYuanti", "Yuanti SC", "Hiragino Sans GB", sans-serif':'"Yuanti SC", "STYuanti", "PingFang SC", sans-serif':c.includes("Inter")?r?'Inter, "Hiragino Sans GB", sans-serif':'Inter, "PingFang SC", sans-serif':c.includes("Georgia")?'Georgia, "Songti SC", serif':c.toLowerCase().includes("serif")||c.includes("Song")?`"${c}", "Songti SC", serif`:r?`"${c}", "Hiragino Sans GB", "PingFang SC", sans-serif`:`"${c}", "PingFang SC", sans-serif`}function ja(u,r=!1){if(!u)return'16px "PingFang SC", sans-serif';const s=u.match(/^(.*?)([\d.]+(?:px|pt|em|rem))\s+(.+)$/);if(!s)return u;const c=s[1],d=s[2],x=s[3];return`${c}${d} ${Gp(x,r)}`}async function qp(u,r){const{page:s,spec:c,config:d,totalPageCount:x=1,getImage:g,isServer:v=!1}=r,{algorithm:N,theme:m,chrome:y}=d;Dh(d.canvasStyle),u.save(),u.fillStyle=m.bgColor,u.fillRect(0,0,c.width,c.height),u.restore(),d.canvasStyle?.fill&&Lp(u,c,d.canvasStyle.fill);const p=d.coverTheme,b=async G=>{if(!G)return;const S=await g(G.src);if(!S)throw new Error("Failed to load cover theme image");const q=G.fit==="contain"?Math.min(c.width/S.width,c.height/S.height):Math.max(c.width/S.width,c.height/S.height),_=G.fit==="fill"?c.width:S.width*q,te=G.fit==="fill"?c.height:S.height*q;u.save(),u.globalAlpha=G.opacity,u.drawImage(S,(c.width-_)*G.position.x/100,(c.height-te)*G.position.y/100,_,te),u.restore()};if(p){if(!d.canvasStyle?.fill){const S=p.background.fill;if(u.save(),S.type==="solid")u.fillStyle=S.color;else{let q;if(S.type==="linear"){const _=S.angle*Math.PI/180,te=Math.cos(_)*c.width/2,ne=Math.sin(_)*c.height/2;q=u.createLinearGradient(c.width/2-te,c.height/2-ne,c.width/2+te,c.height/2+ne)}else{const _=c.width*S.position.x/100,te=c.height*S.position.y/100;q=u.createRadialGradient(_,te,0,_,te,Math.hypot(c.width,c.height))}for(const _ of S.stops)q.addColorStop(_.offset/100,_.color);u.fillStyle=q}u.fillRect(0,0,c.width,c.height),u.restore()}await b(p.background.image),p.background.overlay&&(u.save(),u.fillStyle=p.background.overlay.color,u.globalAlpha=p.background.overlay.opacity,u.fillRect(0,0,c.width,c.height),u.restore());const G=p.decoration;if(!d.canvasStyle?.pattern){u.save(),u.strokeStyle=u.fillStyle=G.color,u.globalAlpha=G.opacity;const S=Math.max(8,G.size);if(u.beginPath(),["lines","grid","dots"].includes(G.pattern)){for(let q=0;q<c.width;q+=S)if(G.pattern==="grid"&&(u.moveTo(q,0),u.lineTo(q,c.height)),G.pattern==="dots")for(let _=0;_<c.height;_+=S)u.moveTo(q+2,_),u.arc(q,_,2,0,Math.PI*2);if(G.pattern!=="dots")for(let q=0;q<c.height;q+=S)u.moveTo(0,q),u.lineTo(c.width,q)}else if(G.pattern==="rings")for(let q=S;q<Math.hypot(c.width,c.height);q+=S)u.moveTo(c.width/2+q,c.height/2),u.arc(c.width/2,c.height/2,q,0,Math.PI*2);else if(G.pattern==="burst")for(let q=0;q<Math.PI*2;q+=Math.PI/Math.max(8,Math.round(S/3)))u.moveTo(c.width/2,c.height/2),u.lineTo(c.width/2+Math.cos(q)*c.width,c.height/2+Math.sin(q)*c.height);G.pattern==="dots"?u.fill():u.stroke(),u.restore()}await b(G.image)}d.canvasStyle?.pattern&&Hp(u,c,d.canvasStyle.pattern);const{stageX:w,stageY:M}=zn(c,N.safeArea,N.contentBottomGap),Q=d.aspectRatio==="wechat-cover-2.35",B=y?.showHeader??!Q,L=(y?.showWatermark??!Q)&&!!d.watermarkText?.trim(),$=(y?.showPageNumber??(!Q&&x>1))&&x>1;if(B&&(L||$)){const G=Math.max(24,Math.floor(N.safeArea.top*.45));if(L&&(u.save(),u.font=ja("600 14px PingFang SC",v),u.fillStyle=m.watermarkColor,u.globalAlpha=.45,u.textBaseline="middle",u.textAlign="left",u.fillText(d.watermarkText.toUpperCase(),N.safeArea.left,G),u.restore()),$){u.save();const S=`P.${String(s.pageNumber).padStart(2,"0")}`;u.font='500 12px "SF Mono", Monaco, Menlo, Consolas, monospace',u.textBaseline="middle",u.textAlign="left";const _=u.measureText(S).width+16,te=24,ne=c.width-N.safeArea.right-_,he=G-te/2;u.strokeStyle=m.textColor,u.globalAlpha=.4,u.lineWidth=1,u.beginPath(),u.roundRect(ne,he,_,te,12),u.stroke(),u.fillStyle=m.textColor,u.fillText(S,ne+8,G),u.restore()}}const ee=[...s.images||[]].sort((G,S)=>{const q=G.zIndex??(G.isAbsolute?20:5),_=S.zIndex??(S.isAbsolute?20:5);return q-_}),ce=async G=>{for(const S of G){let q;try{q=await g(S.src)}catch(D){throw S.templateAssetKey?new Error(`模板素材 ${S.templateAssetKey} 加载失败:${D instanceof Error?D.message:String(D)}`):D}if(!q&&S.templateAssetKey)throw new Error(`模板素材 ${S.templateAssetKey} 加载失败:图片不存在或无法读取`);const _=w+S.x,te=M+S.y,ne=_+S.width/2,he=te+S.height/2;u.save(),u.translate(ne,he),S.rotate&&u.rotate(S.rotate*Math.PI/180),u.globalAlpha=S.opacity??1;const Y=S.width,O=S.height,k=Math.min(S.borderRadius??12,Y/2,O/2);if(u.beginPath(),u.roundRect(-Y/2,-O/2,Y,O,k),u.clip(),q?u.drawImage(q,-Y/2,-O/2,Y,O):(u.fillStyle=m.cardBg||"#222222",u.fillRect(-Y/2,-O/2,Y,O)),u.restore(),S.caption?.trim()){u.save();const D=Math.max(14,Math.round(N.baseFontSize*.45));u.font=ja(`400 ${D}px PingFang SC`,v),u.fillStyle=m.captionColor,u.textBaseline="top",u.textAlign="center",u.fillText(S.caption,ne,te+O+12),u.restore()}}};await ce(ee.filter(G=>(G.zIndex??(G.isAbsolute?20:5))<10));for(const G of s.lines){const S=w+G.x,q=M+G.y;if(G.className==="body-quote"){u.save(),u.fillStyle=m.accentColor,u.globalAlpha=.85,u.beginPath();const te=Math.max(1,G.lineHeight-8);typeof u.roundRect=="function"?u.roundRect(w,q+4,3.5,te,2):u.rect(w,q+4,3.5,te),u.fill(),u.restore()}if(G.bullet&&G.bulletX!==void 0){if(u.save(),u.fillStyle=m.accentColor,G.bullet==="•"){const te=Math.max(3,Math.round(N.baseFontSize*.08)),ne=w+G.bulletX+8,he=q+Math.round(G.lineHeight*.42);u.beginPath(),u.arc(ne,he,te,0,Math.PI*2),u.fill()}else u.font=ja(G.font,v),u.textBaseline="top",u.textAlign="left",u.fillText(G.bullet,w+G.bulletX,q);u.restore()}let _=S;for(const te of G.fragments){const ne=te.font||G.font,he=ja(ne,v);u.font=he,u.textBaseline="top",u.textAlign="left",te.highlight?u.fillStyle=m.accentColor:G.className.includes("heading")?u.fillStyle=m.headingColor||m.textColor:G.className.includes("quote")?u.fillStyle=m.quoteColor||m.textColor:u.fillStyle=m.textColor,u.letterSpacing=`${te.letterSpacing||0}px`,u.fillText(te.text,_,q);const Y=te.letterSpacing?te.occupiedWidth:u.measureText(te.text).width;_+=Y+(te.gapBefore||0)}}await ce(ee.filter(G=>(G.zIndex??(G.isAbsolute?20:5))>=10)),u.letterSpacing="0px";const ue=y?.showFooter??!Q,H=y?.showFooterDivider??(!Q&&!!d.footerText?.trim()),V=(y?.showFooterText??!Q)&&!!d.footerText?.trim();if(ue){const G=c.height-Math.max(24,Math.floor(N.safeArea.bottom*.45));if(H&&(u.save(),u.strokeStyle=m.borderSubtle||"#e5e5e5",u.lineWidth=1,u.beginPath(),u.moveTo(N.safeArea.left,G-14),u.lineTo(c.width-N.safeArea.right,G-14),u.stroke(),u.restore()),y?.showFillRatio&&(u.save(),u.font=ja("500 13px PingFang SC",v),u.fillStyle=m.captionColor,u.textBaseline="middle",u.textAlign="right",u.fillText(`填充率 ${Math.round(s.fillRatio*100)}%`,c.width-N.safeArea.right,G),u.restore()),V){u.save();const S=p?.typography.footer;u.font=ja(S?`${S.fontWeight} ${S.fontSize}px "${S.fontFamily}"`:"500 13px PingFang SC",v),u.letterSpacing=`${S?.letterSpacing||0}px`,u.fillStyle=m.watermarkColor||m.captionColor,u.globalAlpha=.6,u.textBaseline="middle",u.textAlign="left",u.fillText(d.footerText,N.safeArea.left,G),u.restore()}}Up(u,c,d.canvasStyle?.border)}const Yp=({page:u,spec:r,config:s,totalPageCount:c,zoom:d})=>{const x=fe.useRef(null),[g,v]=fe.useState(null);return fe.useEffect(()=>{const N=x.current;if(!N)return;const m=N.getContext("2d");if(!m)return;N.dataset.renderState="loading",v(null);let y=!1;const p=new AbortController,b=M=>M?new Promise(Q=>{const B=new Image;let L;const $=ce=>{p.signal.removeEventListener("abort",ee),B.onload=B.onerror=null,L&&(L.onload=L.onerror=null),Q(ce)},ee=()=>$(null);if(p.signal.aborted){$(null);return}p.signal.addEventListener("abort",ee,{once:!0}),B.crossOrigin="anonymous",B.onload=()=>$(B),B.onerror=()=>{L=new Image,L.onload=()=>$(L),L.onerror=()=>$(null),L.src=M},B.src=M}):Promise.resolve(null);return(async()=>{const M=document.createElement("canvas");M.width=r.width,M.height=r.height;const Q=M.getContext("2d");Q&&(await qp(Q,{page:u,spec:r,config:s,totalPageCount:c,getImage:b,isServer:!1}),y||(m.clearRect(0,0,r.width,r.height),m.drawImage(M,0,0),N.dataset.renderState="ready"))})().catch(M=>{y||(N.dataset.renderState="error",m.clearRect(0,0,r.width,r.height),v(M instanceof Error?M.message:"画布绘制失败"))}),()=>{y=!0,p.abort()}},[u,r,s,c]),f.jsxs(f.Fragment,{children:[f.jsx("canvas",{id:`typeset-page-${u.pageNumber}`,ref:x,width:r.width,height:r.height,className:"typeset-page absolute top-0 left-0 border border-[#e0e0e0] dark:border-[#222222] shadow-sm select-none",style:{width:r.width*d,height:r.height*d,backgroundColor:s.theme.bgColor}}),g&&f.jsx("div",{role:"alert",className:"absolute inset-0 flex items-center justify-center bg-white/90 p-4 text-sm text-red-600",children:g})]})},Xp=({result:u,zoom:r,viewportRef:s,onAutoFit:c,isAutoFit:d,viewMode:x="grid",onToggleViewMode:g,onFocusPage:v})=>{const{pages:N,canvasSpec:m,config:y}=u;return f.jsxs("main",{ref:s,className:"flex-1 min-w-0 overflow-auto bg-[#f5f5f5] dark:bg-[#050505] bg-grid flex flex-col p-6 select-none relative transition-colors",children:[f.jsxs("div",{className:"sticky top-0 z-20 self-center mb-6 px-3.5 py-1.5 rounded-full bg-white/90 dark:bg-[#111111]/90 backdrop-blur border border-[#eaeaea] dark:border-[#222222] text-[11px] font-mono text-[#666666] dark:text-[#888888] flex items-center gap-2.5 shadow-sm",children:[f.jsx("span",{className:"text-[#171717] dark:text-white font-semibold",children:m.name}),f.jsx("span",{children:"•"}),f.jsxs("span",{children:[m.width," × ",m.height,"px"]}),f.jsx("span",{children:"•"}),f.jsxs("span",{className:"text-black dark:text-white font-medium",children:[N.length," 张图片"]}),N.length>1&&g&&f.jsxs(f.Fragment,{children:[f.jsx("span",{children:"•"}),f.jsxs("div",{className:"flex items-center bg-[#eaeaea] dark:bg-[#1a1a1a] rounded-md p-0.5 border border-[#dfdfdf] dark:border-[#262626]",children:[f.jsxs("button",{onClick:()=>g("grid"),className:`flex items-center gap-1 px-2 py-0.5 rounded text-[10px] font-medium transition-all ${x==="grid"?"bg-white dark:bg-[#2b2b2b] text-black dark:text-white shadow-xs font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,title:"多图瀑布流平铺全览",children:[f.jsx(bp,{className:"w-3 h-3"}),f.jsx("span",{children:"多图平铺"})]}),f.jsxs("button",{onClick:()=>g("stack"),className:`flex items-center gap-1 px-2 py-0.5 rounded text-[10px] font-medium transition-all ${x==="stack"?"bg-white dark:bg-[#2b2b2b] text-black dark:text-white shadow-xs font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,title:"单列纵向逐页滚动",children:[f.jsx(Ap,{className:"w-3 h-3"}),f.jsx("span",{children:"纵向单列"})]})]})]}),c&&f.jsxs(f.Fragment,{children:[f.jsx("span",{children:"•"}),f.jsx("button",{onClick:c,className:`hover:text-black dark:hover:text-white transition-colors underline underline-offset-2 ${d?"text-emerald-600 dark:text-emerald-400 font-semibold":""}`,title:N.length>1?"缩放至视口内完整排列多张图片":"自适应画布比例",children:d?N.length>1?"已平铺适配":"已自适应":N.length>1?"平铺适配":"自适应"})]})]}),f.jsx("div",{className:"min-w-fit w-full flex-1 flex flex-col items-center justify-start pb-32",children:f.jsx("div",{className:`flex items-start justify-center gap-7 transition-all duration-300 ${x==="grid"?"flex-wrap max-w-full":"flex-col items-center"}`,children:N.map(p=>f.jsxs("div",{className:"flex flex-col items-center",children:[N.length>1&&f.jsxs("div",{className:"mb-2 px-2.5 py-1 rounded-md bg-white/90 dark:bg-[#181818]/90 border border-[#eaeaea] dark:border-[#262626] text-[11px] font-mono text-[#666666] dark:text-[#888888] shadow-xs flex items-center justify-between transition-colors",style:{width:m.width*r},children:[f.jsxs("div",{className:"flex items-center gap-1.5 truncate",children:[f.jsxs("span",{className:"font-semibold text-[#171717] dark:text-white",children:["第 ",p.pageNumber," / ",N.length," 页"]}),f.jsx("span",{children:"•"}),f.jsx("span",{className:"truncate",children:m.name})]}),v&&f.jsxs("button",{onClick:b=>{b.stopPropagation(),v(p.pageNumber)},className:"shrink-0 text-[10px] px-1.5 py-0.5 rounded bg-[#f5f5f5] dark:bg-[#242424] hover:bg-[#eaeaea] dark:hover:bg-[#333333] text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 font-medium transition-colors flex items-center gap-1 cursor-pointer",title:"放大聚焦此页",children:[f.jsx(kh,{className:"w-2.5 h-2.5"}),f.jsx("span",{children:"聚焦单图"})]})]}),f.jsx("div",{onDoubleClick:()=>v?.(p.pageNumber),className:"relative shrink-0 shadow-xl dark:shadow-2xl rounded-sm transition-shadow hover:shadow-2xl cursor-pointer",title:N.length>1?"双击放大聚焦此页":void 0,style:{width:m.width*r,height:m.height*r},children:f.jsx(Yp,{page:p,spec:m,config:y,totalPageCount:N.length,zoom:r})})]},p.pageNumber))})})]})},Qp=({markdown:u,onMarkdownChange:r,images:s,onAddImage:c,onToggleBackground:d,onResetImageLayout:x,backgroundImageIds:g,onUpdateImage:v,onRemoveImage:N,onMoveImage:m,pageCount:y=1,highlightWords:p,onHighlightWordsChange:b,adminKey:w})=>{const[M,Q]=fe.useState("text"),[B,L]=fe.useState(""),$=fe.useRef(null),[ee,ce]=fe.useState(!1),ue=S=>{r(u?`${u}
|
|
290
290
|
|
|
291
291
|
${S}`:S)},H=async S=>{const q=S.target.files?.[0];if(!q)return;const _=ne=>c({src:ne,alt:q.name,caption:"",x:40,y:400,width:440,height:300,captionHeight:36,layoutPreset:"auto"}),te=()=>{const ne=new FileReader;ne.onload=()=>{typeof ne.result=="string"&&_(ne.result)},ne.readAsDataURL(q)};ce(!0);try{const ne=new FormData;ne.append("file",q);const Y=await(await fetch("/api/upload",{method:"POST",headers:w?{"x-admin-key":w}:{},body:ne})).json();Y.ok&&Y.url?_(Y.url):te()}catch{te()}finally{ce(!1),$.current&&($.current.value="")}},V=()=>{B.trim()&&(p.includes(B.trim())||b([...p,B.trim()]),L(""))},G=S=>{b(p.filter(q=>q!==S))};return f.jsxs("aside",{className:"w-80 border-r border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] flex flex-col shrink-0 select-none transition-colors",children:[f.jsxs("div",{className:"flex border-b border-[#eaeaea] dark:border-[#222222] bg-[#f9f9f9] dark:bg-[#050505] p-1 gap-1",children:[f.jsxs("button",{onClick:()=>Q("text"),className:`flex-1 flex items-center justify-center gap-1.5 py-1.5 text-xs rounded font-medium transition-all ${M==="text"?"bg-white dark:bg-[#1f1f1f] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-[#cccccc]"}`,children:[f.jsx(fp,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"正文"})]}),f.jsxs("button",{onClick:()=>Q("images"),className:`flex-1 flex items-center justify-center gap-1.5 py-1.5 text-xs rounded font-medium transition-all ${M==="images"?"bg-white dark:bg-[#1f1f1f] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-[#cccccc]"}`,children:[f.jsx(gp,{className:"w-3.5 h-3.5"}),f.jsxs("span",{children:["配图 (",s.length,")"]})]}),f.jsxs("button",{onClick:()=>Q("highlights"),className:`flex-1 flex items-center justify-center gap-1.5 py-1.5 text-xs rounded font-medium transition-all ${M==="highlights"?"bg-white dark:bg-[#1f1f1f] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-[#cccccc]"}`,children:[f.jsx(mp,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"重点词"})]})]}),M==="text"&&f.jsxs("div",{className:"flex-1 flex flex-col p-3 gap-2 overflow-hidden",children:[f.jsxs("div",{className:"flex items-center gap-1 pb-1 flex-wrap border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("button",{onClick:()=>ue("# 标题"),className:"px-2 py-1 bg-[#f5f5f5] dark:bg-[#141414] hover:bg-[#eaeaea] dark:hover:bg-[#202020] text-[#555555] dark:text-[#aaaaaa] hover:text-black dark:hover:text-white rounded text-[11px] font-mono flex items-center gap-1 transition-colors",title:"插入主标题",children:[f.jsx(hp,{className:"w-3 h-3"}),f.jsx("span",{children:"H1"})]}),f.jsxs("button",{onClick:()=>ue("## 二级标题"),className:"px-2 py-1 bg-[#f5f5f5] dark:bg-[#141414] hover:bg-[#eaeaea] dark:hover:bg-[#202020] text-[#555555] dark:text-[#aaaaaa] hover:text-black dark:hover:text-white rounded text-[11px] font-mono flex items-center gap-1 transition-colors",title:"插入副标题",children:[f.jsx(xp,{className:"w-3 h-3"}),f.jsx("span",{children:"H2"})]}),f.jsx("button",{onClick:()=>ue("> 引用格言名句..."),className:"px-2 py-1 bg-[#f5f5f5] dark:bg-[#141414] hover:bg-[#eaeaea] dark:hover:bg-[#202020] text-[#555555] dark:text-[#aaaaaa] hover:text-black dark:hover:text-white rounded text-[11px] font-mono transition-colors",title:"插入引用块",children:"Quote"}),f.jsxs("button",{onClick:()=>ue("【第二页】"),className:"px-2 py-1 bg-blue-500/10 hover:bg-blue-500/20 text-blue-600 dark:text-blue-400 rounded text-[11px] font-mono flex items-center gap-1 transition-colors",title:"显式分页标记",children:[f.jsx(pp,{className:"w-3 h-3"}),f.jsx("span",{children:"分页面"})]})]}),f.jsx("textarea",{value:u,onChange:S=>r(S.target.value),placeholder:"在此输入 Markdown 内容,纯算法即时排版...",className:"flex-1 w-full bg-[#fafafa] dark:bg-[#0d0d0d] border border-[#eaeaea] dark:border-[#222222] rounded-lg p-3 text-xs font-mono text-[#171717] dark:text-[#ededed] placeholder-[#999999] dark:placeholder-[#444444] resize-none focus:outline-none focus:border-black dark:focus:border-[#444444] transition-all leading-relaxed"}),f.jsxs("div",{className:"flex items-center justify-between text-[11px] text-[#888888] dark:text-[#555555] font-mono px-1",children:[f.jsxs("span",{children:["字符数: ",u.length]}),f.jsxs("span",{children:["行数: ",u.split(`
|
|
292
|
-
`).length]})]})]}),M==="images"&&f.jsxs("div",{className:"flex-1 flex flex-col p-3 gap-3 overflow-y-auto",children:[f.jsxs("div",{className:"flex gap-2",children:[f.jsx("input",{type:"file",ref:$,onChange:H,accept:"image/*",className:"hidden"}),f.jsxs("button",{onClick:()=>$.current?.click(),disabled:ee,className:"flex-1 flex items-center justify-center gap-2 py-2.5 rounded-lg border border-dashed border-[#d4d4d4] dark:border-[#333333] hover:border-black dark:hover:border-[#555555] bg-[#fafafa] dark:bg-[#0f0f0f] hover:bg-[#f5f5f5] dark:hover:bg-[#141414] text-xs text-[#555555] dark:text-[#cccccc] hover:text-black dark:hover:text-white transition-all",children:[f.jsx(Op,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:ee?"正在上传...":"上传配图素材"})]}),f.jsx("button",{onClick:()=>c({src:"https://images.unsplash.com/photo-1579783900882-c0d3dad7b119?w=800&auto=format&fit=crop&q=80",alt:"艺术插画",caption:"示例艺术配图",x:36,y:400,width:440,height:300,captionHeight:36,layoutPreset:"auto"}),className:"px-3 py-2.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] bg-[#fafafa] dark:bg-[#0f0f0f] hover:bg-[#f5f5f5] dark:hover:bg-[#141414] text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white transition-all",title:"插入在线示例图",children:f.jsx(Sp,{className:"w-3.5 h-3.5"})})]}),f.jsx("div",{className:"flex flex-col gap-2.5",children:s.length===0?f.jsx("div",{className:"text-center py-8 text-xs text-[#888888] dark:text-[#555555]",children:"暂无配图素材,点击上方按钮上传或插入"}):s.map((S,q)=>f.jsxs("div",{className:"bg-[#fafafa] dark:bg-[#0f0f0f] border border-[#eaeaea] dark:border-[#222222] rounded-lg p-2.5 flex flex-col gap-2",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsx("img",{src:S.src,alt:S.alt,className:"w-12 h-12 object-cover rounded bg-[#eeeeee] dark:bg-[#1a1a1a] border border-[#e5e5e5] dark:border-[#262626] shrink-0"}),f.jsxs("div",{className:"flex-1 min-w-0",children:[f.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[f.jsxs("span",{className:"text-[10px] px-1 rounded bg-[#eaeaea] dark:bg-[#262626] font-mono text-[#555555] dark:text-[#aaaaaa] font-semibold shrink-0",children:["#",q+1]}),f.jsx("span",{className:"text-xs font-medium text-[#171717] dark:text-white truncate max-w-[120px]",children:S.caption||S.alt||`配图 #${q+1}`}),f.jsxs("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border border-emerald-500/20 font-medium shrink-0",children:["第 ",S.pageIndex||1," 页"]})]}),f.jsxs("div",{className:"text-[10px] text-[#888888] dark:text-[#666666] font-mono mt-0.5",children:[S.width," × ",S.height,"px · X: ",S.x??0,", Y: ",S.y??0]})]}),f.jsxs("div",{className:"flex items-center gap-0.5",children:[f.jsx("button",{onClick:()=>m?.(S.id,"up"),disabled:q===0,className:"p-1 text-[#888888] hover:text-black dark:hover:text-white disabled:opacity-20 rounded hover:bg-[#eeeeee] dark:hover:bg-[#1f1f1f]",title:"上移顺序 (调整在同一页中的先后次序)",children:f.jsx(cp,{className:"w-3.5 h-3.5"})}),f.jsx("button",{onClick:()=>m?.(S.id,"down"),disabled:q===s.length-1,className:"p-1 text-[#888888] hover:text-black dark:hover:text-white disabled:opacity-20 rounded hover:bg-[#eeeeee] dark:hover:bg-[#1f1f1f]",title:"下移顺序 (调整在同一页中的先后次序)",children:f.jsx(up,{className:"w-3.5 h-3.5"})}),f.jsx("button",{onClick:()=>N(S.id),className:"p-1 text-[#888888] hover:text-red-500 rounded hover:bg-[#eeeeee] dark:hover:bg-[#1f1f1f]",title:"删除该图",children:f.jsx(Eh,{className:"w-3.5 h-3.5"})})]})]}),f.jsxs("div",{className:"flex bg-[#eeeeee] dark:bg-[#1a1a1a] p-0.5 rounded text-[11px] font-medium pt-1 border-t border-[#eeeeee] dark:border-[#1a1a1a]",children:[f.jsx("button",{onClick:()=>v(S.id,{isAbsolute:!1}),className:`flex-1 py-1 rounded transition-all text-center ${S.isAbsolute?"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white":"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold"}`,children:"绕排避让 (Flow)"}),f.jsx("button",{onClick:()=>v(S.id,{isAbsolute:!0,layoutPreset:"custom",zIndex:S.zIndex??15,rotate:S.rotate??0,opacity:S.opacity??1}),className:`flex-1 py-1 rounded transition-all text-center ${S.isAbsolute?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:"自由图层 (Absolute)"})]}),f.jsxs("div",{className:"flex flex-col gap-2 text-[11px]",children:[f.jsxs("label",{className:"flex items-center gap-2",children:[f.jsx("input",{type:"checkbox",checked:S.templateAssetKey!==void 0,onChange:_=>v(S.id,{templateAssetKey:_.target.checked?`asset_${S.id.replace(/[^a-zA-Z0-9_-]/g,"_")}`:void 0,repeatEveryPage:!1})}),"固定模板素材"]}),S.templateAssetKey!==void 0&&f.jsxs(f.Fragment,{children:[f.jsxs("label",{className:"flex flex-col gap-1",children:["素材标识",f.jsx("input",{"aria-label":"素材标识",value:S.templateAssetKey,onChange:_=>v(S.id,{templateAssetKey:_.target.value}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1"})]}),s.some(_=>_.id!==S.id&&_.templateAssetKey===S.templateAssetKey)&&f.jsx("span",{role:"alert",className:"text-red-600",children:"素材标识不能重复"}),f.jsxs("label",{className:"flex items-center gap-2",children:[f.jsx("input",{type:"checkbox",disabled:!S.isAbsolute,checked:!!(S.isAbsolute&&S.repeatEveryPage),onChange:_=>v(S.id,{repeatEveryPage:_.target.checked})}),"每页重复"]}),!S.isAbsolute&&f.jsx("span",{className:"text-[#888888]",children:"每页重复仅支持自由图层,避免阻塞文字排版。"}),f.jsx("span",{className:"text-[#888888]",children:"默认保留此图,仅按素材标识明确替换。"})]}),S.isAbsolute&&f.jsxs("label",{className:"flex items-center gap-2",children:[f.jsx("input",{type:"checkbox",checked:g.includes(S.id),onChange:_=>d(S.id,_.target.checked)}),"设为整页背景"]}),f.jsx("button",{type:"button",onClick:()=>x(S.id),title:"恢复上传或应用模板时的尺寸、位置和图层设置",className:"rounded border border-[#d4d4d4] dark:border-[#333333] px-2 py-1.5 hover:bg-[#eeeeee] dark:hover:bg-[#222222]",children:"重置布局"})]}),S.isAbsolute?f.jsxs(f.Fragment,{children:[f.jsxs("div",{className:"text-[10px] text-blue-600 dark:text-blue-400 bg-blue-500/10 p-1.5 rounded flex items-center gap-1 font-medium",children:[f.jsx(So,{className:"w-3 h-3 shrink-0"}),f.jsx("span",{children:"自由定位图层:脱离文本流,不触发障碍物绕排"})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"所属页面"}),f.jsx("select",{value:S.pageIndex||1,onChange:_=>v(S.id,{pageIndex:parseInt(_.target.value,10)||1}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] focus:outline-none",children:Array.from({length:Math.max(y,2)},(_,te)=>te+1).map(_=>f.jsxs("option",{value:_,children:["第 ",_," 页 ",_===1?"(首页/封面)":""]},_))})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] mb-1",children:[f.jsx("span",{children:"层级 (Z-Index)"}),f.jsx("span",{className:"font-mono text-black dark:text-white font-semibold",children:S.zIndex??15})]}),f.jsx("div",{className:"flex gap-1",children:[{label:"底",val:0,title:"底层背景"},{label:"文字",val:10,title:"正文同层"},{label:"顶",val:20,title:"置顶贴纸"}].map(_=>f.jsx("button",{onClick:()=>v(S.id,{zIndex:_.val}),title:_.title,className:`flex-1 py-0.5 text-[10px] rounded border ${(S.zIndex??15)===_.val?"bg-black dark:bg-white text-white dark:text-black border-transparent font-bold":"border-[#d4d4d4] dark:border-[#262626] text-[#666666] dark:text-[#888888]"}`,children:_.label},_.val))})]})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] mb-1",children:[f.jsxs("span",{className:"flex items-center gap-0.5",children:[f.jsx(Ep,{className:"w-2.5 h-2.5"})," 旋转角度"]}),f.jsxs("span",{className:"font-mono text-black dark:text-white font-semibold",children:[S.rotate??0,"°"]})]}),f.jsx("input",{type:"range",min:"-45",max:"45",step:"1",value:S.rotate??0,onChange:_=>v(S.id,{rotate:parseInt(_.target.value,10)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded cursor-pointer mt-1"})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] mb-1",children:[f.jsx("span",{children:"不透明度"}),f.jsxs("span",{className:"font-mono text-black dark:text-white font-semibold",children:[Math.round((S.opacity??1)*100),"%"]})]}),f.jsx("input",{type:"range",min:"0.1",max:"1",step:"0.05",value:S.opacity??1,onChange:_=>v(S.id,{opacity:parseFloat(_.target.value)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded cursor-pointer mt-1"})]})]}),f.jsxs("div",{className:"text-[11px]",children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"圆角半径 (px)"}),f.jsx("input",{type:"number",min:"0",step:"4",value:S.borderRadius??12,onChange:_=>v(S.id,{borderRadius:parseInt(_.target.value,10)||0}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"横向 X"}),f.jsx("input",{type:"number",step:"10",value:S.x??0,onChange:_=>v(S.id,{x:parseInt(_.target.value,10)||0}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"纵向 Y"}),f.jsx("input",{type:"number",step:"10",value:S.y??0,onChange:_=>v(S.id,{y:parseInt(_.target.value,10)||0}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"宽度 (W)"}),f.jsx("input",{type:"number",step:"10",value:S.width??420,onChange:_=>v(S.id,{width:Math.max(20,parseInt(_.target.value,10)||20)}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"高度 (H)"}),f.jsx("input",{type:"number",step:"10",value:S.height??280,onChange:_=>v(S.id,{height:Math.max(20,parseInt(_.target.value,10)||20)}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]})]})]}):f.jsxs(f.Fragment,{children:[f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"排版预设"}),f.jsxs("select",{value:S.layoutPreset||"auto",onChange:_=>v(S.id,{layoutPreset:_.target.value}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] focus:outline-none",children:[f.jsx("option",{value:"auto",children:"自适应 (Auto)"}),f.jsx("option",{value:"mid-left",children:"居左浮动 (Left)"}),f.jsx("option",{value:"mid-right",children:"居右浮动 (Right)"}),f.jsx("option",{value:"center",children:"居中横幅 (Center)"}),f.jsx("option",{value:"staggered",children:"交错排版 (Staggered)"}),f.jsx("option",{value:"corner-soft",children:"角落软着陆 (Corner)"}),f.jsx("option",{value:"fill",children:"底部填满 (Fill)"}),f.jsx("option",{value:"custom",children:"自定义坐标 (Custom)"})]})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"所属页面"}),f.jsx("select",{value:S.pageIndex||1,onChange:_=>v(S.id,{pageIndex:parseInt(_.target.value,10)||1}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] focus:outline-none",children:Array.from({length:Math.max(y,2)},(_,te)=>te+1).map(_=>f.jsxs("option",{value:_,children:["第 ",_," 页 ",_===1?"(首页/封面)":""]},_))})]})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"宽度 (W)"}),f.jsx("input",{type:"number",min:"50",step:"10",value:S.width??420,onChange:_=>v(S.id,{width:Math.max(50,parseInt(_.target.value,10)||50)}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"高度 (H)"}),f.jsx("input",{type:"number",min:"50",step:"10",value:S.height??280,onChange:_=>v(S.id,{height:Math.max(50,parseInt(_.target.value,10)||50)}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"纵向位置 Y"}),f.jsx("input",{type:"number",step:"20",value:S.y??300,onChange:_=>v(S.id,{y:parseInt(_.target.value,10)||0,layoutPreset:"custom"}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"横向坐标 X"}),f.jsx("input",{type:"number",step:"10",value:S.x??16,onChange:_=>v(S.id,{x:parseInt(_.target.value,10)||0,layoutPreset:"custom"}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] text-[11px] block mb-1",children:"图片说明 (Caption)"}),f.jsx("input",{type:"text",placeholder:"下方说明文字...",value:S.caption||"",onChange:_=>v(S.id,{caption:_.target.value}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white text-[11px] focus:outline-none"})]})]})]},S.id))})]}),M==="highlights"&&f.jsxs("div",{className:"flex-1 flex flex-col p-3 gap-3 overflow-y-auto",children:[f.jsx("div",{className:"text-xs text-[#666666] dark:text-[#888888] leading-relaxed",children:"在正文中出现的高亮词,将被算法自动匹配并渲染为品牌强调色。"}),f.jsxs("div",{className:"flex gap-2",children:[f.jsx("input",{type:"text",placeholder:"新增高亮关键词...",value:B,onChange:S=>L(S.target.value),onKeyDown:S=>S.key==="Enter"&&V(),className:"flex-1 bg-white dark:bg-[#0d0d0d] border border-[#d4d4d4] dark:border-[#222222] rounded-lg px-2.5 py-1.5 text-xs text-black dark:text-white placeholder-[#888888] dark:placeholder-[#555555] focus:outline-none focus:border-black dark:focus:border-[#444444]"}),f.jsx("button",{onClick:V,className:"px-3 py-1.5 bg-black dark:bg-[#1f1f1f] hover:bg-[#262626] text-white rounded-lg text-xs font-medium",children:"添加"})]}),f.jsx("div",{className:"flex flex-wrap gap-1.5 mt-1",children:p.map(S=>f.jsxs("span",{className:"flex items-center gap-1 px-2.5 py-1 rounded-md bg-[#f0fdf4] dark:bg-[#161616] border border-[#bbf7d0] dark:border-[#262626] text-xs text-emerald-700 dark:text-emerald-400 font-medium",children:[f.jsx(So,{className:"w-3 h-3"}),f.jsx("span",{children:S}),f.jsx("button",{onClick:()=>G(S),className:"hover:text-red-500 ml-1",children:"×"})]},S))})]})]})},Vp=[{id:"wechat-cover-2.35",label:"微信封面",ratioTag:"2.35:1"},{id:"longform-3-4",label:"通用长图文",ratioTag:"3:4"},{id:"wide-16-9",label:"通用宽屏",ratioTag:"16:9"},{id:"square-1-1",label:"通用正方形",ratioTag:"1:1"}],Zp=({currentRatio:u,onSelectRatio:r,zoom:s,onZoomChange:c,onAutoFit:d,isAutoFit:x,onOpenTemplates:g,isTemplateDrawerOpen:v,templateName:N,onSaveTemplate:m,onOpenAuth:y,onExport:p,isExporting:b,isAuthed:w,pageCount:M,themeMode:Q,onToggleThemeMode:B})=>f.jsxs("header",{className:"h-14 border-b border-[#eaeaea] dark:border-[#222222] bg-white/80 dark:bg-[#000000]/80 backdrop-blur-md px-4 flex items-center justify-between select-none z-30 shrink-0 transition-colors",children:[f.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[f.jsxs("div",{className:"flex items-center gap-2 font-semibold text-[#171717] dark:text-white tracking-tight text-sm",children:[f.jsx("span",{className:"flex items-center justify-center w-6 h-6 rounded bg-black dark:bg-white text-white dark:text-black font-black text-xs shadow-sm",children:"▲"}),f.jsx("span",{className:"hidden 2xl:inline",children:"Typeset Studio"})]}),f.jsx("span",{className:"text-xs text-[#888888] dark:text-[#555555] font-mono hidden 2xl:inline",children:"v0.2.6"}),f.jsxs("div",{title:N||"未命名模板",className:"flex min-w-0 items-center gap-1.5 px-2 py-0.5 rounded-full bg-[#f5f5f5] dark:bg-[#111111] border border-[#e5e5e5] dark:border-[#222222] text-[11px] text-emerald-600 dark:text-[#00e676]",children:[f.jsx("span",{className:"w-1.5 h-1.5 shrink-0 rounded-full bg-emerald-500 dark:bg-[#00e676]"}),f.jsx("span",{"aria-live":"polite",className:"max-w-40 truncate",children:N||"未命名模板"})]})]}),f.jsx("div",{className:"flex items-center bg-[#f5f5f5] dark:bg-[#0a0a0a] border border-[#eaeaea] dark:border-[#222222] rounded-lg p-0.5 shadow-inner",children:Vp.map(L=>{const $=u===L.id;return f.jsxs("button",{onClick:()=>r(L.id),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium transition-all ${$?"bg-white dark:bg-[#1f1f1f] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-[#171717] dark:hover:text-[#cccccc] hover:bg-[#eaeaea] dark:hover:bg-[#141414]"}`,children:[f.jsx("span",{className:"hidden xl:inline",children:L.label}),f.jsx("span",{className:`text-[10px] font-mono px-1 py-0.2 rounded ${$?"bg-[#eaeaea] dark:bg-[#333333] text-black dark:text-white font-semibold":"bg-[#e5e5e5] dark:bg-[#181818] text-[#777777] dark:text-[#666666]"}`,children:L.ratioTag})]},L.id)})}),f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsxs("div",{className:"flex items-center bg-[#f5f5f5] dark:bg-[#0a0a0a] border border-[#eaeaea] dark:border-[#222222] rounded-lg p-0.5 text-xs text-[#666666] dark:text-[#888888]",children:[f.jsx("button",{onClick:()=>c(Math.max(.2,Number((s-.05).toFixed(2)))),className:"p-1 hover:text-black dark:hover:text-white rounded hover:bg-[#e8e8e8] dark:hover:bg-[#1f1f1f]",title:"缩小",children:f.jsx(Bp,{className:"w-3.5 h-3.5"})}),f.jsxs("span",{onDoubleClick:d,className:"w-11 text-center font-mono text-[11px] text-[#333333] dark:text-[#cccccc] cursor-pointer hover:underline select-none",title:"双击恢复自适应",children:[Math.round(s*100),"%"]}),f.jsx("button",{onClick:()=>c(Math.min(1.5,Number((s+.05).toFixed(2)))),className:"p-1 hover:text-black dark:hover:text-white rounded hover:bg-[#e8e8e8] dark:hover:bg-[#1f1f1f]",title:"放大",children:f.jsx(kh,{className:"w-3.5 h-3.5"})}),d&&f.jsxs(f.Fragment,{children:[f.jsx("div",{className:"w-[1px] h-3 bg-[#e0e0e0] dark:bg-[#262626] mx-0.5"}),f.jsxs("button",{onClick:d,className:`flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] transition-all ${x?"bg-white dark:bg-[#1f1f1f] text-black dark:text-white shadow-xs font-semibold":"hover:text-black dark:hover:text-white hover:bg-[#e8e8e8] dark:hover:bg-[#1f1f1f]"}`,title:M>1?"缩放至视口内完整排列多张图片(瀑布流平铺)":"自适应画布大小",children:[f.jsx(vp,{className:"w-3 h-3"}),f.jsx("span",{children:M>1?"多图平铺":"自适应"})]})]})]}),f.jsx("button",{onClick:B,className:"p-2 rounded-lg border border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] hover:bg-[#f5f5f5] dark:hover:bg-[#161616] text-[#444444] dark:text-[#cccccc] transition-all btn-vercel",title:Q==="light"?"切换至深色模式":"切换至浅色模式",children:Q==="light"?f.jsx(yp,{className:"w-3.5 h-3.5 text-[#555555]"}):f.jsx(kp,{className:"w-3.5 h-3.5 text-amber-400"})}),f.jsxs("button",{onClick:g,"aria-expanded":v,className:"flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] hover:bg-[#f5f5f5] dark:hover:bg-[#161616] text-xs text-[#333333] dark:text-[#cccccc] hover:text-black dark:hover:text-white transition-all btn-vercel",children:[f.jsx(dp,{className:"w-3.5 h-3.5 text-[#777777] dark:text-[#888888]"}),f.jsx("span",{children:"模板库"})]}),f.jsxs("button",{onClick:m,className:"flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] hover:bg-[#f5f5f5] dark:hover:bg-[#161616] text-xs text-[#333333] dark:text-[#cccccc] transition-all btn-vercel",children:[f.jsx(dh,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"保存模板"})]}),f.jsxs("button",{onClick:p,disabled:b,className:"flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-black text-white hover:bg-[#262626] dark:bg-white dark:text-black dark:hover:bg-[#eaeaea] text-xs font-semibold transition-all btn-vercel shadow-sm disabled:opacity-50",children:[b?f.jsx(ch,{className:"w-3.5 h-3.5 animate-spin"}):f.jsx(op,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:b?"导出中...":"导出图片"}),M>1&&f.jsxs("span",{className:"text-[10px] bg-white/20 dark:bg-black text-white px-1.5 py-0.2 rounded font-mono",children:[M,"P"]})]}),f.jsx("button",{onClick:y,className:`p-1.5 rounded-lg border transition-all btn-vercel ${w?"border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] text-[#777777] dark:text-[#888888] hover:text-black dark:hover:text-white hover:bg-[#f5f5f5] dark:hover:bg-[#161616]":"border-amber-500/50 bg-amber-500/10 text-amber-600 dark:text-amber-400"}`,title:w?"超管密钥已就绪":"配置超管密钥",children:f.jsx(eh,{className:"w-3.5 h-3.5"})})]})]});function Kp(){const[u,r]=fe.useState([]),[s,c]=fe.useState(!1),d=fe.useCallback(async(x=!1)=>{try{c(!0);const g=await fetch(`/api/fonts${x?"?refresh=1":""}`);if(!g.ok)return;const v=await g.json();if(!v.ok||!Array.isArray(v.fonts))return;r(v.fonts);let N=!1;if(typeof window<"u"&&"FontFace"in window&&document.fonts)for(const m of v.fonts)try{let y=!1;const p=[];if(document.fonts.forEach(b=>{(b.family===m.family||b.family===`"${m.family}"`)&&(y=!0,p.push(b))}),x&&(p.forEach(b=>document.fonts.delete(b)),y=!1),!y){const w=await new FontFace(m.family,`url(${m.url}${x?`?v=${Date.now()}`:""})`).load();document.fonts.add(w),N=!0}}catch(y){console.warn(`[useLocalFonts] Failed to load web font ${m.family}:`,y)}N&&window.dispatchEvent(new Event("typeset-fonts-loaded"))}catch(g){console.warn("[useLocalFonts] Failed to fetch local fonts:",g)}finally{c(!1)}},[]);return fe.useEffect(()=>{d()},[d]),{fonts:u,loading:s,refreshFonts:()=>d(!0)}}const mo="w-full rounded border border-[#dfdfdf] dark:border-[#333333] bg-white dark:bg-[#141414] px-2 py-1 text-[11px]";function Jp({config:u,onChange:r}){const s=u.canvasStyle||{},c=s.fill||u.coverTheme?.background.fill||{type:"solid",color:u.theme.bgColor},d=s.pattern||u.coverTheme?.decoration||_p,x=s.border||Rp,g=b=>r({...s,fill:b}),v=b=>r({...s,pattern:{...d,...b}}),N=b=>r({...s,border:{...x,...b}}),m=(b,w,M)=>f.jsxs("label",{className:"flex items-center justify-between gap-2",children:[f.jsx("span",{children:b}),f.jsxs("span",{className:"flex items-center gap-1.5 font-mono",children:[f.jsx("span",{children:w}),f.jsx("input",{"aria-label":b,type:"color",value:w,onChange:Q=>M(Q.target.value),className:"h-6 w-7 cursor-pointer bg-transparent"})]})]}),y=(b,w,M,Q,B,L=1)=>f.jsxs("label",{className:"flex flex-col gap-1",children:[f.jsxs("span",{className:"flex justify-between",children:[f.jsx("span",{children:b}),f.jsx("span",{className:"font-mono",children:L<1?`${Math.round(w*100)}%`:w})]}),f.jsx("input",{"aria-label":b,type:"range",min:M,max:Q,step:L,value:w,onChange:$=>B(Number($.target.value)),className:"w-full accent-emerald-600"})]}),p=b=>{const w=c.type==="solid"?c.color:c.stops[0].color,M=c.type==="solid"?[{color:w,offset:0},{color:u.theme.accentColor,offset:100}]:c.stops;g(b==="solid"?{type:b,color:w}:b==="linear"?{type:b,angle:90,stops:M}:{type:b,position:{x:50,y:30},stops:M})};return f.jsxs("section",{className:"border-b border-[#f0f0f0] dark:border-[#1c1c1c] p-3.5 text-xs",children:[f.jsx("div",{className:"mb-3 font-semibold text-[#171717] dark:text-white",children:"背景、花纹与边框"}),f.jsxs("div",{className:"flex flex-col gap-3 text-[11px] text-[#666666] dark:text-[#aaaaaa]",children:[f.jsxs("label",{className:"flex flex-col gap-1",children:["背景类型",f.jsxs("select",{className:mo,value:c.type,onChange:b=>p(b.target.value),children:[f.jsx("option",{value:"solid",children:"纯色"}),f.jsx("option",{value:"linear",children:"线性渐变"}),f.jsx("option",{value:"radial",children:"径向渐变"})]})]}),c.type==="solid"?m("背景颜色",c.color,b=>g({type:"solid",color:b})):f.jsxs(f.Fragment,{children:[f.jsxs("div",{className:"flex flex-col gap-2 rounded border border-[#eaeaea] dark:border-[#333333] p-2",children:[c.stops.map((b,w)=>f.jsxs("div",{className:"flex flex-col gap-1.5",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsxs("label",{className:"flex flex-1 items-center gap-1.5",children:[f.jsx("input",{"aria-label":`渐变颜色 ${w+1}`,type:"color",value:b.color,onChange:M=>g({...c,stops:c.stops.map((Q,B)=>B===w?{...Q,color:M.target.value}:Q)}),className:"h-6 w-7 bg-transparent"}),f.jsx("span",{className:"font-mono",children:b.color})]}),f.jsx("button",{type:"button",disabled:c.stops.length<=2,onClick:()=>g({...c,stops:c.stops.filter((M,Q)=>Q!==w)}),className:"disabled:opacity-30","aria-label":`删除渐变颜色 ${w+1}`,children:"移除"})]}),y(`节点 ${w+1} 位置`,b.offset,0,100,M=>g({...c,stops:c.stops.map((Q,B)=>B===w?{...Q,offset:M}:Q)}))]},w)),f.jsx("button",{type:"button",disabled:c.stops.length>=8,onClick:()=>g({...c,stops:[...c.stops,{color:u.theme.accentColor,offset:50}]}),className:"rounded border border-[#dfdfdf] dark:border-[#333333] py-1 disabled:opacity-30",children:"添加颜色节点"})]}),c.type==="linear"?y("渐变角度",c.angle,0,360,b=>g({...c,angle:b})):f.jsxs(f.Fragment,{children:[y("渐变中心 X",c.position.x,0,100,b=>g({...c,position:{...c.position,x:b}})),y("渐变中心 Y",c.position.y,0,100,b=>g({...c,position:{...c.position,y:b}}))]})]}),f.jsxs("label",{className:"flex flex-col gap-1",children:["几何花纹",f.jsx("select",{className:mo,value:d.pattern,onChange:b=>v({pattern:b.target.value}),children:Object.entries(Fh).map(([b,w])=>f.jsx("option",{value:b,children:w},b))})]}),d.pattern!=="none"&&f.jsxs(f.Fragment,{children:[m("花纹颜色",d.color,b=>v({color:b})),y("花纹透明度",d.opacity,0,1,b=>v({opacity:b}),.01),y("花纹间距",d.size,16,240,b=>v({size:b}))]}),f.jsxs("label",{className:"flex flex-col gap-1",children:["边框样式",f.jsx("select",{className:mo,value:x.style,onChange:b=>N({style:b.target.value}),children:Object.entries(jh).map(([b,w])=>f.jsx("option",{value:b,children:w},b))})]}),x.style!=="none"&&f.jsxs(f.Fragment,{children:[m("边框颜色",x.color,b=>N({color:b})),x.style==="gradient"&&m("边框渐变终色",x.endColor,b=>N({endColor:b})),y("边框粗细",x.width,1,24,b=>N({width:b})),y("边框内缩",x.inset,0,200,b=>N({inset:b})),x.style!=="corners"&&y("边框圆角",x.radius,0,200,b=>N({radius:b})),y("边框透明度",x.opacity,0,1,b=>N({opacity:b}),.01)]}),f.jsx("p",{className:"leading-relaxed text-[#888888]",children:"配置随模板保存,作用于每页。背景图会覆盖底色与花纹;边框绘制在最上层。"})]})]})}const yx=[{label:"苹方 / 极简黑体 (默认清爽)",value:"PingFang SC"},{label:"思源黑体 (现代极简·粗黑)",value:"Noto Sans SC"},{label:"典雅宋体 (经典报刊·书卷)",value:"Songti SC"},{label:"思源宋体 (高阶报刊·典雅)",value:"Noto Serif SC"},{label:"人文楷体 (温润随笔·手写)",value:"Kaiti SC"},{label:"柔和圆体 (亲和灵动·现代)",value:"Yuanti SC"},{label:"Inter / 国际西文无衬线",value:"Inter"},{label:"Georgia / 文艺西文衬线",value:"Georgia"}],Ip=({config:u,onUpdateAlgorithm:r,onUpdateTheme:s,onUpdateTypography:c,onUpdateSafeArea:d,onUpdateBranding:x,onUpdateChrome:g,onUpdateCanvasStyle:v})=>{const{algorithm:N,theme:m,typography:y}=u,{fonts:p,loading:b,refreshFonts:w}=Kp();return f.jsxs("aside",{className:"w-80 border-l border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] flex flex-col shrink-0 select-none overflow-y-auto transition-colors",children:[f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(rp,{className:"w-3.5 h-3.5 text-blue-500 dark:text-blue-400"}),f.jsx("span",{children:"文字对齐与空间居中"})]}),f.jsxs("div",{className:"flex flex-col gap-3 text-xs",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] text-[11px] block mb-1.5 font-medium",children:"垂直排版对齐 (封面必备)"}),f.jsx("div",{className:"grid grid-cols-3 gap-1 bg-[#f5f5f5] dark:bg-[#141414] p-1 rounded-lg border border-[#e5e5e5] dark:border-[#262626]",children:[{id:"top",label:"顶端对齐"},{id:"center",label:"垂直居中"},{id:"bottom",label:"底端对齐"}].map(M=>f.jsx("button",{onClick:()=>r({verticalAlign:M.id}),className:`py-1 text-[11px] rounded transition-all font-medium ${(N.verticalAlign||"top")===M.id?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:M.label},M.id))})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] text-[11px] block mb-1.5 font-medium",children:"水平排版对齐"}),f.jsxs("div",{className:"grid grid-cols-3 gap-1 bg-[#f5f5f5] dark:bg-[#141414] p-1 rounded-lg border border-[#e5e5e5] dark:border-[#262626]",children:[f.jsxs("button",{onClick:()=>r({textAlign:"left"}),className:`py-1 flex items-center justify-center gap-1 text-[11px] rounded transition-all font-medium ${(N.textAlign||"left")==="left"?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:[f.jsx(jp,{className:"w-3 h-3"}),f.jsx("span",{children:"居左"})]}),f.jsxs("button",{onClick:()=>r({textAlign:"center"}),className:`py-1 flex items-center justify-center gap-1 text-[11px] rounded transition-all font-medium ${N.textAlign==="center"?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:[f.jsx(Fp,{className:"w-3 h-3"}),f.jsx("span",{children:"居中"})]}),f.jsxs("button",{onClick:()=>r({textAlign:"right"}),className:`py-1 flex items-center justify-center gap-1 text-[11px] rounded transition-all font-medium ${N.textAlign==="right"?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:[f.jsx(Tp,{className:"w-3 h-3"}),f.jsx("span",{children:"居右"})]})]})]})]})]}),f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center justify-between text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsx(Dp,{className:"w-3.5 h-3.5 text-indigo-500 dark:text-indigo-400"}),f.jsx("span",{children:"字体与排版字阶"})]}),f.jsx("button",{onClick:()=>w(),disabled:b,title:"重新扫描 public/fonts 目录",className:"p-1 text-[#888888] hover:text-black dark:hover:text-white rounded hover:bg-[#eaeaea] dark:hover:bg-[#222222] transition-colors",children:f.jsx(ch,{className:`w-3 h-3 ${b?"animate-spin text-blue-500":""}`})})]}),f.jsxs("div",{className:"flex flex-col gap-3 text-xs",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] text-[11px] block mb-1",children:"标题字体 (Heading Font)"}),f.jsxs("select",{value:y.headingFont,onChange:M=>c({headingFont:M.target.value}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded-md px-2 py-1.5 text-black dark:text-white text-xs focus:outline-none",children:[p.length>0&&f.jsx("optgroup",{label:"✨ 项目本地字体 (public/fonts)",children:p.map(M=>f.jsx("option",{value:M.family,children:M.label},`head-local-${M.family}`))}),f.jsx("optgroup",{label:"🌐 系统 / 云端预设",children:yx.map(M=>f.jsx("option",{value:M.value,children:M.label},`head-preset-${M.value}`))})]})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] text-[11px] block mb-1",children:"正文字体 (Body Font)"}),f.jsxs("select",{value:y.bodyFont,onChange:M=>c({bodyFont:M.target.value}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded-md px-2 py-1.5 text-black dark:text-white text-xs focus:outline-none",children:[p.length>0&&f.jsx("optgroup",{label:"✨ 项目本地字体 (public/fonts)",children:p.map(M=>f.jsx("option",{value:M.family,children:M.label},`body-local-${M.family}`))}),f.jsx("optgroup",{label:"🌐 系统 / 云端预设",children:yx.map(M=>f.jsx("option",{value:M.value,children:M.label},`body-preset-${M.value}`))})]})]}),p.length===0?f.jsx("div",{className:"text-[10px] text-[#888888] dark:text-[#666666] flex items-center justify-between pt-1 border-t border-[#f5f5f5] dark:border-[#1a1a1a]",children:f.jsxs("span",{children:["💡 将 .ttf / .otf 放入 ",f.jsx("code",{children:"public/fonts/"})," 即可识别"]})}):f.jsx("div",{className:"text-[10px] text-emerald-600 dark:text-emerald-400 flex items-center justify-between pt-1 border-t border-[#f5f5f5] dark:border-[#1a1a1a]",children:f.jsxs("span",{children:["✨ 已加载 ",p.length," 个项目本地字体"]})})]})]}),f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(wp,{className:"w-3.5 h-3.5 text-blue-500 dark:text-blue-400"}),f.jsx("span",{children:"字号与比例参数"})]}),f.jsxs("div",{className:"flex flex-col gap-3.5 text-xs",children:[f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] dark:text-[#888888] mb-1 font-mono text-[11px]",children:[f.jsx("span",{children:"基准字号 (Base Size)"}),f.jsxs("span",{className:"text-[#171717] dark:text-white font-semibold",children:[N.baseFontSize,"px"]})]}),f.jsx("input",{type:"range",min:"24",max:"96",step:"1",value:N.baseFontSize,onChange:M=>r({baseFontSize:parseInt(M.target.value,10)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded-lg cursor-pointer"})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] dark:text-[#888888] mb-1 font-mono text-[11px]",children:[f.jsx("span",{children:"比例字阶系数 (大标题倍率)"}),f.jsxs("span",{className:"text-[#171717] dark:text-white font-semibold",children:[N.scaleRatio.toFixed(2),"x"]})]}),f.jsx("input",{type:"range",min:"1.15",max:"1.6",step:"0.01",value:N.scaleRatio,onChange:M=>r({scaleRatio:parseFloat(M.target.value)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded-lg cursor-pointer"})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] dark:text-[#888888] mb-1 font-mono text-[11px]",children:[f.jsx("span",{children:"行高舒展倍率"}),f.jsx("span",{className:"text-[#171717] dark:text-white font-semibold",children:N.lineHeightMultiplier.toFixed(2)})]}),f.jsx("input",{type:"range",min:"1.2",max:"1.8",step:"0.02",value:N.lineHeightMultiplier,onChange:M=>r({lineHeightMultiplier:parseFloat(M.target.value)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded-lg cursor-pointer"})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] dark:text-[#888888] mb-1 font-mono text-[11px]",children:[f.jsx("span",{children:"配图避让间隙 (Gap)"}),f.jsxs("span",{className:"text-[#171717] dark:text-white font-semibold",children:[N.obstacleGap,"px"]})]}),f.jsx("input",{type:"range",min:"12",max:"48",step:"2",value:N.obstacleGap,onChange:M=>r({obstacleGap:parseInt(M.target.value,10)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded-lg cursor-pointer"})]})]})]}),f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(Mp,{className:"w-3.5 h-3.5 text-emerald-600 dark:text-emerald-400"}),f.jsx("span",{children:"版心安全边距"})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px] font-mono",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#777777] dark:text-[#666666] block mb-1",children:"上边距 (Top)"}),f.jsx("input",{type:"number",value:N.safeArea.top,onChange:M=>d({top:parseInt(M.target.value,10)||0}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#777777] dark:text-[#666666] block mb-1",children:"下边距 (Bottom)"}),f.jsx("input",{type:"number",value:N.safeArea.bottom,onChange:M=>d({bottom:parseInt(M.target.value,10)||0}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#777777] dark:text-[#666666] block mb-1",children:"左边距 (Left)"}),f.jsx("input",{type:"number",value:N.safeArea.left,onChange:M=>d({left:parseInt(M.target.value,10)||0}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#777777] dark:text-[#666666] block mb-1",children:"右边距 (Right)"}),f.jsx("input",{type:"number",value:N.safeArea.right,onChange:M=>d({right:parseInt(M.target.value,10)||0}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white"})]})]})]}),f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(Np,{className:"w-3.5 h-3.5 text-purple-600 dark:text-purple-400"}),f.jsx("span",{children:"视觉色彩主题"})]}),f.jsxs("div",{className:"flex flex-col gap-2.5 text-xs",children:[f.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[f.jsx("button",{onClick:()=>s({bgColor:"#ffffff",textColor:"#171717",headingColor:"#171717",accentColor:"#059669",quoteColor:"#525252",cardBg:"#f5f5f5"}),className:"w-6 h-6 rounded-full bg-[#ffffff] border-2 border-emerald-500 shadow-sm hover:scale-105 transition-all",title:"素白雅致 (推荐)"}),f.jsx("button",{onClick:()=>s({bgColor:"#f9fcfa",textColor:"#22201d",headingColor:"#0f2e22",accentColor:"#1d4f39",quoteColor:"#474038",cardBg:"#ffffff"}),className:"w-6 h-6 rounded-full bg-[#f9fcfa] border border-[#ccc] shadow-sm hover:scale-105 transition-all",title:"纸白浅草"}),f.jsx("button",{onClick:()=>s({bgColor:"#0a0a0a",textColor:"#ededed",headingColor:"#ffffff",accentColor:"#00e676",quoteColor:"#a0a0a0",cardBg:"#121212"}),className:"w-6 h-6 rounded-full bg-[#0a0a0a] border border-[#444] shadow-sm hover:scale-105 transition-all",title:"深邃暗夜"}),f.jsx("button",{onClick:()=>s({bgColor:"#09090b",textColor:"#fafafa",headingColor:"#ffffff",accentColor:"#3b82f6",quoteColor:"#a1a1aa",cardBg:"#18181b"}),className:"w-6 h-6 rounded-full bg-[#09090b] border border-blue-500 shadow-sm hover:scale-105 transition-all",title:"数码蓝暗黑"})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] font-medium",children:"标题颜色 (Heading)"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx("input",{type:"color",value:m.headingColor||m.textColor,onChange:M=>s({headingColor:M.target.value}),className:"w-6 h-6 rounded cursor-pointer bg-transparent border-0"}),f.jsx("span",{className:"font-mono text-[11px] text-[#444444] dark:text-[#cccccc]",children:m.headingColor||m.textColor})]})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888]",children:"正文字色 (Text)"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx("input",{type:"color",value:m.textColor,onChange:M=>s({textColor:M.target.value}),className:"w-6 h-6 rounded cursor-pointer bg-transparent border-0"}),f.jsx("span",{className:"font-mono text-[11px] text-[#444444] dark:text-[#cccccc]",children:m.textColor})]})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888]",children:"重点强调色 (Accent)"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx("input",{type:"color",value:m.accentColor,onChange:M=>s({accentColor:M.target.value}),className:"w-6 h-6 rounded cursor-pointer bg-transparent border-0"}),f.jsx("span",{className:"font-mono text-[11px] text-[#444444] dark:text-[#cccccc]",children:m.accentColor})]})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888]",children:"背景底色 (Canvas)"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx("input",{type:"color",value:u.canvasStyle?.fill?.type==="solid"?u.canvasStyle.fill.color:m.bgColor,onChange:M=>s({bgColor:M.target.value}),className:"w-6 h-6 rounded cursor-pointer bg-transparent border-0"}),f.jsx("span",{className:"font-mono text-[11px] text-[#444444] dark:text-[#cccccc]",children:m.bgColor})]})]})]})]}),f.jsx(Jp,{config:u,onChange:v}),f.jsxs("div",{className:"p-3.5",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(sp,{className:"w-3.5 h-3.5 text-amber-500 dark:text-amber-400"}),f.jsx("span",{children:"页眉页脚与版式装饰 (Chrome)"})]}),f.jsxs("div",{className:"flex flex-col gap-3 text-xs",children:[f.jsxs("div",{className:"bg-[#f9f9f9] dark:bg-[#141414] p-2.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] flex flex-col gap-2",children:[f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"font-semibold text-[#333333] dark:text-[#cccccc] text-[11px]",children:"顶部栏 (Header)"}),f.jsxs("label",{className:"flex items-center gap-1.5 cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showHeader??!!u.watermarkText?.trim(),onChange:M=>g({showHeader:M.target.checked}),className:"rounded text-emerald-500 accent-emerald-500 cursor-pointer"}),f.jsx("span",{className:"text-[10px] text-[#666666] dark:text-[#888888]",children:"启用"})]})]}),(u.chrome?.showHeader??!!u.watermarkText?.trim())&&f.jsxs("div",{className:"flex flex-col gap-2 pl-2 border-l-2 border-[#e0e0e0] dark:border-[#2a2a2a] mt-1",children:[f.jsxs("div",{children:[f.jsxs("div",{className:"flex items-center justify-between mb-1",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"水印 / 品牌标识"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showWatermark??!0,onChange:M=>g({showWatermark:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]}),f.jsx("input",{type:"text",value:u.watermarkText,onChange:M=>x(u.footerText,M.target.value),placeholder:"作者水印/标识文本...",className:"w-full bg-white dark:bg-[#0a0a0a] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white text-[11px]"})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"页码角标 (P.01)"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showPageNumber??u.aspectRatio==="longform-3-4",onChange:M=>g({showPageNumber:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]})]})]}),f.jsxs("div",{className:"bg-[#f9f9f9] dark:bg-[#141414] p-2.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] flex flex-col gap-2",children:[f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"font-semibold text-[#333333] dark:text-[#cccccc] text-[11px]",children:"底部栏 (Footer)"}),f.jsxs("label",{className:"flex items-center gap-1.5 cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showFooter??!!u.footerText?.trim(),onChange:M=>g({showFooter:M.target.checked}),className:"rounded text-emerald-500 accent-emerald-500 cursor-pointer"}),f.jsx("span",{className:"text-[10px] text-[#666666] dark:text-[#888888]",children:"启用"})]})]}),(u.chrome?.showFooter??!!u.footerText?.trim())&&f.jsxs("div",{className:"flex flex-col gap-2 pl-2 border-l-2 border-[#e0e0e0] dark:border-[#2a2a2a] mt-1",children:[f.jsxs("div",{children:[f.jsxs("div",{className:"flex items-center justify-between mb-1",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"页脚署名 / 版权"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showFooterText??!0,onChange:M=>g({showFooterText:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]}),f.jsx("input",{type:"text",value:u.footerText,onChange:M=>x(M.target.value,u.watermarkText),placeholder:"页脚版权/署名...",className:"w-full bg-white dark:bg-[#0a0a0a] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white text-[11px]"})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"顶部分割细线"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showFooterDivider??!!u.footerText?.trim(),onChange:M=>g({showFooterDivider:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"算法填充率提示"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showFillRatio??!1,onChange:M=>g({showFillRatio:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]})]})]})]})]})]})},Wp=({isOpen:u,onClose:r,refreshKey:s,onApplyTemplate:c,adminKey:d})=>{const[x,g]=fe.useState([]),[v,N]=fe.useState({}),[m,y]=fe.useState("default"),[p,b]=fe.useState("all"),[w,M]=fe.useState(!1),[Q,B]=fe.useState(null),L=async(H=m)=>{try{const V=await fetch(`/api/templates/slots?account=${encodeURIComponent(H)}`,{headers:{"x-admin-key":d}}),G=await V.json();if(!V.ok||!G.ok)throw new Error(G.message||G.error||"获取槽位失败");G.ok&&G.slots&&N(G.slots)}catch(V){B(V instanceof Error?V.message:"模板请求失败")}},$=async(H,V)=>{try{const G=await fetch("/api/templates/slots",{method:"POST",headers:{"Content-Type":"application/json",...d?{"x-admin-key":d}:{}},body:JSON.stringify({slot:H,templateId:V,account:m})}),S=await G.json();if(!G.ok||!S.ok)throw new Error(S.message||S.error||"设置默认模板失败");S.ok&&await L(m)}catch(G){B(G instanceof Error?G.message:"模板请求失败")}},ee=async()=>{M(!0),B(null);try{const H=await fetch("/api/templates",{headers:d?{"x-admin-key":d}:{}}),V=await H.json();H.ok&&V.ok&&Array.isArray(V.templates)?g(V.templates):B(V.message||"获取模板失败,请检查密钥")}catch{B("连接后端服务失败")}finally{M(!1)}};fe.useEffect(()=>{u&&(ee(),L(m))},[u,m,d,s]),fe.useEffect(()=>{if(!u)return;const H=V=>{V.key==="Escape"&&!document.querySelector("dialog[open]")&&r()};return window.addEventListener("keydown",H),()=>window.removeEventListener("keydown",H)},[u,r]);const ce=async H=>{try{const V=await fetch(`/api/templates/${encodeURIComponent(H)}`,{method:"DELETE",headers:d?{"x-admin-key":d}:{}}),G=await V.json();if(!V.ok||!G.ok)throw new Error(G.message||G.error||"删除模板失败");g(S=>S.filter(q=>q.id!==H)),await L(m)}catch(V){B(V instanceof Error?V.message:"模板请求失败")}};if(!u)return null;const ue=x.filter(H=>p==="all"?!0:H.slot===p);return f.jsxs("aside",{"aria-label":"模板库",className:"absolute inset-y-0 right-0 z-40 w-80 max-w-full bg-white dark:bg-[#0f0f0f] border-l border-[#eaeaea] dark:border-[#262626] flex flex-col shadow-xl overflow-hidden",children:[f.jsxs("div",{className:"flex items-center justify-between px-5 py-3.5 border-b border-[#eaeaea] dark:border-[#222222]",children:[f.jsxs("div",{className:"flex items-center gap-2 font-semibold text-sm text-[#171717] dark:text-white",children:[f.jsx(So,{className:"w-4 h-4 text-emerald-500 dark:text-emerald-400"}),f.jsx("span",{children:"模板库"})]}),f.jsx("button",{onClick:r,"aria-label":"关闭模板库",className:"text-[#888888] hover:text-black dark:hover:text-white p-1 rounded-md hover:bg-[#f5f5f5] dark:hover:bg-[#1a1a1a]",children:f.jsx(jo,{className:"w-4 h-4"})})]}),f.jsxs("div",{className:"p-3 flex-1 min-h-0 flex flex-col gap-4 overflow-y-auto",children:[Q&&f.jsx("div",{role:"alert",className:"text-xs text-red-500 bg-red-500/10 p-2 rounded border border-red-500/20",children:Q}),f.jsxs("div",{className:"flex flex-col gap-2",children:[f.jsx("div",{className:"flex items-center justify-between text-xs",children:f.jsxs("div",{className:"flex items-center gap-1.5 font-medium text-[#666666] dark:text-[#888888]",children:[f.jsx("span",{children:"槽位账号:"}),f.jsxs("select",{value:m,onChange:H=>y(H.target.value),className:"bg-white dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#2a2a2a] rounded px-2 py-0.5 text-xs text-black dark:text-white focus:outline-none font-mono",children:[f.jsx("option",{value:"default",children:"default (主账号)"}),f.jsx("option",{value:"ancientone",children:"ancientone"})]})]})}),f.jsxs("div",{className:"flex flex-wrap items-center gap-1 text-xs",children:[f.jsx("button",{onClick:()=>b("all"),className:`px-2.5 py-1 rounded text-xs transition-colors font-medium ${p==="all"?"bg-black text-white dark:bg-white dark:text-black":"text-[#666666] dark:text-[#888888] hover:bg-[#f5f5f5] dark:hover:bg-[#1c1c1c]"}`,children:"全部"}),f.jsx("button",{onClick:()=>b("article_cover"),className:`px-2.5 py-1 rounded text-xs transition-colors font-medium ${p==="article_cover"?"bg-black text-white dark:bg-white dark:text-black":"text-[#666666] dark:text-[#888888] hover:bg-[#f5f5f5] dark:hover:bg-[#1c1c1c]"}`,children:"文章封面"}),f.jsx("button",{onClick:()=>b("newspic_cover"),className:`px-2.5 py-1 rounded text-xs transition-colors font-medium ${p==="newspic_cover"?"bg-black text-white dark:bg-white dark:text-black":"text-[#666666] dark:text-[#888888] hover:bg-[#f5f5f5] dark:hover:bg-[#1c1c1c]"}`,children:"贴图封面"}),f.jsx("button",{onClick:()=>b("newspic_content"),className:`px-2.5 py-1 rounded text-xs transition-colors font-medium ${p==="newspic_content"?"bg-black text-white dark:bg-white dark:text-black":"text-[#666666] dark:text-[#888888] hover:bg-[#f5f5f5] dark:hover:bg-[#1c1c1c]"}`,children:"贴图内容"})]})]}),f.jsx("div",{className:"flex flex-col gap-2",children:w?f.jsx("div",{className:"text-center py-8 text-xs text-[#888888] dark:text-[#555555]",children:"正在加载模板..."}):ue.length===0?f.jsx("div",{className:"text-center py-8 text-xs text-[#888888] dark:text-[#555555]",children:"暂无匹配模板"}):ue.map(H=>{const V=v.article_cover?.id===H.id,G=v.newspic_cover?.id===H.id,S=v.newspic_content?.id===H.id;return f.jsxs("div",{className:"flex flex-col justify-between p-3 rounded-lg bg-[#fafafa] dark:bg-[#141414] border border-[#eaeaea] dark:border-[#222222] hover:border-[#cccccc] dark:hover:border-[#333333] transition-all gap-2 group",children:[f.jsxs("div",{className:"flex items-center gap-3",children:[f.jsx("div",{className:"w-5 h-5 rounded border border-[#d4d4d4] dark:border-[#333333] shrink-0",style:{backgroundColor:H.theme.bgColor}}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[f.jsx("span",{className:"text-xs font-semibold text-[#171717] dark:text-white",children:H.name}),H.slot&&f.jsx("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-blue-500/10 text-blue-600 dark:text-blue-400 border border-blue-500/20 font-medium",children:H.slot==="article_cover"?"文章封面":H.slot==="newspic_cover"?"贴图封面":"贴图内容"}),V&&f.jsxs("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-amber-500/10 text-amber-600 dark:text-amber-400 border border-amber-500/20 font-medium flex items-center gap-0.5",children:[f.jsx(ho,{className:"w-2.5 h-2.5 fill-amber-500"})," 文章封面默认"]}),G&&f.jsxs("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-amber-500/10 text-amber-600 dark:text-amber-400 border border-amber-500/20 font-medium flex items-center gap-0.5",children:[f.jsx(ho,{className:"w-2.5 h-2.5 fill-amber-500"})," 贴图封面默认"]}),S&&f.jsxs("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border border-emerald-500/20 font-medium flex items-center gap-0.5",children:[f.jsx(ho,{className:"w-2.5 h-2.5 fill-emerald-500"})," 贴图内容默认"]})]}),f.jsxs("div",{className:"text-[10px] text-[#888888] dark:text-[#666666] font-mono mt-0.5",children:[H.aspectRatio," • 字号: ",H.algorithm.baseFontSize,"px",H.images&&H.images.length>0&&` • 配图: ${H.images.length}个`]})]})]}),f.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[H.id&&f.jsxs("select",{value:"",onChange:q=>{q.target.value&&$(q.target.value,H.id)},className:"text-[11px] bg-white dark:bg-[#1a1a1a] border border-[#d4d4d4] dark:border-[#333333] text-[#666666] dark:text-[#aaaaaa] rounded px-2 py-1 focus:outline-none",title:"为此账号设为某个槽位的默认模板",children:[f.jsx("option",{value:"",children:"设为槽位默认..."}),f.jsx("option",{value:"article_cover",children:"设为「文章封面默认」"}),f.jsx("option",{value:"newspic_cover",children:"设为「贴图封面默认」"}),f.jsx("option",{value:"newspic_content",children:"设为「贴图内容默认」"})]}),f.jsxs("button",{onClick:()=>{c(H)},className:"flex items-center gap-1 px-2.5 py-1 bg-white dark:bg-[#1f1f1f] hover:bg-emerald-50 dark:hover:bg-emerald-500/20 text-[#333333] dark:text-[#cccccc] hover:text-emerald-700 dark:hover:text-emerald-400 border border-[#d4d4d4] dark:border-[#2a2a2a] hover:border-emerald-500/40 rounded text-xs transition-all font-medium",children:[f.jsx(Qx,{className:"w-3 h-3"}),f.jsx("span",{children:"套用"})]}),H.id&&!H.id.startsWith("tpl_wechat_")&&!H.id.startsWith("tpl_longform_")&&!H.id.startsWith("tpl_square_")&&!H.id.startsWith("tpl_wide_")&&f.jsx("button",{onClick:()=>ce(H.id),className:"p-1 text-[#888888] dark:text-[#555555] hover:text-red-500 rounded hover:bg-[#f0f0f0] dark:hover:bg-[#1f1f1f]",title:"删除自定义模板",children:f.jsx(Eh,{className:"w-3.5 h-3.5"})})]})]},H.id)})})]})]})};function Cr(u=[]){if(!Array.isArray(u))throw new RangeError("模板图片必须是数组");const r=new Set;for(const s of u){if(!s||typeof s!="object")throw new RangeError("无效的模板图片");if(s.templateAssetKey===void 0)continue;const c=s.templateAssetKey;if(s.repeatEveryPage!==void 0&&typeof s.repeatEveryPage!="boolean")throw new RangeError(`素材 ${c} 的每页重复开关必须是布尔值`);if(typeof c!="string"||!/^[a-zA-Z0-9_-]+$/.test(c))throw new RangeError("素材标识只能包含字母、数字、下划线和短横线");if(s.repeatEveryPage&&!s.isAbsolute)throw new RangeError(`素材 ${c} 的每页重复仅支持自由定位模式`);if(r.has(c))throw new RangeError(`重复的模板素材标识:${c}`);r.add(c)}}function $p(u,r=[],s={}){if(Cr(r),!s||typeof s!="object"||Array.isArray(s))throw new RangeError("素材替换必须是标识到图片地址的映射");const c=r.filter(v=>v.templateAssetKey);for(const[v,N]of Object.entries(s)){if(!c.some(m=>m.templateAssetKey===v))throw new RangeError(`未知模板素材:${v}`);if(typeof N!="string"||!N.trim())throw new RangeError(`素材 ${v} 的替换图片不能为空`)}const d=u.filter(v=>!v.templateAssetKey),x=r.filter(v=>!v.templateAssetKey);return[...d.length===0?x.map(v=>({...v,id:`img_${crypto.randomUUID()}`})):d.map((v,N)=>{const m=x[N];return m?{...v,layoutPreset:m.layoutPreset??v.layoutPreset,isAbsolute:m.isAbsolute??v.isAbsolute,x:m.x??v.x,y:m.y??v.y,width:m.width??v.width,height:m.height??v.height,rotate:m.rotate??v.rotate,opacity:m.opacity??v.opacity,zIndex:m.zIndex??v.zIndex,borderRadius:m.borderRadius??v.borderRadius,captionHeight:m.captionHeight??v.captionHeight,pageIndex:m.pageIndex??v.pageIndex}:v}),...c.map(v=>({...v,src:Object.hasOwn(s,v.templateAssetKey)?s[v.templateAssetKey]:v.src}))]}const Pp=({isOpen:u,onClose:r,currentConfig:s,onSaved:c,adminKey:d})=>{const x=fe.useRef(null),[g,v]=fe.useState(""),[N,m]=fe.useState("none"),[y,p]=fe.useState(!1),[b,w]=fe.useState(null);fe.useEffect(()=>{u?(v(s.name||"我的自定义模板"),m(s.slot||(s.aspectRatio==="wechat-cover-2.35"?"article_cover":"newspic_content")),w(null),x.current?.showModal()):x.current?.close()},[u]);const M=async Q=>{if(Q.preventDefault(),!(!g.trim()||y)){p(!0),w(null);try{Cr(s.images);const B=await fetch("/api/templates",{method:"POST",headers:{"Content-Type":"application/json",...d?{"x-admin-key":d}:{}},body:JSON.stringify({...s,id:void 0,name:g.trim(),slot:N==="none"?void 0:N})}),L=await B.json();if(!B.ok||!L.ok)throw new Error(L.message||L.error||"保存模板失败");c(L.template),r()}catch(B){w(B instanceof Error?B.message:"保存模板请求异常")}finally{p(!1)}}};return f.jsx("dialog",{ref:x,"aria-labelledby":"save-template-title",onCancel:Q=>{Q.preventDefault(),y||r()},className:"m-auto w-[calc(100%-2rem)] max-w-sm p-0 rounded-xl border border-[#eaeaea] dark:border-[#262626] bg-white dark:bg-[#0f0f0f] text-[#171717] dark:text-white shadow-2xl backdrop:bg-black/40",children:f.jsxs("form",{onSubmit:M,children:[f.jsxs("div",{className:"flex items-center justify-between px-5 py-3.5 border-b border-[#eaeaea] dark:border-[#222222]",children:[f.jsx("h2",{id:"save-template-title",className:"text-sm font-semibold",children:"保存模板"}),f.jsx("button",{type:"button",onClick:r,disabled:y,"aria-label":"关闭保存模板",className:"p-1 rounded hover:bg-black/5 dark:hover:bg-white/10 disabled:opacity-50",children:f.jsx(jo,{className:"w-4 h-4"})})]}),f.jsxs("div",{className:"p-5 flex flex-col gap-4",children:[f.jsxs("label",{className:"flex flex-col gap-2 text-xs",children:["模板名称",f.jsx("input",{autoFocus:!0,required:!0,value:g,onChange:Q=>v(Q.target.value),placeholder:"输入模板名称",className:"bg-transparent border border-[#d4d4d4] dark:border-[#333333] rounded px-3 py-2 focus:outline-none focus:border-emerald-500"})]}),f.jsxs("label",{className:"flex flex-col gap-2 text-xs",children:["保存到槽位",f.jsxs("select",{value:N,onChange:Q=>m(Q.target.value),className:"bg-white dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#333333] rounded px-3 py-2",children:[f.jsx("option",{value:"article_cover",children:"文章封面 (2.35:1)"}),f.jsx("option",{value:"newspic_cover",children:"贴图封面 (3:4)"}),f.jsx("option",{value:"newspic_content",children:"贴图内容 (3:4)"}),f.jsx("option",{value:"none",children:"通用模板"})]})]}),b&&f.jsx("p",{role:"alert",className:"text-xs text-red-500",children:b}),f.jsxs("button",{type:"submit",disabled:y||!g.trim(),className:"flex items-center justify-center gap-2 px-3 py-2 rounded bg-black text-white dark:bg-white dark:text-black text-xs font-semibold disabled:opacity-50",children:[f.jsx(dh,{className:"w-3.5 h-3.5"}),y?"保存中...":"保存模板"]})]})]})})},go="typeset_studio_admin_key";function eb(){const[u,r]=fe.useState(()=>localStorage.getItem(go)||""),[s,c]=fe.useState(null),[d,x]=fe.useState(!1),g=async N=>{if(!N)return c(!1),!1;x(!0);try{const p=!!(await(await fetch("/api/auth/verify",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:N})})).json()).ok;return c(p),p}catch{return c(!1),!1}finally{x(!1)}},v=N=>{localStorage.setItem(go,N),r(N),g(N)};return fe.useEffect(()=>{(async()=>{let m=u;if(!m)try{const p=await(await fetch("/api/auth/current-key")).json();p.ok&&p.key&&(m=p.key,r(p.key),localStorage.setItem(go,p.key))}catch{}m?g(m):c(!1)})()},[]),{adminKey:u,setAdminKey:v,isVerified:s,isVerifying:d,verifyKey:g}}const tb=["BN","BN","BN","BN","BN","BN","BN","BN","BN","S","B","S","WS","B","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","B","B","B","S","WS","ON","ON","ET","ET","ET","ON","ON","ON","ON","ON","ES","CS","ES","CS","CS","EN","EN","EN","EN","EN","EN","EN","EN","EN","EN","CS","ON","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","ON","ON","ON","BN","BN","BN","BN","BN","BN","B","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","CS","ON","ET","ET","ET","ET","ON","ON","ON","ON","L","ON","ON","BN","ON","ON","ET","ET","EN","EN","ON","L","ON","ON","ON","EN","L","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","L","L","L","L","L","L","L","L"],Nx=[[697,698,"ON"],[706,719,"ON"],[722,735,"ON"],[741,749,"ON"],[751,767,"ON"],[768,879,"NSM"],[884,885,"ON"],[894,894,"ON"],[900,901,"ON"],[903,903,"ON"],[1014,1014,"ON"],[1155,1161,"NSM"],[1418,1418,"ON"],[1421,1422,"ON"],[1423,1423,"ET"],[1424,1424,"R"],[1425,1469,"NSM"],[1470,1470,"R"],[1471,1471,"NSM"],[1472,1472,"R"],[1473,1474,"NSM"],[1475,1475,"R"],[1476,1477,"NSM"],[1478,1478,"R"],[1479,1479,"NSM"],[1480,1535,"R"],[1536,1541,"AN"],[1542,1543,"ON"],[1544,1544,"AL"],[1545,1546,"ET"],[1547,1547,"AL"],[1548,1548,"CS"],[1549,1549,"AL"],[1550,1551,"ON"],[1552,1562,"NSM"],[1563,1610,"AL"],[1611,1631,"NSM"],[1632,1641,"AN"],[1642,1642,"ET"],[1643,1644,"AN"],[1645,1647,"AL"],[1648,1648,"NSM"],[1649,1749,"AL"],[1750,1756,"NSM"],[1757,1757,"AN"],[1758,1758,"ON"],[1759,1764,"NSM"],[1765,1766,"AL"],[1767,1768,"NSM"],[1769,1769,"ON"],[1770,1773,"NSM"],[1774,1775,"AL"],[1776,1785,"EN"],[1786,1808,"AL"],[1809,1809,"NSM"],[1810,1839,"AL"],[1840,1866,"NSM"],[1867,1957,"AL"],[1958,1968,"NSM"],[1969,1983,"AL"],[1984,2026,"R"],[2027,2035,"NSM"],[2036,2037,"R"],[2038,2041,"ON"],[2042,2044,"R"],[2045,2045,"NSM"],[2046,2069,"R"],[2070,2073,"NSM"],[2074,2074,"R"],[2075,2083,"NSM"],[2084,2084,"R"],[2085,2087,"NSM"],[2088,2088,"R"],[2089,2093,"NSM"],[2094,2136,"R"],[2137,2139,"NSM"],[2140,2143,"R"],[2144,2191,"AL"],[2192,2193,"AN"],[2194,2198,"AL"],[2199,2207,"NSM"],[2208,2249,"AL"],[2250,2273,"NSM"],[2274,2274,"AN"],[2275,2306,"NSM"],[2362,2362,"NSM"],[2364,2364,"NSM"],[2369,2376,"NSM"],[2381,2381,"NSM"],[2385,2391,"NSM"],[2402,2403,"NSM"],[2433,2433,"NSM"],[2492,2492,"NSM"],[2497,2500,"NSM"],[2509,2509,"NSM"],[2530,2531,"NSM"],[2546,2547,"ET"],[2555,2555,"ET"],[2558,2558,"NSM"],[2561,2562,"NSM"],[2620,2620,"NSM"],[2625,2626,"NSM"],[2631,2632,"NSM"],[2635,2637,"NSM"],[2641,2641,"NSM"],[2672,2673,"NSM"],[2677,2677,"NSM"],[2689,2690,"NSM"],[2748,2748,"NSM"],[2753,2757,"NSM"],[2759,2760,"NSM"],[2765,2765,"NSM"],[2786,2787,"NSM"],[2801,2801,"ET"],[2810,2815,"NSM"],[2817,2817,"NSM"],[2876,2876,"NSM"],[2879,2879,"NSM"],[2881,2884,"NSM"],[2893,2893,"NSM"],[2901,2902,"NSM"],[2914,2915,"NSM"],[2946,2946,"NSM"],[3008,3008,"NSM"],[3021,3021,"NSM"],[3059,3064,"ON"],[3065,3065,"ET"],[3066,3066,"ON"],[3072,3072,"NSM"],[3076,3076,"NSM"],[3132,3132,"NSM"],[3134,3136,"NSM"],[3142,3144,"NSM"],[3146,3149,"NSM"],[3157,3158,"NSM"],[3170,3171,"NSM"],[3192,3198,"ON"],[3201,3201,"NSM"],[3260,3260,"NSM"],[3276,3277,"NSM"],[3298,3299,"NSM"],[3328,3329,"NSM"],[3387,3388,"NSM"],[3393,3396,"NSM"],[3405,3405,"NSM"],[3426,3427,"NSM"],[3457,3457,"NSM"],[3530,3530,"NSM"],[3538,3540,"NSM"],[3542,3542,"NSM"],[3633,3633,"NSM"],[3636,3642,"NSM"],[3647,3647,"ET"],[3655,3662,"NSM"],[3761,3761,"NSM"],[3764,3772,"NSM"],[3784,3790,"NSM"],[3864,3865,"NSM"],[3893,3893,"NSM"],[3895,3895,"NSM"],[3897,3897,"NSM"],[3898,3901,"ON"],[3953,3966,"NSM"],[3968,3972,"NSM"],[3974,3975,"NSM"],[3981,3991,"NSM"],[3993,4028,"NSM"],[4038,4038,"NSM"],[4141,4144,"NSM"],[4146,4151,"NSM"],[4153,4154,"NSM"],[4157,4158,"NSM"],[4184,4185,"NSM"],[4190,4192,"NSM"],[4209,4212,"NSM"],[4226,4226,"NSM"],[4229,4230,"NSM"],[4237,4237,"NSM"],[4253,4253,"NSM"],[4957,4959,"NSM"],[5008,5017,"ON"],[5120,5120,"ON"],[5760,5760,"WS"],[5787,5788,"ON"],[5906,5908,"NSM"],[5938,5939,"NSM"],[5970,5971,"NSM"],[6002,6003,"NSM"],[6068,6069,"NSM"],[6071,6077,"NSM"],[6086,6086,"NSM"],[6089,6099,"NSM"],[6107,6107,"ET"],[6109,6109,"NSM"],[6128,6137,"ON"],[6144,6154,"ON"],[6155,6157,"NSM"],[6158,6158,"BN"],[6159,6159,"NSM"],[6277,6278,"NSM"],[6313,6313,"NSM"],[6432,6434,"NSM"],[6439,6440,"NSM"],[6450,6450,"NSM"],[6457,6459,"NSM"],[6464,6464,"ON"],[6468,6469,"ON"],[6622,6655,"ON"],[6679,6680,"NSM"],[6683,6683,"NSM"],[6742,6742,"NSM"],[6744,6750,"NSM"],[6752,6752,"NSM"],[6754,6754,"NSM"],[6757,6764,"NSM"],[6771,6780,"NSM"],[6783,6783,"NSM"],[6832,6877,"NSM"],[6880,6891,"NSM"],[6912,6915,"NSM"],[6964,6964,"NSM"],[6966,6970,"NSM"],[6972,6972,"NSM"],[6978,6978,"NSM"],[7019,7027,"NSM"],[7040,7041,"NSM"],[7074,7077,"NSM"],[7080,7081,"NSM"],[7083,7085,"NSM"],[7142,7142,"NSM"],[7144,7145,"NSM"],[7149,7149,"NSM"],[7151,7153,"NSM"],[7212,7219,"NSM"],[7222,7223,"NSM"],[7376,7378,"NSM"],[7380,7392,"NSM"],[7394,7400,"NSM"],[7405,7405,"NSM"],[7412,7412,"NSM"],[7416,7417,"NSM"],[7616,7679,"NSM"],[8125,8125,"ON"],[8127,8129,"ON"],[8141,8143,"ON"],[8157,8159,"ON"],[8173,8175,"ON"],[8189,8190,"ON"],[8192,8202,"WS"],[8203,8205,"BN"],[8207,8207,"R"],[8208,8231,"ON"],[8232,8232,"WS"],[8233,8233,"B"],[8234,8238,"BN"],[8239,8239,"CS"],[8240,8244,"ET"],[8245,8259,"ON"],[8260,8260,"CS"],[8261,8286,"ON"],[8287,8287,"WS"],[8288,8303,"BN"],[8304,8304,"EN"],[8308,8313,"EN"],[8314,8315,"ES"],[8316,8318,"ON"],[8320,8329,"EN"],[8330,8331,"ES"],[8332,8334,"ON"],[8352,8399,"ET"],[8400,8432,"NSM"],[8448,8449,"ON"],[8451,8454,"ON"],[8456,8457,"ON"],[8468,8468,"ON"],[8470,8472,"ON"],[8478,8483,"ON"],[8485,8485,"ON"],[8487,8487,"ON"],[8489,8489,"ON"],[8494,8494,"ET"],[8506,8507,"ON"],[8512,8516,"ON"],[8522,8525,"ON"],[8528,8543,"ON"],[8585,8587,"ON"],[8592,8721,"ON"],[8722,8722,"ES"],[8723,8723,"ET"],[8724,9013,"ON"],[9083,9108,"ON"],[9110,9257,"ON"],[9280,9290,"ON"],[9312,9351,"ON"],[9352,9371,"EN"],[9450,9899,"ON"],[9901,10239,"ON"],[10496,11123,"ON"],[11126,11263,"ON"],[11493,11498,"ON"],[11503,11505,"NSM"],[11513,11519,"ON"],[11647,11647,"NSM"],[11744,11775,"NSM"],[11776,11869,"ON"],[11904,11929,"ON"],[11931,12019,"ON"],[12032,12245,"ON"],[12272,12287,"ON"],[12288,12288,"WS"],[12289,12292,"ON"],[12296,12320,"ON"],[12330,12333,"NSM"],[12336,12336,"ON"],[12342,12343,"ON"],[12349,12351,"ON"],[12441,12442,"NSM"],[12443,12444,"ON"],[12448,12448,"ON"],[12539,12539,"ON"],[12736,12773,"ON"],[12783,12783,"ON"],[12829,12830,"ON"],[12880,12895,"ON"],[12924,12926,"ON"],[12977,12991,"ON"],[13004,13007,"ON"],[13175,13178,"ON"],[13278,13279,"ON"],[13311,13311,"ON"],[19904,19967,"ON"],[42128,42182,"ON"],[42509,42511,"ON"],[42607,42610,"NSM"],[42611,42611,"ON"],[42612,42621,"NSM"],[42622,42623,"ON"],[42654,42655,"NSM"],[42736,42737,"NSM"],[42752,42785,"ON"],[42888,42888,"ON"],[43010,43010,"NSM"],[43014,43014,"NSM"],[43019,43019,"NSM"],[43045,43046,"NSM"],[43048,43051,"ON"],[43052,43052,"NSM"],[43064,43065,"ET"],[43124,43127,"ON"],[43204,43205,"NSM"],[43232,43249,"NSM"],[43263,43263,"NSM"],[43302,43309,"NSM"],[43335,43345,"NSM"],[43392,43394,"NSM"],[43443,43443,"NSM"],[43446,43449,"NSM"],[43452,43453,"NSM"],[43493,43493,"NSM"],[43561,43566,"NSM"],[43569,43570,"NSM"],[43573,43574,"NSM"],[43587,43587,"NSM"],[43596,43596,"NSM"],[43644,43644,"NSM"],[43696,43696,"NSM"],[43698,43700,"NSM"],[43703,43704,"NSM"],[43710,43711,"NSM"],[43713,43713,"NSM"],[43756,43757,"NSM"],[43766,43766,"NSM"],[43882,43883,"ON"],[44005,44005,"NSM"],[44008,44008,"NSM"],[44013,44013,"NSM"],[64285,64285,"R"],[64286,64286,"NSM"],[64287,64296,"R"],[64297,64297,"ES"],[64298,64335,"R"],[64336,64450,"AL"],[64451,64466,"ON"],[64467,64829,"AL"],[64830,64847,"ON"],[64848,64911,"AL"],[64912,64913,"ON"],[64914,64967,"AL"],[64968,64975,"ON"],[64976,65007,"BN"],[65008,65020,"AL"],[65021,65023,"ON"],[65024,65039,"NSM"],[65040,65049,"ON"],[65056,65071,"NSM"],[65072,65103,"ON"],[65104,65104,"CS"],[65105,65105,"ON"],[65106,65106,"CS"],[65108,65108,"ON"],[65109,65109,"CS"],[65110,65118,"ON"],[65119,65119,"ET"],[65120,65121,"ON"],[65122,65123,"ES"],[65124,65126,"ON"],[65128,65128,"ON"],[65129,65130,"ET"],[65131,65131,"ON"],[65136,65278,"AL"],[65279,65279,"BN"],[65281,65282,"ON"],[65283,65285,"ET"],[65286,65290,"ON"],[65291,65291,"ES"],[65292,65292,"CS"],[65293,65293,"ES"],[65294,65295,"CS"],[65296,65305,"EN"],[65306,65306,"CS"],[65307,65312,"ON"],[65339,65344,"ON"],[65371,65381,"ON"],[65504,65505,"ET"],[65506,65508,"ON"],[65509,65510,"ET"],[65512,65518,"ON"],[65520,65528,"BN"],[65529,65533,"ON"],[65534,65535,"BN"],[65793,65793,"ON"],[65856,65932,"ON"],[65936,65948,"ON"],[65952,65952,"ON"],[66045,66045,"NSM"],[66272,66272,"NSM"],[66273,66299,"EN"],[66422,66426,"NSM"],[67584,67870,"R"],[67871,67871,"ON"],[67872,68096,"R"],[68097,68099,"NSM"],[68100,68100,"R"],[68101,68102,"NSM"],[68103,68107,"R"],[68108,68111,"NSM"],[68112,68151,"R"],[68152,68154,"NSM"],[68155,68158,"R"],[68159,68159,"NSM"],[68160,68324,"R"],[68325,68326,"NSM"],[68327,68408,"R"],[68409,68415,"ON"],[68416,68863,"R"],[68864,68899,"AL"],[68900,68903,"NSM"],[68904,68911,"AL"],[68912,68921,"AN"],[68922,68927,"AL"],[68928,68937,"AN"],[68938,68968,"R"],[68969,68973,"NSM"],[68974,68974,"ON"],[68975,69215,"R"],[69216,69246,"AN"],[69247,69290,"R"],[69291,69292,"NSM"],[69293,69311,"R"],[69312,69327,"AL"],[69328,69336,"ON"],[69337,69369,"AL"],[69370,69375,"NSM"],[69376,69423,"R"],[69424,69445,"AL"],[69446,69456,"NSM"],[69457,69487,"AL"],[69488,69505,"R"],[69506,69509,"NSM"],[69510,69631,"R"],[69633,69633,"NSM"],[69688,69702,"NSM"],[69714,69733,"ON"],[69744,69744,"NSM"],[69747,69748,"NSM"],[69759,69761,"NSM"],[69811,69814,"NSM"],[69817,69818,"NSM"],[69826,69826,"NSM"],[69888,69890,"NSM"],[69927,69931,"NSM"],[69933,69940,"NSM"],[70003,70003,"NSM"],[70016,70017,"NSM"],[70070,70078,"NSM"],[70089,70092,"NSM"],[70095,70095,"NSM"],[70191,70193,"NSM"],[70196,70196,"NSM"],[70198,70199,"NSM"],[70206,70206,"NSM"],[70209,70209,"NSM"],[70367,70367,"NSM"],[70371,70378,"NSM"],[70400,70401,"NSM"],[70459,70460,"NSM"],[70464,70464,"NSM"],[70502,70508,"NSM"],[70512,70516,"NSM"],[70587,70592,"NSM"],[70606,70606,"NSM"],[70608,70608,"NSM"],[70610,70610,"NSM"],[70625,70626,"NSM"],[70712,70719,"NSM"],[70722,70724,"NSM"],[70726,70726,"NSM"],[70750,70750,"NSM"],[70835,70840,"NSM"],[70842,70842,"NSM"],[70847,70848,"NSM"],[70850,70851,"NSM"],[71090,71093,"NSM"],[71100,71101,"NSM"],[71103,71104,"NSM"],[71132,71133,"NSM"],[71219,71226,"NSM"],[71229,71229,"NSM"],[71231,71232,"NSM"],[71264,71276,"ON"],[71339,71339,"NSM"],[71341,71341,"NSM"],[71344,71349,"NSM"],[71351,71351,"NSM"],[71453,71453,"NSM"],[71455,71455,"NSM"],[71458,71461,"NSM"],[71463,71467,"NSM"],[71727,71735,"NSM"],[71737,71738,"NSM"],[71995,71996,"NSM"],[71998,71998,"NSM"],[72003,72003,"NSM"],[72148,72151,"NSM"],[72154,72155,"NSM"],[72160,72160,"NSM"],[72193,72198,"NSM"],[72201,72202,"NSM"],[72243,72248,"NSM"],[72251,72254,"NSM"],[72263,72263,"NSM"],[72273,72278,"NSM"],[72281,72283,"NSM"],[72330,72342,"NSM"],[72344,72345,"NSM"],[72544,72544,"NSM"],[72546,72548,"NSM"],[72550,72550,"NSM"],[72752,72758,"NSM"],[72760,72765,"NSM"],[72850,72871,"NSM"],[72874,72880,"NSM"],[72882,72883,"NSM"],[72885,72886,"NSM"],[73009,73014,"NSM"],[73018,73018,"NSM"],[73020,73021,"NSM"],[73023,73029,"NSM"],[73031,73031,"NSM"],[73104,73105,"NSM"],[73109,73109,"NSM"],[73111,73111,"NSM"],[73459,73460,"NSM"],[73472,73473,"NSM"],[73526,73530,"NSM"],[73536,73536,"NSM"],[73538,73538,"NSM"],[73562,73562,"NSM"],[73685,73692,"ON"],[73693,73696,"ET"],[73697,73713,"ON"],[78912,78912,"NSM"],[78919,78933,"NSM"],[90398,90409,"NSM"],[90413,90415,"NSM"],[92912,92916,"NSM"],[92976,92982,"NSM"],[94031,94031,"NSM"],[94095,94098,"NSM"],[94178,94178,"ON"],[94180,94180,"NSM"],[113821,113822,"NSM"],[113824,113827,"BN"],[117760,117973,"ON"],[118e3,118009,"EN"],[118010,118012,"ON"],[118016,118451,"ON"],[118458,118480,"ON"],[118496,118512,"ON"],[118528,118573,"NSM"],[118576,118598,"NSM"],[119143,119145,"NSM"],[119155,119162,"BN"],[119163,119170,"NSM"],[119173,119179,"NSM"],[119210,119213,"NSM"],[119273,119274,"ON"],[119296,119361,"ON"],[119362,119364,"NSM"],[119365,119365,"ON"],[119552,119638,"ON"],[120513,120513,"ON"],[120539,120539,"ON"],[120571,120571,"ON"],[120597,120597,"ON"],[120629,120629,"ON"],[120655,120655,"ON"],[120687,120687,"ON"],[120713,120713,"ON"],[120745,120745,"ON"],[120771,120771,"ON"],[120782,120831,"EN"],[121344,121398,"NSM"],[121403,121452,"NSM"],[121461,121461,"NSM"],[121476,121476,"NSM"],[121499,121503,"NSM"],[121505,121519,"NSM"],[122880,122886,"NSM"],[122888,122904,"NSM"],[122907,122913,"NSM"],[122915,122916,"NSM"],[122918,122922,"NSM"],[123023,123023,"NSM"],[123184,123190,"NSM"],[123566,123566,"NSM"],[123628,123631,"NSM"],[123647,123647,"ET"],[124140,124143,"NSM"],[124398,124399,"NSM"],[124643,124643,"NSM"],[124646,124646,"NSM"],[124654,124655,"NSM"],[124661,124661,"NSM"],[124928,125135,"R"],[125136,125142,"NSM"],[125143,125251,"R"],[125252,125258,"NSM"],[125259,126063,"R"],[126064,126143,"AL"],[126144,126207,"R"],[126208,126287,"AL"],[126288,126463,"R"],[126464,126703,"AL"],[126704,126705,"ON"],[126706,126719,"AL"],[126720,126975,"R"],[126976,127019,"ON"],[127024,127123,"ON"],[127136,127150,"ON"],[127153,127167,"ON"],[127169,127183,"ON"],[127185,127221,"ON"],[127232,127242,"EN"],[127243,127247,"ON"],[127279,127279,"ON"],[127338,127343,"ON"],[127405,127405,"ON"],[127584,127589,"ON"],[127744,128728,"ON"],[128732,128748,"ON"],[128752,128764,"ON"],[128768,128985,"ON"],[128992,129003,"ON"],[129008,129008,"ON"],[129024,129035,"ON"],[129040,129095,"ON"],[129104,129113,"ON"],[129120,129159,"ON"],[129168,129197,"ON"],[129200,129211,"ON"],[129216,129217,"ON"],[129232,129240,"ON"],[129280,129623,"ON"],[129632,129645,"ON"],[129648,129660,"ON"],[129664,129674,"ON"],[129678,129734,"ON"],[129736,129736,"ON"],[129741,129756,"ON"],[129759,129770,"ON"],[129775,129784,"ON"],[129792,129938,"ON"],[129940,130031,"ON"],[130032,130041,"EN"],[130042,130042,"ON"],[131070,131071,"BN"],[196606,196607,"BN"],[262142,262143,"BN"],[327678,327679,"BN"],[393214,393215,"BN"],[458750,458751,"BN"],[524286,524287,"BN"],[589822,589823,"BN"],[655358,655359,"BN"],[720894,720895,"BN"],[786430,786431,"BN"],[851966,851967,"BN"],[917502,917759,"BN"],[917760,917999,"NSM"],[918e3,921599,"BN"],[983038,983039,"BN"],[1048574,1048575,"BN"],[1114110,1114111,"BN"]];function lb(u){if(u<=255)return tb[u];let r=0,s=Nx.length-1;for(;r<=s;){const c=r+s>>1,d=Nx[c];if(u<d[0]){s=c-1;continue}if(u>d[1]){r=c+1;continue}return d[2]}return"L"}function nb(u){const r=u.length;if(r===0)return null;const s=new Array(r);let c=!1;for(let m=0;m<r;){const y=u.charCodeAt(m);let p=y,b=1;if(y>=55296&&y<=56319&&m+1<r){const M=u.charCodeAt(m+1);M>=56320&&M<=57343&&(p=(y-55296<<10)+(M-56320)+65536,b=2)}const w=lb(p);(w==="R"||w==="AL"||w==="AN")&&(c=!0);for(let M=0;M<b;M++)s[m+M]=w;m+=b}if(!c)return null;let d=0;for(let m=0;m<r;m++){const y=s[m];if(y==="L"){d=0;break}if(y==="R"||y==="AL"){d=1;break}}const x=new Int8Array(r);for(let m=0;m<r;m++)x[m]=d;const g=d&1?"R":"L",v=g;let N=v;for(let m=0;m<r;m++)s[m]==="NSM"?s[m]=N:N=s[m];N=v;for(let m=0;m<r;m++){const y=s[m];y==="EN"?s[m]=N==="AL"?"AN":"EN":(y==="R"||y==="L"||y==="AL")&&(N=y)}for(let m=0;m<r;m++)s[m]==="AL"&&(s[m]="R");for(let m=1;m<r-1;m++)s[m]==="ES"&&s[m-1]==="EN"&&s[m+1]==="EN"&&(s[m]="EN"),s[m]==="CS"&&(s[m-1]==="EN"||s[m-1]==="AN")&&s[m+1]===s[m-1]&&(s[m]=s[m-1]);for(let m=0;m<r;m++){if(s[m]!=="EN")continue;let y;for(y=m-1;y>=0&&s[y]==="ET";y--)s[y]="EN";for(y=m+1;y<r&&s[y]==="ET";y++)s[y]="EN"}for(let m=0;m<r;m++){const y=s[m];(y==="WS"||y==="ES"||y==="ET"||y==="CS")&&(s[m]="ON")}N=v;for(let m=0;m<r;m++){const y=s[m];y==="EN"?s[m]=N==="L"?"L":"EN":(y==="R"||y==="L")&&(N=y)}for(let m=0;m<r;m++){if(s[m]!=="ON")continue;let y=m+1;for(;y<r&&s[y]==="ON";)y++;const p=m>0?s[m-1]:v,b=y<r?s[y]:v,w=p!=="L"?"R":"L";if(w===(b!=="L"?"R":"L"))for(let Q=m;Q<y;Q++)s[Q]=w;m=y-1}for(let m=0;m<r;m++)s[m]==="ON"&&(s[m]=g);for(let m=0;m<r;m++){const y=s[m];(x[m]&1)===0?y==="R"?x[m]++:(y==="AN"||y==="EN")&&(x[m]+=2):(y==="L"||y==="AN"||y==="EN")&&x[m]++}return x}function ab(u,r){const s=nb(u);if(s===null)return null;const c=new Int8Array(r.length);for(let d=0;d<r.length;d++)c[d]=s[r[d]];return c}const ib=/[ \t\n\r\f]+/g,ub=/[\t\n\r\f]| {2,}|^ | $/;function rb(u){const r=u??"normal";return r==="pre-wrap"?{mode:r,preserveOrdinarySpaces:!0,preserveHardBreaks:!0}:{mode:r,preserveOrdinarySpaces:!1,preserveHardBreaks:!1}}function cb(u){if(!ub.test(u))return u;let r=u.replace(ib," ");return r.charCodeAt(0)===32&&(r=r.slice(1)),r.length>0&&r.charCodeAt(r.length-1)===32&&(r=r.slice(0,-1)),r}function sb(u){return/[\r\f]/.test(u)?u.replace(/\r\n/g,`
|
|
292
|
+
`).length]})]})]}),M==="images"&&f.jsxs("div",{className:"flex-1 flex flex-col p-3 gap-3 overflow-y-auto",children:[f.jsxs("div",{className:"flex gap-2",children:[f.jsx("input",{type:"file",ref:$,onChange:H,accept:"image/*",className:"hidden"}),f.jsxs("button",{onClick:()=>$.current?.click(),disabled:ee,className:"flex-1 flex items-center justify-center gap-2 py-2.5 rounded-lg border border-dashed border-[#d4d4d4] dark:border-[#333333] hover:border-black dark:hover:border-[#555555] bg-[#fafafa] dark:bg-[#0f0f0f] hover:bg-[#f5f5f5] dark:hover:bg-[#141414] text-xs text-[#555555] dark:text-[#cccccc] hover:text-black dark:hover:text-white transition-all",children:[f.jsx(Op,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:ee?"正在上传...":"上传配图素材"})]}),f.jsx("button",{onClick:()=>c({src:"https://images.unsplash.com/photo-1579783900882-c0d3dad7b119?w=800&auto=format&fit=crop&q=80",alt:"艺术插画",caption:"示例艺术配图",x:36,y:400,width:440,height:300,captionHeight:36,layoutPreset:"auto"}),className:"px-3 py-2.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] bg-[#fafafa] dark:bg-[#0f0f0f] hover:bg-[#f5f5f5] dark:hover:bg-[#141414] text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white transition-all",title:"插入在线示例图",children:f.jsx(Sp,{className:"w-3.5 h-3.5"})})]}),f.jsx("div",{className:"flex flex-col gap-2.5",children:s.length===0?f.jsx("div",{className:"text-center py-8 text-xs text-[#888888] dark:text-[#555555]",children:"暂无配图素材,点击上方按钮上传或插入"}):s.map((S,q)=>f.jsxs("div",{className:"bg-[#fafafa] dark:bg-[#0f0f0f] border border-[#eaeaea] dark:border-[#222222] rounded-lg p-2.5 flex flex-col gap-2",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsx("img",{src:S.src,alt:S.alt,className:"w-12 h-12 object-cover rounded bg-[#eeeeee] dark:bg-[#1a1a1a] border border-[#e5e5e5] dark:border-[#262626] shrink-0"}),f.jsxs("div",{className:"flex-1 min-w-0",children:[f.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[f.jsxs("span",{className:"text-[10px] px-1 rounded bg-[#eaeaea] dark:bg-[#262626] font-mono text-[#555555] dark:text-[#aaaaaa] font-semibold shrink-0",children:["#",q+1]}),f.jsx("span",{className:"text-xs font-medium text-[#171717] dark:text-white truncate max-w-[120px]",children:S.caption||S.alt||`配图 #${q+1}`}),f.jsxs("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border border-emerald-500/20 font-medium shrink-0",children:["第 ",S.pageIndex||1," 页"]})]}),f.jsxs("div",{className:"text-[10px] text-[#888888] dark:text-[#666666] font-mono mt-0.5",children:[S.width," × ",S.height,"px · X: ",S.x??0,", Y: ",S.y??0]})]}),f.jsxs("div",{className:"flex items-center gap-0.5",children:[f.jsx("button",{onClick:()=>m?.(S.id,"up"),disabled:q===0,className:"p-1 text-[#888888] hover:text-black dark:hover:text-white disabled:opacity-20 rounded hover:bg-[#eeeeee] dark:hover:bg-[#1f1f1f]",title:"上移顺序 (调整在同一页中的先后次序)",children:f.jsx(cp,{className:"w-3.5 h-3.5"})}),f.jsx("button",{onClick:()=>m?.(S.id,"down"),disabled:q===s.length-1,className:"p-1 text-[#888888] hover:text-black dark:hover:text-white disabled:opacity-20 rounded hover:bg-[#eeeeee] dark:hover:bg-[#1f1f1f]",title:"下移顺序 (调整在同一页中的先后次序)",children:f.jsx(up,{className:"w-3.5 h-3.5"})}),f.jsx("button",{onClick:()=>N(S.id),className:"p-1 text-[#888888] hover:text-red-500 rounded hover:bg-[#eeeeee] dark:hover:bg-[#1f1f1f]",title:"删除该图",children:f.jsx(Eh,{className:"w-3.5 h-3.5"})})]})]}),f.jsxs("div",{className:"flex bg-[#eeeeee] dark:bg-[#1a1a1a] p-0.5 rounded text-[11px] font-medium pt-1 border-t border-[#eeeeee] dark:border-[#1a1a1a]",children:[f.jsx("button",{onClick:()=>v(S.id,{isAbsolute:!1}),className:`flex-1 py-1 rounded transition-all text-center ${S.isAbsolute?"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white":"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold"}`,children:"绕排避让 (Flow)"}),f.jsx("button",{onClick:()=>v(S.id,{isAbsolute:!0,layoutPreset:"custom",zIndex:S.zIndex??15,rotate:S.rotate??0,opacity:S.opacity??1}),className:`flex-1 py-1 rounded transition-all text-center ${S.isAbsolute?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:"自由图层 (Absolute)"})]}),f.jsxs("div",{className:"flex flex-col gap-2 text-[11px]",children:[f.jsxs("label",{className:"flex items-center gap-2",children:[f.jsx("input",{type:"checkbox",checked:S.templateAssetKey!==void 0,onChange:_=>v(S.id,{templateAssetKey:_.target.checked?`asset_${S.id.replace(/[^a-zA-Z0-9_-]/g,"_")}`:void 0,repeatEveryPage:!1})}),"固定模板素材"]}),S.templateAssetKey!==void 0&&f.jsxs(f.Fragment,{children:[f.jsxs("label",{className:"flex flex-col gap-1",children:["素材标识",f.jsx("input",{"aria-label":"素材标识",value:S.templateAssetKey,onChange:_=>v(S.id,{templateAssetKey:_.target.value}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1"})]}),s.some(_=>_.id!==S.id&&_.templateAssetKey===S.templateAssetKey)&&f.jsx("span",{role:"alert",className:"text-red-600",children:"素材标识不能重复"}),f.jsxs("label",{className:"flex items-center gap-2",children:[f.jsx("input",{type:"checkbox",disabled:!S.isAbsolute,checked:!!(S.isAbsolute&&S.repeatEveryPage),onChange:_=>v(S.id,{repeatEveryPage:_.target.checked})}),"每页重复"]}),!S.isAbsolute&&f.jsx("span",{className:"text-[#888888]",children:"每页重复仅支持自由图层,避免阻塞文字排版。"}),f.jsx("span",{className:"text-[#888888]",children:"默认保留此图,仅按素材标识明确替换。"})]}),S.isAbsolute&&f.jsxs("label",{className:"flex items-center gap-2",children:[f.jsx("input",{type:"checkbox",checked:g.includes(S.id),onChange:_=>d(S.id,_.target.checked)}),"设为整页背景"]}),f.jsx("button",{type:"button",onClick:()=>x(S.id),title:"恢复上传或应用模板时的尺寸、位置和图层设置",className:"rounded border border-[#d4d4d4] dark:border-[#333333] px-2 py-1.5 hover:bg-[#eeeeee] dark:hover:bg-[#222222]",children:"重置布局"})]}),S.isAbsolute?f.jsxs(f.Fragment,{children:[f.jsxs("div",{className:"text-[10px] text-blue-600 dark:text-blue-400 bg-blue-500/10 p-1.5 rounded flex items-center gap-1 font-medium",children:[f.jsx(So,{className:"w-3 h-3 shrink-0"}),f.jsx("span",{children:"自由定位图层:脱离文本流,不触发障碍物绕排"})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"所属页面"}),f.jsx("select",{value:S.pageIndex||1,onChange:_=>v(S.id,{pageIndex:parseInt(_.target.value,10)||1}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] focus:outline-none",children:Array.from({length:Math.max(y,2)},(_,te)=>te+1).map(_=>f.jsxs("option",{value:_,children:["第 ",_," 页 ",_===1?"(首页/封面)":""]},_))})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] mb-1",children:[f.jsx("span",{children:"层级 (Z-Index)"}),f.jsx("span",{className:"font-mono text-black dark:text-white font-semibold",children:S.zIndex??15})]}),f.jsx("div",{className:"flex gap-1",children:[{label:"底",val:0,title:"底层背景"},{label:"文字",val:10,title:"正文同层"},{label:"顶",val:20,title:"置顶贴纸"}].map(_=>f.jsx("button",{onClick:()=>v(S.id,{zIndex:_.val}),title:_.title,className:`flex-1 py-0.5 text-[10px] rounded border ${(S.zIndex??15)===_.val?"bg-black dark:bg-white text-white dark:text-black border-transparent font-bold":"border-[#d4d4d4] dark:border-[#262626] text-[#666666] dark:text-[#888888]"}`,children:_.label},_.val))})]})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] mb-1",children:[f.jsxs("span",{className:"flex items-center gap-0.5",children:[f.jsx(Ep,{className:"w-2.5 h-2.5"})," 旋转角度"]}),f.jsxs("span",{className:"font-mono text-black dark:text-white font-semibold",children:[S.rotate??0,"°"]})]}),f.jsx("input",{type:"range",min:"-45",max:"45",step:"1",value:S.rotate??0,onChange:_=>v(S.id,{rotate:parseInt(_.target.value,10)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded cursor-pointer mt-1"})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] mb-1",children:[f.jsx("span",{children:"不透明度"}),f.jsxs("span",{className:"font-mono text-black dark:text-white font-semibold",children:[Math.round((S.opacity??1)*100),"%"]})]}),f.jsx("input",{type:"range",min:"0.1",max:"1",step:"0.05",value:S.opacity??1,onChange:_=>v(S.id,{opacity:parseFloat(_.target.value)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded cursor-pointer mt-1"})]})]}),f.jsxs("div",{className:"text-[11px]",children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"圆角半径 (px)"}),f.jsx("input",{type:"number",min:"0",step:"4",value:S.borderRadius??12,onChange:_=>v(S.id,{borderRadius:parseInt(_.target.value,10)||0}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"横向 X"}),f.jsx("input",{type:"number",step:"10",value:S.x??0,onChange:_=>v(S.id,{x:parseInt(_.target.value,10)||0}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"纵向 Y"}),f.jsx("input",{type:"number",step:"10",value:S.y??0,onChange:_=>v(S.id,{y:parseInt(_.target.value,10)||0}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"宽度 (W)"}),f.jsx("input",{type:"number",step:"10",value:S.width??420,onChange:_=>v(S.id,{width:Math.max(20,parseInt(_.target.value,10)||20)}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"高度 (H)"}),f.jsx("input",{type:"number",step:"10",value:S.height??280,onChange:_=>v(S.id,{height:Math.max(20,parseInt(_.target.value,10)||20)}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]})]})]}):f.jsxs(f.Fragment,{children:[f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"排版预设"}),f.jsxs("select",{value:S.layoutPreset||"auto",onChange:_=>v(S.id,{layoutPreset:_.target.value}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] focus:outline-none",children:[f.jsx("option",{value:"auto",children:"自适应 (Auto)"}),f.jsx("option",{value:"mid-left",children:"居左浮动 (Left)"}),f.jsx("option",{value:"mid-right",children:"居右浮动 (Right)"}),f.jsx("option",{value:"center",children:"居中横幅 (Center)"}),f.jsx("option",{value:"staggered",children:"交错排版 (Staggered)"}),f.jsx("option",{value:"corner-soft",children:"角落软着陆 (Corner)"}),f.jsx("option",{value:"fill",children:"底部填满 (Fill)"}),f.jsx("option",{value:"custom",children:"自定义坐标 (Custom)"})]})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"所属页面"}),f.jsx("select",{value:S.pageIndex||1,onChange:_=>v(S.id,{pageIndex:parseInt(_.target.value,10)||1}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] focus:outline-none",children:Array.from({length:Math.max(y,2)},(_,te)=>te+1).map(_=>f.jsxs("option",{value:_,children:["第 ",_," 页 ",_===1?"(首页/封面)":""]},_))})]})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"宽度 (W)"}),f.jsx("input",{type:"number",min:"50",step:"10",value:S.width??420,onChange:_=>v(S.id,{width:Math.max(50,parseInt(_.target.value,10)||50)}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"高度 (H)"}),f.jsx("input",{type:"number",min:"50",step:"10",value:S.height??280,onChange:_=>v(S.id,{height:Math.max(50,parseInt(_.target.value,10)||50)}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px]",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"纵向位置 Y"}),f.jsx("input",{type:"number",step:"20",value:S.y??300,onChange:_=>v(S.id,{y:parseInt(_.target.value,10)||0,layoutPreset:"custom"}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] block mb-1",children:"横向坐标 X"}),f.jsx("input",{type:"number",step:"10",value:S.x??16,onChange:_=>v(S.id,{x:parseInt(_.target.value,10)||0,layoutPreset:"custom"}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-1.5 py-1 text-black dark:text-white text-[11px] font-mono focus:outline-none"})]})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] text-[11px] block mb-1",children:"图片说明 (Caption)"}),f.jsx("input",{type:"text",placeholder:"下方说明文字...",value:S.caption||"",onChange:_=>v(S.id,{caption:_.target.value}),className:"w-full bg-white dark:bg-[#181818] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white text-[11px] focus:outline-none"})]})]})]},S.id))})]}),M==="highlights"&&f.jsxs("div",{className:"flex-1 flex flex-col p-3 gap-3 overflow-y-auto",children:[f.jsx("div",{className:"text-xs text-[#666666] dark:text-[#888888] leading-relaxed",children:"在正文中出现的高亮词,将被算法自动匹配并渲染为品牌强调色。"}),f.jsxs("div",{className:"flex gap-2",children:[f.jsx("input",{type:"text",placeholder:"新增高亮关键词...",value:B,onChange:S=>L(S.target.value),onKeyDown:S=>S.key==="Enter"&&V(),className:"flex-1 bg-white dark:bg-[#0d0d0d] border border-[#d4d4d4] dark:border-[#222222] rounded-lg px-2.5 py-1.5 text-xs text-black dark:text-white placeholder-[#888888] dark:placeholder-[#555555] focus:outline-none focus:border-black dark:focus:border-[#444444]"}),f.jsx("button",{onClick:V,className:"px-3 py-1.5 bg-black dark:bg-[#1f1f1f] hover:bg-[#262626] text-white rounded-lg text-xs font-medium",children:"添加"})]}),f.jsx("div",{className:"flex flex-wrap gap-1.5 mt-1",children:p.map(S=>f.jsxs("span",{className:"flex items-center gap-1 px-2.5 py-1 rounded-md bg-[#f0fdf4] dark:bg-[#161616] border border-[#bbf7d0] dark:border-[#262626] text-xs text-emerald-700 dark:text-emerald-400 font-medium",children:[f.jsx(So,{className:"w-3 h-3"}),f.jsx("span",{children:S}),f.jsx("button",{onClick:()=>G(S),className:"hover:text-red-500 ml-1",children:"×"})]},S))})]})]})},Vp=[{id:"wechat-cover-2.35",label:"微信封面",ratioTag:"3.35:1"},{id:"longform-3-4",label:"通用长图文",ratioTag:"3:4"},{id:"wide-16-9",label:"通用宽屏",ratioTag:"16:9"},{id:"square-1-1",label:"通用正方形",ratioTag:"1:1"}],Zp=({currentRatio:u,onSelectRatio:r,zoom:s,onZoomChange:c,onAutoFit:d,isAutoFit:x,onOpenTemplates:g,isTemplateDrawerOpen:v,templateName:N,onSaveTemplate:m,onOpenAuth:y,onExport:p,isExporting:b,isAuthed:w,pageCount:M,themeMode:Q,onToggleThemeMode:B})=>f.jsxs("header",{className:"h-14 border-b border-[#eaeaea] dark:border-[#222222] bg-white/80 dark:bg-[#000000]/80 backdrop-blur-md px-4 flex items-center justify-between select-none z-30 shrink-0 transition-colors",children:[f.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[f.jsxs("div",{className:"flex items-center gap-2 font-semibold text-[#171717] dark:text-white tracking-tight text-sm",children:[f.jsx("span",{className:"flex items-center justify-center w-6 h-6 rounded bg-black dark:bg-white text-white dark:text-black font-black text-xs shadow-sm",children:"▲"}),f.jsx("span",{className:"hidden 2xl:inline",children:"Typeset Studio"})]}),f.jsx("span",{className:"text-xs text-[#888888] dark:text-[#555555] font-mono hidden 2xl:inline",children:"v0.2.7"}),f.jsxs("div",{title:N||"未命名模板",className:"flex min-w-0 items-center gap-1.5 px-2 py-0.5 rounded-full bg-[#f5f5f5] dark:bg-[#111111] border border-[#e5e5e5] dark:border-[#222222] text-[11px] text-emerald-600 dark:text-[#00e676]",children:[f.jsx("span",{className:"w-1.5 h-1.5 shrink-0 rounded-full bg-emerald-500 dark:bg-[#00e676]"}),f.jsx("span",{"aria-live":"polite",className:"max-w-40 truncate",children:N||"未命名模板"})]})]}),f.jsx("div",{className:"flex items-center bg-[#f5f5f5] dark:bg-[#0a0a0a] border border-[#eaeaea] dark:border-[#222222] rounded-lg p-0.5 shadow-inner",children:Vp.map(L=>{const $=u===L.id;return f.jsxs("button",{onClick:()=>r(L.id),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium transition-all ${$?"bg-white dark:bg-[#1f1f1f] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-[#171717] dark:hover:text-[#cccccc] hover:bg-[#eaeaea] dark:hover:bg-[#141414]"}`,children:[f.jsx("span",{className:"hidden xl:inline",children:L.label}),f.jsx("span",{className:`text-[10px] font-mono px-1 py-0.2 rounded ${$?"bg-[#eaeaea] dark:bg-[#333333] text-black dark:text-white font-semibold":"bg-[#e5e5e5] dark:bg-[#181818] text-[#777777] dark:text-[#666666]"}`,children:L.ratioTag})]},L.id)})}),f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsxs("div",{className:"flex items-center bg-[#f5f5f5] dark:bg-[#0a0a0a] border border-[#eaeaea] dark:border-[#222222] rounded-lg p-0.5 text-xs text-[#666666] dark:text-[#888888]",children:[f.jsx("button",{onClick:()=>c(Math.max(.2,Number((s-.05).toFixed(2)))),className:"p-1 hover:text-black dark:hover:text-white rounded hover:bg-[#e8e8e8] dark:hover:bg-[#1f1f1f]",title:"缩小",children:f.jsx(Bp,{className:"w-3.5 h-3.5"})}),f.jsxs("span",{onDoubleClick:d,className:"w-11 text-center font-mono text-[11px] text-[#333333] dark:text-[#cccccc] cursor-pointer hover:underline select-none",title:"双击恢复自适应",children:[Math.round(s*100),"%"]}),f.jsx("button",{onClick:()=>c(Math.min(1.5,Number((s+.05).toFixed(2)))),className:"p-1 hover:text-black dark:hover:text-white rounded hover:bg-[#e8e8e8] dark:hover:bg-[#1f1f1f]",title:"放大",children:f.jsx(kh,{className:"w-3.5 h-3.5"})}),d&&f.jsxs(f.Fragment,{children:[f.jsx("div",{className:"w-[1px] h-3 bg-[#e0e0e0] dark:bg-[#262626] mx-0.5"}),f.jsxs("button",{onClick:d,className:`flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] transition-all ${x?"bg-white dark:bg-[#1f1f1f] text-black dark:text-white shadow-xs font-semibold":"hover:text-black dark:hover:text-white hover:bg-[#e8e8e8] dark:hover:bg-[#1f1f1f]"}`,title:M>1?"缩放至视口内完整排列多张图片(瀑布流平铺)":"自适应画布大小",children:[f.jsx(vp,{className:"w-3 h-3"}),f.jsx("span",{children:M>1?"多图平铺":"自适应"})]})]})]}),f.jsx("button",{onClick:B,className:"p-2 rounded-lg border border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] hover:bg-[#f5f5f5] dark:hover:bg-[#161616] text-[#444444] dark:text-[#cccccc] transition-all btn-vercel",title:Q==="light"?"切换至深色模式":"切换至浅色模式",children:Q==="light"?f.jsx(yp,{className:"w-3.5 h-3.5 text-[#555555]"}):f.jsx(kp,{className:"w-3.5 h-3.5 text-amber-400"})}),f.jsxs("button",{onClick:g,"aria-expanded":v,className:"flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] hover:bg-[#f5f5f5] dark:hover:bg-[#161616] text-xs text-[#333333] dark:text-[#cccccc] hover:text-black dark:hover:text-white transition-all btn-vercel",children:[f.jsx(dp,{className:"w-3.5 h-3.5 text-[#777777] dark:text-[#888888]"}),f.jsx("span",{children:"模板库"})]}),f.jsxs("button",{onClick:m,className:"flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] hover:bg-[#f5f5f5] dark:hover:bg-[#161616] text-xs text-[#333333] dark:text-[#cccccc] transition-all btn-vercel",children:[f.jsx(dh,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"保存模板"})]}),f.jsxs("button",{onClick:p,disabled:b,className:"flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-black text-white hover:bg-[#262626] dark:bg-white dark:text-black dark:hover:bg-[#eaeaea] text-xs font-semibold transition-all btn-vercel shadow-sm disabled:opacity-50",children:[b?f.jsx(ch,{className:"w-3.5 h-3.5 animate-spin"}):f.jsx(op,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:b?"导出中...":"导出图片"}),M>1&&f.jsxs("span",{className:"text-[10px] bg-white/20 dark:bg-black text-white px-1.5 py-0.2 rounded font-mono",children:[M,"P"]})]}),f.jsx("button",{onClick:y,className:`p-1.5 rounded-lg border transition-all btn-vercel ${w?"border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] text-[#777777] dark:text-[#888888] hover:text-black dark:hover:text-white hover:bg-[#f5f5f5] dark:hover:bg-[#161616]":"border-amber-500/50 bg-amber-500/10 text-amber-600 dark:text-amber-400"}`,title:w?"超管密钥已就绪":"配置超管密钥",children:f.jsx(eh,{className:"w-3.5 h-3.5"})})]})]});function Kp(){const[u,r]=fe.useState([]),[s,c]=fe.useState(!1),d=fe.useCallback(async(x=!1)=>{try{c(!0);const g=await fetch(`/api/fonts${x?"?refresh=1":""}`);if(!g.ok)return;const v=await g.json();if(!v.ok||!Array.isArray(v.fonts))return;r(v.fonts);let N=!1;if(typeof window<"u"&&"FontFace"in window&&document.fonts)for(const m of v.fonts)try{let y=!1;const p=[];if(document.fonts.forEach(b=>{(b.family===m.family||b.family===`"${m.family}"`)&&(y=!0,p.push(b))}),x&&(p.forEach(b=>document.fonts.delete(b)),y=!1),!y){const w=await new FontFace(m.family,`url(${m.url}${x?`?v=${Date.now()}`:""})`).load();document.fonts.add(w),N=!0}}catch(y){console.warn(`[useLocalFonts] Failed to load web font ${m.family}:`,y)}N&&window.dispatchEvent(new Event("typeset-fonts-loaded"))}catch(g){console.warn("[useLocalFonts] Failed to fetch local fonts:",g)}finally{c(!1)}},[]);return fe.useEffect(()=>{d()},[d]),{fonts:u,loading:s,refreshFonts:()=>d(!0)}}const mo="w-full rounded border border-[#dfdfdf] dark:border-[#333333] bg-white dark:bg-[#141414] px-2 py-1 text-[11px]";function Jp({config:u,onChange:r}){const s=u.canvasStyle||{},c=s.fill||u.coverTheme?.background.fill||{type:"solid",color:u.theme.bgColor},d=s.pattern||u.coverTheme?.decoration||_p,x=s.border||Rp,g=b=>r({...s,fill:b}),v=b=>r({...s,pattern:{...d,...b}}),N=b=>r({...s,border:{...x,...b}}),m=(b,w,M)=>f.jsxs("label",{className:"flex items-center justify-between gap-2",children:[f.jsx("span",{children:b}),f.jsxs("span",{className:"flex items-center gap-1.5 font-mono",children:[f.jsx("span",{children:w}),f.jsx("input",{"aria-label":b,type:"color",value:w,onChange:Q=>M(Q.target.value),className:"h-6 w-7 cursor-pointer bg-transparent"})]})]}),y=(b,w,M,Q,B,L=1)=>f.jsxs("label",{className:"flex flex-col gap-1",children:[f.jsxs("span",{className:"flex justify-between",children:[f.jsx("span",{children:b}),f.jsx("span",{className:"font-mono",children:L<1?`${Math.round(w*100)}%`:w})]}),f.jsx("input",{"aria-label":b,type:"range",min:M,max:Q,step:L,value:w,onChange:$=>B(Number($.target.value)),className:"w-full accent-emerald-600"})]}),p=b=>{const w=c.type==="solid"?c.color:c.stops[0].color,M=c.type==="solid"?[{color:w,offset:0},{color:u.theme.accentColor,offset:100}]:c.stops;g(b==="solid"?{type:b,color:w}:b==="linear"?{type:b,angle:90,stops:M}:{type:b,position:{x:50,y:30},stops:M})};return f.jsxs("section",{className:"border-b border-[#f0f0f0] dark:border-[#1c1c1c] p-3.5 text-xs",children:[f.jsx("div",{className:"mb-3 font-semibold text-[#171717] dark:text-white",children:"背景、花纹与边框"}),f.jsxs("div",{className:"flex flex-col gap-3 text-[11px] text-[#666666] dark:text-[#aaaaaa]",children:[f.jsxs("label",{className:"flex flex-col gap-1",children:["背景类型",f.jsxs("select",{className:mo,value:c.type,onChange:b=>p(b.target.value),children:[f.jsx("option",{value:"solid",children:"纯色"}),f.jsx("option",{value:"linear",children:"线性渐变"}),f.jsx("option",{value:"radial",children:"径向渐变"})]})]}),c.type==="solid"?m("背景颜色",c.color,b=>g({type:"solid",color:b})):f.jsxs(f.Fragment,{children:[f.jsxs("div",{className:"flex flex-col gap-2 rounded border border-[#eaeaea] dark:border-[#333333] p-2",children:[c.stops.map((b,w)=>f.jsxs("div",{className:"flex flex-col gap-1.5",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsxs("label",{className:"flex flex-1 items-center gap-1.5",children:[f.jsx("input",{"aria-label":`渐变颜色 ${w+1}`,type:"color",value:b.color,onChange:M=>g({...c,stops:c.stops.map((Q,B)=>B===w?{...Q,color:M.target.value}:Q)}),className:"h-6 w-7 bg-transparent"}),f.jsx("span",{className:"font-mono",children:b.color})]}),f.jsx("button",{type:"button",disabled:c.stops.length<=2,onClick:()=>g({...c,stops:c.stops.filter((M,Q)=>Q!==w)}),className:"disabled:opacity-30","aria-label":`删除渐变颜色 ${w+1}`,children:"移除"})]}),y(`节点 ${w+1} 位置`,b.offset,0,100,M=>g({...c,stops:c.stops.map((Q,B)=>B===w?{...Q,offset:M}:Q)}))]},w)),f.jsx("button",{type:"button",disabled:c.stops.length>=8,onClick:()=>g({...c,stops:[...c.stops,{color:u.theme.accentColor,offset:50}]}),className:"rounded border border-[#dfdfdf] dark:border-[#333333] py-1 disabled:opacity-30",children:"添加颜色节点"})]}),c.type==="linear"?y("渐变角度",c.angle,0,360,b=>g({...c,angle:b})):f.jsxs(f.Fragment,{children:[y("渐变中心 X",c.position.x,0,100,b=>g({...c,position:{...c.position,x:b}})),y("渐变中心 Y",c.position.y,0,100,b=>g({...c,position:{...c.position,y:b}}))]})]}),f.jsxs("label",{className:"flex flex-col gap-1",children:["几何花纹",f.jsx("select",{className:mo,value:d.pattern,onChange:b=>v({pattern:b.target.value}),children:Object.entries(Fh).map(([b,w])=>f.jsx("option",{value:b,children:w},b))})]}),d.pattern!=="none"&&f.jsxs(f.Fragment,{children:[m("花纹颜色",d.color,b=>v({color:b})),y("花纹透明度",d.opacity,0,1,b=>v({opacity:b}),.01),y("花纹间距",d.size,16,240,b=>v({size:b}))]}),f.jsxs("label",{className:"flex flex-col gap-1",children:["边框样式",f.jsx("select",{className:mo,value:x.style,onChange:b=>N({style:b.target.value}),children:Object.entries(jh).map(([b,w])=>f.jsx("option",{value:b,children:w},b))})]}),x.style!=="none"&&f.jsxs(f.Fragment,{children:[m("边框颜色",x.color,b=>N({color:b})),x.style==="gradient"&&m("边框渐变终色",x.endColor,b=>N({endColor:b})),y("边框粗细",x.width,1,24,b=>N({width:b})),y("边框内缩",x.inset,0,200,b=>N({inset:b})),x.style!=="corners"&&y("边框圆角",x.radius,0,200,b=>N({radius:b})),y("边框透明度",x.opacity,0,1,b=>N({opacity:b}),.01)]}),f.jsx("p",{className:"leading-relaxed text-[#888888]",children:"配置随模板保存,作用于每页。背景图会覆盖底色与花纹;边框绘制在最上层。"})]})]})}const yx=[{label:"苹方 / 极简黑体 (默认清爽)",value:"PingFang SC"},{label:"思源黑体 (现代极简·粗黑)",value:"Noto Sans SC"},{label:"典雅宋体 (经典报刊·书卷)",value:"Songti SC"},{label:"思源宋体 (高阶报刊·典雅)",value:"Noto Serif SC"},{label:"人文楷体 (温润随笔·手写)",value:"Kaiti SC"},{label:"柔和圆体 (亲和灵动·现代)",value:"Yuanti SC"},{label:"Inter / 国际西文无衬线",value:"Inter"},{label:"Georgia / 文艺西文衬线",value:"Georgia"}],Ip=({config:u,onUpdateAlgorithm:r,onUpdateTheme:s,onUpdateTypography:c,onUpdateSafeArea:d,onUpdateBranding:x,onUpdateChrome:g,onUpdateCanvasStyle:v})=>{const{algorithm:N,theme:m,typography:y}=u,{fonts:p,loading:b,refreshFonts:w}=Kp();return f.jsxs("aside",{className:"w-80 border-l border-[#eaeaea] dark:border-[#222222] bg-white dark:bg-[#0a0a0a] flex flex-col shrink-0 select-none overflow-y-auto transition-colors",children:[f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(rp,{className:"w-3.5 h-3.5 text-blue-500 dark:text-blue-400"}),f.jsx("span",{children:"文字对齐与空间居中"})]}),f.jsxs("div",{className:"flex flex-col gap-3 text-xs",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] text-[11px] block mb-1.5 font-medium",children:"垂直排版对齐 (封面必备)"}),f.jsx("div",{className:"grid grid-cols-3 gap-1 bg-[#f5f5f5] dark:bg-[#141414] p-1 rounded-lg border border-[#e5e5e5] dark:border-[#262626]",children:[{id:"top",label:"顶端对齐"},{id:"center",label:"垂直居中"},{id:"bottom",label:"底端对齐"}].map(M=>f.jsx("button",{onClick:()=>r({verticalAlign:M.id}),className:`py-1 text-[11px] rounded transition-all font-medium ${(N.verticalAlign||"top")===M.id?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:M.label},M.id))})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] text-[11px] block mb-1.5 font-medium",children:"水平排版对齐"}),f.jsxs("div",{className:"grid grid-cols-3 gap-1 bg-[#f5f5f5] dark:bg-[#141414] p-1 rounded-lg border border-[#e5e5e5] dark:border-[#262626]",children:[f.jsxs("button",{onClick:()=>r({textAlign:"left"}),className:`py-1 flex items-center justify-center gap-1 text-[11px] rounded transition-all font-medium ${(N.textAlign||"left")==="left"?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:[f.jsx(jp,{className:"w-3 h-3"}),f.jsx("span",{children:"居左"})]}),f.jsxs("button",{onClick:()=>r({textAlign:"center"}),className:`py-1 flex items-center justify-center gap-1 text-[11px] rounded transition-all font-medium ${N.textAlign==="center"?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:[f.jsx(Fp,{className:"w-3 h-3"}),f.jsx("span",{children:"居中"})]}),f.jsxs("button",{onClick:()=>r({textAlign:"right"}),className:`py-1 flex items-center justify-center gap-1 text-[11px] rounded transition-all font-medium ${N.textAlign==="right"?"bg-white dark:bg-[#262626] text-black dark:text-white shadow-sm font-semibold":"text-[#666666] dark:text-[#888888] hover:text-black dark:hover:text-white"}`,children:[f.jsx(Tp,{className:"w-3 h-3"}),f.jsx("span",{children:"居右"})]})]})]})]})]}),f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center justify-between text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsxs("div",{className:"flex items-center gap-2",children:[f.jsx(Dp,{className:"w-3.5 h-3.5 text-indigo-500 dark:text-indigo-400"}),f.jsx("span",{children:"字体与排版字阶"})]}),f.jsx("button",{onClick:()=>w(),disabled:b,title:"重新扫描 public/fonts 目录",className:"p-1 text-[#888888] hover:text-black dark:hover:text-white rounded hover:bg-[#eaeaea] dark:hover:bg-[#222222] transition-colors",children:f.jsx(ch,{className:`w-3 h-3 ${b?"animate-spin text-blue-500":""}`})})]}),f.jsxs("div",{className:"flex flex-col gap-3 text-xs",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] text-[11px] block mb-1",children:"标题字体 (Heading Font)"}),f.jsxs("select",{value:y.headingFont,onChange:M=>c({headingFont:M.target.value}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded-md px-2 py-1.5 text-black dark:text-white text-xs focus:outline-none",children:[p.length>0&&f.jsx("optgroup",{label:"✨ 项目本地字体 (public/fonts)",children:p.map(M=>f.jsx("option",{value:M.family,children:M.label},`head-local-${M.family}`))}),f.jsx("optgroup",{label:"🌐 系统 / 云端预设",children:yx.map(M=>f.jsx("option",{value:M.value,children:M.label},`head-preset-${M.value}`))})]})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] text-[11px] block mb-1",children:"正文字体 (Body Font)"}),f.jsxs("select",{value:y.bodyFont,onChange:M=>c({bodyFont:M.target.value}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded-md px-2 py-1.5 text-black dark:text-white text-xs focus:outline-none",children:[p.length>0&&f.jsx("optgroup",{label:"✨ 项目本地字体 (public/fonts)",children:p.map(M=>f.jsx("option",{value:M.family,children:M.label},`body-local-${M.family}`))}),f.jsx("optgroup",{label:"🌐 系统 / 云端预设",children:yx.map(M=>f.jsx("option",{value:M.value,children:M.label},`body-preset-${M.value}`))})]})]}),p.length===0?f.jsx("div",{className:"text-[10px] text-[#888888] dark:text-[#666666] flex items-center justify-between pt-1 border-t border-[#f5f5f5] dark:border-[#1a1a1a]",children:f.jsxs("span",{children:["💡 将 .ttf / .otf 放入 ",f.jsx("code",{children:"public/fonts/"})," 即可识别"]})}):f.jsx("div",{className:"text-[10px] text-emerald-600 dark:text-emerald-400 flex items-center justify-between pt-1 border-t border-[#f5f5f5] dark:border-[#1a1a1a]",children:f.jsxs("span",{children:["✨ 已加载 ",p.length," 个项目本地字体"]})})]})]}),f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(wp,{className:"w-3.5 h-3.5 text-blue-500 dark:text-blue-400"}),f.jsx("span",{children:"字号与比例参数"})]}),f.jsxs("div",{className:"flex flex-col gap-3.5 text-xs",children:[f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] dark:text-[#888888] mb-1 font-mono text-[11px]",children:[f.jsx("span",{children:"基准字号 (Base Size)"}),f.jsxs("span",{className:"text-[#171717] dark:text-white font-semibold",children:[N.baseFontSize,"px"]})]}),f.jsx("input",{type:"range",min:"24",max:"96",step:"1",value:N.baseFontSize,onChange:M=>r({baseFontSize:parseInt(M.target.value,10)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded-lg cursor-pointer"})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] dark:text-[#888888] mb-1 font-mono text-[11px]",children:[f.jsx("span",{children:"比例字阶系数 (大标题倍率)"}),f.jsxs("span",{className:"text-[#171717] dark:text-white font-semibold",children:[N.scaleRatio.toFixed(2),"x"]})]}),f.jsx("input",{type:"range",min:"1.15",max:"1.6",step:"0.01",value:N.scaleRatio,onChange:M=>r({scaleRatio:parseFloat(M.target.value)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded-lg cursor-pointer"})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] dark:text-[#888888] mb-1 font-mono text-[11px]",children:[f.jsx("span",{children:"行高舒展倍率"}),f.jsx("span",{className:"text-[#171717] dark:text-white font-semibold",children:N.lineHeightMultiplier.toFixed(2)})]}),f.jsx("input",{type:"range",min:"1.2",max:"1.8",step:"0.02",value:N.lineHeightMultiplier,onChange:M=>r({lineHeightMultiplier:parseFloat(M.target.value)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded-lg cursor-pointer"})]}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex justify-between text-[#666666] dark:text-[#888888] mb-1 font-mono text-[11px]",children:[f.jsx("span",{children:"配图避让间隙 (Gap)"}),f.jsxs("span",{className:"text-[#171717] dark:text-white font-semibold",children:[N.obstacleGap,"px"]})]}),f.jsx("input",{type:"range",min:"12",max:"48",step:"2",value:N.obstacleGap,onChange:M=>r({obstacleGap:parseInt(M.target.value,10)}),className:"w-full h-1.5 bg-[#e5e5e5] dark:bg-[#222222] rounded-lg cursor-pointer"})]})]})]}),f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(Mp,{className:"w-3.5 h-3.5 text-emerald-600 dark:text-emerald-400"}),f.jsx("span",{children:"版心安全边距"})]}),f.jsxs("div",{className:"grid grid-cols-2 gap-2 text-[11px] font-mono",children:[f.jsxs("div",{children:[f.jsx("span",{className:"text-[#777777] dark:text-[#666666] block mb-1",children:"上边距 (Top)"}),f.jsx("input",{type:"number",value:N.safeArea.top,onChange:M=>d({top:parseInt(M.target.value,10)||0}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#777777] dark:text-[#666666] block mb-1",children:"下边距 (Bottom)"}),f.jsx("input",{type:"number",value:N.safeArea.bottom,onChange:M=>d({bottom:parseInt(M.target.value,10)||0}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#777777] dark:text-[#666666] block mb-1",children:"左边距 (Left)"}),f.jsx("input",{type:"number",value:N.safeArea.left,onChange:M=>d({left:parseInt(M.target.value,10)||0}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white"})]}),f.jsxs("div",{children:[f.jsx("span",{className:"text-[#777777] dark:text-[#666666] block mb-1",children:"右边距 (Right)"}),f.jsx("input",{type:"number",value:N.safeArea.right,onChange:M=>d({right:parseInt(M.target.value,10)||0}),className:"w-full bg-[#fafafa] dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white"})]})]})]}),f.jsxs("div",{className:"p-3.5 border-b border-[#f0f0f0] dark:border-[#1c1c1c]",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(Np,{className:"w-3.5 h-3.5 text-purple-600 dark:text-purple-400"}),f.jsx("span",{children:"视觉色彩主题"})]}),f.jsxs("div",{className:"flex flex-col gap-2.5 text-xs",children:[f.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[f.jsx("button",{onClick:()=>s({bgColor:"#ffffff",textColor:"#171717",headingColor:"#171717",accentColor:"#059669",quoteColor:"#525252",cardBg:"#f5f5f5"}),className:"w-6 h-6 rounded-full bg-[#ffffff] border-2 border-emerald-500 shadow-sm hover:scale-105 transition-all",title:"素白雅致 (推荐)"}),f.jsx("button",{onClick:()=>s({bgColor:"#f9fcfa",textColor:"#22201d",headingColor:"#0f2e22",accentColor:"#1d4f39",quoteColor:"#474038",cardBg:"#ffffff"}),className:"w-6 h-6 rounded-full bg-[#f9fcfa] border border-[#ccc] shadow-sm hover:scale-105 transition-all",title:"纸白浅草"}),f.jsx("button",{onClick:()=>s({bgColor:"#0a0a0a",textColor:"#ededed",headingColor:"#ffffff",accentColor:"#00e676",quoteColor:"#a0a0a0",cardBg:"#121212"}),className:"w-6 h-6 rounded-full bg-[#0a0a0a] border border-[#444] shadow-sm hover:scale-105 transition-all",title:"深邃暗夜"}),f.jsx("button",{onClick:()=>s({bgColor:"#09090b",textColor:"#fafafa",headingColor:"#ffffff",accentColor:"#3b82f6",quoteColor:"#a1a1aa",cardBg:"#18181b"}),className:"w-6 h-6 rounded-full bg-[#09090b] border border-blue-500 shadow-sm hover:scale-105 transition-all",title:"数码蓝暗黑"})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888] font-medium",children:"标题颜色 (Heading)"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx("input",{type:"color",value:m.headingColor||m.textColor,onChange:M=>s({headingColor:M.target.value}),className:"w-6 h-6 rounded cursor-pointer bg-transparent border-0"}),f.jsx("span",{className:"font-mono text-[11px] text-[#444444] dark:text-[#cccccc]",children:m.headingColor||m.textColor})]})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888]",children:"正文字色 (Text)"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx("input",{type:"color",value:m.textColor,onChange:M=>s({textColor:M.target.value}),className:"w-6 h-6 rounded cursor-pointer bg-transparent border-0"}),f.jsx("span",{className:"font-mono text-[11px] text-[#444444] dark:text-[#cccccc]",children:m.textColor})]})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888]",children:"重点强调色 (Accent)"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx("input",{type:"color",value:m.accentColor,onChange:M=>s({accentColor:M.target.value}),className:"w-6 h-6 rounded cursor-pointer bg-transparent border-0"}),f.jsx("span",{className:"font-mono text-[11px] text-[#444444] dark:text-[#cccccc]",children:m.accentColor})]})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#666666] dark:text-[#888888]",children:"背景底色 (Canvas)"}),f.jsxs("div",{className:"flex items-center gap-1.5",children:[f.jsx("input",{type:"color",value:u.canvasStyle?.fill?.type==="solid"?u.canvasStyle.fill.color:m.bgColor,onChange:M=>s({bgColor:M.target.value}),className:"w-6 h-6 rounded cursor-pointer bg-transparent border-0"}),f.jsx("span",{className:"font-mono text-[11px] text-[#444444] dark:text-[#cccccc]",children:m.bgColor})]})]})]})]}),f.jsx(Jp,{config:u,onChange:v}),f.jsxs("div",{className:"p-3.5",children:[f.jsxs("div",{className:"flex items-center gap-2 text-xs font-semibold text-[#171717] dark:text-white mb-3",children:[f.jsx(sp,{className:"w-3.5 h-3.5 text-amber-500 dark:text-amber-400"}),f.jsx("span",{children:"页眉页脚与版式装饰 (Chrome)"})]}),f.jsxs("div",{className:"flex flex-col gap-3 text-xs",children:[f.jsxs("div",{className:"bg-[#f9f9f9] dark:bg-[#141414] p-2.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] flex flex-col gap-2",children:[f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"font-semibold text-[#333333] dark:text-[#cccccc] text-[11px]",children:"顶部栏 (Header)"}),f.jsxs("label",{className:"flex items-center gap-1.5 cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showHeader??!!u.watermarkText?.trim(),onChange:M=>g({showHeader:M.target.checked}),className:"rounded text-emerald-500 accent-emerald-500 cursor-pointer"}),f.jsx("span",{className:"text-[10px] text-[#666666] dark:text-[#888888]",children:"启用"})]})]}),(u.chrome?.showHeader??!!u.watermarkText?.trim())&&f.jsxs("div",{className:"flex flex-col gap-2 pl-2 border-l-2 border-[#e0e0e0] dark:border-[#2a2a2a] mt-1",children:[f.jsxs("div",{children:[f.jsxs("div",{className:"flex items-center justify-between mb-1",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"水印 / 品牌标识"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showWatermark??!0,onChange:M=>g({showWatermark:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]}),f.jsx("input",{type:"text",value:u.watermarkText,onChange:M=>x(u.footerText,M.target.value),placeholder:"作者水印/标识文本...",className:"w-full bg-white dark:bg-[#0a0a0a] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white text-[11px]"})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"页码角标 (P.01)"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showPageNumber??u.aspectRatio==="longform-3-4",onChange:M=>g({showPageNumber:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]})]})]}),f.jsxs("div",{className:"bg-[#f9f9f9] dark:bg-[#141414] p-2.5 rounded-lg border border-[#eaeaea] dark:border-[#222222] flex flex-col gap-2",children:[f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"font-semibold text-[#333333] dark:text-[#cccccc] text-[11px]",children:"底部栏 (Footer)"}),f.jsxs("label",{className:"flex items-center gap-1.5 cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showFooter??!!u.footerText?.trim(),onChange:M=>g({showFooter:M.target.checked}),className:"rounded text-emerald-500 accent-emerald-500 cursor-pointer"}),f.jsx("span",{className:"text-[10px] text-[#666666] dark:text-[#888888]",children:"启用"})]})]}),(u.chrome?.showFooter??!!u.footerText?.trim())&&f.jsxs("div",{className:"flex flex-col gap-2 pl-2 border-l-2 border-[#e0e0e0] dark:border-[#2a2a2a] mt-1",children:[f.jsxs("div",{children:[f.jsxs("div",{className:"flex items-center justify-between mb-1",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"页脚署名 / 版权"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showFooterText??!0,onChange:M=>g({showFooterText:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]}),f.jsx("input",{type:"text",value:u.footerText,onChange:M=>x(M.target.value,u.watermarkText),placeholder:"页脚版权/署名...",className:"w-full bg-white dark:bg-[#0a0a0a] border border-[#d4d4d4] dark:border-[#262626] rounded px-2 py-1 text-black dark:text-white text-[11px]"})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"顶部分割细线"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showFooterDivider??!!u.footerText?.trim(),onChange:M=>g({showFooterDivider:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]}),f.jsxs("div",{className:"flex items-center justify-between",children:[f.jsx("span",{className:"text-[#777777] dark:text-[#888888] text-[10px]",children:"算法填充率提示"}),f.jsxs("label",{className:"flex items-center gap-1 text-[10px] text-[#666666] dark:text-[#888888] cursor-pointer",children:[f.jsx("input",{type:"checkbox",checked:u.chrome?.showFillRatio??!1,onChange:M=>g({showFillRatio:M.target.checked}),className:"rounded accent-emerald-500 cursor-pointer"}),f.jsx("span",{children:"显示"})]})]})]})]})]})]})]})},Wp=({isOpen:u,onClose:r,refreshKey:s,onApplyTemplate:c,adminKey:d})=>{const[x,g]=fe.useState([]),[v,N]=fe.useState({}),[m,y]=fe.useState("default"),[p,b]=fe.useState("all"),[w,M]=fe.useState(!1),[Q,B]=fe.useState(null),L=async(H=m)=>{try{const V=await fetch(`/api/templates/slots?account=${encodeURIComponent(H)}`,{headers:{"x-admin-key":d}}),G=await V.json();if(!V.ok||!G.ok)throw new Error(G.message||G.error||"获取槽位失败");G.ok&&G.slots&&N(G.slots)}catch(V){B(V instanceof Error?V.message:"模板请求失败")}},$=async(H,V)=>{try{const G=await fetch("/api/templates/slots",{method:"POST",headers:{"Content-Type":"application/json",...d?{"x-admin-key":d}:{}},body:JSON.stringify({slot:H,templateId:V,account:m})}),S=await G.json();if(!G.ok||!S.ok)throw new Error(S.message||S.error||"设置默认模板失败");S.ok&&await L(m)}catch(G){B(G instanceof Error?G.message:"模板请求失败")}},ee=async()=>{M(!0),B(null);try{const H=await fetch("/api/templates",{headers:d?{"x-admin-key":d}:{}}),V=await H.json();H.ok&&V.ok&&Array.isArray(V.templates)?g(V.templates):B(V.message||"获取模板失败,请检查密钥")}catch{B("连接后端服务失败")}finally{M(!1)}};fe.useEffect(()=>{u&&(ee(),L(m))},[u,m,d,s]),fe.useEffect(()=>{if(!u)return;const H=V=>{V.key==="Escape"&&!document.querySelector("dialog[open]")&&r()};return window.addEventListener("keydown",H),()=>window.removeEventListener("keydown",H)},[u,r]);const ce=async H=>{try{const V=await fetch(`/api/templates/${encodeURIComponent(H)}`,{method:"DELETE",headers:d?{"x-admin-key":d}:{}}),G=await V.json();if(!V.ok||!G.ok)throw new Error(G.message||G.error||"删除模板失败");g(S=>S.filter(q=>q.id!==H)),await L(m)}catch(V){B(V instanceof Error?V.message:"模板请求失败")}};if(!u)return null;const ue=x.filter(H=>p==="all"?!0:H.slot===p);return f.jsxs("aside",{"aria-label":"模板库",className:"absolute inset-y-0 right-0 z-40 w-80 max-w-full bg-white dark:bg-[#0f0f0f] border-l border-[#eaeaea] dark:border-[#262626] flex flex-col shadow-xl overflow-hidden",children:[f.jsxs("div",{className:"flex items-center justify-between px-5 py-3.5 border-b border-[#eaeaea] dark:border-[#222222]",children:[f.jsxs("div",{className:"flex items-center gap-2 font-semibold text-sm text-[#171717] dark:text-white",children:[f.jsx(So,{className:"w-4 h-4 text-emerald-500 dark:text-emerald-400"}),f.jsx("span",{children:"模板库"})]}),f.jsx("button",{onClick:r,"aria-label":"关闭模板库",className:"text-[#888888] hover:text-black dark:hover:text-white p-1 rounded-md hover:bg-[#f5f5f5] dark:hover:bg-[#1a1a1a]",children:f.jsx(jo,{className:"w-4 h-4"})})]}),f.jsxs("div",{className:"p-3 flex-1 min-h-0 flex flex-col gap-4 overflow-y-auto",children:[Q&&f.jsx("div",{role:"alert",className:"text-xs text-red-500 bg-red-500/10 p-2 rounded border border-red-500/20",children:Q}),f.jsxs("div",{className:"flex flex-col gap-2",children:[f.jsx("div",{className:"flex items-center justify-between text-xs",children:f.jsxs("div",{className:"flex items-center gap-1.5 font-medium text-[#666666] dark:text-[#888888]",children:[f.jsx("span",{children:"槽位账号:"}),f.jsxs("select",{value:m,onChange:H=>y(H.target.value),className:"bg-white dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#2a2a2a] rounded px-2 py-0.5 text-xs text-black dark:text-white focus:outline-none font-mono",children:[f.jsx("option",{value:"default",children:"default (主账号)"}),f.jsx("option",{value:"ancientone",children:"ancientone"})]})]})}),f.jsxs("div",{className:"flex flex-wrap items-center gap-1 text-xs",children:[f.jsx("button",{onClick:()=>b("all"),className:`px-2.5 py-1 rounded text-xs transition-colors font-medium ${p==="all"?"bg-black text-white dark:bg-white dark:text-black":"text-[#666666] dark:text-[#888888] hover:bg-[#f5f5f5] dark:hover:bg-[#1c1c1c]"}`,children:"全部"}),f.jsx("button",{onClick:()=>b("article_cover"),className:`px-2.5 py-1 rounded text-xs transition-colors font-medium ${p==="article_cover"?"bg-black text-white dark:bg-white dark:text-black":"text-[#666666] dark:text-[#888888] hover:bg-[#f5f5f5] dark:hover:bg-[#1c1c1c]"}`,children:"文章封面"}),f.jsx("button",{onClick:()=>b("newspic_cover"),className:`px-2.5 py-1 rounded text-xs transition-colors font-medium ${p==="newspic_cover"?"bg-black text-white dark:bg-white dark:text-black":"text-[#666666] dark:text-[#888888] hover:bg-[#f5f5f5] dark:hover:bg-[#1c1c1c]"}`,children:"贴图封面"}),f.jsx("button",{onClick:()=>b("newspic_content"),className:`px-2.5 py-1 rounded text-xs transition-colors font-medium ${p==="newspic_content"?"bg-black text-white dark:bg-white dark:text-black":"text-[#666666] dark:text-[#888888] hover:bg-[#f5f5f5] dark:hover:bg-[#1c1c1c]"}`,children:"贴图内容"})]})]}),f.jsx("div",{className:"flex flex-col gap-2",children:w?f.jsx("div",{className:"text-center py-8 text-xs text-[#888888] dark:text-[#555555]",children:"正在加载模板..."}):ue.length===0?f.jsx("div",{className:"text-center py-8 text-xs text-[#888888] dark:text-[#555555]",children:"暂无匹配模板"}):ue.map(H=>{const V=v.article_cover?.id===H.id,G=v.newspic_cover?.id===H.id,S=v.newspic_content?.id===H.id;return f.jsxs("div",{className:"flex flex-col justify-between p-3 rounded-lg bg-[#fafafa] dark:bg-[#141414] border border-[#eaeaea] dark:border-[#222222] hover:border-[#cccccc] dark:hover:border-[#333333] transition-all gap-2 group",children:[f.jsxs("div",{className:"flex items-center gap-3",children:[f.jsx("div",{className:"w-5 h-5 rounded border border-[#d4d4d4] dark:border-[#333333] shrink-0",style:{backgroundColor:H.theme.bgColor}}),f.jsxs("div",{children:[f.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[f.jsx("span",{className:"text-xs font-semibold text-[#171717] dark:text-white",children:H.name}),H.slot&&f.jsx("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-blue-500/10 text-blue-600 dark:text-blue-400 border border-blue-500/20 font-medium",children:H.slot==="article_cover"?"文章封面":H.slot==="newspic_cover"?"贴图封面":"贴图内容"}),V&&f.jsxs("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-amber-500/10 text-amber-600 dark:text-amber-400 border border-amber-500/20 font-medium flex items-center gap-0.5",children:[f.jsx(ho,{className:"w-2.5 h-2.5 fill-amber-500"})," 文章封面默认"]}),G&&f.jsxs("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-amber-500/10 text-amber-600 dark:text-amber-400 border border-amber-500/20 font-medium flex items-center gap-0.5",children:[f.jsx(ho,{className:"w-2.5 h-2.5 fill-amber-500"})," 贴图封面默认"]}),S&&f.jsxs("span",{className:"text-[10px] px-1.5 py-0.2 rounded bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border border-emerald-500/20 font-medium flex items-center gap-0.5",children:[f.jsx(ho,{className:"w-2.5 h-2.5 fill-emerald-500"})," 贴图内容默认"]})]}),f.jsxs("div",{className:"text-[10px] text-[#888888] dark:text-[#666666] font-mono mt-0.5",children:[H.aspectRatio," • 字号: ",H.algorithm.baseFontSize,"px",H.images&&H.images.length>0&&` • 配图: ${H.images.length}个`]})]})]}),f.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[H.id&&f.jsxs("select",{value:"",onChange:q=>{q.target.value&&$(q.target.value,H.id)},className:"text-[11px] bg-white dark:bg-[#1a1a1a] border border-[#d4d4d4] dark:border-[#333333] text-[#666666] dark:text-[#aaaaaa] rounded px-2 py-1 focus:outline-none",title:"为此账号设为某个槽位的默认模板",children:[f.jsx("option",{value:"",children:"设为槽位默认..."}),f.jsx("option",{value:"article_cover",children:"设为「文章封面默认」"}),f.jsx("option",{value:"newspic_cover",children:"设为「贴图封面默认」"}),f.jsx("option",{value:"newspic_content",children:"设为「贴图内容默认」"})]}),f.jsxs("button",{onClick:()=>{c(H)},className:"flex items-center gap-1 px-2.5 py-1 bg-white dark:bg-[#1f1f1f] hover:bg-emerald-50 dark:hover:bg-emerald-500/20 text-[#333333] dark:text-[#cccccc] hover:text-emerald-700 dark:hover:text-emerald-400 border border-[#d4d4d4] dark:border-[#2a2a2a] hover:border-emerald-500/40 rounded text-xs transition-all font-medium",children:[f.jsx(Qx,{className:"w-3 h-3"}),f.jsx("span",{children:"套用"})]}),H.id&&!H.id.startsWith("tpl_wechat_")&&!H.id.startsWith("tpl_longform_")&&!H.id.startsWith("tpl_square_")&&!H.id.startsWith("tpl_wide_")&&f.jsx("button",{onClick:()=>ce(H.id),className:"p-1 text-[#888888] dark:text-[#555555] hover:text-red-500 rounded hover:bg-[#f0f0f0] dark:hover:bg-[#1f1f1f]",title:"删除自定义模板",children:f.jsx(Eh,{className:"w-3.5 h-3.5"})})]})]},H.id)})})]})]})};function Cr(u=[]){if(!Array.isArray(u))throw new RangeError("模板图片必须是数组");const r=new Set;for(const s of u){if(!s||typeof s!="object")throw new RangeError("无效的模板图片");if(s.templateAssetKey===void 0)continue;const c=s.templateAssetKey;if(s.repeatEveryPage!==void 0&&typeof s.repeatEveryPage!="boolean")throw new RangeError(`素材 ${c} 的每页重复开关必须是布尔值`);if(typeof c!="string"||!/^[a-zA-Z0-9_-]+$/.test(c))throw new RangeError("素材标识只能包含字母、数字、下划线和短横线");if(s.repeatEveryPage&&!s.isAbsolute)throw new RangeError(`素材 ${c} 的每页重复仅支持自由定位模式`);if(r.has(c))throw new RangeError(`重复的模板素材标识:${c}`);r.add(c)}}function $p(u,r=[],s={}){if(Cr(r),!s||typeof s!="object"||Array.isArray(s))throw new RangeError("素材替换必须是标识到图片地址的映射");const c=r.filter(v=>v.templateAssetKey);for(const[v,N]of Object.entries(s)){if(!c.some(m=>m.templateAssetKey===v))throw new RangeError(`未知模板素材:${v}`);if(typeof N!="string"||!N.trim())throw new RangeError(`素材 ${v} 的替换图片不能为空`)}const d=u.filter(v=>!v.templateAssetKey),x=r.filter(v=>!v.templateAssetKey);return[...d.length===0?x.map(v=>({...v,id:`img_${crypto.randomUUID()}`})):d.map((v,N)=>{const m=x[N];return m?{...v,layoutPreset:m.layoutPreset??v.layoutPreset,isAbsolute:m.isAbsolute??v.isAbsolute,x:m.x??v.x,y:m.y??v.y,width:m.width??v.width,height:m.height??v.height,rotate:m.rotate??v.rotate,opacity:m.opacity??v.opacity,zIndex:m.zIndex??v.zIndex,borderRadius:m.borderRadius??v.borderRadius,captionHeight:m.captionHeight??v.captionHeight,pageIndex:m.pageIndex??v.pageIndex}:v}),...c.map(v=>({...v,src:Object.hasOwn(s,v.templateAssetKey)?s[v.templateAssetKey]:v.src}))]}const Pp=({isOpen:u,onClose:r,currentConfig:s,onSaved:c,adminKey:d})=>{const x=fe.useRef(null),[g,v]=fe.useState(""),[N,m]=fe.useState("none"),[y,p]=fe.useState(!1),[b,w]=fe.useState(null);fe.useEffect(()=>{u?(v(s.name||"我的自定义模板"),m(s.slot||(s.aspectRatio==="wechat-cover-2.35"?"article_cover":"newspic_content")),w(null),x.current?.showModal()):x.current?.close()},[u]);const M=async Q=>{if(Q.preventDefault(),!(!g.trim()||y)){p(!0),w(null);try{Cr(s.images);const B=await fetch("/api/templates",{method:"POST",headers:{"Content-Type":"application/json",...d?{"x-admin-key":d}:{}},body:JSON.stringify({...s,id:void 0,name:g.trim(),slot:N==="none"?void 0:N})}),L=await B.json();if(!B.ok||!L.ok)throw new Error(L.message||L.error||"保存模板失败");c(L.template),r()}catch(B){w(B instanceof Error?B.message:"保存模板请求异常")}finally{p(!1)}}};return f.jsx("dialog",{ref:x,"aria-labelledby":"save-template-title",onCancel:Q=>{Q.preventDefault(),y||r()},className:"m-auto w-[calc(100%-2rem)] max-w-sm p-0 rounded-xl border border-[#eaeaea] dark:border-[#262626] bg-white dark:bg-[#0f0f0f] text-[#171717] dark:text-white shadow-2xl backdrop:bg-black/40",children:f.jsxs("form",{onSubmit:M,children:[f.jsxs("div",{className:"flex items-center justify-between px-5 py-3.5 border-b border-[#eaeaea] dark:border-[#222222]",children:[f.jsx("h2",{id:"save-template-title",className:"text-sm font-semibold",children:"保存模板"}),f.jsx("button",{type:"button",onClick:r,disabled:y,"aria-label":"关闭保存模板",className:"p-1 rounded hover:bg-black/5 dark:hover:bg-white/10 disabled:opacity-50",children:f.jsx(jo,{className:"w-4 h-4"})})]}),f.jsxs("div",{className:"p-5 flex flex-col gap-4",children:[f.jsxs("label",{className:"flex flex-col gap-2 text-xs",children:["模板名称",f.jsx("input",{autoFocus:!0,required:!0,value:g,onChange:Q=>v(Q.target.value),placeholder:"输入模板名称",className:"bg-transparent border border-[#d4d4d4] dark:border-[#333333] rounded px-3 py-2 focus:outline-none focus:border-emerald-500"})]}),f.jsxs("label",{className:"flex flex-col gap-2 text-xs",children:["保存到槽位",f.jsxs("select",{value:N,onChange:Q=>m(Q.target.value),className:"bg-white dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#333333] rounded px-3 py-2",children:[f.jsx("option",{value:"article_cover",children:"文章封面 (3.35:1)"}),f.jsx("option",{value:"newspic_cover",children:"贴图封面 (3:4)"}),f.jsx("option",{value:"newspic_content",children:"贴图内容 (3:4)"}),f.jsx("option",{value:"none",children:"通用模板"})]})]}),b&&f.jsx("p",{role:"alert",className:"text-xs text-red-500",children:b}),f.jsxs("button",{type:"submit",disabled:y||!g.trim(),className:"flex items-center justify-center gap-2 px-3 py-2 rounded bg-black text-white dark:bg-white dark:text-black text-xs font-semibold disabled:opacity-50",children:[f.jsx(dh,{className:"w-3.5 h-3.5"}),y?"保存中...":"保存模板"]})]})]})})},go="typeset_studio_admin_key";function eb(){const[u,r]=fe.useState(()=>localStorage.getItem(go)||""),[s,c]=fe.useState(null),[d,x]=fe.useState(!1),g=async N=>{if(!N)return c(!1),!1;x(!0);try{const p=!!(await(await fetch("/api/auth/verify",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:N})})).json()).ok;return c(p),p}catch{return c(!1),!1}finally{x(!1)}},v=N=>{localStorage.setItem(go,N),r(N),g(N)};return fe.useEffect(()=>{(async()=>{let m=u;if(!m)try{const p=await(await fetch("/api/auth/current-key")).json();p.ok&&p.key&&(m=p.key,r(p.key),localStorage.setItem(go,p.key))}catch{}m?g(m):c(!1)})()},[]),{adminKey:u,setAdminKey:v,isVerified:s,isVerifying:d,verifyKey:g}}const tb=["BN","BN","BN","BN","BN","BN","BN","BN","BN","S","B","S","WS","B","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","B","B","B","S","WS","ON","ON","ET","ET","ET","ON","ON","ON","ON","ON","ES","CS","ES","CS","CS","EN","EN","EN","EN","EN","EN","EN","EN","EN","EN","CS","ON","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","ON","ON","ON","BN","BN","BN","BN","BN","BN","B","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","CS","ON","ET","ET","ET","ET","ON","ON","ON","ON","L","ON","ON","BN","ON","ON","ET","ET","EN","EN","ON","L","ON","ON","ON","EN","L","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","L","L","L","L","L","L","L","L"],Nx=[[697,698,"ON"],[706,719,"ON"],[722,735,"ON"],[741,749,"ON"],[751,767,"ON"],[768,879,"NSM"],[884,885,"ON"],[894,894,"ON"],[900,901,"ON"],[903,903,"ON"],[1014,1014,"ON"],[1155,1161,"NSM"],[1418,1418,"ON"],[1421,1422,"ON"],[1423,1423,"ET"],[1424,1424,"R"],[1425,1469,"NSM"],[1470,1470,"R"],[1471,1471,"NSM"],[1472,1472,"R"],[1473,1474,"NSM"],[1475,1475,"R"],[1476,1477,"NSM"],[1478,1478,"R"],[1479,1479,"NSM"],[1480,1535,"R"],[1536,1541,"AN"],[1542,1543,"ON"],[1544,1544,"AL"],[1545,1546,"ET"],[1547,1547,"AL"],[1548,1548,"CS"],[1549,1549,"AL"],[1550,1551,"ON"],[1552,1562,"NSM"],[1563,1610,"AL"],[1611,1631,"NSM"],[1632,1641,"AN"],[1642,1642,"ET"],[1643,1644,"AN"],[1645,1647,"AL"],[1648,1648,"NSM"],[1649,1749,"AL"],[1750,1756,"NSM"],[1757,1757,"AN"],[1758,1758,"ON"],[1759,1764,"NSM"],[1765,1766,"AL"],[1767,1768,"NSM"],[1769,1769,"ON"],[1770,1773,"NSM"],[1774,1775,"AL"],[1776,1785,"EN"],[1786,1808,"AL"],[1809,1809,"NSM"],[1810,1839,"AL"],[1840,1866,"NSM"],[1867,1957,"AL"],[1958,1968,"NSM"],[1969,1983,"AL"],[1984,2026,"R"],[2027,2035,"NSM"],[2036,2037,"R"],[2038,2041,"ON"],[2042,2044,"R"],[2045,2045,"NSM"],[2046,2069,"R"],[2070,2073,"NSM"],[2074,2074,"R"],[2075,2083,"NSM"],[2084,2084,"R"],[2085,2087,"NSM"],[2088,2088,"R"],[2089,2093,"NSM"],[2094,2136,"R"],[2137,2139,"NSM"],[2140,2143,"R"],[2144,2191,"AL"],[2192,2193,"AN"],[2194,2198,"AL"],[2199,2207,"NSM"],[2208,2249,"AL"],[2250,2273,"NSM"],[2274,2274,"AN"],[2275,2306,"NSM"],[2362,2362,"NSM"],[2364,2364,"NSM"],[2369,2376,"NSM"],[2381,2381,"NSM"],[2385,2391,"NSM"],[2402,2403,"NSM"],[2433,2433,"NSM"],[2492,2492,"NSM"],[2497,2500,"NSM"],[2509,2509,"NSM"],[2530,2531,"NSM"],[2546,2547,"ET"],[2555,2555,"ET"],[2558,2558,"NSM"],[2561,2562,"NSM"],[2620,2620,"NSM"],[2625,2626,"NSM"],[2631,2632,"NSM"],[2635,2637,"NSM"],[2641,2641,"NSM"],[2672,2673,"NSM"],[2677,2677,"NSM"],[2689,2690,"NSM"],[2748,2748,"NSM"],[2753,2757,"NSM"],[2759,2760,"NSM"],[2765,2765,"NSM"],[2786,2787,"NSM"],[2801,2801,"ET"],[2810,2815,"NSM"],[2817,2817,"NSM"],[2876,2876,"NSM"],[2879,2879,"NSM"],[2881,2884,"NSM"],[2893,2893,"NSM"],[2901,2902,"NSM"],[2914,2915,"NSM"],[2946,2946,"NSM"],[3008,3008,"NSM"],[3021,3021,"NSM"],[3059,3064,"ON"],[3065,3065,"ET"],[3066,3066,"ON"],[3072,3072,"NSM"],[3076,3076,"NSM"],[3132,3132,"NSM"],[3134,3136,"NSM"],[3142,3144,"NSM"],[3146,3149,"NSM"],[3157,3158,"NSM"],[3170,3171,"NSM"],[3192,3198,"ON"],[3201,3201,"NSM"],[3260,3260,"NSM"],[3276,3277,"NSM"],[3298,3299,"NSM"],[3328,3329,"NSM"],[3387,3388,"NSM"],[3393,3396,"NSM"],[3405,3405,"NSM"],[3426,3427,"NSM"],[3457,3457,"NSM"],[3530,3530,"NSM"],[3538,3540,"NSM"],[3542,3542,"NSM"],[3633,3633,"NSM"],[3636,3642,"NSM"],[3647,3647,"ET"],[3655,3662,"NSM"],[3761,3761,"NSM"],[3764,3772,"NSM"],[3784,3790,"NSM"],[3864,3865,"NSM"],[3893,3893,"NSM"],[3895,3895,"NSM"],[3897,3897,"NSM"],[3898,3901,"ON"],[3953,3966,"NSM"],[3968,3972,"NSM"],[3974,3975,"NSM"],[3981,3991,"NSM"],[3993,4028,"NSM"],[4038,4038,"NSM"],[4141,4144,"NSM"],[4146,4151,"NSM"],[4153,4154,"NSM"],[4157,4158,"NSM"],[4184,4185,"NSM"],[4190,4192,"NSM"],[4209,4212,"NSM"],[4226,4226,"NSM"],[4229,4230,"NSM"],[4237,4237,"NSM"],[4253,4253,"NSM"],[4957,4959,"NSM"],[5008,5017,"ON"],[5120,5120,"ON"],[5760,5760,"WS"],[5787,5788,"ON"],[5906,5908,"NSM"],[5938,5939,"NSM"],[5970,5971,"NSM"],[6002,6003,"NSM"],[6068,6069,"NSM"],[6071,6077,"NSM"],[6086,6086,"NSM"],[6089,6099,"NSM"],[6107,6107,"ET"],[6109,6109,"NSM"],[6128,6137,"ON"],[6144,6154,"ON"],[6155,6157,"NSM"],[6158,6158,"BN"],[6159,6159,"NSM"],[6277,6278,"NSM"],[6313,6313,"NSM"],[6432,6434,"NSM"],[6439,6440,"NSM"],[6450,6450,"NSM"],[6457,6459,"NSM"],[6464,6464,"ON"],[6468,6469,"ON"],[6622,6655,"ON"],[6679,6680,"NSM"],[6683,6683,"NSM"],[6742,6742,"NSM"],[6744,6750,"NSM"],[6752,6752,"NSM"],[6754,6754,"NSM"],[6757,6764,"NSM"],[6771,6780,"NSM"],[6783,6783,"NSM"],[6832,6877,"NSM"],[6880,6891,"NSM"],[6912,6915,"NSM"],[6964,6964,"NSM"],[6966,6970,"NSM"],[6972,6972,"NSM"],[6978,6978,"NSM"],[7019,7027,"NSM"],[7040,7041,"NSM"],[7074,7077,"NSM"],[7080,7081,"NSM"],[7083,7085,"NSM"],[7142,7142,"NSM"],[7144,7145,"NSM"],[7149,7149,"NSM"],[7151,7153,"NSM"],[7212,7219,"NSM"],[7222,7223,"NSM"],[7376,7378,"NSM"],[7380,7392,"NSM"],[7394,7400,"NSM"],[7405,7405,"NSM"],[7412,7412,"NSM"],[7416,7417,"NSM"],[7616,7679,"NSM"],[8125,8125,"ON"],[8127,8129,"ON"],[8141,8143,"ON"],[8157,8159,"ON"],[8173,8175,"ON"],[8189,8190,"ON"],[8192,8202,"WS"],[8203,8205,"BN"],[8207,8207,"R"],[8208,8231,"ON"],[8232,8232,"WS"],[8233,8233,"B"],[8234,8238,"BN"],[8239,8239,"CS"],[8240,8244,"ET"],[8245,8259,"ON"],[8260,8260,"CS"],[8261,8286,"ON"],[8287,8287,"WS"],[8288,8303,"BN"],[8304,8304,"EN"],[8308,8313,"EN"],[8314,8315,"ES"],[8316,8318,"ON"],[8320,8329,"EN"],[8330,8331,"ES"],[8332,8334,"ON"],[8352,8399,"ET"],[8400,8432,"NSM"],[8448,8449,"ON"],[8451,8454,"ON"],[8456,8457,"ON"],[8468,8468,"ON"],[8470,8472,"ON"],[8478,8483,"ON"],[8485,8485,"ON"],[8487,8487,"ON"],[8489,8489,"ON"],[8494,8494,"ET"],[8506,8507,"ON"],[8512,8516,"ON"],[8522,8525,"ON"],[8528,8543,"ON"],[8585,8587,"ON"],[8592,8721,"ON"],[8722,8722,"ES"],[8723,8723,"ET"],[8724,9013,"ON"],[9083,9108,"ON"],[9110,9257,"ON"],[9280,9290,"ON"],[9312,9351,"ON"],[9352,9371,"EN"],[9450,9899,"ON"],[9901,10239,"ON"],[10496,11123,"ON"],[11126,11263,"ON"],[11493,11498,"ON"],[11503,11505,"NSM"],[11513,11519,"ON"],[11647,11647,"NSM"],[11744,11775,"NSM"],[11776,11869,"ON"],[11904,11929,"ON"],[11931,12019,"ON"],[12032,12245,"ON"],[12272,12287,"ON"],[12288,12288,"WS"],[12289,12292,"ON"],[12296,12320,"ON"],[12330,12333,"NSM"],[12336,12336,"ON"],[12342,12343,"ON"],[12349,12351,"ON"],[12441,12442,"NSM"],[12443,12444,"ON"],[12448,12448,"ON"],[12539,12539,"ON"],[12736,12773,"ON"],[12783,12783,"ON"],[12829,12830,"ON"],[12880,12895,"ON"],[12924,12926,"ON"],[12977,12991,"ON"],[13004,13007,"ON"],[13175,13178,"ON"],[13278,13279,"ON"],[13311,13311,"ON"],[19904,19967,"ON"],[42128,42182,"ON"],[42509,42511,"ON"],[42607,42610,"NSM"],[42611,42611,"ON"],[42612,42621,"NSM"],[42622,42623,"ON"],[42654,42655,"NSM"],[42736,42737,"NSM"],[42752,42785,"ON"],[42888,42888,"ON"],[43010,43010,"NSM"],[43014,43014,"NSM"],[43019,43019,"NSM"],[43045,43046,"NSM"],[43048,43051,"ON"],[43052,43052,"NSM"],[43064,43065,"ET"],[43124,43127,"ON"],[43204,43205,"NSM"],[43232,43249,"NSM"],[43263,43263,"NSM"],[43302,43309,"NSM"],[43335,43345,"NSM"],[43392,43394,"NSM"],[43443,43443,"NSM"],[43446,43449,"NSM"],[43452,43453,"NSM"],[43493,43493,"NSM"],[43561,43566,"NSM"],[43569,43570,"NSM"],[43573,43574,"NSM"],[43587,43587,"NSM"],[43596,43596,"NSM"],[43644,43644,"NSM"],[43696,43696,"NSM"],[43698,43700,"NSM"],[43703,43704,"NSM"],[43710,43711,"NSM"],[43713,43713,"NSM"],[43756,43757,"NSM"],[43766,43766,"NSM"],[43882,43883,"ON"],[44005,44005,"NSM"],[44008,44008,"NSM"],[44013,44013,"NSM"],[64285,64285,"R"],[64286,64286,"NSM"],[64287,64296,"R"],[64297,64297,"ES"],[64298,64335,"R"],[64336,64450,"AL"],[64451,64466,"ON"],[64467,64829,"AL"],[64830,64847,"ON"],[64848,64911,"AL"],[64912,64913,"ON"],[64914,64967,"AL"],[64968,64975,"ON"],[64976,65007,"BN"],[65008,65020,"AL"],[65021,65023,"ON"],[65024,65039,"NSM"],[65040,65049,"ON"],[65056,65071,"NSM"],[65072,65103,"ON"],[65104,65104,"CS"],[65105,65105,"ON"],[65106,65106,"CS"],[65108,65108,"ON"],[65109,65109,"CS"],[65110,65118,"ON"],[65119,65119,"ET"],[65120,65121,"ON"],[65122,65123,"ES"],[65124,65126,"ON"],[65128,65128,"ON"],[65129,65130,"ET"],[65131,65131,"ON"],[65136,65278,"AL"],[65279,65279,"BN"],[65281,65282,"ON"],[65283,65285,"ET"],[65286,65290,"ON"],[65291,65291,"ES"],[65292,65292,"CS"],[65293,65293,"ES"],[65294,65295,"CS"],[65296,65305,"EN"],[65306,65306,"CS"],[65307,65312,"ON"],[65339,65344,"ON"],[65371,65381,"ON"],[65504,65505,"ET"],[65506,65508,"ON"],[65509,65510,"ET"],[65512,65518,"ON"],[65520,65528,"BN"],[65529,65533,"ON"],[65534,65535,"BN"],[65793,65793,"ON"],[65856,65932,"ON"],[65936,65948,"ON"],[65952,65952,"ON"],[66045,66045,"NSM"],[66272,66272,"NSM"],[66273,66299,"EN"],[66422,66426,"NSM"],[67584,67870,"R"],[67871,67871,"ON"],[67872,68096,"R"],[68097,68099,"NSM"],[68100,68100,"R"],[68101,68102,"NSM"],[68103,68107,"R"],[68108,68111,"NSM"],[68112,68151,"R"],[68152,68154,"NSM"],[68155,68158,"R"],[68159,68159,"NSM"],[68160,68324,"R"],[68325,68326,"NSM"],[68327,68408,"R"],[68409,68415,"ON"],[68416,68863,"R"],[68864,68899,"AL"],[68900,68903,"NSM"],[68904,68911,"AL"],[68912,68921,"AN"],[68922,68927,"AL"],[68928,68937,"AN"],[68938,68968,"R"],[68969,68973,"NSM"],[68974,68974,"ON"],[68975,69215,"R"],[69216,69246,"AN"],[69247,69290,"R"],[69291,69292,"NSM"],[69293,69311,"R"],[69312,69327,"AL"],[69328,69336,"ON"],[69337,69369,"AL"],[69370,69375,"NSM"],[69376,69423,"R"],[69424,69445,"AL"],[69446,69456,"NSM"],[69457,69487,"AL"],[69488,69505,"R"],[69506,69509,"NSM"],[69510,69631,"R"],[69633,69633,"NSM"],[69688,69702,"NSM"],[69714,69733,"ON"],[69744,69744,"NSM"],[69747,69748,"NSM"],[69759,69761,"NSM"],[69811,69814,"NSM"],[69817,69818,"NSM"],[69826,69826,"NSM"],[69888,69890,"NSM"],[69927,69931,"NSM"],[69933,69940,"NSM"],[70003,70003,"NSM"],[70016,70017,"NSM"],[70070,70078,"NSM"],[70089,70092,"NSM"],[70095,70095,"NSM"],[70191,70193,"NSM"],[70196,70196,"NSM"],[70198,70199,"NSM"],[70206,70206,"NSM"],[70209,70209,"NSM"],[70367,70367,"NSM"],[70371,70378,"NSM"],[70400,70401,"NSM"],[70459,70460,"NSM"],[70464,70464,"NSM"],[70502,70508,"NSM"],[70512,70516,"NSM"],[70587,70592,"NSM"],[70606,70606,"NSM"],[70608,70608,"NSM"],[70610,70610,"NSM"],[70625,70626,"NSM"],[70712,70719,"NSM"],[70722,70724,"NSM"],[70726,70726,"NSM"],[70750,70750,"NSM"],[70835,70840,"NSM"],[70842,70842,"NSM"],[70847,70848,"NSM"],[70850,70851,"NSM"],[71090,71093,"NSM"],[71100,71101,"NSM"],[71103,71104,"NSM"],[71132,71133,"NSM"],[71219,71226,"NSM"],[71229,71229,"NSM"],[71231,71232,"NSM"],[71264,71276,"ON"],[71339,71339,"NSM"],[71341,71341,"NSM"],[71344,71349,"NSM"],[71351,71351,"NSM"],[71453,71453,"NSM"],[71455,71455,"NSM"],[71458,71461,"NSM"],[71463,71467,"NSM"],[71727,71735,"NSM"],[71737,71738,"NSM"],[71995,71996,"NSM"],[71998,71998,"NSM"],[72003,72003,"NSM"],[72148,72151,"NSM"],[72154,72155,"NSM"],[72160,72160,"NSM"],[72193,72198,"NSM"],[72201,72202,"NSM"],[72243,72248,"NSM"],[72251,72254,"NSM"],[72263,72263,"NSM"],[72273,72278,"NSM"],[72281,72283,"NSM"],[72330,72342,"NSM"],[72344,72345,"NSM"],[72544,72544,"NSM"],[72546,72548,"NSM"],[72550,72550,"NSM"],[72752,72758,"NSM"],[72760,72765,"NSM"],[72850,72871,"NSM"],[72874,72880,"NSM"],[72882,72883,"NSM"],[72885,72886,"NSM"],[73009,73014,"NSM"],[73018,73018,"NSM"],[73020,73021,"NSM"],[73023,73029,"NSM"],[73031,73031,"NSM"],[73104,73105,"NSM"],[73109,73109,"NSM"],[73111,73111,"NSM"],[73459,73460,"NSM"],[73472,73473,"NSM"],[73526,73530,"NSM"],[73536,73536,"NSM"],[73538,73538,"NSM"],[73562,73562,"NSM"],[73685,73692,"ON"],[73693,73696,"ET"],[73697,73713,"ON"],[78912,78912,"NSM"],[78919,78933,"NSM"],[90398,90409,"NSM"],[90413,90415,"NSM"],[92912,92916,"NSM"],[92976,92982,"NSM"],[94031,94031,"NSM"],[94095,94098,"NSM"],[94178,94178,"ON"],[94180,94180,"NSM"],[113821,113822,"NSM"],[113824,113827,"BN"],[117760,117973,"ON"],[118e3,118009,"EN"],[118010,118012,"ON"],[118016,118451,"ON"],[118458,118480,"ON"],[118496,118512,"ON"],[118528,118573,"NSM"],[118576,118598,"NSM"],[119143,119145,"NSM"],[119155,119162,"BN"],[119163,119170,"NSM"],[119173,119179,"NSM"],[119210,119213,"NSM"],[119273,119274,"ON"],[119296,119361,"ON"],[119362,119364,"NSM"],[119365,119365,"ON"],[119552,119638,"ON"],[120513,120513,"ON"],[120539,120539,"ON"],[120571,120571,"ON"],[120597,120597,"ON"],[120629,120629,"ON"],[120655,120655,"ON"],[120687,120687,"ON"],[120713,120713,"ON"],[120745,120745,"ON"],[120771,120771,"ON"],[120782,120831,"EN"],[121344,121398,"NSM"],[121403,121452,"NSM"],[121461,121461,"NSM"],[121476,121476,"NSM"],[121499,121503,"NSM"],[121505,121519,"NSM"],[122880,122886,"NSM"],[122888,122904,"NSM"],[122907,122913,"NSM"],[122915,122916,"NSM"],[122918,122922,"NSM"],[123023,123023,"NSM"],[123184,123190,"NSM"],[123566,123566,"NSM"],[123628,123631,"NSM"],[123647,123647,"ET"],[124140,124143,"NSM"],[124398,124399,"NSM"],[124643,124643,"NSM"],[124646,124646,"NSM"],[124654,124655,"NSM"],[124661,124661,"NSM"],[124928,125135,"R"],[125136,125142,"NSM"],[125143,125251,"R"],[125252,125258,"NSM"],[125259,126063,"R"],[126064,126143,"AL"],[126144,126207,"R"],[126208,126287,"AL"],[126288,126463,"R"],[126464,126703,"AL"],[126704,126705,"ON"],[126706,126719,"AL"],[126720,126975,"R"],[126976,127019,"ON"],[127024,127123,"ON"],[127136,127150,"ON"],[127153,127167,"ON"],[127169,127183,"ON"],[127185,127221,"ON"],[127232,127242,"EN"],[127243,127247,"ON"],[127279,127279,"ON"],[127338,127343,"ON"],[127405,127405,"ON"],[127584,127589,"ON"],[127744,128728,"ON"],[128732,128748,"ON"],[128752,128764,"ON"],[128768,128985,"ON"],[128992,129003,"ON"],[129008,129008,"ON"],[129024,129035,"ON"],[129040,129095,"ON"],[129104,129113,"ON"],[129120,129159,"ON"],[129168,129197,"ON"],[129200,129211,"ON"],[129216,129217,"ON"],[129232,129240,"ON"],[129280,129623,"ON"],[129632,129645,"ON"],[129648,129660,"ON"],[129664,129674,"ON"],[129678,129734,"ON"],[129736,129736,"ON"],[129741,129756,"ON"],[129759,129770,"ON"],[129775,129784,"ON"],[129792,129938,"ON"],[129940,130031,"ON"],[130032,130041,"EN"],[130042,130042,"ON"],[131070,131071,"BN"],[196606,196607,"BN"],[262142,262143,"BN"],[327678,327679,"BN"],[393214,393215,"BN"],[458750,458751,"BN"],[524286,524287,"BN"],[589822,589823,"BN"],[655358,655359,"BN"],[720894,720895,"BN"],[786430,786431,"BN"],[851966,851967,"BN"],[917502,917759,"BN"],[917760,917999,"NSM"],[918e3,921599,"BN"],[983038,983039,"BN"],[1048574,1048575,"BN"],[1114110,1114111,"BN"]];function lb(u){if(u<=255)return tb[u];let r=0,s=Nx.length-1;for(;r<=s;){const c=r+s>>1,d=Nx[c];if(u<d[0]){s=c-1;continue}if(u>d[1]){r=c+1;continue}return d[2]}return"L"}function nb(u){const r=u.length;if(r===0)return null;const s=new Array(r);let c=!1;for(let m=0;m<r;){const y=u.charCodeAt(m);let p=y,b=1;if(y>=55296&&y<=56319&&m+1<r){const M=u.charCodeAt(m+1);M>=56320&&M<=57343&&(p=(y-55296<<10)+(M-56320)+65536,b=2)}const w=lb(p);(w==="R"||w==="AL"||w==="AN")&&(c=!0);for(let M=0;M<b;M++)s[m+M]=w;m+=b}if(!c)return null;let d=0;for(let m=0;m<r;m++){const y=s[m];if(y==="L"){d=0;break}if(y==="R"||y==="AL"){d=1;break}}const x=new Int8Array(r);for(let m=0;m<r;m++)x[m]=d;const g=d&1?"R":"L",v=g;let N=v;for(let m=0;m<r;m++)s[m]==="NSM"?s[m]=N:N=s[m];N=v;for(let m=0;m<r;m++){const y=s[m];y==="EN"?s[m]=N==="AL"?"AN":"EN":(y==="R"||y==="L"||y==="AL")&&(N=y)}for(let m=0;m<r;m++)s[m]==="AL"&&(s[m]="R");for(let m=1;m<r-1;m++)s[m]==="ES"&&s[m-1]==="EN"&&s[m+1]==="EN"&&(s[m]="EN"),s[m]==="CS"&&(s[m-1]==="EN"||s[m-1]==="AN")&&s[m+1]===s[m-1]&&(s[m]=s[m-1]);for(let m=0;m<r;m++){if(s[m]!=="EN")continue;let y;for(y=m-1;y>=0&&s[y]==="ET";y--)s[y]="EN";for(y=m+1;y<r&&s[y]==="ET";y++)s[y]="EN"}for(let m=0;m<r;m++){const y=s[m];(y==="WS"||y==="ES"||y==="ET"||y==="CS")&&(s[m]="ON")}N=v;for(let m=0;m<r;m++){const y=s[m];y==="EN"?s[m]=N==="L"?"L":"EN":(y==="R"||y==="L")&&(N=y)}for(let m=0;m<r;m++){if(s[m]!=="ON")continue;let y=m+1;for(;y<r&&s[y]==="ON";)y++;const p=m>0?s[m-1]:v,b=y<r?s[y]:v,w=p!=="L"?"R":"L";if(w===(b!=="L"?"R":"L"))for(let Q=m;Q<y;Q++)s[Q]=w;m=y-1}for(let m=0;m<r;m++)s[m]==="ON"&&(s[m]=g);for(let m=0;m<r;m++){const y=s[m];(x[m]&1)===0?y==="R"?x[m]++:(y==="AN"||y==="EN")&&(x[m]+=2):(y==="L"||y==="AN"||y==="EN")&&x[m]++}return x}function ab(u,r){const s=nb(u);if(s===null)return null;const c=new Int8Array(r.length);for(let d=0;d<r.length;d++)c[d]=s[r[d]];return c}const ib=/[ \t\n\r\f]+/g,ub=/[\t\n\r\f]| {2,}|^ | $/;function rb(u){const r=u??"normal";return r==="pre-wrap"?{mode:r,preserveOrdinarySpaces:!0,preserveHardBreaks:!0}:{mode:r,preserveOrdinarySpaces:!1,preserveHardBreaks:!1}}function cb(u){if(!ub.test(u))return u;let r=u.replace(ib," ");return r.charCodeAt(0)===32&&(r=r.slice(1)),r.length>0&&r.charCodeAt(r.length-1)===32&&(r=r.slice(0,-1)),r}function sb(u){return/[\r\f]/.test(u)?u.replace(/\r\n/g,`
|
|
293
293
|
`).replace(/[\r\f]/g,`
|
|
294
294
|
`):u}let br=null,ob;function fb(){return br===null&&(br=new Intl.Segmenter(ob,{granularity:"word"})),br}function db(){br=null}const xb=/\p{Script=Arabic}/u,cn=/\p{M}/u,Do=/\p{Nd}/u;function Sx(u){return xb.test(u)}function Ex(u){return u>=19968&&u<=40959||u>=13312&&u<=19903||u>=131072&&u<=173791||u>=173824&&u<=177983||u>=177984&&u<=178207||u>=178208&&u<=183983||u>=183984&&u<=191471||u>=191472&&u<=192093||u>=194560&&u<=195103||u>=196608&&u<=201551||u>=201552&&u<=205743||u>=205744&&u<=210041||u>=63744&&u<=64255||u>=12288&&u<=12351||u>=12352&&u<=12447||u>=12448&&u<=12543||u>=12592&&u<=12687||u>=44032&&u<=55215||u>=65280&&u<=65519}function dl(u){for(let r=0;r<u.length;r++){const s=u.charCodeAt(r);if(!(s<12288)){if(s>=55296&&s<=56319&&r+1<u.length){const c=u.charCodeAt(r+1);if(c>=56320&&c<=57343){const d=(s-55296<<10)+(c-56320)+65536;if(Ex(d))return!0;r++;continue}}if(Ex(s))return!0}}return!1}function hb(u){const r=Ri(u);return r!==null&&(Oo.has(r)||Rn.has(r))}const mb=new Set([" "," ","","\uFEFF"]),gb=new Set(["-","‐","–","—"]);function pb(u){const r=Ri(u);return r!==null&&mb.has(r)}function bb(u){const r=Ri(u);return r!==null&&gb.has(r)}function Oh(u,r){return pb(u)?!1:r?!(hb(u)||bb(u)):!0}const Oo=new Set([",",".","!",":",";","?","、","。","・",")","〕","〉","》","」","』","】","〗","〙","〛","ー","々","〻","ゝ","ゞ","ヽ","ヾ"]),Mr=new Set(['"',"(","[","{","¡","¿","“","‘","‚","„","«","‹","⸘","(","〔","〈","《","「","『","【","〖","〘","〚"]),Bo=new Set(["'","’"]),Rn=new Set([".",",","!","?",":",";","،","؛","؟","।","॥","၊","။","၌","၍","၏",")","]","}","%",'"',"”","’","»","›","…"]),vb=new Set([":",".","،","؛"]),yb=new Set(["၏"]),Nb=new Set(["”","’","»","›","」","』","】","》","〉","〕",")"]);function Sb(u){if(zo(u))return!0;let r=!1;for(const s of u){if(Rn.has(s)||kr(s)){r=!0;continue}if(!(r&&cn.test(s)))return!1}return r}function Eb(u){for(const r of u)if(!Oo.has(r)&&!Rn.has(r))return!1;return u.length>0}function Ab(u){if(zo(u))return!0;for(const r of u)if(!Mr.has(r)&&!Bo.has(r)&&!cn.test(r)&&!kr(r))return!1;return u.length>0}function zo(u){let r=!1;for(const s of u)if(!(s==="\\"||cn.test(s))){if(Mr.has(s)||Rn.has(s)||Bo.has(s)){r=!0;continue}return!1}return r}function wr(u,r){const s=r-1;if(s<=0)return Math.max(s,0);const c=u.charCodeAt(s);if(c<56320||c>57343)return s;const d=s-1;if(d<0)return s;const x=u.charCodeAt(d);return x>=55296&&x<=56319?d:s}function Ri(u){if(u.length===0)return null;const r=wr(u,u.length);return u.slice(r)}function Cb(u){for(const r of u)if(!cn.test(r))return r;return null}function Mb(u){for(let r=u.length;r>0;){const s=wr(u,r),c=u.slice(s,r);if(!cn.test(c))return c;r=s}return null}const wb=[36,37,43,43,92,92,162,165,176,177,1423,1423,1545,1547,1642,1642,2046,2047,2546,2547,2553,2555,2801,2801,3065,3065,3449,3449,3647,3647,6107,6107,8240,8247,8279,8279,8352,8399,8451,8451,8457,8457,8470,8470,8722,8723,43064,43064,65020,65020,65129,65130,65284,65285,65504,65505,65509,65510,73693,73696,123647,123647,126124,126124,126128,126128];function kb(u,r){for(let s=0;s<r.length;s+=2)if(u>=r[s]&&u<=r[s+1])return!0;return!1}function kr(u){const r=u.codePointAt(0);return r!==void 0&&kb(r,wb)}function Tb(u){const r=Mb(u);return r!==null&&kr(r)}function Fb(u){const r=Cb(u);return r!==null&&Do.test(r)}function jb(u){const r=Array.from(u);let s=r.length;for(;s>0;){const c=r[s-1];if(cn.test(c)){s--;continue}if(Mr.has(c)||Bo.has(c)){s--;continue}break}return s<=0||s===r.length?null:{head:r.slice(0,s).join(""),tail:r.slice(s).join("")}}function Db(u,r,s){return s==="text"&&!r&&u.length===1&&u!=="-"&&u!=="—"?u:null}function Ax(u,r,s,c){const d=r[c],x=u[c];if(d==null)return x;const g=s[c];if(x.length===g)return x;const v=d.repeat(g);return u[c]=v,v}function Cx(u,r){return u&&r!==null&&vb.has(r)}function Ob(u){const r=Ri(u);return r!==null&&yb.has(r)}function Bb(u){if(u.length<2||u[0]!==" ")return null;const r=u.slice(1);return/^\p{M}+$/u.test(r)?{space:" ",marks:r}:null}function Eo(u){let r=u.length;for(;r>0;){const s=wr(u,r),c=u.slice(s,r);if(Nb.has(c))return!0;if(!Rn.has(c))return!1;r=s}return!1}function zb(u,r){if(r.preserveOrdinarySpaces||r.preserveHardBreaks){if(u===" ")return"preserved-space";if(u===" ")return"tab";if(r.preserveHardBreaks&&u===`
|
|
295
295
|
`)return"hard-break"}return u===" "?"space":u===" "||u===" "||u===""||u==="\uFEFF"?"glue":u===""?"zero-width-break":u===""?"soft-hyphen":"text"}const _b=/[\x20\t\n\xA0\xAD\u200B\u202F\u2060\uFEFF]/;function $t(u){return u.length===1?u[0]:u.join("")}function Rb(u,r){const s=[];for(let c=u.length-1;c>=0;c--)s.push(u[c]);return s.push(r),$t(s)}function Lb(u,r,s,c){if(!_b.test(u))return[{text:u,isWordLike:r,kind:"text",start:s}];const d=[];let x=null,g=[],v=s,N=!1,m=0;for(const y of u){const p=zb(y,c),b=p==="text"&&r;if(x!==null&&p===x&&b===N){g.push(y),m+=y.length;continue}x!==null&&d.push({text:$t(g),isWordLike:N,kind:x,start:v}),x=p,g=[y],v=s+m,N=b,m+=y.length}return x!==null&&d.push({text:$t(g),isWordLike:N,kind:x,start:v}),d}function Ao(u){return u==="space"||u==="preserved-space"||u==="zero-width-break"||u==="hard-break"}const Hb=/^[A-Za-z][A-Za-z0-9+.-]*:$/;function Ub(u,r){const s=u.texts[r];return s.startsWith("www.")?!0:Hb.test(s)&&r+1<u.len&&u.kinds[r+1]==="text"&&u.texts[r+1]==="//"}function Gb(u){return u.includes("?")&&(u.includes("://")||u.startsWith("www."))}function qb(u){const r=u.texts.slice(),s=u.isWordLike.slice(),c=u.kinds.slice(),d=u.starts.slice();for(let g=0;g<u.len;g++){if(c[g]!=="text"||!Ub(u,g))continue;const v=[r[g]];let N=g+1;for(;N<u.len&&!Ao(c[N]);){v.push(r[N]),s[g]=!0;const m=r[N].includes("?");if(c[N]="text",r[N]="",N++,m)break}r[g]=$t(v)}let x=0;for(let g=0;g<r.length;g++){const v=r[g];v.length!==0&&(x!==g&&(r[x]=v,s[x]=s[g],c[x]=c[g],d[x]=d[g]),x++)}return r.length=x,s.length=x,c.length=x,d.length=x,{len:x,texts:r,isWordLike:s,kinds:c,starts:d}}function Yb(u){const r=[],s=[],c=[],d=[];for(let x=0;x<u.len;x++){const g=u.texts[x];if(r.push(g),s.push(u.isWordLike[x]),c.push(u.kinds[x]),d.push(u.starts[x]),!Gb(g))continue;const v=x+1;if(v>=u.len||Ao(u.kinds[v]))continue;const N=[],m=u.starts[v];let y=v;for(;y<u.len&&!Ao(u.kinds[y]);)N.push(u.texts[y]),y++;N.length>0&&(r.push($t(N)),s.push(!0),c.push("text"),d.push(m),x=y-1)}return{len:r.length,texts:r,isWordLike:s,kinds:c,starts:d}}const Xb=new Set([":","-","/","×",",",".","+","–","—"]),Qb=/[\p{P}\p{S}\p{Co}]/u,Vb=/\p{Emoji_Presentation}/u,Zb=new Set(["?","֊","-","‐","‒","–","—","…","‼","‽","⁉"]);function Kb(u){return u>=33&&u<=47&&u!==45||u>=58&&u<=64&&u!==63||u>=91&&u<=96||u>=123&&u<=126}function Bh(u){const r=u.charCodeAt(0);return r<128?Kb(r):!Zb.has(u)&&!Vb.test(u)&&Qb.test(u)}function Mx(u){let r=!1;for(const s of u)if(!cn.test(s)){if(!Bh(s))return!1;r=!0}return r}function Jb(u){for(let r=u.length;r>0;){const s=wr(u,r),c=u.slice(s,r);if(cn.test(c)){r=s;continue}return Bh(c)||kr(c)}return!1}function Ib(u,r,s,c){const d=!r&&Mx(u),x=!c&&Mx(s),g=Tb(u),v=(r||g)&&Jb(u);return!d&&!x&&!v||dl(u)||dl(s)?!1:(r||d||g)&&(c||x)}function zh(u){for(const r of u)if(Do.test(r))return!0;return!1}function Sr(u){if(u.length===0)return!1;for(const r of u)if(!(Do.test(r)||Xb.has(r)))return!1;return!0}function Wb(u){const r=[],s=[],c=[],d=[];for(let x=0;x<u.len;x++){const g=u.texts[x],v=u.kinds[x];if(v==="text"&&Sr(g)&&zh(g)){const N=[g];let m=x+1;for(;m<u.len&&u.kinds[m]==="text"&&Sr(u.texts[m]);)N.push(u.texts[m]),m++;r.push($t(N)),s.push(!0),c.push("text"),d.push(u.starts[x]),x=m-1;continue}r.push(g),s.push(u.isWordLike[x]),c.push(v),d.push(u.starts[x])}return{len:r.length,texts:r,isWordLike:s,kinds:c,starts:d}}function $b(u){const r=[],s=[],c=[],d=[];let x=0;for(;x<u.len;){const g=u.texts[x],v=u.kinds[x],N=u.isWordLike[x];if(v==="text"){const m=[g];let y=x+1,p=N;for(;y<u.len&&u.kinds[y]==="text"&&Ib(u.texts[y-1],u.isWordLike[y-1],u.texts[y],u.isWordLike[y]);){const b=u.texts[y];m.push(b),p=p||u.isWordLike[y],y++}if(y>x+1){r.push($t(m)),s.push(p),c.push("text"),d.push(u.starts[x]),x=y;continue}}r.push(g),s.push(N),c.push(v),d.push(u.starts[x]),x++}return{len:r.length,texts:r,isWordLike:s,kinds:c,starts:d}}function Pb(u){const r=[],s=[],c=[],d=[];for(let x=0;x<u.len;x++){const g=u.texts[x];if(u.kinds[x]==="text"&&g.includes("-")){const v=g.split("-");let N=v.length>1;for(let m=0;m<v.length;m++){const y=v[m];if(!N)break;(y.length===0||!zh(y)||!Sr(y))&&(N=!1)}if(N){let m=0;for(let y=0;y<v.length;y++){const p=v[y],b=y<v.length-1?`${p}-`:p;r.push(b),s.push(!0),c.push("text"),d.push(u.starts[x]+m),m+=b.length}continue}}r.push(g),s.push(u.isWordLike[x]),c.push(u.kinds[x]),d.push(u.starts[x])}return{len:r.length,texts:r,isWordLike:s,kinds:c,starts:d}}function ev(u){const r=[],s=[],c=[],d=[];let x=0;for(;x<u.len;){const g=[u.texts[x]];let v=u.isWordLike[x],N=u.kinds[x],m=u.starts[x];if(N==="glue"){const y=[g[0]],p=m;for(x++;x<u.len&&u.kinds[x]==="glue";)y.push(u.texts[x]),x++;const b=$t(y);if(x<u.len&&u.kinds[x]==="text")g[0]=b,g.push(u.texts[x]),v=u.isWordLike[x],N="text",m=p,x++;else{r.push(b),s.push(!1),c.push("glue"),d.push(p);continue}}else x++;if(N==="text")for(;x<u.len&&u.kinds[x]==="glue";){const y=[];for(;x<u.len&&u.kinds[x]==="glue";)y.push(u.texts[x]),x++;const p=$t(y);if(x<u.len&&u.kinds[x]==="text"){g.push(p,u.texts[x]),v=v||u.isWordLike[x],x++;continue}g.push(p)}r.push($t(g)),s.push(v),c.push(N),d.push(m)}return{len:r.length,texts:r,isWordLike:s,kinds:c,starts:d}}function tv(u){const r=u.texts.slice(),s=u.isWordLike.slice(),c=u.kinds.slice(),d=u.starts.slice();for(let x=0;x<r.length-1;x++){if(c[x]!=="text"||c[x+1]!=="text"||!dl(r[x])||!dl(r[x+1]))continue;const g=jb(r[x]);g!==null&&(r[x]=g.head,r[x+1]=g.tail+r[x+1],d[x+1]=d[x]+g.head.length)}return{len:r.length,texts:r,isWordLike:s,kinds:c,starts:d}}function lv(u,r,s){const c=fb();let d=0;const x=[],g=[],v=[],N=[],m=[],y=[],p=[],b=[],w=[],M=[],Q=[],B=[];for(const H of c.segment(u))for(const V of Lb(H.segment,H.isWordLike??!1,H.index,s)){let O=function(){y[Y]!==null&&(g[Y]=[Ax(x,y,p,Y)],y[Y]=null),g[Y].push(V.text),v[Y]=v[Y]||V.isWordLike,b[Y]=b[Y]||q,w[Y]=w[Y]||_,M[Y]=ne,Q[Y]=he,B[Y]=Cx(w[Y],te)};const G=V.kind==="text",S=Db(V.text,V.isWordLike,V.kind),q=dl(V.text),_=Sx(V.text),te=Ri(V.text),ne=Eo(V.text),he=Ob(V.text),Y=d-1;r.carryCJKAfterClosingQuote&&G&&d>0&&N[Y]==="text"&&q&&b[Y]&&M[Y]||G&&d>0&&N[Y]==="text"&&Eb(V.text)&&b[Y]||G&&d>0&&N[Y]==="text"&&Q[Y]?O():G&&d>0&&N[Y]==="text"&&V.isWordLike&&_&&B[Y]?(O(),v[Y]=!0):S!==null&&d>0&&N[Y]==="text"&&y[Y]===S?p[Y]=(p[Y]??1)+1:G&&!V.isWordLike&&d>0&&N[Y]==="text"&&!b[Y]&&(Sb(V.text)||V.text==="-"&&v[Y])?O():(x[d]=V.text,g[d]=[V.text],v[d]=V.isWordLike,N[d]=V.kind,m[d]=V.start,y[d]=S,p[d]=S===null?0:1,b[d]=q,w[d]=_,M[d]=ne,Q[d]=he,B[d]=Cx(_,te),d++)}for(let H=0;H<d;H++){if(y[H]!==null){x[H]=Ax(x,y,p,H);continue}x[H]=$t(g[H])}for(let H=1;H<d;H++)N[H]==="text"&&!v[H]&&zo(x[H])&&N[H-1]==="text"&&!b[H-1]&&(x[H-1]+=x[H],v[H-1]=v[H-1]||v[H],x[H]="");const L=Array.from({length:d},()=>null);let $=-1;for(let H=d-1;H>=0;H--){const V=x[H];if(V.length!==0){if(N[H]==="text"&&!v[H]&&$>=0&&N[$]==="text"&&(Ab(V)||V==="-"&&Fb(x[$]))){const G=L[$]??[];G.push(V),L[$]=G,m[$]=m[H],x[H]="";continue}$=H}}for(let H=0;H<d;H++){const V=L[H];V!=null&&(x[H]=Rb(V,x[H]))}let ee=0;for(let H=0;H<d;H++){const V=x[H];V.length!==0&&(ee!==H&&(x[ee]=V,v[ee]=v[H],N[ee]=N[H],m[ee]=m[H]),ee++)}x.length=ee,v.length=ee,N.length=ee,m.length=ee;const ce=ev({len:ee,texts:x,isWordLike:v,kinds:N,starts:m}),ue=tv($b(Pb(Wb(Yb(qb(ce))))));for(let H=0;H<ue.len-1;H++){const V=Bb(ue.texts[H]);V!==null&&(ue.kinds[H]!=="space"&&ue.kinds[H]!=="preserved-space"||ue.kinds[H+1]!=="text"||!Sx(ue.texts[H+1])||(ue.texts[H]=V.space,ue.isWordLike[H]=!1,ue.kinds[H]=ue.kinds[H]==="preserved-space"?"preserved-space":"space",ue.texts[H+1]=V.marks+ue.texts[H+1],ue.starts[H+1]=ue.starts[H]+V.space.length))}return ue}function nv(u,r){if(u.len===0)return[];if(!r.preserveHardBreaks)return[{startSegmentIndex:0,endSegmentIndex:u.len,consumedEndSegmentIndex:u.len}];const s=[];let c=0;for(let d=0;d<u.len;d++)u.kinds[d]==="hard-break"&&(s.push({startSegmentIndex:c,endSegmentIndex:d,consumedEndSegmentIndex:d+1}),c=d+1);return c<u.len&&s.push({startSegmentIndex:c,endSegmentIndex:u.len,consumedEndSegmentIndex:u.len}),s}function av(u,r,s){if(r.len<=1)return r;const c=[],d=[],x=[],g=[];let v=-1,N=!1;function m(b){c.push(r.texts[b]),d.push(r.isWordLike[b]),x.push("text"),g.push(r.starts[b])}function y(b,w){let M=!1;for(let L=b;L<w;L++)M=M||r.isWordLike[L];const Q=r.starts[b],B=w<r.len?r.starts[w]:u.length;c.push(u.slice(Q,B)),d.push(M),x.push("text"),g.push(Q)}function p(b){if(!(v<0)){if(N)v+1===b?m(v):y(v,b);else for(let w=v;w<b;w++)m(w);v=-1,N=!1}}for(let b=0;b<r.len;b++){const w=r.texts[b],M=r.kinds[b];if(M==="text"){v>=0&&!Oh(r.texts[b-1],s)&&p(b),v<0&&(v=b),N=N||dl(w);continue}p(b),c.push(w),d.push(r.isWordLike[b]),x.push(M),g.push(r.starts[b])}return p(r.len),{len:c.length,texts:c,isWordLike:d,kinds:x,starts:g}}function iv(u,r,s="normal",c="normal"){const d=rb(s),x=d.mode==="pre-wrap"?sb(u):cb(u);if(x.length===0)return{normalized:x,chunks:[],len:0,texts:[],isWordLike:[],kinds:[],starts:[]};const g=lv(x,r,d),v=c==="keep-all"?av(x,g,r.breakKeepAllAfterPunctuation):g;return{normalized:x,chunks:nv(v,d),...v}}let Da=null;const Co=new Map;let Oa=null;const uv=96,rv=/\p{Emoji_Presentation}/u,cv=/[\p{Emoji_Presentation}\p{Extended_Pictographic}\p{Regional_Indicator}\uFE0F\u20E3]/u;let vr=null;const Mo=new Map;function _o(){if(Da!==null)return Da;if(typeof OffscreenCanvas<"u")return Da=new OffscreenCanvas(1,1).getContext("2d"),Da;if(typeof document<"u")return Da=document.createElement("canvas").getContext("2d"),Da;throw new Error("Text measurement requires OffscreenCanvas or a DOM canvas context.")}function sv(u){let r=Co.get(u);return r||(r=new Map,Co.set(u,r)),r}function rn(u,r){let s=r.get(u);return s===void 0&&(s={width:_o().measureText(u).width,containsCJK:dl(u)},r.set(u,s)),s}function La(){if(Oa!==null)return Oa;if(typeof navigator>"u")return Oa={lineFitEpsilon:.005,carryCJKAfterClosingQuote:!1,breakKeepAllAfterPunctuation:!0,preferPrefixWidthsForBreakableRuns:!1,preferEarlySoftHyphenBreak:!1},Oa;const u=navigator.userAgent,s=navigator.vendor==="Apple Computer, Inc."&&u.includes("Safari/")&&!u.includes("Chrome/")&&!u.includes("Chromium/")&&!u.includes("CriOS/")&&!u.includes("FxiOS/")&&!u.includes("EdgiOS/"),c=u.includes("Chrome/")||u.includes("Chromium/")||u.includes("CriOS/")||u.includes("Edg/");return Oa={lineFitEpsilon:s?1/64:.005,carryCJKAfterClosingQuote:c,breakKeepAllAfterPunctuation:!s,preferPrefixWidthsForBreakableRuns:s,preferEarlySoftHyphenBreak:s},Oa}function ov(u){const r=u.match(/(\d+(?:\.\d+)?)\s*px/);return r?parseFloat(r[1]):16}function _h(){return vr===null&&(vr=new Intl.Segmenter(void 0,{granularity:"grapheme"})),vr}function fv(u){return rv.test(u)||u.includes("️")}function dv(u){return cv.test(u)}function xv(u,r){let s=Mo.get(u);if(s!==void 0)return s;const c=_o();c.font=u;const d=c.measureText("😀").width;if(s=0,d>r+.5&&typeof document<"u"&&document.body!==null){const x=document.createElement("span");x.style.font=u,x.style.display="inline-block",x.style.visibility="hidden",x.style.position="absolute",x.textContent="😀",document.body.appendChild(x);const g=x.getBoundingClientRect().width;document.body.removeChild(x),d-g>.5&&(s=d-g)}return Mo.set(u,s),s}function hv(u){let r=0;const s=_h();for(const c of s.segment(u))fv(c.segment)&&r++;return r}function mv(u,r){return r.emojiCount===void 0&&(r.emojiCount=hv(u)),r.emojiCount}function _n(u,r,s){return s===0?r.width:r.width-mv(u,r)*s}function gv(u,r,s,c,d){if(r.breakableFitAdvances!==void 0&&r.breakableFitMode===d)return r.breakableFitAdvances;r.breakableFitMode=d;const x=_h(),g=[];for(const y of x.segment(u))g.push(y.segment);if(g.length<=1)return r.breakableFitAdvances=null,r.breakableFitAdvances;if(d==="sum-graphemes"){const y=[];for(const p of g){const b=rn(p,s);y.push(_n(p,b,c))}return r.breakableFitAdvances=y,r.breakableFitAdvances}if(d==="pair-context"||g.length>uv){const y=[];let p=null,b=0;for(const w of g){const M=rn(w,s),Q=_n(w,M,c);if(p===null)y.push(Q);else{const B=p+w,L=rn(B,s);y.push(_n(B,L,c)-b)}p=w,b=Q}return r.breakableFitAdvances=y,r.breakableFitAdvances}const v=[];let N="",m=0;for(const y of g){N+=y;const p=rn(N,s),b=_n(N,p,c);v.push(b-m),m=b}return r.breakableFitAdvances=v,r.breakableFitAdvances}function pv(u,r){const s=_o();s.font=u;const c=sv(u),d=ov(u),x=r?xv(u,d):0;return{cache:c,fontSize:d,emojiCorrection:x}}function bv(){Co.clear(),Mo.clear(),vr=null}function vv(u){return u==="space"||u==="zero-width-break"||u==="soft-hyphen"}function Tr(u){return u==="space"||u==="preserved-space"||u==="tab"||u==="zero-width-break"||u==="soft-hyphen"}function Ro(u,r,s=u.widths.length){for(;r<s;){const c=u.kinds[r];if(!vv(c))break;r++}return r}function Rh(u,r){if(r<=0)return 0;const s=u%r;return Math.abs(s)<=1e-6?r:r-s}function Lh(u,r,s){return u.letterSpacing!==0&&r&&u.spacingGraphemeCounts[s]>0?u.letterSpacing:0}function Lo(u,r){return r===0?0:u+r}function yv(u,r){return u.letterSpacing!==0&&u.spacingGraphemeCounts[r]>0?u.letterSpacing:0}function Hh(u,r,s,c,d){const x=r==="tab"?d+yv(u,s):u.lineEndFitAdvances[s];return Lo(c,x)}function Er(u,r,s,c){const d=r==="tab"?0:u.lineEndFitAdvances[s];return Lo(c,d)}function Ar(u,r,s,c,d){const x=r==="tab"?d:u.lineEndPaintAdvances[s];return Lo(c,x)}function Uh(u,r,s){return u.letterSpacing!==0&&r?s+u.letterSpacing:s}function Gh(u,r){return u.letterSpacing===0?r:r+u.letterSpacing}function Ra(u,r,s){let c=r;for(;c<u.length&&u[c]<s;)c++;return c}function Nv(u,r,s,c,d){if(u.letterSpacing===0)return 0;if(d>0)return u.spacingGraphemeCounts[c]>0?u.letterSpacing:0;for(let x=c-1;x>=r;x--){const g=u.kinds[x];if(!(g==="space"||g==="zero-width-break"||g==="hard-break")){if(g==="soft-hyphen"){if(x===c-1)return 0;continue}return x===r&&s>0||u.spacingGraphemeCounts[x]>0?u.letterSpacing:0}}return 0}function qh(u,r,s,c,d,x){return r+Nv(u,s,c,d,x)}function Sv(u,r){let s=0,c=u.chunks.length;for(;s<c;){const d=Math.floor((s+c)/2);r<u.chunks[d].consumedEndSegmentIndex?c=d:s=d+1}return s<u.chunks.length?s:-1}function Ev(u,r,s){let c=s.segmentIndex;if(s.graphemeIndex>0)return r;const d=u.chunks[r];return d.startSegmentIndex===d.endSegmentIndex&&c===d.startSegmentIndex||(c<d.startSegmentIndex&&(c=d.startSegmentIndex),c=Ro(u,c,d.endSegmentIndex),c<d.endSegmentIndex)?(s.segmentIndex=c,s.graphemeIndex=0,r):d.consumedEndSegmentIndex>=u.widths.length?-1:(s.segmentIndex=d.consumedEndSegmentIndex,s.graphemeIndex=0,r+1)}function Av(u,r){if(r.segmentIndex>=u.widths.length)return-1;const s=Sv(u,r.segmentIndex);return s<0?-1:Ev(u,s,r)}function Cv(u,r,s){const{widths:c,kinds:d,breakableFitAdvances:x,breakablePreferredBreaks:g}=u;if(c.length===0)return 0;const N=La().lineFitEpsilon,m=r+N;let y=0,p=0,b=!1,w=0,M=0,Q=0,B=0,L=-1,$=0;function ee(){L=-1,$=0}function ce(q=Q,_=B,te=p){y++,s?.(te,w,M,q,_),p=0,b=!1,ee()}function ue(q,_){b=!0,w=q,M=0,Q=q+1,B=0,p=_}function H(q,_,te){b=!0,w=q,M=_,Q=q,B=_+1,p=te}function V(q,_){if(!b){ue(q,_);return}p+=_,Q=q+1,B=0}function G(q,_){const te=x[q],ne=g[q]??null;let he=ne===null?-1:Ra(ne,0,_+1),Y=-1,O=0,k=_;for(;k<te.length;){const D=te[k];if(!b)H(q,k,D);else if(p+D>m){if(ne!==null&&Y>_){ce(q,Y,O),k=Y,he=Ra(ne,he,k+1),Y=-1,O=0;continue}ce(),H(q,k,D)}else p+=D,Q=q,B=k+1;const K=k+1;ne!==null&&ne[he]===K&&(Y=K,O=p,he++),k++}b&&Q===q&&B===te.length&&(Q=q+1,B=0)}let S=0;for(;S<c.length&&!(!b&&(S=Ro(u,S),S>=c.length));){const q=c[S],_=d[S],te=Tr(_);if(!b){q>m&&x[S]!==null?G(S,0):ue(S,q),te&&(L=S+1,$=p-q),S++;continue}if(p+q>m){if(te){V(S,q),ce(S+1,0,p-q),S++;continue}if(L>=0){if(Q>L||Q===L&&B>0){ce();continue}ce(L,0,$);continue}if(q>m&&x[S]!==null){ce(),G(S,0),S++;continue}ce();continue}V(S,q),te&&(L=S+1,$=p-q),S++}return b&&ce(),y}function Mv(u,r,s){if(u.simpleLineWalkFastPath)return Cv(u,r,s);const{widths:c,kinds:d,breakableFitAdvances:x,breakablePreferredBreaks:g,discretionaryHyphenWidth:v,chunks:N}=u;if(c.length===0||N.length===0)return 0;const m=La(),y=m.lineFitEpsilon,p=r+y;let b=0,w=0,M=!1,Q=0,B=0,L=0,$=0,ee=-1,ce=0,ue=0,H=null;function V(){ee=-1,ce=0,ue=0,H=null}function G(){return H==="soft-hyphen"&&ee===L&&$===0?ue:w}function S(O=L,k=$,D){b++,s!==void 0&&s(qh(u,D??G(),Q,B,O,k),Q,B,O,k),w=0,M=!1,V()}function q(O,k){M=!0,Q=O,B=0,L=O+1,$=0,w=k}function _(O,k,D){M=!0,Q=O,B=k,L=O,$=k+1,w=D}function te(O,k){if(!M){q(O,k);return}w+=k,L=O+1,$=0}function ne(O,k,D,K,P,re){if(!k)return;const le=Er(u,O,D,P),ae=Ar(u,O,D,P,K);ee=D+1,ce=w-re+le,ue=w-re+ae,H=O}function he(O,k){const D=x[O],K=g[O]??null;let P=K===null?-1:Ra(K,0,k+1),re=-1,le=0,ae=k;for(;ae<D.length;){const A=D[ae];if(!M)_(O,ae,A);else{const Z=Uh(u,!0,A),W=w+Z;if(Gh(u,W)>p){if(K!==null&&re>k){S(O,re,le),ae=re,P=Ra(K,P,ae+1),re=-1,le=0;continue}S(),_(O,ae,A)}else w=W,L=O,$=ae+1}const X=ae+1;K!==null&&K[P]===X&&(re=X,le=w,P++),ae++}M&&L===O&&$===D.length&&(L=O+1,$=0)}function Y(O){b++,s?.(0,O.startSegmentIndex,0,O.consumedEndSegmentIndex,0),V()}for(let O=0;O<N.length;O++){const k=N[O];if(k.startSegmentIndex===k.endSegmentIndex){Y(k);continue}M=!1,w=0,Q=k.startSegmentIndex,B=0,L=k.startSegmentIndex,$=0,V();let D=k.startSegmentIndex;for(;D<k.endSegmentIndex&&!(!M&&(D=Ro(u,D,k.endSegmentIndex),D>=k.endSegmentIndex));){const K=d[D],P=Tr(K),re=Lh(u,M,D),le=K==="tab"?Rh(w+re,u.tabStopAdvance):c[D],ae=re+le,A=Hh(u,K,D,re,le);if(K==="soft-hyphen"){M&&(L=D+1,$=0,ee=D+1,ce=w+v,ue=w+v,H=K),D++;continue}if(!M){A>p&&x[D]!==null?he(D,0):q(D,le),ne(K,P,D,le,re,ae),D++;continue}if(w+A>p){const Z=w+Er(u,K,D,re),W=w+Ar(u,K,D,re,le);if(H==="soft-hyphen"&&m.preferEarlySoftHyphenBreak&&ce<=p){S(ee,0,ue);continue}if(P&&Z<=p){te(D,ae),S(D+1,0,W),D++;continue}if(ee>=0&&ce<=p){if(L>ee||L===ee&&$>0){S();continue}const me=ee;S(me,0,ue),D=me;continue}if(A>p&&x[D]!==null){S(),he(D,0),D++;continue}S();continue}te(D,ae),ne(K,P,D,le,re,ae),D++}if(M){const K=ee===k.consumedEndSegmentIndex?ue:w;S(k.consumedEndSegmentIndex,0,K)}}return b}function wv(u,r,s,c){const d=u.chunks[s];if(d.startSegmentIndex===d.endSegmentIndex)return r.segmentIndex=d.consumedEndSegmentIndex,r.graphemeIndex=0,0;const{widths:x,kinds:g,breakableFitAdvances:v,breakablePreferredBreaks:N,discretionaryHyphenWidth:m}=u,y=La(),p=y.lineFitEpsilon,b=c+p,w=r.segmentIndex,M=r.graphemeIndex;let Q=0,B=!1,L=r.segmentIndex,$=r.graphemeIndex,ee=-1,ce=0,ue=0,H=null;function V(){return H==="soft-hyphen"&&ee===L&&$===0?ue:Q}function G(Y=L,O=$,k=V()){return B?(r.segmentIndex=Y,r.graphemeIndex=O,qh(u,k,w,M,Y,O)):null}function S(Y,O){B=!0,L=Y+1,$=0,Q=O}function q(Y,O,k){B=!0,L=Y,$=O+1,Q=k}function _(Y,O){if(!B){S(Y,O);return}Q+=O,L=Y+1,$=0}function te(Y,O,k,D,K,P){if(!O)return;const re=Er(u,Y,k,K),le=Ar(u,Y,k,K,D);ee=k+1,ce=Q-P+re,ue=Q-P+le,H=Y}function ne(Y,O){const k=v[Y],D=N[Y]??null;let K=D===null?-1:Ra(D,0,O+1),P=-1,re=0;for(let le=O;le<k.length;le++){const ae=k[le];if(!B)q(Y,le,ae);else{const X=Uh(u,!0,ae),Z=Q+X;if(Gh(u,Z)>b)return D!==null&&P>O?G(Y,P,re):G();Q=Z,L=Y,$=le+1}const A=le+1;D!==null&&D[K]===A&&(P=A,re=Q,K++)}return B&&L===Y&&$===k.length&&(L=Y+1,$=0),null}function he(){return H!=="soft-hyphen"||ee<0?null:ce<=b?G(ee,0,ue):null}for(let Y=r.segmentIndex;Y<d.endSegmentIndex;Y++){const O=g[Y],k=Tr(O),D=Y===r.segmentIndex?r.graphemeIndex:0,K=Lh(u,B,Y),P=O==="tab"?Rh(Q+K,u.tabStopAdvance):x[Y],re=K+P,le=Hh(u,O,Y,K,P);if(O==="soft-hyphen"&&D===0){B&&(L=Y+1,$=0,ee=Y+1,ce=Q+m,ue=Q+m,H=O);continue}if(!B){if(D>0){const A=ne(Y,D);if(A!==null)return A}else if(le>b&&v[Y]!==null){const A=ne(Y,0);if(A!==null)return A}else S(Y,P);te(O,k,Y,P,K,re);continue}if(Q+le>b){const A=Q+Er(u,O,Y,K),X=Q+Ar(u,O,Y,K,P);if(H==="soft-hyphen"&&y.preferEarlySoftHyphenBreak&&ce<=b)return G(ee,0,ue);const Z=he();if(Z!==null)return Z;if(k&&A<=b)return _(Y,re),G(Y+1,0,X);if(ee>=0&&ce<=b)return L>ee||L===ee&&$>0?G():G(ee,0,ue);if(le>b&&v[Y]!==null){const W=G();if(W!==null)return W;const me=ne(Y,0);if(me!==null)return me}return G()}_(Y,re),te(O,k,Y,P,K,re)}return ee===d.consumedEndSegmentIndex&&$===0?G(d.consumedEndSegmentIndex,0,ue):G(d.consumedEndSegmentIndex,0,Q)}function kv(u,r,s){const{widths:c,kinds:d,breakableFitAdvances:x,breakablePreferredBreaks:g}=u,N=La().lineFitEpsilon,m=s+N;let y=0,p=!1,b=r.segmentIndex,w=r.graphemeIndex,M=-1,Q=0;for(let B=r.segmentIndex;B<c.length;B++){const L=d[B],$=Tr(L),ee=B===r.segmentIndex?r.graphemeIndex:0,ce=x[B],ue=c[B];if(!p){if(ee>0||ue>m&&ce!==null){const H=ce,V=g[B]??null;let G=V===null?-1:Ra(V,0,ee+1),S=-1,q=0;const _=H[ee];p=!0,y=_,b=B,w=ee+1,V!==null&&V[G]===w&&(S=w,q=y,G++);for(let te=ee+1;te<H.length;te++){const ne=H[te];if(y+ne>m)return V!==null&&S>ee?(r.segmentIndex=B,r.graphemeIndex=S,q):(r.segmentIndex=b,r.graphemeIndex=w,y);y+=ne,b=B,w=te+1,V!==null&&V[G]===w&&(S=w,q=y,G++)}b===B&&w===H.length&&(b=B+1,w=0)}else p=!0,y=ue,b=B+1,w=0;$&&(M=B+1,Q=y-ue);continue}if(y+ue>m)return $?(r.segmentIndex=B+1,r.graphemeIndex=0,y):M>=0?b>M||b===M&&w>0?(r.segmentIndex=b,r.graphemeIndex=w,y):(r.segmentIndex=M,r.graphemeIndex=0,Q):(r.segmentIndex=b,r.graphemeIndex=w,y);y+=ue,b=B+1,w=0,$&&(M=B+1,Q=y-ue)}return p?(r.segmentIndex=b,r.graphemeIndex=w,y):null}function Tv(u,r,s,c){return u.simpleLineWalkFastPath?kv(u,r,c):wv(u,r,s,c)}function wo(u,r,s){const c=Av(u,r);return c<0?null:Tv(u,r,c,s)}let yr=null,ko=new WeakMap;function Fv(){return yr===null&&(yr=new Intl.Segmenter(void 0,{granularity:"grapheme"})),yr}function wx(u,r,s){let c=s.get(u);if(c!==void 0)return c;c=[];const d=Fv();for(const x of d.segment(r[u]))c.push(x.segment);return s.set(u,c),c}function jv(u,r,s){return s>r&&u[s-1]==="soft-hyphen"}function kx(u,r,s,c){for(let d=s;d<c;d++)u+=r[d];return u}function Dv(u){let r=ko.get(u);return r!==void 0||(r=new Map,ko.set(u,r)),r}function Ov(u,r,s,c,d,x){let g="";const v=jv(u.kinds,s,d);for(let N=s;N<d;N++)if(!(u.kinds[N]==="soft-hyphen"||u.kinds[N]==="hard-break"))if(N===s&&c>0){const m=wx(N,u.segments,r);g=kx(g,m,c,m.length)}else g+=u.segments[N];if(x>0){v&&(g+="-");const N=wx(d,u.segments,r);g=kx(g,N,s===d?c:0,x)}else v&&(g+="-");return g}function Bv(){yr=null,ko=new WeakMap}let Nr=null;function Ho(){return Nr===null&&(Nr=new Intl.Segmenter(void 0,{granularity:"grapheme"})),Nr}function zv(u){return{widths:[],lineEndFitAdvances:[],lineEndPaintAdvances:[],kinds:[],simpleLineWalkFastPath:!0,segLevels:null,breakableFitAdvances:[],breakablePreferredBreaks:[],letterSpacing:0,spacingGraphemeCounts:[],discretionaryHyphenWidth:0,tabStopAdvance:0,chunks:[],segments:[]}}function _v(u,r){const s=[];let c=[],d=0,x=!1,g=!1,v=!1;function N(){c.length!==0&&(s.push({text:c.length===1?c[0]:c.join(""),start:d}),c=[],x=!1,g=!1,v=!1)}function m(p,b,w){c=[p],d=b,x=w,g=Eo(p),v=Mr.has(p)}function y(p,b){c.push(p),x=x||b;const w=Eo(p);p.length===1&&Rn.has(p)?g=g||w:g=w,v=!1}for(const p of Ho().segment(u)){const b=p.segment,w=dl(b);if(c.length===0){m(b,p.index,w);continue}if(v||Oo.has(b)||Rn.has(b)||r.carryCJKAfterClosingQuote&&w&&g){y(b,w);continue}if(!x&&!w){y(b,w);continue}N(),m(b,p.index,w)}return N(),s}function Rv(u,r,s){if(r.length<=1)return r;const c=[];let d=-1,x=!1;function g(N,m){const y=r[N].start,p=m<r.length?r[m].start:u.length;c.push({text:u.slice(y,p),start:y})}function v(N){if(!(d<0)){if(x)d+1===N?c.push(r[d]):g(d,N);else for(let m=d;m<N;m++)c.push(r[m]);d=-1,x=!1}}for(let N=0;N<r.length;N++){const m=r[N];d>=0&&!Oh(r[N-1].text,s)&&v(N),d<0&&(d=N),x=x||dl(m.text)}return v(r.length),c}function Tx(u,r){if(r==="zero-width-break"||r==="soft-hyphen"||r==="hard-break")return 0;if(r==="tab")return 1;let s=0;const c=Ho();for(const d of c.segment(u))s++;return s}function Lv(u){return u==="-"||u==="֊"||u==="‐"||u==="‒"||u==="–"||u==="—"}function Hv(u){if(!/[-\u058A\u2010\u2012\u2013\u2014]/u.test(u))return null;const r=[];let s=0;for(const c of Ho().segment(u))s++,Lv(c.segment)&&r.push(s);return r.length===0?null:r}function Uv(u,r,s){return r>1?u+(r-1)*s:u}function Gv(u,r,s,c,d){const x=La(),{cache:g,emojiCorrection:v}=pv(r,dv(u.normalized)),N=_n("-",rn("-",g),v)+(d===0?0:d*2),y=_n(" ",rn(" ",g),v)*8,p=d!==0;if(u.len===0)return zv();const b=[],w=[],M=[],Q=[];let B=u.chunks.length<=1&&!p;const L=s?[]:null,$=[],ee=[],ce=[],ue=s?[]:null,H=Array.from({length:u.len});function V(_,te,ne,he,Y,O,k,D,K){Y!=="text"&&Y!=="space"&&Y!=="zero-width-break"&&(B=!1),b.push(te),w.push(ne),M.push(he),Q.push(Y),L?.push(O),$.push(k),ee.push(D),p&&ce.push(K),ue!==null&&ue.push(_)}function G(_,te,ne,he,Y){const O=rn(_,g),k=p?Tx(_,te):0,D=Uv(_n(_,O,v),k,d),K=te==="space"||te==="preserved-space"||te==="zero-width-break"?0:D,P=K===0?0:K+(k>0?d:0),re=te==="space"||te==="zero-width-break"?0:D;if(Y&&he&&_.length>1){let le="sum-graphemes";d!==0?le="segment-prefixes":Sr(_)?le="pair-context":x.preferPrefixWidthsForBreakableRuns&&(le="segment-prefixes");const ae=gv(_,O,g,v,le),A=ae===null||c==="keep-all"?null:Hv(_);V(_,D,P,re,te,ne,ae,A,k);return}V(_,D,P,re,te,ne,null,null,k)}for(let _=0;_<u.len;_++){H[_]=b.length;const te=u.texts[_],ne=u.isWordLike[_],he=u.kinds[_],Y=u.starts[_];if(he==="soft-hyphen"){V(te,0,N,N,he,Y,null,null,0);continue}if(he==="hard-break"){V(te,0,0,0,he,Y,null,null,0);continue}if(he==="tab"){V(te,0,0,0,he,Y,null,null,p?Tx(te,he):0);continue}const O=rn(te,g);if(he==="text"&&O.containsCJK){const k=_v(te,x),D=c==="keep-all"?Rv(te,k,x.breakKeepAllAfterPunctuation):k;for(let K=0;K<D.length;K++){const P=D[K];G(P.text,"text",Y+P.start,ne,c==="keep-all"||!dl(P.text))}continue}G(te,he,Y,ne,!0)}const S=qv(u.chunks,H,b.length),q=L===null?null:ab(u.normalized,L);return ue!==null?{widths:b,lineEndFitAdvances:w,lineEndPaintAdvances:M,kinds:Q,simpleLineWalkFastPath:B,segLevels:q,breakableFitAdvances:$,breakablePreferredBreaks:ee,letterSpacing:d,spacingGraphemeCounts:ce,discretionaryHyphenWidth:N,tabStopAdvance:y,chunks:S,segments:ue}:{widths:b,lineEndFitAdvances:w,lineEndPaintAdvances:M,kinds:Q,simpleLineWalkFastPath:B,segLevels:q,breakableFitAdvances:$,breakablePreferredBreaks:ee,letterSpacing:d,spacingGraphemeCounts:ce,discretionaryHyphenWidth:N,tabStopAdvance:y,chunks:S}}function qv(u,r,s){const c=[];for(let d=0;d<u.length;d++){const x=u[d],g=x.startSegmentIndex<r.length?r[x.startSegmentIndex]:s,v=x.endSegmentIndex<r.length?r[x.endSegmentIndex]:s,N=x.consumedEndSegmentIndex<r.length?r[x.consumedEndSegmentIndex]:s;c.push({startSegmentIndex:g,endSegmentIndex:v,consumedEndSegmentIndex:N})}return c}function Yv(u,r,s,c){const d=c?.wordBreak??"normal",x=c?.letterSpacing??0,g=iv(u,La(),c?.whiteSpace,d);return Gv(g,r,s,d,x)}function To(u,r,s){return Yv(u,r,!0,s)}function Fx(u){let r=0;return Mv(u,Number.POSITIVE_INFINITY,s=>{s>r&&(r=s)}),r}function Xv(){db(),Nr=null,Bv(),bv()}function dr(u){return u.replace(/[ \t]+/g," ")}function Qv(u,r=[]){const s=[],c=r.filter(m=>m.length>0).map(m=>m.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),d=c.length?new RegExp(`(${c.join("|")})`,"g"):null,x=/(\*\*[^*]+\*\*|\*[^*]+\*|==[^=]+==)/g;let g=0,v;function N(m,y={}){if(!m)return;if(!d){s.push({text:m,...y});return}d.lastIndex=0;let p=0,b;for(;(b=d.exec(m))!==null;)b.index>p&&s.push({text:m.slice(p,b.index),...y}),s.push({text:b[0],...y,highlight:!0}),p=b.index+b[0].length;p<m.length&&s.push({text:m.slice(p),...y})}for(;(v=x.exec(u))!==null;){v.index>g&&N(u.slice(g,v.index));const m=v[0];m.startsWith("**")&&m.endsWith("**")?N(m.slice(2,-2),{bold:!0}):m.startsWith("*")&&m.endsWith("*")?N(m.slice(1,-1),{italic:!0}):m.startsWith("==")&&m.endsWith("==")&&s.push({text:m.slice(2,-2),highlight:!0,bold:!0}),g=v.index+m.length}return g<u.length&&N(u.slice(g)),s.length>0?s:[{text:u}]}function Vv(u){const r=u.replaceAll(`\r
|
package/dist/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
rel="stylesheet"
|
|
12
12
|
/>
|
|
13
13
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lxgw-wenkai-screen-web/style.css" />
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-CVzTRIjV.js"></script>
|
|
15
15
|
<link rel="stylesheet" crossorigin href="/assets/index-JCv_QmUn.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body class="bg-[#fafafa] dark:bg-[#000000] text-[#171717] dark:text-[#ededed] antialiased selection:bg-[#eaeaea] selection:text-[#000000] dark:selection:bg-[#333333] dark:selection:text-[#ffffff] overflow-hidden">
|
package/dist/lib/adapter.js
CHANGED
|
@@ -12,10 +12,10 @@ var CANVAS_SPECS = {
|
|
|
12
12
|
"wechat-cover-2.35": {
|
|
13
13
|
id: "wechat-cover-2.35",
|
|
14
14
|
name: "微信文章封面",
|
|
15
|
-
ratio:
|
|
16
|
-
width:
|
|
15
|
+
ratio: 3.35,
|
|
16
|
+
width: 3350,
|
|
17
17
|
height: 1000,
|
|
18
|
-
description: "
|
|
18
|
+
description: "微信文章封面原图 (3.35:1):左侧 2.35:1 大图,右侧 1:1 小图",
|
|
19
19
|
defaultSafeArea: { top: 120, right: 140, bottom: 120, left: 140 }
|
|
20
20
|
},
|
|
21
21
|
"longform-3-4": {
|
|
@@ -103,8 +103,8 @@ async function renderRemoteBatch(studioUrl, body, outputDir, route, kind) {
|
|
|
103
103
|
}
|
|
104
104
|
async function renderLocalBatch(body, outputDir, route, kind) {
|
|
105
105
|
const [{ resolveTypesetResult }, { renderTypesetResultToPngs }] = await Promise.all([
|
|
106
|
-
import("./render-
|
|
107
|
-
import("./canvas-renderer-
|
|
106
|
+
import("./render-064weavx.js"),
|
|
107
|
+
import("./canvas-renderer-wce6xgb2.js")
|
|
108
108
|
]);
|
|
109
109
|
const { result } = resolveTypesetResult(body);
|
|
110
110
|
const pngs = await renderTypesetResultToPngs(result);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
renderTypesetResultToPngs,
|
|
8
8
|
resolveDataDir,
|
|
9
9
|
validateCanvasStyle
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-697fkv5y.js";
|
|
11
11
|
import {
|
|
12
12
|
buildLineTextFromRange,
|
|
13
13
|
getLineTextCache,
|
|
@@ -2699,7 +2699,7 @@ var BUILTIN_PRESETS = [
|
|
|
2699
2699
|
{
|
|
2700
2700
|
...getDefaultConfig("wechat-cover-2.35"),
|
|
2701
2701
|
id: "tpl_wechat_cover_minimal",
|
|
2702
|
-
name: "微信纯净大图封面 (
|
|
2702
|
+
name: "微信纯净大图封面 (3.35:1)",
|
|
2703
2703
|
slot: "article_cover",
|
|
2704
2704
|
algorithm: {
|
|
2705
2705
|
...getDefaultConfig("wechat-cover-2.35").algorithm,
|
|
@@ -2754,7 +2754,7 @@ var BUILTIN_PRESETS = [
|
|
|
2754
2754
|
{
|
|
2755
2755
|
...getDefaultConfig("wechat-cover-2.35"),
|
|
2756
2756
|
id: "tpl_wechat_cover_editorial",
|
|
2757
|
-
name: "微信杂志标封面 (
|
|
2757
|
+
name: "微信杂志标封面 (3.35:1)",
|
|
2758
2758
|
slot: "article_cover",
|
|
2759
2759
|
algorithm: {
|
|
2760
2760
|
...getDefaultConfig("wechat-cover-2.35").algorithm,
|
package/dist/lib/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
plugin,
|
|
3
3
|
typesetStudioAdapter
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-dkwbnaj7.js";
|
|
5
5
|
import {
|
|
6
6
|
applyTemplateImages,
|
|
7
7
|
getDefaultConfig,
|
|
8
8
|
resolveTypesetResult,
|
|
9
9
|
runTypeset,
|
|
10
10
|
validateTemplateAssets
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-qszn98j2.js";
|
|
12
12
|
import {
|
|
13
13
|
drawPageToContext,
|
|
14
14
|
renderPageToCanvas,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
renderTypesetResultToPngs,
|
|
17
17
|
resolveCanvasFont,
|
|
18
18
|
resolveCanvasFontFamily
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-697fkv5y.js";
|
|
20
20
|
import {
|
|
21
21
|
readFontFamilyName,
|
|
22
22
|
registerServerFonts,
|
package/package.json
CHANGED
package/src/adapter.test.ts
CHANGED
|
@@ -24,7 +24,7 @@ describe("Typeset Studio — zzhub-pipeline ImageRenderPlugin Adapter", () => {
|
|
|
24
24
|
expect(fontCheck?.ok).toBe(true);
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
it("renders wechat-article
|
|
27
|
+
it("renders wechat-article 3.35:1 cover asset correctly", async () => {
|
|
28
28
|
const outDir = join(tempTestDir, "article");
|
|
29
29
|
const input: ImageRenderInput = {
|
|
30
30
|
title: "大模型架构演进:从密集注意力到专家混合架构",
|
|
@@ -57,6 +57,8 @@ describe("Typeset Studio — zzhub-pipeline ImageRenderPlugin Adapter", () => {
|
|
|
57
57
|
expect(buf[1]).toBe(0x50); // 'P'
|
|
58
58
|
expect(buf[2]).toBe(0x4e); // 'N'
|
|
59
59
|
expect(buf[3]).toBe(0x47); // 'G'
|
|
60
|
+
expect(buf.readUInt32BE(16)).toBe(3350);
|
|
61
|
+
expect(buf.readUInt32BE(20)).toBe(1000);
|
|
60
62
|
});
|
|
61
63
|
|
|
62
64
|
it("renders wechat-newspic 3:4 multi-page poster and articles", async () => {
|
|
@@ -4,7 +4,7 @@ import { renderPageToPng, renderTypesetResultToPngs } from "./canvas-renderer";
|
|
|
4
4
|
import type { PipelineCoverTheme } from "./types";
|
|
5
5
|
|
|
6
6
|
describe("Server-Side Canvas Native PNG Renderer", () => {
|
|
7
|
-
it("renders a single
|
|
7
|
+
it("renders a single 3.35:1 WeChat cover with space for the square thumbnail", async () => {
|
|
8
8
|
const config = getDefaultConfig("wechat-cover-2.35");
|
|
9
9
|
const result = runTypeset({
|
|
10
10
|
markdown: "# 纯算法无头出图测试\n基于 @napi-rs/canvas 毫秒级原生渲染",
|
|
@@ -21,6 +21,9 @@ describe("Server-Side Canvas Native PNG Renderer", () => {
|
|
|
21
21
|
expect(pngBuffer[1]).toBe(0x50);
|
|
22
22
|
expect(pngBuffer[2]).toBe(0x4e);
|
|
23
23
|
expect(pngBuffer[3]).toBe(0x47);
|
|
24
|
+
expect(pngBuffer.readUInt32BE(16)).toBe(3350);
|
|
25
|
+
expect(pngBuffer.readUInt32BE(20)).toBe(1000);
|
|
26
|
+
expect(result.canvasSpec.ratio).toBe(3.35);
|
|
24
27
|
});
|
|
25
28
|
|
|
26
29
|
it("renders multi-page 3:4 longform article into multiple PNG buffers", async () => {
|
package/src/core/geometry.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { AspectRatioType, CanvasSpec } from "./types";
|
|
2
2
|
|
|
3
3
|
export const CANVAS_SPECS: Record<AspectRatioType, CanvasSpec> = {
|
|
4
|
+
// 保留旧标识兼容已保存模板;画布包含左侧大图与右侧方形小图。
|
|
4
5
|
"wechat-cover-2.35": {
|
|
5
6
|
id: "wechat-cover-2.35",
|
|
6
7
|
name: "微信文章封面",
|
|
7
|
-
ratio:
|
|
8
|
-
width:
|
|
8
|
+
ratio: 3.35,
|
|
9
|
+
width: 3350,
|
|
9
10
|
height: 1000,
|
|
10
|
-
description: "
|
|
11
|
+
description: "微信文章封面原图 (3.35:1):左侧 2.35:1 大图,右侧 1:1 小图",
|
|
11
12
|
defaultSafeArea: { top: 120, right: 140, bottom: 120, left: 140 },
|
|
12
13
|
},
|
|
13
14
|
"longform-3-4": {
|
package/src/server/index.ts
CHANGED
|
@@ -37,6 +37,8 @@ describe("Template Slots & Fallback Compatibility", () => {
|
|
|
37
37
|
expect(data.ok).toBe(true);
|
|
38
38
|
expect(data.slot).toBe("article_cover");
|
|
39
39
|
expect(data.result.canvasSpec.id).toBe("wechat-cover-2.35");
|
|
40
|
+
expect(data.result.canvasSpec.width).toBe(3350);
|
|
41
|
+
expect(data.result.canvasSpec.height).toBe(1000);
|
|
40
42
|
});
|
|
41
43
|
|
|
42
44
|
it("renders wechat-newspic content route by auto-resolving newspic_content slot", async () => {
|
|
@@ -42,7 +42,7 @@ export const BUILTIN_PRESETS: TypesetConfig[] = [
|
|
|
42
42
|
{
|
|
43
43
|
...getDefaultConfig("wechat-cover-2.35"),
|
|
44
44
|
id: "tpl_wechat_cover_minimal",
|
|
45
|
-
name: "微信纯净大图封面 (
|
|
45
|
+
name: "微信纯净大图封面 (3.35:1)",
|
|
46
46
|
slot: "article_cover",
|
|
47
47
|
algorithm: {
|
|
48
48
|
...getDefaultConfig("wechat-cover-2.35").algorithm,
|
|
@@ -97,7 +97,7 @@ export const BUILTIN_PRESETS: TypesetConfig[] = [
|
|
|
97
97
|
{
|
|
98
98
|
...getDefaultConfig("wechat-cover-2.35"),
|
|
99
99
|
id: "tpl_wechat_cover_editorial",
|
|
100
|
-
name: "微信杂志标封面 (
|
|
100
|
+
name: "微信杂志标封面 (3.35:1)",
|
|
101
101
|
slot: "article_cover",
|
|
102
102
|
algorithm: {
|
|
103
103
|
...getDefaultConfig("wechat-cover-2.35").algorithm,
|
|
@@ -23,7 +23,7 @@ interface HeaderProps {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const RATIO_ITEMS: Array<{ id: AspectRatioType; label: string; ratioTag: string }> = [
|
|
26
|
-
{ id: "wechat-cover-2.35", label: "微信封面", ratioTag: "
|
|
26
|
+
{ id: "wechat-cover-2.35", label: "微信封面", ratioTag: "3.35:1" },
|
|
27
27
|
{ id: "longform-3-4", label: "通用长图文", ratioTag: "3:4" },
|
|
28
28
|
{ id: "wide-16-9", label: "通用宽屏", ratioTag: "16:9" },
|
|
29
29
|
{ id: "square-1-1", label: "通用正方形", ratioTag: "1:1" },
|
|
@@ -58,7 +58,7 @@ export const Header: React.FC<HeaderProps> = ({
|
|
|
58
58
|
</span>
|
|
59
59
|
<span className="hidden 2xl:inline">Typeset Studio</span>
|
|
60
60
|
</div>
|
|
61
|
-
<span className="text-xs text-[#888888] dark:text-[#555555] font-mono hidden 2xl:inline">v0.2.
|
|
61
|
+
<span className="text-xs text-[#888888] dark:text-[#555555] font-mono hidden 2xl:inline">v0.2.7</span>
|
|
62
62
|
<div title={templateName || "未命名模板"} className="flex min-w-0 items-center gap-1.5 px-2 py-0.5 rounded-full bg-[#f5f5f5] dark:bg-[#111111] border border-[#e5e5e5] dark:border-[#222222] text-[11px] text-emerald-600 dark:text-[#00e676]">
|
|
63
63
|
<span className="w-1.5 h-1.5 shrink-0 rounded-full bg-emerald-500 dark:bg-[#00e676]" />
|
|
64
64
|
<span aria-live="polite" className="max-w-40 truncate">{templateName || "未命名模板"}</span>
|
|
@@ -88,7 +88,7 @@ export const SaveTemplateModal: React.FC<SaveTemplateModalProps> = ({
|
|
|
88
88
|
<label className="flex flex-col gap-2 text-xs">
|
|
89
89
|
保存到槽位
|
|
90
90
|
<select value={saveSlot} onChange={(event) => setSaveSlot(event.target.value as TemplateSlot | "none")} className="bg-white dark:bg-[#141414] border border-[#d4d4d4] dark:border-[#333333] rounded px-3 py-2">
|
|
91
|
-
<option value="article_cover">文章封面 (
|
|
91
|
+
<option value="article_cover">文章封面 (3.35:1)</option>
|
|
92
92
|
<option value="newspic_cover">贴图封面 (3:4)</option>
|
|
93
93
|
<option value="newspic_content">贴图内容 (3:4)</option>
|
|
94
94
|
<option value="none">通用模板</option>
|