@elementor/editor-audits 4.4.0-1104 → 4.4.0-1106

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/index.mjs CHANGED
@@ -77,17 +77,17 @@ async function requestFreshNonce() {
77
77
  }
78
78
 
79
79
  // src/api/page-context-client.ts
80
- async function fetchPageContext(documentId, attachmentIds) {
81
- return requestPageContext(documentId, attachmentIds, true);
80
+ async function fetchPageContext(documentId, imageSizeRequests) {
81
+ return requestPageContext(documentId, imageSizeRequests, true);
82
82
  }
83
- async function requestPageContext(documentId, attachmentIds, allowNonceRetry) {
83
+ async function requestPageContext(documentId, imageSizeRequests, allowNonceRetry) {
84
84
  const { restNamespace, nonce } = getWindowConfig();
85
85
  const url = `${restNamespace}/audits/page-context`;
86
86
  try {
87
87
  const response = await httpService().get(url, {
88
88
  params: {
89
89
  document_id: documentId,
90
- attachment_ids: attachmentIds
90
+ image_size_requests: imageSizeRequests
91
91
  },
92
92
  headers: { "X-WP-Nonce": nonce }
93
93
  });
@@ -97,7 +97,7 @@ async function requestPageContext(documentId, attachmentIds, allowNonceRetry) {
97
97
  throw error;
98
98
  }
99
99
  await refreshAuditsNonce();
100
- return requestPageContext(documentId, attachmentIds, false);
100
+ return requestPageContext(documentId, imageSizeRequests, false);
101
101
  }
102
102
  }
103
103
 
@@ -282,6 +282,23 @@ function computeReport(documentId, results) {
282
282
  };
283
283
  }
284
284
 
285
+ // src/utils/atomic-background-image-sources.ts
286
+ import { getElementStyles } from "@elementor/editor-elements";
287
+ import {
288
+ backgroundImageOverlayPropTypeUtil,
289
+ backgroundOverlayPropTypeUtil,
290
+ backgroundPropTypeUtil
291
+ } from "@elementor/editor-props";
292
+
293
+ // src/utils/atomic-image-sources.ts
294
+ import {
295
+ imageAttachmentIdPropType,
296
+ imagePropTypeUtil,
297
+ imageSrcPropTypeUtil,
298
+ stringPropTypeUtil,
299
+ urlPropTypeUtil
300
+ } from "@elementor/editor-props";
301
+
285
302
  // src/utils/walk.ts
286
303
  function walkElements(tree, visit) {
287
304
  const parents = [];
@@ -296,6 +313,89 @@ function recurse(nodes, parents, visit) {
296
313
  }
297
314
  }
298
315
 
316
+ // src/utils/atomic-image-sources.ts
317
+ var ATOMIC_IMAGE_PROP_KEYS = ["image", "poster"];
318
+ function walkAtomicImageSources(tree, visit) {
319
+ walkElements(tree, (node) => {
320
+ if (node.elType !== "widget") {
321
+ return;
322
+ }
323
+ for (const key of ATOMIC_IMAGE_PROP_KEYS) {
324
+ const media = extractAtomicImageMedia(node.settings[key]);
325
+ if (media) {
326
+ visit({ node, media });
327
+ }
328
+ }
329
+ });
330
+ }
331
+ function extractAtomicImageMedia(imageProp) {
332
+ const image = imagePropTypeUtil.extract(imageProp);
333
+ if (!image) {
334
+ return null;
335
+ }
336
+ const src = imageSrcPropTypeUtil.extract(image.src);
337
+ if (!src) {
338
+ return null;
339
+ }
340
+ const id = imageAttachmentIdPropType.extract(src.id) ?? void 0;
341
+ const url = urlPropTypeUtil.extract(src.url) ?? void 0;
342
+ if (!id && !url) {
343
+ return null;
344
+ }
345
+ const size = stringPropTypeUtil.extract(image.size) ?? void 0;
346
+ return { id, url, size };
347
+ }
348
+
349
+ // src/utils/atomic-background-image-sources.ts
350
+ function walkAtomicBackgroundImageSources(tree, visit) {
351
+ walkElements(tree, (node) => {
352
+ const styles = getElementStyles(node.id);
353
+ if (!styles) {
354
+ return;
355
+ }
356
+ for (const media of extractBackgroundImageMedia(styles)) {
357
+ visit({ node, media });
358
+ }
359
+ });
360
+ }
361
+ function extractBackgroundImageMedia(styles) {
362
+ const sources = [];
363
+ for (const style of Object.values(styles)) {
364
+ for (const variant of style.variants) {
365
+ const background = backgroundPropTypeUtil.extract(variant.props.background);
366
+ const overlays = backgroundOverlayPropTypeUtil.extract(background?.["background-overlay"]) ?? [];
367
+ for (const overlay of overlays) {
368
+ const imageOverlay = backgroundImageOverlayPropTypeUtil.extract(overlay);
369
+ const media = extractAtomicImageMedia(imageOverlay?.image);
370
+ if (media) {
371
+ sources.push(media);
372
+ }
373
+ }
374
+ }
375
+ }
376
+ return sources;
377
+ }
378
+
379
+ // src/utils/background-image-sources.ts
380
+ var BACKGROUND_IMAGE_SETTING_KEYS = [
381
+ "background_image",
382
+ "background_hover_image",
383
+ "background_overlay_image",
384
+ "background_overlay_hover_image",
385
+ "_background_image",
386
+ "_background_hover_image"
387
+ ];
388
+ function walkBackgroundImageSources(tree, visit) {
389
+ walkElements(tree, (node) => {
390
+ for (const key of BACKGROUND_IMAGE_SETTING_KEYS) {
391
+ const media = node.settings[key];
392
+ if (media?.id || media?.url) {
393
+ visit({ node, media });
394
+ }
395
+ }
396
+ });
397
+ }
398
+
299
399
  // src/utils/image-like-sources.ts
300
400
  var IMAGE_LIKE_WIDGETS = /* @__PURE__ */ new Set(["image", "image-box", "image-carousel", "gallery", "image-gallery"]);
301
401
  function hasPageImages(tree) {
@@ -324,28 +424,38 @@ function collectMediaFromNode(node) {
324
424
  const sources = [];
325
425
  const image = node.settings.image;
326
426
  if (image?.id || image?.url) {
327
- sources.push(image);
427
+ sources.push({ ...image, size: node.settings.image_size });
328
428
  }
329
429
  const gallery = node.settings.carousel ?? node.settings.gallery ?? node.settings.wp_gallery;
330
430
  if (Array.isArray(gallery)) {
431
+ const gallerySize = node.settings.thumbnail_size;
331
432
  for (const item of gallery) {
332
433
  if (item?.id || item?.url) {
333
- sources.push(item);
434
+ sources.push({ ...item, size: gallerySize });
334
435
  }
335
436
  }
336
437
  }
337
438
  return sources;
338
439
  }
339
440
 
441
+ // src/utils/image-size-key.ts
442
+ function buildImageSizeKey({ id, size }) {
443
+ return `${id}:${size || "full"}`;
444
+ }
445
+
340
446
  // src/utils/page-attachments.ts
341
- function extractAttachmentIds(tree) {
342
- const ids = /* @__PURE__ */ new Set();
343
- walkImageLikeSources(tree, ({ media }) => {
447
+ function extractImageSizeRequests(tree) {
448
+ const keys = /* @__PURE__ */ new Set();
449
+ const collect = (media) => {
344
450
  if (media.id) {
345
- ids.add(media.id);
451
+ keys.add(buildImageSizeKey({ id: media.id, size: media.size }));
346
452
  }
347
- });
348
- return Array.from(ids).sort((a, b) => a - b);
453
+ };
454
+ walkImageLikeSources(tree, ({ media }) => collect(media));
455
+ walkBackgroundImageSources(tree, ({ media }) => collect(media));
456
+ walkAtomicImageSources(tree, ({ media }) => collect(media));
457
+ walkAtomicBackgroundImageSources(tree, ({ media }) => collect(media));
458
+ return Array.from(keys).sort();
349
459
  }
350
460
 
351
461
  // src/utils/read-kit-snapshot.ts
@@ -440,8 +550,8 @@ function toSnapshot(element) {
440
550
  // src/runner.ts
441
551
  async function runPageAudit(documentId) {
442
552
  const tree = buildSnapshotTree(getElements());
443
- const attachmentIds = extractAttachmentIds(tree);
444
- const pageContext = await fetchPageContext(documentId, attachmentIds);
553
+ const imageSizeRequests = extractImageSizeRequests(tree);
554
+ const pageContext = await fetchPageContext(documentId, imageSizeRequests);
445
555
  const elements = { documentId, tree };
446
556
  const kit = await readKitSnapshot(pageContext.kit_id);
447
557
  const ctx = { documentId, elements, pageContext, kit };
@@ -2361,7 +2471,8 @@ function hasMeaningfulAlt(media, pageContext) {
2361
2471
  return true;
2362
2472
  }
2363
2473
  if (media.id) {
2364
- const alt = pageContext.image_sizes[media.id]?.alt ?? "";
2474
+ const key = buildImageSizeKey({ id: media.id, size: media.size });
2475
+ const alt = pageContext.image_sizes[key]?.alt ?? "";
2365
2476
  return alt.trim().length > 0;
2366
2477
  }
2367
2478
  return (media.alt ?? "").trim().length > 0;
@@ -2419,17 +2530,18 @@ var audit10 = {
2419
2530
  severity: "warning",
2420
2531
  weight: 7,
2421
2532
  evaluate: (ctx) => {
2422
- if (!hasPageImages(ctx.elements.tree)) {
2423
- return { status: "skipped", reason: __34("No images", "elementor") };
2424
- }
2425
2533
  const widgetMaxKb = /* @__PURE__ */ new Map();
2426
2534
  let oversizedImageCount = 0;
2427
- walkImageLikeSources(ctx.elements.tree, ({ node, media }) => {
2535
+ let hasAnyImage = false;
2536
+ const evaluateSource = (node, media) => {
2537
+ if (media.id || media.url) {
2538
+ hasAnyImage = true;
2539
+ }
2428
2540
  const id = media.id;
2429
2541
  if (!id) {
2430
2542
  return;
2431
2543
  }
2432
- const size = ctx.pageContext.image_sizes[id];
2544
+ const size = ctx.pageContext.image_sizes[buildImageSizeKey({ id, size: media.size })];
2433
2545
  if (!size || size.filesize_bytes <= SIZE_THRESHOLD_BYTES) {
2434
2546
  return;
2435
2547
  }
@@ -2437,7 +2549,14 @@ var audit10 = {
2437
2549
  const kb = Math.round(size.filesize_bytes / BYTES_PER_KB);
2438
2550
  const currentMax = widgetMaxKb.get(node.id) ?? 0;
2439
2551
  widgetMaxKb.set(node.id, Math.max(currentMax, kb));
2440
- });
2552
+ };
2553
+ walkImageLikeSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2554
+ walkBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2555
+ walkAtomicImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2556
+ walkAtomicBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2557
+ if (!hasAnyImage) {
2558
+ return { status: "skipped", reason: __34("No images", "elementor") };
2559
+ }
2441
2560
  const violations = Array.from(widgetMaxKb.entries()).map(([elementId, kb]) => ({
2442
2561
  auditId: audit10.id,
2443
2562
  elementId,