@elementor/editor-audits 4.4.0-1105 → 4.4.0-1107
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 +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +491 -294
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +480 -273
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -13
- package/src/api/page-context-client.ts +8 -5
- package/src/audits/accessibility-statement.ts +39 -0
- package/src/audits/accessibility-widget.ts +41 -0
- package/src/audits/google-consent-mode.ts +4 -7
- package/src/audits/images-too-large.ts +23 -9
- package/src/components/violation-cta-button.tsx +3 -2
- package/src/components/violation-row.tsx +13 -4
- package/src/register-audits.ts +4 -0
- package/src/runner.ts +9 -5
- package/src/types.ts +8 -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/src/utils/scan-accessibility-widgets.ts +7 -0
package/dist/index.js
CHANGED
|
@@ -52,18 +52,18 @@ var import_editor_floating_panels2 = require("@elementor/editor-floating-panels"
|
|
|
52
52
|
|
|
53
53
|
// src/components/audit-panel.tsx
|
|
54
54
|
var React25 = __toESM(require("react"));
|
|
55
|
-
var
|
|
55
|
+
var import_editor_elements6 = require("@elementor/editor-elements");
|
|
56
56
|
var import_editor_floating_panels = require("@elementor/editor-floating-panels");
|
|
57
57
|
var import_ui24 = require("@elementor/ui");
|
|
58
58
|
var import_i18n23 = require("@wordpress/i18n");
|
|
59
59
|
|
|
60
60
|
// src/hooks/use-audit-report.ts
|
|
61
61
|
var import_react = require("react");
|
|
62
|
-
var
|
|
62
|
+
var import_editor_elements3 = require("@elementor/editor-elements");
|
|
63
63
|
var import_store2 = require("@elementor/store");
|
|
64
64
|
|
|
65
65
|
// src/runner.ts
|
|
66
|
-
var
|
|
66
|
+
var import_editor_elements2 = require("@elementor/editor-elements");
|
|
67
67
|
|
|
68
68
|
// src/api/page-context-client.ts
|
|
69
69
|
var import_http_client = require("@elementor/http-client");
|
|
@@ -115,17 +115,17 @@ async function requestFreshNonce() {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
// src/api/page-context-client.ts
|
|
118
|
-
async function fetchPageContext(documentId,
|
|
119
|
-
return requestPageContext(documentId,
|
|
118
|
+
async function fetchPageContext(documentId, imageSizeRequests) {
|
|
119
|
+
return requestPageContext(documentId, imageSizeRequests, true);
|
|
120
120
|
}
|
|
121
|
-
async function requestPageContext(documentId,
|
|
121
|
+
async function requestPageContext(documentId, imageSizeRequests, allowNonceRetry) {
|
|
122
122
|
const { restNamespace, nonce } = getWindowConfig();
|
|
123
123
|
const url = `${restNamespace}/audits/page-context`;
|
|
124
124
|
try {
|
|
125
125
|
const response = await (0, import_http_client.httpService)().get(url, {
|
|
126
126
|
params: {
|
|
127
127
|
document_id: documentId,
|
|
128
|
-
|
|
128
|
+
image_size_requests: imageSizeRequests
|
|
129
129
|
},
|
|
130
130
|
headers: { "X-WP-Nonce": nonce }
|
|
131
131
|
});
|
|
@@ -135,14 +135,14 @@ async function requestPageContext(documentId, attachmentIds, allowNonceRetry) {
|
|
|
135
135
|
throw error;
|
|
136
136
|
}
|
|
137
137
|
await refreshAuditsNonce();
|
|
138
|
-
return requestPageContext(documentId,
|
|
138
|
+
return requestPageContext(documentId, imageSizeRequests, false);
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// src/registry.ts
|
|
143
143
|
var registry = /* @__PURE__ */ new Map();
|
|
144
|
-
function registerAudit(
|
|
145
|
-
registry.set(
|
|
144
|
+
function registerAudit(audit25) {
|
|
145
|
+
registry.set(audit25.id, audit25);
|
|
146
146
|
}
|
|
147
147
|
function getRegisteredAudits() {
|
|
148
148
|
return Array.from(registry.values());
|
|
@@ -179,8 +179,8 @@ var CATEGORY_LABELS = {
|
|
|
179
179
|
var import_i18n2 = require("@wordpress/i18n");
|
|
180
180
|
|
|
181
181
|
// src/utils/is-scored-audit.ts
|
|
182
|
-
function isScoredAudit(
|
|
183
|
-
return
|
|
182
|
+
function isScoredAudit(audit25) {
|
|
183
|
+
return audit25.weight > 0;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
// src/utils/sort-failed-audits.ts
|
|
@@ -236,8 +236,8 @@ function auditStatusDisplayCounts(report) {
|
|
|
236
236
|
let pass = 0;
|
|
237
237
|
let skipped = 0;
|
|
238
238
|
let totalViolations = 0;
|
|
239
|
-
for (const { audit:
|
|
240
|
-
if (!isScoredAudit(
|
|
239
|
+
for (const { audit: audit25, result } of report.auditResults) {
|
|
240
|
+
if (!isScoredAudit(audit25)) {
|
|
241
241
|
continue;
|
|
242
242
|
}
|
|
243
243
|
switch (result.status) {
|
|
@@ -287,16 +287,16 @@ function computeReport(documentId, results) {
|
|
|
287
287
|
const accumulators = Object.fromEntries(
|
|
288
288
|
ALL_CATEGORIES.map((c) => [c, { totalWeight: 0, passedWeight: 0, total: 0, failed: 0 }])
|
|
289
289
|
);
|
|
290
|
-
for (const { audit:
|
|
290
|
+
for (const { audit: audit25, result } of results) {
|
|
291
291
|
if (result.status === "skipped") {
|
|
292
292
|
continue;
|
|
293
293
|
}
|
|
294
|
-
for (const category of
|
|
294
|
+
for (const category of audit25.categories) {
|
|
295
295
|
const acc = accumulators[category];
|
|
296
296
|
acc.total++;
|
|
297
|
-
acc.totalWeight +=
|
|
297
|
+
acc.totalWeight += audit25.weight;
|
|
298
298
|
if (result.status === "pass") {
|
|
299
|
-
acc.passedWeight +=
|
|
299
|
+
acc.passedWeight += audit25.weight;
|
|
300
300
|
} else {
|
|
301
301
|
acc.failed++;
|
|
302
302
|
}
|
|
@@ -320,6 +320,34 @@ function computeReport(documentId, results) {
|
|
|
320
320
|
};
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
// src/utils/fetch-rendered-html.ts
|
|
324
|
+
var FETCH_TIMEOUT_MS = 1e4;
|
|
325
|
+
async function fetchRenderedHtml(url) {
|
|
326
|
+
if (!url) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
const timeoutController = new AbortController();
|
|
330
|
+
const timeoutId = setTimeout(() => timeoutController.abort(), FETCH_TIMEOUT_MS);
|
|
331
|
+
try {
|
|
332
|
+
const response = await fetch(url, { credentials: "omit", signal: timeoutController.signal });
|
|
333
|
+
if (!response.ok) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
return await response.text();
|
|
337
|
+
} catch {
|
|
338
|
+
return null;
|
|
339
|
+
} finally {
|
|
340
|
+
clearTimeout(timeoutId);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/utils/atomic-background-image-sources.ts
|
|
345
|
+
var import_editor_elements = require("@elementor/editor-elements");
|
|
346
|
+
var import_editor_props2 = require("@elementor/editor-props");
|
|
347
|
+
|
|
348
|
+
// src/utils/atomic-image-sources.ts
|
|
349
|
+
var import_editor_props = require("@elementor/editor-props");
|
|
350
|
+
|
|
323
351
|
// src/utils/walk.ts
|
|
324
352
|
function walkElements(tree, visit) {
|
|
325
353
|
const parents = [];
|
|
@@ -334,6 +362,89 @@ function recurse(nodes, parents, visit) {
|
|
|
334
362
|
}
|
|
335
363
|
}
|
|
336
364
|
|
|
365
|
+
// src/utils/atomic-image-sources.ts
|
|
366
|
+
var ATOMIC_IMAGE_PROP_KEYS = ["image", "poster"];
|
|
367
|
+
function walkAtomicImageSources(tree, visit) {
|
|
368
|
+
walkElements(tree, (node) => {
|
|
369
|
+
if (node.elType !== "widget") {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
for (const key of ATOMIC_IMAGE_PROP_KEYS) {
|
|
373
|
+
const media = extractAtomicImageMedia(node.settings[key]);
|
|
374
|
+
if (media) {
|
|
375
|
+
visit({ node, media });
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
function extractAtomicImageMedia(imageProp) {
|
|
381
|
+
const image = import_editor_props.imagePropTypeUtil.extract(imageProp);
|
|
382
|
+
if (!image) {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
const src = import_editor_props.imageSrcPropTypeUtil.extract(image.src);
|
|
386
|
+
if (!src) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
const id = import_editor_props.imageAttachmentIdPropType.extract(src.id) ?? void 0;
|
|
390
|
+
const url = import_editor_props.urlPropTypeUtil.extract(src.url) ?? void 0;
|
|
391
|
+
if (!id && !url) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
const size = import_editor_props.stringPropTypeUtil.extract(image.size) ?? void 0;
|
|
395
|
+
return { id, url, size };
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/utils/atomic-background-image-sources.ts
|
|
399
|
+
function walkAtomicBackgroundImageSources(tree, visit) {
|
|
400
|
+
walkElements(tree, (node) => {
|
|
401
|
+
const styles = (0, import_editor_elements.getElementStyles)(node.id);
|
|
402
|
+
if (!styles) {
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
for (const media of extractBackgroundImageMedia(styles)) {
|
|
406
|
+
visit({ node, media });
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
function extractBackgroundImageMedia(styles) {
|
|
411
|
+
const sources = [];
|
|
412
|
+
for (const style of Object.values(styles)) {
|
|
413
|
+
for (const variant of style.variants) {
|
|
414
|
+
const background = import_editor_props2.backgroundPropTypeUtil.extract(variant.props.background);
|
|
415
|
+
const overlays = import_editor_props2.backgroundOverlayPropTypeUtil.extract(background?.["background-overlay"]) ?? [];
|
|
416
|
+
for (const overlay of overlays) {
|
|
417
|
+
const imageOverlay = import_editor_props2.backgroundImageOverlayPropTypeUtil.extract(overlay);
|
|
418
|
+
const media = extractAtomicImageMedia(imageOverlay?.image);
|
|
419
|
+
if (media) {
|
|
420
|
+
sources.push(media);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return sources;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// src/utils/background-image-sources.ts
|
|
429
|
+
var BACKGROUND_IMAGE_SETTING_KEYS = [
|
|
430
|
+
"background_image",
|
|
431
|
+
"background_hover_image",
|
|
432
|
+
"background_overlay_image",
|
|
433
|
+
"background_overlay_hover_image",
|
|
434
|
+
"_background_image",
|
|
435
|
+
"_background_hover_image"
|
|
436
|
+
];
|
|
437
|
+
function walkBackgroundImageSources(tree, visit) {
|
|
438
|
+
walkElements(tree, (node) => {
|
|
439
|
+
for (const key of BACKGROUND_IMAGE_SETTING_KEYS) {
|
|
440
|
+
const media = node.settings[key];
|
|
441
|
+
if (media?.id || media?.url) {
|
|
442
|
+
visit({ node, media });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
337
448
|
// src/utils/image-like-sources.ts
|
|
338
449
|
var IMAGE_LIKE_WIDGETS = /* @__PURE__ */ new Set(["image", "image-box", "image-carousel", "gallery", "image-gallery"]);
|
|
339
450
|
function hasPageImages(tree) {
|
|
@@ -362,28 +473,38 @@ function collectMediaFromNode(node) {
|
|
|
362
473
|
const sources = [];
|
|
363
474
|
const image = node.settings.image;
|
|
364
475
|
if (image?.id || image?.url) {
|
|
365
|
-
sources.push(image);
|
|
476
|
+
sources.push({ ...image, size: node.settings.image_size });
|
|
366
477
|
}
|
|
367
478
|
const gallery = node.settings.carousel ?? node.settings.gallery ?? node.settings.wp_gallery;
|
|
368
479
|
if (Array.isArray(gallery)) {
|
|
480
|
+
const gallerySize = node.settings.thumbnail_size;
|
|
369
481
|
for (const item of gallery) {
|
|
370
482
|
if (item?.id || item?.url) {
|
|
371
|
-
sources.push(item);
|
|
483
|
+
sources.push({ ...item, size: gallerySize });
|
|
372
484
|
}
|
|
373
485
|
}
|
|
374
486
|
}
|
|
375
487
|
return sources;
|
|
376
488
|
}
|
|
377
489
|
|
|
490
|
+
// src/utils/image-size-key.ts
|
|
491
|
+
function buildImageSizeKey({ id, size }) {
|
|
492
|
+
return `${id}:${size || "full"}`;
|
|
493
|
+
}
|
|
494
|
+
|
|
378
495
|
// src/utils/page-attachments.ts
|
|
379
|
-
function
|
|
380
|
-
const
|
|
381
|
-
|
|
496
|
+
function extractImageSizeRequests(tree) {
|
|
497
|
+
const keys = /* @__PURE__ */ new Set();
|
|
498
|
+
const collect = (media) => {
|
|
382
499
|
if (media.id) {
|
|
383
|
-
|
|
500
|
+
keys.add(buildImageSizeKey({ id: media.id, size: media.size }));
|
|
384
501
|
}
|
|
385
|
-
}
|
|
386
|
-
|
|
502
|
+
};
|
|
503
|
+
walkImageLikeSources(tree, ({ media }) => collect(media));
|
|
504
|
+
walkBackgroundImageSources(tree, ({ media }) => collect(media));
|
|
505
|
+
walkAtomicImageSources(tree, ({ media }) => collect(media));
|
|
506
|
+
walkAtomicBackgroundImageSources(tree, ({ media }) => collect(media));
|
|
507
|
+
return Array.from(keys).sort();
|
|
387
508
|
}
|
|
388
509
|
|
|
389
510
|
// src/utils/read-kit-snapshot.ts
|
|
@@ -477,18 +598,21 @@ function toSnapshot(element) {
|
|
|
477
598
|
|
|
478
599
|
// src/runner.ts
|
|
479
600
|
async function runPageAudit(documentId) {
|
|
480
|
-
const tree = buildSnapshotTree((0,
|
|
481
|
-
const
|
|
482
|
-
const pageContext = await fetchPageContext(documentId,
|
|
601
|
+
const tree = buildSnapshotTree((0, import_editor_elements2.getElements)());
|
|
602
|
+
const imageSizeRequests = extractImageSizeRequests(tree);
|
|
603
|
+
const pageContext = await fetchPageContext(documentId, imageSizeRequests);
|
|
483
604
|
const elements = { documentId, tree };
|
|
484
|
-
const kit = await
|
|
485
|
-
|
|
605
|
+
const [kit, renderedHtml] = await Promise.all([
|
|
606
|
+
readKitSnapshot(pageContext.kit_id),
|
|
607
|
+
fetchRenderedHtml(pageContext.frontend_url)
|
|
608
|
+
]);
|
|
609
|
+
const ctx = { documentId, elements, pageContext, kit, renderedHtml };
|
|
486
610
|
const registered = getRegisteredAudits();
|
|
487
611
|
const auditResults = await Promise.all(
|
|
488
|
-
registered.map(async (
|
|
489
|
-
const { evaluate: _evaluate, ...meta } =
|
|
612
|
+
registered.map(async (audit25) => {
|
|
613
|
+
const { evaluate: _evaluate, ...meta } = audit25;
|
|
490
614
|
try {
|
|
491
|
-
const result = await
|
|
615
|
+
const result = await audit25.evaluate(ctx);
|
|
492
616
|
return { audit: meta, result };
|
|
493
617
|
} catch (error) {
|
|
494
618
|
const reason = error instanceof Error ? error.message : "unknown-error";
|
|
@@ -563,7 +687,7 @@ function useAuditReport() {
|
|
|
563
687
|
const report = (0, import_store2.__useSelector)((state) => selectReport(state));
|
|
564
688
|
const error = (0, import_store2.__useSelector)((state) => selectError(state));
|
|
565
689
|
const dispatch = (0, import_store2.__useDispatch)();
|
|
566
|
-
const documentId = (0,
|
|
690
|
+
const documentId = (0, import_editor_elements3.getCurrentDocumentId)() ?? 0;
|
|
567
691
|
(0, import_react.useEffect)(() => {
|
|
568
692
|
if (!documentId || report?.documentId === documentId) {
|
|
569
693
|
return;
|
|
@@ -820,20 +944,20 @@ function SubpageHeader({ title, onBack, backLabel, icon }) {
|
|
|
820
944
|
// src/components/violation-row.tsx
|
|
821
945
|
var React11 = __toESM(require("react"));
|
|
822
946
|
var import_react4 = require("react");
|
|
823
|
-
var
|
|
947
|
+
var import_editor_elements5 = require("@elementor/editor-elements");
|
|
824
948
|
var import_icons7 = require("@elementor/icons");
|
|
825
949
|
var import_ui10 = require("@elementor/ui");
|
|
826
950
|
var import_i18n11 = require("@wordpress/i18n");
|
|
827
951
|
|
|
828
952
|
// src/hooks/focus-violation.ts
|
|
829
|
-
var
|
|
953
|
+
var import_editor_elements4 = require("@elementor/editor-elements");
|
|
830
954
|
var import_editor_v1_adapters2 = require("@elementor/editor-v1-adapters");
|
|
831
955
|
var SCROLL_TO_VIEW_DELAY_MS = 200;
|
|
832
956
|
function focusViolation(violation) {
|
|
833
957
|
if (violation.elementId) {
|
|
834
|
-
const container = (0,
|
|
958
|
+
const container = (0, import_editor_elements4.getContainer)(violation.elementId);
|
|
835
959
|
if (container) {
|
|
836
|
-
(0,
|
|
960
|
+
(0, import_editor_elements4.selectElement)(violation.elementId);
|
|
837
961
|
const domElement = container.view?.getDomElement?.();
|
|
838
962
|
if (domElement) {
|
|
839
963
|
window.elementor?.helpers?.scrollToView?.(domElement, SCROLL_TO_VIEW_DELAY_MS);
|
|
@@ -938,13 +1062,13 @@ function SeverityIcon({ severity }) {
|
|
|
938
1062
|
// src/components/violation-cta-button.tsx
|
|
939
1063
|
var React9 = __toESM(require("react"));
|
|
940
1064
|
var import_ui8 = require("@elementor/ui");
|
|
941
|
-
function ViolationCtaButton({ ctaLabel, externalUrl }) {
|
|
1065
|
+
function ViolationCtaButton({ ctaLabel, externalUrl, variant = "outlined" }) {
|
|
942
1066
|
const handleClick = (event) => {
|
|
943
1067
|
event.stopPropagation();
|
|
944
1068
|
event.preventDefault();
|
|
945
1069
|
window.open(externalUrl, "_blank", "noopener");
|
|
946
1070
|
};
|
|
947
|
-
return /* @__PURE__ */ React9.createElement(import_ui8.Button, { variant
|
|
1071
|
+
return /* @__PURE__ */ React9.createElement(import_ui8.Button, { variant, color: "secondary", size: "small", onClick: handleClick }, ctaLabel);
|
|
948
1072
|
}
|
|
949
1073
|
|
|
950
1074
|
// src/components/violation-icons.tsx
|
|
@@ -976,13 +1100,13 @@ function ViolationIcon({ violation, widgetIcon }) {
|
|
|
976
1100
|
function SkipReasonTooltip({ reason }) {
|
|
977
1101
|
return /* @__PURE__ */ React11.createElement(import_ui10.Tooltip, { title: reason, placement: "top" }, /* @__PURE__ */ React11.createElement(import_ui10.Box, { "aria-label": reason, component: "span", sx: { display: "inline-flex", alignItems: "center" } }, /* @__PURE__ */ React11.createElement(import_icons7.HelpIcon, { fontSize: "small", color: "action" })));
|
|
978
1102
|
}
|
|
979
|
-
function StatusIndicator({ audit:
|
|
1103
|
+
function StatusIndicator({ audit: audit25, violations }) {
|
|
980
1104
|
if (violations) {
|
|
981
|
-
return /* @__PURE__ */ React11.createElement(React11.Fragment, null, isScoredAudit(
|
|
1105
|
+
return /* @__PURE__ */ React11.createElement(React11.Fragment, null, isScoredAudit(audit25) && /* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "caption", color: "text.secondary", fontWeight: "bold" }, violations.length), /* @__PURE__ */ React11.createElement(SeverityIcon, { severity: audit25.severity }));
|
|
982
1106
|
}
|
|
983
1107
|
return /* @__PURE__ */ React11.createElement(import_icons7.CheckIcon, { fontSize: "small", color: "success" });
|
|
984
1108
|
}
|
|
985
|
-
function ViolationRow({ audit:
|
|
1109
|
+
function ViolationRow({ audit: audit25, skipReason, violations }) {
|
|
986
1110
|
const [expanded, setExpanded] = (0, import_react4.useState)(false);
|
|
987
1111
|
const toggleExpanded = () => setExpanded((value) => !value);
|
|
988
1112
|
return /* @__PURE__ */ React11.createElement(import_ui10.Box, { sx: { borderBottom: 1, borderColor: "divider", paddingBlock: 0.5 } }, /* @__PURE__ */ React11.createElement(import_ui10.Box, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React11.createElement(
|
|
@@ -998,8 +1122,8 @@ function ViolationRow({ audit: audit23, skipReason, violations }) {
|
|
|
998
1122
|
},
|
|
999
1123
|
onClick: toggleExpanded
|
|
1000
1124
|
},
|
|
1001
|
-
/* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "body2", sx: { flex: 1 } },
|
|
1002
|
-
!skipReason && /* @__PURE__ */ React11.createElement(StatusIndicator, { audit:
|
|
1125
|
+
/* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "body2", sx: { flex: 1 } }, audit25.title),
|
|
1126
|
+
!skipReason && /* @__PURE__ */ React11.createElement(StatusIndicator, { audit: audit25, violations })
|
|
1003
1127
|
), skipReason && /* @__PURE__ */ React11.createElement(SkipReasonTooltip, { reason: skipReason }), /* @__PURE__ */ React11.createElement(
|
|
1004
1128
|
import_ui10.IconButton,
|
|
1005
1129
|
{
|
|
@@ -1025,7 +1149,7 @@ function ViolationRow({ audit: audit23, skipReason, violations }) {
|
|
|
1025
1149
|
icon: /* @__PURE__ */ React11.createElement(import_icons7.AlertCircleIcon, { fontSize: "small", color: "secondary", "aria-hidden": true })
|
|
1026
1150
|
},
|
|
1027
1151
|
/* @__PURE__ */ React11.createElement(import_ui10.AlertTitle, null, /* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "caption", component: "p", color: "text.primary", fontWeight: "bold" }, (0, import_i18n11.__)("What's the issue", "elementor"))),
|
|
1028
|
-
/* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "caption", component: "p", color: "text.secondary" },
|
|
1152
|
+
/* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "caption", component: "p", color: "text.secondary" }, audit25.description)
|
|
1029
1153
|
), /* @__PURE__ */ React11.createElement(
|
|
1030
1154
|
import_ui10.Alert,
|
|
1031
1155
|
{
|
|
@@ -1034,10 +1158,10 @@ function ViolationRow({ audit: audit23, skipReason, violations }) {
|
|
|
1034
1158
|
icon: /* @__PURE__ */ React11.createElement(import_icons7.BulbIcon, { fontSize: "small", color: "info", "aria-hidden": true })
|
|
1035
1159
|
},
|
|
1036
1160
|
/* @__PURE__ */ React11.createElement(import_ui10.AlertTitle, null, /* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "caption", component: "p", color: "text.primary", fontWeight: "bold" }, (0, import_i18n11.__)("How to resolve", "elementor"))),
|
|
1037
|
-
/* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "caption", component: "p", color: "text.secondary" },
|
|
1161
|
+
/* @__PURE__ */ React11.createElement(import_ui10.Typography, { variant: "caption", component: "p", color: "text.secondary" }, audit25.fixHint)
|
|
1038
1162
|
)), violations && violations.length > 0 && /* @__PURE__ */ React11.createElement(import_ui10.Box, { role: "list", sx: { paddingBlockEnd: 1, paddingInlineStart: 2 } }, violations.map((violation, idx) => {
|
|
1039
|
-
const widgetIcon = violation.elementId ? (0,
|
|
1040
|
-
const elementTitle = violation.elementId ? (0,
|
|
1163
|
+
const widgetIcon = violation.elementId ? (0, import_editor_elements5.getElementIcon)(violation.elementId) : null;
|
|
1164
|
+
const elementTitle = violation.elementId ? (0, import_editor_elements5.getElementTitle)(violation.elementId) : null;
|
|
1041
1165
|
const rowLabel = elementTitle ? `${elementTitle} - ${violation.label}` : violation.label;
|
|
1042
1166
|
return /* @__PURE__ */ React11.createElement(
|
|
1043
1167
|
import_ui10.Box,
|
|
@@ -1070,13 +1194,20 @@ function ViolationRow({ audit: audit23, skipReason, violations }) {
|
|
|
1070
1194
|
prompt: violation.angiePrompt ?? buildAngiePrompt(rowLabel)
|
|
1071
1195
|
}
|
|
1072
1196
|
),
|
|
1073
|
-
violation.ctaLabel && violation.externalUrl ? /* @__PURE__ */ React11.createElement(
|
|
1197
|
+
violation.ctaLabel && violation.externalUrl ? /* @__PURE__ */ React11.createElement(import_ui10.Box, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React11.createElement(
|
|
1074
1198
|
ViolationCtaButton,
|
|
1075
1199
|
{
|
|
1076
1200
|
ctaLabel: violation.ctaLabel,
|
|
1077
1201
|
externalUrl: violation.externalUrl
|
|
1078
1202
|
}
|
|
1079
|
-
)
|
|
1203
|
+
), violation.secondaryCtaLabel && violation.secondaryCtaUrl && /* @__PURE__ */ React11.createElement(
|
|
1204
|
+
ViolationCtaButton,
|
|
1205
|
+
{
|
|
1206
|
+
ctaLabel: violation.secondaryCtaLabel,
|
|
1207
|
+
externalUrl: violation.secondaryCtaUrl,
|
|
1208
|
+
variant: "text"
|
|
1209
|
+
}
|
|
1210
|
+
)) : /* @__PURE__ */ React11.createElement(
|
|
1080
1211
|
import_icons7.EyeIcon,
|
|
1081
1212
|
{
|
|
1082
1213
|
className: "violation-hover-icon",
|
|
@@ -1174,17 +1305,17 @@ var import_i18n14 = require("@wordpress/i18n");
|
|
|
1174
1305
|
var ALL_SEVERITIES = ["error", "warning", "info"];
|
|
1175
1306
|
function countSeverities(report, category) {
|
|
1176
1307
|
const counts = { error: 0, warning: 0, info: 0 };
|
|
1177
|
-
for (const { audit:
|
|
1308
|
+
for (const { audit: audit25, result } of report.auditResults) {
|
|
1178
1309
|
if (result.status !== "fail") {
|
|
1179
1310
|
continue;
|
|
1180
1311
|
}
|
|
1181
|
-
if (category && !
|
|
1312
|
+
if (category && !audit25.categories.includes(category)) {
|
|
1182
1313
|
continue;
|
|
1183
1314
|
}
|
|
1184
|
-
if (!isScoredAudit(
|
|
1315
|
+
if (!isScoredAudit(audit25)) {
|
|
1185
1316
|
continue;
|
|
1186
1317
|
}
|
|
1187
|
-
counts[
|
|
1318
|
+
counts[audit25.severity] += result.violations.length;
|
|
1188
1319
|
}
|
|
1189
1320
|
return counts;
|
|
1190
1321
|
}
|
|
@@ -1768,7 +1899,7 @@ function ReportShell({ report }) {
|
|
|
1768
1899
|
// src/components/audit-panel.tsx
|
|
1769
1900
|
function AuditPanel() {
|
|
1770
1901
|
const { status, report, error, run } = useAuditReport();
|
|
1771
|
-
const currentDocumentId = (0,
|
|
1902
|
+
const currentDocumentId = (0, import_editor_elements6.getCurrentDocumentId)() ?? 0;
|
|
1772
1903
|
const onRun = () => run(currentDocumentId);
|
|
1773
1904
|
const lastScanLabel = report ? new Date(report.runAt).toLocaleTimeString() : null;
|
|
1774
1905
|
return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(
|
|
@@ -1868,16 +1999,93 @@ var audit = {
|
|
|
1868
1999
|
}
|
|
1869
2000
|
};
|
|
1870
2001
|
|
|
1871
|
-
// src/audits/
|
|
2002
|
+
// src/audits/accessibility-statement.ts
|
|
1872
2003
|
var import_i18n26 = require("@wordpress/i18n");
|
|
1873
2004
|
var audit2 = {
|
|
1874
|
-
id: "audits/
|
|
1875
|
-
title: (0, import_i18n26.__)("
|
|
2005
|
+
id: "audits/accessibility-statement",
|
|
2006
|
+
title: (0, import_i18n26.__)("Create an accessibility statement", "elementor"),
|
|
1876
2007
|
description: (0, import_i18n26.__)(
|
|
2008
|
+
"An accessibility statement showcases your efforts to create an inclusive online space, highlighting helpful features and a commitment to accessibility.",
|
|
2009
|
+
"elementor"
|
|
2010
|
+
),
|
|
2011
|
+
fixHint: (0, import_i18n26.__)("Use Ally to create and publish an accessibility statement for your site.", "elementor"),
|
|
2012
|
+
categories: ["accessibility"],
|
|
2013
|
+
severity: "info",
|
|
2014
|
+
weight: 1,
|
|
2015
|
+
evaluate: (ctx) => {
|
|
2016
|
+
const isReady = ctx.pageContext.ally_plugin_active;
|
|
2017
|
+
if (isReady && ctx.pageContext.ally_accessibility_statement_created) {
|
|
2018
|
+
return { status: "pass" };
|
|
2019
|
+
}
|
|
2020
|
+
return {
|
|
2021
|
+
status: "fail",
|
|
2022
|
+
violations: [
|
|
2023
|
+
{
|
|
2024
|
+
auditId: audit2.id,
|
|
2025
|
+
label: (0, import_i18n26.__)("No accessibility statement has been created for this site.", "elementor"),
|
|
2026
|
+
externalUrl: isReady ? ctx.pageContext.ally_accessibility_statement_url : ctx.pageContext.ally_plugin_url,
|
|
2027
|
+
ctaLabel: isReady ? (0, import_i18n26.__)("Create", "elementor") : void 0,
|
|
2028
|
+
secondaryCtaLabel: (0, import_i18n26.__)("Learn more", "elementor"),
|
|
2029
|
+
secondaryCtaUrl: "https://go.elementor.com/acc-plg-learn-more"
|
|
2030
|
+
}
|
|
2031
|
+
]
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
};
|
|
2035
|
+
|
|
2036
|
+
// src/audits/accessibility-widget.ts
|
|
2037
|
+
var import_i18n27 = require("@wordpress/i18n");
|
|
2038
|
+
|
|
2039
|
+
// src/utils/scan-accessibility-widgets.ts
|
|
2040
|
+
var ACCESSIBILITY_WIDGET_SCRIPT_SOURCES = ["cdn.elementor.com/a11y/widget.js"];
|
|
2041
|
+
function hasAccessibilityWidgetScript(html) {
|
|
2042
|
+
return ACCESSIBILITY_WIDGET_SCRIPT_SOURCES.some((src) => html.includes(src));
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
// src/audits/accessibility-widget.ts
|
|
2046
|
+
var audit3 = {
|
|
2047
|
+
id: "audits/accessibility-widget",
|
|
2048
|
+
title: (0, import_i18n27.__)("Add an accessibility widget", "elementor"),
|
|
2049
|
+
description: (0, import_i18n27.__)("Make your site more inclusive by adding an accessibility widget.", "elementor"),
|
|
2050
|
+
fixHint: (0, import_i18n27.__)("Activate Ally\u2019s accessibility widget to give visitors on-page accessibility tools.", "elementor"),
|
|
2051
|
+
categories: ["accessibility"],
|
|
2052
|
+
severity: "info",
|
|
2053
|
+
weight: 1,
|
|
2054
|
+
evaluate: (ctx) => {
|
|
2055
|
+
if (!ctx.pageContext.frontend_url) {
|
|
2056
|
+
return { status: "skipped", reason: (0, import_i18n27.__)("Page is not published.", "elementor") };
|
|
2057
|
+
}
|
|
2058
|
+
if (!ctx.renderedHtml) {
|
|
2059
|
+
return { status: "skipped", reason: (0, import_i18n27.__)("Could not fetch the published page.", "elementor") };
|
|
2060
|
+
}
|
|
2061
|
+
if (hasAccessibilityWidgetScript(ctx.renderedHtml)) {
|
|
2062
|
+
return { status: "pass" };
|
|
2063
|
+
}
|
|
2064
|
+
const isReady = ctx.pageContext.ally_plugin_active;
|
|
2065
|
+
return {
|
|
2066
|
+
status: "fail",
|
|
2067
|
+
violations: [
|
|
2068
|
+
{
|
|
2069
|
+
auditId: audit3.id,
|
|
2070
|
+
label: (0, import_i18n27.__)("No accessibility widget is active on this site.", "elementor"),
|
|
2071
|
+
externalUrl: isReady ? ctx.pageContext.ally_widget_settings_url : ctx.pageContext.ally_plugin_url,
|
|
2072
|
+
ctaLabel: (0, import_i18n27.__)("Activate", "elementor")
|
|
2073
|
+
}
|
|
2074
|
+
]
|
|
2075
|
+
};
|
|
2076
|
+
}
|
|
2077
|
+
};
|
|
2078
|
+
|
|
2079
|
+
// src/audits/cookie-policy.ts
|
|
2080
|
+
var import_i18n28 = require("@wordpress/i18n");
|
|
2081
|
+
var audit4 = {
|
|
2082
|
+
id: "audits/cookie-policy",
|
|
2083
|
+
title: (0, import_i18n28.__)("Cookie policy", "elementor"),
|
|
2084
|
+
description: (0, import_i18n28.__)(
|
|
1877
2085
|
"A cookie policy is required by privacy regulations such as GDPR (EU) or CCPA (US) to inform visitors about tracking and data collection.",
|
|
1878
2086
|
"elementor"
|
|
1879
2087
|
),
|
|
1880
|
-
fixHint: (0,
|
|
2088
|
+
fixHint: (0, import_i18n28.__)("Install the Cookiez plugin to add a cookie policy to your website.", "elementor"),
|
|
1881
2089
|
categories: ["compliance"],
|
|
1882
2090
|
severity: "info",
|
|
1883
2091
|
weight: 1,
|
|
@@ -1889,8 +2097,8 @@ var audit2 = {
|
|
|
1889
2097
|
status: "fail",
|
|
1890
2098
|
violations: [
|
|
1891
2099
|
{
|
|
1892
|
-
auditId:
|
|
1893
|
-
label: (0,
|
|
2100
|
+
auditId: audit4.id,
|
|
2101
|
+
label: (0, import_i18n28.__)("Cookiez plugin is not installed or active.", "elementor"),
|
|
1894
2102
|
externalUrl: ctx.pageContext.cookiez_plugin_url
|
|
1895
2103
|
}
|
|
1896
2104
|
]
|
|
@@ -1899,8 +2107,8 @@ var audit2 = {
|
|
|
1899
2107
|
};
|
|
1900
2108
|
|
|
1901
2109
|
// src/audits/deep-nesting.ts
|
|
1902
|
-
var
|
|
1903
|
-
var
|
|
2110
|
+
var import_editor_elements7 = require("@elementor/editor-elements");
|
|
2111
|
+
var import_i18n29 = require("@wordpress/i18n");
|
|
1904
2112
|
var MAX_NESTING_DEPTH = 6;
|
|
1905
2113
|
function isNestingElement(node, widgetsCache) {
|
|
1906
2114
|
if (node.elType === "container") {
|
|
@@ -1908,22 +2116,22 @@ function isNestingElement(node, widgetsCache) {
|
|
|
1908
2116
|
}
|
|
1909
2117
|
return !!widgetsCache?.[node.elType]?.meta?.is_container;
|
|
1910
2118
|
}
|
|
1911
|
-
var
|
|
2119
|
+
var audit5 = {
|
|
1912
2120
|
id: "audits/deep-nesting",
|
|
1913
|
-
title: (0,
|
|
1914
|
-
description: (0,
|
|
2121
|
+
title: (0, import_i18n29.__)("Deep container nesting", "elementor"),
|
|
2122
|
+
description: (0, import_i18n29.__)(
|
|
1915
2123
|
"Container nesting exceeds the recommended depth. Deep DOM trees hurt rendering performance and readability.",
|
|
1916
2124
|
"elementor"
|
|
1917
2125
|
),
|
|
1918
|
-
fixHint: (0,
|
|
2126
|
+
fixHint: (0, import_i18n29.__)("Flatten the layout by removing unnecessary wrapper containers.", "elementor"),
|
|
1919
2127
|
categories: ["performance", "best-practices"],
|
|
1920
2128
|
severity: "warning",
|
|
1921
2129
|
weight: 5,
|
|
1922
2130
|
evaluate: (ctx) => {
|
|
1923
2131
|
if (ctx.elements.tree.length === 0) {
|
|
1924
|
-
return { status: "skipped", reason: (0,
|
|
2132
|
+
return { status: "skipped", reason: (0, import_i18n29.__)("No elements", "elementor") };
|
|
1925
2133
|
}
|
|
1926
|
-
const widgetsCache = (0,
|
|
2134
|
+
const widgetsCache = (0, import_editor_elements7.getWidgetsCache)();
|
|
1927
2135
|
const violations = [];
|
|
1928
2136
|
walkElements(ctx.elements.tree, (node, parents) => {
|
|
1929
2137
|
if (!isNestingElement(node, widgetsCache)) {
|
|
@@ -1932,10 +2140,10 @@ var audit3 = {
|
|
|
1932
2140
|
const depth = parents.filter((parent) => isNestingElement(parent, widgetsCache)).length + 1;
|
|
1933
2141
|
if (depth > MAX_NESTING_DEPTH) {
|
|
1934
2142
|
violations.push({
|
|
1935
|
-
auditId:
|
|
2143
|
+
auditId: audit5.id,
|
|
1936
2144
|
elementId: node.id,
|
|
1937
2145
|
targetHint: "element-settings",
|
|
1938
|
-
label: (0,
|
|
2146
|
+
label: (0, import_i18n29.__)("Container nesting is too deep.", "elementor")
|
|
1939
2147
|
});
|
|
1940
2148
|
}
|
|
1941
2149
|
});
|
|
@@ -1944,15 +2152,15 @@ var audit3 = {
|
|
|
1944
2152
|
};
|
|
1945
2153
|
|
|
1946
2154
|
// src/audits/default-design-system.ts
|
|
1947
|
-
var
|
|
1948
|
-
var
|
|
2155
|
+
var import_i18n30 = require("@wordpress/i18n");
|
|
2156
|
+
var audit6 = {
|
|
1949
2157
|
id: "audits/default-design-system",
|
|
1950
|
-
title: (0,
|
|
1951
|
-
description: (0,
|
|
2158
|
+
title: (0, import_i18n30.__)("Default website kit", "elementor"),
|
|
2159
|
+
description: (0, import_i18n30.__)(
|
|
1952
2160
|
"Your website is using the default design system colors and fonts. Custom branding makes the website feel uniquely yours.",
|
|
1953
2161
|
"elementor"
|
|
1954
2162
|
),
|
|
1955
|
-
fixHint: (0,
|
|
2163
|
+
fixHint: (0, import_i18n30.__)("Open Site Settings and customize your kit (colors, fonts, layout).", "elementor"),
|
|
1956
2164
|
categories: ["best-practices"],
|
|
1957
2165
|
severity: "info",
|
|
1958
2166
|
weight: 1,
|
|
@@ -1964,8 +2172,8 @@ var audit4 = {
|
|
|
1964
2172
|
status: "fail",
|
|
1965
2173
|
violations: [
|
|
1966
2174
|
{
|
|
1967
|
-
auditId:
|
|
1968
|
-
label: (0,
|
|
2175
|
+
auditId: audit6.id,
|
|
2176
|
+
label: (0, import_i18n30.__)("Kit appears unchanged from default.", "elementor"),
|
|
1969
2177
|
targetHint: "site-settings"
|
|
1970
2178
|
}
|
|
1971
2179
|
]
|
|
@@ -1974,22 +2182,22 @@ var audit4 = {
|
|
|
1974
2182
|
};
|
|
1975
2183
|
|
|
1976
2184
|
// src/audits/deprecated-widgets.ts
|
|
1977
|
-
var
|
|
1978
|
-
var
|
|
2185
|
+
var import_editor_elements8 = require("@elementor/editor-elements");
|
|
2186
|
+
var import_i18n31 = require("@wordpress/i18n");
|
|
1979
2187
|
var DEPRECATION_CONTROL_NAME = "deprecation_message";
|
|
1980
|
-
var
|
|
2188
|
+
var audit7 = {
|
|
1981
2189
|
id: "audits/deprecated-widgets",
|
|
1982
|
-
title: (0,
|
|
1983
|
-
description: (0,
|
|
2190
|
+
title: (0, import_i18n31.__)("Deprecated widgets", "elementor"),
|
|
2191
|
+
description: (0, import_i18n31.__)(
|
|
1984
2192
|
"Deprecated widgets should not be used. For better capabilities use the recommended replacement.",
|
|
1985
2193
|
"elementor"
|
|
1986
2194
|
),
|
|
1987
|
-
fixHint: (0,
|
|
2195
|
+
fixHint: (0, import_i18n31.__)("Replace each deprecated widget with the recommended new widget shown in its panel.", "elementor"),
|
|
1988
2196
|
categories: ["best-practices", "performance"],
|
|
1989
2197
|
severity: "warning",
|
|
1990
2198
|
weight: 7,
|
|
1991
2199
|
evaluate: (ctx) => {
|
|
1992
|
-
const widgetsCache = (0,
|
|
2200
|
+
const widgetsCache = (0, import_editor_elements8.getWidgetsCache)();
|
|
1993
2201
|
if (!widgetsCache) {
|
|
1994
2202
|
return { status: "skipped", reason: "widgets-cache-unavailable" };
|
|
1995
2203
|
}
|
|
@@ -2008,10 +2216,10 @@ var audit5 = {
|
|
|
2008
2216
|
return;
|
|
2009
2217
|
}
|
|
2010
2218
|
violations.push({
|
|
2011
|
-
auditId:
|
|
2219
|
+
auditId: audit7.id,
|
|
2012
2220
|
elementId: node.id,
|
|
2013
2221
|
targetHint: "element-settings",
|
|
2014
|
-
label: (0,
|
|
2222
|
+
label: (0, import_i18n31.__)("Using deprecated widget.", "elementor")
|
|
2015
2223
|
});
|
|
2016
2224
|
});
|
|
2017
2225
|
return violations.length === 0 ? { status: "pass" } : { status: "fail", violations };
|
|
@@ -2019,28 +2227,7 @@ var audit5 = {
|
|
|
2019
2227
|
};
|
|
2020
2228
|
|
|
2021
2229
|
// src/audits/google-consent-mode.ts
|
|
2022
|
-
var
|
|
2023
|
-
|
|
2024
|
-
// src/utils/fetch-rendered-html.ts
|
|
2025
|
-
var FETCH_TIMEOUT_MS = 1e4;
|
|
2026
|
-
async function fetchRenderedHtml(url) {
|
|
2027
|
-
if (!url) {
|
|
2028
|
-
return null;
|
|
2029
|
-
}
|
|
2030
|
-
const timeoutController = new AbortController();
|
|
2031
|
-
const timeoutId = setTimeout(() => timeoutController.abort(), FETCH_TIMEOUT_MS);
|
|
2032
|
-
try {
|
|
2033
|
-
const response = await fetch(url, { credentials: "omit", signal: timeoutController.signal });
|
|
2034
|
-
if (!response.ok) {
|
|
2035
|
-
return null;
|
|
2036
|
-
}
|
|
2037
|
-
return await response.text();
|
|
2038
|
-
} catch {
|
|
2039
|
-
return null;
|
|
2040
|
-
} finally {
|
|
2041
|
-
clearTimeout(timeoutId);
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2230
|
+
var import_i18n32 = require("@wordpress/i18n");
|
|
2044
2231
|
|
|
2045
2232
|
// src/utils/scan-consent-signals.ts
|
|
2046
2233
|
var GOOGLE_TRACKING_PATTERNS = [
|
|
@@ -2061,44 +2248,43 @@ function hasConsentDefaultCall(html) {
|
|
|
2061
2248
|
}
|
|
2062
2249
|
|
|
2063
2250
|
// src/audits/google-consent-mode.ts
|
|
2064
|
-
var
|
|
2251
|
+
var audit8 = {
|
|
2065
2252
|
id: "audits/google-consent-mode",
|
|
2066
|
-
title: (0,
|
|
2067
|
-
description: (0,
|
|
2253
|
+
title: (0, import_i18n32.__)("Google Consent Mode", "elementor"),
|
|
2254
|
+
description: (0, import_i18n32.__)(
|
|
2068
2255
|
"Google Analytics, Ads, or Tag Manager are running on this site and may not receive a consent signal, which risks losing conversion/analytics data and compliance exposure.",
|
|
2069
2256
|
"elementor"
|
|
2070
2257
|
),
|
|
2071
|
-
fixHint: (0,
|
|
2258
|
+
fixHint: (0, import_i18n32.__)(
|
|
2072
2259
|
"Turn on Google Consent Mode in your cookie consent plugin so Google tags respect visitor consent choices.",
|
|
2073
2260
|
"elementor"
|
|
2074
2261
|
),
|
|
2075
2262
|
categories: ["compliance"],
|
|
2076
2263
|
severity: "warning",
|
|
2077
2264
|
weight: 1,
|
|
2078
|
-
evaluate:
|
|
2265
|
+
evaluate: (ctx) => {
|
|
2079
2266
|
if (!ctx.pageContext.frontend_url) {
|
|
2080
|
-
return { status: "skipped", reason: (0,
|
|
2267
|
+
return { status: "skipped", reason: (0, import_i18n32.__)("Page is not published.", "elementor") };
|
|
2081
2268
|
}
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
return { status: "skipped", reason: (0, import_i18n30.__)("Could not fetch the published page.", "elementor") };
|
|
2269
|
+
if (!ctx.renderedHtml) {
|
|
2270
|
+
return { status: "skipped", reason: (0, import_i18n32.__)("Could not fetch the published page.", "elementor") };
|
|
2085
2271
|
}
|
|
2086
|
-
if (!hasGoogleTracking(
|
|
2087
|
-
return { status: "skipped", reason: (0,
|
|
2272
|
+
if (!hasGoogleTracking(ctx.renderedHtml)) {
|
|
2273
|
+
return { status: "skipped", reason: (0, import_i18n32.__)("No Google tracking product detected.", "elementor") };
|
|
2088
2274
|
}
|
|
2089
|
-
if (hasConsentDefaultCall(
|
|
2275
|
+
if (hasConsentDefaultCall(ctx.renderedHtml)) {
|
|
2090
2276
|
return { status: "pass" };
|
|
2091
2277
|
}
|
|
2092
|
-
const label = (0,
|
|
2278
|
+
const label = (0, import_i18n32.__)("No Google Consent Mode signal was found on the page.", "elementor");
|
|
2093
2279
|
const isCookiezReady = ctx.pageContext.cookiez_plugin_installed && ctx.pageContext.cookiez_plugin_active;
|
|
2094
2280
|
if (isCookiezReady) {
|
|
2095
2281
|
return {
|
|
2096
2282
|
status: "fail",
|
|
2097
2283
|
violations: [
|
|
2098
2284
|
{
|
|
2099
|
-
auditId:
|
|
2285
|
+
auditId: audit8.id,
|
|
2100
2286
|
label,
|
|
2101
|
-
ctaLabel: (0,
|
|
2287
|
+
ctaLabel: (0, import_i18n32.__)("Enable", "elementor"),
|
|
2102
2288
|
externalUrl: ctx.pageContext.cookiez_consent_mode_settings_url
|
|
2103
2289
|
}
|
|
2104
2290
|
]
|
|
@@ -2108,7 +2294,7 @@ var audit6 = {
|
|
|
2108
2294
|
status: "fail",
|
|
2109
2295
|
violations: [
|
|
2110
2296
|
{
|
|
2111
|
-
auditId:
|
|
2297
|
+
auditId: audit8.id,
|
|
2112
2298
|
label,
|
|
2113
2299
|
externalUrl: ctx.pageContext.cookiez_plugin_action_url
|
|
2114
2300
|
}
|
|
@@ -2118,7 +2304,7 @@ var audit6 = {
|
|
|
2118
2304
|
};
|
|
2119
2305
|
|
|
2120
2306
|
// src/audits/heading-structure.ts
|
|
2121
|
-
var
|
|
2307
|
+
var import_i18n33 = require("@wordpress/i18n");
|
|
2122
2308
|
var HEADING_LEVELS = ["h1", "h2", "h3", "h4", "h5", "h6"];
|
|
2123
2309
|
var HEADING_CONTROLS_REGISTRY = {
|
|
2124
2310
|
// Core
|
|
@@ -2294,47 +2480,47 @@ function extractPageHeadings(tree) {
|
|
|
2294
2480
|
});
|
|
2295
2481
|
return headings;
|
|
2296
2482
|
}
|
|
2297
|
-
var
|
|
2483
|
+
var audit9 = {
|
|
2298
2484
|
id: "audits/heading-structure",
|
|
2299
|
-
title: (0,
|
|
2300
|
-
description: (0,
|
|
2301
|
-
fixHint: (0,
|
|
2485
|
+
title: (0, import_i18n33.__)("Heading structure", "elementor"),
|
|
2486
|
+
description: (0, import_i18n33.__)("Pages should have exactly one H1 and a non-skipping heading order.", "elementor"),
|
|
2487
|
+
fixHint: (0, import_i18n33.__)("Ensure your page has one H1 and that heading levels do not skip (no H2 \u2192 H4).", "elementor"),
|
|
2302
2488
|
categories: ["seo", "accessibility"],
|
|
2303
2489
|
severity: "error",
|
|
2304
2490
|
weight: 10,
|
|
2305
2491
|
evaluate: (ctx) => {
|
|
2306
2492
|
if (ctx.elements.tree.length === 0) {
|
|
2307
|
-
return { status: "skipped", reason: (0,
|
|
2493
|
+
return { status: "skipped", reason: (0, import_i18n33.__)("No elements", "elementor") };
|
|
2308
2494
|
}
|
|
2309
2495
|
const headings = extractPageHeadings(ctx.elements.tree);
|
|
2310
2496
|
const violations = [];
|
|
2311
2497
|
if (headings.length === 0) {
|
|
2312
2498
|
violations.push({
|
|
2313
|
-
auditId:
|
|
2314
|
-
label: (0,
|
|
2499
|
+
auditId: audit9.id,
|
|
2500
|
+
label: (0, import_i18n33.__)("No headings found on the page.", "elementor")
|
|
2315
2501
|
});
|
|
2316
2502
|
} else {
|
|
2317
2503
|
const h1Count = headings.filter((h) => h.level === 1).length;
|
|
2318
2504
|
if (h1Count === 0) {
|
|
2319
|
-
violations.push({ auditId:
|
|
2505
|
+
violations.push({ auditId: audit9.id, label: (0, import_i18n33.__)("No H1 on the page.", "elementor") });
|
|
2320
2506
|
}
|
|
2321
2507
|
if (h1Count > 1) {
|
|
2322
2508
|
headings.filter((h) => h.level === 1).slice(1).forEach(
|
|
2323
2509
|
(h) => violations.push({
|
|
2324
|
-
auditId:
|
|
2510
|
+
auditId: audit9.id,
|
|
2325
2511
|
elementId: h.elementId,
|
|
2326
2512
|
targetHint: "element-settings",
|
|
2327
|
-
label: (0,
|
|
2513
|
+
label: (0, import_i18n33.__)("More than one H1 on the page.", "elementor")
|
|
2328
2514
|
})
|
|
2329
2515
|
);
|
|
2330
2516
|
}
|
|
2331
2517
|
for (let i = 1; i < headings.length; i++) {
|
|
2332
2518
|
if (headings[i].level - headings[i - 1].level > 1) {
|
|
2333
2519
|
violations.push({
|
|
2334
|
-
auditId:
|
|
2520
|
+
auditId: audit9.id,
|
|
2335
2521
|
elementId: headings[i].elementId,
|
|
2336
2522
|
targetHint: "element-settings",
|
|
2337
|
-
label: (0,
|
|
2523
|
+
label: (0, import_i18n33.__)("Heading level skipped.", "elementor")
|
|
2338
2524
|
});
|
|
2339
2525
|
}
|
|
2340
2526
|
}
|
|
@@ -2344,33 +2530,33 @@ var audit7 = {
|
|
|
2344
2530
|
};
|
|
2345
2531
|
|
|
2346
2532
|
// src/audits/hidden-elements.ts
|
|
2347
|
-
var
|
|
2533
|
+
var import_i18n34 = require("@wordpress/i18n");
|
|
2348
2534
|
function isHiddenOnAllDevices(settings) {
|
|
2349
2535
|
return Boolean(settings.hide_desktop) && Boolean(settings.hide_tablet) && Boolean(settings.hide_mobile);
|
|
2350
2536
|
}
|
|
2351
|
-
var
|
|
2537
|
+
var audit10 = {
|
|
2352
2538
|
id: "audits/hidden-elements",
|
|
2353
|
-
title: (0,
|
|
2354
|
-
description: (0,
|
|
2539
|
+
title: (0, import_i18n34.__)("Hidden elements", "elementor"),
|
|
2540
|
+
description: (0, import_i18n34.__)(
|
|
2355
2541
|
"Elements hidden on all devices simultaneously are effectively dead code in the page tree.",
|
|
2356
2542
|
"elementor"
|
|
2357
2543
|
),
|
|
2358
|
-
fixHint: (0,
|
|
2544
|
+
fixHint: (0, import_i18n34.__)("Remove the element or make it visible on at least one device breakpoint.", "elementor"),
|
|
2359
2545
|
categories: ["best-practices", "performance"],
|
|
2360
2546
|
severity: "info",
|
|
2361
2547
|
weight: 3,
|
|
2362
2548
|
evaluate: (ctx) => {
|
|
2363
2549
|
if (ctx.elements.tree.length === 0) {
|
|
2364
|
-
return { status: "skipped", reason: (0,
|
|
2550
|
+
return { status: "skipped", reason: (0, import_i18n34.__)("No elements", "elementor") };
|
|
2365
2551
|
}
|
|
2366
2552
|
const violations = [];
|
|
2367
2553
|
walkElements(ctx.elements.tree, (node) => {
|
|
2368
2554
|
if (isHiddenOnAllDevices(node.settings)) {
|
|
2369
2555
|
violations.push({
|
|
2370
|
-
auditId:
|
|
2556
|
+
auditId: audit10.id,
|
|
2371
2557
|
elementId: node.id,
|
|
2372
2558
|
targetHint: "element-settings",
|
|
2373
|
-
label: (0,
|
|
2559
|
+
label: (0, import_i18n34.__)("Element is hidden on all devices.", "elementor")
|
|
2374
2560
|
});
|
|
2375
2561
|
}
|
|
2376
2562
|
});
|
|
@@ -2379,7 +2565,7 @@ var audit8 = {
|
|
|
2379
2565
|
};
|
|
2380
2566
|
|
|
2381
2567
|
// src/audits/images-alt-text.ts
|
|
2382
|
-
var
|
|
2568
|
+
var import_i18n35 = require("@wordpress/i18n");
|
|
2383
2569
|
|
|
2384
2570
|
// src/utils/image-alt.ts
|
|
2385
2571
|
function hasMeaningfulAlt(media, pageContext) {
|
|
@@ -2387,7 +2573,8 @@ function hasMeaningfulAlt(media, pageContext) {
|
|
|
2387
2573
|
return true;
|
|
2388
2574
|
}
|
|
2389
2575
|
if (media.id) {
|
|
2390
|
-
const
|
|
2576
|
+
const key = buildImageSizeKey({ id: media.id, size: media.size });
|
|
2577
|
+
const alt = pageContext.image_sizes[key]?.alt ?? "";
|
|
2391
2578
|
return alt.trim().length > 0;
|
|
2392
2579
|
}
|
|
2393
2580
|
return (media.alt ?? "").trim().length > 0;
|
|
@@ -2397,17 +2584,17 @@ function isImageSourcePresent(media) {
|
|
|
2397
2584
|
}
|
|
2398
2585
|
|
|
2399
2586
|
// src/audits/images-alt-text.ts
|
|
2400
|
-
var
|
|
2587
|
+
var audit11 = {
|
|
2401
2588
|
id: "audits/images-alt-text",
|
|
2402
|
-
title: (0,
|
|
2403
|
-
description: (0,
|
|
2404
|
-
fixHint: (0,
|
|
2589
|
+
title: (0, import_i18n35.__)("Images alt text", "elementor"),
|
|
2590
|
+
description: (0, import_i18n35.__)("Every image needs a meaningful alt attribute for screen readers and image-search.", "elementor"),
|
|
2591
|
+
fixHint: (0, import_i18n35.__)("Open the image's settings and add an Alt Text describing the image.", "elementor"),
|
|
2405
2592
|
categories: ["seo", "accessibility"],
|
|
2406
2593
|
severity: "error",
|
|
2407
2594
|
weight: 10,
|
|
2408
2595
|
evaluate: (ctx) => {
|
|
2409
2596
|
if (!hasPageImages(ctx.elements.tree)) {
|
|
2410
|
-
return { status: "skipped", reason: (0,
|
|
2597
|
+
return { status: "skipped", reason: (0, import_i18n35.__)("No images", "elementor") };
|
|
2411
2598
|
}
|
|
2412
2599
|
const violations = [];
|
|
2413
2600
|
const failedWidgetIds = /* @__PURE__ */ new Set();
|
|
@@ -2420,10 +2607,10 @@ var audit9 = {
|
|
|
2420
2607
|
if (!failedWidgetIds.has(node.id)) {
|
|
2421
2608
|
failedWidgetIds.add(node.id);
|
|
2422
2609
|
violations.push({
|
|
2423
|
-
auditId:
|
|
2610
|
+
auditId: audit11.id,
|
|
2424
2611
|
elementId: node.id,
|
|
2425
2612
|
targetHint: "element-settings",
|
|
2426
|
-
label: (0,
|
|
2613
|
+
label: (0, import_i18n35.__)("Image is missing alt text.", "elementor"),
|
|
2427
2614
|
externalUrl: ctx.pageContext.ally_plugin_url
|
|
2428
2615
|
});
|
|
2429
2616
|
}
|
|
@@ -2433,29 +2620,30 @@ var audit9 = {
|
|
|
2433
2620
|
};
|
|
2434
2621
|
|
|
2435
2622
|
// src/audits/images-too-large.ts
|
|
2436
|
-
var
|
|
2623
|
+
var import_i18n36 = require("@wordpress/i18n");
|
|
2437
2624
|
var SIZE_THRESHOLD_BYTES = 500 * 1024;
|
|
2438
2625
|
var BYTES_PER_KB = 1024;
|
|
2439
|
-
var
|
|
2626
|
+
var audit12 = {
|
|
2440
2627
|
id: "audits/images-too-large",
|
|
2441
|
-
title: (0,
|
|
2442
|
-
description: (0,
|
|
2443
|
-
fixHint: (0,
|
|
2628
|
+
title: (0, import_i18n36.__)("Oversized images", "elementor"),
|
|
2629
|
+
description: (0, import_i18n36.__)("Large image files slow down the page.", "elementor"),
|
|
2630
|
+
fixHint: (0, import_i18n36.__)("Replace the image with a smaller version or enable image optimization.", "elementor"),
|
|
2444
2631
|
categories: ["performance"],
|
|
2445
2632
|
severity: "warning",
|
|
2446
2633
|
weight: 7,
|
|
2447
2634
|
evaluate: (ctx) => {
|
|
2448
|
-
if (!hasPageImages(ctx.elements.tree)) {
|
|
2449
|
-
return { status: "skipped", reason: (0, import_i18n34.__)("No images", "elementor") };
|
|
2450
|
-
}
|
|
2451
2635
|
const widgetMaxKb = /* @__PURE__ */ new Map();
|
|
2452
2636
|
let oversizedImageCount = 0;
|
|
2453
|
-
|
|
2637
|
+
let hasAnyImage = false;
|
|
2638
|
+
const evaluateSource = (node, media) => {
|
|
2639
|
+
if (media.id || media.url) {
|
|
2640
|
+
hasAnyImage = true;
|
|
2641
|
+
}
|
|
2454
2642
|
const id = media.id;
|
|
2455
2643
|
if (!id) {
|
|
2456
2644
|
return;
|
|
2457
2645
|
}
|
|
2458
|
-
const size = ctx.pageContext.image_sizes[id];
|
|
2646
|
+
const size = ctx.pageContext.image_sizes[buildImageSizeKey({ id, size: media.size })];
|
|
2459
2647
|
if (!size || size.filesize_bytes <= SIZE_THRESHOLD_BYTES) {
|
|
2460
2648
|
return;
|
|
2461
2649
|
}
|
|
@@ -2463,14 +2651,21 @@ var audit10 = {
|
|
|
2463
2651
|
const kb = Math.round(size.filesize_bytes / BYTES_PER_KB);
|
|
2464
2652
|
const currentMax = widgetMaxKb.get(node.id) ?? 0;
|
|
2465
2653
|
widgetMaxKb.set(node.id, Math.max(currentMax, kb));
|
|
2466
|
-
}
|
|
2654
|
+
};
|
|
2655
|
+
walkImageLikeSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2656
|
+
walkBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2657
|
+
walkAtomicImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2658
|
+
walkAtomicBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2659
|
+
if (!hasAnyImage) {
|
|
2660
|
+
return { status: "skipped", reason: (0, import_i18n36.__)("No images", "elementor") };
|
|
2661
|
+
}
|
|
2467
2662
|
const violations = Array.from(widgetMaxKb.entries()).map(([elementId, kb]) => ({
|
|
2468
|
-
auditId:
|
|
2663
|
+
auditId: audit12.id,
|
|
2469
2664
|
elementId,
|
|
2470
2665
|
targetHint: "element-settings",
|
|
2471
|
-
label: (0,
|
|
2666
|
+
label: (0, import_i18n36.sprintf)(
|
|
2472
2667
|
/* translators: %d is the image file size in kilobytes. */
|
|
2473
|
-
(0,
|
|
2668
|
+
(0, import_i18n36.__)("Image is %d KB (over 500 KB).", "elementor"),
|
|
2474
2669
|
kb
|
|
2475
2670
|
),
|
|
2476
2671
|
externalUrl: ctx.pageContext.image_optimization_plugin_url
|
|
@@ -2480,21 +2675,21 @@ var audit10 = {
|
|
|
2480
2675
|
};
|
|
2481
2676
|
|
|
2482
2677
|
// src/audits/nested-boxed-containers.ts
|
|
2483
|
-
var
|
|
2678
|
+
var import_i18n37 = require("@wordpress/i18n");
|
|
2484
2679
|
function isBoxed(settings) {
|
|
2485
2680
|
return settings.content_width === "boxed";
|
|
2486
2681
|
}
|
|
2487
|
-
var
|
|
2682
|
+
var audit13 = {
|
|
2488
2683
|
id: "audits/nested-boxed-containers",
|
|
2489
|
-
title: (0,
|
|
2490
|
-
description: (0,
|
|
2491
|
-
fixHint: (0,
|
|
2684
|
+
title: (0, import_i18n37.__)("Boxed container nested inside a boxed parent", "elementor"),
|
|
2685
|
+
description: (0, import_i18n37.__)("An inner container does not need to be boxed when its parent already is.", "elementor"),
|
|
2686
|
+
fixHint: (0, import_i18n37.__)("Change the inner container's content width to Full Width.", "elementor"),
|
|
2492
2687
|
categories: ["best-practices", "performance"],
|
|
2493
2688
|
severity: "info",
|
|
2494
2689
|
weight: 5,
|
|
2495
2690
|
evaluate: (ctx) => {
|
|
2496
2691
|
if (ctx.elements.tree.length === 0) {
|
|
2497
|
-
return { status: "skipped", reason: (0,
|
|
2692
|
+
return { status: "skipped", reason: (0, import_i18n37.__)("No elements", "elementor") };
|
|
2498
2693
|
}
|
|
2499
2694
|
const violations = [];
|
|
2500
2695
|
walkElements(ctx.elements.tree, (node, parents) => {
|
|
@@ -2504,10 +2699,10 @@ var audit11 = {
|
|
|
2504
2699
|
const nearestContainerAncestor = [...parents].reverse().find((p) => p.elType === "container");
|
|
2505
2700
|
if (nearestContainerAncestor && isBoxed(nearestContainerAncestor.settings)) {
|
|
2506
2701
|
violations.push({
|
|
2507
|
-
auditId:
|
|
2702
|
+
auditId: audit13.id,
|
|
2508
2703
|
elementId: node.id,
|
|
2509
2704
|
targetHint: "element-settings",
|
|
2510
|
-
label: (0,
|
|
2705
|
+
label: (0, import_i18n37.__)("Nested boxed container.", "elementor")
|
|
2511
2706
|
});
|
|
2512
2707
|
}
|
|
2513
2708
|
});
|
|
@@ -2516,12 +2711,12 @@ var audit11 = {
|
|
|
2516
2711
|
};
|
|
2517
2712
|
|
|
2518
2713
|
// src/audits/page-excerpt.ts
|
|
2519
|
-
var
|
|
2520
|
-
var
|
|
2714
|
+
var import_i18n38 = require("@wordpress/i18n");
|
|
2715
|
+
var audit14 = {
|
|
2521
2716
|
id: "audits/page-excerpt",
|
|
2522
|
-
title: (0,
|
|
2523
|
-
description: (0,
|
|
2524
|
-
fixHint: (0,
|
|
2717
|
+
title: (0, import_i18n38.__)("Page excerpt", "elementor"),
|
|
2718
|
+
description: (0, import_i18n38.__)("A descriptive excerpt helps search engines and previews summarize the page.", "elementor"),
|
|
2719
|
+
fixHint: (0, import_i18n38.__)("Open Page Settings and write a short excerpt.", "elementor"),
|
|
2525
2720
|
categories: ["seo"],
|
|
2526
2721
|
severity: "warning",
|
|
2527
2722
|
weight: 5,
|
|
@@ -2533,8 +2728,8 @@ var audit12 = {
|
|
|
2533
2728
|
status: "fail",
|
|
2534
2729
|
violations: [
|
|
2535
2730
|
{
|
|
2536
|
-
auditId:
|
|
2537
|
-
label: (0,
|
|
2731
|
+
auditId: audit14.id,
|
|
2732
|
+
label: (0, import_i18n38.__)("Page has no excerpt.", "elementor"),
|
|
2538
2733
|
targetHint: "page-settings",
|
|
2539
2734
|
angieFix: true
|
|
2540
2735
|
}
|
|
@@ -2544,12 +2739,12 @@ var audit12 = {
|
|
|
2544
2739
|
};
|
|
2545
2740
|
|
|
2546
2741
|
// src/audits/page-featured-image.ts
|
|
2547
|
-
var
|
|
2548
|
-
var
|
|
2742
|
+
var import_i18n39 = require("@wordpress/i18n");
|
|
2743
|
+
var audit15 = {
|
|
2549
2744
|
id: "audits/page-featured-image",
|
|
2550
|
-
title: (0,
|
|
2551
|
-
description: (0,
|
|
2552
|
-
fixHint: (0,
|
|
2745
|
+
title: (0, import_i18n39.__)("Page featured image", "elementor"),
|
|
2746
|
+
description: (0, import_i18n39.__)("Featured images are used by social shares and many themes for hero visuals.", "elementor"),
|
|
2747
|
+
fixHint: (0, import_i18n39.__)("Open Page Settings and set a featured image.", "elementor"),
|
|
2553
2748
|
categories: ["seo"],
|
|
2554
2749
|
severity: "info",
|
|
2555
2750
|
weight: 5,
|
|
@@ -2561,8 +2756,8 @@ var audit13 = {
|
|
|
2561
2756
|
status: "fail",
|
|
2562
2757
|
violations: [
|
|
2563
2758
|
{
|
|
2564
|
-
auditId:
|
|
2565
|
-
label: (0,
|
|
2759
|
+
auditId: audit15.id,
|
|
2760
|
+
label: (0, import_i18n39.__)("No featured image set.", "elementor"),
|
|
2566
2761
|
targetHint: "page-settings"
|
|
2567
2762
|
}
|
|
2568
2763
|
]
|
|
@@ -2571,13 +2766,13 @@ var audit13 = {
|
|
|
2571
2766
|
};
|
|
2572
2767
|
|
|
2573
2768
|
// src/audits/page-title.ts
|
|
2574
|
-
var
|
|
2769
|
+
var import_i18n40 = require("@wordpress/i18n");
|
|
2575
2770
|
var MAX_TITLE_LENGTH = 60;
|
|
2576
|
-
var
|
|
2771
|
+
var audit16 = {
|
|
2577
2772
|
id: "audits/page-title",
|
|
2578
|
-
title: (0,
|
|
2579
|
-
description: (0,
|
|
2580
|
-
fixHint: (0,
|
|
2773
|
+
title: (0, import_i18n40.__)("Page title", "elementor"),
|
|
2774
|
+
description: (0, import_i18n40.__)("Pages need a clear title for SEO and screen-reader navigation.", "elementor"),
|
|
2775
|
+
fixHint: (0, import_i18n40.__)("Open Page Settings and add a title.", "elementor"),
|
|
2581
2776
|
categories: ["seo"],
|
|
2582
2777
|
severity: "error",
|
|
2583
2778
|
weight: 10,
|
|
@@ -2588,11 +2783,11 @@ var audit14 = {
|
|
|
2588
2783
|
status: "fail",
|
|
2589
2784
|
violations: [
|
|
2590
2785
|
{
|
|
2591
|
-
auditId:
|
|
2592
|
-
label: (0,
|
|
2786
|
+
auditId: audit16.id,
|
|
2787
|
+
label: (0, import_i18n40.__)("Page has no title.", "elementor"),
|
|
2593
2788
|
targetHint: "page-settings",
|
|
2594
2789
|
angieFix: true,
|
|
2595
|
-
angiePrompt: (0,
|
|
2790
|
+
angiePrompt: (0, import_i18n40.__)(
|
|
2596
2791
|
"Based on this page's contents, generate a title for this page.",
|
|
2597
2792
|
"elementor"
|
|
2598
2793
|
)
|
|
@@ -2605,8 +2800,8 @@ var audit14 = {
|
|
|
2605
2800
|
status: "fail",
|
|
2606
2801
|
violations: [
|
|
2607
2802
|
{
|
|
2608
|
-
auditId:
|
|
2609
|
-
label: (0,
|
|
2803
|
+
auditId: audit16.id,
|
|
2804
|
+
label: (0, import_i18n40.__)("Page title is too long.", "elementor"),
|
|
2610
2805
|
targetHint: "page-settings",
|
|
2611
2806
|
angieFix: true
|
|
2612
2807
|
}
|
|
@@ -2618,7 +2813,7 @@ var audit14 = {
|
|
|
2618
2813
|
};
|
|
2619
2814
|
|
|
2620
2815
|
// src/audits/prefer-global-colors.ts
|
|
2621
|
-
var
|
|
2816
|
+
var import_i18n41 = require("@wordpress/i18n");
|
|
2622
2817
|
|
|
2623
2818
|
// src/utils/collect-hardcoded-colors.ts
|
|
2624
2819
|
var RESERVED_SETTING_KEYS = /* @__PURE__ */ new Set(["__globals__", "__dynamic__"]);
|
|
@@ -2684,20 +2879,20 @@ function findMatchingGlobalByValue(value, globals) {
|
|
|
2684
2879
|
}
|
|
2685
2880
|
|
|
2686
2881
|
// src/audits/prefer-global-colors.ts
|
|
2687
|
-
var
|
|
2882
|
+
var audit17 = {
|
|
2688
2883
|
id: "audits/prefer-global-colors",
|
|
2689
|
-
title: (0,
|
|
2690
|
-
description: (0,
|
|
2691
|
-
fixHint: (0,
|
|
2884
|
+
title: (0, import_i18n41.__)("Prefer global colors", "elementor"),
|
|
2885
|
+
description: (0, import_i18n41.__)("Global colors make the design consistent and easy to update site-wide.", "elementor"),
|
|
2886
|
+
fixHint: (0, import_i18n41.__)("Replace the hard-coded value with the matching global color.", "elementor"),
|
|
2692
2887
|
categories: ["best-practices"],
|
|
2693
2888
|
severity: "info",
|
|
2694
2889
|
weight: 3,
|
|
2695
2890
|
evaluate: (ctx) => {
|
|
2696
2891
|
if (ctx.elements.tree.length === 0) {
|
|
2697
|
-
return { status: "skipped", reason: (0,
|
|
2892
|
+
return { status: "skipped", reason: (0, import_i18n41.__)("No elements", "elementor") };
|
|
2698
2893
|
}
|
|
2699
2894
|
if (ctx.kit.globals.colors.length === 0) {
|
|
2700
|
-
return { status: "skipped", reason: (0,
|
|
2895
|
+
return { status: "skipped", reason: (0, import_i18n41.__)("No global colors", "elementor") };
|
|
2701
2896
|
}
|
|
2702
2897
|
const violations = [];
|
|
2703
2898
|
walkElements(ctx.elements.tree, (node) => {
|
|
@@ -2707,13 +2902,13 @@ var audit15 = {
|
|
|
2707
2902
|
continue;
|
|
2708
2903
|
}
|
|
2709
2904
|
violations.push({
|
|
2710
|
-
auditId:
|
|
2905
|
+
auditId: audit17.id,
|
|
2711
2906
|
elementId: node.id,
|
|
2712
2907
|
targetHint: "element-settings",
|
|
2713
2908
|
angieFix: true,
|
|
2714
|
-
label: (0,
|
|
2909
|
+
label: (0, import_i18n41.sprintf)(
|
|
2715
2910
|
/* translators: 1: hard-coded color value, 2: global color title. */
|
|
2716
|
-
(0,
|
|
2911
|
+
(0, import_i18n41.__)('replace "%1$s" with "%2$s" global color', "elementor"),
|
|
2717
2912
|
value,
|
|
2718
2913
|
global.title
|
|
2719
2914
|
)
|
|
@@ -2725,7 +2920,7 @@ var audit15 = {
|
|
|
2725
2920
|
};
|
|
2726
2921
|
|
|
2727
2922
|
// src/audits/prefer-global-fonts.ts
|
|
2728
|
-
var
|
|
2923
|
+
var import_i18n42 = require("@wordpress/i18n");
|
|
2729
2924
|
|
|
2730
2925
|
// src/utils/collect-hardcoded-fonts.ts
|
|
2731
2926
|
var RESERVED_SETTING_KEYS2 = /* @__PURE__ */ new Set(["__globals__", "__dynamic__"]);
|
|
@@ -2783,20 +2978,20 @@ function collectHardcodedFonts(settings, pathPrefix = "") {
|
|
|
2783
2978
|
}
|
|
2784
2979
|
|
|
2785
2980
|
// src/audits/prefer-global-fonts.ts
|
|
2786
|
-
var
|
|
2981
|
+
var audit18 = {
|
|
2787
2982
|
id: "audits/prefer-global-fonts",
|
|
2788
|
-
title: (0,
|
|
2789
|
-
description: (0,
|
|
2790
|
-
fixHint: (0,
|
|
2983
|
+
title: (0, import_i18n42.__)("Prefer global fonts", "elementor"),
|
|
2984
|
+
description: (0, import_i18n42.__)("Global fonts make the design consistent and easy to update site-wide.", "elementor"),
|
|
2985
|
+
fixHint: (0, import_i18n42.__)("Replace the hard-coded value with the matching global font.", "elementor"),
|
|
2791
2986
|
categories: ["best-practices", "performance"],
|
|
2792
2987
|
severity: "info",
|
|
2793
2988
|
weight: 3,
|
|
2794
2989
|
evaluate: (ctx) => {
|
|
2795
2990
|
if (ctx.elements.tree.length === 0) {
|
|
2796
|
-
return { status: "skipped", reason: (0,
|
|
2991
|
+
return { status: "skipped", reason: (0, import_i18n42.__)("No elements", "elementor") };
|
|
2797
2992
|
}
|
|
2798
2993
|
if (ctx.kit.globals.fonts.length === 0) {
|
|
2799
|
-
return { status: "skipped", reason: (0,
|
|
2994
|
+
return { status: "skipped", reason: (0, import_i18n42.__)("No global fonts", "elementor") };
|
|
2800
2995
|
}
|
|
2801
2996
|
const violations = [];
|
|
2802
2997
|
walkElements(ctx.elements.tree, (node) => {
|
|
@@ -2806,12 +3001,12 @@ var audit16 = {
|
|
|
2806
3001
|
continue;
|
|
2807
3002
|
}
|
|
2808
3003
|
violations.push({
|
|
2809
|
-
auditId:
|
|
3004
|
+
auditId: audit18.id,
|
|
2810
3005
|
elementId: node.id,
|
|
2811
3006
|
targetHint: "element-settings",
|
|
2812
|
-
label: (0,
|
|
3007
|
+
label: (0, import_i18n42.sprintf)(
|
|
2813
3008
|
/* translators: %s: global font title. */
|
|
2814
|
-
(0,
|
|
3009
|
+
(0, import_i18n42.__)('replace hardcoded typography with "%s" global font', "elementor"),
|
|
2815
3010
|
global.title
|
|
2816
3011
|
)
|
|
2817
3012
|
});
|
|
@@ -2822,15 +3017,15 @@ var audit16 = {
|
|
|
2822
3017
|
};
|
|
2823
3018
|
|
|
2824
3019
|
// src/audits/privacy-policy.ts
|
|
2825
|
-
var
|
|
2826
|
-
var
|
|
3020
|
+
var import_i18n43 = require("@wordpress/i18n");
|
|
3021
|
+
var audit19 = {
|
|
2827
3022
|
id: "audits/privacy-policy",
|
|
2828
|
-
title: (0,
|
|
2829
|
-
description: (0,
|
|
3023
|
+
title: (0, import_i18n43.__)("Privacy policy", "elementor"),
|
|
3024
|
+
description: (0, import_i18n43.__)(
|
|
2830
3025
|
"A privacy policy page is required by privacy regulations such as GDPR (EU) and CCPA (US).",
|
|
2831
3026
|
"elementor"
|
|
2832
3027
|
),
|
|
2833
|
-
fixHint: (0,
|
|
3028
|
+
fixHint: (0, import_i18n43.__)(
|
|
2834
3029
|
"Go to Settings > Privacy in the WordPress admin and assign a published privacy policy page.",
|
|
2835
3030
|
"elementor"
|
|
2836
3031
|
),
|
|
@@ -2845,10 +3040,10 @@ var audit17 = {
|
|
|
2845
3040
|
status: "fail",
|
|
2846
3041
|
violations: [
|
|
2847
3042
|
{
|
|
2848
|
-
auditId:
|
|
2849
|
-
label: (0,
|
|
3043
|
+
auditId: audit19.id,
|
|
3044
|
+
label: (0, import_i18n43.__)("No privacy policy page is set.", "elementor"),
|
|
2850
3045
|
externalUrl: ctx.pageContext.privacy_settings_url,
|
|
2851
|
-
ctaLabel: (0,
|
|
3046
|
+
ctaLabel: (0, import_i18n43.__)("Create", "elementor")
|
|
2852
3047
|
}
|
|
2853
3048
|
]
|
|
2854
3049
|
};
|
|
@@ -2856,15 +3051,15 @@ var audit17 = {
|
|
|
2856
3051
|
};
|
|
2857
3052
|
|
|
2858
3053
|
// src/audits/robots-noindex.ts
|
|
2859
|
-
var
|
|
2860
|
-
var
|
|
3054
|
+
var import_i18n44 = require("@wordpress/i18n");
|
|
3055
|
+
var audit20 = {
|
|
2861
3056
|
id: "audits/robots-noindex",
|
|
2862
|
-
title: (0,
|
|
2863
|
-
description: (0,
|
|
3057
|
+
title: (0, import_i18n44.__)("Search engine visibility", "elementor"),
|
|
3058
|
+
description: (0, import_i18n44.__)(
|
|
2864
3059
|
"When search engine visibility is checked in WordPress Settings -> Reading -> Search Engine Visibility, search engines are discouraged from indexing the website.",
|
|
2865
3060
|
"elementor"
|
|
2866
3061
|
),
|
|
2867
|
-
fixHint: (0,
|
|
3062
|
+
fixHint: (0, import_i18n44.__)(
|
|
2868
3063
|
'Go to Settings \u2192 Reading in the WordPress admin and uncheck "Discourage search engines from indexing this site" when the website should be indexed.',
|
|
2869
3064
|
"elementor"
|
|
2870
3065
|
),
|
|
@@ -2879,8 +3074,8 @@ var audit18 = {
|
|
|
2879
3074
|
status: "fail",
|
|
2880
3075
|
violations: [
|
|
2881
3076
|
{
|
|
2882
|
-
auditId:
|
|
2883
|
-
label: (0,
|
|
3077
|
+
auditId: audit20.id,
|
|
3078
|
+
label: (0, import_i18n44.__)("Search engines are discouraged from indexing this website.", "elementor"),
|
|
2884
3079
|
externalUrl: ctx.pageContext.reading_settings_url
|
|
2885
3080
|
}
|
|
2886
3081
|
]
|
|
@@ -2889,15 +3084,15 @@ var audit18 = {
|
|
|
2889
3084
|
};
|
|
2890
3085
|
|
|
2891
3086
|
// src/audits/scan-for-cookies.ts
|
|
2892
|
-
var
|
|
2893
|
-
var
|
|
3087
|
+
var import_i18n45 = require("@wordpress/i18n");
|
|
3088
|
+
var audit21 = {
|
|
2894
3089
|
id: "audits/scan-for-cookies",
|
|
2895
|
-
title: (0,
|
|
2896
|
-
description: (0,
|
|
3090
|
+
title: (0, import_i18n45.__)("Scan for cookies", "elementor"),
|
|
3091
|
+
description: (0, import_i18n45.__)(
|
|
2897
3092
|
"Your site may be setting cookies you haven't disclosed. Some countries require a banner even without a full consent policy. Scan to see what needs disclosure.",
|
|
2898
3093
|
"elementor"
|
|
2899
3094
|
),
|
|
2900
|
-
fixHint: (0,
|
|
3095
|
+
fixHint: (0, import_i18n45.__)("Run a Cookiez scan on this page to see which cookies need disclosure.", "elementor"),
|
|
2901
3096
|
categories: ["compliance"],
|
|
2902
3097
|
severity: "info",
|
|
2903
3098
|
weight: 0,
|
|
@@ -2907,8 +3102,8 @@ var audit19 = {
|
|
|
2907
3102
|
status: "fail",
|
|
2908
3103
|
violations: [
|
|
2909
3104
|
{
|
|
2910
|
-
auditId:
|
|
2911
|
-
label: (0,
|
|
3105
|
+
auditId: audit21.id,
|
|
3106
|
+
label: (0, import_i18n45.__)("This page has not been scanned for cookies yet.", "elementor"),
|
|
2912
3107
|
externalUrl: isReady ? ctx.pageContext.cookiez_scan_url : ctx.pageContext.cookiez_plugin_action_url
|
|
2913
3108
|
}
|
|
2914
3109
|
]
|
|
@@ -2917,29 +3112,29 @@ var audit19 = {
|
|
|
2917
3112
|
};
|
|
2918
3113
|
|
|
2919
3114
|
// src/audits/sections-and-columns.ts
|
|
2920
|
-
var
|
|
2921
|
-
var
|
|
3115
|
+
var import_i18n46 = require("@wordpress/i18n");
|
|
3116
|
+
var audit22 = {
|
|
2922
3117
|
id: "audits/sections-and-columns",
|
|
2923
|
-
title: (0,
|
|
2924
|
-
description: (0,
|
|
3118
|
+
title: (0, import_i18n46.__)("Sections and columns", "elementor"),
|
|
3119
|
+
description: (0, import_i18n46.__)(
|
|
2925
3120
|
"Sections and columns are legacy elements. Containers render fewer DOM nodes and are more flexible.",
|
|
2926
3121
|
"elementor"
|
|
2927
3122
|
),
|
|
2928
|
-
fixHint: (0,
|
|
3123
|
+
fixHint: (0, import_i18n46.__)("Use the Container Converter to replace each section/column with a container.", "elementor"),
|
|
2929
3124
|
categories: ["best-practices", "performance"],
|
|
2930
3125
|
severity: "warning",
|
|
2931
3126
|
weight: 7,
|
|
2932
3127
|
evaluate: (ctx) => {
|
|
2933
3128
|
if (ctx.elements.tree.length === 0) {
|
|
2934
|
-
return { status: "skipped", reason: (0,
|
|
3129
|
+
return { status: "skipped", reason: (0, import_i18n46.__)("No elements", "elementor") };
|
|
2935
3130
|
}
|
|
2936
3131
|
const violations = [];
|
|
2937
3132
|
walkElements(ctx.elements.tree, (node) => {
|
|
2938
3133
|
if (node.elType === "section" || node.elType === "column") {
|
|
2939
3134
|
violations.push({
|
|
2940
|
-
auditId:
|
|
3135
|
+
auditId: audit22.id,
|
|
2941
3136
|
elementId: node.id,
|
|
2942
|
-
label: node.elType === "section" ? (0,
|
|
3137
|
+
label: node.elType === "section" ? (0, import_i18n46.__)("Section element", "elementor") : (0, import_i18n46.__)("Column element", "elementor")
|
|
2943
3138
|
});
|
|
2944
3139
|
}
|
|
2945
3140
|
});
|
|
@@ -2948,15 +3143,15 @@ var audit20 = {
|
|
|
2948
3143
|
};
|
|
2949
3144
|
|
|
2950
3145
|
// src/audits/site-identity.ts
|
|
2951
|
-
var
|
|
2952
|
-
var
|
|
3146
|
+
var import_i18n47 = require("@wordpress/i18n");
|
|
3147
|
+
var audit23 = {
|
|
2953
3148
|
id: "audits/site-identity",
|
|
2954
|
-
title: (0,
|
|
2955
|
-
description: (0,
|
|
3149
|
+
title: (0, import_i18n47.__)("Site identity", "elementor"),
|
|
3150
|
+
description: (0, import_i18n47.__)(
|
|
2956
3151
|
"Site name, description, logo, and favicon establish your brand and appear in search results and browser tabs.",
|
|
2957
3152
|
"elementor"
|
|
2958
3153
|
),
|
|
2959
|
-
fixHint: (0,
|
|
3154
|
+
fixHint: (0, import_i18n47.__)("Open Site Settings \u2192 Site Identity and complete all the missing fields.", "elementor"),
|
|
2960
3155
|
categories: ["best-practices", "seo"],
|
|
2961
3156
|
severity: "info",
|
|
2962
3157
|
weight: 7,
|
|
@@ -2965,30 +3160,30 @@ var audit21 = {
|
|
|
2965
3160
|
const violations = [];
|
|
2966
3161
|
if (!identity.site_name_set) {
|
|
2967
3162
|
violations.push({
|
|
2968
|
-
auditId:
|
|
2969
|
-
label: (0,
|
|
3163
|
+
auditId: audit23.id,
|
|
3164
|
+
label: (0, import_i18n47.__)("Site name is missing or still uses the default.", "elementor"),
|
|
2970
3165
|
targetHint: "site-identity-settings"
|
|
2971
3166
|
});
|
|
2972
3167
|
}
|
|
2973
3168
|
if (!identity.site_description_set) {
|
|
2974
3169
|
violations.push({
|
|
2975
|
-
auditId:
|
|
2976
|
-
label: (0,
|
|
3170
|
+
auditId: audit23.id,
|
|
3171
|
+
label: (0, import_i18n47.__)("Site description is missing or still uses the default.", "elementor"),
|
|
2977
3172
|
targetHint: "site-identity-settings",
|
|
2978
3173
|
angieFix: true
|
|
2979
3174
|
});
|
|
2980
3175
|
}
|
|
2981
3176
|
if (!identity.site_logo_set) {
|
|
2982
3177
|
violations.push({
|
|
2983
|
-
auditId:
|
|
2984
|
-
label: (0,
|
|
3178
|
+
auditId: audit23.id,
|
|
3179
|
+
label: (0, import_i18n47.__)("Site logo is not set.", "elementor"),
|
|
2985
3180
|
targetHint: "site-identity-settings"
|
|
2986
3181
|
});
|
|
2987
3182
|
}
|
|
2988
3183
|
if (!identity.site_favicon_set) {
|
|
2989
3184
|
violations.push({
|
|
2990
|
-
auditId:
|
|
2991
|
-
label: (0,
|
|
3185
|
+
auditId: audit23.id,
|
|
3186
|
+
label: (0, import_i18n47.__)("Site favicon is not set.", "elementor"),
|
|
2992
3187
|
targetHint: "site-identity-settings"
|
|
2993
3188
|
});
|
|
2994
3189
|
}
|
|
@@ -3003,8 +3198,8 @@ var audit21 = {
|
|
|
3003
3198
|
};
|
|
3004
3199
|
|
|
3005
3200
|
// src/audits/too-many-widgets.ts
|
|
3006
|
-
var
|
|
3007
|
-
var
|
|
3201
|
+
var import_editor_elements9 = require("@elementor/editor-elements");
|
|
3202
|
+
var import_i18n48 = require("@wordpress/i18n");
|
|
3008
3203
|
var WIDGET_COUNT_THRESHOLD = 100;
|
|
3009
3204
|
function isCountableWidget(node, widgetsCache) {
|
|
3010
3205
|
if (node.elType === "widget") {
|
|
@@ -3012,19 +3207,19 @@ function isCountableWidget(node, widgetsCache) {
|
|
|
3012
3207
|
}
|
|
3013
3208
|
return !!widgetsCache?.[node.elType]?.meta?.is_compound;
|
|
3014
3209
|
}
|
|
3015
|
-
var
|
|
3210
|
+
var audit24 = {
|
|
3016
3211
|
id: "audits/too-many-widgets",
|
|
3017
|
-
title: (0,
|
|
3018
|
-
description: (0,
|
|
3019
|
-
fixHint: (0,
|
|
3212
|
+
title: (0, import_i18n48.__)("Too many widgets", "elementor"),
|
|
3213
|
+
description: (0, import_i18n48.__)("Excessive DOM size caused by too many widgets degrades rendering performance.", "elementor"),
|
|
3214
|
+
fixHint: (0, import_i18n48.__)("Reduce the number of widgets on the page by removing or combining elements.", "elementor"),
|
|
3020
3215
|
categories: ["best-practices", "performance"],
|
|
3021
3216
|
severity: "warning",
|
|
3022
3217
|
weight: 5,
|
|
3023
3218
|
evaluate: (ctx) => {
|
|
3024
3219
|
if (ctx.elements.tree.length === 0) {
|
|
3025
|
-
return { status: "skipped", reason: (0,
|
|
3220
|
+
return { status: "skipped", reason: (0, import_i18n48.__)("No elements", "elementor") };
|
|
3026
3221
|
}
|
|
3027
|
-
const widgetsCache = (0,
|
|
3222
|
+
const widgetsCache = (0, import_editor_elements9.getWidgetsCache)();
|
|
3028
3223
|
let widgetCount = 0;
|
|
3029
3224
|
walkElements(ctx.elements.tree, (node) => {
|
|
3030
3225
|
if (isCountableWidget(node, widgetsCache)) {
|
|
@@ -3038,8 +3233,8 @@ var audit22 = {
|
|
|
3038
3233
|
status: "fail",
|
|
3039
3234
|
violations: [
|
|
3040
3235
|
{
|
|
3041
|
-
auditId:
|
|
3042
|
-
label: (0,
|
|
3236
|
+
auditId: audit24.id,
|
|
3237
|
+
label: (0, import_i18n48.__)("Page has too many widgets.", "elementor")
|
|
3043
3238
|
}
|
|
3044
3239
|
]
|
|
3045
3240
|
};
|
|
@@ -3048,32 +3243,34 @@ var audit22 = {
|
|
|
3048
3243
|
|
|
3049
3244
|
// src/register-audits.ts
|
|
3050
3245
|
var AUDITS = [
|
|
3246
|
+
audit16,
|
|
3051
3247
|
audit14,
|
|
3052
|
-
audit12,
|
|
3053
|
-
audit13,
|
|
3054
|
-
audit8,
|
|
3055
|
-
audit5,
|
|
3056
|
-
audit22,
|
|
3057
|
-
audit20,
|
|
3058
|
-
audit3,
|
|
3059
|
-
audit11,
|
|
3060
|
-
audit4,
|
|
3061
|
-
audit21,
|
|
3062
3248
|
audit15,
|
|
3063
|
-
audit16,
|
|
3064
|
-
audit7,
|
|
3065
|
-
audit9,
|
|
3066
3249
|
audit10,
|
|
3067
|
-
|
|
3250
|
+
audit7,
|
|
3251
|
+
audit24,
|
|
3252
|
+
audit22,
|
|
3253
|
+
audit5,
|
|
3254
|
+
audit13,
|
|
3255
|
+
audit6,
|
|
3256
|
+
audit23,
|
|
3068
3257
|
audit17,
|
|
3258
|
+
audit18,
|
|
3259
|
+
audit9,
|
|
3260
|
+
audit11,
|
|
3261
|
+
audit12,
|
|
3262
|
+
audit20,
|
|
3263
|
+
audit19,
|
|
3069
3264
|
audit,
|
|
3070
3265
|
audit2,
|
|
3071
|
-
|
|
3072
|
-
|
|
3266
|
+
audit3,
|
|
3267
|
+
audit4,
|
|
3268
|
+
audit21,
|
|
3269
|
+
audit8
|
|
3073
3270
|
];
|
|
3074
3271
|
function registerAllAudits() {
|
|
3075
|
-
for (const
|
|
3076
|
-
registerAudit(
|
|
3272
|
+
for (const audit25 of AUDITS) {
|
|
3273
|
+
registerAudit(audit25);
|
|
3077
3274
|
}
|
|
3078
3275
|
}
|
|
3079
3276
|
|