cantarella 1.3.0 → 1.3.1
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 +17 -3
- package/dist/lib/core/command.js +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
两个子命令:`compress` 压缩(默认覆盖原文件,覆盖前自动备份到 `.backup/`,可用 `--backup-dir` 自定义;或用 `--out` 写进独立目录树,原图一个字节都不动);`watermark` 批量加水印(图片 logo 或文字,九宫格定位、平铺防盗图、可调倾斜角)。
|
|
8
8
|
|
|
9
|
+
嫌名字长?装好就有短写:`ct c` = `cantarella compress`,`ct wm` = `cantarella watermark`。
|
|
10
|
+
|
|
9
11
|
[](https://nodejs.org/)
|
|
10
12
|
[](./LICENSE)
|
|
11
13
|
[](https://www.typescriptlang.org/)
|
|
@@ -34,13 +36,15 @@
|
|
|
34
36
|
npm install -g cantarella
|
|
35
37
|
```
|
|
36
38
|
|
|
39
|
+
同时注册 `cantarella` 全名与 `ct` 短名两个全局命令,随你选用。
|
|
40
|
+
|
|
37
41
|
或从源码运行:
|
|
38
42
|
|
|
39
43
|
```bash
|
|
40
44
|
git clone https://github.com/zzl110712/cantarella.git
|
|
41
45
|
pnpm install
|
|
42
46
|
pnpm build # 编译并压缩 TS 到 dist/(bin 入口指向编译产物)
|
|
43
|
-
npm link # 注册全局命令 cantarella
|
|
47
|
+
npm link # 注册全局命令 cantarella / ct(改过 bin 字段需重跑一次)
|
|
44
48
|
```
|
|
45
49
|
|
|
46
50
|
> 要求 Node.js ≥ 22.12.0(npm 包为编译后的纯 JS,无需构建)
|
|
@@ -48,6 +52,10 @@ npm link # 注册全局命令 cantarella
|
|
|
48
52
|
## 🚀 用法
|
|
49
53
|
|
|
50
54
|
```bash
|
|
55
|
+
# 短写:ct c = cantarella compress,ct wm = cantarella watermark,下文示例同义可替换
|
|
56
|
+
ct c ./photos -q 60
|
|
57
|
+
ct wm ./photos -t "© LeoZhao"
|
|
58
|
+
|
|
51
59
|
cantarella compress # 交互模式:逐项问答
|
|
52
60
|
cantarella compress ./photos # 压缩目录下所有图片(仅当前层)
|
|
53
61
|
cantarella compress ./photos -r # 递归子目录
|
|
@@ -72,7 +80,7 @@ cantarella watermark ./photos -t "x" --dry # 预览:真实合成但不写
|
|
|
72
80
|
|
|
73
81
|
## ⚙️ 选项
|
|
74
82
|
|
|
75
|
-
### compress
|
|
83
|
+
### compress(别名 `c`)
|
|
76
84
|
|
|
77
85
|
| 选项 | 说明 | 默认值 |
|
|
78
86
|
| ------------------------ | ---------------------------------------------------------------------------------------------------------- | --------------------- |
|
|
@@ -88,7 +96,7 @@ cantarella watermark ./photos -t "x" --dry # 预览:真实合成但不写
|
|
|
88
96
|
| `-o, --out <dir>` | 输出到独立目录(镜像源目录结构,不动原图、不写备份;压不动的文件原样拷贝保证树完整;不能指向目标目录本身) | 无(原地覆盖 + 备份) |
|
|
89
97
|
| `-s, --smart` | 智能模式:每张图在原格式与 webp 间实测选最小(png 额外加赛无损 webp);与 `-f` 互斥 | 关闭 |
|
|
90
98
|
|
|
91
|
-
### watermark
|
|
99
|
+
### watermark(别名 `wm`)
|
|
92
100
|
|
|
93
101
|
| 选项 | 说明 | 默认值 |
|
|
94
102
|
| ------------------------ | ----------------------------------------------------------------------------------------------------------- | --------------------- |
|
|
@@ -158,6 +166,12 @@ pnpm build # 编译并压缩到 dist/(发布、npm link 前需要)
|
|
|
158
166
|
|
|
159
167
|
## 📜 版本记录
|
|
160
168
|
|
|
169
|
+
### 🚀 1.3.1 · 2026-09-20
|
|
170
|
+
|
|
171
|
+
- ✨ **新增** 全局短命令 `ct`:`bin` 里给同一入口多挂一个名字,安装后 `cantarella` / `ct` 两个命令并存随你选用
|
|
172
|
+
- ✨ **新增** 子命令别名:`compress` 可写作 `c`、`watermark` 可写作 `wm`,最短形态 `ct c ./photos -q 60`;help 的用法行自动显示 `compress|c`
|
|
173
|
+
- 💡 别名是子命令级(永远跟在主命令后输入),不与系统命令冲突;已有全局安装需重跑一次 `npm i -g cantarella` 才会生成 `ct`
|
|
174
|
+
|
|
161
175
|
### 🚀 1.3.0 · 2026-09-16
|
|
162
176
|
|
|
163
177
|
- ✨ **重构** PNG 的 `-q` 语义为档位表:旧公式"quality 越低压缩等级越高"存在语义倒置(`-q 100` 会算出 cl0 = 完全不压缩),且 `quality <= 60` 才开 palette 的门槛太高;现在 quality 直接踩在 PNG 的位深台阶上(256 / 16 / 4 / 2 色),档内用抖动强度微调画质与字节
|
package/dist/lib/core/command.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{InvalidArgumentError as r,Option as t}from"commander";import{compress as a}from"./compress.js";import{OUTPUT_FORMATS as p}from"./compressImage.js";import{watermark as s}from"./watermark.js";import{WATERMARK_POSITIONS as c}from"./watermarkImage.js";function m(n){const o=Number.parseInt(n,10);if(Number.isNaN(o)||o<1||o>100)throw new r("\u5FC5\u987B\u662F 1 - 100 \u7684\u6574\u6570");return o}function u(n){const o=Number.parseInt(n,10);if(Number.isNaN(o)||o<=0)throw new r("\u5FC5\u987B\u662F\u6B63\u6574\u6570");return o}function e(n){const o=n.trim();if(o===""||o==="."||o===".."||o.includes("/")||o.includes("\\"))throw new r("\u5FC5\u987B\u662F\u5355\u7EAF\u7684\u76EE\u5F55\u540D\uFF08\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u4E0D\u80FD\u5305\u542B / \\ . ..\uFF09");return o}function i(n){const o=Number.parseInt(n,10);if(Number.isNaN(o)||o<1||o>1024)throw new r("\u5FC5\u987B\u662F 1 - 1024 \u7684\u6574\u6570");return o}function f(n){const o=n.trim();if(o==="")throw new r("\u8F93\u51FA\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");return o}function N(n){const o=Number(n);if(Number.isNaN(o)||o<.1||o>1)throw new r("\u5FC5\u987B\u662F 0.1 - 1 \u4E4B\u95F4\u7684\u5C0F\u6570");return o}function
|
|
1
|
+
import{InvalidArgumentError as r,Option as t}from"commander";import{compress as a}from"./compress.js";import{OUTPUT_FORMATS as p}from"./compressImage.js";import{watermark as s}from"./watermark.js";import{WATERMARK_POSITIONS as c}from"./watermarkImage.js";function m(n){const o=Number.parseInt(n,10);if(Number.isNaN(o)||o<1||o>100)throw new r("\u5FC5\u987B\u662F 1 - 100 \u7684\u6574\u6570");return o}function u(n){const o=Number.parseInt(n,10);if(Number.isNaN(o)||o<=0)throw new r("\u5FC5\u987B\u662F\u6B63\u6574\u6570");return o}function e(n){const o=n.trim();if(o===""||o==="."||o===".."||o.includes("/")||o.includes("\\"))throw new r("\u5FC5\u987B\u662F\u5355\u7EAF\u7684\u76EE\u5F55\u540D\uFF08\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u4E0D\u80FD\u5305\u542B / \\ . ..\uFF09");return o}function i(n){const o=Number.parseInt(n,10);if(Number.isNaN(o)||o<1||o>1024)throw new r("\u5FC5\u987B\u662F 1 - 1024 \u7684\u6574\u6570");return o}function f(n){const o=n.trim();if(o==="")throw new r("\u8F93\u51FA\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");return o}function N(n){const o=Number(n);if(Number.isNaN(o)||o<.1||o>1)throw new r("\u5FC5\u987B\u662F 0.1 - 1 \u4E4B\u95F4\u7684\u5C0F\u6570");return o}function l(n){const o=Number.parseInt(n,10);if(Number.isNaN(o)||o<1||o>100)throw new r("\u5FC5\u987B\u662F 1 - 100 \u7684\u6574\u6570");return o}function w(n){const o=Number.parseInt(n,10);if(Number.isNaN(o)||o<-89||o>89)throw new r("\u5FC5\u987B\u662F -89 - 89 \u7684\u6574\u6570\uFF080 = \u4E0D\u503E\u659C\uFF09");return o}const d=new t("-f, --format <format>","\u8F6C\u6362\u8F93\u51FA\u683C\u5F0F\uFF08\u9ED8\u8BA4\u4FDD\u6301\u539F\u683C\u5F0F\uFF09").choices([...p]);export function myCompress(n){n.command("compress [target]").alias("c").description("\u6279\u91CF\u538B\u7F29\u56FE\u7247\uFF08\u8986\u76D6\u539F\u6587\u4EF6\u524D\u81EA\u52A8\u5907\u4EFD\u5230\u5907\u4EFD\u76EE\u5F55\uFF0C\u9ED8\u8BA4 .backup/\uFF09").option("-q, --quality <number>","\u538B\u7F29\u8D28\u91CF 1-100\uFF0C\u9ED8\u8BA4 80\uFF08png \u6620\u5C04\u4E3A\u8C03\u8272\u677F\u989C\u8272\u6570\uFF09",m,80).addOption(d).option("-w, --max-width <px>","\u7B49\u6BD4\u7F29\u653E\u7684\u6700\u5927\u5BBD\u5EA6\uFF0C\u53EA\u7F29\u5C0F\u4E0D\u653E\u5927",u).option("-r, --recursive","\u9012\u5F52\u5904\u7406\u5B50\u76EE\u5F55",!1).option("--dry","\u9884\u89C8\u6A21\u5F0F\uFF1A\u771F\u5B9E\u8BA1\u7B97\u538B\u7F29\u540E\u5927\u5C0F\uFF0C\u4F46\u4E0D\u5199\u4EFB\u4F55\u6587\u4EF6",!1).option("--report","\u5728\u76EE\u6807\u76EE\u5F55\u751F\u6210 markdown \u538B\u7F29\u62A5\u544A",!1).option("-y, --yes","\u8DF3\u8FC7\u5168\u90E8\u95EE\u7B54\u3001\u76F4\u63A5\u7528\u9ED8\u8BA4\u503C\u5F00\u538B",!1).option("--backup-dir <name>","\u5907\u4EFD\u76EE\u5F55\u540D\uFF08\u9ED8\u8BA4 .backup\uFF09",e).option("-c, --concurrency <n>","\u540C\u65F6\u5904\u7406\u591A\u5C11\u5F20\u56FE\u7247",i,4).option("-o, --out <dir>","\u8F93\u51FA\u5230\u72EC\u7ACB\u76EE\u5F55\uFF08\u955C\u50CF\u6E90\u76EE\u5F55\u7ED3\u6784\uFF0C\u4E0D\u8986\u76D6\u539F\u56FE\uFF09",f).option("-s, --smart","\u6BCF\u5F20\u56FE\u5206\u522B\u6309\u591A\u4E2A\u5019\u9009\u683C\u5F0F\u7F16\u7801",!1).action(a)}const b=new t("-p, --position <pos>","\u6C34\u5370\u4F4D\u7F6E\uFF08\u4E5D\u5BAB\u683C\u7F29\u5199\uFF09").choices([...c]).default("br");export function myWatermark(n){n.command("watermark [target]").alias("wm").description("\u6279\u91CF\u7ED9\u56FE\u7247\u52A0\u6C34\u5370\uFF1A\u56FE\u7247 logo \u6216\u6587\u5B57\uFF0C\u652F\u6301\u4E5D\u5BAB\u683C\u5B9A\u4F4D\u4E0E\u5E73\u94FA\u9632\u76D7\u56FE").option("-m, --mark <file>","\u6C34\u5370\u56FE\u7247\u8DEF\u5F84\uFF08\u4E0E -t \u4E92\u65A5\uFF09").option("-t, --text <string>","\u6C34\u5370\u6587\u5B57\uFF08\u4E0E -m \u4E92\u65A5\uFF09").addOption(b).option("--opacity <0.1-1>","\u4E0D\u900F\u660E\u5EA6\uFF0C\u9ED8\u8BA4 0.5",N,.5).option("-s, --scale <1-100>","\u6C34\u5370\u5927\u5C0F = \u4E3B\u56FE\u5BBD\u7684\u767E\u5206\u6BD4\uFF08\u9ED8\u8BA4\uFF1A\u56FE\u7247 15\uFF0C\u6587\u5B57 5\uFF09",l).option("--tile","\u5E73\u94FA\u6574\u5F20\u56FE\uFF08\u9632\u76D7\u56FE\uFF09",!1).option("-r, --recursive","\u9012\u5F52\u5904\u7406\u5B50\u76EE\u5F55",!1).option("--dry","\u9884\u89C8\u6A21\u5F0F\uFF1A\u771F\u5B9E\u5408\u6210\uFF0C\u4F46\u4E0D\u5199\u4EFB\u4F55\u6587\u4EF6",!1).option("-y, --yes","\u8DF3\u8FC7\u5168\u90E8\u95EE\u7B54\u3001\u76F4\u63A5\u7528\u9ED8\u8BA4\u503C",!1).option("--backup-dir <name>","\u5907\u4EFD\u76EE\u5F55\u540D\uFF08\u9ED8\u8BA4 .backup\uFF09",e).option("-c, --concurrency <n>","\u540C\u65F6\u5904\u7406\u591A\u5C11\u5F20\u56FE\u7247",i,4).option("-a, --angle <deg>","\u5E73\u94FA\u6C34\u5370\u7684\u503E\u659C\u89D2\u5EA6\uFF08\u5EA6\uFF0C0 = \u4E0D\u503E\u659C\uFF09",w).action(s)}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cantarella",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "批量压缩图片的命令行工具",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"cantarella": "dist/bin/cli.js"
|
|
7
|
+
"cantarella": "dist/bin/cli.js",
|
|
8
|
+
"ct": "dist/bin/cli.js"
|
|
8
9
|
},
|
|
9
10
|
"scripts": {
|
|
10
11
|
"start": "node --conditions=development bin/cli.ts --help",
|