@divriots/jampack 0.31.1 → 0.32.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.
@@ -65,6 +65,12 @@ const default_options = {
65
65
  how: 'native',
66
66
  },
67
67
  },
68
+ video: {
69
+ autoplay_lazyload: {
70
+ when: 'below-the-fold',
71
+ how: 'js',
72
+ },
73
+ },
68
74
  misc: {
69
75
  prefetch_links: 'off',
70
76
  },
@@ -65,6 +65,12 @@ export type Options = {
65
65
  how: 'native' | 'js';
66
66
  };
67
67
  };
68
+ video: {
69
+ autoplay_lazyload: {
70
+ when: 'never' | 'below-the-fold' | 'always';
71
+ how: 'js';
72
+ };
73
+ };
68
74
  misc: {
69
75
  prefetch_links: 'in-viewport' | 'off';
70
76
  };
package/dist/optimize.js CHANGED
@@ -13,6 +13,7 @@ import { downloadExternalImage } from './optimizers/img-external.js';
13
13
  import { inlineCriticalCss } from './optimizers/inline-critical-css.js';
14
14
  import { prefetch_links_in_viewport } from './optimizers/prefetch-links.js';
15
15
  import { processIframe } from './optimizers/process-iframe.js';
16
+ import { processVideo } from './optimizers/process-video.js';
16
17
  const UNPIC_DEFAULT_HOST_REGEX = /^https:\/\/n\//g;
17
18
  const ABOVE_FOLD_DATA_ATTR = 'data-abovethefold';
18
19
  function getIntAttr(img, attr) {
@@ -33,68 +34,9 @@ async function analyse(state, file) {
33
34
  return;
34
35
  const $ = cheerio.load(html, { sourceCodeLocationInfo: true });
35
36
  const theFold = getTheFold($);
36
- const imgs = $('img');
37
- const imgsArray = [];
38
- imgs.each((index, imgElement) => {
39
- imgsArray.push(imgElement);
40
- });
41
- // Process images sequentially
42
- const spinnerImg = ora({ prefixText: ' ' }).start();
43
- for (let i = 0; i < imgsArray.length; i++) {
44
- const imgElement = imgsArray[i];
45
- spinnerImg.text = kleur.dim(`<img> [${i + 1}/${imgsArray.length}] ${$(imgElement).attr('src')}`);
46
- const img = $(imgElement);
47
- const isAboveTheFold = isElementAboveTheFold(img, imgElement, theFold);
48
- img.removeAttr(ABOVE_FOLD_DATA_ATTR);
49
- try {
50
- await processImage(state, file, img, isAboveTheFold);
51
- }
52
- catch (e) {
53
- state.reportIssue(file, {
54
- type: 'erro',
55
- msg: e.message ||
56
- `Unexpected error while processing image: ${JSON.stringify(e)}`,
57
- });
58
- }
59
- }
60
- // Reset spinner
61
- spinnerImg.text = kleur.dim(`<img> [${imgsArray.length}/${imgsArray.length}]`);
62
- // Notify issues
63
- const issues = state.issues.get(file);
64
- if (issues) {
65
- spinnerImg.fail();
66
- console.log(kleur.red(` ${issues.length} issue${issues.length > 1 ? 's' : ''}`));
67
- }
68
- else {
69
- spinnerImg.succeed();
70
- }
71
- const iframes = $('iframe');
72
- const iframesArray = [];
73
- iframes.each((index, ifElement) => {
74
- iframesArray.push(ifElement);
75
- });
76
- // Process iframes sequentially
77
- const spinnerIframe = ora({ prefixText: ' ' }).start();
78
- for (let i = 0; i < iframesArray.length; i++) {
79
- const ifElement = iframesArray[i];
80
- spinnerIframe.text = kleur.dim(`<iframe> [${i + 1}/${iframesArray.length}] ${$(ifElement).attr('src')}`);
81
- const ifr = $(ifElement);
82
- const isAboveTheFold = isElementAboveTheFold(ifr, ifElement, theFold);
83
- ifr.removeAttr(ABOVE_FOLD_DATA_ATTR);
84
- try {
85
- await processIframe(state, file, $, ifElement, isAboveTheFold, appendToBody);
86
- }
87
- catch (e) {
88
- state.reportIssue(file, {
89
- type: 'erro',
90
- msg: e.message ||
91
- `Unexpected error while processing image: ${JSON.stringify(e)}`,
92
- });
93
- }
94
- }
95
- // Reset spinner
96
- spinnerIframe.text = kleur.dim(`<iframe> [${iframesArray.length}/${iframesArray.length}]`);
97
- spinnerIframe.succeed();
37
+ await processTag(state, file, $, 'img', 'src', processImage, theFold, appendToBody);
38
+ await processTag(state, file, $, 'iframe', 'src', processIframe, theFold, appendToBody);
39
+ await processTag(state, file, $, 'video', 'src', processVideo, theFold, appendToBody);
98
40
  // Remove the fold
99
41
  //
100
42
  if (theFold) {
@@ -774,3 +716,41 @@ export async function optimize(state, include, exclude) {
774
716
  await analyse(state, file);
775
717
  }
776
718
  }
719
+ async function processTag(state, file, $, tag, attribute_to_log, processor, theFold, appendToBody) {
720
+ const previous_issues = state.issues.get(file);
721
+ const tags = $(tag);
722
+ const tagsArray = [];
723
+ tags.each((index, tagElement) => {
724
+ tagsArray.push(tagElement);
725
+ });
726
+ // Process tags sequentially
727
+ const spinnerImg = ora({ prefixText: ' ' }).start();
728
+ for (let i = 0; i < tagsArray.length; i++) {
729
+ const tagElement = tagsArray[i];
730
+ spinnerImg.text = kleur.dim(`<${tag}> [${i + 1}/${tagsArray.length}] ${$(tagElement).attr(attribute_to_log)}`);
731
+ const el = $(tagElement);
732
+ const isAboveTheFold = isElementAboveTheFold(el, tagElement, theFold);
733
+ el.removeAttr(ABOVE_FOLD_DATA_ATTR);
734
+ try {
735
+ await processor(state, file, el, isAboveTheFold, appendToBody);
736
+ }
737
+ catch (e) {
738
+ state.reportIssue(file, {
739
+ type: 'erro',
740
+ msg: e.message ||
741
+ `Unexpected error while processing ${tag}: ${JSON.stringify(e)}`,
742
+ });
743
+ }
744
+ }
745
+ // Reset spinner
746
+ spinnerImg.text = kleur.dim(`<${tag}> [${tagsArray.length}/${tagsArray.length}]`);
747
+ // Notify issues
748
+ const issues = state.issues.get(file);
749
+ const newIssues = ((issues === null || issues === void 0 ? void 0 : issues.length) || 0) - ((previous_issues === null || previous_issues === void 0 ? void 0 : previous_issues.length) || 0);
750
+ if (newIssues > 0) {
751
+ spinnerImg.fail();
752
+ }
753
+ else {
754
+ spinnerImg.succeed();
755
+ }
756
+ }
@@ -1,3 +1,3 @@
1
1
  import * as cheerio from '@divriots/cheerio';
2
2
  import type { GlobalState } from '../state.js';
3
- export declare function processIframe(state: GlobalState, htmlfile: string, $: cheerio.CheerioAPI, imgElement: cheerio.Element, isAboveTheFold: boolean, appendToBody: Record<string, string>): Promise<void>;
3
+ export declare function processIframe(state: GlobalState, htmlfile: string, iframe: cheerio.Cheerio<cheerio.Element>, isAboveTheFold: boolean, appendToBody: Record<string, string>): Promise<void>;
@@ -1,6 +1,5 @@
1
- import { install_dependency } from '../utils/install-dep.js';
2
- export async function processIframe(state, htmlfile, $, imgElement, isAboveTheFold, appendToBody) {
3
- const iframe = $(imgElement);
1
+ import { install_lozad } from '../utils/install-dep.js';
2
+ export async function processIframe(state, htmlfile, iframe, isAboveTheFold, appendToBody) {
4
3
  // Reset loading attribute
5
4
  iframe.removeAttr('loading');
6
5
  const lazyloadOptions = state.options.iframe.lazyload;
@@ -18,19 +17,7 @@ export async function processIframe(state, htmlfile, $, imgElement, isAboveTheFo
18
17
  iframe.attr('class', 'jampack-lozad');
19
18
  iframe.attr('data-src', src);
20
19
  iframe.removeAttr('src');
21
- await install_dependency(state, htmlfile, {
22
- source: {
23
- npm_package_name: 'lozad',
24
- absolute_path_to_file: '/dist',
25
- filename: 'lozad.es.js',
26
- },
27
- destination: {
28
- folder_name: 'lozad-1.16',
29
- code_loader: `import lozad from "./lozad.es.js";
30
- const observer = lozad('.jampack-lozad', { rootMargin: '100px 0px', threshold: [0.1] });
31
- observer.observe();`,
32
- },
33
- }, appendToBody);
20
+ await install_lozad(state, htmlfile, appendToBody);
34
21
  }
35
22
  }
36
23
  }
@@ -0,0 +1,3 @@
1
+ import * as cheerio from '@divriots/cheerio';
2
+ import type { GlobalState } from '../state.js';
3
+ export declare function processVideo(state: GlobalState, htmlfile: string, video: cheerio.Cheerio<cheerio.Element>, isAboveTheFold: boolean, appendToBody: Record<string, string>): Promise<void>;
@@ -0,0 +1,29 @@
1
+ import { install_lozad } from '../utils/install-dep.js';
2
+ export async function processVideo(state, htmlfile, video, isAboveTheFold, appendToBody) {
3
+ const autoplay = video.attr('autoplay');
4
+ if (!autoplay || autoplay === '0' || autoplay === 'false') {
5
+ // If the video is not autoplay we can postpone loading
6
+ // if there is a poster
7
+ if (video.attr('poster')) {
8
+ video.attr('preload', 'none');
9
+ return;
10
+ }
11
+ // TODO create poster for videos without poster
12
+ }
13
+ const lazyloadOptions = state.options.video.autoplay_lazyload;
14
+ if (lazyloadOptions.when === 'never') {
15
+ return;
16
+ }
17
+ if (lazyloadOptions.when === 'always' ||
18
+ (lazyloadOptions.when === 'below-the-fold' && !isAboveTheFold)) {
19
+ if (lazyloadOptions.how === 'js') {
20
+ video.attr('class', 'jampack-lozad');
21
+ const src = video.attr('src');
22
+ if (src) {
23
+ video.attr('data-src', src);
24
+ video.removeAttr('src');
25
+ }
26
+ await install_lozad(state, htmlfile, appendToBody);
27
+ }
28
+ }
29
+ }
@@ -10,3 +10,4 @@ export declare function install_dependency(state: GlobalState, html_file: string
10
10
  code_loader: string;
11
11
  };
12
12
  }, appendToBody: Record<string, string>): Promise<void>;
13
+ export declare function install_lozad(state: GlobalState, html_file: string, appendToBody: Record<string, string>): Promise<void>;
@@ -25,3 +25,18 @@ export async function install_dependency(state, html_file, options, appendToBody
25
25
  appendToBody[options.source.npm_package_name] = `<script type="module" src="${path.relative(path_html, url_loader)}"></script>`;
26
26
  }
27
27
  }
28
+ export async function install_lozad(state, html_file, appendToBody) {
29
+ return install_dependency(state, html_file, {
30
+ source: {
31
+ npm_package_name: 'lozad',
32
+ absolute_path_to_file: '/dist',
33
+ filename: 'lozad.es.js',
34
+ },
35
+ destination: {
36
+ folder_name: 'lozad-1.16',
37
+ code_loader: `import lozad from "./lozad.es.js";
38
+ const observer = lozad('.jampack-lozad', { rootMargin: '100px 0px', threshold: [0.1] });
39
+ observer.observe();`,
40
+ },
41
+ }, appendToBody);
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@divriots/jampack",
3
- "version": "0.31.1",
3
+ "version": "0.32.0",
4
4
  "cache-version": {
5
5
  "img": "v1",
6
6
  "img-ext": "v1"