@divriots/jampack 0.12.2 → 0.14.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.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
- export type Category = 'img' | 'img-ext';
2
+ declare const listOfCategories: readonly ["img", "img-ext"];
3
+ export type Category = (typeof listOfCategories)[number];
3
4
  export type CacheData = {
4
5
  buffer: Buffer;
5
6
  meta: any;
package/dist/cache.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import hasha from 'hasha';
2
2
  import path from 'path';
3
3
  import * as fs from 'fs/promises';
4
- import { VERSION } from './version.js';
5
4
  import $state from './state.js';
5
+ import { CACHE_VERSIONS } from './packagejson.js';
6
+ const listOfCategories = ['img', 'img-ext'];
6
7
  const CACHE_FOLDER = '.jampack/cache';
7
- const CACHE_FOLDER_VERSION = CACHE_FOLDER + '/' + VERSION;
8
8
  async function cleanCache(full) {
9
9
  if (full) {
10
10
  try {
@@ -15,19 +15,36 @@ async function cleanCache(full) {
15
15
  }
16
16
  return;
17
17
  }
18
- // List versions in cache
19
- let files;
18
+ // Delete old cache category
19
+ let catFolders = [];
20
20
  try {
21
- files = await fs.readdir(CACHE_FOLDER);
21
+ catFolders = await fs.readdir(CACHE_FOLDER);
22
22
  }
23
23
  catch (e) {
24
- // Nothing to do probably no cache available
25
- return;
24
+ // No problem
25
+ }
26
+ for (const f of catFolders) {
27
+ // @ts-ignore
28
+ if (!listOfCategories.includes(f))
29
+ fs.rm(path.join(CACHE_FOLDER, f), { recursive: true });
30
+ }
31
+ // Loop cache folders
32
+ for (const cat of listOfCategories) {
33
+ const location = path.join(CACHE_FOLDER, cat);
34
+ // List versions in cache
35
+ let folders;
36
+ try {
37
+ folders = await fs.readdir(location);
38
+ }
39
+ catch (e) {
40
+ continue;
41
+ }
42
+ // Delete old cache versions
43
+ for (const f of folders) {
44
+ if (f !== CACHE_VERSIONS[cat])
45
+ fs.rm(path.join(location, f), { recursive: true });
46
+ }
26
47
  }
27
- // Delete old cache versions
28
- await files
29
- .filter((f) => f !== VERSION)
30
- .forEach(async (f) => fs.rm(path.join(CACHE_FOLDER, f), { recursive: true }));
31
48
  }
32
49
  function computeCacheHash(buffer, options) {
33
50
  if ($state.args.nocache) {
@@ -39,8 +56,11 @@ function computeCacheHash(buffer, options) {
39
56
  }
40
57
  return hash;
41
58
  }
59
+ function getVersionOfCategory(category) {
60
+ return CACHE_VERSIONS[category];
61
+ }
42
62
  function getLocation(hash, category) {
43
- return path.join(CACHE_FOLDER_VERSION, category, hash);
63
+ return path.join(CACHE_FOLDER, category, getVersionOfCategory(category), hash);
44
64
  }
45
65
  async function getFromCache(category, hash) {
46
66
  if ($state.args.nocache) {
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 });
@@ -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) && ((_b = options.resize) === null || _b === void 0 ? void 0 : _b.height)) {
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
- ...options.resize,
119
- fit: 'fill',
119
+ ...resize,
120
120
  withoutEnlargement: true,
121
121
  });
122
122
  }
@@ -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: /^.*$/,
@@ -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' | 'cdn-srcset-when-possible' | 'add-dimensions-only';
16
+ process: 'off' | 'download';
15
17
  src_include: RegExp;
16
18
  src_exclude: RegExp | null;
17
19
  };
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 './version.js';
13
+ import { VERSION } from './packagejson.js';
14
+ import { mkdirSync } from 'fs';
15
+ import { join } from 'path';
14
16
  const logo = ` __ __
15
17
  |__|____ _____ ___________ ____ | | __
16
18
  | \\__ \\ / \\\\____ \\__ \\ _/ ___\\| |/ /
@@ -53,7 +55,15 @@ program
53
55
  fast();
54
56
  }
55
57
  // Clean cache
56
- cleanCache(options.cleancache);
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
- const htmlFolder = path.dirname(path.resolve(path.join($state.dir, htmlfile)));
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
  /*
@@ -259,6 +254,7 @@ async function processImage(htmlfile, $, imgElement, isAboveTheFold) {
259
254
  }
260
255
  newImage = await compressImage(await originalImage.getData(), {
261
256
  toFormat: srcToFormat,
257
+ resize: { width: config.image.srcset_max_width },
262
258
  });
263
259
  if ((newImage === null || newImage === void 0 ? void 0 : newImage.data) &&
264
260
  (newImage.data.length < (await originalImage.getLen()) ||
@@ -458,9 +454,8 @@ async function generateSrcSet(htmlfile, originalImage, startSrc, startSrcLength,
458
454
  }
459
455
  // Start reduction
460
456
  const step = 300; //px
461
- const ratio = imageWidth / imageHeight;
462
457
  let valueW = !startSrc ? imageWidth : imageWidth - step;
463
- let valueH = Math.trunc(valueW / ratio);
458
+ valueW = Math.min(valueW, config.image.srcset_max_width);
464
459
  let previousImageSize = startSrcLength || Number.MAX_VALUE;
465
460
  while (valueW >= config.image.srcset_min_width) {
466
461
  const src = imageSrc(`@${valueW}w`);
@@ -468,7 +463,7 @@ async function generateSrcSet(htmlfile, originalImage, startSrc, startSrcLength,
468
463
  let doAddToSrcSet = true;
469
464
  // Don't generate srcset file twice
470
465
  if (!$state.compressedFiles.has(absoluteFilename)) {
471
- const compressedImage = await compressImage(await originalImage.getData(), { ...options, resize: { width: valueW, height: valueH } });
466
+ const compressedImage = await compressImage(await originalImage.getData(), { ...options, resize: { width: valueW } });
472
467
  if (!(compressedImage === null || compressedImage === void 0 ? void 0 : compressedImage.data) ||
473
468
  compressedImage.data.length >= previousImageSize) {
474
469
  // New image is not compressed or bigger than previous image in srcset
@@ -491,7 +486,6 @@ async function generateSrcSet(htmlfile, originalImage, startSrc, startSrcLength,
491
486
  }
492
487
  // reduce size
493
488
  valueW -= step;
494
- valueH = Math.trunc(valueW / ratio);
495
489
  }
496
490
  if (new_srcset) {
497
491
  return startSrc
@@ -1,2 +1,2 @@
1
1
  import '../utils/polyfill-fetch.js';
2
- export declare function downloadExternalImage(href: string, dir: string): Promise<string>;
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(href, dir) {
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 local filename
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 filename = `./_jampack/${hash}.${ext}`;
97
- try {
98
- await fs.mkdir(path.join(dir, '_jampack'));
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
  }
@@ -0,0 +1,2 @@
1
+ export declare const VERSION: string;
2
+ export declare const CACHE_VERSIONS: Record<string, string>;
@@ -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.12.2",
3
+ "version": "0.14.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": {
@@ -29,7 +33,7 @@
29
33
  "lightningcss": "^1.20.0",
30
34
  "mini-svg-data-uri": "^1.4.4",
31
35
  "ora": "^6.3.0",
32
- "sharp": "^0.32.1",
36
+ "sharp": "^0.32.5",
33
37
  "svgo": "^3.0.2",
34
38
  "table": "^6.8.1",
35
39
  "undici": "^5.22.1"
@@ -47,7 +51,8 @@
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;