Skip to content

Commit

Permalink
format
Browse files Browse the repository at this point in the history
  • Loading branch information
supine0703 committed Aug 1, 2024
1 parent da894d0 commit 662bc52
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 116 deletions.
7 changes: 5 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"singleQuote": true,
"semi": false,
"printWidth": 150
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"printWidth": 120
}
6 changes: 3 additions & 3 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ const config: Config = {
collectCoverageFrom: ['src/**/*.ts', 'types/*.ts'],

// The directory where Jest should output its coverage files
coverageDirectory: "coverage",
coverageDirectory: 'coverage',

// An array of regexp pattern strings used to skip coverage collection
// coveragePathIgnorePatterns: [
// "/node_modules/"
// ],

// Indicates which provider should be used to instrument code for coverage
coverageProvider: "v8",
coverageProvider: 'v8',

// A list of reporter names that Jest uses when writing coverage reports
// coverageReporters: [
Expand Down Expand Up @@ -149,7 +149,7 @@ const config: Config = {

// The test environment that will be used for testing

testEnvironment: "node",
testEnvironment: 'node',

// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},
Expand Down
2 changes: 1 addition & 1 deletion src/compress/skip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import { getImageBuffer, getImageInfo } from '../utils';
import { CommonParams, ImageInfo } from '../interface';

export function SkipCompress(ctx: IPicGo, { imageUrl }: CommonParams): Promise<ImageInfo> {
return getImageBuffer(ctx, imageUrl).then((buffer) => getImageInfo(imageUrl, buffer))
return getImageBuffer(ctx, imageUrl).then((buffer) => getImageInfo(imageUrl, buffer));
}
106 changes: 53 additions & 53 deletions src/compress/tinypng/tinypng.ts
Original file line number Diff line number Diff line change
@@ -1,81 +1,81 @@
import * as fs from 'fs-extra'
import * as fs from 'fs-extra';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import Base64 from 'crypto-js/enc-base64.js'
import Utf8 from 'crypto-js/enc-utf8.js'
import { IPicGo } from 'picgo'
import Base64 from 'crypto-js/enc-base64.js';
import Utf8 from 'crypto-js/enc-utf8.js';
import { IPicGo } from 'picgo';
import { getImageBuffer, isNetworkUrl } from '../../utils';
import { TINYPNG_UPLOAD_URL } from '../../config';

interface TinyPngOptions {
keys: string[]
ctx: IPicGo
keys: string[];
ctx: IPicGo;
}

interface TinyCacheConfig {
[key: string]: {
key: string
num: number
}
key: string;
num: number;
};
}

class TinyPng {
// private cacheConfigPath = join(dirname(fileURLToPath(import.meta.url)), 'config.json'); // ES6
private cacheConfigPath = join(__dirname, 'config.json'); // CommonJs
private options!: TinyPngOptions
private IPicGo!: IPicGo
private options!: TinyPngOptions;
private IPicGo!: IPicGo;

// Initialize TinyPng instance with options
async init(options: TinyPngOptions) {
this.IPicGo = options.ctx
this.options = options
await this.readOrWriteConfig(this.options.keys)
this.IPicGo.log.info('TinyPng initialized')
this.IPicGo = options.ctx;
this.options = options;
await this.readOrWriteConfig(this.options.keys);
this.IPicGo.log.info('TinyPng initialized');
}

// Upload image to TinyPng service
async upload(url: string) {
this.IPicGo.log.info('TinyPng upload started')
const key = await this.getKey()
this.IPicGo.log.info('TinyPng upload started');
const key = await this.getKey();
if (isNetworkUrl(url)) {
return this.uploadImage({ url, originalUrl: url, key })
return this.uploadImage({ url, originalUrl: url, key });
} else {
const buffer = await getImageBuffer(this.IPicGo, url)
return this.uploadImage({ key, originalUrl: url, buffer })
const buffer = await getImageBuffer(this.IPicGo, url);
return this.uploadImage({ key, originalUrl: url, buffer });
}
}

// Get key with available usage count
private async getKey() {
const config = await this.readOrWriteConfig()
const innerKeys = Object.keys(config).filter((key) => config[key].num !== -1)
const config = await this.readOrWriteConfig();
const innerKeys = Object.keys(config).filter((key) => config[key].num !== -1);
if (innerKeys.length <= 0) {
throw new Error('No available keys')
throw new Error('No available keys');
}
return innerKeys[0]
return innerKeys[0];
}

// Upload image with specified options
private uploadImage(options: { key: string; originalUrl: string; url?: string; buffer?: Buffer }): Promise<Buffer> {
this.IPicGo.log.info('Using Tinypng key: ' + options.key)
const bearer = Base64.stringify(Utf8.parse(`api:${options.key}`))
this.IPicGo.log.info('Using Tinypng key: ' + options.key);
const bearer = Base64.stringify(Utf8.parse(`api:${options.key}`));
const headersObj = {
Host: 'api.tinify.com',
Authorization: `Basic ${bearer}`,
}
let bodyObj = {}
};
let bodyObj = {};
if (options.url) {
this.IPicGo.log.info('Uploading network image to TinyPng')
this.IPicGo.log.info('Uploading network image to TinyPng');
Object.assign(headersObj, {
'Content-Type': 'application/json',
})
});
Object.assign(bodyObj, {
source: { url: options.url },
})
});
}
if (options.buffer) {
this.IPicGo.log.info('Uploading local image to TinyPng')
bodyObj = options.buffer
this.IPicGo.log.info('Uploading local image to TinyPng');
bodyObj = options.buffer;
}
return this.IPicGo.request({
method: 'POST',
Expand All @@ -85,37 +85,37 @@ class TinyPng {
headers: headersObj,
body: bodyObj,
}).then((response) => {
this.setConfig(options.key, parseInt(response.headers['compression-count'] as any))
this.setConfig(options.key, parseInt(response.headers['compression-count'] as any));
if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) {
console.log(response.statusCode)
console.log(response.headers.location)
return getImageBuffer(this.IPicGo, response.headers.location as any)
console.log(response.statusCode);
console.log(response.headers.location);
return getImageBuffer(this.IPicGo, response.headers.location as any);
}
if (response.statusCode === 429) {
this.setConfig(options.key, -1)
return this.upload(options.originalUrl)
this.setConfig(options.key, -1);
return this.upload(options.originalUrl);
}
throw new Error('Unknown error')
})
throw new Error('Unknown error');
});
}

// Set configuration with key and usage count
private async setConfig(key: string, num: number) {
const config = await this.readOrWriteConfig()
const config = await this.readOrWriteConfig();
config[key] = {
key,
num,
}
await fs.writeJSON(this.cacheConfigPath, config)
};
await fs.writeJSON(this.cacheConfigPath, config);
}

// Read or write configuration file
private async readOrWriteConfig(keys?: string[]): Promise<TinyCacheConfig> {
const config: TinyCacheConfig = {}
const config: TinyCacheConfig = {};
if (await fs.pathExists(this.cacheConfigPath)) {
Object.assign(config, await fs.readJSON(this.cacheConfigPath))
Object.assign(config, await fs.readJSON(this.cacheConfigPath));
} else {
await fs.writeJSON(this.cacheConfigPath, {})
await fs.writeJSON(this.cacheConfigPath, {});
}
if (keys) {
await fs.writeJSON(
Expand All @@ -125,14 +125,14 @@ class TinyPng {
res[key] = {
key,
num: 0,
}
};
}
return res
}, config)
)
return res;
}, config),
);
}
return config
return config;
}
}

export default new TinyPng()
export default new TinyPng();
39 changes: 21 additions & 18 deletions src/compress/tinypngweb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,26 @@ import { getImageBuffer, getImageInfo } from '../utils';
export function TinypngCompress(ctx: IPicGo, { imageUrl }: CommonParams): Promise<ImageInfo> {
return getImageBuffer(ctx, imageUrl).then((buffer) => {
ctx.log.info('TinypngWeb compression started');
return ctx.request({
url: TINYPNG_WEBUPLOAD_URL,
method: 'POST',
headers: getHeaders(),
body: buffer,
resolveWithFullResponse: true
}).then((resp) => {
if (resp.headers.location) {
ctx.log.info('TinypngWeb compression successful: ' + resp.headers.location);
ctx.log.info('Downloading Tinypng image');
return getImageBuffer(ctx, resp.headers.location);
}
// If compression failed, throw an error
throw new Error('TinypngWeb upload failed');
}).then((buffer) => {
return getImageInfo(imageUrl, buffer);
});
return ctx
.request({
url: TINYPNG_WEBUPLOAD_URL,
method: 'POST',
headers: getHeaders(),
body: buffer,
resolveWithFullResponse: true,
})
.then((resp) => {
if (resp.headers.location) {
ctx.log.info('TinypngWeb compression successful: ' + resp.headers.location);
ctx.log.info('Downloading Tinypng image');
return getImageBuffer(ctx, resp.headers.location);
}
// If compression failed, throw an error
throw new Error('TinypngWeb upload failed');
})
.then((buffer) => {
return getImageInfo(imageUrl, buffer);
});
});
}

Expand All @@ -46,4 +49,4 @@ function getHeaders(): Record<string, string> {
'content-type': 'application/x-www-form-urlencoded',
'user-agent': getRandomUserAgent(),
};
}
}
4 changes: 2 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const TINYPNG_UPLOAD_URL = 'https://api.tinify.com/shrink'
export const TINYPNG_UPLOAD_URL = 'https://api.tinify.com/shrink';

export const TINYPNG_WEBUPLOAD_URL = 'https://tinify.cn/web/shrink'
export const TINYPNG_WEBUPLOAD_URL = 'https://tinify.cn/web/shrink';

export enum CompressType {
tinypng = 'tinypng',
Expand Down
21 changes: 13 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,17 @@ const handle = async (ctx: IPicGo): Promise<IPicGo> => {

return Promise.all(tasks).then((output) => {
// Log compressed image information
ctx.log.info('Compressed image info: ' + JSON.stringify(output.map((item) => ({
fileName: item.fileName,
extname: item.extname,
height: item.height,
width: item.width
}))));
ctx.log.info(
'Compressed image info: ' +
JSON.stringify(
output.map((item) => ({
fileName: item.fileName,
extname: item.extname,
height: item.height,
width: item.width,
})),
),
);

// Set output images
ctx.output = output;
Expand Down Expand Up @@ -89,9 +94,9 @@ const CompressTransformers: IPicGoPlugin = (ctx: IPicGo) => {
},
];
},
getHandle(ctx: IPicGo):IPlugin {
getHandle(ctx: IPicGo): IPlugin {
return { handle };
}
},
};
};

Expand Down
20 changes: 10 additions & 10 deletions src/interface.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
export interface ImageInfo {
fileName: string
extname: string
buffer: Buffer
width: number
height: number
fileName: string;
extname: string;
buffer: Buffer;
width: number;
height: number;
}

export interface CommonParams {
imageUrl: string
imageUrl: string;
}

export interface IConfig {
compress: string
key: string
tinypngKey: string
nameType: string
compress: string;
key: string;
tinypngKey: string;
nameType: string;
}
26 changes: 14 additions & 12 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,20 @@ export function isNetworkUrl(url: string): boolean {

// Fetch image data from a URL
export async function fetchImage(ctx: IPicGo, url: string): Promise<Buffer> {
return await ctx.request({
method: 'GET',
url,
resolveWithFullResponse: true,
responseType: 'arraybuffer'
}).then((resp) => {
const contentType = resp.headers['content-type'];
if (contentType?.includes('image')) {
return resp.data as Buffer;
}
throw new Error(`${url} is not an image`);
});
return await ctx
.request({
method: 'GET',
url,
resolveWithFullResponse: true,
responseType: 'arraybuffer',
})
.then((resp) => {
const contentType = resp.headers['content-type'];
if (contentType?.includes('image')) {
return resp.data as Buffer;
}
throw new Error(`${url} is not an image`);
});
}

// Get image buffer either from network or local file
Expand Down
Loading

0 comments on commit 662bc52

Please sign in to comment.