@elementor/editor-audits 4.4.0-1129 → 4.4.0-1131

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.js CHANGED
@@ -246,16 +246,16 @@ async function requestPageContext(documentId, imageSizeRequests, allowNonceRetry
246
246
 
247
247
  // src/registry.ts
248
248
  var registry = /* @__PURE__ */ new Map();
249
- function registerAudit(audit26) {
250
- registry.set(audit26.id, audit26);
249
+ function registerAudit(audit25) {
250
+ registry.set(audit25.id, audit25);
251
251
  }
252
252
  function getRegisteredAudits() {
253
253
  return Array.from(registry.values());
254
254
  }
255
255
 
256
256
  // src/utils/is-scored-audit.ts
257
- function isScoredAudit(audit26) {
258
- return audit26.weight > 0;
257
+ function isScoredAudit(audit25) {
258
+ return audit25.weight > 0;
259
259
  }
260
260
 
261
261
  // src/utils/sort-failed-audits.ts
@@ -316,16 +316,16 @@ function computeReport(documentId, results) {
316
316
  const accumulators = Object.fromEntries(
317
317
  ALL_CATEGORIES.map((c) => [c, { totalWeight: 0, passedWeight: 0, total: 0, failed: 0 }])
318
318
  );
319
- for (const { audit: audit26, result } of results) {
319
+ for (const { audit: audit25, result } of results) {
320
320
  if (result.status === "skipped") {
321
321
  continue;
322
322
  }
323
- for (const category of audit26.categories) {
323
+ for (const category of audit25.categories) {
324
324
  const acc = accumulators[category];
325
325
  acc.total++;
326
- acc.totalWeight += audit26.weight;
326
+ acc.totalWeight += audit25.weight;
327
327
  if (result.status === "pass") {
328
- acc.passedWeight += audit26.weight;
328
+ acc.passedWeight += audit25.weight;
329
329
  } else {
330
330
  acc.failed++;
331
331
  }
@@ -392,13 +392,14 @@ function recurse(nodes, parents, visit) {
392
392
  }
393
393
 
394
394
  // src/utils/atomic-image-sources.ts
395
- var ATOMIC_IMAGE_PROP_KEYS = ["image", "poster"];
396
- function walkAtomicImageSources(tree, visit) {
395
+ var ATOMIC_CONTENT_IMAGE_PROP_KEYS = ["image"];
396
+ var ATOMIC_IMAGE_PROP_KEYS = [...ATOMIC_CONTENT_IMAGE_PROP_KEYS, "poster"];
397
+ function walkAtomicImageSources(tree, visit, propKeys = ATOMIC_IMAGE_PROP_KEYS) {
397
398
  walkElements(tree, (node) => {
398
399
  if (node.elType !== "widget") {
399
400
  return;
400
401
  }
401
- for (const key of ATOMIC_IMAGE_PROP_KEYS) {
402
+ for (const key of propKeys) {
402
403
  const media = extractAtomicImageMedia(node.settings[key]);
403
404
  if (media) {
404
405
  visit({ node, media });
@@ -420,8 +421,9 @@ function extractAtomicImageMedia(imageProp) {
420
421
  if (!id && !url) {
421
422
  return null;
422
423
  }
424
+ const alt = import_editor_props.stringPropTypeUtil.extract(src.alt) ?? void 0;
423
425
  const size = import_editor_props.stringPropTypeUtil.extract(image.size) ?? void 0;
424
- return { id, url, size };
426
+ return { id, url, alt, size };
425
427
  }
426
428
 
427
429
  // src/utils/atomic-background-image-sources.ts
@@ -476,15 +478,6 @@ function walkBackgroundImageSources(tree, visit) {
476
478
 
477
479
  // src/utils/image-like-sources.ts
478
480
  var IMAGE_LIKE_WIDGETS = /* @__PURE__ */ new Set(["image", "image-box", "image-carousel", "gallery", "image-gallery"]);
479
- function hasPageImages(tree) {
480
- let found = false;
481
- walkImageLikeSources(tree, ({ media }) => {
482
- if (media.id || media.url) {
483
- found = true;
484
- }
485
- });
486
- return found;
487
- }
488
481
  function walkImageLikeSources(tree, visit) {
489
482
  walkElements(tree, (node) => {
490
483
  if (node.elType !== "widget") {
@@ -516,6 +509,14 @@ function collectMediaFromNode(node) {
516
509
  return sources;
517
510
  }
518
511
 
512
+ // src/utils/all-image-sources.ts
513
+ function walkAllImageSources(tree, visit) {
514
+ walkImageLikeSources(tree, visit);
515
+ walkBackgroundImageSources(tree, visit);
516
+ walkAtomicImageSources(tree, visit);
517
+ walkAtomicBackgroundImageSources(tree, visit);
518
+ }
519
+
519
520
  // src/utils/image-size-key.ts
520
521
  function buildImageSizeKey({ id, size }) {
521
522
  return `${id}:${size || "full"}`;
@@ -524,15 +525,11 @@ function buildImageSizeKey({ id, size }) {
524
525
  // src/utils/page-attachments.ts
525
526
  function extractImageSizeRequests(tree) {
526
527
  const keys = /* @__PURE__ */ new Set();
527
- const collect = (media) => {
528
+ walkAllImageSources(tree, ({ media }) => {
528
529
  if (media.id) {
529
530
  keys.add(buildImageSizeKey({ id: media.id, size: media.size }));
530
531
  }
531
- };
532
- walkImageLikeSources(tree, ({ media }) => collect(media));
533
- walkBackgroundImageSources(tree, ({ media }) => collect(media));
534
- walkAtomicImageSources(tree, ({ media }) => collect(media));
535
- walkAtomicBackgroundImageSources(tree, ({ media }) => collect(media));
532
+ });
536
533
  return Array.from(keys).sort();
537
534
  }
538
535
 
@@ -641,10 +638,10 @@ async function runPageAudit(documentId) {
641
638
  const ctx = { documentId, elements, pageContext, kit, renderedHtml };
642
639
  const registered = getRegisteredAudits();
643
640
  const auditResults = await Promise.all(
644
- registered.map(async (audit26) => {
645
- const { evaluate: _evaluate, ...meta } = audit26;
641
+ registered.map(async (audit25) => {
642
+ const { evaluate: _evaluate, ...meta } = audit25;
646
643
  try {
647
- const result = await audit26.evaluate(ctx);
644
+ const result = await audit25.evaluate(ctx);
648
645
  return { audit: meta, result };
649
646
  } catch (error) {
650
647
  const reason = error instanceof Error ? error.message : "unknown-error";
@@ -1125,9 +1122,9 @@ function ViolationIcon({ violation, widgetIcon }) {
1125
1122
  function SkipReasonTooltip({ reason }) {
1126
1123
  return /* @__PURE__ */ React12.createElement(import_ui11.Tooltip, { title: reason, placement: "top" }, /* @__PURE__ */ React12.createElement(import_ui11.Box, { "aria-label": reason, component: "span", sx: { display: "inline-flex", alignItems: "center" } }, /* @__PURE__ */ React12.createElement(import_icons10.HelpIcon, { fontSize: "small", color: "action" })));
1127
1124
  }
1128
- function StatusIndicator({ audit: audit26, violations }) {
1125
+ function StatusIndicator({ audit: audit25, violations }) {
1129
1126
  if (violations) {
1130
- return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(SeverityIcon, { severity: audit26.severity }), isScoredAudit(audit26) && /* @__PURE__ */ React12.createElement(import_ui11.Typography, { variant: "caption", color: "text.secondary", fontWeight: "bold" }, violations.length));
1127
+ return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(SeverityIcon, { severity: audit25.severity }), isScoredAudit(audit25) && /* @__PURE__ */ React12.createElement(import_ui11.Typography, { variant: "caption", color: "text.secondary", fontWeight: "bold" }, violations.length));
1131
1128
  }
1132
1129
  return /* @__PURE__ */ React12.createElement(import_icons10.CheckIcon, { fontSize: "small", color: "success" });
1133
1130
  }
@@ -1169,7 +1166,7 @@ function getSharedAngiePrompt(violations) {
1169
1166
  );
1170
1167
  return allShareTheSameFix ? first.angiePrompt : void 0;
1171
1168
  }
1172
- function ViolationRow({ audit: audit26, expanded, onToggleExpand, skipReason, violations }) {
1169
+ function ViolationRow({ audit: audit25, expanded, onToggleExpand, skipReason, violations }) {
1173
1170
  const primaryViolation = violations?.[0];
1174
1171
  const isGuidanceFocusable = !!primaryViolation;
1175
1172
  const panelZIndex = (0, import_editor_floating_panels2.useFloatingPanelZIndex)(AUDIT_PANEL_ID);
@@ -1192,8 +1189,8 @@ function ViolationRow({ audit: audit26, expanded, onToggleExpand, skipReason, vi
1192
1189
  },
1193
1190
  onClick: onToggleExpand
1194
1191
  },
1195
- /* @__PURE__ */ React12.createElement(import_ui11.Typography, { variant: "subtitle2", color: "text.secondary", sx: { flex: 1 } }, audit26.title),
1196
- !skipReason && /* @__PURE__ */ React12.createElement(StatusIndicator, { audit: audit26, violations })
1192
+ /* @__PURE__ */ React12.createElement(import_ui11.Typography, { variant: "subtitle2", color: "text.secondary", sx: { flex: 1 } }, audit25.title),
1193
+ !skipReason && /* @__PURE__ */ React12.createElement(StatusIndicator, { audit: audit25, violations })
1197
1194
  ), skipReason && /* @__PURE__ */ React12.createElement(SkipReasonTooltip, { reason: skipReason }), /* @__PURE__ */ React12.createElement(
1198
1195
  import_ui11.IconButton,
1199
1196
  {
@@ -1211,7 +1208,7 @@ function ViolationRow({ audit: audit26, expanded, onToggleExpand, skipReason, vi
1211
1208
  }
1212
1209
  }
1213
1210
  )
1214
- )), /* @__PURE__ */ React12.createElement(import_ui11.Collapse, { in: expanded }, /* @__PURE__ */ React12.createElement(import_ui11.Box, { paddingBlock: 1 }, /* @__PURE__ */ React12.createElement(import_ui11.Tooltip, { title: audit26.fixHint, placement: "top" }, /* @__PURE__ */ React12.createElement(
1211
+ )), /* @__PURE__ */ React12.createElement(import_ui11.Collapse, { in: expanded }, /* @__PURE__ */ React12.createElement(import_ui11.Box, { paddingBlock: 1 }, /* @__PURE__ */ React12.createElement(import_ui11.Tooltip, { title: audit25.fixHint, placement: "top" }, /* @__PURE__ */ React12.createElement(
1215
1212
  import_ui11.Alert,
1216
1213
  {
1217
1214
  severity: "secondary",
@@ -1222,7 +1219,7 @@ function ViolationRow({ audit: audit26, expanded, onToggleExpand, skipReason, vi
1222
1219
  onClick: isGuidanceFocusable ? handleGuidanceClick : void 0,
1223
1220
  onKeyDown: isGuidanceFocusable ? onKeyboardClick(handleGuidanceClick) : void 0
1224
1221
  },
1225
- /* @__PURE__ */ React12.createElement(import_ui11.Typography, { variant: "caption", component: "p", color: "text.secondary" }, audit26.description),
1222
+ /* @__PURE__ */ React12.createElement(import_ui11.Typography, { variant: "caption", component: "p", color: "text.secondary" }, audit25.description),
1226
1223
  primaryViolation && /* @__PURE__ */ React12.createElement(
1227
1224
  GuidanceAction,
1228
1225
  {
@@ -1340,17 +1337,17 @@ var import_i18n12 = require("@wordpress/i18n");
1340
1337
  var ALL_SEVERITIES = ["error", "warning", "info"];
1341
1338
  function countSeverities(report, category) {
1342
1339
  const counts = { error: 0, warning: 0, info: 0 };
1343
- for (const { audit: audit26, result } of report.auditResults) {
1340
+ for (const { audit: audit25, result } of report.auditResults) {
1344
1341
  if (result.status !== "fail") {
1345
1342
  continue;
1346
1343
  }
1347
- if (category && !audit26.categories.includes(category)) {
1344
+ if (category && !audit25.categories.includes(category)) {
1348
1345
  continue;
1349
1346
  }
1350
- if (!isScoredAudit(audit26)) {
1347
+ if (!isScoredAudit(audit25)) {
1351
1348
  continue;
1352
1349
  }
1353
- counts[audit26.severity] += result.violations.length;
1350
+ counts[audit25.severity] += result.violations.length;
1354
1351
  }
1355
1352
  return counts;
1356
1353
  }
@@ -1556,7 +1553,7 @@ function SeverityCard({ severity, count }) {
1556
1553
  flex: 1,
1557
1554
  flexDirection: "column",
1558
1555
  gap: 1,
1559
- bgcolor: "grey.50",
1556
+ bgcolor: "action.hover",
1560
1557
  borderRadius: 1.5,
1561
1558
  px: 1.5,
1562
1559
  py: 1
@@ -2293,6 +2290,21 @@ var audit10 = {
2293
2290
  // src/audits/images-alt-text.ts
2294
2291
  var import_i18n29 = require("@wordpress/i18n");
2295
2292
 
2293
+ // src/utils/alt-text-image-sources.ts
2294
+ function walkAltTextImageSources(tree, visit) {
2295
+ walkImageLikeSources(tree, visit);
2296
+ walkAtomicImageSources(tree, visit, ATOMIC_CONTENT_IMAGE_PROP_KEYS);
2297
+ }
2298
+ function hasAltTextImages(tree) {
2299
+ let found = false;
2300
+ walkAltTextImageSources(tree, ({ media }) => {
2301
+ if (media.id || media.url) {
2302
+ found = true;
2303
+ }
2304
+ });
2305
+ return found;
2306
+ }
2307
+
2296
2308
  // src/utils/image-alt.ts
2297
2309
  function hasMeaningfulAlt(media, pageContext) {
2298
2310
  if (!media.id && !media.url) {
@@ -2319,14 +2331,14 @@ var audit11 = {
2319
2331
  severity: "error",
2320
2332
  weight: 10,
2321
2333
  evaluate: (ctx) => {
2322
- if (!hasPageImages(ctx.elements.tree)) {
2334
+ if (!hasAltTextImages(ctx.elements.tree)) {
2323
2335
  return { status: "skipped", reason: (0, import_i18n29.__)("No images", "elementor") };
2324
2336
  }
2325
2337
  const isReady = ctx.pageContext.ally_plugin_active;
2326
2338
  const violations = [];
2327
2339
  const failedWidgetIds = /* @__PURE__ */ new Set();
2328
2340
  let missingAltImageCount = 0;
2329
- walkImageLikeSources(ctx.elements.tree, ({ node, media }) => {
2341
+ walkAltTextImageSources(ctx.elements.tree, ({ node, media }) => {
2330
2342
  if (!isImageSourcePresent(media) || hasMeaningfulAlt(media, ctx.pageContext)) {
2331
2343
  return;
2332
2344
  }
@@ -2378,10 +2390,7 @@ var audit12 = {
2378
2390
  inefficientImageFormatCount++;
2379
2391
  offendingElementIds.add(node.id);
2380
2392
  };
2381
- walkImageLikeSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2382
- walkBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2383
- walkAtomicImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2384
- walkAtomicBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2393
+ walkAllImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2385
2394
  if (!hasAnyImage) {
2386
2395
  return { status: "skipped", reason: (0, import_i18n30.__)("No images", "elementor") };
2387
2396
  }
@@ -2431,10 +2440,7 @@ var audit13 = {
2431
2440
  const currentMax = widgetMaxKb.get(node.id) ?? 0;
2432
2441
  widgetMaxKb.set(node.id, Math.max(currentMax, kb));
2433
2442
  };
2434
- walkImageLikeSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2435
- walkBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2436
- walkAtomicImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2437
- walkAtomicBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2443
+ walkAllImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
2438
2444
  if (!hasAnyImage) {
2439
2445
  return { status: "skipped", reason: (0, import_i18n31.__)("No images", "elementor") };
2440
2446
  }
@@ -2982,50 +2988,6 @@ var audit24 = {
2982
2988
  }
2983
2989
  };
2984
2990
 
2985
- // src/audits/too-many-widgets.ts
2986
- var import_editor_elements9 = require("@elementor/editor-elements");
2987
- var import_i18n43 = require("@wordpress/i18n");
2988
- var WIDGET_COUNT_THRESHOLD = 100;
2989
- function isCountableWidget(node, widgetsCache) {
2990
- if (node.elType === "widget") {
2991
- return true;
2992
- }
2993
- return !!widgetsCache?.[node.elType]?.meta?.is_compound;
2994
- }
2995
- var audit25 = {
2996
- id: "audits/too-many-widgets",
2997
- title: (0, import_i18n43.__)("Too many widgets", "elementor"),
2998
- description: (0, import_i18n43.__)("Excessive DOM size caused by too many widgets degrades rendering performance.", "elementor"),
2999
- fixHint: (0, import_i18n43.__)("Reduce the number of widgets on the page by removing or combining elements.", "elementor"),
3000
- categories: ["best-practices", "performance"],
3001
- severity: "warning",
3002
- weight: 5,
3003
- evaluate: (ctx) => {
3004
- if (ctx.elements.tree.length === 0) {
3005
- return { status: "skipped", reason: (0, import_i18n43.__)("No elements", "elementor") };
3006
- }
3007
- const widgetsCache = (0, import_editor_elements9.getWidgetsCache)();
3008
- let widgetCount = 0;
3009
- walkElements(ctx.elements.tree, (node) => {
3010
- if (isCountableWidget(node, widgetsCache)) {
3011
- widgetCount++;
3012
- }
3013
- });
3014
- if (widgetCount <= WIDGET_COUNT_THRESHOLD) {
3015
- return { status: "pass" };
3016
- }
3017
- return {
3018
- status: "fail",
3019
- violations: [
3020
- {
3021
- auditId: audit25.id,
3022
- label: (0, import_i18n43.__)("Page has too many widgets.", "elementor")
3023
- }
3024
- ]
3025
- };
3026
- }
3027
- };
3028
-
3029
2991
  // src/register-audits.ts
3030
2992
  var AUDITS = [
3031
2993
  audit17,
@@ -3033,7 +2995,6 @@ var AUDITS = [
3033
2995
  audit16,
3034
2996
  audit10,
3035
2997
  audit7,
3036
- audit25,
3037
2998
  audit23,
3038
2999
  audit5,
3039
3000
  audit14,
@@ -3055,8 +3016,8 @@ var AUDITS = [
3055
3016
  audit8
3056
3017
  ];
3057
3018
  function registerAllAudits() {
3058
- for (const audit26 of AUDITS) {
3059
- registerAudit(audit26);
3019
+ for (const audit25 of AUDITS) {
3020
+ registerAudit(audit25);
3060
3021
  }
3061
3022
  }
3062
3023