Skip to content

Commit 0f5d2a9

Browse files
committed
✨ Feature(transformer): add fallback to support more image formats such as HEIC
change probe-image-size -> image-size to support more formats ISSUES CLOSED: #13
1 parent 6adc070 commit 0f5d2a9

File tree

6 files changed

+131
-91
lines changed

6 files changed

+131
-91
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"ejs": "^2.6.1",
8282
"fs-extra": "^6.0.1",
8383
"globby": "^8.0.2",
84+
"image-size": "^0.8.3",
8485
"inquirer": "^6.0.0",
8586
"lodash-id": "^0.14.0",
8687
"lowdb": "^1.0.0",

src/plugins/transformer/path.ts

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
1-
import probe from 'probe-image-size'
2-
import path from 'path'
3-
import fs from 'fs-extra'
41
import PicGo from '../../core/PicGo'
5-
import { getURLFile } from '../../utils/getURLFile'
6-
import { isUrl } from '../../utils/common'
7-
import { IPathTransformedImgInfo, ImgInfo } from '../../utils/interfaces'
2+
import {
3+
isUrl,
4+
getImageSize,
5+
getFSFile,
6+
getURLFile
7+
} from '../../utils/common'
8+
import { IPathTransformedImgInfo, ImgInfo, ImgSize } from '../../utils/interfaces'
89

910
const handle = async (ctx: PicGo): Promise<PicGo> => {
1011
let results: ImgInfo[] = ctx.output
1112
await Promise.all(ctx.input.map(async (item: string) => {
1213
let info: IPathTransformedImgInfo
1314
if (isUrl(item)) {
14-
info = await getURLFile(ctx, item)
15+
info = await getURLFile(item)
1516
} else {
1617
info = await getFSFile(item)
1718
}
1819
if (info.success) {
1920
try {
20-
const imgSize = probe.sync(info.buffer)
21+
const imgSize = getImgSize(ctx, info.buffer, item)
2122
results.push({
2223
buffer: info.buffer,
2324
fileName: info.fileName,
2425
width: imgSize.width,
2526
height: imgSize.height,
26-
extname: path.extname(item)
27+
extname: info.extname
2728
})
2829
} catch (e) {
2930
ctx.log.error(e)
@@ -35,20 +36,13 @@ const handle = async (ctx: PicGo): Promise<PicGo> => {
3536
return ctx
3637
}
3738

38-
const getFSFile = async (item: string): Promise<IPathTransformedImgInfo> => {
39-
try {
40-
return {
41-
extname: path.extname(item),
42-
fileName: path.basename(item),
43-
buffer: await fs.readFile(item),
44-
success: true
45-
}
46-
} catch {
47-
return {
48-
reason: `read file ${item} error`,
49-
success: false
50-
}
39+
const getImgSize = (ctx: PicGo, file: Buffer, path: string): ImgSize => {
40+
const imageSize = getImageSize(file)
41+
if (!imageSize.real) {
42+
ctx.log.warn(`can't get ${path}'s image size`)
43+
ctx.log.warn(`fallback to 200 * 200`)
5144
}
45+
return imageSize
5246
}
5347

5448
export default {

src/utils/common.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
import request from 'request'
2+
import requestPromise from 'request-promise-native'
3+
import fs from 'fs-extra'
4+
import path from 'path'
5+
import { imageSize } from 'image-size'
6+
import {
7+
ImgSize,
8+
IPathTransformedImgInfo
9+
} from './interfaces'
10+
111
export const isUrl = (url: string): boolean => (url.startsWith('http://') || url.startsWith('https://'))
212
export const isUrlEncode = (url: string): boolean => {
313
url = url || ''
@@ -14,3 +24,91 @@ export const handleUrlEncode = (url: string): string => {
1424
}
1525
return url
1626
}
27+
28+
export const getImageSize = (file: Buffer): ImgSize => {
29+
try {
30+
const { width, height } = imageSize(file)
31+
return {
32+
real: true,
33+
width,
34+
height
35+
}
36+
} catch (e) {
37+
// fallback to 200 * 200
38+
return {
39+
real: false,
40+
width: 200,
41+
height: 200
42+
}
43+
}
44+
}
45+
46+
export const getFSFile = async (filePath: string): Promise<IPathTransformedImgInfo> => {
47+
try {
48+
return {
49+
extname: path.extname(filePath),
50+
fileName: path.basename(filePath),
51+
buffer: await fs.readFile(filePath),
52+
success: true
53+
}
54+
} catch {
55+
return {
56+
reason: `read file ${filePath} error`,
57+
success: false
58+
}
59+
}
60+
}
61+
62+
export const getURLFile = async (url: string): Promise<IPathTransformedImgInfo> => {
63+
const requestOptions = {
64+
method: 'GET',
65+
url,
66+
encoding: null
67+
}
68+
let isImage = false
69+
let extname = ''
70+
let timeoutId
71+
// tslint:disable-next-line: typedef
72+
const requestFn = new Promise<IPathTransformedImgInfo>(async (resolve): Promise<void> => {
73+
try {
74+
const res = await requestPromise(requestOptions)
75+
.on('response', (response: request.Response): void => {
76+
const contentType = response.headers['content-type']
77+
if (contentType.includes('image')) {
78+
isImage = true
79+
extname = `.${contentType.split('image/')[1]}`
80+
}
81+
})
82+
clearTimeout(timeoutId)
83+
if (isImage) {
84+
resolve({
85+
buffer: res,
86+
fileName: path.basename(requestOptions.url.split('?')[0]),
87+
extname,
88+
success: true
89+
})
90+
} else {
91+
resolve({
92+
success: false,
93+
reason: `${url} is not image`
94+
})
95+
}
96+
} catch {
97+
clearTimeout(timeoutId)
98+
resolve({
99+
success: false,
100+
reason: `request ${url} error`
101+
})
102+
}
103+
})
104+
// tslint:disable-next-line: typedef
105+
const timeoutPromise = new Promise<IPathTransformedImgInfo>((resolve): void => {
106+
timeoutId = setTimeout(() => {
107+
resolve({
108+
success: false,
109+
reason: `request ${url} timeout`
110+
})
111+
}, 10000)
112+
})
113+
return Promise.race([requestFn, timeoutPromise])
114+
}

src/utils/getURLFile.ts

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/utils/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export interface Result {
6969
export interface ImgSize {
7070
width: number
7171
height: number
72+
real?: boolean
7273
}
7374

7475
/**

yarn.lock

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,6 +2336,13 @@ ignore@^3.3.5:
23362336
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
23372337
integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
23382338

2339+
image-size@^0.8.3:
2340+
version "0.8.3"
2341+
resolved "https://registry.npmjs.org/image-size/-/image-size-0.8.3.tgz#f0b568857e034f29baffd37013587f2c0cad8b46"
2342+
integrity sha512-SMtq1AJ+aqHB45c3FsB4ERK0UCiA2d3H1uq8s+8T0Pf8A3W4teyBQyaFaktH6xvZqh+npwlKU7i4fJo0r7TYTg==
2343+
dependencies:
2344+
queue "6.0.1"
2345+
23392346
import-fresh@^2.0.0:
23402347
version "2.0.0"
23412348
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
@@ -2819,21 +2826,11 @@ lodash.templatesettings@^4.0.0:
28192826
dependencies:
28202827
lodash._reinterpolate "^3.0.0"
28212828

2822-
lodash@4, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.2.1:
2829+
lodash@4, lodash@4.17.11, lodash@4.17.14, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.2.1:
28232830
version "4.17.15"
28242831
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
28252832
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
28262833

2827-
lodash@4.17.11:
2828-
version "4.17.11"
2829-
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
2830-
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
2831-
2832-
lodash@4.17.14:
2833-
version "4.17.14"
2834-
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba"
2835-
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==
2836-
28372834
log-symbols@^2.2.0:
28382835
version "2.2.0"
28392836
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
@@ -3607,6 +3604,13 @@ qs@~6.5.2:
36073604
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
36083605
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
36093606

3607+
queue@6.0.1:
3608+
version "6.0.1"
3609+
resolved "https://registry.npmjs.org/queue/-/queue-6.0.1.tgz#abd5a5b0376912f070a25729e0b6a7d565683791"
3610+
integrity sha512-AJBQabRCCNr9ANq8v77RJEv73DPbn55cdTb+Giq4X0AVnNVZvMHlYp7XlQiN+1npCZj1DuSmaA2hYVUUDgxFDg==
3611+
dependencies:
3612+
inherits "~2.0.3"
3613+
36103614
quick-lru@^1.0.0:
36113615
version "1.1.0"
36123616
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"

0 commit comments

Comments
 (0)