@divriots/jampack 0.13.0 → 0.15.0
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/dist/cache.js +1 -4
- package/dist/compress.js +1 -1
- package/dist/compressors/images.js +5 -5
- package/dist/config-default.js +5 -0
- package/dist/config-fast.js +3 -0
- package/dist/config-types.d.ts +6 -1
- package/dist/config.js +1 -1
- package/dist/index.js +11 -1
- package/dist/optimize.js +9 -13
- package/dist/optimizers/img-external.d.ts +1 -1
- package/dist/optimizers/img-external.js +8 -10
- package/dist/packagejson.d.ts +2 -0
- package/dist/{version.js → packagejson.js} +1 -0
- package/package.json +17 -12
- package/dist/version.d.ts +0 -1
package/dist/cache.js
CHANGED
|
@@ -2,12 +2,9 @@ import hasha from 'hasha';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import * as fs from 'fs/promises';
|
|
4
4
|
import $state from './state.js';
|
|
5
|
+
import { CACHE_VERSIONS } from './packagejson.js';
|
|
5
6
|
const listOfCategories = ['img', 'img-ext'];
|
|
6
7
|
const CACHE_FOLDER = '.jampack/cache';
|
|
7
|
-
const CACHE_VERSIONS = {
|
|
8
|
-
img: 'v1',
|
|
9
|
-
'img-ext': 'v1',
|
|
10
|
-
};
|
|
11
8
|
async function cleanCache(full) {
|
|
12
9
|
if (full) {
|
|
13
10
|
try {
|
package/dist/compress.js
CHANGED
|
@@ -69,7 +69,7 @@ const processFile = async (file, stats) => {
|
|
|
69
69
|
};
|
|
70
70
|
export async function compressFolder(exclude) {
|
|
71
71
|
const spinner = ora(getProgressText()).start();
|
|
72
|
-
const globs = ['**/**'];
|
|
72
|
+
const globs = ['**/**', '!_jampack/**']; // Exclude jampack folder because already compressed
|
|
73
73
|
if (exclude)
|
|
74
74
|
globs.push('!' + exclude);
|
|
75
75
|
const paths = await globby(globs, { cwd: $state.dir, absolute: true });
|
|
@@ -19,8 +19,6 @@ export async function compressImage(data, options) {
|
|
|
19
19
|
}
|
|
20
20
|
// Load modifiable toFormat
|
|
21
21
|
let toFormat = options.toFormat || 'unchanged';
|
|
22
|
-
if (!config.image.compress)
|
|
23
|
-
return undefined;
|
|
24
22
|
let sharpFile = await sharp(data, { animated: true });
|
|
25
23
|
const meta = await sharpFile.metadata();
|
|
26
24
|
if (meta.pages && meta.pages > 1) {
|
|
@@ -30,6 +28,8 @@ export async function compressImage(data, options) {
|
|
|
30
28
|
let outputFormat;
|
|
31
29
|
// Special case for svg
|
|
32
30
|
if (meta.format === 'svg') {
|
|
31
|
+
if (!config.image.svg.optimization)
|
|
32
|
+
return undefined;
|
|
33
33
|
try {
|
|
34
34
|
const output = svgo(data.toString(), {
|
|
35
35
|
multipass: true,
|
|
@@ -113,10 +113,10 @@ export async function compressImage(data, options) {
|
|
|
113
113
|
if (!outputFormat)
|
|
114
114
|
return undefined;
|
|
115
115
|
// If resize is requested
|
|
116
|
-
if (((_a = options.resize) === null || _a === void 0 ? void 0 : _a.width)
|
|
116
|
+
if (((_a = options.resize) === null || _a === void 0 ? void 0 : _a.width) || ((_b = options.resize) === null || _b === void 0 ? void 0 : _b.height)) {
|
|
117
|
+
const resize = options.resize;
|
|
117
118
|
sharpFile = sharpFile.resize({
|
|
118
|
-
...
|
|
119
|
-
fit: 'fill',
|
|
119
|
+
...resize,
|
|
120
120
|
withoutEnlargement: true,
|
|
121
121
|
});
|
|
122
122
|
}
|
package/dist/config-default.js
CHANGED
|
@@ -5,6 +5,8 @@ const default_options = {
|
|
|
5
5
|
image: {
|
|
6
6
|
embed_size: 1500,
|
|
7
7
|
srcset_min_width: 640,
|
|
8
|
+
srcset_max_width: 1920 * 2,
|
|
9
|
+
max_width: 99999,
|
|
8
10
|
external: {
|
|
9
11
|
process: 'off',
|
|
10
12
|
src_include: /^.*$/,
|
|
@@ -34,6 +36,9 @@ const default_options = {
|
|
|
34
36
|
mode: 'lossly',
|
|
35
37
|
},
|
|
36
38
|
},
|
|
39
|
+
svg: {
|
|
40
|
+
optimization: true,
|
|
41
|
+
},
|
|
37
42
|
},
|
|
38
43
|
};
|
|
39
44
|
export default default_options;
|
package/dist/config-fast.js
CHANGED
package/dist/config-types.d.ts
CHANGED
|
@@ -10,8 +10,10 @@ export type Options = {
|
|
|
10
10
|
image: {
|
|
11
11
|
embed_size: number;
|
|
12
12
|
srcset_min_width: number;
|
|
13
|
+
srcset_max_width: number;
|
|
14
|
+
max_width: number;
|
|
13
15
|
external: {
|
|
14
|
-
process: 'off' | 'download'
|
|
16
|
+
process: 'off' | 'download';
|
|
15
17
|
src_include: RegExp;
|
|
16
18
|
src_exclude: RegExp | null;
|
|
17
19
|
};
|
|
@@ -31,5 +33,8 @@ export type Options = {
|
|
|
31
33
|
options_lossless: WebpOptions;
|
|
32
34
|
options_lossly: WebpOptions;
|
|
33
35
|
};
|
|
36
|
+
svg: {
|
|
37
|
+
optimization: boolean;
|
|
38
|
+
};
|
|
34
39
|
};
|
|
35
40
|
};
|
package/dist/config.js
CHANGED
|
@@ -10,7 +10,7 @@ export function fast() {
|
|
|
10
10
|
export async function loadConfig() {
|
|
11
11
|
const proload = await load('jampack', { mustExist: false });
|
|
12
12
|
if (proload) {
|
|
13
|
-
console.log('
|
|
13
|
+
console.log('Merging default config with:');
|
|
14
14
|
console.log(JSON.stringify(proload.value, null, 2));
|
|
15
15
|
Object.assign(options, deepmerge(options, proload.value));
|
|
16
16
|
}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,9 @@ import { printTitle } from './logger.js';
|
|
|
10
10
|
import { exit } from 'process';
|
|
11
11
|
import kleur from 'kleur';
|
|
12
12
|
import { cleanCache } from './cache.js';
|
|
13
|
-
import { VERSION } from './
|
|
13
|
+
import { VERSION } from './packagejson.js';
|
|
14
|
+
import { mkdirSync } from 'fs';
|
|
15
|
+
import { join } from 'path';
|
|
14
16
|
const logo = ` __ __
|
|
15
17
|
|__|____ _____ ___________ ____ | | __
|
|
16
18
|
| \\__ \\ / \\\\____ \\__ \\ _/ ___\\| |/ /
|
|
@@ -54,6 +56,14 @@ program
|
|
|
54
56
|
}
|
|
55
57
|
// Clean cache
|
|
56
58
|
await cleanCache(options.cleancache);
|
|
59
|
+
// Make _jampack folder
|
|
60
|
+
try {
|
|
61
|
+
mkdirSync(join(dir, '_jampack'));
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
console.error('Failed to create `_jampack` folder.');
|
|
65
|
+
exit(1);
|
|
66
|
+
}
|
|
57
67
|
if (!options.onlycomp) {
|
|
58
68
|
printTitle('PASS 1 - Optimizing');
|
|
59
69
|
console.time('Done');
|
package/dist/optimize.js
CHANGED
|
@@ -194,8 +194,7 @@ async function processImage(htmlfile, $, imgElement, isAboveTheFold) {
|
|
|
194
194
|
return;
|
|
195
195
|
case 'download': // Download external image for local processing
|
|
196
196
|
try {
|
|
197
|
-
|
|
198
|
-
attrib_src = await downloadExternalImage(attrib_src, htmlFolder);
|
|
197
|
+
attrib_src = await downloadExternalImage(htmlfile, attrib_src);
|
|
199
198
|
img.attr('src', attrib_src);
|
|
200
199
|
}
|
|
201
200
|
catch (e) {
|
|
@@ -206,10 +205,6 @@ async function processImage(htmlfile, $, imgElement, isAboveTheFold) {
|
|
|
206
205
|
return; // No more processing
|
|
207
206
|
}
|
|
208
207
|
break;
|
|
209
|
-
case 'add-dimensions-only': // Only add dimensions of image
|
|
210
|
-
throw new Error('External images with `add-dimensions-only` is not implemented yet.');
|
|
211
|
-
case 'cdn-srcset-when-possible': // Use unpic to use CDN capabilities
|
|
212
|
-
throw new Error('External images with `cdn-srcset-when-possible` is not implemented yet.');
|
|
213
208
|
}
|
|
214
209
|
}
|
|
215
210
|
/*
|
|
@@ -257,9 +252,12 @@ async function processImage(htmlfile, $, imgElement, isAboveTheFold) {
|
|
|
257
252
|
? 'unchanged'
|
|
258
253
|
: 'webp';
|
|
259
254
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
255
|
+
if (config.image.compress) {
|
|
256
|
+
newImage = await compressImage(await originalImage.getData(), {
|
|
257
|
+
toFormat: srcToFormat,
|
|
258
|
+
resize: { width: config.image.srcset_max_width },
|
|
259
|
+
});
|
|
260
|
+
}
|
|
263
261
|
if ((newImage === null || newImage === void 0 ? void 0 : newImage.data) &&
|
|
264
262
|
(newImage.data.length < (await originalImage.getLen()) ||
|
|
265
263
|
srcToFormat === 'jpeg+progressive') // Progressive override all even if worse
|
|
@@ -458,9 +456,8 @@ async function generateSrcSet(htmlfile, originalImage, startSrc, startSrcLength,
|
|
|
458
456
|
}
|
|
459
457
|
// Start reduction
|
|
460
458
|
const step = 300; //px
|
|
461
|
-
const ratio = imageWidth / imageHeight;
|
|
462
459
|
let valueW = !startSrc ? imageWidth : imageWidth - step;
|
|
463
|
-
|
|
460
|
+
valueW = Math.min(valueW, config.image.srcset_max_width);
|
|
464
461
|
let previousImageSize = startSrcLength || Number.MAX_VALUE;
|
|
465
462
|
while (valueW >= config.image.srcset_min_width) {
|
|
466
463
|
const src = imageSrc(`@${valueW}w`);
|
|
@@ -468,7 +465,7 @@ async function generateSrcSet(htmlfile, originalImage, startSrc, startSrcLength,
|
|
|
468
465
|
let doAddToSrcSet = true;
|
|
469
466
|
// Don't generate srcset file twice
|
|
470
467
|
if (!$state.compressedFiles.has(absoluteFilename)) {
|
|
471
|
-
const compressedImage = await compressImage(await originalImage.getData(), { ...options, resize: { width: valueW
|
|
468
|
+
const compressedImage = await compressImage(await originalImage.getData(), { ...options, resize: { width: valueW } });
|
|
472
469
|
if (!(compressedImage === null || compressedImage === void 0 ? void 0 : compressedImage.data) ||
|
|
473
470
|
compressedImage.data.length >= previousImageSize) {
|
|
474
471
|
// New image is not compressed or bigger than previous image in srcset
|
|
@@ -491,7 +488,6 @@ async function generateSrcSet(htmlfile, originalImage, startSrc, startSrcLength,
|
|
|
491
488
|
}
|
|
492
489
|
// reduce size
|
|
493
490
|
valueW -= step;
|
|
494
|
-
valueH = Math.trunc(valueW / ratio);
|
|
495
491
|
}
|
|
496
492
|
if (new_srcset) {
|
|
497
493
|
return startSrc
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import '../utils/polyfill-fetch.js';
|
|
2
|
-
export declare function downloadExternalImage(
|
|
2
|
+
export declare function downloadExternalImage(htmlfile: string, href: string): Promise<string>;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as fs from 'fs/promises';
|
|
3
|
+
import $state from '../state.js';
|
|
3
4
|
import hasha from 'hasha';
|
|
4
5
|
import { fileTypeFromBuffer } from 'file-type';
|
|
5
6
|
import { addToCache, getFromCache } from '../cache.js';
|
|
6
7
|
import { parse } from '../utils/cache-control-parser.js';
|
|
7
8
|
import '../utils/polyfill-fetch.js';
|
|
8
|
-
export async function downloadExternalImage(
|
|
9
|
+
export async function downloadExternalImage(htmlfile, href) {
|
|
9
10
|
var _a, _b, _c, _d, _e;
|
|
10
11
|
const hash = hasha(href, {
|
|
11
12
|
algorithm: 'md5',
|
|
@@ -90,16 +91,13 @@ export async function downloadExternalImage(href, dir) {
|
|
|
90
91
|
// buffer can't be undefined here
|
|
91
92
|
if (!buffer)
|
|
92
93
|
throw new Error('Buffer is undefined');
|
|
93
|
-
// Construct
|
|
94
|
+
// Construct contenthash
|
|
95
|
+
const contentHash = hasha(buffer, { algorithm: 'md5' });
|
|
96
|
+
// Construct local filename relative to root dir
|
|
94
97
|
if (!ext)
|
|
95
98
|
throw new Error('Unknown image format');
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
catch (e) {
|
|
101
|
-
// Nothing to do - folder is probably already present
|
|
102
|
-
}
|
|
103
|
-
fs.writeFile(path.join(dir, filename), buffer);
|
|
99
|
+
const htmlFolder = path.dirname(htmlfile);
|
|
100
|
+
const filename = path.relative(path.join($state.dir, htmlFolder), path.join($state.dir, `_jampack/${contentHash}.${ext}`));
|
|
101
|
+
await fs.writeFile(path.join($state.dir, htmlFolder, filename), buffer);
|
|
104
102
|
return filename;
|
|
105
103
|
}
|
|
@@ -4,3 +4,4 @@ import { fileURLToPath } from 'url';
|
|
|
4
4
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
5
5
|
const pkgjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json')).toString());
|
|
6
6
|
export const VERSION = pkgjson.version;
|
|
7
|
+
export const CACHE_VERSIONS = pkgjson['cache-version'];
|
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@divriots/jampack",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
|
+
"cache-version": {
|
|
5
|
+
"img": "v1",
|
|
6
|
+
"img-ext": "v1"
|
|
7
|
+
},
|
|
4
8
|
"description": "Packer for static websites",
|
|
5
9
|
"author": "Georges Gomes @georges-gomes",
|
|
6
10
|
"bin": {
|
|
@@ -18,36 +22,37 @@
|
|
|
18
22
|
"dependencies": {
|
|
19
23
|
"@divriots/cheerio": "1.0.0-rc.12",
|
|
20
24
|
"@proload/core": "^0.3.3",
|
|
21
|
-
"@swc/core": "^1.3.
|
|
25
|
+
"@swc/core": "^1.3.80",
|
|
22
26
|
"commander": "^10.0.1",
|
|
23
27
|
"deepmerge": "^4.3.1",
|
|
24
|
-
"file-type": "^18.
|
|
25
|
-
"globby": "^13.
|
|
28
|
+
"file-type": "^18.5.0",
|
|
29
|
+
"globby": "^13.2.2",
|
|
26
30
|
"hasha": "^5.2.2",
|
|
27
31
|
"html-minifier-terser": "^7.2.0",
|
|
28
32
|
"kleur": "^4.1.5",
|
|
29
|
-
"lightningcss": "^1.
|
|
33
|
+
"lightningcss": "^1.21.5",
|
|
30
34
|
"mini-svg-data-uri": "^1.4.4",
|
|
31
|
-
"ora": "^
|
|
32
|
-
"sharp": "^0.32.
|
|
35
|
+
"ora": "^7.0.1",
|
|
36
|
+
"sharp": "^0.32.5",
|
|
33
37
|
"svgo": "^3.0.2",
|
|
34
38
|
"table": "^6.8.1",
|
|
35
|
-
"undici": "^5.
|
|
39
|
+
"undici": "^5.23.0"
|
|
36
40
|
},
|
|
37
41
|
"devDependencies": {
|
|
38
42
|
"@types/html-minifier-terser": "^7.0.0",
|
|
39
|
-
"@types/node": "^
|
|
43
|
+
"@types/node": "^20.5.7",
|
|
40
44
|
"shx": "^0.3.3",
|
|
41
45
|
"ts-node": "^10.2.1",
|
|
42
|
-
"tslib": "^2.
|
|
43
|
-
"typescript": "^5.
|
|
46
|
+
"tslib": "^2.6.2",
|
|
47
|
+
"typescript": "^5.2.2"
|
|
44
48
|
},
|
|
45
49
|
"scripts": {
|
|
46
50
|
"watch": "pnpm build --watch",
|
|
47
51
|
"try": "shx rm -fr demo && cp -R demo_rf demo && node ./dist/index.js ./demo --nocache --onlyoptim",
|
|
48
52
|
"build": "shx rm -rf dist && tsc -b",
|
|
49
53
|
"lint": "eslint . --ext .ts --config .eslintrc",
|
|
50
|
-
"prepublishOnly": "pnpm build"
|
|
54
|
+
"prepublishOnly": "pnpm build",
|
|
55
|
+
"cleanAllDotJampack": "find -s . | grep '.jampack$' | xargs rm -fr"
|
|
51
56
|
},
|
|
52
57
|
"engines": {
|
|
53
58
|
"node": ">=14.0.0"
|
package/dist/version.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const VERSION: any;
|