@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.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +149 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +141 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -13
- package/src/api/page-context-client.ts +8 -5
- package/src/audits/images-too-large.ts +23 -9
- package/src/runner.ts +3 -3
- package/src/types.ts +2 -1
- package/src/utils/atomic-background-image-sources.ts +56 -0
- package/src/utils/atomic-image-sources.ts +62 -0
- package/src/utils/background-image-sources.ts +32 -0
- package/src/utils/image-alt.ts +3 -1
- package/src/utils/image-like-sources.ts +5 -2
- package/src/utils/image-size-key.ts +8 -0
- package/src/utils/page-attachments.ts +16 -7
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,
|
|
81
|
-
return requestPageContext(documentId,
|
|
80
|
+
async function fetchPageContext(documentId, imageSizeRequests) {
|
|
81
|
+
return requestPageContext(documentId, imageSizeRequests, true);
|
|
82
82
|
}
|
|
83
|
-
async function requestPageContext(documentId,
|
|
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
|
-
|
|
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,
|
|
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
|
|
342
|
-
const
|
|
343
|
-
|
|
447
|
+
function extractImageSizeRequests(tree) {
|
|
448
|
+
const keys = /* @__PURE__ */ new Set();
|
|
449
|
+
const collect = (media) => {
|
|
344
450
|
if (media.id) {
|
|
345
|
-
|
|
451
|
+
keys.add(buildImageSizeKey({ id: media.id, size: media.size }));
|
|
346
452
|
}
|
|
347
|
-
}
|
|
348
|
-
|
|
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
|
|
444
|
-
const pageContext = await fetchPageContext(documentId,
|
|
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
|
|
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
|
-
|
|
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,
|