插件開(kāi)發(fā):實(shí)現(xiàn) PicGo 圖片轉(zhuǎn) webp 格式
我寫(xiě)一些文檔或者公眾號(hào)文章使用的是 Typora,如果涉及到文章中有圖片時(shí),直接復(fù)制圖片粘貼到 Typora 中,然后使用 PicGo 上傳到圖床。
這樣不管是發(fā)布公眾號(hào)(公眾號(hào)會(huì)從圖床下載然后上傳)還是博客,圖片地址的問(wèn)題就解決了。但會(huì)有另外一個(gè)問(wèn)題,網(wǎng)上下載的圖片或者截圖的圖片通常比較大,現(xiàn)在我都是手動(dòng)將文件轉(zhuǎn)為 webp 格式,然后重新復(fù)制到 Typora 中,非常麻煩。
后來(lái)發(fā)現(xiàn) PicGo 有插件機(jī)制,一個(gè)想法就誕生了:
- 在 Typora 點(diǎn)擊右鍵上傳圖片時(shí),PicGo 插件接收到圖片地址并將圖片轉(zhuǎn)為 webp 格式,存儲(chǔ)到本地,返回給 PicGo 新的 webp 文件的地址;
- PicGo 接收到新的地址進(jìn)行圖床的上傳。
下面就來(lái)講解下怎樣來(lái)實(shí)現(xiàn)這個(gè)插件的開(kāi)發(fā)。
環(huán)境
- node:v16.18.1
- npm:9.1.2
- PicGo:2.3.1
- TypeScript:5.1.6
寫(xiě)代碼前的準(zhǔn)備
1、全局安裝 picgo:
sudo npm install picgo -g
2、使用 picgo 命令創(chuàng)建一個(gè)插件項(xiàng)目:
picgo init plugin convert-to-webp
PicGo 的插件名稱(chēng)要求必須帶有前綴:picgo-plugin ,否則不能識(shí)別,使用 picgo 腳手架創(chuàng)建插件項(xiàng)目時(shí),后面的名稱(chēng)只需寫(xiě)真實(shí)名稱(chēng)即可,否則前綴會(huì)重復(fù)。
執(zhí)行上面命令后,會(huì)有命令行的向?qū)?,需要填?xiě)一些關(guān)鍵信息,內(nèi)容如下:
? Plugin name: convert-to-webp
? Plugin description: convert image to webp
? author: oec2003
? Choose modules you want to develop:
? uploader
? transformer
?? beforeTransformPlugins
? beforeUploadPlugins
? afterUploadPlugins
Your plugin is just used in CLI? (Y/n) n
? Use TS or JS? (Use arrow keys)
? Yes, use TS Project(recommended)
Yes, use JS Project
? Your plugin has some shortcut for GUI? (Y/n) n
3、向?qū)е型扑]使用 TS 語(yǔ)言,我這里使用的就是默認(rèn)選項(xiàng),所以需要全局安裝 typescript:
npm install -g typescript
4、本插件的目的是將上傳的圖片轉(zhuǎn)為 webp 格式,需要使用 sharp 庫(kù),安裝命令如下:
npm install -g sharp
npm install @types/sharp --save-dev
編寫(xiě)代碼
使用腳手架創(chuàng)建的代碼只有一個(gè) index.ts 文件,如下圖:
在根目錄中執(zhí)行npm install 安裝依賴(lài)。
index.ts 代碼如下:
import path from 'path';
import sharp from 'sharp';
import { promises as fs } from 'fs';
import { PicGo } from 'picgo'
export = (ctx: PicGo) => {
const handle = async (ctx: PicGo): Promise<PicGo> => {
// ctx.input 是一個(gè)數(shù)組,因?yàn)槎际菃蝹€(gè)文件上傳,所以取數(shù)組中第一個(gè)數(shù)據(jù)就行
// imgPath 得到的就是文件的本地路徑
let [imgPath] = ctx.input;
let imgExt= path.extname(imgPath);
//如果上傳的就是 webp 格式的文件直接返回
if (imgExt === '.webp') {
return ctx;
}
//將文件轉(zhuǎn)為 webp 格式的流
let imgBuffer = await sharp(imgPath)
.webp()
.toBuffer();
//得到 webp 文件的本地路徑
const webpPath =path.join(path.dirname(imgPath), path.basename(imgPath, imgExt) + '.webp');
//將 webp 文件寫(xiě)入本地,我是想要在本地保留 webp 文件的備份
// 如果不需要,也可以在 afterUploadPlugins 事件中將本地文件刪除
await fs.writeFile(webpPath, imgBuffer);
//將新的 webp 地址包裝為數(shù)組返回給 ctx 的 input 對(duì)象
ctx.input = [webpPath]
return ctx;
};
const register = () => {
//注意:此處需要使用 beforeTransformPlugins 事件
ctx.helper.beforeTransformPlugins.register('picgo-plugin-convert-to-webp', {
handle
});
}
return {
register
}
}
執(zhí)行命令 npm run build 進(jìn)行打包,打包后會(huì)生成 dist 目錄,如下圖:
安裝
在 PicGo 的插件設(shè)置中,導(dǎo)入本地插件:
目錄選擇 dist 目錄所在的目錄:
安裝成功后如下圖:
這時(shí)可以截圖粘貼到 Typora 中,點(diǎn)擊右鍵上傳圖片:
上傳成功后,會(huì)發(fā)現(xiàn)已經(jīng)變成了 webp 格式:
更新插件
如果插件的代碼有修改,修改完成后,在 package.json 文件中升級(jí)一個(gè)版本,重新打包:
卸載插件。如果不卸載直接進(jìn)行插件導(dǎo)入,會(huì)提示成功,但實(shí)際是無(wú)效的:
重新本地導(dǎo)入插件。
導(dǎo)入成功后,需要更新插件:
更新成功后,需要重啟才能生效:
重啟后,如果看到版本變?yōu)?1.0.1 表示更新成功:
調(diào)試
在導(dǎo)入本地插件或者進(jìn)行圖片上傳的過(guò)程中,有可能會(huì)出現(xiàn)錯(cuò)誤,錯(cuò)誤日志記錄在 picgo.log 文件中,在 Mac 系統(tǒng)中,該文件的路徑如下:
~/Library/Application\ Support/picgo/picgo.log
比如:我們?cè)诖a中可以通過(guò)下面的代碼來(lái)輸出日志:
ctx.log.info('ctx.input.path'+imgPath)
在 picgo.log 中就會(huì)輸出日志:
通過(guò)這個(gè)日志文件的內(nèi)容,可以進(jìn)行錯(cuò)誤的排查。
源碼
本插件的源碼已經(jīng)上傳到 Github,地址如下:
https://github.com/oec2003/picgo-plugin-convert-to-webp。