@loadingman/pdf_cli 1.0.5

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 ADDED
@@ -0,0 +1,320 @@
1
+ # pdf-cli
2
+
3
+ [![License](https://img.shields.io/badge/License-UNLICENSED-lightgrey.svg)](#许可证)
4
+ [![Go Version](https://img.shields.io/badge/go-%3E%3D1.17-blue.svg)](https://go.dev/)
5
+ [![npm version](https://img.shields.io/npm/v/@loadingman/pdf_cli.svg)](https://www.npmjs.com/package/@loadingman/pdf_cli)
6
+
7
+ PDF 翻译与 PDF 工具命令行客户端。覆盖 PDF 翻译、合并、转换、拆分、压缩、加密、页面操作、内容提取等核心场景。
8
+
9
+ [安装](#安装与快速开始) · [认证](#认证) · [命令总览](#命令总览) · [高级用法](#高级用法) · [配置](#配置) · [详细文档](#详细文档)
10
+
11
+ ## 为什么用 pdf-cli?
12
+
13
+ - **覆盖广** — 翻译、工具、用户、会员四大模块,60+ 子命令,对应官方接口
14
+ - **异步友好** — tools 全链路自动轮询任务状态,超时仍返回 `queryKey` 便于后续手动恢复
15
+ - **多种输出** — `--format json/pretty/table` 三种格式,错误统一为 JSON envelope,方便脚本接管
16
+ - **零依赖二进制** — Go 静态编译,无运行时依赖,单文件即可使用
17
+ - **两种安装方式** — npm 一键安装预编译二进制,或从源码 `make install`
18
+
19
+ ## 功能模块
20
+
21
+ | 模块 | 能力 |
22
+ | --------------- | ---------------------------------------------------------------------------------------------------------- |
23
+ | 🌐 translate | PDF 文档翻译、AI 文本翻译、arXiv 取译、引擎/语种枚举、任务状态轮询、历史记录 |
24
+ | 🛠 tools | 合并、PDF 转 Word、拆分、重排、旋转、页面提取/删除、页码、压缩、水印、叠加、提取图片/文本、元数据、加解密 |
25
+ | 🔐 auth | 邮箱密码登录、登录状态、登出 |
26
+ | 👤 user | 个人资料、上传文件、使用记录、API Key 管理、反馈提交 |
27
+ | 💎 member | 会员信息、权益、定价、订单、兑换码 |
28
+ | 📢 other | 公告、版本历史、使用指南 |
29
+
30
+ ## 安装与快速开始
31
+
32
+ ### 环境要求
33
+
34
+ 开始之前请确认:
35
+
36
+ - Node.js(`npm` / `npx`)—— 仅 npm 安装方式需要
37
+ - Go `v1.17`+ —— 仅从源码安装时需要
38
+
39
+ ### 安装
40
+
41
+ 从以下两种方式中任选其一:
42
+
43
+ **方式一 — 从 npm 安装(推荐):**
44
+
45
+ ```bash
46
+ npm install -g @loadingman/pdf_cli
47
+
48
+ # 安装 CLI SKILL(必需)
49
+ npx skills add @loadingman/pdf_cli -y -g
50
+ ```
51
+
52
+ `postinstall` 会根据当前平台(darwin / linux / windows × x64 / arm64)自动从 GitHub Release 下载对应的预编译二进制,并把 `pdf-cli` 命令注册到 PATH。
53
+
54
+ **方式二 — 从源码安装:**
55
+
56
+ 需要 Go `v1.17`+。
57
+
58
+ ```bash
59
+ git clone https://gitee.com/loadingmans/pdf_cli.git
60
+ cd pdf_cli
61
+ make install
62
+
63
+ # 安装 CLI SKILL(必需)
64
+ npx skills add @loadingman/pdf_cli -y -g
65
+ ```
66
+
67
+ `make install` 会编译并安装到 `/usr/local/bin/pdf-cli`。如需自定义路径:
68
+
69
+ ```bash
70
+ make install PREFIX=$HOME/.local
71
+ ```
72
+
73
+ ### 配置与使用
74
+
75
+ ```bash
76
+ # 1. 登录(密码以隐藏方式交互输入)
77
+ pdf-cli auth login --email you@example.com
78
+
79
+ # 2. 翻译 PDF(异步:上传 → 启动 → 轮询 → 下载)
80
+ pdf-cli translate upload --file ./paper.pdf
81
+ pdf-cli translate start --file-key <key> --to zh
82
+ pdf-cli translate status --task-id <id> --wait
83
+ pdf-cli translate download --task-id <id> -o paper.zh.pdf
84
+
85
+ # 3. PDF 工具
86
+ pdf-cli tools merge --files a.pdf,b.pdf,c.pdf
87
+ pdf-cli tools convert pdf-to-word --file document.pdf
88
+ pdf-cli tools page extract --file document.pdf --pages 1-3
89
+ pdf-cli tools job status --query-key <key>
90
+ ```
91
+
92
+ 执行 `pdf-cli --help` 查看所有命令。
93
+
94
+ ## 认证
95
+
96
+ | 命令 | 说明 |
97
+ | ------------- | -------------------------- |
98
+ | `auth login` | 邮箱密码登录,密码隐藏输入 |
99
+ | `auth status` | 查看当前登录身份与 token |
100
+ | `auth logout` | 注销并清除本地凭证 |
101
+
102
+ ```bash
103
+ pdf-cli auth login --email you@example.com
104
+ pdf-cli auth status
105
+ pdf-cli auth logout
106
+ ```
107
+
108
+ 凭证保存在 `~/.config/pdf-cli/config.json`(权限 `0600`),包含 `token` 和稳定的 `device_id`。
109
+
110
+ ## 命令总览
111
+
112
+ ### translate — 翻译
113
+
114
+ ```bash
115
+ pdf-cli translate languages
116
+ pdf-cli translate engines
117
+ pdf-cli translate upload --file ./paper.pdf
118
+ pdf-cli translate start --file-key <key> --to zh
119
+ pdf-cli translate start --file-key <key> --to zh --from en
120
+ pdf-cli translate free --file ./paper.pdf --to zh
121
+ pdf-cli translate arxiv --arxiv-id 2401.00001 --to zh
122
+ pdf-cli translate text --text "hello world" --to zh
123
+ pdf-cli translate status --task-id <id>
124
+ pdf-cli translate status --task-id <id> --wait
125
+ pdf-cli translate download --task-id <id> -o result.pdf
126
+ pdf-cli translate history
127
+ pdf-cli translate history --page 2 --page-size 10
128
+ ```
129
+
130
+ ### tools — PDF 工具
131
+
132
+ ```bash
133
+ # 合并
134
+ pdf-cli tools merge --files a.pdf,b.pdf,c.pdf
135
+ pdf-cli tools merge --files a.pdf,b.pdf --create-bookmarks
136
+
137
+ # 转换
138
+ pdf-cli tools convert pdf-to-word --file document.pdf
139
+
140
+ # 拆分
141
+ pdf-cli tools split --file document.pdf --mode pages-per-pdf --pages-per-pdf 2
142
+ pdf-cli tools split --file document.pdf --mode even-odd
143
+ pdf-cli tools split --file document.pdf --mode cut-in-half
144
+ pdf-cli tools split --file document.pdf --mode custom --split-points 2,5
145
+
146
+ # 页面操作
147
+ pdf-cli tools reorder --file document.pdf --order 3,1,2
148
+ pdf-cli tools rotate --file document.pdf --pages 1,2 --angle 90
149
+ pdf-cli tools page extract --file document.pdf --pages 1-3,5
150
+ pdf-cli tools page delete --file document.pdf --pages 2,4
151
+ pdf-cli tools page-number add --file document.pdf --pattern "{NUM}/{CNT}"
152
+
153
+ # 压缩与水印
154
+ pdf-cli tools compress --file large.pdf --dpi 144 --image-quality 75
155
+ pdf-cli tools compress --file large.pdf --color-mode gray
156
+ pdf-cli tools watermark --file document.pdf --text "CONFIDENTIAL"
157
+ pdf-cli tools overlay --file base.pdf --overlay-file overlay.pdf --position foreground
158
+
159
+ # 提取内容
160
+ pdf-cli tools extract image --file document.pdf
161
+ pdf-cli tools extract text --file document.pdf
162
+
163
+ # 元数据
164
+ pdf-cli tools metadata set --file document.pdf --title "My Doc" --author "Alice"
165
+ pdf-cli tools metadata remove --file document.pdf
166
+
167
+ # 加密 / 解密
168
+ pdf-cli tools security encrypt --file document.pdf --password 123456
169
+ pdf-cli tools security decrypt --file encrypted.pdf --password 123456
170
+
171
+ # 异步任务管理
172
+ pdf-cli tools job status --query-key <key>
173
+ pdf-cli tools job download --query-key <key> -o result.pdf
174
+ ```
175
+
176
+ ### user — 用户
177
+
178
+ ```bash
179
+ pdf-cli user profile
180
+ pdf-cli user update --name Alice
181
+ pdf-cli user files list
182
+ pdf-cli user records list
183
+ pdf-cli user records get --id 101
184
+ pdf-cli user api-key list
185
+ pdf-cli user api-key create --name "my-key"
186
+ pdf-cli user api-key delete --id 1
187
+ pdf-cli user feedback submit --title "标题" --content "内容"
188
+ ```
189
+
190
+ ### member — 会员
191
+
192
+ ```bash
193
+ pdf-cli member info
194
+ pdf-cli member rights
195
+ pdf-cli member pricing
196
+ pdf-cli member order list
197
+ pdf-cli member order get --order-no ORD123
198
+ pdf-cli member redeem --code XXXX-XXXX-XXXX
199
+ ```
200
+
201
+ ### other — 其他
202
+
203
+ ```bash
204
+ pdf-cli other version
205
+ pdf-cli other notice
206
+ pdf-cli other help-guide
207
+ ```
208
+
209
+ ## 高级用法
210
+
211
+ ### 输出格式
212
+
213
+ 全局 `--format` 标志影响所有命令:
214
+
215
+ ```bash
216
+ --format pretty # 人类友好对齐输出(默认)
217
+ --format json # 完整 JSON 响应,错误也包成 JSON envelope
218
+ --format table # ASCII 表格
219
+ ```
220
+
221
+ ```bash
222
+ pdf-cli user profile --format json
223
+ pdf-cli translate history --format table
224
+ ```
225
+
226
+ ### 输出到文件
227
+
228
+ ```bash
229
+ pdf-cli translate download --task-id <id> -o ./out/result.pdf
230
+ pdf-cli user profile --format json --output profile.json
231
+ ```
232
+
233
+ `--output` 既可指向文件,也可指向目录(自动追加默认文件名)。
234
+
235
+ ### 异步任务链路
236
+
237
+ tools 子命令底层都是异步任务,CLI 会自动轮询直到完成或超时(默认每 2 秒一次,最多 120 次 ≈ 4 分钟)。超时不会丢失任务,会打印 `queryKey` 让你之后用 `tools job status / download` 继续:
238
+
239
+ ```text
240
+ 1. POST core/tools/box/file/aws/pre/upload # 申请预签名上传
241
+ 2. POST core/tools/box/file/new/upload # 注册上传记录
242
+ 3. POST core/tools/todo/operate # 启动操作,得到 queryKey
243
+ 4. GET core/tools/operate/status?queryKey=... # 轮询状态
244
+ 5. 下载结果文件
245
+ ```
246
+
247
+ ### 退出码
248
+
249
+ | Code | 含义 |
250
+ | ---- | -------------------------- |
251
+ | 0 | 成功 |
252
+ | 2 | 用法错误(参数解析失败) |
253
+ | 3 | 参数校验失败 |
254
+ | 11 | 未登录或登录态失效 |
255
+ | 14 | 任务执行失败 |
256
+
257
+ 便于 shell 脚本根据退出码做不同分支。
258
+
259
+ ## 配置
260
+
261
+ 配置文件位于 `~/.config/pdf-cli/config.json`,目录权限 `0700`,文件权限 `0600`:
262
+
263
+ ```json
264
+ {
265
+ "token": "登录后自动保存",
266
+ "device_id": "首次登录自动生成的 UUID",
267
+ "base_url": "主服务地址",
268
+ "tool_url": "工具服务地址",
269
+ "download_url": "文件下载基地址",
270
+ "format": "默认输出格式(pretty/json/table)"
271
+ }
272
+ ```
273
+
274
+ `device_id` 在 `auth logout` 后仍会保留,避免设备指纹漂移。
275
+
276
+ ## 详细文档
277
+
278
+ 各模块完整命令、参数说明、接口映射见 [document/](./document/) 目录:
279
+
280
+ | 文档 | 说明 |
281
+ | --------------------------------------------- | ----------------------------- |
282
+ | [index.md](./document/index.md) | 文档总入口 |
283
+ | [cli-report.md](./document/cli-report.md) | 完整 CLI 行为参考 |
284
+ | [api-mapping.md](./document/api-mapping.md) | CLI 命令到后端接口的映射 |
285
+ | [async-flows.md](./document/async-flows.md) | 异步任务与 queryKey 流程 |
286
+ | [end-to-end.md](./document/end-to-end.md) | 端到端示例工作流 |
287
+ | [errors.md](./document/errors.md) | 错误码与异常处理 |
288
+ | [conventions.md](./document/conventions.md) | 代码与命令命名约定 |
289
+ | [proposal.md](./document/proposal.md) | 设计提案与决策记录 |
290
+
291
+ ## 维护者发布流程
292
+
293
+ 仅项目维护者需要关注。完整链路在 [scripts/](./scripts/):
294
+
295
+ ```bash
296
+ # 1. bump package.json 版本,提交并推送
297
+ # 2. 打 tag(脚本会做前置检查)
298
+ bash scripts/tag-release.sh
299
+
300
+ # 3. 交叉编译 6 个平台二进制到 dist/
301
+ bash scripts/release.sh
302
+
303
+ # 4. 把 dist/ 下产物上传到对应 GitHub Release
304
+ gh release upload "$(node -p "require('./package.json').version")" dist/pdf-cli-*.{tar.gz,zip}
305
+
306
+ # 5. 发布 npm 包
307
+ npm publish --access public
308
+ ```
309
+
310
+ 注意:当前 tag 命名约定是裸版本号(`1.0.0`),不带 `v` 前缀,与 [scripts/install.js](./scripts/install.js) 拼接的 Release URL 保持一致。
311
+
312
+ ## 说明
313
+
314
+ - 当前 CLI 仅暴露 README 中列出的 tools 子命令。
315
+ - `convert` 当前只暴露 `pdf-to-word`;提取文本请使用 `extract text`。
316
+ - `tools job status` 与 `tools job download` 主参数为 `--query-key`,`--job-id` 仅保留兼容。
317
+
318
+ ## 许可证
319
+
320
+ UNLICENSED — 内部使用。详见 [package.json](./package.json)。
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@loadingman/pdf_cli",
3
+ "version": "1.0.5",
4
+ "description": "PDF translation and PDF tools CLI — translate PDFs, merge, split, compress, encrypt, extract pages and more",
5
+ "keywords": [
6
+ "pdf",
7
+ "cli",
8
+ "pdf-translate",
9
+ "pdf-tools",
10
+ "pdf-merge",
11
+ "pdf-split",
12
+ "pdf-compress",
13
+ "pdf-to-word"
14
+ ],
15
+ "homepage": "https://gitee.com/loadingmans/pdf_cli#readme",
16
+ "bugs": {
17
+ "url": "https://gitee.com/loadingmans/pdf_cli/issues"
18
+ },
19
+ "bin": {
20
+ "pdf-cli": "scripts/run.js"
21
+ },
22
+ "scripts": {
23
+ "postinstall": "node scripts/install.js"
24
+ },
25
+ "os": [
26
+ "darwin",
27
+ "linux",
28
+ "win32"
29
+ ],
30
+ "cpu": [
31
+ "x64",
32
+ "arm64"
33
+ ],
34
+ "engines": {
35
+ "node": ">=16"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://gitee.com/loadingmans/pdf_cli.git"
40
+ },
41
+ "license": "UNLICENSED",
42
+ "files": [
43
+ "scripts/install.js",
44
+ "scripts/run.js"
45
+ ]
46
+ }
@@ -0,0 +1,86 @@
1
+ const fs = require("fs");
2
+ const os = require("os");
3
+ const path = require("path");
4
+ const { execSync } = require("child_process");
5
+
6
+ const VERSION = require("../package.json").version;
7
+ const REPO = "loadingmans/pdf_cli";
8
+ const NAME = "pdf-cli";
9
+
10
+ const PLATFORM_MAP = {
11
+ darwin: "darwin",
12
+ linux: "linux",
13
+ win32: "windows",
14
+ };
15
+
16
+ const ARCH_MAP = {
17
+ x64: "amd64",
18
+ arm64: "arm64",
19
+ };
20
+
21
+ const platform = PLATFORM_MAP[process.platform];
22
+ const arch = ARCH_MAP[process.arch];
23
+
24
+ if (!platform || !arch) {
25
+ console.error(`Unsupported platform: ${process.platform}-${process.arch}`);
26
+ process.exit(1);
27
+ }
28
+
29
+ const isWindows = process.platform === "win32";
30
+ const ext = isWindows ? ".zip" : ".tar.gz";
31
+ const archiveName = `${NAME}-${VERSION}-${platform}-${arch}${ext}`;
32
+ const releaseURL = `https://gitee.com/${REPO}/releases/download/v${VERSION}/${archiveName}`;
33
+
34
+ const binDir = path.join(__dirname, "..", "bin");
35
+ const dest = path.join(binDir, NAME + (isWindows ? ".exe" : ""));
36
+
37
+ fs.mkdirSync(binDir, { recursive: true });
38
+
39
+ function download(url, destPath) {
40
+ const sslFlag = isWindows ? "--ssl-revoke-best-effort " : "";
41
+ execSync(
42
+ `curl ${sslFlag}--fail --location --silent --show-error --connect-timeout 10 --max-time 120 --output "${destPath}" "${url}"`,
43
+ { stdio: ["ignore", "ignore", "pipe"] }
44
+ );
45
+ }
46
+
47
+ function extract(archivePath, tmpDir) {
48
+ if (isWindows) {
49
+ execSync(
50
+ `powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${tmpDir}' -Force"`,
51
+ { stdio: "ignore" }
52
+ );
53
+ return;
54
+ }
55
+
56
+ execSync(`tar -xzf "${archivePath}" -C "${tmpDir}"`, { stdio: "ignore" });
57
+ }
58
+
59
+ function install() {
60
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "pdf-cli-"));
61
+ const archivePath = path.join(tmpDir, archiveName);
62
+ const binaryName = NAME + (isWindows ? ".exe" : "");
63
+ const extractedBinary = path.join(tmpDir, binaryName);
64
+
65
+ try {
66
+ download(releaseURL, archivePath);
67
+ extract(archivePath, tmpDir);
68
+ fs.copyFileSync(extractedBinary, dest);
69
+ if (!isWindows) {
70
+ fs.chmodSync(dest, 0o755);
71
+ }
72
+ console.log(`${NAME} v${VERSION} installed successfully`);
73
+ } finally {
74
+ fs.rmSync(tmpDir, { recursive: true, force: true });
75
+ }
76
+ }
77
+
78
+ try {
79
+ install();
80
+ } catch (error) {
81
+ console.error(`Failed to install ${NAME}:`, error.message);
82
+ console.error(
83
+ "\nRelease asset not found or download failed. Confirm that the matching Gitee Release exists before publishing this npm version."
84
+ );
85
+ process.exit(1);
86
+ }
package/scripts/run.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ const { execFileSync } = require("child_process");
3
+ const path = require("path");
4
+
5
+ const ext = process.platform === "win32" ? ".exe" : "";
6
+ const bin = path.join(__dirname, "..", "bin", "pdf-cli" + ext);
7
+
8
+ try {
9
+ execFileSync(bin, process.argv.slice(2), { stdio: "inherit" });
10
+ } catch (error) {
11
+ process.exit(error.status || 1);
12
+ }