picgo-plugin-img-avif 1.0.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/License +21 -0
- package/README.md +18 -0
- package/package.json +23 -0
- package/src/index.js +140 -0
package/License
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Carbene Hu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## picgo-plugin-img-avif
|
|
2
|
+
|
|
3
|
+
一个使用 `sharp` 库进行图片压缩和格式转换的 PicGo 插件。可以将图片转换为 `jpeg`、`png`、`webp`、`avif` 格式,并可选择按质量进行压缩。在 `beforeUploadPlugins` 生命周期中工作。
|
|
4
|
+
|
|
5
|
+
### 功能特点
|
|
6
|
+
|
|
7
|
+
- **格式转换**:支持原图(不改变)、`jpeg`、`png`、`webp`、`avif` 格式
|
|
8
|
+
- **质量配置**:可设置压缩质量(0–100)
|
|
9
|
+
- **自动重命名**:格式变化时自动修改文件扩展名
|
|
10
|
+
- **可靠上传**:使用缓冲区上传确保可靠性
|
|
11
|
+
|
|
12
|
+
## 安装方法
|
|
13
|
+
|
|
14
|
+
在 PicGo 插件商店搜索 `img-avif` 并安装。
|
|
15
|
+
|
|
16
|
+
### 许可证
|
|
17
|
+
|
|
18
|
+
详见 `License` 文件。
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "picgo-plugin-img-avif",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "一个压缩并转换图片格式的 PicGo 插件",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/liyao52033/picgo-plugin-img-avif",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"publish": "npm publish"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"picgo",
|
|
15
|
+
"picgo-gui-plugin",
|
|
16
|
+
"picgo-plugin"
|
|
17
|
+
],
|
|
18
|
+
"author": "liyao52033",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"sharp": "^0.34.5"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
const sharp = require('sharp')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
// Plugin configuration schema
|
|
5
|
+
const config = (ctx) => {
|
|
6
|
+
let userConfig = ctx.getConfig('picgo-plugin-converter')
|
|
7
|
+
if (!userConfig) {
|
|
8
|
+
userConfig = {}
|
|
9
|
+
}
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
name: 'format',
|
|
13
|
+
type: 'list',
|
|
14
|
+
alias: '目标格式',
|
|
15
|
+
default: userConfig.format || 'original',
|
|
16
|
+
message: 'Select output format',
|
|
17
|
+
choices: [
|
|
18
|
+
{ name: '原格式', value: 'original' },
|
|
19
|
+
{ name: 'JPEG', value: 'jpeg' },
|
|
20
|
+
{ name: 'PNG', value: 'png' },
|
|
21
|
+
{ name: 'WebP', value: 'webp' },
|
|
22
|
+
{ name: 'AVIF', value: 'avif' }
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'quality',
|
|
27
|
+
type: 'input',
|
|
28
|
+
alias: '压缩质量(0-100)',
|
|
29
|
+
default: userConfig.quality || '80',
|
|
30
|
+
message: 'Compression quality (0-100)',
|
|
31
|
+
validate: function (val) {
|
|
32
|
+
if (val >= 0 && val <= 100) return true
|
|
33
|
+
return 'Please enter a number between 0 and 100'
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'lossless',
|
|
38
|
+
type: 'confirm',
|
|
39
|
+
alias: 'WebP/AVIF无损压缩',
|
|
40
|
+
default: userConfig.lossless || false,
|
|
41
|
+
message: 'Enable lossless compression for WebP/AVIF? (May increase file size)' // 修改提示文案
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Core handler function
|
|
47
|
+
const handle = async (ctx) => {
|
|
48
|
+
// Get user configuration
|
|
49
|
+
const userConfig = ctx.getConfig('picgo-plugin-converter') || {}
|
|
50
|
+
const targetFormat = userConfig.format || 'original'
|
|
51
|
+
const quality = parseInt(userConfig.quality) || 80
|
|
52
|
+
const lossless = userConfig.lossless || false
|
|
53
|
+
// 1. 新增 AVIF 到支持的输入格式列表
|
|
54
|
+
const VALID_INPUT_FORMATS = ['.jpg', '.jpeg', '.png', '.webp', '.bmp', '.tiff', '.avif']
|
|
55
|
+
|
|
56
|
+
const output = ctx.output
|
|
57
|
+
|
|
58
|
+
// Iterate over files to upload
|
|
59
|
+
await Promise.all(output.map(async (item) => {
|
|
60
|
+
// Simple format filter: only process images
|
|
61
|
+
if (!item.buffer && !item.base64Image) return // Skip if no content
|
|
62
|
+
const ext = path.extname(item.fileName).toLowerCase()
|
|
63
|
+
// We only process common image formats for now
|
|
64
|
+
if (!VALID_INPUT_FORMATS.includes(ext)) {
|
|
65
|
+
ctx.log.warn(`File extension ${ext} is not supported for conversion. Skipping ${item.fileName}.`)
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
// Instantiate sharp
|
|
71
|
+
// PicGo's Transformer outputs a Buffer by default, but may also be base64
|
|
72
|
+
let image = sharp(item.buffer || Buffer.from(item.base64Image, 'base64'))
|
|
73
|
+
|
|
74
|
+
let finalFormat = targetFormat
|
|
75
|
+
ctx.log.info(`[Convertor] Processing ${item.fileName}: target format = ${targetFormat}, quality = ${quality}`)
|
|
76
|
+
|
|
77
|
+
// If 'original' is selected, keep original format; still specify format for compression
|
|
78
|
+
if (finalFormat === 'original') {
|
|
79
|
+
// sharp requires explicit format names, e.g., 'jpeg' not 'jpg'
|
|
80
|
+
finalFormat = ext.replace('.', '')
|
|
81
|
+
if (finalFormat === 'jpg') finalFormat = 'jpeg'
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const options = {
|
|
85
|
+
quality: quality
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (finalFormat === 'jpeg') {
|
|
89
|
+
options.mozjpeg = true
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 2. 扩展无损压缩判断条件,支持 AVIF
|
|
93
|
+
if ((finalFormat === 'webp' || finalFormat === 'avif') && lossless) {
|
|
94
|
+
options.lossless = true
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Perform conversion and compression
|
|
98
|
+
// sharp's toFormat supports setting quality
|
|
99
|
+
// Note: PNG quality requires libvips support; recent sharp versions typically support it
|
|
100
|
+
image = image.toFormat(finalFormat, options)
|
|
101
|
+
|
|
102
|
+
// Export as Buffer
|
|
103
|
+
const newBuffer = await image.toBuffer()
|
|
104
|
+
|
|
105
|
+
// Update data in ctx.output
|
|
106
|
+
item.buffer = newBuffer
|
|
107
|
+
item.base64Image = null // Clear base64 to force buffer upload and avoid confusion
|
|
108
|
+
|
|
109
|
+
// If format changed, update file extension
|
|
110
|
+
if (targetFormat !== 'original') {
|
|
111
|
+
// 3. 新增 AVIF 格式的扩展名映射
|
|
112
|
+
const newExt = `.${targetFormat === 'jpeg' ? 'jpg' : targetFormat}`
|
|
113
|
+
item.fileName = item.fileName.replace(path.extname(item.fileName), newExt)
|
|
114
|
+
item.extname = newExt
|
|
115
|
+
ctx.log.info(`[Convertor] Converted ${item.fileName} to ${newExt} with quality ${quality}`)
|
|
116
|
+
}
|
|
117
|
+
} catch (e) {
|
|
118
|
+
ctx.log.error(`[Convertor] Error processing ${item.fileName}: ${e.message}`)
|
|
119
|
+
// On error, skip processing and upload original, or choose to throw
|
|
120
|
+
}
|
|
121
|
+
}))
|
|
122
|
+
|
|
123
|
+
return ctx
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = (ctx) => {
|
|
127
|
+
const register = () => {
|
|
128
|
+
// Register in the 'beforeUploadPlugins' lifecycle
|
|
129
|
+
// Intercepts after Transformer (post-file) and before Uploader (pre-upload)
|
|
130
|
+
ctx.helper.beforeUploadPlugins.register('converter', {
|
|
131
|
+
handle,
|
|
132
|
+
config,
|
|
133
|
+
name: '图片压缩与转换' // Friendly plugin name shown in the GUI
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
register,
|
|
138
|
+
config // Export config for PicGo GUI to generate settings menu
|
|
139
|
+
}
|
|
140
|
+
}
|