intools-cli 1.0.6 → 1.0.8
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/PLUGIN_API.md
CHANGED
|
@@ -141,56 +141,172 @@
|
|
|
141
141
|
"icon": { "type": "svg", "value": "<svg>...</svg>" }
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
## Preload
|
|
144
|
+
## Preload 预加载脚本 ⭐ 核心概念
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
> [!IMPORTANT]
|
|
147
|
+
> **Preload 是 InTools 插件访问 Node.js 能力的核心机制。** 对于需要在渲染进程(UI)中使用 Node.js API、第三方 npm 模块或 Electron 渲染进程 API 的插件来说,Preload 是**必不可少**的。
|
|
148
|
+
|
|
149
|
+
### 什么是 Preload?
|
|
150
|
+
|
|
151
|
+
Preload 脚本是一个特殊的 JavaScript 文件,在**渲染进程加载之前**执行,具有以下特点:
|
|
152
|
+
|
|
153
|
+
| 特性 | 说明 |
|
|
154
|
+
|------|------|
|
|
155
|
+
| 🔧 **Node.js 完整支持** | 可以使用 `require()` 导入任何 Node.js 原生模块和 npm 包 |
|
|
156
|
+
| 🖥️ **Electron API 访问** | 可以调用 Electron 渲染进程 API |
|
|
157
|
+
| 🌉 **桥接能力** | 通过 `window.xxx` 将原生能力暴露给前端 React/Vue 组件 |
|
|
158
|
+
| ⚡ **同步执行** | 在页面 DOM 加载前执行,确保 API 可用 |
|
|
159
|
+
|
|
160
|
+
### 适用场景
|
|
161
|
+
|
|
162
|
+
以下场景**需要使用** Preload:
|
|
163
|
+
|
|
164
|
+
- 📂 使用 `pdf-lib`、`sharp`、`ffmpeg` 等需要 Node.js 环境的 npm 包
|
|
165
|
+
- 🔐 调用 Node.js 加密模块 (`crypto`)、子进程 (`child_process`)
|
|
166
|
+
- 📁 需要比 `window.intools.filesystem` 更底层的文件操作
|
|
167
|
+
- 🔗 与本地数据库交互 (SQLite、LevelDB 等)
|
|
168
|
+
- 🎯 任何需要原生能力但又想在前端统一调用的场景
|
|
169
|
+
|
|
170
|
+
---
|
|
147
171
|
|
|
148
172
|
### 配置方式
|
|
149
173
|
|
|
174
|
+
在 `manifest.json` 中添加 `preload` 字段,指定预加载脚本路径:
|
|
175
|
+
|
|
150
176
|
```json
|
|
151
177
|
{
|
|
152
|
-
"
|
|
178
|
+
"name": "my-plugin",
|
|
179
|
+
"version": "1.0.0",
|
|
180
|
+
"displayName": "我的插件",
|
|
181
|
+
"main": "dist/main.js",
|
|
182
|
+
"ui": "ui/index.html",
|
|
183
|
+
"preload": "preload.js", // 👈 指定预加载脚本
|
|
184
|
+
"features": [...]
|
|
153
185
|
}
|
|
154
186
|
```
|
|
155
187
|
|
|
156
|
-
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
### preload.js 编写规范
|
|
157
191
|
|
|
158
192
|
```javascript
|
|
159
|
-
// preload.js -
|
|
193
|
+
// preload.js - 必须使用 CommonJS 规范
|
|
160
194
|
const fs = require('fs')
|
|
161
195
|
const os = require('os')
|
|
162
196
|
const path = require('path')
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
197
|
+
const { PDFDocument } = require('pdf-lib') // 可使用 npm 包
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 通过 window 对象暴露 API 给前端
|
|
201
|
+
* 命名建议:window.{插件名}Api 或 window.{功能名}Api
|
|
202
|
+
*/
|
|
203
|
+
window.myPluginApi = {
|
|
204
|
+
// 同步方法
|
|
166
205
|
getHomeDir: () => os.homedir(),
|
|
167
|
-
|
|
168
|
-
|
|
206
|
+
getPlatform: () => process.platform,
|
|
207
|
+
|
|
208
|
+
// 异步方法
|
|
209
|
+
readFile: async (filePath) => {
|
|
210
|
+
return fs.promises.readFile(filePath, 'utf-8')
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
// 复杂功能封装
|
|
214
|
+
mergePDFs: async (pdfPaths, outputPath) => {
|
|
215
|
+
const mergedPdf = await PDFDocument.create()
|
|
216
|
+
for (const pdfPath of pdfPaths) {
|
|
217
|
+
const pdfBytes = fs.readFileSync(pdfPath)
|
|
218
|
+
const pdf = await PDFDocument.load(pdfBytes)
|
|
219
|
+
const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices())
|
|
220
|
+
pages.forEach(page => mergedPdf.addPage(page))
|
|
221
|
+
}
|
|
222
|
+
const bytes = await mergedPdf.save()
|
|
223
|
+
fs.writeFileSync(outputPath, bytes)
|
|
224
|
+
return outputPath
|
|
225
|
+
}
|
|
169
226
|
}
|
|
227
|
+
|
|
228
|
+
console.log('[Preload] API 已挂载到 window.myPluginApi')
|
|
170
229
|
```
|
|
171
230
|
|
|
172
|
-
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
### 前端调用示例
|
|
173
234
|
|
|
174
|
-
```
|
|
175
|
-
// 在
|
|
176
|
-
|
|
177
|
-
const content = window.myApi?.readFile('/path/to/file.txt')
|
|
235
|
+
```tsx
|
|
236
|
+
// 在 React 组件中调用
|
|
237
|
+
import { useEffect, useState } from 'react'
|
|
178
238
|
|
|
179
|
-
//
|
|
180
|
-
|
|
239
|
+
// 类型声明(推荐单独放在 types.d.ts)
|
|
240
|
+
declare global {
|
|
241
|
+
interface Window {
|
|
242
|
+
myPluginApi?: {
|
|
243
|
+
getHomeDir: () => string
|
|
244
|
+
getPlatform: () => string
|
|
245
|
+
readFile: (path: string) => Promise<string>
|
|
246
|
+
mergePDFs: (paths: string[], output: string) => Promise<string>
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function MyComponent() {
|
|
252
|
+
const [homeDir, setHomeDir] = useState('')
|
|
253
|
+
|
|
254
|
+
useEffect(() => {
|
|
255
|
+
// 使用可选链确保安全访问
|
|
256
|
+
if (window.myPluginApi) {
|
|
257
|
+
setHomeDir(window.myPluginApi.getHomeDir())
|
|
258
|
+
}
|
|
259
|
+
}, [])
|
|
260
|
+
|
|
261
|
+
const handleMerge = async () => {
|
|
262
|
+
const result = await window.myPluginApi?.mergePDFs(
|
|
263
|
+
['/path/to/1.pdf', '/path/to/2.pdf'],
|
|
264
|
+
'/path/to/merged.pdf'
|
|
265
|
+
)
|
|
266
|
+
console.log('合并完成:', result)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// 核心 API 仍然可用
|
|
270
|
+
const handleCopy = async () => {
|
|
271
|
+
const text = await window.intools.clipboard.readText()
|
|
272
|
+
console.log('剪贴板内容:', text)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return <div>Home: {homeDir}</div>
|
|
276
|
+
}
|
|
181
277
|
```
|
|
182
278
|
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
### 与 Main 后端的区别
|
|
282
|
+
|
|
283
|
+
| 对比项 | Preload 脚本 | Main 后端 (main.js) |
|
|
284
|
+
|--------|--------------|---------------------|
|
|
285
|
+
| 执行环境 | 渲染进程(带 Node.js 权限) | 独立 Worker 进程 |
|
|
286
|
+
| 调用方式 | `window.xxxApi.method()` | `window.intools.host.invoke()` |
|
|
287
|
+
| 适合场景 | 同步操作、UI 紧密相关的原生功能 | 后台任务、长时间运行的操作 |
|
|
288
|
+
| 进程通信 | 无需 IPC,直接调用 | 需要 IPC,异步调用 |
|
|
289
|
+
| 生命周期 | 随 UI 窗口创建/销毁 | 独立管理,可持久化 |
|
|
290
|
+
|
|
291
|
+
> [!TIP]
|
|
292
|
+
> **选择建议**:如果功能与 UI 紧密相关且需要快速响应,使用 **Preload**;如果是后台任务或需要在无 UI 时运行,使用 **Main 后端**。
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
183
296
|
### 注意事项
|
|
184
297
|
|
|
185
298
|
| 项目 | 说明 |
|
|
186
299
|
|------|------|
|
|
187
|
-
| 文件格式 | CommonJS 格式,使用 `require()` 导入模块 |
|
|
188
|
-
| 代码规范 |
|
|
189
|
-
| 可用模块 | Node.js 原生模块 +
|
|
190
|
-
| API 暴露 | 通过 `window.xxx`
|
|
191
|
-
| 核心 API | `window.intools` 核心 API
|
|
192
|
-
| 安全性 |
|
|
193
|
-
| 打包 |
|
|
300
|
+
| 📝 文件格式 | **必须是 CommonJS** 格式,使用 `require()` 导入模块 |
|
|
301
|
+
| 🔍 代码规范 | 必须是清晰可读的源码,**禁止压缩/混淆**(安全审查需要) |
|
|
302
|
+
| 📦 可用模块 | Node.js 原生模块 + 已安装的 npm 包 |
|
|
303
|
+
| 🌐 API 暴露 | 通过 `window.xxx` 暴露,建议使用 `window.{插件名}Api` 命名 |
|
|
304
|
+
| 🔧 核心 API | `window.intools` 核心 API 在 Preload 环境中**仍然可用** |
|
|
305
|
+
| ⚠️ 安全性 | 拥有完整 Node.js 权限,**请谨慎处理用户输入** |
|
|
306
|
+
| 📦 打包 | `intools pack` 会自动包含 preload 及其依赖 |
|
|
307
|
+
|
|
308
|
+
> [!CAUTION]
|
|
309
|
+
> Preload 脚本拥有完整的 Node.js 权限,可以访问文件系统、网络等敏感资源。请确保代码安全,避免执行不可信的用户输入。
|
|
194
310
|
|
|
195
311
|
---
|
|
196
312
|
|
|
@@ -215,7 +331,7 @@ const text = await window.intools.clipboard.readText()
|
|
|
215
331
|
| 方法 | 环境 | 说明 |
|
|
216
332
|
|------|------|------|
|
|
217
333
|
| `readFile(path, encoding?)` | R/B | 读取文件 → `Buffer | string` |
|
|
218
|
-
| `writeFile(path, data, encoding?)` | R/B | 写入文件 |
|
|
334
|
+
| `writeFile(path, data, encoding?)` | R/B | 写入文件 (`data`: `string \| Buffer \| ArrayBuffer`) |
|
|
219
335
|
| `exists(path)` | R/B | 检查是否存在 → `boolean` |
|
|
220
336
|
| `unlink(path)` | R/B | 删除文件 |
|
|
221
337
|
| `readdir(path)` | R/B | 读取目录 → `string[]` |
|
|
@@ -281,10 +397,10 @@ const text = await window.intools.clipboard.readText()
|
|
|
281
397
|
|
|
282
398
|
| 方法 | 环境 | 说明 |
|
|
283
399
|
|------|------|------|
|
|
284
|
-
| `request(options)` | R/B | 发起请求 → `HttpResponse` |
|
|
400
|
+
| `request(options)` | R/B | 发起请求 (`body`: `string \| object \| Buffer \| ArrayBuffer`) → `HttpResponse` |
|
|
285
401
|
| `get(url, headers?)` | R/B | GET 请求 |
|
|
286
|
-
| `post(url, body?, headers?)` | R/B | POST 请求 |
|
|
287
|
-
| `put(url, body?, headers?)` | R/B | PUT 请求 |
|
|
402
|
+
| `post(url, body?, headers?)` | R/B | POST 请求 (`body`: `string \| object \| Buffer \| ArrayBuffer`) |
|
|
403
|
+
| `put(url, body?, headers?)` | R/B | PUT 请求 (`body`: `string \| object \| Buffer \| ArrayBuffer`) |
|
|
288
404
|
| `delete(url, headers?)` | R/B | DELETE 请求 |
|
|
289
405
|
|
|
290
406
|
**HttpRequestOptions**: `url`, `method`, `headers`, `body`, `timeout`
|
|
@@ -332,7 +448,7 @@ const text = await window.intools.clipboard.readText()
|
|
|
332
448
|
| 方法 | 环境 | 说明 |
|
|
333
449
|
|------|------|------|
|
|
334
450
|
| `hideMainWindowPasteText(text)` | R/B | 粘贴文本到焦点应用 |
|
|
335
|
-
| `hideMainWindowPasteImage(image)` | R/B | 粘贴图片到焦点应用 |
|
|
451
|
+
| `hideMainWindowPasteImage(image)` | R/B | 粘贴图片到焦点应用 (`image`: `Path \| Buffer \| DataURL \| ArrayBuffer`) |
|
|
336
452
|
| `hideMainWindowPasteFile(paths)` | R/B | 粘贴文件到焦点应用 |
|
|
337
453
|
| `hideMainWindowTypeString(text)` | R/B | 模拟键入文本 |
|
|
338
454
|
| `simulateKeyboardTap(key, ...modifiers)` | R/B | 模拟按键 |
|
|
@@ -489,7 +605,7 @@ const text = await window.intools.clipboard.readText()
|
|
|
489
605
|
|------|------|------|
|
|
490
606
|
| `isEncryptionAvailable()` | R/B | 检查加密可用性 |
|
|
491
607
|
| `encryptString(plainText)` | R/B | 加密字符串 → `Buffer` |
|
|
492
|
-
| `decryptString(encrypted)` | R/B | 解密字符串 → `string` |
|
|
608
|
+
| `decryptString(encrypted)` | R/B | 解密字符串 (`encrypted`: `Buffer \| ArrayBuffer`) → `string` |
|
|
493
609
|
|
|
494
610
|
---
|
|
495
611
|
|
|
@@ -55,6 +55,14 @@ async function createBasicProject(targetDir, name) {
|
|
|
55
55
|
const mainTs = (0, basic_1.buildBasicMain)(name);
|
|
56
56
|
fs.writeFileSync(path.join(targetDir, 'src/main.ts'), mainTs);
|
|
57
57
|
console.log(chalk_1.default.green(' ✓ src/main.ts'));
|
|
58
|
+
// 创建 .gitignore
|
|
59
|
+
const gitignore = (0, basic_1.buildGitignore)();
|
|
60
|
+
fs.writeFileSync(path.join(targetDir, '.gitignore'), gitignore);
|
|
61
|
+
console.log(chalk_1.default.green(' ✓ .gitignore'));
|
|
62
|
+
// 创建 README.md
|
|
63
|
+
const readme = (0, basic_1.buildBasicReadme)(name);
|
|
64
|
+
fs.writeFileSync(path.join(targetDir, 'README.md'), readme);
|
|
65
|
+
console.log(chalk_1.default.green(' ✓ README.md'));
|
|
58
66
|
// 复制 API 参考文档
|
|
59
67
|
const apiDocSrc = path.join(__dirname, '../../..', 'PLUGIN_API.md');
|
|
60
68
|
if (fs.existsSync(apiDocSrc)) {
|
|
@@ -54,6 +54,8 @@ async function createReactProject(targetDir, name) {
|
|
|
54
54
|
createBackendMain(targetDir, name);
|
|
55
55
|
createReactUI(targetDir, name);
|
|
56
56
|
createIntoolsTypes(targetDir);
|
|
57
|
+
createGitignore(targetDir);
|
|
58
|
+
createReadme(targetDir, name);
|
|
57
59
|
// 复制 API 参考文档
|
|
58
60
|
const apiDocSrc = path.join(__dirname, '../../..', 'PLUGIN_API.md');
|
|
59
61
|
if (fs.existsSync(apiDocSrc)) {
|
|
@@ -110,3 +112,13 @@ function createIntoolsTypes(targetDir) {
|
|
|
110
112
|
fs.writeFileSync(path.join(targetDir, 'src/types/intools.d.ts'), typesDts);
|
|
111
113
|
console.log(chalk_1.default.green(' ✓ src/types/intools.d.ts'));
|
|
112
114
|
}
|
|
115
|
+
function createGitignore(targetDir) {
|
|
116
|
+
const gitignore = (0, react_1.buildGitignore)();
|
|
117
|
+
fs.writeFileSync(path.join(targetDir, '.gitignore'), gitignore);
|
|
118
|
+
console.log(chalk_1.default.green(' ✓ .gitignore'));
|
|
119
|
+
}
|
|
120
|
+
function createReadme(targetDir, name) {
|
|
121
|
+
const readme = (0, react_1.buildReactReadme)(name);
|
|
122
|
+
fs.writeFileSync(path.join(targetDir, 'README.md'), readme);
|
|
123
|
+
console.log(chalk_1.default.green(' ✓ README.md'));
|
|
124
|
+
}
|
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.buildBasicManifest = buildBasicManifest;
|
|
4
4
|
exports.buildBasicPackageJson = buildBasicPackageJson;
|
|
5
5
|
exports.buildBasicMain = buildBasicMain;
|
|
6
|
+
exports.buildGitignore = buildGitignore;
|
|
7
|
+
exports.buildBasicReadme = buildBasicReadme;
|
|
6
8
|
function buildBasicManifest(name) {
|
|
7
9
|
return {
|
|
8
10
|
id: name,
|
|
@@ -93,3 +95,68 @@ const plugin = { onLoad, onUnload, onEnable, onDisable, run }
|
|
|
93
95
|
export default plugin
|
|
94
96
|
`;
|
|
95
97
|
}
|
|
98
|
+
function buildGitignore() {
|
|
99
|
+
return `node_modules
|
|
100
|
+
dist
|
|
101
|
+
.DS_Store
|
|
102
|
+
*.log
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
105
|
+
function buildBasicReadme(name) {
|
|
106
|
+
return `# ${name}
|
|
107
|
+
|
|
108
|
+
插件描述
|
|
109
|
+
|
|
110
|
+
## 功能特性
|
|
111
|
+
|
|
112
|
+
- 功能 1
|
|
113
|
+
- 功能 2
|
|
114
|
+
- 功能 3
|
|
115
|
+
|
|
116
|
+
## 触发方式
|
|
117
|
+
|
|
118
|
+
- \`${name}\` - 主功能
|
|
119
|
+
|
|
120
|
+
## 开发
|
|
121
|
+
|
|
122
|
+
### 安装依赖
|
|
123
|
+
|
|
124
|
+
\`\`\`bash
|
|
125
|
+
npm install
|
|
126
|
+
\`\`\`
|
|
127
|
+
|
|
128
|
+
### 开发模式
|
|
129
|
+
|
|
130
|
+
\`\`\`bash
|
|
131
|
+
npm run dev
|
|
132
|
+
\`\`\`
|
|
133
|
+
|
|
134
|
+
### 构建
|
|
135
|
+
|
|
136
|
+
\`\`\`bash
|
|
137
|
+
npm run build
|
|
138
|
+
\`\`\`
|
|
139
|
+
|
|
140
|
+
### 打包
|
|
141
|
+
|
|
142
|
+
\`\`\`bash
|
|
143
|
+
npm run pack
|
|
144
|
+
\`\`\`
|
|
145
|
+
|
|
146
|
+
## 项目结构
|
|
147
|
+
|
|
148
|
+
\`\`\`
|
|
149
|
+
${name}/
|
|
150
|
+
├── manifest.json # 插件配置
|
|
151
|
+
├── package.json
|
|
152
|
+
├── src/
|
|
153
|
+
│ └── main.ts # 后端入口
|
|
154
|
+
├── dist/ # 构建输出
|
|
155
|
+
└── icon.png # 插件图标
|
|
156
|
+
\`\`\`
|
|
157
|
+
|
|
158
|
+
## 许可证
|
|
159
|
+
|
|
160
|
+
MIT License
|
|
161
|
+
`;
|
|
162
|
+
}
|
|
@@ -10,6 +10,8 @@ exports.buildMainTsx = buildMainTsx;
|
|
|
10
10
|
exports.buildAppTsx = buildAppTsx;
|
|
11
11
|
exports.buildStylesCss = buildStylesCss;
|
|
12
12
|
exports.buildUseIntools = buildUseIntools;
|
|
13
|
+
exports.buildGitignore = buildGitignore;
|
|
14
|
+
exports.buildReactReadme = buildReactReadme;
|
|
13
15
|
exports.buildIntoolsTypes = buildIntoolsTypes;
|
|
14
16
|
function buildReactManifest(name) {
|
|
15
17
|
return {
|
|
@@ -676,6 +678,82 @@ export function useIntools(pluginId?: string) {
|
|
|
676
678
|
}
|
|
677
679
|
`;
|
|
678
680
|
}
|
|
681
|
+
function buildGitignore() {
|
|
682
|
+
return `node_modules
|
|
683
|
+
dist
|
|
684
|
+
ui
|
|
685
|
+
.DS_Store
|
|
686
|
+
*.log
|
|
687
|
+
`;
|
|
688
|
+
}
|
|
689
|
+
function buildReactReadme(name) {
|
|
690
|
+
return `# ${name}
|
|
691
|
+
|
|
692
|
+
插件描述
|
|
693
|
+
|
|
694
|
+
## 功能特性
|
|
695
|
+
|
|
696
|
+
- 功能 1
|
|
697
|
+
- 功能 2
|
|
698
|
+
- 功能 3
|
|
699
|
+
|
|
700
|
+
## 触发方式
|
|
701
|
+
|
|
702
|
+
- \`${name}\` - 主功能
|
|
703
|
+
|
|
704
|
+
## 开发
|
|
705
|
+
|
|
706
|
+
### 安装依赖
|
|
707
|
+
|
|
708
|
+
\`\`\`bash
|
|
709
|
+
npm install
|
|
710
|
+
\`\`\`
|
|
711
|
+
|
|
712
|
+
### 开发模式
|
|
713
|
+
|
|
714
|
+
\`\`\`bash
|
|
715
|
+
npm run dev
|
|
716
|
+
\`\`\`
|
|
717
|
+
|
|
718
|
+
### 构建
|
|
719
|
+
|
|
720
|
+
\`\`\`bash
|
|
721
|
+
npm run build
|
|
722
|
+
\`\`\`
|
|
723
|
+
|
|
724
|
+
### 打包
|
|
725
|
+
|
|
726
|
+
\`\`\`bash
|
|
727
|
+
npm run pack
|
|
728
|
+
\`\`\`
|
|
729
|
+
|
|
730
|
+
## 项目结构
|
|
731
|
+
|
|
732
|
+
\`\`\`
|
|
733
|
+
${name}/
|
|
734
|
+
├── manifest.json # 插件配置
|
|
735
|
+
├── package.json
|
|
736
|
+
├── src/
|
|
737
|
+
│ ├── main.ts # 后端入口
|
|
738
|
+
│ ├── ui/
|
|
739
|
+
│ │ ├── App.tsx # 主应用
|
|
740
|
+
│ │ ├── main.tsx # UI 入口
|
|
741
|
+
│ │ ├── index.html # HTML 模板
|
|
742
|
+
│ │ ├── styles.css # 全局样式
|
|
743
|
+
│ │ ├── hooks/
|
|
744
|
+
│ │ │ └── useIntools.ts # InTools API Hook
|
|
745
|
+
│ │ └── types/
|
|
746
|
+
│ │ └── intools.d.ts # 类型定义
|
|
747
|
+
├── dist/ # 后端构建输出
|
|
748
|
+
├── ui/ # UI 构建输出
|
|
749
|
+
└── icon.png # 插件图标
|
|
750
|
+
\`\`\`
|
|
751
|
+
|
|
752
|
+
## 许可证
|
|
753
|
+
|
|
754
|
+
MIT License
|
|
755
|
+
`;
|
|
756
|
+
}
|
|
679
757
|
function buildIntoolsTypes() {
|
|
680
758
|
return `// InTools API 类型定义
|
|
681
759
|
|