@elementor/editor-audits 4.3.4 → 4.3.5
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 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +789 -1098
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +731 -1040
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -17
- package/src/audits/accessibility-statement.ts +2 -2
- package/src/audits/cookie-policy.ts +1 -0
- package/src/audits/images-alt-text.ts +6 -4
- package/src/audits/images-inefficient-format.ts +8 -9
- package/src/audits/images-too-large.ts +8 -9
- package/src/audits/nested-boxed-containers.ts +5 -0
- package/src/components/audit-feedback.tsx +4 -1
- package/src/components/audit-panel.tsx +13 -13
- package/src/components/audit-toggle-icon.tsx +22 -0
- package/src/components/fix-violation-with-angie.tsx +18 -7
- package/src/components/pages/category-page.tsx +27 -3
- package/src/components/pages/overview-page.tsx +24 -29
- package/src/components/report-shell.tsx +10 -91
- package/src/components/rescan-button.tsx +38 -0
- package/src/components/severity-icons.tsx +5 -1
- package/src/components/severity-summary-cards.tsx +52 -0
- package/src/components/violation-cta-button.tsx +10 -2
- package/src/components/violation-icons.tsx +2 -2
- package/src/components/violation-row.tsx +118 -69
- package/src/hooks/use-audit-report.ts +5 -4
- package/src/hooks/use-audit-toggle-props.ts +2 -2
- package/src/hooks/use-single-expanded-card.ts +11 -0
- package/src/init.ts +2 -0
- package/src/register-audits.ts +0 -2
- package/src/register-promotions.ts +0 -23
- package/src/runner.ts +6 -2
- package/src/store/selectors.ts +4 -0
- package/src/store/slice.ts +10 -1
- package/src/sync-report-staleness.ts +14 -0
- package/src/types.ts +2 -0
- package/src/utils/all-image-sources.ts +17 -0
- package/src/utils/alt-text-image-sources.ts +24 -0
- package/src/utils/atomic-image-sources.ts +8 -4
- package/src/utils/audit-status-summary.ts +0 -57
- package/src/utils/image-like-sources.ts +0 -12
- package/src/utils/page-attachments.ts +3 -11
- package/src/audits/too-many-widgets.ts +0 -53
- package/src/components/audit-statuses-section.tsx +0 -65
- package/src/components/count-summary-circle.tsx +0 -66
- package/src/components/pages/all-audits-page.tsx +0 -65
- package/src/components/pages/issues-page.tsx +0 -65
- package/src/components/score-bar.tsx +0 -56
- package/src/components/score-circle.tsx +0 -60
- package/src/components/severity-filter-chips.tsx +0 -57
- package/src/utils/score-thresholds.ts +0 -23
package/dist/index.mjs
CHANGED
|
@@ -6,26 +6,131 @@ import { __registerSlice as registerSlice } from "@elementor/store";
|
|
|
6
6
|
import { utilitiesMenu } from "@elementor/editor-app-bar";
|
|
7
7
|
|
|
8
8
|
// src/hooks/use-audit-toggle-props.ts
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import { __ as __18 } from "@wordpress/i18n";
|
|
10
|
+
|
|
11
|
+
// src/components/audit-toggle-icon.tsx
|
|
12
|
+
import * as React from "react";
|
|
13
|
+
import { ShieldCheckIcon } from "@elementor/icons";
|
|
14
|
+
import { __useSelector as useSelector } from "@elementor/store";
|
|
15
|
+
import { Badge } from "@elementor/ui";
|
|
16
|
+
|
|
17
|
+
// src/store/slice.ts
|
|
18
|
+
import { __createSlice } from "@elementor/store";
|
|
19
|
+
var initialState = { status: "idle", report: null, error: null, isStale: false };
|
|
20
|
+
var slice = __createSlice({
|
|
21
|
+
name: "audits",
|
|
22
|
+
initialState,
|
|
23
|
+
reducers: {
|
|
24
|
+
runStarted(state) {
|
|
25
|
+
state.status = "loading";
|
|
26
|
+
state.error = null;
|
|
27
|
+
},
|
|
28
|
+
runSucceeded(state, action) {
|
|
29
|
+
state.status = "ready";
|
|
30
|
+
state.report = action.payload;
|
|
31
|
+
state.isStale = false;
|
|
32
|
+
},
|
|
33
|
+
runFailed(state, action) {
|
|
34
|
+
state.status = "error";
|
|
35
|
+
state.error = action.payload;
|
|
36
|
+
},
|
|
37
|
+
runAborted(state) {
|
|
38
|
+
state.status = state.report ? "ready" : "idle";
|
|
39
|
+
},
|
|
40
|
+
reportRestored(state, action) {
|
|
41
|
+
state.status = "ready";
|
|
42
|
+
state.report = action.payload;
|
|
43
|
+
state.error = null;
|
|
44
|
+
state.isStale = false;
|
|
45
|
+
},
|
|
46
|
+
reportCleared(state) {
|
|
47
|
+
state.status = "idle";
|
|
48
|
+
state.report = null;
|
|
49
|
+
state.error = null;
|
|
50
|
+
state.isStale = false;
|
|
51
|
+
},
|
|
52
|
+
reportStale(state) {
|
|
53
|
+
if (state.report) {
|
|
54
|
+
state.isStale = true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// src/store/selectors.ts
|
|
61
|
+
function selectStatus(state) {
|
|
62
|
+
return state.audits.status;
|
|
63
|
+
}
|
|
64
|
+
function selectReport(state) {
|
|
65
|
+
return state.audits.report;
|
|
66
|
+
}
|
|
67
|
+
function selectError(state) {
|
|
68
|
+
return state.audits.error;
|
|
69
|
+
}
|
|
70
|
+
function selectIsStale(state) {
|
|
71
|
+
return state.audits.isStale;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/components/audit-toggle-icon.tsx
|
|
75
|
+
function AuditToggleIcon() {
|
|
76
|
+
const isStale = useSelector((state) => selectIsStale(state));
|
|
77
|
+
return /* @__PURE__ */ React.createElement(
|
|
78
|
+
Badge,
|
|
79
|
+
{
|
|
80
|
+
variant: "dot",
|
|
81
|
+
color: "warning",
|
|
82
|
+
invisible: !isStale,
|
|
83
|
+
overlap: "circular",
|
|
84
|
+
slotProps: { badge: { "data-testid": "audit-stale-indicator" } }
|
|
85
|
+
},
|
|
86
|
+
/* @__PURE__ */ React.createElement(ShieldCheckIcon, null)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
11
89
|
|
|
12
90
|
// src/editor-panel.tsx
|
|
13
91
|
import { createFloatingPanel } from "@elementor/editor-floating-panels";
|
|
14
92
|
|
|
15
93
|
// src/components/audit-panel.tsx
|
|
16
|
-
import * as
|
|
17
|
-
import {
|
|
94
|
+
import * as React21 from "react";
|
|
95
|
+
import { getHostDocumentId as getHostDocumentId3 } from "@elementor/editor-elements";
|
|
18
96
|
import { FloatingPanelBody, FloatingPanelFooter, FloatingPanelHeader } from "@elementor/editor-floating-panels";
|
|
19
|
-
import { Box as
|
|
20
|
-
import { __ as
|
|
97
|
+
import { Box as Box15, Typography as Typography12 } from "@elementor/ui";
|
|
98
|
+
import { __ as __17 } from "@wordpress/i18n";
|
|
99
|
+
|
|
100
|
+
// src/constants.ts
|
|
101
|
+
import { __ } from "@wordpress/i18n";
|
|
102
|
+
var AUDIT_PANEL_ID = "audit-panel";
|
|
103
|
+
var REPORT_STORAGE_KEY_PREFIX = "elementor/audits/report";
|
|
104
|
+
var CREATE_WIDGET_EVENT = "elementor/editor/create-widget";
|
|
105
|
+
var ANGIE_FIX_ENTRY_POINT = "audit_violation";
|
|
106
|
+
var FEEDBACK_EXPERIMENT_NAME = "in_editor_feedback";
|
|
107
|
+
var FEEDBACK_ENTRY_POINT = "audit_panel";
|
|
108
|
+
var FEEDBACK_CLICKED_EVENT = "audit_feedback_clicked";
|
|
109
|
+
var FEEDBACK_SENT_EVENT = "audit_feedback_sent";
|
|
110
|
+
var FEEDBACK_CANCELLED_EVENT = "audit_feedback_cancelled";
|
|
111
|
+
var FEEDBACK_CLOSED_EVENT = "audit_feedback_closed";
|
|
112
|
+
var ALL_CATEGORIES = [
|
|
113
|
+
"best-practices",
|
|
114
|
+
"seo",
|
|
115
|
+
"accessibility",
|
|
116
|
+
"performance",
|
|
117
|
+
"compliance"
|
|
118
|
+
];
|
|
119
|
+
var CATEGORY_LABELS = {
|
|
120
|
+
"best-practices": __("Best Practices", "elementor"),
|
|
121
|
+
seo: __("SEO", "elementor"),
|
|
122
|
+
accessibility: __("Accessibility", "elementor"),
|
|
123
|
+
performance: __("Performance", "elementor"),
|
|
124
|
+
compliance: __("Site compliance", "elementor")
|
|
125
|
+
};
|
|
21
126
|
|
|
22
127
|
// src/hooks/use-audit-report.ts
|
|
23
128
|
import { useEffect } from "react";
|
|
24
|
-
import {
|
|
25
|
-
import { __useDispatch as useDispatch, __useSelector as
|
|
129
|
+
import { getHostDocumentId as getHostDocumentId2 } from "@elementor/editor-elements";
|
|
130
|
+
import { __useDispatch as useDispatch, __useSelector as useSelector2 } from "@elementor/store";
|
|
26
131
|
|
|
27
132
|
// src/runner.ts
|
|
28
|
-
import {
|
|
133
|
+
import { getHostDocumentElements, getHostDocumentId } from "@elementor/editor-elements";
|
|
29
134
|
|
|
30
135
|
// src/api/page-context-client.ts
|
|
31
136
|
import { httpService } from "@elementor/http-client";
|
|
@@ -103,46 +208,16 @@ async function requestPageContext(documentId, imageSizeRequests, allowNonceRetry
|
|
|
103
208
|
|
|
104
209
|
// src/registry.ts
|
|
105
210
|
var registry = /* @__PURE__ */ new Map();
|
|
106
|
-
function registerAudit(
|
|
107
|
-
registry.set(
|
|
211
|
+
function registerAudit(audit25) {
|
|
212
|
+
registry.set(audit25.id, audit25);
|
|
108
213
|
}
|
|
109
214
|
function getRegisteredAudits() {
|
|
110
215
|
return Array.from(registry.values());
|
|
111
216
|
}
|
|
112
217
|
|
|
113
|
-
// src/constants.ts
|
|
114
|
-
import { __ } from "@wordpress/i18n";
|
|
115
|
-
var AUDIT_PANEL_ID = "audit-panel";
|
|
116
|
-
var REPORT_STORAGE_KEY_PREFIX = "elementor/audits/report";
|
|
117
|
-
var CREATE_WIDGET_EVENT = "elementor/editor/create-widget";
|
|
118
|
-
var ANGIE_FIX_ENTRY_POINT = "audit_violation";
|
|
119
|
-
var FEEDBACK_EXPERIMENT_NAME = "in_editor_feedback";
|
|
120
|
-
var FEEDBACK_ENTRY_POINT = "audit_panel";
|
|
121
|
-
var FEEDBACK_CLICKED_EVENT = "audit_feedback_clicked";
|
|
122
|
-
var FEEDBACK_SENT_EVENT = "audit_feedback_sent";
|
|
123
|
-
var FEEDBACK_CANCELLED_EVENT = "audit_feedback_cancelled";
|
|
124
|
-
var FEEDBACK_CLOSED_EVENT = "audit_feedback_closed";
|
|
125
|
-
var ALL_CATEGORIES = [
|
|
126
|
-
"best-practices",
|
|
127
|
-
"seo",
|
|
128
|
-
"accessibility",
|
|
129
|
-
"performance",
|
|
130
|
-
"compliance"
|
|
131
|
-
];
|
|
132
|
-
var CATEGORY_LABELS = {
|
|
133
|
-
"best-practices": __("Best Practices", "elementor"),
|
|
134
|
-
seo: __("SEO", "elementor"),
|
|
135
|
-
accessibility: __("Accessibility", "elementor"),
|
|
136
|
-
performance: __("Performance", "elementor"),
|
|
137
|
-
compliance: __("Site compliance", "elementor")
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// src/utils/audit-status-summary.ts
|
|
141
|
-
import { __ as __2 } from "@wordpress/i18n";
|
|
142
|
-
|
|
143
218
|
// src/utils/is-scored-audit.ts
|
|
144
|
-
function isScoredAudit(
|
|
145
|
-
return
|
|
219
|
+
function isScoredAudit(audit25) {
|
|
220
|
+
return audit25.weight > 0;
|
|
146
221
|
}
|
|
147
222
|
|
|
148
223
|
// src/utils/sort-failed-audits.ts
|
|
@@ -194,52 +269,6 @@ function partitionAuditResults(report, options = {}) {
|
|
|
194
269
|
totalViolations
|
|
195
270
|
};
|
|
196
271
|
}
|
|
197
|
-
function auditStatusDisplayCounts(report) {
|
|
198
|
-
let pass = 0;
|
|
199
|
-
let skipped = 0;
|
|
200
|
-
let totalViolations = 0;
|
|
201
|
-
for (const { audit: audit26, result } of report.auditResults) {
|
|
202
|
-
if (!isScoredAudit(audit26)) {
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
switch (result.status) {
|
|
206
|
-
case "fail":
|
|
207
|
-
totalViolations += result.violations.length;
|
|
208
|
-
break;
|
|
209
|
-
case "pass":
|
|
210
|
-
pass++;
|
|
211
|
-
break;
|
|
212
|
-
case "skipped":
|
|
213
|
-
skipped++;
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return {
|
|
218
|
-
fail: totalViolations,
|
|
219
|
-
pass,
|
|
220
|
-
skipped
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
function auditStatusColor(status) {
|
|
224
|
-
switch (status) {
|
|
225
|
-
case "fail":
|
|
226
|
-
return "error";
|
|
227
|
-
case "pass":
|
|
228
|
-
return "success";
|
|
229
|
-
case "skipped":
|
|
230
|
-
return "default";
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
function auditStatusLabel(status) {
|
|
234
|
-
switch (status) {
|
|
235
|
-
case "fail":
|
|
236
|
-
return __2("Failed audits", "elementor");
|
|
237
|
-
case "pass":
|
|
238
|
-
return __2("Passed audits", "elementor");
|
|
239
|
-
case "skipped":
|
|
240
|
-
return __2("Skipped audits", "elementor");
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
272
|
function getPopulatedCategories(categoryTotals, categories) {
|
|
244
273
|
return categories.filter((category) => categoryTotals[category].total > 0);
|
|
245
274
|
}
|
|
@@ -249,16 +278,16 @@ function computeReport(documentId, results) {
|
|
|
249
278
|
const accumulators = Object.fromEntries(
|
|
250
279
|
ALL_CATEGORIES.map((c) => [c, { totalWeight: 0, passedWeight: 0, total: 0, failed: 0 }])
|
|
251
280
|
);
|
|
252
|
-
for (const { audit:
|
|
281
|
+
for (const { audit: audit25, result } of results) {
|
|
253
282
|
if (result.status === "skipped") {
|
|
254
283
|
continue;
|
|
255
284
|
}
|
|
256
|
-
for (const category of
|
|
285
|
+
for (const category of audit25.categories) {
|
|
257
286
|
const acc = accumulators[category];
|
|
258
287
|
acc.total++;
|
|
259
|
-
acc.totalWeight +=
|
|
288
|
+
acc.totalWeight += audit25.weight;
|
|
260
289
|
if (result.status === "pass") {
|
|
261
|
-
acc.passedWeight +=
|
|
290
|
+
acc.passedWeight += audit25.weight;
|
|
262
291
|
} else {
|
|
263
292
|
acc.failed++;
|
|
264
293
|
}
|
|
@@ -335,13 +364,14 @@ function recurse(nodes, parents, visit) {
|
|
|
335
364
|
}
|
|
336
365
|
|
|
337
366
|
// src/utils/atomic-image-sources.ts
|
|
338
|
-
var
|
|
339
|
-
|
|
367
|
+
var ATOMIC_CONTENT_IMAGE_PROP_KEYS = ["image"];
|
|
368
|
+
var ATOMIC_IMAGE_PROP_KEYS = [...ATOMIC_CONTENT_IMAGE_PROP_KEYS, "poster"];
|
|
369
|
+
function walkAtomicImageSources(tree, visit, propKeys = ATOMIC_IMAGE_PROP_KEYS) {
|
|
340
370
|
walkElements(tree, (node) => {
|
|
341
371
|
if (node.elType !== "widget") {
|
|
342
372
|
return;
|
|
343
373
|
}
|
|
344
|
-
for (const key of
|
|
374
|
+
for (const key of propKeys) {
|
|
345
375
|
const media = extractAtomicImageMedia(node.settings[key]);
|
|
346
376
|
if (media) {
|
|
347
377
|
visit({ node, media });
|
|
@@ -363,8 +393,9 @@ function extractAtomicImageMedia(imageProp) {
|
|
|
363
393
|
if (!id && !url) {
|
|
364
394
|
return null;
|
|
365
395
|
}
|
|
396
|
+
const alt = stringPropTypeUtil.extract(src.alt) ?? void 0;
|
|
366
397
|
const size = stringPropTypeUtil.extract(image.size) ?? void 0;
|
|
367
|
-
return { id, url, size };
|
|
398
|
+
return { id, url, alt, size };
|
|
368
399
|
}
|
|
369
400
|
|
|
370
401
|
// src/utils/atomic-background-image-sources.ts
|
|
@@ -419,15 +450,6 @@ function walkBackgroundImageSources(tree, visit) {
|
|
|
419
450
|
|
|
420
451
|
// src/utils/image-like-sources.ts
|
|
421
452
|
var IMAGE_LIKE_WIDGETS = /* @__PURE__ */ new Set(["image", "image-box", "image-carousel", "gallery", "image-gallery"]);
|
|
422
|
-
function hasPageImages(tree) {
|
|
423
|
-
let found = false;
|
|
424
|
-
walkImageLikeSources(tree, ({ media }) => {
|
|
425
|
-
if (media.id || media.url) {
|
|
426
|
-
found = true;
|
|
427
|
-
}
|
|
428
|
-
});
|
|
429
|
-
return found;
|
|
430
|
-
}
|
|
431
453
|
function walkImageLikeSources(tree, visit) {
|
|
432
454
|
walkElements(tree, (node) => {
|
|
433
455
|
if (node.elType !== "widget") {
|
|
@@ -459,6 +481,14 @@ function collectMediaFromNode(node) {
|
|
|
459
481
|
return sources;
|
|
460
482
|
}
|
|
461
483
|
|
|
484
|
+
// src/utils/all-image-sources.ts
|
|
485
|
+
function walkAllImageSources(tree, visit) {
|
|
486
|
+
walkImageLikeSources(tree, visit);
|
|
487
|
+
walkBackgroundImageSources(tree, visit);
|
|
488
|
+
walkAtomicImageSources(tree, visit);
|
|
489
|
+
walkAtomicBackgroundImageSources(tree, visit);
|
|
490
|
+
}
|
|
491
|
+
|
|
462
492
|
// src/utils/image-size-key.ts
|
|
463
493
|
function buildImageSizeKey({ id, size }) {
|
|
464
494
|
return `${id}:${size || "full"}`;
|
|
@@ -467,15 +497,11 @@ function buildImageSizeKey({ id, size }) {
|
|
|
467
497
|
// src/utils/page-attachments.ts
|
|
468
498
|
function extractImageSizeRequests(tree) {
|
|
469
499
|
const keys = /* @__PURE__ */ new Set();
|
|
470
|
-
|
|
500
|
+
walkAllImageSources(tree, ({ media }) => {
|
|
471
501
|
if (media.id) {
|
|
472
502
|
keys.add(buildImageSizeKey({ id: media.id, size: media.size }));
|
|
473
503
|
}
|
|
474
|
-
};
|
|
475
|
-
walkImageLikeSources(tree, ({ media }) => collect(media));
|
|
476
|
-
walkBackgroundImageSources(tree, ({ media }) => collect(media));
|
|
477
|
-
walkAtomicImageSources(tree, ({ media }) => collect(media));
|
|
478
|
-
walkAtomicBackgroundImageSources(tree, ({ media }) => collect(media));
|
|
504
|
+
});
|
|
479
505
|
return Array.from(keys).sort();
|
|
480
506
|
}
|
|
481
507
|
|
|
@@ -570,7 +596,10 @@ function toSnapshot(element) {
|
|
|
570
596
|
|
|
571
597
|
// src/runner.ts
|
|
572
598
|
async function runPageAudit(documentId) {
|
|
573
|
-
|
|
599
|
+
if (documentId !== getHostDocumentId()) {
|
|
600
|
+
throw new Error("runPageAudit: documentId must match the host document.");
|
|
601
|
+
}
|
|
602
|
+
const tree = buildSnapshotTree(getHostDocumentElements());
|
|
574
603
|
const imageSizeRequests = extractImageSizeRequests(tree);
|
|
575
604
|
const pageContext = await fetchPageContext(documentId, imageSizeRequests);
|
|
576
605
|
const elements = { documentId, tree };
|
|
@@ -581,10 +610,10 @@ async function runPageAudit(documentId) {
|
|
|
581
610
|
const ctx = { documentId, elements, pageContext, kit, renderedHtml };
|
|
582
611
|
const registered = getRegisteredAudits();
|
|
583
612
|
const auditResults = await Promise.all(
|
|
584
|
-
registered.map(async (
|
|
585
|
-
const { evaluate: _evaluate, ...meta } =
|
|
613
|
+
registered.map(async (audit25) => {
|
|
614
|
+
const { evaluate: _evaluate, ...meta } = audit25;
|
|
586
615
|
try {
|
|
587
|
-
const result = await
|
|
616
|
+
const result = await audit25.evaluate(ctx);
|
|
588
617
|
return { audit: meta, result };
|
|
589
618
|
} catch (error) {
|
|
590
619
|
const reason = error instanceof Error ? error.message : "unknown-error";
|
|
@@ -595,52 +624,6 @@ async function runPageAudit(documentId) {
|
|
|
595
624
|
return computeReport(documentId, auditResults);
|
|
596
625
|
}
|
|
597
626
|
|
|
598
|
-
// src/store/slice.ts
|
|
599
|
-
import { __createSlice } from "@elementor/store";
|
|
600
|
-
var initialState = { status: "idle", report: null, error: null };
|
|
601
|
-
var slice = __createSlice({
|
|
602
|
-
name: "audits",
|
|
603
|
-
initialState,
|
|
604
|
-
reducers: {
|
|
605
|
-
runStarted(state) {
|
|
606
|
-
state.status = "loading";
|
|
607
|
-
state.error = null;
|
|
608
|
-
},
|
|
609
|
-
runSucceeded(state, action) {
|
|
610
|
-
state.status = "ready";
|
|
611
|
-
state.report = action.payload;
|
|
612
|
-
},
|
|
613
|
-
runFailed(state, action) {
|
|
614
|
-
state.status = "error";
|
|
615
|
-
state.error = action.payload;
|
|
616
|
-
},
|
|
617
|
-
runAborted(state) {
|
|
618
|
-
state.status = state.report ? "ready" : "idle";
|
|
619
|
-
},
|
|
620
|
-
reportRestored(state, action) {
|
|
621
|
-
state.status = "ready";
|
|
622
|
-
state.report = action.payload;
|
|
623
|
-
state.error = null;
|
|
624
|
-
},
|
|
625
|
-
reportCleared(state) {
|
|
626
|
-
state.status = "idle";
|
|
627
|
-
state.report = null;
|
|
628
|
-
state.error = null;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
// src/store/selectors.ts
|
|
634
|
-
function selectStatus(state) {
|
|
635
|
-
return state.audits.status;
|
|
636
|
-
}
|
|
637
|
-
function selectReport(state) {
|
|
638
|
-
return state.audits.report;
|
|
639
|
-
}
|
|
640
|
-
function selectError(state) {
|
|
641
|
-
return state.audits.error;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
627
|
// src/utils/report-storage.ts
|
|
645
628
|
import { getSessionStorageItem, setSessionStorageItem } from "@elementor/session";
|
|
646
629
|
function getStorageKey(documentId) {
|
|
@@ -655,42 +638,44 @@ function persistReport(documentId, report) {
|
|
|
655
638
|
|
|
656
639
|
// src/hooks/use-audit-report.ts
|
|
657
640
|
function useAuditReport() {
|
|
658
|
-
const status =
|
|
659
|
-
const report =
|
|
660
|
-
const error =
|
|
661
|
-
const
|
|
662
|
-
const
|
|
641
|
+
const status = useSelector2((state) => selectStatus(state));
|
|
642
|
+
const report = useSelector2((state) => selectReport(state));
|
|
643
|
+
const error = useSelector2((state) => selectError(state));
|
|
644
|
+
const isStale = useSelector2((state) => selectIsStale(state));
|
|
645
|
+
const dispatch2 = useDispatch();
|
|
646
|
+
const documentId = getHostDocumentId2() ?? 0;
|
|
663
647
|
useEffect(() => {
|
|
664
648
|
if (!documentId || report?.documentId === documentId) {
|
|
665
649
|
return;
|
|
666
650
|
}
|
|
667
651
|
const persisted = getPersistedReport(documentId);
|
|
668
652
|
if (persisted) {
|
|
669
|
-
|
|
653
|
+
dispatch2(slice.actions.reportRestored(persisted));
|
|
670
654
|
} else if (report) {
|
|
671
|
-
|
|
655
|
+
dispatch2(slice.actions.reportCleared());
|
|
672
656
|
}
|
|
673
|
-
}, [documentId, report,
|
|
657
|
+
}, [documentId, report, dispatch2]);
|
|
674
658
|
const run = async (documentIdToRun) => {
|
|
675
|
-
|
|
659
|
+
dispatch2(slice.actions.runStarted());
|
|
676
660
|
try {
|
|
677
661
|
const nextReport = await runPageAudit(documentIdToRun);
|
|
678
|
-
|
|
662
|
+
dispatch2(slice.actions.runSucceeded(nextReport));
|
|
679
663
|
persistReport(documentIdToRun, nextReport);
|
|
680
664
|
} catch (e) {
|
|
681
665
|
if (e instanceof SessionExpiredError) {
|
|
682
|
-
|
|
666
|
+
dispatch2(slice.actions.runAborted());
|
|
683
667
|
return;
|
|
684
668
|
}
|
|
685
|
-
|
|
669
|
+
dispatch2(slice.actions.runFailed(e instanceof Error ? e.message : "Unknown error"));
|
|
686
670
|
}
|
|
687
671
|
};
|
|
688
|
-
return { status, report, error, run };
|
|
672
|
+
return { status, report, error, isStale, run };
|
|
689
673
|
}
|
|
690
674
|
|
|
691
675
|
// src/components/audit-feedback.tsx
|
|
692
|
-
import * as
|
|
676
|
+
import * as React2 from "react";
|
|
693
677
|
import { useState } from "react";
|
|
678
|
+
import { useFloatingPanelZIndex } from "@elementor/editor-floating-panels";
|
|
694
679
|
import { notify } from "@elementor/editor-notifications";
|
|
695
680
|
import { isExperimentActive } from "@elementor/editor-v1-adapters";
|
|
696
681
|
import { useMixpanel } from "@elementor/events";
|
|
@@ -709,9 +694,9 @@ import {
|
|
|
709
694
|
Tooltip,
|
|
710
695
|
Typography
|
|
711
696
|
} from "@elementor/ui";
|
|
712
|
-
import { __ as
|
|
697
|
+
import { __ as __2 } from "@wordpress/i18n";
|
|
713
698
|
var FEEDBACK_SUBJECT = "Page Audit Tool";
|
|
714
|
-
var FEEDBACK_SUBJECT_LABEL =
|
|
699
|
+
var FEEDBACK_SUBJECT_LABEL = __2("Page Audit Tool", "elementor");
|
|
715
700
|
var SUCCESS_NOTIFICATION_ID = "audit-feedback-success";
|
|
716
701
|
var ERROR_NOTIFICATION_ID = "audit-feedback-error";
|
|
717
702
|
var DIALOG_TITLE_ID = "audit-feedback-dialog-title";
|
|
@@ -720,18 +705,19 @@ var isUserConnected = () => Boolean(window.elementorCommon?.config?.library_conn
|
|
|
720
705
|
var notifySuccess = () => notify({
|
|
721
706
|
id: SUCCESS_NOTIFICATION_ID,
|
|
722
707
|
type: "success",
|
|
723
|
-
message:
|
|
708
|
+
message: __2("Feedback sent. Thanks for helping us out.", "elementor")
|
|
724
709
|
});
|
|
725
710
|
var notifyError = () => notify({
|
|
726
711
|
id: ERROR_NOTIFICATION_ID,
|
|
727
712
|
type: "error",
|
|
728
|
-
message:
|
|
713
|
+
message: __2("Something went wrong. Please try sending your feedback again.", "elementor")
|
|
729
714
|
});
|
|
730
715
|
function AuditFeedback() {
|
|
731
716
|
const [isOpen, setIsOpen] = useState(false);
|
|
732
717
|
const [feedbackText, setFeedbackText] = useState("");
|
|
733
718
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
734
719
|
const { dispatchEvent: trackEvent = (...args) => void args } = useMixpanel();
|
|
720
|
+
const panelZIndex = useFloatingPanelZIndex(AUDIT_PANEL_ID);
|
|
735
721
|
if (!isExperimentActive(FEEDBACK_EXPERIMENT_NAME)) {
|
|
736
722
|
return null;
|
|
737
723
|
}
|
|
@@ -740,7 +726,7 @@ function AuditFeedback() {
|
|
|
740
726
|
if (!connected && !connectUrl) {
|
|
741
727
|
return null;
|
|
742
728
|
}
|
|
743
|
-
const triggerLabel =
|
|
729
|
+
const triggerLabel = __2("Give feedback", "elementor");
|
|
744
730
|
const handleOpen = () => {
|
|
745
731
|
if (!connected) {
|
|
746
732
|
window.open(connectUrl, "_blank", "noopener");
|
|
@@ -773,7 +759,7 @@ function AuditFeedback() {
|
|
|
773
759
|
trackEvent(FEEDBACK_SENT_EVENT, { entry_point: FEEDBACK_ENTRY_POINT });
|
|
774
760
|
}).catch(notifyError).finally(() => setIsSubmitting(false));
|
|
775
761
|
};
|
|
776
|
-
return /* @__PURE__ */
|
|
762
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Tooltip, { title: triggerLabel, placement: "top", PopperProps: { sx: { zIndex: panelZIndex } } }, /* @__PURE__ */ React2.createElement(IconButton, { size: "small", "aria-label": triggerLabel, onClick: handleOpen }, /* @__PURE__ */ React2.createElement(MessageLinesIcon, { fontSize: "small" }))), /* @__PURE__ */ React2.createElement(
|
|
777
763
|
Dialog,
|
|
778
764
|
{
|
|
779
765
|
open: isOpen,
|
|
@@ -782,11 +768,11 @@ function AuditFeedback() {
|
|
|
782
768
|
"aria-describedby": DIALOG_DESCRIPTION_ID,
|
|
783
769
|
PaperProps: { sx: { borderRadius: 1 } }
|
|
784
770
|
},
|
|
785
|
-
/* @__PURE__ */
|
|
786
|
-
/* @__PURE__ */
|
|
771
|
+
/* @__PURE__ */ React2.createElement(DialogHeader, { logo: false, onClose: handleClose }, /* @__PURE__ */ React2.createElement(DialogTitle, { id: DIALOG_TITLE_ID }, __2("Let us know what you think", "elementor"))),
|
|
772
|
+
/* @__PURE__ */ React2.createElement(DialogContent, { dividers: true }, /* @__PURE__ */ React2.createElement(Stack, { direction: "column", gap: 2 }, /* @__PURE__ */ React2.createElement(TextField, { value: FEEDBACK_SUBJECT_LABEL, disabled: true, fullWidth: true, size: "small" }), /* @__PURE__ */ React2.createElement(
|
|
787
773
|
TextField,
|
|
788
774
|
{
|
|
789
|
-
placeholder:
|
|
775
|
+
placeholder: __2(
|
|
790
776
|
"Tell us what you had in mind, what we can improve or fix to make this feature better.",
|
|
791
777
|
"elementor"
|
|
792
778
|
),
|
|
@@ -797,11 +783,11 @@ function AuditFeedback() {
|
|
|
797
783
|
onChange: (event) => setFeedbackText(event.target.value),
|
|
798
784
|
value: feedbackText
|
|
799
785
|
}
|
|
800
|
-
), /* @__PURE__ */
|
|
786
|
+
), /* @__PURE__ */ React2.createElement(Typography, { id: DIALOG_DESCRIPTION_ID, variant: "caption", color: "text.secondary" }, __2(
|
|
801
787
|
"We appreciate your feedback! While we review all submissions, we can't guarantee that every suggestion will result in a change or update.",
|
|
802
788
|
"elementor"
|
|
803
789
|
)))),
|
|
804
|
-
/* @__PURE__ */
|
|
790
|
+
/* @__PURE__ */ React2.createElement(DialogActions, null, /* @__PURE__ */ React2.createElement(Button, { variant: "text", color: "secondary", onClick: handleCancel }, __2("Cancel", "elementor")), /* @__PURE__ */ React2.createElement(
|
|
805
791
|
Button,
|
|
806
792
|
{
|
|
807
793
|
variant: "contained",
|
|
@@ -809,35 +795,35 @@ function AuditFeedback() {
|
|
|
809
795
|
disabled: isSubmitting || feedbackText.trim().length === 0,
|
|
810
796
|
onClick: handleSubmit
|
|
811
797
|
},
|
|
812
|
-
|
|
798
|
+
__2("Send", "elementor")
|
|
813
799
|
))
|
|
814
800
|
));
|
|
815
801
|
}
|
|
816
802
|
|
|
817
803
|
// src/components/pages/error-page.tsx
|
|
818
|
-
import * as
|
|
804
|
+
import * as React3 from "react";
|
|
819
805
|
import { Box, Button as Button2, Typography as Typography2 } from "@elementor/ui";
|
|
820
|
-
import { __ as
|
|
806
|
+
import { __ as __3 } from "@wordpress/i18n";
|
|
821
807
|
function ErrorPage({ message, onRetry }) {
|
|
822
|
-
return /* @__PURE__ */
|
|
808
|
+
return /* @__PURE__ */ React3.createElement(Box, { sx: { display: "flex", flexDirection: "column", alignItems: "center", gap: 1.5, p: 4 } }, /* @__PURE__ */ React3.createElement(Typography2, { variant: "body2", color: "error", textAlign: "center" }, message), /* @__PURE__ */ React3.createElement(Button2, { variant: "contained", size: "small", onClick: onRetry }, __3("Try again", "elementor")));
|
|
823
809
|
}
|
|
824
810
|
|
|
825
811
|
// src/components/pages/loading-page.tsx
|
|
826
|
-
import * as
|
|
812
|
+
import * as React4 from "react";
|
|
827
813
|
import { Box as Box2, CircularProgress, Typography as Typography3 } from "@elementor/ui";
|
|
828
|
-
import { __ as
|
|
814
|
+
import { __ as __4 } from "@wordpress/i18n";
|
|
829
815
|
function LoadingPage() {
|
|
830
|
-
return /* @__PURE__ */
|
|
816
|
+
return /* @__PURE__ */ React4.createElement(Box2, { sx: { display: "flex", flexDirection: "column", alignItems: "center", gap: 1.5, p: 4 } }, /* @__PURE__ */ React4.createElement(CircularProgress, { size: 32 }), /* @__PURE__ */ React4.createElement(Typography3, { variant: "body2" }, __4("Audit in progress.", "elementor")));
|
|
831
817
|
}
|
|
832
818
|
|
|
833
819
|
// src/components/pages/welcome-page.tsx
|
|
834
|
-
import * as
|
|
820
|
+
import * as React5 from "react";
|
|
835
821
|
import { Box as Box3, Typography as Typography4 } from "@elementor/ui";
|
|
836
|
-
import { __ as
|
|
822
|
+
import { __ as __5 } from "@wordpress/i18n";
|
|
837
823
|
var INFORMATION_IMAGE_PATH = "images/information.svg";
|
|
838
824
|
function WelcomePage() {
|
|
839
825
|
const assetsUrl = window.elementorCommon?.config?.urls?.assets ?? "";
|
|
840
|
-
return /* @__PURE__ */
|
|
826
|
+
return /* @__PURE__ */ React5.createElement(
|
|
841
827
|
Box3,
|
|
842
828
|
{
|
|
843
829
|
sx: {
|
|
@@ -849,17 +835,17 @@ function WelcomePage() {
|
|
|
849
835
|
p: 3
|
|
850
836
|
}
|
|
851
837
|
},
|
|
852
|
-
/* @__PURE__ */
|
|
838
|
+
/* @__PURE__ */ React5.createElement(
|
|
853
839
|
"img",
|
|
854
840
|
{
|
|
855
841
|
className: "elementor-nerd-box-icon",
|
|
856
842
|
src: `${assetsUrl}${INFORMATION_IMAGE_PATH}`,
|
|
857
843
|
loading: "lazy",
|
|
858
|
-
alt:
|
|
844
|
+
alt: __5("Elementor", "elementor")
|
|
859
845
|
}
|
|
860
846
|
),
|
|
861
|
-
/* @__PURE__ */
|
|
862
|
-
/* @__PURE__ */
|
|
847
|
+
/* @__PURE__ */ React5.createElement(Typography4, { variant: "subtitle1", component: "h3", sx: { marginBlockStart: 2 } }, __5("Audit your page!", "elementor")),
|
|
848
|
+
/* @__PURE__ */ React5.createElement(Typography4, { variant: "caption", textAlign: "center" }, __5(
|
|
863
849
|
'Check SEO, accessibility, performance, and best practices. Click "Run page audit" to begin.',
|
|
864
850
|
"elementor"
|
|
865
851
|
))
|
|
@@ -867,40 +853,59 @@ function WelcomePage() {
|
|
|
867
853
|
}
|
|
868
854
|
|
|
869
855
|
// src/components/report-shell.tsx
|
|
870
|
-
import * as
|
|
871
|
-
import { useState as
|
|
872
|
-
import { Box as
|
|
873
|
-
import { __ as __22 } from "@wordpress/i18n";
|
|
856
|
+
import * as React19 from "react";
|
|
857
|
+
import { useState as useState4 } from "react";
|
|
858
|
+
import { Box as Box14 } from "@elementor/ui";
|
|
874
859
|
|
|
875
|
-
// src/components/pages/
|
|
876
|
-
import * as
|
|
860
|
+
// src/components/pages/category-page.tsx
|
|
861
|
+
import * as React13 from "react";
|
|
877
862
|
import { Box as Box8 } from "@elementor/ui";
|
|
878
|
-
import { __ as
|
|
863
|
+
import { __ as __11 } from "@wordpress/i18n";
|
|
879
864
|
|
|
880
|
-
// src/
|
|
881
|
-
import * as React5 from "react";
|
|
865
|
+
// src/hooks/use-single-expanded-card.ts
|
|
882
866
|
import { useState as useState2 } from "react";
|
|
867
|
+
function useSingleExpandedCard(initialId = null) {
|
|
868
|
+
const [expandedId, setExpandedId] = useState2(initialId);
|
|
869
|
+
const toggle = (id) => {
|
|
870
|
+
setExpandedId((current) => current === id ? null : id);
|
|
871
|
+
};
|
|
872
|
+
return { expandedId, toggle };
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// src/components/category-icons.ts
|
|
876
|
+
import { BoltIcon, ElementorAccessibilityIcon, FileSearchIcon, Settings2Icon, ShieldCheckIcon as ShieldCheckIcon2 } from "@elementor/icons";
|
|
877
|
+
var CATEGORY_ICONS = {
|
|
878
|
+
"best-practices": Settings2Icon,
|
|
879
|
+
seo: FileSearchIcon,
|
|
880
|
+
accessibility: ElementorAccessibilityIcon,
|
|
881
|
+
performance: BoltIcon,
|
|
882
|
+
compliance: ShieldCheckIcon2
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
// src/components/status-section.tsx
|
|
886
|
+
import * as React6 from "react";
|
|
887
|
+
import { useState as useState3 } from "react";
|
|
883
888
|
import { ChevronDownIcon } from "@elementor/icons";
|
|
884
889
|
import { Box as Box4, Chip, Collapse, IconButton as IconButton2 } from "@elementor/ui";
|
|
885
|
-
import { __ as
|
|
890
|
+
import { __ as __6 } from "@wordpress/i18n";
|
|
886
891
|
function StatusSection({ label, count, color = "default", defaultExpanded = false, children }) {
|
|
887
|
-
const [expanded, setExpanded] =
|
|
888
|
-
if (
|
|
892
|
+
const [expanded, setExpanded] = useState3(defaultExpanded);
|
|
893
|
+
if (React6.Children.count(children) === 0) {
|
|
889
894
|
return null;
|
|
890
895
|
}
|
|
891
|
-
return /* @__PURE__ */
|
|
896
|
+
return /* @__PURE__ */ React6.createElement(Box4, { sx: { paddingBlock: 1 } }, /* @__PURE__ */ React6.createElement(
|
|
892
897
|
Box4,
|
|
893
898
|
{
|
|
894
899
|
sx: { display: "flex", alignItems: "center", gap: 0.5, cursor: "pointer" },
|
|
895
900
|
onClick: () => setExpanded((v) => !v)
|
|
896
901
|
},
|
|
897
|
-
/* @__PURE__ */
|
|
902
|
+
/* @__PURE__ */ React6.createElement(
|
|
898
903
|
IconButton2,
|
|
899
904
|
{
|
|
900
905
|
size: "small",
|
|
901
|
-
"aria-label": expanded ?
|
|
906
|
+
"aria-label": expanded ? __6("Collapse", "elementor") : __6("Expand", "elementor")
|
|
902
907
|
},
|
|
903
|
-
/* @__PURE__ */
|
|
908
|
+
/* @__PURE__ */ React6.createElement(
|
|
904
909
|
ChevronDownIcon,
|
|
905
910
|
{
|
|
906
911
|
fontSize: "small",
|
|
@@ -911,27 +916,27 @@ function StatusSection({ label, count, color = "default", defaultExpanded = fals
|
|
|
911
916
|
}
|
|
912
917
|
)
|
|
913
918
|
),
|
|
914
|
-
/* @__PURE__ */
|
|
915
|
-
), /* @__PURE__ */
|
|
919
|
+
/* @__PURE__ */ React6.createElement(Chip, { label: `${label} (${count})`, size: "small", color, variant: "standard" })
|
|
920
|
+
), /* @__PURE__ */ React6.createElement(Collapse, { in: expanded }, /* @__PURE__ */ React6.createElement(Box4, { sx: { paddingInlineStart: 4.25, paddingBlock: 2 } }, children)));
|
|
916
921
|
}
|
|
917
922
|
|
|
918
923
|
// src/components/subpage-header.tsx
|
|
919
|
-
import * as
|
|
924
|
+
import * as React7 from "react";
|
|
920
925
|
import { ArrowLeftIcon } from "@elementor/icons";
|
|
921
926
|
import { Box as Box5, IconButton as IconButton3, Rotate, Typography as Typography5, useTheme } from "@elementor/ui";
|
|
922
|
-
import { __ as
|
|
927
|
+
import { __ as __7 } from "@wordpress/i18n";
|
|
923
928
|
function SubpageHeader({ title, onBack, backLabel, icon }) {
|
|
924
929
|
const isRtl = "rtl" === useTheme().direction;
|
|
925
|
-
return /* @__PURE__ */
|
|
930
|
+
return /* @__PURE__ */ React7.createElement(Box5, { sx: { display: "flex", alignItems: "center", gap: 0.5, p: 1 } }, /* @__PURE__ */ React7.createElement(IconButton3, { size: "small", onClick: onBack, "aria-label": backLabel ?? __7("Back", "elementor") }, /* @__PURE__ */ React7.createElement(Rotate, { in: isRtl }, /* @__PURE__ */ React7.createElement(ArrowLeftIcon, { fontSize: "small" }))), icon, /* @__PURE__ */ React7.createElement(Typography5, { variant: "subtitle2", fontWeight: "bold" }, title));
|
|
926
931
|
}
|
|
927
932
|
|
|
928
933
|
// src/components/violation-row.tsx
|
|
929
|
-
import * as
|
|
930
|
-
import { useState as useState3 } from "react";
|
|
934
|
+
import * as React12 from "react";
|
|
931
935
|
import { getElementIcon, getElementTitle } from "@elementor/editor-elements";
|
|
932
|
-
import {
|
|
933
|
-
import {
|
|
934
|
-
import {
|
|
936
|
+
import { useFloatingPanelZIndex as useFloatingPanelZIndex2 } from "@elementor/editor-floating-panels";
|
|
937
|
+
import { CheckIcon, ChevronDownIcon as ChevronDownIcon2, HelpIcon, InfoCircleIcon } from "@elementor/icons";
|
|
938
|
+
import { Alert, Box as Box7, Collapse as Collapse2, IconButton as IconButton5, Tooltip as Tooltip3, Typography as Typography6 } from "@elementor/ui";
|
|
939
|
+
import { __ as __10 } from "@wordpress/i18n";
|
|
935
940
|
|
|
936
941
|
// src/hooks/focus-violation.ts
|
|
937
942
|
import { getContainer, selectElement } from "@elementor/editor-elements";
|
|
@@ -972,11 +977,11 @@ function focusViolation(violation) {
|
|
|
972
977
|
}
|
|
973
978
|
|
|
974
979
|
// src/utils/build-angie-prompt.ts
|
|
975
|
-
import { __ as
|
|
980
|
+
import { __ as __8, sprintf } from "@wordpress/i18n";
|
|
976
981
|
function buildAngiePrompt(violationText) {
|
|
977
982
|
return sprintf(
|
|
978
983
|
/* translators: %s: audit violation description. */
|
|
979
|
-
|
|
984
|
+
__8("Help me fix: %s", "elementor"),
|
|
980
985
|
violationText
|
|
981
986
|
);
|
|
982
987
|
}
|
|
@@ -992,13 +997,13 @@ function onKeyboardClick(callback) {
|
|
|
992
997
|
}
|
|
993
998
|
|
|
994
999
|
// src/components/fix-violation-with-angie.tsx
|
|
995
|
-
import * as
|
|
1000
|
+
import * as React8 from "react";
|
|
996
1001
|
import { isAngieAvailable, sendPromptToAngie } from "@elementor/editor-mcp";
|
|
997
1002
|
import { AngieIcon } from "@elementor/icons";
|
|
998
|
-
import { IconButton as IconButton4, Tooltip as Tooltip2 } from "@elementor/ui";
|
|
999
|
-
import { __ as
|
|
1000
|
-
function FixViolationWithAngie({ prompt }) {
|
|
1001
|
-
const label =
|
|
1003
|
+
import { Button as Button3, IconButton as IconButton4, Tooltip as Tooltip2 } from "@elementor/ui";
|
|
1004
|
+
import { __ as __9 } from "@wordpress/i18n";
|
|
1005
|
+
function FixViolationWithAngie({ prompt, panelZIndex, variant = "icon" }) {
|
|
1006
|
+
const label = __9("Fix with Angie", "elementor");
|
|
1002
1007
|
const href = `#angie-prompt=${encodeURIComponent(prompt)}`;
|
|
1003
1008
|
const handleClick = (event) => {
|
|
1004
1009
|
event.stopPropagation();
|
|
@@ -1016,52 +1021,69 @@ function FixViolationWithAngie({ prompt }) {
|
|
|
1016
1021
|
})
|
|
1017
1022
|
);
|
|
1018
1023
|
};
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1024
|
+
if (variant === "button") {
|
|
1025
|
+
return /* @__PURE__ */ React8.createElement(
|
|
1026
|
+
Button3,
|
|
1027
|
+
{
|
|
1028
|
+
component: "a",
|
|
1029
|
+
href,
|
|
1030
|
+
size: "small",
|
|
1031
|
+
color: "secondary",
|
|
1032
|
+
variant: "outlined",
|
|
1033
|
+
startIcon: /* @__PURE__ */ React8.createElement(AngieIcon, { fontSize: "tiny", "aria-hidden": true }),
|
|
1034
|
+
onClick: handleClick
|
|
1035
|
+
},
|
|
1036
|
+
label
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
return /* @__PURE__ */ React8.createElement(Tooltip2, { title: label, placement: "top", PopperProps: { sx: { zIndex: panelZIndex } } }, /* @__PURE__ */ React8.createElement(IconButton4, { component: "a", href, size: "small", "aria-label": label, onClick: handleClick }, /* @__PURE__ */ React8.createElement(AngieIcon, { fontSize: "tiny" })));
|
|
1031
1040
|
}
|
|
1032
1041
|
|
|
1033
1042
|
// src/components/severity-icons.tsx
|
|
1034
|
-
import * as
|
|
1043
|
+
import * as React9 from "react";
|
|
1035
1044
|
import { AlertCircleIcon, AlertTriangleFilledIcon, BulbIcon } from "@elementor/icons";
|
|
1036
1045
|
var SEVERITY_CONFIG = {
|
|
1037
1046
|
error: { Icon: AlertTriangleFilledIcon, color: "error" },
|
|
1038
1047
|
warning: { Icon: AlertCircleIcon, color: "warning" },
|
|
1039
1048
|
info: { Icon: BulbIcon, color: "info" }
|
|
1040
1049
|
};
|
|
1050
|
+
var INFO_ICON_VERTICAL_NUDGE = "translateY(-2px)";
|
|
1041
1051
|
function SeverityIcon({ severity }) {
|
|
1042
1052
|
const { Icon, color } = SEVERITY_CONFIG[severity];
|
|
1043
|
-
|
|
1053
|
+
const sx = "info" === severity ? { transform: INFO_ICON_VERTICAL_NUDGE } : void 0;
|
|
1054
|
+
return /* @__PURE__ */ React9.createElement(Icon, { fontSize: "small", color, sx });
|
|
1044
1055
|
}
|
|
1045
1056
|
|
|
1046
1057
|
// src/components/violation-cta-button.tsx
|
|
1047
|
-
import * as
|
|
1048
|
-
import {
|
|
1049
|
-
|
|
1058
|
+
import * as React10 from "react";
|
|
1059
|
+
import { WandIcon } from "@elementor/icons";
|
|
1060
|
+
import { Button as Button4 } from "@elementor/ui";
|
|
1061
|
+
function ViolationCtaButton({ ctaLabel, externalUrl, variant = "outlined", withIcon = false }) {
|
|
1050
1062
|
const handleClick = (event) => {
|
|
1051
1063
|
event.stopPropagation();
|
|
1052
1064
|
event.preventDefault();
|
|
1053
1065
|
window.open(externalUrl, "_blank", "noopener");
|
|
1054
1066
|
};
|
|
1055
|
-
return /* @__PURE__ */
|
|
1067
|
+
return /* @__PURE__ */ React10.createElement(
|
|
1068
|
+
Button4,
|
|
1069
|
+
{
|
|
1070
|
+
variant,
|
|
1071
|
+
color: "secondary",
|
|
1072
|
+
size: "small",
|
|
1073
|
+
startIcon: withIcon ? /* @__PURE__ */ React10.createElement(WandIcon, { fontSize: "tiny", "aria-hidden": true }) : void 0,
|
|
1074
|
+
onClick: handleClick
|
|
1075
|
+
},
|
|
1076
|
+
ctaLabel
|
|
1077
|
+
);
|
|
1056
1078
|
}
|
|
1057
1079
|
|
|
1058
1080
|
// src/components/violation-icons.tsx
|
|
1059
|
-
import * as
|
|
1060
|
-
import { FileSettingsIcon, SettingsIcon
|
|
1081
|
+
import * as React11 from "react";
|
|
1082
|
+
import { FileSettingsIcon, SettingsIcon } from "@elementor/icons";
|
|
1061
1083
|
import { Box as Box6 } from "@elementor/ui";
|
|
1062
1084
|
function ViolationIcon({ violation, widgetIcon }) {
|
|
1063
1085
|
if (widgetIcon) {
|
|
1064
|
-
return /* @__PURE__ */
|
|
1086
|
+
return /* @__PURE__ */ React11.createElement(
|
|
1065
1087
|
Box6,
|
|
1066
1088
|
{
|
|
1067
1089
|
component: "i",
|
|
@@ -1072,28 +1094,73 @@ function ViolationIcon({ violation, widgetIcon }) {
|
|
|
1072
1094
|
);
|
|
1073
1095
|
}
|
|
1074
1096
|
if (violation.targetHint === "page-settings") {
|
|
1075
|
-
return /* @__PURE__ */
|
|
1097
|
+
return /* @__PURE__ */ React11.createElement(FileSettingsIcon, { fontSize: "inherit", "aria-hidden": true });
|
|
1076
1098
|
}
|
|
1077
1099
|
if (violation.targetHint === "site-settings" || violation.targetHint === "site-identity-settings") {
|
|
1078
|
-
return /* @__PURE__ */
|
|
1100
|
+
return /* @__PURE__ */ React11.createElement(SettingsIcon, { fontSize: "inherit", "aria-hidden": true });
|
|
1079
1101
|
}
|
|
1080
|
-
return /* @__PURE__ */
|
|
1102
|
+
return /* @__PURE__ */ React11.createElement(SettingsIcon, { fontSize: "inherit", "aria-hidden": true });
|
|
1081
1103
|
}
|
|
1082
1104
|
|
|
1083
1105
|
// src/components/violation-row.tsx
|
|
1084
1106
|
function SkipReasonTooltip({ reason }) {
|
|
1085
|
-
return /* @__PURE__ */
|
|
1107
|
+
return /* @__PURE__ */ React12.createElement(Tooltip3, { title: reason, placement: "top" }, /* @__PURE__ */ React12.createElement(Box7, { "aria-label": reason, component: "span", sx: { display: "inline-flex", alignItems: "center" } }, /* @__PURE__ */ React12.createElement(HelpIcon, { fontSize: "small", color: "action" })));
|
|
1086
1108
|
}
|
|
1087
|
-
function StatusIndicator({ audit:
|
|
1109
|
+
function StatusIndicator({ audit: audit25, violations }) {
|
|
1088
1110
|
if (violations) {
|
|
1089
|
-
return /* @__PURE__ */
|
|
1111
|
+
return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(SeverityIcon, { severity: audit25.severity }), isScoredAudit(audit25) && /* @__PURE__ */ React12.createElement(Typography6, { variant: "caption", color: "text.secondary", fontWeight: "bold" }, violations.length));
|
|
1112
|
+
}
|
|
1113
|
+
return /* @__PURE__ */ React12.createElement(CheckIcon, { fontSize: "small", color: "success" });
|
|
1114
|
+
}
|
|
1115
|
+
function GuidanceAction({
|
|
1116
|
+
violation,
|
|
1117
|
+
sharedAngiePrompt,
|
|
1118
|
+
panelZIndex
|
|
1119
|
+
}) {
|
|
1120
|
+
const hasPrimaryCta = !!(violation.ctaLabel && violation.externalUrl);
|
|
1121
|
+
if (!hasPrimaryCta && !sharedAngiePrompt) {
|
|
1122
|
+
return null;
|
|
1123
|
+
}
|
|
1124
|
+
return /* @__PURE__ */ React12.createElement(Box7, { display: "flex", alignItems: "center", gap: 1, mt: 1 }, hasPrimaryCta && /* @__PURE__ */ React12.createElement(
|
|
1125
|
+
ViolationCtaButton,
|
|
1126
|
+
{
|
|
1127
|
+
ctaLabel: violation.ctaLabel,
|
|
1128
|
+
externalUrl: violation.externalUrl,
|
|
1129
|
+
withIcon: true
|
|
1130
|
+
}
|
|
1131
|
+
), hasPrimaryCta && violation.secondaryCtaLabel && violation.secondaryCtaUrl && /* @__PURE__ */ React12.createElement(
|
|
1132
|
+
ViolationCtaButton,
|
|
1133
|
+
{
|
|
1134
|
+
ctaLabel: violation.secondaryCtaLabel,
|
|
1135
|
+
externalUrl: violation.secondaryCtaUrl,
|
|
1136
|
+
variant: "text"
|
|
1137
|
+
}
|
|
1138
|
+
), sharedAngiePrompt && /* @__PURE__ */ React12.createElement(FixViolationWithAngie, { prompt: sharedAngiePrompt, panelZIndex, variant: "button" }));
|
|
1139
|
+
}
|
|
1140
|
+
function getSharedAngiePrompt(violations) {
|
|
1141
|
+
if (!violations || violations.length < 2) {
|
|
1142
|
+
return void 0;
|
|
1143
|
+
}
|
|
1144
|
+
const [first, ...rest] = violations;
|
|
1145
|
+
if (!first.angieFix || !first.angiePrompt) {
|
|
1146
|
+
return void 0;
|
|
1090
1147
|
}
|
|
1091
|
-
|
|
1148
|
+
const allShareTheSameFix = rest.every(
|
|
1149
|
+
(violation) => violation.angieFix && violation.angiePrompt === first.angiePrompt
|
|
1150
|
+
);
|
|
1151
|
+
return allShareTheSameFix ? first.angiePrompt : void 0;
|
|
1092
1152
|
}
|
|
1093
|
-
function ViolationRow({ audit:
|
|
1094
|
-
const
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1153
|
+
function ViolationRow({ audit: audit25, expanded, onToggleExpand, skipReason, violations }) {
|
|
1154
|
+
const primaryViolation = violations?.[0];
|
|
1155
|
+
const isGuidanceFocusable = !!primaryViolation;
|
|
1156
|
+
const panelZIndex = useFloatingPanelZIndex2(AUDIT_PANEL_ID);
|
|
1157
|
+
const sharedAngiePrompt = getSharedAngiePrompt(violations);
|
|
1158
|
+
const handleGuidanceClick = () => {
|
|
1159
|
+
if (isGuidanceFocusable && primaryViolation) {
|
|
1160
|
+
focusViolation(primaryViolation);
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1163
|
+
return /* @__PURE__ */ React12.createElement(Box7, { sx: { borderBottom: 1, borderColor: "divider", paddingBlock: 0.5 } }, /* @__PURE__ */ React12.createElement(Box7, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React12.createElement(
|
|
1097
1164
|
Box7,
|
|
1098
1165
|
{
|
|
1099
1166
|
sx: {
|
|
@@ -1104,18 +1171,18 @@ function ViolationRow({ audit: audit26, skipReason, violations }) {
|
|
|
1104
1171
|
gap: 0.5,
|
|
1105
1172
|
minWidth: 0
|
|
1106
1173
|
},
|
|
1107
|
-
onClick:
|
|
1174
|
+
onClick: onToggleExpand
|
|
1108
1175
|
},
|
|
1109
|
-
/* @__PURE__ */
|
|
1110
|
-
!skipReason && /* @__PURE__ */
|
|
1111
|
-
), skipReason && /* @__PURE__ */
|
|
1176
|
+
/* @__PURE__ */ React12.createElement(Typography6, { variant: "subtitle2", color: "text.secondary", sx: { flex: 1 } }, audit25.title),
|
|
1177
|
+
!skipReason && /* @__PURE__ */ React12.createElement(StatusIndicator, { audit: audit25, violations })
|
|
1178
|
+
), skipReason && /* @__PURE__ */ React12.createElement(SkipReasonTooltip, { reason: skipReason }), /* @__PURE__ */ React12.createElement(
|
|
1112
1179
|
IconButton5,
|
|
1113
1180
|
{
|
|
1114
1181
|
size: "small",
|
|
1115
|
-
"aria-label": expanded ?
|
|
1116
|
-
onClick:
|
|
1182
|
+
"aria-label": expanded ? __10("Collapse", "elementor") : __10("Expand", "elementor"),
|
|
1183
|
+
onClick: onToggleExpand
|
|
1117
1184
|
},
|
|
1118
|
-
/* @__PURE__ */
|
|
1185
|
+
/* @__PURE__ */ React12.createElement(
|
|
1119
1186
|
ChevronDownIcon2,
|
|
1120
1187
|
{
|
|
1121
1188
|
fontSize: "small",
|
|
@@ -1125,29 +1192,33 @@ function ViolationRow({ audit: audit26, skipReason, violations }) {
|
|
|
1125
1192
|
}
|
|
1126
1193
|
}
|
|
1127
1194
|
)
|
|
1128
|
-
)), /* @__PURE__ */
|
|
1195
|
+
)), /* @__PURE__ */ React12.createElement(Collapse2, { in: expanded }, /* @__PURE__ */ React12.createElement(Box7, { paddingBlock: 1 }, /* @__PURE__ */ React12.createElement(Tooltip3, { title: audit25.fixHint, placement: "top" }, /* @__PURE__ */ React12.createElement(
|
|
1129
1196
|
Alert,
|
|
1130
1197
|
{
|
|
1131
1198
|
severity: "secondary",
|
|
1132
|
-
sx: { p: 1 },
|
|
1133
|
-
icon: /* @__PURE__ */
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
Alert,
|
|
1139
|
-
{
|
|
1140
|
-
severity: "info",
|
|
1141
|
-
sx: { p: 1 },
|
|
1142
|
-
icon: /* @__PURE__ */ React11.createElement(BulbIcon2, { fontSize: "small", color: "info", "aria-hidden": true })
|
|
1199
|
+
sx: { p: 1, cursor: isGuidanceFocusable ? "pointer" : void 0 },
|
|
1200
|
+
icon: /* @__PURE__ */ React12.createElement(InfoCircleIcon, { fontSize: "small", "aria-hidden": true }),
|
|
1201
|
+
role: isGuidanceFocusable ? "button" : void 0,
|
|
1202
|
+
tabIndex: isGuidanceFocusable ? 0 : void 0,
|
|
1203
|
+
onClick: isGuidanceFocusable ? handleGuidanceClick : void 0,
|
|
1204
|
+
onKeyDown: isGuidanceFocusable ? onKeyboardClick(handleGuidanceClick) : void 0
|
|
1143
1205
|
},
|
|
1144
|
-
/* @__PURE__ */
|
|
1145
|
-
/* @__PURE__ */
|
|
1146
|
-
|
|
1206
|
+
/* @__PURE__ */ React12.createElement(Typography6, { variant: "caption", component: "p", color: "text.secondary" }, audit25.description),
|
|
1207
|
+
primaryViolation && /* @__PURE__ */ React12.createElement(
|
|
1208
|
+
GuidanceAction,
|
|
1209
|
+
{
|
|
1210
|
+
violation: primaryViolation,
|
|
1211
|
+
sharedAngiePrompt,
|
|
1212
|
+
panelZIndex
|
|
1213
|
+
}
|
|
1214
|
+
)
|
|
1215
|
+
))), violations && violations.length > 0 && /* @__PURE__ */ React12.createElement(Box7, { role: "list", sx: { paddingBlockEnd: 1 } }, violations.map((violation, idx) => {
|
|
1147
1216
|
const widgetIcon = violation.elementId ? getElementIcon(violation.elementId) : null;
|
|
1148
1217
|
const elementTitle = violation.elementId ? getElementTitle(violation.elementId) : null;
|
|
1149
|
-
const
|
|
1150
|
-
|
|
1218
|
+
const displayLabel = elementTitle ?? violation.label;
|
|
1219
|
+
const angiePromptContext = elementTitle ? `${elementTitle} - ${violation.label}` : violation.label;
|
|
1220
|
+
const showsOwnFixAction = !!violation.angieFix && !sharedAngiePrompt;
|
|
1221
|
+
return /* @__PURE__ */ React12.createElement(
|
|
1151
1222
|
Box7,
|
|
1152
1223
|
{
|
|
1153
1224
|
key: idx,
|
|
@@ -1160,265 +1231,130 @@ function ViolationRow({ audit: audit26, skipReason, violations }) {
|
|
|
1160
1231
|
alignItems: "center",
|
|
1161
1232
|
gap: 1,
|
|
1162
1233
|
paddingBlock: 0.5,
|
|
1163
|
-
paddingInline:
|
|
1234
|
+
paddingInline: 1,
|
|
1164
1235
|
borderRadius: 1,
|
|
1165
1236
|
cursor: "pointer",
|
|
1166
|
-
"& .violation-hover-icon": { opacity: 0, transition: "opacity .15s" },
|
|
1167
1237
|
"&:hover": { bgcolor: "action.hover" },
|
|
1168
|
-
"&:hover .violation-
|
|
1238
|
+
"&:hover .violation-row-fix-action, &:focus-visible .violation-row-fix-action": {
|
|
1169
1239
|
opacity: 1
|
|
1170
1240
|
}
|
|
1171
1241
|
}
|
|
1172
1242
|
},
|
|
1173
|
-
/* @__PURE__ */
|
|
1174
|
-
/* @__PURE__ */
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
{
|
|
1178
|
-
prompt: violation.angiePrompt ?? buildAngiePrompt(rowLabel)
|
|
1179
|
-
}
|
|
1180
|
-
),
|
|
1181
|
-
violation.ctaLabel && violation.externalUrl ? /* @__PURE__ */ React11.createElement(Box7, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React11.createElement(
|
|
1182
|
-
ViolationCtaButton,
|
|
1183
|
-
{
|
|
1184
|
-
ctaLabel: violation.ctaLabel,
|
|
1185
|
-
externalUrl: violation.externalUrl
|
|
1186
|
-
}
|
|
1187
|
-
), violation.secondaryCtaLabel && violation.secondaryCtaUrl && /* @__PURE__ */ React11.createElement(
|
|
1188
|
-
ViolationCtaButton,
|
|
1189
|
-
{
|
|
1190
|
-
ctaLabel: violation.secondaryCtaLabel,
|
|
1191
|
-
externalUrl: violation.secondaryCtaUrl,
|
|
1192
|
-
variant: "text"
|
|
1193
|
-
}
|
|
1194
|
-
)) : /* @__PURE__ */ React11.createElement(
|
|
1195
|
-
EyeIcon,
|
|
1243
|
+
/* @__PURE__ */ React12.createElement(ViolationIcon, { violation, widgetIcon }),
|
|
1244
|
+
/* @__PURE__ */ React12.createElement(Box7, { sx: { flex: 1 } }, /* @__PURE__ */ React12.createElement(Typography6, { variant: "caption" }, displayLabel), violation.detail && /* @__PURE__ */ React12.createElement(Typography6, { variant: "caption", color: "text.secondary" }, violation.detail)),
|
|
1245
|
+
showsOwnFixAction && /* @__PURE__ */ React12.createElement(
|
|
1246
|
+
Box7,
|
|
1196
1247
|
{
|
|
1197
|
-
className: "violation-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1248
|
+
className: "violation-row-fix-action",
|
|
1249
|
+
sx: { opacity: 0, transition: "opacity .15s" }
|
|
1250
|
+
},
|
|
1251
|
+
/* @__PURE__ */ React12.createElement(
|
|
1252
|
+
FixViolationWithAngie,
|
|
1253
|
+
{
|
|
1254
|
+
prompt: violation.angiePrompt ?? buildAngiePrompt(angiePromptContext),
|
|
1255
|
+
panelZIndex
|
|
1256
|
+
}
|
|
1257
|
+
)
|
|
1201
1258
|
)
|
|
1202
1259
|
);
|
|
1203
1260
|
}))));
|
|
1204
1261
|
}
|
|
1205
1262
|
|
|
1206
|
-
// src/components/pages/all-audits-page.tsx
|
|
1207
|
-
function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
|
|
1208
|
-
const { failed, passed, skipped, totalViolations } = partitionAuditResults(report);
|
|
1209
|
-
const expandFail = !initialExpandedStatus || initialExpandedStatus === "fail";
|
|
1210
|
-
const expandPass = initialExpandedStatus === "pass";
|
|
1211
|
-
const expandSkipped = initialExpandedStatus === "skipped";
|
|
1212
|
-
return /* @__PURE__ */ React12.createElement(Box8, { key: initialExpandedStatus ?? "default" }, /* @__PURE__ */ React12.createElement(SubpageHeader, { title: __12("All audits", "elementor"), onBack }), /* @__PURE__ */ React12.createElement(Box8, { sx: { p: 1 } }, /* @__PURE__ */ React12.createElement(
|
|
1213
|
-
StatusSection,
|
|
1214
|
-
{
|
|
1215
|
-
label: auditStatusLabel("fail"),
|
|
1216
|
-
count: totalViolations,
|
|
1217
|
-
color: auditStatusColor("fail"),
|
|
1218
|
-
defaultExpanded: expandFail
|
|
1219
|
-
},
|
|
1220
|
-
failed.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, violations: r.result.violations }))
|
|
1221
|
-
), /* @__PURE__ */ React12.createElement(
|
|
1222
|
-
StatusSection,
|
|
1223
|
-
{
|
|
1224
|
-
label: auditStatusLabel("pass"),
|
|
1225
|
-
count: passed.length,
|
|
1226
|
-
color: auditStatusColor("pass"),
|
|
1227
|
-
defaultExpanded: expandPass
|
|
1228
|
-
},
|
|
1229
|
-
passed.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit }))
|
|
1230
|
-
), /* @__PURE__ */ React12.createElement(
|
|
1231
|
-
StatusSection,
|
|
1232
|
-
{
|
|
1233
|
-
label: auditStatusLabel("skipped"),
|
|
1234
|
-
count: skipped.length,
|
|
1235
|
-
color: auditStatusColor("skipped"),
|
|
1236
|
-
defaultExpanded: expandSkipped
|
|
1237
|
-
},
|
|
1238
|
-
skipped.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, skipReason: r.result.reason }))
|
|
1239
|
-
)));
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
// src/components/pages/category-page.tsx
|
|
1243
|
-
import * as React13 from "react";
|
|
1244
|
-
import { Box as Box9 } from "@elementor/ui";
|
|
1245
|
-
import { __ as __13 } from "@wordpress/i18n";
|
|
1246
|
-
|
|
1247
|
-
// src/components/category-icons.ts
|
|
1248
|
-
import { BoltIcon, ElementorAccessibilityIcon, FileSearchIcon, Settings2Icon, ShieldCheckIcon as ShieldCheckIcon2 } from "@elementor/icons";
|
|
1249
|
-
var CATEGORY_ICONS = {
|
|
1250
|
-
"best-practices": Settings2Icon,
|
|
1251
|
-
seo: FileSearchIcon,
|
|
1252
|
-
accessibility: ElementorAccessibilityIcon,
|
|
1253
|
-
performance: BoltIcon,
|
|
1254
|
-
compliance: ShieldCheckIcon2
|
|
1255
|
-
};
|
|
1256
|
-
|
|
1257
1263
|
// src/components/pages/category-page.tsx
|
|
1258
1264
|
function CategoryPage({ category, report, onBack }) {
|
|
1259
1265
|
const Icon = CATEGORY_ICONS[category];
|
|
1260
|
-
const { failed, passed, totalViolations } = partitionAuditResults(report, { category });
|
|
1266
|
+
const { failed, passed, skipped, totalViolations } = partitionAuditResults(report, { category });
|
|
1267
|
+
const { expandedId, toggle } = useSingleExpandedCard();
|
|
1261
1268
|
return /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(
|
|
1262
1269
|
SubpageHeader,
|
|
1263
1270
|
{
|
|
1264
1271
|
title: CATEGORY_LABELS[category],
|
|
1265
1272
|
onBack,
|
|
1266
|
-
backLabel:
|
|
1273
|
+
backLabel: __11("Back to all issues", "elementor"),
|
|
1267
1274
|
icon: /* @__PURE__ */ React13.createElement(Icon, { fontSize: "small", color: "action" })
|
|
1268
1275
|
}
|
|
1269
|
-
), /* @__PURE__ */ React13.createElement(
|
|
1276
|
+
), /* @__PURE__ */ React13.createElement(Box8, { sx: { p: 1 } }, /* @__PURE__ */ React13.createElement(
|
|
1270
1277
|
StatusSection,
|
|
1271
1278
|
{
|
|
1272
|
-
label:
|
|
1279
|
+
label: __11("Failed audits", "elementor"),
|
|
1273
1280
|
count: totalViolations,
|
|
1274
1281
|
color: "error",
|
|
1275
1282
|
defaultExpanded: true
|
|
1276
1283
|
},
|
|
1277
|
-
failed.map((r) => /* @__PURE__ */ React13.createElement(
|
|
1278
|
-
|
|
1284
|
+
failed.map((r) => /* @__PURE__ */ React13.createElement(
|
|
1285
|
+
ViolationRow,
|
|
1286
|
+
{
|
|
1287
|
+
key: r.audit.id,
|
|
1288
|
+
audit: r.audit,
|
|
1289
|
+
violations: r.result.violations,
|
|
1290
|
+
expanded: expandedId === r.audit.id,
|
|
1291
|
+
onToggleExpand: () => toggle(r.audit.id)
|
|
1292
|
+
}
|
|
1293
|
+
))
|
|
1294
|
+
), /* @__PURE__ */ React13.createElement(StatusSection, { label: __11("Passed audits", "elementor"), count: passed.length, color: "success" }, passed.map((r) => /* @__PURE__ */ React13.createElement(
|
|
1295
|
+
ViolationRow,
|
|
1296
|
+
{
|
|
1297
|
+
key: r.audit.id,
|
|
1298
|
+
audit: r.audit,
|
|
1299
|
+
expanded: expandedId === r.audit.id,
|
|
1300
|
+
onToggleExpand: () => toggle(r.audit.id)
|
|
1301
|
+
}
|
|
1302
|
+
))), /* @__PURE__ */ React13.createElement(StatusSection, { label: __11("Skipped audits", "elementor"), count: skipped.length, color: "default" }, skipped.map((r) => /* @__PURE__ */ React13.createElement(
|
|
1303
|
+
ViolationRow,
|
|
1304
|
+
{
|
|
1305
|
+
key: r.audit.id,
|
|
1306
|
+
audit: r.audit,
|
|
1307
|
+
skipReason: r.result.reason,
|
|
1308
|
+
expanded: expandedId === r.audit.id,
|
|
1309
|
+
onToggleExpand: () => toggle(r.audit.id)
|
|
1310
|
+
}
|
|
1311
|
+
)))));
|
|
1279
1312
|
}
|
|
1280
1313
|
|
|
1281
|
-
// src/components/pages/
|
|
1282
|
-
import * as React18 from "react";
|
|
1283
|
-
import {
|
|
1284
|
-
import {
|
|
1285
|
-
import { __ as __17 } from "@wordpress/i18n";
|
|
1314
|
+
// src/components/pages/overview-page.tsx
|
|
1315
|
+
import * as React18 from "react";
|
|
1316
|
+
import { Box as Box13, Typography as Typography11 } from "@elementor/ui";
|
|
1317
|
+
import { __ as __15 } from "@wordpress/i18n";
|
|
1286
1318
|
|
|
1287
1319
|
// src/utils/severity-counts.ts
|
|
1288
|
-
import { __ as
|
|
1320
|
+
import { __ as __12 } from "@wordpress/i18n";
|
|
1289
1321
|
var ALL_SEVERITIES = ["error", "warning", "info"];
|
|
1290
1322
|
function countSeverities(report, category) {
|
|
1291
1323
|
const counts = { error: 0, warning: 0, info: 0 };
|
|
1292
|
-
for (const { audit:
|
|
1324
|
+
for (const { audit: audit25, result } of report.auditResults) {
|
|
1293
1325
|
if (result.status !== "fail") {
|
|
1294
1326
|
continue;
|
|
1295
1327
|
}
|
|
1296
|
-
if (category && !
|
|
1328
|
+
if (category && !audit25.categories.includes(category)) {
|
|
1297
1329
|
continue;
|
|
1298
1330
|
}
|
|
1299
|
-
if (!isScoredAudit(
|
|
1331
|
+
if (!isScoredAudit(audit25)) {
|
|
1300
1332
|
continue;
|
|
1301
1333
|
}
|
|
1302
|
-
counts[
|
|
1334
|
+
counts[audit25.severity] += result.violations.length;
|
|
1303
1335
|
}
|
|
1304
1336
|
return counts;
|
|
1305
1337
|
}
|
|
1306
1338
|
function severityPluralLabel(severity) {
|
|
1307
1339
|
switch (severity) {
|
|
1308
1340
|
case "error":
|
|
1309
|
-
return
|
|
1341
|
+
return __12("Errors", "elementor");
|
|
1310
1342
|
case "warning":
|
|
1311
|
-
return
|
|
1343
|
+
return __12("Warnings", "elementor");
|
|
1312
1344
|
case "info":
|
|
1313
|
-
return
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
// src/components/audit-statuses-section.tsx
|
|
1318
|
-
import * as React15 from "react";
|
|
1319
|
-
import { Box as Box11, Divider, Typography as Typography8 } from "@elementor/ui";
|
|
1320
|
-
import { __ as __15, sprintf as sprintf2 } from "@wordpress/i18n";
|
|
1321
|
-
|
|
1322
|
-
// src/components/count-summary-circle.tsx
|
|
1323
|
-
import * as React14 from "react";
|
|
1324
|
-
import { Box as Box10, Chip as Chip2, Typography as Typography7 } from "@elementor/ui";
|
|
1325
|
-
var COUNT_SUMMARY_CIRCLE_SIZE = 64;
|
|
1326
|
-
var COUNT_SUMMARY_BORDER_WIDTH = 4;
|
|
1327
|
-
function chipBorderColor(theme, color) {
|
|
1328
|
-
if (color === "default" || !color) {
|
|
1329
|
-
return theme.palette.text.secondary;
|
|
1345
|
+
return __12("Suggestions", "elementor");
|
|
1330
1346
|
}
|
|
1331
|
-
return theme.palette[color].main;
|
|
1332
|
-
}
|
|
1333
|
-
function CountSummaryCircle({ ariaLabel, color, count, label, onClick }) {
|
|
1334
|
-
return /* @__PURE__ */ React14.createElement(
|
|
1335
|
-
Box10,
|
|
1336
|
-
{
|
|
1337
|
-
"aria-label": ariaLabel,
|
|
1338
|
-
component: "button",
|
|
1339
|
-
onClick,
|
|
1340
|
-
type: "button",
|
|
1341
|
-
sx: {
|
|
1342
|
-
alignItems: "center",
|
|
1343
|
-
background: "none",
|
|
1344
|
-
border: "none",
|
|
1345
|
-
cursor: "pointer",
|
|
1346
|
-
display: "flex",
|
|
1347
|
-
flex: 1,
|
|
1348
|
-
flexDirection: "column",
|
|
1349
|
-
gap: 0.5,
|
|
1350
|
-
padding: 0
|
|
1351
|
-
}
|
|
1352
|
-
},
|
|
1353
|
-
/* @__PURE__ */ React14.createElement(
|
|
1354
|
-
Chip2,
|
|
1355
|
-
{
|
|
1356
|
-
color,
|
|
1357
|
-
label: count,
|
|
1358
|
-
size: "small",
|
|
1359
|
-
variant: "standard",
|
|
1360
|
-
sx: (theme) => ({
|
|
1361
|
-
border: `${COUNT_SUMMARY_BORDER_WIDTH}px solid ${chipBorderColor(theme, color)}`,
|
|
1362
|
-
borderRadius: "50%",
|
|
1363
|
-
height: COUNT_SUMMARY_CIRCLE_SIZE,
|
|
1364
|
-
maxWidth: COUNT_SUMMARY_CIRCLE_SIZE,
|
|
1365
|
-
width: COUNT_SUMMARY_CIRCLE_SIZE,
|
|
1366
|
-
"& .MuiChip-label": {
|
|
1367
|
-
fontSize: theme.typography.body2.fontSize,
|
|
1368
|
-
fontWeight: 700,
|
|
1369
|
-
lineHeight: 1,
|
|
1370
|
-
padding: 0
|
|
1371
|
-
}
|
|
1372
|
-
})
|
|
1373
|
-
}
|
|
1374
|
-
),
|
|
1375
|
-
/* @__PURE__ */ React14.createElement(Typography7, { color: "text.secondary", sx: { textAlign: "center" }, variant: "caption" }, label)
|
|
1376
|
-
);
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
// src/components/audit-statuses-section.tsx
|
|
1380
|
-
var STATUS_ARIA_LABELS = {
|
|
1381
|
-
pass: (count) => sprintf2(
|
|
1382
|
-
/* translators: %d: number of passed audits. */
|
|
1383
|
-
__15("%d passed audits, view all", "elementor"),
|
|
1384
|
-
count
|
|
1385
|
-
),
|
|
1386
|
-
fail: (count) => sprintf2(
|
|
1387
|
-
/* translators: %d: number of failed audit violations. */
|
|
1388
|
-
__15("%d failed audits, view all", "elementor"),
|
|
1389
|
-
count
|
|
1390
|
-
),
|
|
1391
|
-
skipped: (count) => sprintf2(
|
|
1392
|
-
/* translators: %d: number of skipped audits. */
|
|
1393
|
-
__15("%d skipped audits, view all", "elementor"),
|
|
1394
|
-
count
|
|
1395
|
-
)
|
|
1396
|
-
};
|
|
1397
|
-
var STATUS_GROUPS = ["fail", "pass", "skipped"];
|
|
1398
|
-
function AuditStatusesSection({ report, onStatusClick }) {
|
|
1399
|
-
const statusCounts = auditStatusDisplayCounts(report);
|
|
1400
|
-
return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Typography8, { variant: "subtitle1", fontWeight: "bold" }, __15("Audit statuses", "elementor")), /* @__PURE__ */ React15.createElement(Box11, { sx: { display: "flex", justifyContent: "space-around", gap: 2 } }, STATUS_GROUPS.map((status) => /* @__PURE__ */ React15.createElement(
|
|
1401
|
-
CountSummaryCircle,
|
|
1402
|
-
{
|
|
1403
|
-
key: status,
|
|
1404
|
-
ariaLabel: STATUS_ARIA_LABELS[status](statusCounts[status]),
|
|
1405
|
-
color: auditStatusColor(status),
|
|
1406
|
-
count: statusCounts[status],
|
|
1407
|
-
label: auditStatusLabel(status),
|
|
1408
|
-
onClick: () => onStatusClick(status)
|
|
1409
|
-
}
|
|
1410
|
-
))), /* @__PURE__ */ React15.createElement(Divider, null));
|
|
1411
1347
|
}
|
|
1412
1348
|
|
|
1413
1349
|
// src/components/issues-category-row.tsx
|
|
1414
|
-
import * as
|
|
1350
|
+
import * as React14 from "react";
|
|
1415
1351
|
import { ChevronRightIcon } from "@elementor/icons";
|
|
1416
|
-
import { Box as
|
|
1352
|
+
import { Box as Box9, Rotate as Rotate2, Typography as Typography7, useTheme as useTheme2 } from "@elementor/ui";
|
|
1417
1353
|
function IssuesCategoryRow({ category, label, counts, onClick }) {
|
|
1418
1354
|
const isRtl = "rtl" === useTheme2().direction;
|
|
1419
1355
|
const Icon = CATEGORY_ICONS[category];
|
|
1420
|
-
return /* @__PURE__ */
|
|
1421
|
-
|
|
1356
|
+
return /* @__PURE__ */ React14.createElement(
|
|
1357
|
+
Box9,
|
|
1422
1358
|
{
|
|
1423
1359
|
role: "button",
|
|
1424
1360
|
tabIndex: 0,
|
|
@@ -1439,112 +1375,21 @@ function IssuesCategoryRow({ category, label, counts, onClick }) {
|
|
|
1439
1375
|
"&:focus-visible": { outline: "2px solid", outlineColor: "primary.main" }
|
|
1440
1376
|
}
|
|
1441
1377
|
},
|
|
1442
|
-
/* @__PURE__ */
|
|
1443
|
-
/* @__PURE__ */
|
|
1444
|
-
/* @__PURE__ */
|
|
1445
|
-
/* @__PURE__ */
|
|
1446
|
-
);
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
// src/components/severity-filter-chips.tsx
|
|
1450
|
-
import * as React17 from "react";
|
|
1451
|
-
import { Box as Box13, Chip as Chip3 } from "@elementor/ui";
|
|
1452
|
-
import { __ as __16 } from "@wordpress/i18n";
|
|
1453
|
-
function SeverityFilterChips({ selected, onChange }) {
|
|
1454
|
-
return /* @__PURE__ */ React17.createElement(Box13, { sx: { display: "flex", alignItems: "center", gap: 1 } }, /* @__PURE__ */ React17.createElement(
|
|
1455
|
-
FilterChip,
|
|
1456
|
-
{
|
|
1457
|
-
label: __16("All", "elementor"),
|
|
1458
|
-
isSelected: selected === "all",
|
|
1459
|
-
onClick: () => onChange("all")
|
|
1460
|
-
}
|
|
1461
|
-
), ALL_SEVERITIES.map((severity) => /* @__PURE__ */ React17.createElement(
|
|
1462
|
-
FilterChip,
|
|
1463
|
-
{
|
|
1464
|
-
key: severity,
|
|
1465
|
-
label: severityPluralLabel(severity),
|
|
1466
|
-
icon: /* @__PURE__ */ React17.createElement(SeverityIcon, { severity }),
|
|
1467
|
-
isSelected: selected === severity,
|
|
1468
|
-
onClick: () => onChange(severity)
|
|
1469
|
-
}
|
|
1470
|
-
)));
|
|
1471
|
-
}
|
|
1472
|
-
function FilterChip({ label, icon, isSelected, onClick }) {
|
|
1473
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1474
|
-
Chip3,
|
|
1475
|
-
{
|
|
1476
|
-
label,
|
|
1477
|
-
icon,
|
|
1478
|
-
size: "small",
|
|
1479
|
-
variant: "filled",
|
|
1480
|
-
color: "default",
|
|
1481
|
-
onClick,
|
|
1482
|
-
"aria-pressed": isSelected,
|
|
1483
|
-
sx: { bgcolor: isSelected ? "action.selected" : "transparent" }
|
|
1484
|
-
}
|
|
1378
|
+
/* @__PURE__ */ React14.createElement(Icon, { fontSize: "small", color: "action" }),
|
|
1379
|
+
/* @__PURE__ */ React14.createElement(Typography7, { variant: "body2", fontWeight: "bold", sx: { flex: 1 } }, label),
|
|
1380
|
+
/* @__PURE__ */ React14.createElement(Box9, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, ALL_SEVERITIES.filter((s) => counts[s] > 0).map((severity) => /* @__PURE__ */ React14.createElement(Box9, { key: severity, sx: { display: "flex", alignItems: "center", gap: 0.25 } }, /* @__PURE__ */ React14.createElement(SeverityIcon, { severity }), /* @__PURE__ */ React14.createElement(Typography7, { variant: "caption", color: "text.primary", fontWeight: "bold" }, counts[severity])))),
|
|
1381
|
+
/* @__PURE__ */ React14.createElement(Rotate2, { in: isRtl }, /* @__PURE__ */ React14.createElement(ChevronRightIcon, { fontSize: "small", color: "action" }))
|
|
1485
1382
|
);
|
|
1486
1383
|
}
|
|
1487
1384
|
|
|
1488
|
-
// src/components/pages/issues-page.tsx
|
|
1489
|
-
function filterCounts(counts, filter) {
|
|
1490
|
-
if (filter === "all") {
|
|
1491
|
-
return counts;
|
|
1492
|
-
}
|
|
1493
|
-
return { error: 0, warning: 0, info: 0, [filter]: counts[filter] };
|
|
1494
|
-
}
|
|
1495
|
-
function IssuesPage({ report, onCategoryClick, onAllAuditsClick, onStatusClick }) {
|
|
1496
|
-
const [filter, setFilter] = useState4("all");
|
|
1497
|
-
const populatedCategories = getPopulatedCategories(report.categories, ALL_CATEGORIES);
|
|
1498
|
-
const categoryRows = populatedCategories.map((category) => ({ category, counts: filterCounts(countSeverities(report, category), filter) })).filter(({ counts }) => Object.values(counts).some((count) => count > 0));
|
|
1499
|
-
return /* @__PURE__ */ React18.createElement(Box14, { sx: { display: "flex", flexDirection: "column", gap: 4, p: 2 } }, /* @__PURE__ */ React18.createElement(AuditStatusesSection, { report, onStatusClick }), /* @__PURE__ */ React18.createElement(
|
|
1500
|
-
Link,
|
|
1501
|
-
{
|
|
1502
|
-
component: "button",
|
|
1503
|
-
underline: "none",
|
|
1504
|
-
color: "inherit",
|
|
1505
|
-
onClick: onAllAuditsClick,
|
|
1506
|
-
sx: { textAlign: "start" }
|
|
1507
|
-
},
|
|
1508
|
-
/* @__PURE__ */ React18.createElement(Typography10, { variant: "subtitle1", component: "h2" }, __17("All issues", "elementor"))
|
|
1509
|
-
), /* @__PURE__ */ React18.createElement(SeverityFilterChips, { selected: filter, onChange: setFilter }), /* @__PURE__ */ React18.createElement(Box14, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, categoryRows.map(({ category, counts }) => /* @__PURE__ */ React18.createElement(
|
|
1510
|
-
IssuesCategoryRow,
|
|
1511
|
-
{
|
|
1512
|
-
key: category,
|
|
1513
|
-
category,
|
|
1514
|
-
label: CATEGORY_LABELS[category],
|
|
1515
|
-
counts,
|
|
1516
|
-
onClick: () => onCategoryClick(category)
|
|
1517
|
-
}
|
|
1518
|
-
))));
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
// src/components/pages/overview-page.tsx
|
|
1522
|
-
import * as React23 from "react";
|
|
1523
|
-
import { Box as Box19, Chip as Chip4, Typography as Typography15 } from "@elementor/ui";
|
|
1524
|
-
import { __ as __21 } from "@wordpress/i18n";
|
|
1525
|
-
|
|
1526
|
-
// src/utils/score-thresholds.ts
|
|
1527
|
-
import { __ as __18 } from "@wordpress/i18n";
|
|
1528
|
-
var GOOD_THRESHOLD = 90;
|
|
1529
|
-
var OK_THRESHOLD = 50;
|
|
1530
|
-
function getScoreTier(score) {
|
|
1531
|
-
if (score >= GOOD_THRESHOLD) {
|
|
1532
|
-
return { color: "success", label: __18("Good", "elementor") };
|
|
1533
|
-
}
|
|
1534
|
-
if (score >= OK_THRESHOLD) {
|
|
1535
|
-
return { color: "warning", label: __18("Needs work", "elementor") };
|
|
1536
|
-
}
|
|
1537
|
-
return { color: "error", label: __18("At risk", "elementor") };
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
1385
|
// src/components/promotions.tsx
|
|
1541
|
-
import * as
|
|
1542
|
-
import { Box as
|
|
1543
|
-
import { __ as
|
|
1386
|
+
import * as React16 from "react";
|
|
1387
|
+
import { Box as Box11, Divider, Typography as Typography9 } from "@elementor/ui";
|
|
1388
|
+
import { __ as __14 } from "@wordpress/i18n";
|
|
1544
1389
|
|
|
1545
1390
|
// src/register-promotions.ts
|
|
1546
1391
|
import { ElementorCookieIcon, PhotoIcon, ShieldHalfFilledIcon } from "@elementor/icons";
|
|
1547
|
-
import { __ as
|
|
1392
|
+
import { __ as __13, _n, sprintf as sprintf2 } from "@wordpress/i18n";
|
|
1548
1393
|
function firstFailExternalUrl(run) {
|
|
1549
1394
|
return run.result.status === "fail" ? run.result.violations[0]?.externalUrl : void 0;
|
|
1550
1395
|
}
|
|
@@ -1552,7 +1397,7 @@ var PROMOTIONS = [
|
|
|
1552
1397
|
{
|
|
1553
1398
|
auditId: "audits/images-alt-text",
|
|
1554
1399
|
icon: PhotoIcon,
|
|
1555
|
-
ctaLabel:
|
|
1400
|
+
ctaLabel: __13("Fix with Ally", "elementor"),
|
|
1556
1401
|
formatSubtitle: (run) => {
|
|
1557
1402
|
if (run.result.status !== "fail") {
|
|
1558
1403
|
return null;
|
|
@@ -1561,7 +1406,7 @@ var PROMOTIONS = [
|
|
|
1561
1406
|
if (count === 0) {
|
|
1562
1407
|
return null;
|
|
1563
1408
|
}
|
|
1564
|
-
return
|
|
1409
|
+
return sprintf2(
|
|
1565
1410
|
/* translators: %d: number of images missing alt text. */
|
|
1566
1411
|
_n("%d image", "%d images", count, "elementor"),
|
|
1567
1412
|
count
|
|
@@ -1572,21 +1417,21 @@ var PROMOTIONS = [
|
|
|
1572
1417
|
{
|
|
1573
1418
|
auditId: "audits/cookie-policy",
|
|
1574
1419
|
icon: ElementorCookieIcon,
|
|
1575
|
-
ctaLabel:
|
|
1576
|
-
formatSubtitle: (run) => run.result.status === "fail" ?
|
|
1420
|
+
ctaLabel: __13("Fix with Cookiez", "elementor"),
|
|
1421
|
+
formatSubtitle: (run) => run.result.status === "fail" ? __13("Generate cookie policy", "elementor") : null,
|
|
1577
1422
|
getCtaUrl: firstFailExternalUrl
|
|
1578
1423
|
},
|
|
1579
1424
|
{
|
|
1580
1425
|
auditId: "audits/scan-for-cookies",
|
|
1581
1426
|
icon: ElementorCookieIcon,
|
|
1582
|
-
ctaLabel:
|
|
1583
|
-
formatSubtitle: (run) => run.result.status === "fail" ?
|
|
1427
|
+
ctaLabel: __13("Scan", "elementor"),
|
|
1428
|
+
formatSubtitle: (run) => run.result.status === "fail" ? __13("Scan this page for cookies", "elementor") : null,
|
|
1584
1429
|
getCtaUrl: firstFailExternalUrl
|
|
1585
1430
|
},
|
|
1586
1431
|
{
|
|
1587
1432
|
auditId: "audits/images-too-large",
|
|
1588
1433
|
icon: ShieldHalfFilledIcon,
|
|
1589
|
-
ctaLabel:
|
|
1434
|
+
ctaLabel: __13("Optimize all", "elementor"),
|
|
1590
1435
|
formatSubtitle: (run) => {
|
|
1591
1436
|
if (run.result.status !== "fail") {
|
|
1592
1437
|
return null;
|
|
@@ -1595,33 +1440,13 @@ var PROMOTIONS = [
|
|
|
1595
1440
|
if (count === 0) {
|
|
1596
1441
|
return null;
|
|
1597
1442
|
}
|
|
1598
|
-
return
|
|
1443
|
+
return sprintf2(
|
|
1599
1444
|
/* translators: %d: number of oversized images. */
|
|
1600
1445
|
_n("%d image", "%d images", count, "elementor"),
|
|
1601
1446
|
count
|
|
1602
1447
|
);
|
|
1603
1448
|
},
|
|
1604
1449
|
getCtaUrl: firstFailExternalUrl
|
|
1605
|
-
},
|
|
1606
|
-
{
|
|
1607
|
-
auditId: "audits/images-inefficient-format",
|
|
1608
|
-
icon: ShieldHalfFilledIcon,
|
|
1609
|
-
ctaLabel: __19("Optimize all", "elementor"),
|
|
1610
|
-
formatSubtitle: (run) => {
|
|
1611
|
-
if (run.result.status !== "fail") {
|
|
1612
|
-
return null;
|
|
1613
|
-
}
|
|
1614
|
-
const count = run.result.metadata?.inefficientImageFormatCount ?? 0;
|
|
1615
|
-
if (count === 0) {
|
|
1616
|
-
return null;
|
|
1617
|
-
}
|
|
1618
|
-
return sprintf3(
|
|
1619
|
-
/* translators: %d: number of images served in an inefficient format. */
|
|
1620
|
-
_n("%d image", "%d images", count, "elementor"),
|
|
1621
|
-
count
|
|
1622
|
-
);
|
|
1623
|
-
},
|
|
1624
|
-
getCtaUrl: firstFailExternalUrl
|
|
1625
1450
|
}
|
|
1626
1451
|
];
|
|
1627
1452
|
|
|
@@ -1631,11 +1456,11 @@ function findAuditRun(report, auditId) {
|
|
|
1631
1456
|
}
|
|
1632
1457
|
|
|
1633
1458
|
// src/components/promotion-card.tsx
|
|
1634
|
-
import * as
|
|
1635
|
-
import { Box as
|
|
1459
|
+
import * as React15 from "react";
|
|
1460
|
+
import { Box as Box10, Button as Button5, Typography as Typography8 } from "@elementor/ui";
|
|
1636
1461
|
function PromotionCard({ ctaDisabled, ctaLabel, icon: Icon, onCtaClick, subtitle, title }) {
|
|
1637
|
-
return /* @__PURE__ */
|
|
1638
|
-
|
|
1462
|
+
return /* @__PURE__ */ React15.createElement(
|
|
1463
|
+
Box10,
|
|
1639
1464
|
{
|
|
1640
1465
|
sx: {
|
|
1641
1466
|
alignItems: "center",
|
|
@@ -1648,9 +1473,9 @@ function PromotionCard({ ctaDisabled, ctaLabel, icon: Icon, onCtaClick, subtitle
|
|
|
1648
1473
|
py: 1.5
|
|
1649
1474
|
}
|
|
1650
1475
|
},
|
|
1651
|
-
/* @__PURE__ */
|
|
1652
|
-
/* @__PURE__ */
|
|
1653
|
-
/* @__PURE__ */
|
|
1476
|
+
/* @__PURE__ */ React15.createElement(Icon, { fontSize: "small", color: "action" }),
|
|
1477
|
+
/* @__PURE__ */ React15.createElement(Box10, { sx: { display: "flex", flex: 1, flexDirection: "column", gap: 0.25, minWidth: 0 } }, /* @__PURE__ */ React15.createElement(Typography8, { variant: "body2", fontWeight: "bold" }, title), /* @__PURE__ */ React15.createElement(Typography8, { variant: "caption", color: "text.secondary" }, subtitle)),
|
|
1478
|
+
/* @__PURE__ */ React15.createElement(Button5, { variant: "outlined", color: "secondary", size: "small", disabled: ctaDisabled, onClick: onCtaClick }, ctaLabel)
|
|
1654
1479
|
);
|
|
1655
1480
|
}
|
|
1656
1481
|
|
|
@@ -1679,7 +1504,7 @@ function Promotions({ report }) {
|
|
|
1679
1504
|
if (cards.length === 0) {
|
|
1680
1505
|
return null;
|
|
1681
1506
|
}
|
|
1682
|
-
return /* @__PURE__ */
|
|
1507
|
+
return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Divider, null), /* @__PURE__ */ React16.createElement(Typography9, { variant: "subtitle1", fontWeight: "bold" }, __14("Quick actions", "elementor")), /* @__PURE__ */ React16.createElement(Box11, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, cards.map(({ config, ctaUrl, key, run, subtitle }) => /* @__PURE__ */ React16.createElement(
|
|
1683
1508
|
PromotionCard,
|
|
1684
1509
|
{
|
|
1685
1510
|
key,
|
|
@@ -1697,241 +1522,118 @@ function Promotions({ report }) {
|
|
|
1697
1522
|
))));
|
|
1698
1523
|
}
|
|
1699
1524
|
|
|
1700
|
-
// src/components/
|
|
1701
|
-
import * as
|
|
1702
|
-
import {
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
return /* @__PURE__ */ React21.createElement(
|
|
1707
|
-
Box17,
|
|
1708
|
-
{
|
|
1709
|
-
role: onClick ? "button" : void 0,
|
|
1710
|
-
tabIndex: onClick ? 0 : void 0,
|
|
1711
|
-
onClick,
|
|
1712
|
-
onKeyDown: onClick ? onKeyboardClick(onClick) : void 0,
|
|
1713
|
-
sx: {
|
|
1714
|
-
display: "flex",
|
|
1715
|
-
alignItems: "center",
|
|
1716
|
-
gap: 1,
|
|
1717
|
-
cursor: onClick ? "pointer" : "default",
|
|
1718
|
-
outline: "none",
|
|
1719
|
-
"&:focus-visible": { outline: "2px solid", outlineColor: "primary.main", borderRadius: 1 },
|
|
1720
|
-
py: 0.5
|
|
1721
|
-
}
|
|
1722
|
-
},
|
|
1723
|
-
/* @__PURE__ */ React21.createElement(Typography13, { variant: "body2", sx: { minWidth: 96 } }, label),
|
|
1724
|
-
/* @__PURE__ */ React21.createElement(
|
|
1725
|
-
LinearProgress,
|
|
1726
|
-
{
|
|
1727
|
-
variant: "determinate",
|
|
1728
|
-
value: score,
|
|
1729
|
-
color: getScoreTier(score).color,
|
|
1730
|
-
sx: { flex: 1, height: 6, borderRadius: 4, bgcolor: "action.disabledBackground" }
|
|
1731
|
-
}
|
|
1732
|
-
),
|
|
1733
|
-
/* @__PURE__ */ React21.createElement(
|
|
1734
|
-
Typography13,
|
|
1735
|
-
{
|
|
1736
|
-
variant: "body2",
|
|
1737
|
-
color: "text.primary",
|
|
1738
|
-
sx: { minWidth: 24, textAlign: "right", fontWeight: 900 }
|
|
1739
|
-
},
|
|
1740
|
-
score
|
|
1741
|
-
),
|
|
1742
|
-
onClick && /* @__PURE__ */ React21.createElement(Rotate3, { in: isRtl }, /* @__PURE__ */ React21.createElement(ChevronRightIcon2, { fontSize: "small", color: "action" }))
|
|
1743
|
-
);
|
|
1525
|
+
// src/components/severity-summary-cards.tsx
|
|
1526
|
+
import * as React17 from "react";
|
|
1527
|
+
import { Box as Box12, Typography as Typography10 } from "@elementor/ui";
|
|
1528
|
+
function SeveritySummaryCards({ report }) {
|
|
1529
|
+
const counts = countSeverities(report);
|
|
1530
|
+
return /* @__PURE__ */ React17.createElement(Box12, { display: "flex", gap: 1.5 }, ALL_SEVERITIES.map((severity) => /* @__PURE__ */ React17.createElement(SeverityCard, { key: severity, severity, count: counts[severity] })));
|
|
1744
1531
|
}
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
import { Box as Box18, CircularProgress as CircularProgress2, Typography as Typography14 } from "@elementor/ui";
|
|
1749
|
-
var SCORE_CIRCLE_SIZE = 88;
|
|
1750
|
-
var SCORE_CIRCLE_THICKNESS = 3;
|
|
1751
|
-
function ScoreCircle({ color, score }) {
|
|
1752
|
-
const progressColor = color ?? getScoreTier(score).color;
|
|
1753
|
-
return /* @__PURE__ */ React22.createElement(
|
|
1754
|
-
Box18,
|
|
1532
|
+
function SeverityCard({ severity, count }) {
|
|
1533
|
+
return /* @__PURE__ */ React17.createElement(
|
|
1534
|
+
Box12,
|
|
1755
1535
|
{
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
"
|
|
1759
|
-
|
|
1760
|
-
|
|
1536
|
+
display: "flex",
|
|
1537
|
+
flex: 1,
|
|
1538
|
+
flexDirection: "column",
|
|
1539
|
+
gap: 1,
|
|
1540
|
+
bgcolor: "action.hover",
|
|
1541
|
+
borderRadius: 1.5,
|
|
1542
|
+
px: 1.5,
|
|
1543
|
+
py: 1
|
|
1761
1544
|
},
|
|
1762
|
-
/* @__PURE__ */
|
|
1763
|
-
|
|
1764
|
-
{
|
|
1765
|
-
variant: "determinate",
|
|
1766
|
-
value: 100,
|
|
1767
|
-
size: SCORE_CIRCLE_SIZE,
|
|
1768
|
-
thickness: SCORE_CIRCLE_THICKNESS,
|
|
1769
|
-
sx: { color: "action.disabledBackground" }
|
|
1770
|
-
}
|
|
1771
|
-
),
|
|
1772
|
-
/* @__PURE__ */ React22.createElement(
|
|
1773
|
-
CircularProgress2,
|
|
1774
|
-
{
|
|
1775
|
-
variant: "determinate",
|
|
1776
|
-
value: score,
|
|
1777
|
-
size: SCORE_CIRCLE_SIZE,
|
|
1778
|
-
thickness: SCORE_CIRCLE_THICKNESS,
|
|
1779
|
-
color: progressColor,
|
|
1780
|
-
sx: { position: "absolute", left: 0 }
|
|
1781
|
-
}
|
|
1782
|
-
),
|
|
1783
|
-
/* @__PURE__ */ React22.createElement(
|
|
1784
|
-
Box18,
|
|
1785
|
-
{
|
|
1786
|
-
sx: {
|
|
1787
|
-
position: "absolute",
|
|
1788
|
-
inset: 0,
|
|
1789
|
-
display: "flex",
|
|
1790
|
-
alignItems: "center",
|
|
1791
|
-
justifyContent: "center"
|
|
1792
|
-
}
|
|
1793
|
-
},
|
|
1794
|
-
/* @__PURE__ */ React22.createElement(
|
|
1795
|
-
Typography14,
|
|
1796
|
-
{
|
|
1797
|
-
variant: "h4",
|
|
1798
|
-
component: "span",
|
|
1799
|
-
color: "text.primary",
|
|
1800
|
-
sx: { fontWeight: 700, lineHeight: 1 }
|
|
1801
|
-
},
|
|
1802
|
-
score
|
|
1803
|
-
)
|
|
1804
|
-
)
|
|
1545
|
+
/* @__PURE__ */ React17.createElement(SeverityIcon, { severity }),
|
|
1546
|
+
/* @__PURE__ */ React17.createElement(Box12, { display: "flex", flexDirection: "column" }, /* @__PURE__ */ React17.createElement(Typography10, { variant: "h5", fontWeight: 700, component: "span" }, count), /* @__PURE__ */ React17.createElement(Typography10, { variant: "caption", color: "text.secondary" }, severityPluralLabel(severity)))
|
|
1805
1547
|
);
|
|
1806
1548
|
}
|
|
1807
1549
|
|
|
1808
1550
|
// src/components/pages/overview-page.tsx
|
|
1809
1551
|
function OverviewPage({ onCategoryClick, report }) {
|
|
1810
1552
|
const populatedCategories = getPopulatedCategories(report.categories, ALL_CATEGORIES);
|
|
1811
|
-
const
|
|
1812
|
-
return /* @__PURE__ */
|
|
1813
|
-
|
|
1814
|
-
{
|
|
1815
|
-
label: overallScore.label,
|
|
1816
|
-
color: overallScore.color,
|
|
1817
|
-
variant: "standard",
|
|
1818
|
-
size: "small",
|
|
1819
|
-
sx: { fontWeight: 600, alignSelf: "flex-start" }
|
|
1820
|
-
}
|
|
1821
|
-
), /* @__PURE__ */ React23.createElement(Typography15, { variant: "body2", color: "text.secondary" }, __21("Overall score", "elementor")))), /* @__PURE__ */ React23.createElement(Box19, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, populatedCategories.map((category) => /* @__PURE__ */ React23.createElement(
|
|
1822
|
-
ScoreBar,
|
|
1553
|
+
const categoryRows = populatedCategories.map((category) => ({ category, counts: countSeverities(report, category) })).filter(({ counts }) => Object.values(counts).some((count) => count > 0));
|
|
1554
|
+
return /* @__PURE__ */ React18.createElement(Box13, { display: "flex", flexDirection: "column", gap: 3, p: 2 }, /* @__PURE__ */ React18.createElement(SeveritySummaryCards, { report }), /* @__PURE__ */ React18.createElement(Box13, { display: "flex", flexDirection: "column", gap: 1 }, /* @__PURE__ */ React18.createElement(Typography11, { variant: "subtitle1", component: "h2" }, __15("All issues", "elementor")), /* @__PURE__ */ React18.createElement(Box13, { display: "flex", flexDirection: "column", gap: 1 }, categoryRows.map(({ category, counts }) => /* @__PURE__ */ React18.createElement(
|
|
1555
|
+
IssuesCategoryRow,
|
|
1823
1556
|
{
|
|
1824
1557
|
key: category,
|
|
1558
|
+
category,
|
|
1825
1559
|
label: CATEGORY_LABELS[category],
|
|
1826
|
-
|
|
1560
|
+
counts,
|
|
1827
1561
|
onClick: () => onCategoryClick(category)
|
|
1828
1562
|
}
|
|
1829
|
-
))), /* @__PURE__ */
|
|
1563
|
+
)))), /* @__PURE__ */ React18.createElement(Promotions, { report }));
|
|
1830
1564
|
}
|
|
1831
1565
|
|
|
1832
1566
|
// src/components/report-shell.tsx
|
|
1833
|
-
function activeTab(page) {
|
|
1834
|
-
if (page === "overview") {
|
|
1835
|
-
return "overview";
|
|
1836
|
-
}
|
|
1837
|
-
if (page === "issues") {
|
|
1838
|
-
return "issues";
|
|
1839
|
-
}
|
|
1840
|
-
return page.backTo;
|
|
1841
|
-
}
|
|
1842
|
-
function isAllAuditsPage(page) {
|
|
1843
|
-
return typeof page === "object" && "page" in page && page.page === "all-audits";
|
|
1844
|
-
}
|
|
1845
1567
|
function isCategoryPage(page) {
|
|
1846
1568
|
return typeof page === "object" && "category" in page;
|
|
1847
1569
|
}
|
|
1848
1570
|
function ReportShell({ report }) {
|
|
1849
|
-
const [activePage, setActivePage] =
|
|
1850
|
-
const
|
|
1851
|
-
const
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
return /* @__PURE__ */ React24.createElement(Box20, { sx: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0 } }, /* @__PURE__ */ React24.createElement(Box20, { sx: { flexShrink: 0 } }, /* @__PURE__ */ React24.createElement(
|
|
1866
|
-
Tabs,
|
|
1571
|
+
const [activePage, setActivePage] = useState4("overview");
|
|
1572
|
+
const openCategory = (category) => setActivePage({ category });
|
|
1573
|
+
const backToOverview = () => setActivePage("overview");
|
|
1574
|
+
return /* @__PURE__ */ React19.createElement(Box14, { sx: { flex: 1, minHeight: 0, overflowY: "auto" } }, activePage === "overview" && /* @__PURE__ */ React19.createElement(OverviewPage, { report, onCategoryClick: openCategory }), isCategoryPage(activePage) && /* @__PURE__ */ React19.createElement(CategoryPage, { category: activePage.category, report, onBack: backToOverview }));
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
// src/components/rescan-button.tsx
|
|
1578
|
+
import * as React20 from "react";
|
|
1579
|
+
import { useFloatingPanelZIndex as useFloatingPanelZIndex3 } from "@elementor/editor-floating-panels";
|
|
1580
|
+
import { ReloadIcon } from "@elementor/icons";
|
|
1581
|
+
import { Badge as Badge2, Button as Button6, Tooltip as Tooltip4 } from "@elementor/ui";
|
|
1582
|
+
import { __ as __16 } from "@wordpress/i18n";
|
|
1583
|
+
function RescanButton({ hasScanned, isStale, disabled, onClick }) {
|
|
1584
|
+
const panelZIndex = useFloatingPanelZIndex3(AUDIT_PANEL_ID);
|
|
1585
|
+
return /* @__PURE__ */ React20.createElement(
|
|
1586
|
+
Tooltip4,
|
|
1867
1587
|
{
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
textColor: "secondary",
|
|
1872
|
-
indicatorColor: "secondary",
|
|
1873
|
-
size: "small",
|
|
1874
|
-
centered: true,
|
|
1875
|
-
variant: "fullWidth"
|
|
1588
|
+
title: __16("Page content changed - rescan advised", "elementor"),
|
|
1589
|
+
disableHoverListener: !isStale,
|
|
1590
|
+
PopperProps: { sx: { zIndex: panelZIndex } }
|
|
1876
1591
|
},
|
|
1877
|
-
/* @__PURE__ */
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
onCategoryClick: (category) => openCategory(category, "issues"),
|
|
1890
|
-
onAllAuditsClick: () => openAllAudits(),
|
|
1891
|
-
onStatusClick: (status) => openAllAudits(status)
|
|
1892
|
-
}
|
|
1893
|
-
), isAllAuditsPage(activePage) && /* @__PURE__ */ React24.createElement(
|
|
1894
|
-
AllAuditsPage,
|
|
1895
|
-
{
|
|
1896
|
-
report,
|
|
1897
|
-
initialExpandedStatus: activePage.expand,
|
|
1898
|
-
onBack: backFromSubPage
|
|
1899
|
-
}
|
|
1900
|
-
), isCategoryPage(activePage) && /* @__PURE__ */ React24.createElement(CategoryPage, { category: activePage.category, report, onBack: backFromSubPage })));
|
|
1592
|
+
/* @__PURE__ */ React20.createElement(Badge2, { variant: "dot", color: "warning", invisible: !isStale, overlap: "rectangular" }, /* @__PURE__ */ React20.createElement(
|
|
1593
|
+
Button6,
|
|
1594
|
+
{
|
|
1595
|
+
variant: "contained",
|
|
1596
|
+
size: "small",
|
|
1597
|
+
startIcon: hasScanned ? /* @__PURE__ */ React20.createElement(ReloadIcon, { fontSize: "small" }) : void 0,
|
|
1598
|
+
onClick,
|
|
1599
|
+
disabled
|
|
1600
|
+
},
|
|
1601
|
+
hasScanned ? __16("Rescan", "elementor") : __16("Run page audit", "elementor")
|
|
1602
|
+
))
|
|
1603
|
+
);
|
|
1901
1604
|
}
|
|
1902
1605
|
|
|
1903
1606
|
// src/components/audit-panel.tsx
|
|
1904
1607
|
function AuditPanel() {
|
|
1905
|
-
const { status, report, error, run } = useAuditReport();
|
|
1906
|
-
const
|
|
1907
|
-
const onRun = () => run(
|
|
1608
|
+
const { status, report, error, isStale, run } = useAuditReport();
|
|
1609
|
+
const hostDocumentId = getHostDocumentId3() ?? 0;
|
|
1610
|
+
const onRun = () => run(hostDocumentId);
|
|
1908
1611
|
const lastScanLabel = report ? new Date(report.runAt).toLocaleTimeString() : null;
|
|
1909
|
-
return /* @__PURE__ */
|
|
1612
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(
|
|
1910
1613
|
FloatingPanelHeader,
|
|
1911
1614
|
{
|
|
1912
|
-
panelId:
|
|
1913
|
-
title:
|
|
1914
|
-
badge:
|
|
1615
|
+
panelId: AUDIT_PANEL_ID,
|
|
1616
|
+
title: __17("Page Audit", "elementor"),
|
|
1617
|
+
badge: __17("Beta", "elementor"),
|
|
1915
1618
|
titleVariant: "subtitle2"
|
|
1916
1619
|
}
|
|
1917
|
-
), /* @__PURE__ */
|
|
1620
|
+
), /* @__PURE__ */ React21.createElement(
|
|
1918
1621
|
FloatingPanelBody,
|
|
1919
1622
|
{
|
|
1920
1623
|
sx: status === "ready" ? { display: "flex", flexDirection: "column", overflow: "hidden", minHeight: 0 } : void 0
|
|
1921
1624
|
},
|
|
1922
|
-
status === "idle" && /* @__PURE__ */
|
|
1923
|
-
status === "loading" && /* @__PURE__ */
|
|
1924
|
-
status === "error" && /* @__PURE__ */
|
|
1925
|
-
status === "ready" && report && /* @__PURE__ */
|
|
1926
|
-
), /* @__PURE__ */
|
|
1927
|
-
|
|
1625
|
+
status === "idle" && /* @__PURE__ */ React21.createElement(WelcomePage, null),
|
|
1626
|
+
status === "loading" && /* @__PURE__ */ React21.createElement(LoadingPage, null),
|
|
1627
|
+
status === "error" && /* @__PURE__ */ React21.createElement(ErrorPage, { message: error ?? "", onRetry: onRun }),
|
|
1628
|
+
status === "ready" && report && /* @__PURE__ */ React21.createElement(ReportShell, { report })
|
|
1629
|
+
), /* @__PURE__ */ React21.createElement(FloatingPanelFooter, null, lastScanLabel ? /* @__PURE__ */ React21.createElement(Typography12, { variant: "caption", sx: { flex: 1 } }, __17("Last scan:", "elementor"), " ", lastScanLabel) : /* @__PURE__ */ React21.createElement(Box15, { sx: { flex: 1 } }), lastScanLabel && /* @__PURE__ */ React21.createElement(AuditFeedback, null), /* @__PURE__ */ React21.createElement(
|
|
1630
|
+
RescanButton,
|
|
1928
1631
|
{
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
}
|
|
1934
|
-
lastScanLabel ? __23("Re-scan", "elementor") : __23("Run page audit", "elementor")
|
|
1632
|
+
hasScanned: Boolean(lastScanLabel),
|
|
1633
|
+
isStale,
|
|
1634
|
+
disabled: status === "loading" || hostDocumentId === 0,
|
|
1635
|
+
onClick: onRun
|
|
1636
|
+
}
|
|
1935
1637
|
)));
|
|
1936
1638
|
}
|
|
1937
1639
|
|
|
@@ -1956,8 +1658,8 @@ function useAuditToggleProps() {
|
|
|
1956
1658
|
const { isOpen } = auditPanel.useFloatingPanelStatus();
|
|
1957
1659
|
const { toggle } = auditPanel.useFloatingPanelActions();
|
|
1958
1660
|
return {
|
|
1959
|
-
title:
|
|
1960
|
-
icon:
|
|
1661
|
+
title: __18("Audit Page", "elementor"),
|
|
1662
|
+
icon: AuditToggleIcon,
|
|
1961
1663
|
selected: isOpen,
|
|
1962
1664
|
onClick: () => toggle()
|
|
1963
1665
|
};
|
|
@@ -1974,15 +1676,15 @@ function registerAppBarAuditsToggle() {
|
|
|
1974
1676
|
}
|
|
1975
1677
|
|
|
1976
1678
|
// src/audits/accessibility-policy.ts
|
|
1977
|
-
import { __ as
|
|
1679
|
+
import { __ as __19 } from "@wordpress/i18n";
|
|
1978
1680
|
var audit = {
|
|
1979
1681
|
id: "audits/accessibility-policy",
|
|
1980
|
-
title:
|
|
1981
|
-
description:
|
|
1682
|
+
title: __19("Accessibility policy", "elementor"),
|
|
1683
|
+
description: __19(
|
|
1982
1684
|
"An accessibility policy demonstrates your commitment to digital inclusion and may be legally required in some regions.",
|
|
1983
1685
|
"elementor"
|
|
1984
1686
|
),
|
|
1985
|
-
fixHint:
|
|
1687
|
+
fixHint: __19("Install the Ally plugin to add an accessibility policy to your website.", "elementor"),
|
|
1986
1688
|
categories: ["compliance"],
|
|
1987
1689
|
severity: "info",
|
|
1988
1690
|
weight: 1,
|
|
@@ -1995,7 +1697,7 @@ var audit = {
|
|
|
1995
1697
|
violations: [
|
|
1996
1698
|
{
|
|
1997
1699
|
auditId: audit.id,
|
|
1998
|
-
label:
|
|
1700
|
+
label: __19("Ally plugin is not installed or active.", "elementor"),
|
|
1999
1701
|
externalUrl: ctx.pageContext.ally_plugin_url
|
|
2000
1702
|
}
|
|
2001
1703
|
]
|
|
@@ -2004,15 +1706,15 @@ var audit = {
|
|
|
2004
1706
|
};
|
|
2005
1707
|
|
|
2006
1708
|
// src/audits/accessibility-statement.ts
|
|
2007
|
-
import { __ as
|
|
1709
|
+
import { __ as __20 } from "@wordpress/i18n";
|
|
2008
1710
|
var audit2 = {
|
|
2009
1711
|
id: "audits/accessibility-statement",
|
|
2010
|
-
title:
|
|
2011
|
-
description:
|
|
1712
|
+
title: __20("Create an accessibility statement", "elementor"),
|
|
1713
|
+
description: __20(
|
|
2012
1714
|
"An accessibility statement showcases your efforts to create an inclusive online space, highlighting helpful features and a commitment to accessibility.",
|
|
2013
1715
|
"elementor"
|
|
2014
1716
|
),
|
|
2015
|
-
fixHint:
|
|
1717
|
+
fixHint: __20("Use Ally to create and publish an accessibility statement for your site.", "elementor"),
|
|
2016
1718
|
categories: ["accessibility"],
|
|
2017
1719
|
severity: "info",
|
|
2018
1720
|
weight: 1,
|
|
@@ -2026,11 +1728,11 @@ var audit2 = {
|
|
|
2026
1728
|
violations: [
|
|
2027
1729
|
{
|
|
2028
1730
|
auditId: audit2.id,
|
|
2029
|
-
label:
|
|
1731
|
+
label: __20("No accessibility statement has been created for this site.", "elementor"),
|
|
2030
1732
|
externalUrl: isReady ? ctx.pageContext.ally_accessibility_statement_url : ctx.pageContext.ally_plugin_url,
|
|
2031
|
-
ctaLabel:
|
|
2032
|
-
secondaryCtaLabel:
|
|
2033
|
-
secondaryCtaUrl: "https://
|
|
1733
|
+
ctaLabel: __20("Create", "elementor"),
|
|
1734
|
+
secondaryCtaLabel: __20("Learn more", "elementor"),
|
|
1735
|
+
secondaryCtaUrl: "https://elementor.com/help/start-using-ally/#statement"
|
|
2034
1736
|
}
|
|
2035
1737
|
]
|
|
2036
1738
|
};
|
|
@@ -2038,7 +1740,7 @@ var audit2 = {
|
|
|
2038
1740
|
};
|
|
2039
1741
|
|
|
2040
1742
|
// src/audits/accessibility-widget.ts
|
|
2041
|
-
import { __ as
|
|
1743
|
+
import { __ as __21 } from "@wordpress/i18n";
|
|
2042
1744
|
|
|
2043
1745
|
// src/utils/scan-accessibility-widgets.ts
|
|
2044
1746
|
var ACCESSIBILITY_WIDGET_SCRIPT_SOURCES = ["cdn.elementor.com/a11y/widget.js"];
|
|
@@ -2049,18 +1751,18 @@ function hasAccessibilityWidgetScript(html) {
|
|
|
2049
1751
|
// src/audits/accessibility-widget.ts
|
|
2050
1752
|
var audit3 = {
|
|
2051
1753
|
id: "audits/accessibility-widget",
|
|
2052
|
-
title:
|
|
2053
|
-
description:
|
|
2054
|
-
fixHint:
|
|
1754
|
+
title: __21("Add an accessibility widget", "elementor"),
|
|
1755
|
+
description: __21("Make your site more inclusive by adding an accessibility widget.", "elementor"),
|
|
1756
|
+
fixHint: __21("Activate Ally\u2019s accessibility widget to give visitors on-page accessibility tools.", "elementor"),
|
|
2055
1757
|
categories: ["accessibility"],
|
|
2056
1758
|
severity: "info",
|
|
2057
1759
|
weight: 1,
|
|
2058
1760
|
evaluate: (ctx) => {
|
|
2059
1761
|
if (!ctx.pageContext.frontend_url) {
|
|
2060
|
-
return { status: "skipped", reason:
|
|
1762
|
+
return { status: "skipped", reason: __21("Page is not published.", "elementor") };
|
|
2061
1763
|
}
|
|
2062
1764
|
if (!ctx.renderedHtml) {
|
|
2063
|
-
return { status: "skipped", reason:
|
|
1765
|
+
return { status: "skipped", reason: __21("Could not fetch the published page.", "elementor") };
|
|
2064
1766
|
}
|
|
2065
1767
|
if (hasAccessibilityWidgetScript(ctx.renderedHtml)) {
|
|
2066
1768
|
return { status: "pass" };
|
|
@@ -2071,9 +1773,9 @@ var audit3 = {
|
|
|
2071
1773
|
violations: [
|
|
2072
1774
|
{
|
|
2073
1775
|
auditId: audit3.id,
|
|
2074
|
-
label:
|
|
1776
|
+
label: __21("No accessibility widget is active on this site.", "elementor"),
|
|
2075
1777
|
externalUrl: isReady ? ctx.pageContext.ally_widget_settings_url : ctx.pageContext.ally_plugin_url,
|
|
2076
|
-
ctaLabel:
|
|
1778
|
+
ctaLabel: __21("Activate", "elementor")
|
|
2077
1779
|
}
|
|
2078
1780
|
]
|
|
2079
1781
|
};
|
|
@@ -2081,15 +1783,15 @@ var audit3 = {
|
|
|
2081
1783
|
};
|
|
2082
1784
|
|
|
2083
1785
|
// src/audits/cookie-policy.ts
|
|
2084
|
-
import { __ as
|
|
1786
|
+
import { __ as __22 } from "@wordpress/i18n";
|
|
2085
1787
|
var audit4 = {
|
|
2086
1788
|
id: "audits/cookie-policy",
|
|
2087
|
-
title:
|
|
2088
|
-
description:
|
|
1789
|
+
title: __22("Cookie policy", "elementor"),
|
|
1790
|
+
description: __22(
|
|
2089
1791
|
"A cookie policy is required by privacy regulations such as GDPR (EU) or CCPA (US) to inform visitors about tracking and data collection.",
|
|
2090
1792
|
"elementor"
|
|
2091
1793
|
),
|
|
2092
|
-
fixHint:
|
|
1794
|
+
fixHint: __22("Install the Cookiez plugin to add a cookie policy to your website.", "elementor"),
|
|
2093
1795
|
categories: ["compliance"],
|
|
2094
1796
|
severity: "info",
|
|
2095
1797
|
weight: 1,
|
|
@@ -2102,8 +1804,9 @@ var audit4 = {
|
|
|
2102
1804
|
violations: [
|
|
2103
1805
|
{
|
|
2104
1806
|
auditId: audit4.id,
|
|
2105
|
-
label:
|
|
2106
|
-
externalUrl: ctx.pageContext.cookiez_plugin_url
|
|
1807
|
+
label: __22("Cookiez plugin is not installed or active.", "elementor"),
|
|
1808
|
+
externalUrl: ctx.pageContext.cookiez_plugin_url,
|
|
1809
|
+
ctaLabel: __22("Set up cookie consent", "elementor")
|
|
2107
1810
|
}
|
|
2108
1811
|
]
|
|
2109
1812
|
};
|
|
@@ -2112,7 +1815,7 @@ var audit4 = {
|
|
|
2112
1815
|
|
|
2113
1816
|
// src/audits/deep-nesting.ts
|
|
2114
1817
|
import { getWidgetsCache } from "@elementor/editor-elements";
|
|
2115
|
-
import { __ as
|
|
1818
|
+
import { __ as __23 } from "@wordpress/i18n";
|
|
2116
1819
|
var MAX_NESTING_DEPTH = 6;
|
|
2117
1820
|
function isNestingElement(node, widgetsCache) {
|
|
2118
1821
|
if (node.elType === "container") {
|
|
@@ -2122,18 +1825,18 @@ function isNestingElement(node, widgetsCache) {
|
|
|
2122
1825
|
}
|
|
2123
1826
|
var audit5 = {
|
|
2124
1827
|
id: "audits/deep-nesting",
|
|
2125
|
-
title:
|
|
2126
|
-
description:
|
|
1828
|
+
title: __23("Deep container nesting", "elementor"),
|
|
1829
|
+
description: __23(
|
|
2127
1830
|
"Container nesting exceeds the recommended depth. Deep DOM trees hurt rendering performance and readability.",
|
|
2128
1831
|
"elementor"
|
|
2129
1832
|
),
|
|
2130
|
-
fixHint:
|
|
1833
|
+
fixHint: __23("Flatten the layout by removing unnecessary wrapper containers.", "elementor"),
|
|
2131
1834
|
categories: ["performance", "best-practices"],
|
|
2132
1835
|
severity: "warning",
|
|
2133
1836
|
weight: 5,
|
|
2134
1837
|
evaluate: (ctx) => {
|
|
2135
1838
|
if (ctx.elements.tree.length === 0) {
|
|
2136
|
-
return { status: "skipped", reason:
|
|
1839
|
+
return { status: "skipped", reason: __23("No elements", "elementor") };
|
|
2137
1840
|
}
|
|
2138
1841
|
const widgetsCache = getWidgetsCache();
|
|
2139
1842
|
const violations = [];
|
|
@@ -2147,7 +1850,7 @@ var audit5 = {
|
|
|
2147
1850
|
auditId: audit5.id,
|
|
2148
1851
|
elementId: node.id,
|
|
2149
1852
|
targetHint: "element-settings",
|
|
2150
|
-
label:
|
|
1853
|
+
label: __23("Container nesting is too deep.", "elementor")
|
|
2151
1854
|
});
|
|
2152
1855
|
}
|
|
2153
1856
|
});
|
|
@@ -2156,15 +1859,15 @@ var audit5 = {
|
|
|
2156
1859
|
};
|
|
2157
1860
|
|
|
2158
1861
|
// src/audits/default-design-system.ts
|
|
2159
|
-
import { __ as
|
|
1862
|
+
import { __ as __24 } from "@wordpress/i18n";
|
|
2160
1863
|
var audit6 = {
|
|
2161
1864
|
id: "audits/default-design-system",
|
|
2162
|
-
title:
|
|
2163
|
-
description:
|
|
1865
|
+
title: __24("Default website kit", "elementor"),
|
|
1866
|
+
description: __24(
|
|
2164
1867
|
"Your website is using the default design system colors and fonts. Custom branding makes the website feel uniquely yours.",
|
|
2165
1868
|
"elementor"
|
|
2166
1869
|
),
|
|
2167
|
-
fixHint:
|
|
1870
|
+
fixHint: __24("Open Site Settings and customize your kit (colors, fonts, layout).", "elementor"),
|
|
2168
1871
|
categories: ["best-practices"],
|
|
2169
1872
|
severity: "info",
|
|
2170
1873
|
weight: 1,
|
|
@@ -2177,7 +1880,7 @@ var audit6 = {
|
|
|
2177
1880
|
violations: [
|
|
2178
1881
|
{
|
|
2179
1882
|
auditId: audit6.id,
|
|
2180
|
-
label:
|
|
1883
|
+
label: __24("Kit appears unchanged from default.", "elementor"),
|
|
2181
1884
|
targetHint: "site-settings"
|
|
2182
1885
|
}
|
|
2183
1886
|
]
|
|
@@ -2187,16 +1890,16 @@ var audit6 = {
|
|
|
2187
1890
|
|
|
2188
1891
|
// src/audits/deprecated-widgets.ts
|
|
2189
1892
|
import { getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
|
|
2190
|
-
import { __ as
|
|
1893
|
+
import { __ as __25 } from "@wordpress/i18n";
|
|
2191
1894
|
var DEPRECATION_CONTROL_NAME = "deprecation_message";
|
|
2192
1895
|
var audit7 = {
|
|
2193
1896
|
id: "audits/deprecated-widgets",
|
|
2194
|
-
title:
|
|
2195
|
-
description:
|
|
1897
|
+
title: __25("Deprecated widgets", "elementor"),
|
|
1898
|
+
description: __25(
|
|
2196
1899
|
"Deprecated widgets should not be used. For better capabilities use the recommended replacement.",
|
|
2197
1900
|
"elementor"
|
|
2198
1901
|
),
|
|
2199
|
-
fixHint:
|
|
1902
|
+
fixHint: __25("Replace each deprecated widget with the recommended new widget shown in its panel.", "elementor"),
|
|
2200
1903
|
categories: ["best-practices", "performance"],
|
|
2201
1904
|
severity: "warning",
|
|
2202
1905
|
weight: 7,
|
|
@@ -2223,7 +1926,7 @@ var audit7 = {
|
|
|
2223
1926
|
auditId: audit7.id,
|
|
2224
1927
|
elementId: node.id,
|
|
2225
1928
|
targetHint: "element-settings",
|
|
2226
|
-
label:
|
|
1929
|
+
label: __25("Using deprecated widget.", "elementor")
|
|
2227
1930
|
});
|
|
2228
1931
|
});
|
|
2229
1932
|
return violations.length === 0 ? { status: "pass" } : { status: "fail", violations };
|
|
@@ -2231,7 +1934,7 @@ var audit7 = {
|
|
|
2231
1934
|
};
|
|
2232
1935
|
|
|
2233
1936
|
// src/audits/google-consent-mode.ts
|
|
2234
|
-
import { __ as
|
|
1937
|
+
import { __ as __26 } from "@wordpress/i18n";
|
|
2235
1938
|
|
|
2236
1939
|
// src/utils/scan-consent-signals.ts
|
|
2237
1940
|
var GOOGLE_TRACKING_PATTERNS = [
|
|
@@ -2254,12 +1957,12 @@ function hasConsentDefaultCall(html) {
|
|
|
2254
1957
|
// src/audits/google-consent-mode.ts
|
|
2255
1958
|
var audit8 = {
|
|
2256
1959
|
id: "audits/google-consent-mode",
|
|
2257
|
-
title:
|
|
2258
|
-
description:
|
|
1960
|
+
title: __26("Google Consent Mode", "elementor"),
|
|
1961
|
+
description: __26(
|
|
2259
1962
|
"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.",
|
|
2260
1963
|
"elementor"
|
|
2261
1964
|
),
|
|
2262
|
-
fixHint:
|
|
1965
|
+
fixHint: __26(
|
|
2263
1966
|
"Turn on Google Consent Mode in your cookie consent plugin so Google tags respect visitor consent choices.",
|
|
2264
1967
|
"elementor"
|
|
2265
1968
|
),
|
|
@@ -2268,18 +1971,18 @@ var audit8 = {
|
|
|
2268
1971
|
weight: 1,
|
|
2269
1972
|
evaluate: (ctx) => {
|
|
2270
1973
|
if (!ctx.pageContext.frontend_url) {
|
|
2271
|
-
return { status: "skipped", reason:
|
|
1974
|
+
return { status: "skipped", reason: __26("Page is not published.", "elementor") };
|
|
2272
1975
|
}
|
|
2273
1976
|
if (!ctx.renderedHtml) {
|
|
2274
|
-
return { status: "skipped", reason:
|
|
1977
|
+
return { status: "skipped", reason: __26("Could not fetch the published page.", "elementor") };
|
|
2275
1978
|
}
|
|
2276
1979
|
if (!hasGoogleTracking(ctx.renderedHtml)) {
|
|
2277
|
-
return { status: "skipped", reason:
|
|
1980
|
+
return { status: "skipped", reason: __26("No Google tracking product detected.", "elementor") };
|
|
2278
1981
|
}
|
|
2279
1982
|
if (hasConsentDefaultCall(ctx.renderedHtml)) {
|
|
2280
1983
|
return { status: "pass" };
|
|
2281
1984
|
}
|
|
2282
|
-
const label =
|
|
1985
|
+
const label = __26("No Google Consent Mode signal was found on the page.", "elementor");
|
|
2283
1986
|
const isCookiezReady = ctx.pageContext.cookiez_plugin_installed && ctx.pageContext.cookiez_plugin_active;
|
|
2284
1987
|
if (isCookiezReady) {
|
|
2285
1988
|
return {
|
|
@@ -2288,7 +1991,7 @@ var audit8 = {
|
|
|
2288
1991
|
{
|
|
2289
1992
|
auditId: audit8.id,
|
|
2290
1993
|
label,
|
|
2291
|
-
ctaLabel:
|
|
1994
|
+
ctaLabel: __26("Enable", "elementor"),
|
|
2292
1995
|
externalUrl: ctx.pageContext.cookiez_consent_mode_settings_url
|
|
2293
1996
|
}
|
|
2294
1997
|
]
|
|
@@ -2308,7 +2011,7 @@ var audit8 = {
|
|
|
2308
2011
|
};
|
|
2309
2012
|
|
|
2310
2013
|
// src/audits/heading-structure.ts
|
|
2311
|
-
import { __ as
|
|
2014
|
+
import { __ as __27 } from "@wordpress/i18n";
|
|
2312
2015
|
var HEADING_LEVELS = ["h1", "h2", "h3", "h4", "h5", "h6"];
|
|
2313
2016
|
var HEADING_CONTROLS_REGISTRY = {
|
|
2314
2017
|
// Core
|
|
@@ -2486,27 +2189,27 @@ function extractPageHeadings(tree) {
|
|
|
2486
2189
|
}
|
|
2487
2190
|
var audit9 = {
|
|
2488
2191
|
id: "audits/heading-structure",
|
|
2489
|
-
title:
|
|
2490
|
-
description:
|
|
2491
|
-
fixHint:
|
|
2192
|
+
title: __27("Heading structure", "elementor"),
|
|
2193
|
+
description: __27("Pages should have exactly one H1 and a non-skipping heading order.", "elementor"),
|
|
2194
|
+
fixHint: __27("Ensure your page has one H1 and that heading levels do not skip (no H2 \u2192 H4).", "elementor"),
|
|
2492
2195
|
categories: ["seo", "accessibility"],
|
|
2493
2196
|
severity: "error",
|
|
2494
2197
|
weight: 10,
|
|
2495
2198
|
evaluate: (ctx) => {
|
|
2496
2199
|
if (ctx.elements.tree.length === 0) {
|
|
2497
|
-
return { status: "skipped", reason:
|
|
2200
|
+
return { status: "skipped", reason: __27("No elements", "elementor") };
|
|
2498
2201
|
}
|
|
2499
2202
|
const headings = extractPageHeadings(ctx.elements.tree);
|
|
2500
2203
|
const violations = [];
|
|
2501
2204
|
if (headings.length === 0) {
|
|
2502
2205
|
violations.push({
|
|
2503
2206
|
auditId: audit9.id,
|
|
2504
|
-
label:
|
|
2207
|
+
label: __27("No headings found on the page.", "elementor")
|
|
2505
2208
|
});
|
|
2506
2209
|
} else {
|
|
2507
2210
|
const h1Count = headings.filter((h) => h.level === 1).length;
|
|
2508
2211
|
if (h1Count === 0) {
|
|
2509
|
-
violations.push({ auditId: audit9.id, label:
|
|
2212
|
+
violations.push({ auditId: audit9.id, label: __27("No H1 on the page.", "elementor") });
|
|
2510
2213
|
}
|
|
2511
2214
|
if (h1Count > 1) {
|
|
2512
2215
|
headings.filter((h) => h.level === 1).slice(1).forEach(
|
|
@@ -2514,7 +2217,7 @@ var audit9 = {
|
|
|
2514
2217
|
auditId: audit9.id,
|
|
2515
2218
|
elementId: h.elementId,
|
|
2516
2219
|
targetHint: "element-settings",
|
|
2517
|
-
label:
|
|
2220
|
+
label: __27("More than one H1 on the page.", "elementor")
|
|
2518
2221
|
})
|
|
2519
2222
|
);
|
|
2520
2223
|
}
|
|
@@ -2524,7 +2227,7 @@ var audit9 = {
|
|
|
2524
2227
|
auditId: audit9.id,
|
|
2525
2228
|
elementId: headings[i].elementId,
|
|
2526
2229
|
targetHint: "element-settings",
|
|
2527
|
-
label:
|
|
2230
|
+
label: __27("Heading level skipped.", "elementor")
|
|
2528
2231
|
});
|
|
2529
2232
|
}
|
|
2530
2233
|
}
|
|
@@ -2534,24 +2237,24 @@ var audit9 = {
|
|
|
2534
2237
|
};
|
|
2535
2238
|
|
|
2536
2239
|
// src/audits/hidden-elements.ts
|
|
2537
|
-
import { __ as
|
|
2240
|
+
import { __ as __28 } from "@wordpress/i18n";
|
|
2538
2241
|
function isHiddenOnAllDevices(settings) {
|
|
2539
2242
|
return Boolean(settings.hide_desktop) && Boolean(settings.hide_tablet) && Boolean(settings.hide_mobile);
|
|
2540
2243
|
}
|
|
2541
2244
|
var audit10 = {
|
|
2542
2245
|
id: "audits/hidden-elements",
|
|
2543
|
-
title:
|
|
2544
|
-
description:
|
|
2246
|
+
title: __28("Hidden elements", "elementor"),
|
|
2247
|
+
description: __28(
|
|
2545
2248
|
"Elements hidden on all devices simultaneously are effectively dead code in the page tree.",
|
|
2546
2249
|
"elementor"
|
|
2547
2250
|
),
|
|
2548
|
-
fixHint:
|
|
2251
|
+
fixHint: __28("Remove the element or make it visible on at least one device breakpoint.", "elementor"),
|
|
2549
2252
|
categories: ["best-practices", "performance"],
|
|
2550
2253
|
severity: "info",
|
|
2551
2254
|
weight: 3,
|
|
2552
2255
|
evaluate: (ctx) => {
|
|
2553
2256
|
if (ctx.elements.tree.length === 0) {
|
|
2554
|
-
return { status: "skipped", reason:
|
|
2257
|
+
return { status: "skipped", reason: __28("No elements", "elementor") };
|
|
2555
2258
|
}
|
|
2556
2259
|
const violations = [];
|
|
2557
2260
|
walkElements(ctx.elements.tree, (node) => {
|
|
@@ -2560,7 +2263,7 @@ var audit10 = {
|
|
|
2560
2263
|
auditId: audit10.id,
|
|
2561
2264
|
elementId: node.id,
|
|
2562
2265
|
targetHint: "element-settings",
|
|
2563
|
-
label:
|
|
2266
|
+
label: __28("Element is hidden on all devices.", "elementor")
|
|
2564
2267
|
});
|
|
2565
2268
|
}
|
|
2566
2269
|
});
|
|
@@ -2569,7 +2272,22 @@ var audit10 = {
|
|
|
2569
2272
|
};
|
|
2570
2273
|
|
|
2571
2274
|
// src/audits/images-alt-text.ts
|
|
2572
|
-
import { __ as
|
|
2275
|
+
import { __ as __29 } from "@wordpress/i18n";
|
|
2276
|
+
|
|
2277
|
+
// src/utils/alt-text-image-sources.ts
|
|
2278
|
+
function walkAltTextImageSources(tree, visit) {
|
|
2279
|
+
walkImageLikeSources(tree, visit);
|
|
2280
|
+
walkAtomicImageSources(tree, visit, ATOMIC_CONTENT_IMAGE_PROP_KEYS);
|
|
2281
|
+
}
|
|
2282
|
+
function hasAltTextImages(tree) {
|
|
2283
|
+
let found = false;
|
|
2284
|
+
walkAltTextImageSources(tree, ({ media }) => {
|
|
2285
|
+
if (media.id || media.url) {
|
|
2286
|
+
found = true;
|
|
2287
|
+
}
|
|
2288
|
+
});
|
|
2289
|
+
return found;
|
|
2290
|
+
}
|
|
2573
2291
|
|
|
2574
2292
|
// src/utils/image-alt.ts
|
|
2575
2293
|
function hasMeaningfulAlt(media, pageContext) {
|
|
@@ -2590,20 +2308,21 @@ function isImageSourcePresent(media) {
|
|
|
2590
2308
|
// src/audits/images-alt-text.ts
|
|
2591
2309
|
var audit11 = {
|
|
2592
2310
|
id: "audits/images-alt-text",
|
|
2593
|
-
title:
|
|
2594
|
-
description:
|
|
2595
|
-
fixHint:
|
|
2311
|
+
title: __29("Images alt text", "elementor"),
|
|
2312
|
+
description: __29("Every image needs a meaningful alt attribute for screen readers and image-search.", "elementor"),
|
|
2313
|
+
fixHint: __29("Open the image's settings and add an Alt Text describing the image.", "elementor"),
|
|
2596
2314
|
categories: ["seo", "accessibility"],
|
|
2597
2315
|
severity: "error",
|
|
2598
2316
|
weight: 10,
|
|
2599
2317
|
evaluate: (ctx) => {
|
|
2600
|
-
if (!
|
|
2601
|
-
return { status: "skipped", reason:
|
|
2318
|
+
if (!hasAltTextImages(ctx.elements.tree)) {
|
|
2319
|
+
return { status: "skipped", reason: __29("No images", "elementor") };
|
|
2602
2320
|
}
|
|
2321
|
+
const isReady = ctx.pageContext.ally_plugin_active;
|
|
2603
2322
|
const violations = [];
|
|
2604
2323
|
const failedWidgetIds = /* @__PURE__ */ new Set();
|
|
2605
2324
|
let missingAltImageCount = 0;
|
|
2606
|
-
|
|
2325
|
+
walkAltTextImageSources(ctx.elements.tree, ({ node, media }) => {
|
|
2607
2326
|
if (!isImageSourcePresent(media) || hasMeaningfulAlt(media, ctx.pageContext)) {
|
|
2608
2327
|
return;
|
|
2609
2328
|
}
|
|
@@ -2614,8 +2333,9 @@ var audit11 = {
|
|
|
2614
2333
|
auditId: audit11.id,
|
|
2615
2334
|
elementId: node.id,
|
|
2616
2335
|
targetHint: "element-settings",
|
|
2617
|
-
label:
|
|
2618
|
-
externalUrl: ctx.pageContext.ally_plugin_url
|
|
2336
|
+
label: __29("Image is missing alt text.", "elementor"),
|
|
2337
|
+
externalUrl: isReady ? ctx.pageContext.ally_scan_url : ctx.pageContext.ally_plugin_url,
|
|
2338
|
+
ctaLabel: __29("Fix with Ally", "elementor")
|
|
2619
2339
|
});
|
|
2620
2340
|
}
|
|
2621
2341
|
});
|
|
@@ -2624,17 +2344,18 @@ var audit11 = {
|
|
|
2624
2344
|
};
|
|
2625
2345
|
|
|
2626
2346
|
// src/audits/images-inefficient-format.ts
|
|
2627
|
-
import { __ as
|
|
2347
|
+
import { __ as __30 } from "@wordpress/i18n";
|
|
2628
2348
|
var LEGACY_RASTER_MIME_TYPES = /* @__PURE__ */ new Set(["image/jpeg", "image/png", "image/gif", "image/bmp", "image/tiff"]);
|
|
2629
2349
|
var audit12 = {
|
|
2630
2350
|
id: "audits/images-inefficient-format",
|
|
2631
|
-
title:
|
|
2632
|
-
description:
|
|
2633
|
-
fixHint:
|
|
2351
|
+
title: __30("Inefficient image format", "elementor"),
|
|
2352
|
+
description: __30("Image isn't served in a modern, efficient format like WebP or AVIF.", "elementor"),
|
|
2353
|
+
fixHint: __30("Convert the image to a modern format like WebP or AVIF, or enable image optimization.", "elementor"),
|
|
2634
2354
|
categories: ["performance"],
|
|
2635
2355
|
severity: "info",
|
|
2636
2356
|
weight: 1,
|
|
2637
2357
|
evaluate: (ctx) => {
|
|
2358
|
+
const isReady = ctx.pageContext.image_optimization_plugin_active;
|
|
2638
2359
|
const offendingElementIds = /* @__PURE__ */ new Set();
|
|
2639
2360
|
let hasAnyImage = false;
|
|
2640
2361
|
let inefficientImageFormatCount = 0;
|
|
@@ -2653,37 +2374,36 @@ var audit12 = {
|
|
|
2653
2374
|
inefficientImageFormatCount++;
|
|
2654
2375
|
offendingElementIds.add(node.id);
|
|
2655
2376
|
};
|
|
2656
|
-
|
|
2657
|
-
walkBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2658
|
-
walkAtomicImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2659
|
-
walkAtomicBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2377
|
+
walkAllImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2660
2378
|
if (!hasAnyImage) {
|
|
2661
|
-
return { status: "skipped", reason:
|
|
2379
|
+
return { status: "skipped", reason: __30("No images", "elementor") };
|
|
2662
2380
|
}
|
|
2663
2381
|
const violations = Array.from(offendingElementIds).map((elementId) => ({
|
|
2664
2382
|
auditId: audit12.id,
|
|
2665
2383
|
elementId,
|
|
2666
2384
|
targetHint: "element-settings",
|
|
2667
|
-
label:
|
|
2668
|
-
externalUrl: ctx.pageContext.image_optimization_plugin_url
|
|
2385
|
+
label: __30("Image isn't served in a modern format like WebP or AVIF.", "elementor"),
|
|
2386
|
+
externalUrl: isReady ? ctx.pageContext.image_optimization_settings_url : ctx.pageContext.image_optimization_plugin_url,
|
|
2387
|
+
ctaLabel: __30("Optimize all", "elementor")
|
|
2669
2388
|
}));
|
|
2670
2389
|
return violations.length === 0 ? { status: "pass" } : { status: "fail", violations, metadata: { inefficientImageFormatCount } };
|
|
2671
2390
|
}
|
|
2672
2391
|
};
|
|
2673
2392
|
|
|
2674
2393
|
// src/audits/images-too-large.ts
|
|
2675
|
-
import { __ as
|
|
2394
|
+
import { __ as __31, sprintf as sprintf3 } from "@wordpress/i18n";
|
|
2676
2395
|
var SIZE_THRESHOLD_BYTES = 500 * 1024;
|
|
2677
2396
|
var BYTES_PER_KB = 1024;
|
|
2678
2397
|
var audit13 = {
|
|
2679
2398
|
id: "audits/images-too-large",
|
|
2680
|
-
title:
|
|
2681
|
-
description:
|
|
2682
|
-
fixHint:
|
|
2399
|
+
title: __31("Oversized images", "elementor"),
|
|
2400
|
+
description: __31("Large image files slow down the page.", "elementor"),
|
|
2401
|
+
fixHint: __31("Replace the image with a smaller version or enable image optimization.", "elementor"),
|
|
2683
2402
|
categories: ["performance"],
|
|
2684
2403
|
severity: "warning",
|
|
2685
2404
|
weight: 7,
|
|
2686
2405
|
evaluate: (ctx) => {
|
|
2406
|
+
const isReady = ctx.pageContext.image_optimization_plugin_active;
|
|
2687
2407
|
const widgetMaxKb = /* @__PURE__ */ new Map();
|
|
2688
2408
|
let oversizedImageCount = 0;
|
|
2689
2409
|
let hasAnyImage = false;
|
|
@@ -2704,44 +2424,42 @@ var audit13 = {
|
|
|
2704
2424
|
const currentMax = widgetMaxKb.get(node.id) ?? 0;
|
|
2705
2425
|
widgetMaxKb.set(node.id, Math.max(currentMax, kb));
|
|
2706
2426
|
};
|
|
2707
|
-
|
|
2708
|
-
walkBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2709
|
-
walkAtomicImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2710
|
-
walkAtomicBackgroundImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2427
|
+
walkAllImageSources(ctx.elements.tree, ({ node, media }) => evaluateSource(node, media));
|
|
2711
2428
|
if (!hasAnyImage) {
|
|
2712
|
-
return { status: "skipped", reason:
|
|
2429
|
+
return { status: "skipped", reason: __31("No images", "elementor") };
|
|
2713
2430
|
}
|
|
2714
2431
|
const violations = Array.from(widgetMaxKb.entries()).map(([elementId, kb]) => ({
|
|
2715
2432
|
auditId: audit13.id,
|
|
2716
2433
|
elementId,
|
|
2717
2434
|
targetHint: "element-settings",
|
|
2718
|
-
label:
|
|
2435
|
+
label: sprintf3(
|
|
2719
2436
|
/* translators: %d is the image file size in kilobytes. */
|
|
2720
|
-
|
|
2437
|
+
__31("Image is %d KB (over 500 KB).", "elementor"),
|
|
2721
2438
|
kb
|
|
2722
2439
|
),
|
|
2723
|
-
externalUrl: ctx.pageContext.image_optimization_plugin_url
|
|
2440
|
+
externalUrl: isReady ? ctx.pageContext.image_optimization_settings_url : ctx.pageContext.image_optimization_plugin_url,
|
|
2441
|
+
ctaLabel: __31("Optimize all", "elementor")
|
|
2724
2442
|
}));
|
|
2725
2443
|
return violations.length === 0 ? { status: "pass" } : { status: "fail", violations, metadata: { oversizedImageCount } };
|
|
2726
2444
|
}
|
|
2727
2445
|
};
|
|
2728
2446
|
|
|
2729
2447
|
// src/audits/nested-boxed-containers.ts
|
|
2730
|
-
import { __ as
|
|
2448
|
+
import { __ as __32 } from "@wordpress/i18n";
|
|
2731
2449
|
function isBoxed(settings) {
|
|
2732
2450
|
return settings.content_width === "boxed";
|
|
2733
2451
|
}
|
|
2734
2452
|
var audit14 = {
|
|
2735
2453
|
id: "audits/nested-boxed-containers",
|
|
2736
|
-
title:
|
|
2737
|
-
description:
|
|
2738
|
-
fixHint:
|
|
2454
|
+
title: __32("Boxed container nested inside a boxed parent", "elementor"),
|
|
2455
|
+
description: __32("An inner container does not need to be boxed when its parent already is.", "elementor"),
|
|
2456
|
+
fixHint: __32("Change the inner container's content width to Full Width.", "elementor"),
|
|
2739
2457
|
categories: ["best-practices", "performance"],
|
|
2740
2458
|
severity: "info",
|
|
2741
2459
|
weight: 5,
|
|
2742
2460
|
evaluate: (ctx) => {
|
|
2743
2461
|
if (ctx.elements.tree.length === 0) {
|
|
2744
|
-
return { status: "skipped", reason:
|
|
2462
|
+
return { status: "skipped", reason: __32("No elements", "elementor") };
|
|
2745
2463
|
}
|
|
2746
2464
|
const violations = [];
|
|
2747
2465
|
walkElements(ctx.elements.tree, (node, parents) => {
|
|
@@ -2754,7 +2472,12 @@ var audit14 = {
|
|
|
2754
2472
|
auditId: audit14.id,
|
|
2755
2473
|
elementId: node.id,
|
|
2756
2474
|
targetHint: "element-settings",
|
|
2757
|
-
label:
|
|
2475
|
+
label: __32("Nested boxed container.", "elementor"),
|
|
2476
|
+
angieFix: true,
|
|
2477
|
+
angiePrompt: __32(
|
|
2478
|
+
"Find containers that have nested containers. Containers can be deep-nested. Update the nested container styling so that when a parent container already uses a boxed setting, any inner container inside it is set to Full Width. Keep the first parent container boxed, remove all boxed styling from the nested inner containers, and preserve the inner container\u2019s content, spacing, alignment, and hierarchy.",
|
|
2479
|
+
"elementor"
|
|
2480
|
+
)
|
|
2758
2481
|
});
|
|
2759
2482
|
}
|
|
2760
2483
|
});
|
|
@@ -2763,12 +2486,12 @@ var audit14 = {
|
|
|
2763
2486
|
};
|
|
2764
2487
|
|
|
2765
2488
|
// src/audits/page-excerpt.ts
|
|
2766
|
-
import { __ as
|
|
2489
|
+
import { __ as __33 } from "@wordpress/i18n";
|
|
2767
2490
|
var audit15 = {
|
|
2768
2491
|
id: "audits/page-excerpt",
|
|
2769
|
-
title:
|
|
2770
|
-
description:
|
|
2771
|
-
fixHint:
|
|
2492
|
+
title: __33("Page excerpt", "elementor"),
|
|
2493
|
+
description: __33("A descriptive excerpt helps search engines and previews summarize the page.", "elementor"),
|
|
2494
|
+
fixHint: __33("Open Page Settings and write a short excerpt.", "elementor"),
|
|
2772
2495
|
categories: ["seo"],
|
|
2773
2496
|
severity: "warning",
|
|
2774
2497
|
weight: 5,
|
|
@@ -2781,7 +2504,7 @@ var audit15 = {
|
|
|
2781
2504
|
violations: [
|
|
2782
2505
|
{
|
|
2783
2506
|
auditId: audit15.id,
|
|
2784
|
-
label:
|
|
2507
|
+
label: __33("Page has no excerpt.", "elementor"),
|
|
2785
2508
|
targetHint: "page-settings",
|
|
2786
2509
|
angieFix: true
|
|
2787
2510
|
}
|
|
@@ -2791,12 +2514,12 @@ var audit15 = {
|
|
|
2791
2514
|
};
|
|
2792
2515
|
|
|
2793
2516
|
// src/audits/page-featured-image.ts
|
|
2794
|
-
import { __ as
|
|
2517
|
+
import { __ as __34 } from "@wordpress/i18n";
|
|
2795
2518
|
var audit16 = {
|
|
2796
2519
|
id: "audits/page-featured-image",
|
|
2797
|
-
title:
|
|
2798
|
-
description:
|
|
2799
|
-
fixHint:
|
|
2520
|
+
title: __34("Page featured image", "elementor"),
|
|
2521
|
+
description: __34("Featured images are used by social shares and many themes for hero visuals.", "elementor"),
|
|
2522
|
+
fixHint: __34("Open Page Settings and set a featured image.", "elementor"),
|
|
2800
2523
|
categories: ["seo"],
|
|
2801
2524
|
severity: "info",
|
|
2802
2525
|
weight: 5,
|
|
@@ -2809,7 +2532,7 @@ var audit16 = {
|
|
|
2809
2532
|
violations: [
|
|
2810
2533
|
{
|
|
2811
2534
|
auditId: audit16.id,
|
|
2812
|
-
label:
|
|
2535
|
+
label: __34("No featured image set.", "elementor"),
|
|
2813
2536
|
targetHint: "page-settings"
|
|
2814
2537
|
}
|
|
2815
2538
|
]
|
|
@@ -2818,13 +2541,13 @@ var audit16 = {
|
|
|
2818
2541
|
};
|
|
2819
2542
|
|
|
2820
2543
|
// src/audits/page-title.ts
|
|
2821
|
-
import { __ as
|
|
2544
|
+
import { __ as __35 } from "@wordpress/i18n";
|
|
2822
2545
|
var MAX_TITLE_LENGTH = 60;
|
|
2823
2546
|
var audit17 = {
|
|
2824
2547
|
id: "audits/page-title",
|
|
2825
|
-
title:
|
|
2826
|
-
description:
|
|
2827
|
-
fixHint:
|
|
2548
|
+
title: __35("Page title", "elementor"),
|
|
2549
|
+
description: __35("Pages need a clear title for SEO and screen-reader navigation.", "elementor"),
|
|
2550
|
+
fixHint: __35("Open Page Settings and add a title.", "elementor"),
|
|
2828
2551
|
categories: ["seo"],
|
|
2829
2552
|
severity: "error",
|
|
2830
2553
|
weight: 10,
|
|
@@ -2836,10 +2559,10 @@ var audit17 = {
|
|
|
2836
2559
|
violations: [
|
|
2837
2560
|
{
|
|
2838
2561
|
auditId: audit17.id,
|
|
2839
|
-
label:
|
|
2562
|
+
label: __35("Page has no title.", "elementor"),
|
|
2840
2563
|
targetHint: "page-settings",
|
|
2841
2564
|
angieFix: true,
|
|
2842
|
-
angiePrompt:
|
|
2565
|
+
angiePrompt: __35(
|
|
2843
2566
|
"Based on this page's contents, generate a title for this page.",
|
|
2844
2567
|
"elementor"
|
|
2845
2568
|
)
|
|
@@ -2853,7 +2576,7 @@ var audit17 = {
|
|
|
2853
2576
|
violations: [
|
|
2854
2577
|
{
|
|
2855
2578
|
auditId: audit17.id,
|
|
2856
|
-
label:
|
|
2579
|
+
label: __35("Page title is too long.", "elementor"),
|
|
2857
2580
|
targetHint: "page-settings",
|
|
2858
2581
|
angieFix: true
|
|
2859
2582
|
}
|
|
@@ -2865,7 +2588,7 @@ var audit17 = {
|
|
|
2865
2588
|
};
|
|
2866
2589
|
|
|
2867
2590
|
// src/audits/prefer-global-colors.ts
|
|
2868
|
-
import { __ as
|
|
2591
|
+
import { __ as __36, sprintf as sprintf4 } from "@wordpress/i18n";
|
|
2869
2592
|
|
|
2870
2593
|
// src/utils/collect-hardcoded-colors.ts
|
|
2871
2594
|
var RESERVED_SETTING_KEYS = /* @__PURE__ */ new Set(["__globals__", "__dynamic__"]);
|
|
@@ -2933,18 +2656,18 @@ function findMatchingGlobalByValue(value, globals) {
|
|
|
2933
2656
|
// src/audits/prefer-global-colors.ts
|
|
2934
2657
|
var audit18 = {
|
|
2935
2658
|
id: "audits/prefer-global-colors",
|
|
2936
|
-
title:
|
|
2937
|
-
description:
|
|
2938
|
-
fixHint:
|
|
2659
|
+
title: __36("Prefer global colors", "elementor"),
|
|
2660
|
+
description: __36("Global colors make the design consistent and easy to update site-wide.", "elementor"),
|
|
2661
|
+
fixHint: __36("Replace the hard-coded value with the matching global color.", "elementor"),
|
|
2939
2662
|
categories: ["best-practices"],
|
|
2940
2663
|
severity: "info",
|
|
2941
2664
|
weight: 3,
|
|
2942
2665
|
evaluate: (ctx) => {
|
|
2943
2666
|
if (ctx.elements.tree.length === 0) {
|
|
2944
|
-
return { status: "skipped", reason:
|
|
2667
|
+
return { status: "skipped", reason: __36("No elements", "elementor") };
|
|
2945
2668
|
}
|
|
2946
2669
|
if (ctx.kit.globals.colors.length === 0) {
|
|
2947
|
-
return { status: "skipped", reason:
|
|
2670
|
+
return { status: "skipped", reason: __36("No global colors", "elementor") };
|
|
2948
2671
|
}
|
|
2949
2672
|
const violations = [];
|
|
2950
2673
|
walkElements(ctx.elements.tree, (node) => {
|
|
@@ -2958,9 +2681,9 @@ var audit18 = {
|
|
|
2958
2681
|
elementId: node.id,
|
|
2959
2682
|
targetHint: "element-settings",
|
|
2960
2683
|
angieFix: true,
|
|
2961
|
-
label:
|
|
2684
|
+
label: sprintf4(
|
|
2962
2685
|
/* translators: 1: hard-coded color value, 2: global color title. */
|
|
2963
|
-
|
|
2686
|
+
__36('replace "%1$s" with "%2$s" global color', "elementor"),
|
|
2964
2687
|
value,
|
|
2965
2688
|
global.title
|
|
2966
2689
|
)
|
|
@@ -2972,7 +2695,7 @@ var audit18 = {
|
|
|
2972
2695
|
};
|
|
2973
2696
|
|
|
2974
2697
|
// src/audits/prefer-global-fonts.ts
|
|
2975
|
-
import { __ as
|
|
2698
|
+
import { __ as __37, sprintf as sprintf5 } from "@wordpress/i18n";
|
|
2976
2699
|
|
|
2977
2700
|
// src/utils/collect-hardcoded-fonts.ts
|
|
2978
2701
|
var RESERVED_SETTING_KEYS2 = /* @__PURE__ */ new Set(["__globals__", "__dynamic__"]);
|
|
@@ -3032,18 +2755,18 @@ function collectHardcodedFonts(settings, pathPrefix = "") {
|
|
|
3032
2755
|
// src/audits/prefer-global-fonts.ts
|
|
3033
2756
|
var audit19 = {
|
|
3034
2757
|
id: "audits/prefer-global-fonts",
|
|
3035
|
-
title:
|
|
3036
|
-
description:
|
|
3037
|
-
fixHint:
|
|
2758
|
+
title: __37("Prefer global fonts", "elementor"),
|
|
2759
|
+
description: __37("Global fonts make the design consistent and easy to update site-wide.", "elementor"),
|
|
2760
|
+
fixHint: __37("Replace the hard-coded value with the matching global font.", "elementor"),
|
|
3038
2761
|
categories: ["best-practices", "performance"],
|
|
3039
2762
|
severity: "info",
|
|
3040
2763
|
weight: 3,
|
|
3041
2764
|
evaluate: (ctx) => {
|
|
3042
2765
|
if (ctx.elements.tree.length === 0) {
|
|
3043
|
-
return { status: "skipped", reason:
|
|
2766
|
+
return { status: "skipped", reason: __37("No elements", "elementor") };
|
|
3044
2767
|
}
|
|
3045
2768
|
if (ctx.kit.globals.fonts.length === 0) {
|
|
3046
|
-
return { status: "skipped", reason:
|
|
2769
|
+
return { status: "skipped", reason: __37("No global fonts", "elementor") };
|
|
3047
2770
|
}
|
|
3048
2771
|
const violations = [];
|
|
3049
2772
|
walkElements(ctx.elements.tree, (node) => {
|
|
@@ -3056,9 +2779,9 @@ var audit19 = {
|
|
|
3056
2779
|
auditId: audit19.id,
|
|
3057
2780
|
elementId: node.id,
|
|
3058
2781
|
targetHint: "element-settings",
|
|
3059
|
-
label:
|
|
2782
|
+
label: sprintf5(
|
|
3060
2783
|
/* translators: %s: global font title. */
|
|
3061
|
-
|
|
2784
|
+
__37('replace hardcoded typography with "%s" global font', "elementor"),
|
|
3062
2785
|
global.title
|
|
3063
2786
|
)
|
|
3064
2787
|
});
|
|
@@ -3069,15 +2792,15 @@ var audit19 = {
|
|
|
3069
2792
|
};
|
|
3070
2793
|
|
|
3071
2794
|
// src/audits/privacy-policy.ts
|
|
3072
|
-
import { __ as
|
|
2795
|
+
import { __ as __38 } from "@wordpress/i18n";
|
|
3073
2796
|
var audit20 = {
|
|
3074
2797
|
id: "audits/privacy-policy",
|
|
3075
|
-
title:
|
|
3076
|
-
description:
|
|
2798
|
+
title: __38("Privacy policy", "elementor"),
|
|
2799
|
+
description: __38(
|
|
3077
2800
|
"A privacy policy page is required by privacy regulations such as GDPR (EU) and CCPA (US).",
|
|
3078
2801
|
"elementor"
|
|
3079
2802
|
),
|
|
3080
|
-
fixHint:
|
|
2803
|
+
fixHint: __38(
|
|
3081
2804
|
"Go to Settings > Privacy in the WordPress admin and assign a published privacy policy page.",
|
|
3082
2805
|
"elementor"
|
|
3083
2806
|
),
|
|
@@ -3093,9 +2816,9 @@ var audit20 = {
|
|
|
3093
2816
|
violations: [
|
|
3094
2817
|
{
|
|
3095
2818
|
auditId: audit20.id,
|
|
3096
|
-
label:
|
|
2819
|
+
label: __38("No privacy policy page is set.", "elementor"),
|
|
3097
2820
|
externalUrl: ctx.pageContext.privacy_settings_url,
|
|
3098
|
-
ctaLabel:
|
|
2821
|
+
ctaLabel: __38("Create", "elementor")
|
|
3099
2822
|
}
|
|
3100
2823
|
]
|
|
3101
2824
|
};
|
|
@@ -3103,15 +2826,15 @@ var audit20 = {
|
|
|
3103
2826
|
};
|
|
3104
2827
|
|
|
3105
2828
|
// src/audits/robots-noindex.ts
|
|
3106
|
-
import { __ as
|
|
2829
|
+
import { __ as __39 } from "@wordpress/i18n";
|
|
3107
2830
|
var audit21 = {
|
|
3108
2831
|
id: "audits/robots-noindex",
|
|
3109
|
-
title:
|
|
3110
|
-
description:
|
|
2832
|
+
title: __39("Search engine visibility", "elementor"),
|
|
2833
|
+
description: __39(
|
|
3111
2834
|
"When search engine visibility is checked in WordPress Settings -> Reading -> Search Engine Visibility, search engines are discouraged from indexing the website.",
|
|
3112
2835
|
"elementor"
|
|
3113
2836
|
),
|
|
3114
|
-
fixHint:
|
|
2837
|
+
fixHint: __39(
|
|
3115
2838
|
'Go to Settings \u2192 Reading in the WordPress admin and uncheck "Discourage search engines from indexing this site" when the website should be indexed.',
|
|
3116
2839
|
"elementor"
|
|
3117
2840
|
),
|
|
@@ -3127,7 +2850,7 @@ var audit21 = {
|
|
|
3127
2850
|
violations: [
|
|
3128
2851
|
{
|
|
3129
2852
|
auditId: audit21.id,
|
|
3130
|
-
label:
|
|
2853
|
+
label: __39("Search engines are discouraged from indexing this website.", "elementor"),
|
|
3131
2854
|
externalUrl: ctx.pageContext.reading_settings_url
|
|
3132
2855
|
}
|
|
3133
2856
|
]
|
|
@@ -3136,15 +2859,15 @@ var audit21 = {
|
|
|
3136
2859
|
};
|
|
3137
2860
|
|
|
3138
2861
|
// src/audits/scan-for-cookies.ts
|
|
3139
|
-
import { __ as
|
|
2862
|
+
import { __ as __40 } from "@wordpress/i18n";
|
|
3140
2863
|
var audit22 = {
|
|
3141
2864
|
id: "audits/scan-for-cookies",
|
|
3142
|
-
title:
|
|
3143
|
-
description:
|
|
2865
|
+
title: __40("Scan for cookies", "elementor"),
|
|
2866
|
+
description: __40(
|
|
3144
2867
|
"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.",
|
|
3145
2868
|
"elementor"
|
|
3146
2869
|
),
|
|
3147
|
-
fixHint:
|
|
2870
|
+
fixHint: __40("Run a Cookiez scan on this page to see which cookies need disclosure.", "elementor"),
|
|
3148
2871
|
categories: ["compliance"],
|
|
3149
2872
|
severity: "info",
|
|
3150
2873
|
weight: 0,
|
|
@@ -3155,7 +2878,7 @@ var audit22 = {
|
|
|
3155
2878
|
violations: [
|
|
3156
2879
|
{
|
|
3157
2880
|
auditId: audit22.id,
|
|
3158
|
-
label:
|
|
2881
|
+
label: __40("This page has not been scanned for cookies yet.", "elementor"),
|
|
3159
2882
|
externalUrl: isReady ? ctx.pageContext.cookiez_scan_url : ctx.pageContext.cookiez_plugin_action_url
|
|
3160
2883
|
}
|
|
3161
2884
|
]
|
|
@@ -3164,21 +2887,21 @@ var audit22 = {
|
|
|
3164
2887
|
};
|
|
3165
2888
|
|
|
3166
2889
|
// src/audits/sections-and-columns.ts
|
|
3167
|
-
import { __ as
|
|
2890
|
+
import { __ as __41 } from "@wordpress/i18n";
|
|
3168
2891
|
var audit23 = {
|
|
3169
2892
|
id: "audits/sections-and-columns",
|
|
3170
|
-
title:
|
|
3171
|
-
description:
|
|
2893
|
+
title: __41("Sections and columns", "elementor"),
|
|
2894
|
+
description: __41(
|
|
3172
2895
|
"Sections and columns are legacy elements. Containers render fewer DOM nodes and are more flexible.",
|
|
3173
2896
|
"elementor"
|
|
3174
2897
|
),
|
|
3175
|
-
fixHint:
|
|
2898
|
+
fixHint: __41("Use the Container Converter to replace each section/column with a container.", "elementor"),
|
|
3176
2899
|
categories: ["best-practices", "performance"],
|
|
3177
2900
|
severity: "warning",
|
|
3178
2901
|
weight: 7,
|
|
3179
2902
|
evaluate: (ctx) => {
|
|
3180
2903
|
if (ctx.elements.tree.length === 0) {
|
|
3181
|
-
return { status: "skipped", reason:
|
|
2904
|
+
return { status: "skipped", reason: __41("No elements", "elementor") };
|
|
3182
2905
|
}
|
|
3183
2906
|
const violations = [];
|
|
3184
2907
|
walkElements(ctx.elements.tree, (node) => {
|
|
@@ -3186,7 +2909,7 @@ var audit23 = {
|
|
|
3186
2909
|
violations.push({
|
|
3187
2910
|
auditId: audit23.id,
|
|
3188
2911
|
elementId: node.id,
|
|
3189
|
-
label: node.elType === "section" ?
|
|
2912
|
+
label: node.elType === "section" ? __41("Section element", "elementor") : __41("Column element", "elementor")
|
|
3190
2913
|
});
|
|
3191
2914
|
}
|
|
3192
2915
|
});
|
|
@@ -3195,15 +2918,15 @@ var audit23 = {
|
|
|
3195
2918
|
};
|
|
3196
2919
|
|
|
3197
2920
|
// src/audits/site-identity.ts
|
|
3198
|
-
import { __ as
|
|
2921
|
+
import { __ as __42 } from "@wordpress/i18n";
|
|
3199
2922
|
var audit24 = {
|
|
3200
2923
|
id: "audits/site-identity",
|
|
3201
|
-
title:
|
|
3202
|
-
description:
|
|
2924
|
+
title: __42("Site identity", "elementor"),
|
|
2925
|
+
description: __42(
|
|
3203
2926
|
"Site name, description, logo, and favicon establish your brand and appear in search results and browser tabs.",
|
|
3204
2927
|
"elementor"
|
|
3205
2928
|
),
|
|
3206
|
-
fixHint:
|
|
2929
|
+
fixHint: __42("Open Site Settings \u2192 Site Identity and complete all the missing fields.", "elementor"),
|
|
3207
2930
|
categories: ["best-practices", "seo"],
|
|
3208
2931
|
severity: "info",
|
|
3209
2932
|
weight: 7,
|
|
@@ -3213,14 +2936,14 @@ var audit24 = {
|
|
|
3213
2936
|
if (!identity.site_name_set) {
|
|
3214
2937
|
violations.push({
|
|
3215
2938
|
auditId: audit24.id,
|
|
3216
|
-
label:
|
|
2939
|
+
label: __42("Site name is missing or still uses the default.", "elementor"),
|
|
3217
2940
|
targetHint: "site-identity-settings"
|
|
3218
2941
|
});
|
|
3219
2942
|
}
|
|
3220
2943
|
if (!identity.site_description_set) {
|
|
3221
2944
|
violations.push({
|
|
3222
2945
|
auditId: audit24.id,
|
|
3223
|
-
label:
|
|
2946
|
+
label: __42("Site description is missing or still uses the default.", "elementor"),
|
|
3224
2947
|
targetHint: "site-identity-settings",
|
|
3225
2948
|
angieFix: true
|
|
3226
2949
|
});
|
|
@@ -3228,14 +2951,14 @@ var audit24 = {
|
|
|
3228
2951
|
if (!identity.site_logo_set) {
|
|
3229
2952
|
violations.push({
|
|
3230
2953
|
auditId: audit24.id,
|
|
3231
|
-
label:
|
|
2954
|
+
label: __42("Site logo is not set.", "elementor"),
|
|
3232
2955
|
targetHint: "site-identity-settings"
|
|
3233
2956
|
});
|
|
3234
2957
|
}
|
|
3235
2958
|
if (!identity.site_favicon_set) {
|
|
3236
2959
|
violations.push({
|
|
3237
2960
|
auditId: audit24.id,
|
|
3238
|
-
label:
|
|
2961
|
+
label: __42("Site favicon is not set.", "elementor"),
|
|
3239
2962
|
targetHint: "site-identity-settings"
|
|
3240
2963
|
});
|
|
3241
2964
|
}
|
|
@@ -3249,50 +2972,6 @@ var audit24 = {
|
|
|
3249
2972
|
}
|
|
3250
2973
|
};
|
|
3251
2974
|
|
|
3252
|
-
// src/audits/too-many-widgets.ts
|
|
3253
|
-
import { getWidgetsCache as getWidgetsCache3 } from "@elementor/editor-elements";
|
|
3254
|
-
import { __ as __49 } from "@wordpress/i18n";
|
|
3255
|
-
var WIDGET_COUNT_THRESHOLD = 100;
|
|
3256
|
-
function isCountableWidget(node, widgetsCache) {
|
|
3257
|
-
if (node.elType === "widget") {
|
|
3258
|
-
return true;
|
|
3259
|
-
}
|
|
3260
|
-
return !!widgetsCache?.[node.elType]?.meta?.is_compound;
|
|
3261
|
-
}
|
|
3262
|
-
var audit25 = {
|
|
3263
|
-
id: "audits/too-many-widgets",
|
|
3264
|
-
title: __49("Too many widgets", "elementor"),
|
|
3265
|
-
description: __49("Excessive DOM size caused by too many widgets degrades rendering performance.", "elementor"),
|
|
3266
|
-
fixHint: __49("Reduce the number of widgets on the page by removing or combining elements.", "elementor"),
|
|
3267
|
-
categories: ["best-practices", "performance"],
|
|
3268
|
-
severity: "warning",
|
|
3269
|
-
weight: 5,
|
|
3270
|
-
evaluate: (ctx) => {
|
|
3271
|
-
if (ctx.elements.tree.length === 0) {
|
|
3272
|
-
return { status: "skipped", reason: __49("No elements", "elementor") };
|
|
3273
|
-
}
|
|
3274
|
-
const widgetsCache = getWidgetsCache3();
|
|
3275
|
-
let widgetCount = 0;
|
|
3276
|
-
walkElements(ctx.elements.tree, (node) => {
|
|
3277
|
-
if (isCountableWidget(node, widgetsCache)) {
|
|
3278
|
-
widgetCount++;
|
|
3279
|
-
}
|
|
3280
|
-
});
|
|
3281
|
-
if (widgetCount <= WIDGET_COUNT_THRESHOLD) {
|
|
3282
|
-
return { status: "pass" };
|
|
3283
|
-
}
|
|
3284
|
-
return {
|
|
3285
|
-
status: "fail",
|
|
3286
|
-
violations: [
|
|
3287
|
-
{
|
|
3288
|
-
auditId: audit25.id,
|
|
3289
|
-
label: __49("Page has too many widgets.", "elementor")
|
|
3290
|
-
}
|
|
3291
|
-
]
|
|
3292
|
-
};
|
|
3293
|
-
}
|
|
3294
|
-
};
|
|
3295
|
-
|
|
3296
2975
|
// src/register-audits.ts
|
|
3297
2976
|
var AUDITS = [
|
|
3298
2977
|
audit17,
|
|
@@ -3300,7 +2979,6 @@ var AUDITS = [
|
|
|
3300
2979
|
audit16,
|
|
3301
2980
|
audit10,
|
|
3302
2981
|
audit7,
|
|
3303
|
-
audit25,
|
|
3304
2982
|
audit23,
|
|
3305
2983
|
audit5,
|
|
3306
2984
|
audit14,
|
|
@@ -3322,17 +3000,30 @@ var AUDITS = [
|
|
|
3322
3000
|
audit8
|
|
3323
3001
|
];
|
|
3324
3002
|
function registerAllAudits() {
|
|
3325
|
-
for (const
|
|
3326
|
-
registerAudit(
|
|
3003
|
+
for (const audit25 of AUDITS) {
|
|
3004
|
+
registerAudit(audit25);
|
|
3327
3005
|
}
|
|
3328
3006
|
}
|
|
3329
3007
|
|
|
3008
|
+
// src/sync-report-staleness.ts
|
|
3009
|
+
import { __privateListenTo as listenTo, commandEndEvent } from "@elementor/editor-v1-adapters";
|
|
3010
|
+
import { __dispatch as dispatch } from "@elementor/store";
|
|
3011
|
+
function syncReportStaleness() {
|
|
3012
|
+
listenTo(commandEndEvent("document/save/set-is-modified"), (e) => {
|
|
3013
|
+
const event = e;
|
|
3014
|
+
if (event.args?.status) {
|
|
3015
|
+
dispatch(slice.actions.reportStale());
|
|
3016
|
+
}
|
|
3017
|
+
});
|
|
3018
|
+
}
|
|
3019
|
+
|
|
3330
3020
|
// src/init.ts
|
|
3331
3021
|
function init() {
|
|
3332
3022
|
registerSlice(slice);
|
|
3333
3023
|
registerAllAudits();
|
|
3334
3024
|
registerFloatingPanel(auditPanel.panel);
|
|
3335
3025
|
registerAppBarAuditsToggle();
|
|
3026
|
+
syncReportStaleness();
|
|
3336
3027
|
}
|
|
3337
3028
|
export {
|
|
3338
3029
|
init,
|