@divriots/jampack 0.20.2 → 0.21.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 +0 -0
- package/README.md +0 -0
- package/dist/cache.js +5 -1
- package/dist/config-default.js +1 -1
- package/dist/index.js +3 -0
- package/dist/optimize.js +23 -14
- package/dist/optimizers/inline-critical-css.js +2 -0
- package/dist/state.d.ts +1 -0
- package/dist/utils/resource.d.ts +2 -1
- package/dist/utils/resource.js +19 -3
- package/package.json +17 -16
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
package/dist/cache.js
CHANGED
|
@@ -4,8 +4,11 @@ import * as fs from 'fs/promises';
|
|
|
4
4
|
import $state from './state.js';
|
|
5
5
|
import { CACHE_VERSIONS } from './packagejson.js';
|
|
6
6
|
const listOfCategories = ['img', 'img-ext'];
|
|
7
|
-
|
|
7
|
+
function getCacheFolder() {
|
|
8
|
+
return $state.args.cache_folder || '.jampack/cache';
|
|
9
|
+
}
|
|
8
10
|
async function cleanCache(full) {
|
|
11
|
+
const CACHE_FOLDER = getCacheFolder();
|
|
9
12
|
if (full) {
|
|
10
13
|
try {
|
|
11
14
|
await fs.rm(CACHE_FOLDER, { recursive: true });
|
|
@@ -60,6 +63,7 @@ function getVersionOfCategory(category) {
|
|
|
60
63
|
return CACHE_VERSIONS[category];
|
|
61
64
|
}
|
|
62
65
|
function getLocation(hash, category) {
|
|
66
|
+
const CACHE_FOLDER = getCacheFolder();
|
|
63
67
|
return path.join(CACHE_FOLDER, category, getVersionOfCategory(category), hash);
|
|
64
68
|
}
|
|
65
69
|
async function getFromCache(category, hash) {
|
package/dist/config-default.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -38,11 +38,14 @@ program
|
|
|
38
38
|
.option('--fail', 'Exits with a non-zero return code if issues.')
|
|
39
39
|
.option('--onlyoptim', 'Only optimize (PASS 1).')
|
|
40
40
|
.option('--onlycomp', 'Only compress (PASS 2).')
|
|
41
|
+
.option('--cache_folder <cache_folder>', 'Default: .jampack/cache')
|
|
41
42
|
.option('--cleancache', 'Clean cache before running')
|
|
42
43
|
.option('--nocache', 'Run with no use of cache')
|
|
43
44
|
.action(async (dir, options) => {
|
|
45
|
+
// Arguments
|
|
44
46
|
$state.dir = dir;
|
|
45
47
|
$state.args = options;
|
|
48
|
+
// Print options
|
|
46
49
|
if (options) {
|
|
47
50
|
console.log('Options:');
|
|
48
51
|
console.log(options);
|
package/dist/optimize.js
CHANGED
|
@@ -155,7 +155,7 @@ function getTheFold($) {
|
|
|
155
155
|
return 0;
|
|
156
156
|
}
|
|
157
157
|
async function processImage(htmlfile, $, imgElement, isAboveTheFold) {
|
|
158
|
-
var _a, _b;
|
|
158
|
+
var _a, _b, _c;
|
|
159
159
|
const img = $(imgElement);
|
|
160
160
|
/*
|
|
161
161
|
* Attribute 'src'
|
|
@@ -264,19 +264,17 @@ async function processImage(htmlfile, $, imgElement, isAboveTheFold) {
|
|
|
264
264
|
let srcToFormat = 'unchanged';
|
|
265
265
|
if (isAboveTheFold) {
|
|
266
266
|
// Above the fold, nothing beats progressive JPEG for LCP
|
|
267
|
-
//
|
|
268
|
-
if ((_b = (await originalImage.getImageMeta())) === null || _b === void 0 ? void 0 : _b.
|
|
269
|
-
|
|
270
|
-
|
|
267
|
+
// But jpeg doesn't support transparency
|
|
268
|
+
if ((_b = (await originalImage.getImageMeta())) === null || _b === void 0 ? void 0 : _b.isOpaque) {
|
|
269
|
+
srcToFormat = 'jpeg+progressive';
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
271
272
|
srcToFormat =
|
|
272
273
|
(await originalImage.getMime()) === 'image/avif' ||
|
|
273
274
|
(await originalImage.getMime()) === 'image/webp'
|
|
274
275
|
? 'unchanged'
|
|
275
276
|
: 'webp';
|
|
276
277
|
}
|
|
277
|
-
else {
|
|
278
|
-
srcToFormat = 'jpeg+progressive';
|
|
279
|
-
}
|
|
280
278
|
}
|
|
281
279
|
else if (isInPicture) {
|
|
282
280
|
// srcToFormat should not change if in picture
|
|
@@ -428,18 +426,29 @@ async function processImage(htmlfile, $, imgElement, isAboveTheFold) {
|
|
|
428
426
|
// Only try to generate better images
|
|
429
427
|
// TODO generate more compatible formats (avif => webp/jpeg/png)
|
|
430
428
|
//
|
|
431
|
-
|
|
432
|
-
|
|
429
|
+
const mime = await originalImage.getMime();
|
|
430
|
+
switch (mime) {
|
|
433
431
|
case 'image/png':
|
|
432
|
+
case 'image/jpeg':
|
|
434
433
|
sourcesToGenerate.push({
|
|
435
434
|
mime: 'image/webp',
|
|
436
435
|
format: 'webp',
|
|
437
436
|
});
|
|
438
437
|
case 'image/webp':
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
438
|
+
// Only add AVIF source for lossy images
|
|
439
|
+
// AVIF don't perform well on lossless images
|
|
440
|
+
// PNG and WebP will perform better
|
|
441
|
+
// https://www.reddit.com/r/jpegxl/comments/l9ta2u/how_does_lossless_jpegxl_compared_to_png/
|
|
442
|
+
// https://twitter.com/jonsneyers/status/1346389917816008704?s=19
|
|
443
|
+
const isLossless = mime === 'image/png' ||
|
|
444
|
+
(mime === 'image/webp' &&
|
|
445
|
+
((_c = (await originalImage.getImageMeta())) === null || _c === void 0 ? void 0 : _c.isLossless));
|
|
446
|
+
if (!isLossless) {
|
|
447
|
+
sourcesToGenerate.push({
|
|
448
|
+
mime: 'image/avif',
|
|
449
|
+
format: 'avif',
|
|
450
|
+
});
|
|
451
|
+
}
|
|
443
452
|
case 'image/avif':
|
|
444
453
|
// Nothing better
|
|
445
454
|
break;
|
package/dist/state.d.ts
CHANGED
package/dist/utils/resource.d.ts
CHANGED
package/dist/utils/resource.js
CHANGED
|
@@ -21,21 +21,37 @@ export class Resource {
|
|
|
21
21
|
async getImageMeta() {
|
|
22
22
|
if (this.image_meta === undefined) {
|
|
23
23
|
const ext = await this.getExt();
|
|
24
|
+
let isLossless = false;
|
|
24
25
|
switch (ext) {
|
|
25
26
|
case 'svg':
|
|
26
27
|
case 'gif':
|
|
27
|
-
case 'jpg':
|
|
28
28
|
case 'png':
|
|
29
|
-
case 'webp':
|
|
30
29
|
case 'tif':
|
|
30
|
+
isLossless = true;
|
|
31
|
+
case 'webp':
|
|
32
|
+
if (!isLossless) {
|
|
33
|
+
try {
|
|
34
|
+
// TODO check if webp is lossless
|
|
35
|
+
// const info = await WebPInfo.from(await this.getData());
|
|
36
|
+
// isLossless = info.summary.isLossless;
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
console.warn('Failed to get WebP info');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
31
42
|
case 'avif':
|
|
43
|
+
// TODO
|
|
44
|
+
// Check for lossless avif
|
|
45
|
+
case 'jpg':
|
|
32
46
|
let sharpFile = await sharp(await this.getData(), { animated: true });
|
|
33
47
|
const meta = await sharpFile.metadata();
|
|
48
|
+
const stats = await sharpFile.stats();
|
|
34
49
|
this.image_meta = {
|
|
35
50
|
width: meta.width,
|
|
36
51
|
height: meta.height,
|
|
37
52
|
isProgressive: meta.isProgressive || false,
|
|
38
|
-
|
|
53
|
+
isOpaque: stats.isOpaque,
|
|
54
|
+
isLossless,
|
|
39
55
|
};
|
|
40
56
|
break;
|
|
41
57
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@divriots/jampack",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"cache-version": {
|
|
5
5
|
"img": "v1",
|
|
6
6
|
"img-ext": "v1"
|
|
@@ -22,45 +22,46 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@divriots/cheerio": "1.0.0-rc.12",
|
|
24
24
|
"@proload/core": "^0.3.3",
|
|
25
|
-
"@swc/core": "^1.3.
|
|
25
|
+
"@swc/core": "^1.3.86",
|
|
26
26
|
"add": "^2.0.6",
|
|
27
27
|
"commander": "^10.0.1",
|
|
28
28
|
"critters": "^0.0.20",
|
|
29
29
|
"deepmerge": "^4.3.1",
|
|
30
|
-
"esbuild": "^0.19.
|
|
30
|
+
"esbuild": "^0.19.3",
|
|
31
31
|
"file-type": "^18.5.0",
|
|
32
32
|
"globby": "^13.2.2",
|
|
33
33
|
"hasha": "^5.2.2",
|
|
34
34
|
"html-minifier-terser": "^7.2.0",
|
|
35
35
|
"kleur": "^4.1.5",
|
|
36
|
-
"lightningcss": "^1.
|
|
36
|
+
"lightningcss": "^1.22.0",
|
|
37
37
|
"mini-svg-data-uri": "^1.4.4",
|
|
38
38
|
"ora": "^7.0.1",
|
|
39
39
|
"quicklink": "^2.3.0",
|
|
40
|
-
"sharp": "^0.32.
|
|
40
|
+
"sharp": "^0.32.6",
|
|
41
41
|
"svgo": "^3.0.2",
|
|
42
42
|
"table": "^6.8.1",
|
|
43
|
-
"undici": "^5.
|
|
43
|
+
"undici": "^5.24.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/html-minifier-terser": "^7.0.0",
|
|
47
|
-
"@types/node": "^20.
|
|
47
|
+
"@types/node": "^20.6.2",
|
|
48
48
|
"shx": "^0.3.3",
|
|
49
49
|
"ts-node": "^10.2.1",
|
|
50
50
|
"tslib": "^2.6.2",
|
|
51
51
|
"typescript": "^5.2.2"
|
|
52
52
|
},
|
|
53
|
-
"engines": {
|
|
54
|
-
"node": ">=14.0.0"
|
|
55
|
-
},
|
|
56
|
-
"bugs": "https://github.com/divriots/jampack/issues",
|
|
57
|
-
"keywords": [],
|
|
58
|
-
"types": "dist/index.d.ts",
|
|
59
53
|
"scripts": {
|
|
60
54
|
"watch": "pnpm build --watch",
|
|
61
|
-
"try": "shx rm -fr demo && cp -R
|
|
55
|
+
"try": "shx rm -fr demo && cp -R demo_drc demo && node ./dist/index.js ./demo --nocache",
|
|
62
56
|
"build": "shx rm -rf dist && tsc -b",
|
|
63
57
|
"lint": "eslint . --ext .ts --config .eslintrc",
|
|
58
|
+
"prepublishOnly": "pnpm build",
|
|
64
59
|
"cleanAllDotJampack": "find -s . | grep '.jampack$' | xargs rm -fr"
|
|
65
|
-
}
|
|
66
|
-
|
|
60
|
+
},
|
|
61
|
+
"engines": {
|
|
62
|
+
"node": ">=14.0.0"
|
|
63
|
+
},
|
|
64
|
+
"bugs": "https://github.com/divriots/jampack/issues",
|
|
65
|
+
"keywords": [],
|
|
66
|
+
"types": "dist/index.d.ts"
|
|
67
|
+
}
|