@elementor/editor-audits 4.3.0-1063 → 4.3.0-beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -13,10 +13,10 @@ import { __ as __22 } from "@wordpress/i18n";
13
13
  import { createFloatingPanel } from "@elementor/editor-floating-panels";
14
14
 
15
15
  // src/components/audit-panel.tsx
16
- import * as React22 from "react";
16
+ import * as React23 from "react";
17
17
  import { getCurrentDocumentId as getCurrentDocumentId2 } from "@elementor/editor-elements";
18
18
  import { FloatingPanelBody, FloatingPanelFooter, FloatingPanelHeader } from "@elementor/editor-floating-panels";
19
- import { Box as Box19, Button as Button4, Typography as Typography15 } from "@elementor/ui";
19
+ import { Box as Box19, Button as Button5, Typography as Typography15 } from "@elementor/ui";
20
20
  import { __ as __21 } from "@wordpress/i18n";
21
21
 
22
22
  // src/hooks/use-audit-report.ts
@@ -39,24 +39,72 @@ function getWindowConfig() {
39
39
  return config;
40
40
  }
41
41
 
42
+ // src/utils/session-expiration.ts
43
+ var NONCE_INVALID_CODE = "rest_cookie_invalid_nonce";
44
+ var DEFAULT_AJAX_URL = "/wp-admin/admin-ajax.php";
45
+ var SessionExpiredError = class extends Error {
46
+ };
47
+ var nonceRefreshPromise = null;
48
+ function isNonceInvalidError(error) {
49
+ const response = error?.response;
50
+ return response?.status === 403 && response?.data?.code === NONCE_INVALID_CODE;
51
+ }
52
+ async function refreshAuditsNonce() {
53
+ if (nonceRefreshPromise) {
54
+ return nonceRefreshPromise;
55
+ }
56
+ nonceRefreshPromise = requestFreshNonce();
57
+ try {
58
+ return await nonceRefreshPromise;
59
+ } finally {
60
+ nonceRefreshPromise = null;
61
+ }
62
+ }
63
+ async function requestFreshNonce() {
64
+ const ajaxUrl = window.elementorCommon?.ajax?.config?.url ?? DEFAULT_AJAX_URL;
65
+ const url = new URL(ajaxUrl, window.location.origin);
66
+ url.searchParams.set("action", "rest-nonce");
67
+ const response = await fetch(url.toString(), { credentials: "same-origin" });
68
+ if (!response.ok) {
69
+ throw new Error(`Failed to refresh audits nonce: HTTP ${response.status}`);
70
+ }
71
+ const nonce = await response.text();
72
+ if (!nonce || "0" === nonce) {
73
+ throw new SessionExpiredError("Session expired \u2014 received invalid nonce");
74
+ }
75
+ window.elementorAudits = { ...getWindowConfig(), nonce };
76
+ return nonce;
77
+ }
78
+
42
79
  // src/api/page-context-client.ts
43
80
  async function fetchPageContext(documentId, attachmentIds) {
81
+ return requestPageContext(documentId, attachmentIds, true);
82
+ }
83
+ async function requestPageContext(documentId, attachmentIds, allowNonceRetry) {
44
84
  const { restNamespace, nonce } = getWindowConfig();
45
85
  const url = `${restNamespace}/audits/page-context`;
46
- const response = await httpService().get(url, {
47
- params: {
48
- document_id: documentId,
49
- attachment_ids: attachmentIds
50
- },
51
- headers: { "X-WP-Nonce": nonce }
52
- });
53
- return response.data;
86
+ try {
87
+ const response = await httpService().get(url, {
88
+ params: {
89
+ document_id: documentId,
90
+ attachment_ids: attachmentIds
91
+ },
92
+ headers: { "X-WP-Nonce": nonce }
93
+ });
94
+ return response.data;
95
+ } catch (error) {
96
+ if (!allowNonceRetry || !isNonceInvalidError(error)) {
97
+ throw error;
98
+ }
99
+ await refreshAuditsNonce();
100
+ return requestPageContext(documentId, attachmentIds, false);
101
+ }
54
102
  }
55
103
 
56
104
  // src/registry.ts
57
105
  var registry = /* @__PURE__ */ new Map();
58
- function registerAudit(audit21) {
59
- registry.set(audit21.id, audit21);
106
+ function registerAudit(audit22) {
107
+ registry.set(audit22.id, audit22);
60
108
  }
61
109
  function getRegisteredAudits() {
62
110
  return Array.from(registry.values());
@@ -92,6 +140,11 @@ var CATEGORY_LABELS = {
92
140
  // src/utils/audit-status-summary.ts
93
141
  import { __ as __2 } from "@wordpress/i18n";
94
142
 
143
+ // src/utils/is-scored-audit.ts
144
+ function isScoredAudit(audit22) {
145
+ return audit22.weight > 0;
146
+ }
147
+
95
148
  // src/utils/sort-failed-audits.ts
96
149
  var SEVERITY_SORTING_RANK = {
97
150
  error: 0,
@@ -122,7 +175,9 @@ function partitionAuditResults(report, options = {}) {
122
175
  switch (run.result.status) {
123
176
  case "fail":
124
177
  failed.push({ ...run, result: run.result });
125
- totalViolations += run.result.violations.length;
178
+ if (isScoredAudit(run.audit)) {
179
+ totalViolations += run.result.violations.length;
180
+ }
126
181
  break;
127
182
  case "pass":
128
183
  passed.push({ ...run, result: run.result });
@@ -143,7 +198,10 @@ function auditStatusDisplayCounts(report) {
143
198
  let pass = 0;
144
199
  let skipped = 0;
145
200
  let totalViolations = 0;
146
- for (const { result } of report.auditResults) {
201
+ for (const { audit: audit22, result } of report.auditResults) {
202
+ if (!isScoredAudit(audit22)) {
203
+ continue;
204
+ }
147
205
  switch (result.status) {
148
206
  case "fail":
149
207
  totalViolations += result.violations.length;
@@ -191,16 +249,16 @@ function computeReport(documentId, results) {
191
249
  const accumulators = Object.fromEntries(
192
250
  ALL_CATEGORIES.map((c) => [c, { totalWeight: 0, passedWeight: 0, total: 0, failed: 0 }])
193
251
  );
194
- for (const { audit: audit21, result } of results) {
252
+ for (const { audit: audit22, result } of results) {
195
253
  if (result.status === "skipped") {
196
254
  continue;
197
255
  }
198
- for (const category of audit21.categories) {
256
+ for (const category of audit22.categories) {
199
257
  const acc = accumulators[category];
200
258
  acc.total++;
201
- acc.totalWeight += audit21.weight;
259
+ acc.totalWeight += audit22.weight;
202
260
  if (result.status === "pass") {
203
- acc.passedWeight += audit21.weight;
261
+ acc.passedWeight += audit22.weight;
204
262
  } else {
205
263
  acc.failed++;
206
264
  }
@@ -389,10 +447,10 @@ async function runPageAudit(documentId) {
389
447
  const ctx = { documentId, elements, pageContext, kit };
390
448
  const registered = getRegisteredAudits();
391
449
  const auditResults = await Promise.all(
392
- registered.map(async (audit21) => {
393
- const { evaluate: _evaluate, ...meta } = audit21;
450
+ registered.map(async (audit22) => {
451
+ const { evaluate: _evaluate, ...meta } = audit22;
394
452
  try {
395
- const result = await audit21.evaluate(ctx);
453
+ const result = await audit22.evaluate(ctx);
396
454
  return { audit: meta, result };
397
455
  } catch (error) {
398
456
  const reason = error instanceof Error ? error.message : "unknown-error";
@@ -422,6 +480,9 @@ var slice = __createSlice({
422
480
  state.status = "error";
423
481
  state.error = action.payload;
424
482
  },
483
+ runAborted(state) {
484
+ state.status = state.report ? "ready" : "idle";
485
+ },
425
486
  reportRestored(state, action) {
426
487
  state.status = "ready";
427
488
  state.report = action.payload;
@@ -483,6 +544,10 @@ function useAuditReport() {
483
544
  dispatch(slice.actions.runSucceeded(nextReport));
484
545
  persistReport(documentIdToRun, nextReport);
485
546
  } catch (e) {
547
+ if (e instanceof SessionExpiredError) {
548
+ dispatch(slice.actions.runAborted());
549
+ return;
550
+ }
486
551
  dispatch(slice.actions.runFailed(e instanceof Error ? e.message : "Unknown error"));
487
552
  }
488
553
  };
@@ -668,13 +733,13 @@ function WelcomePage() {
668
733
  }
669
734
 
670
735
  // src/components/report-shell.tsx
671
- import * as React21 from "react";
736
+ import * as React22 from "react";
672
737
  import { useState as useState4 } from "react";
673
738
  import { Box as Box18, Divider as Divider2, Tab, Tabs } from "@elementor/ui";
674
739
  import { __ as __20 } from "@wordpress/i18n";
675
740
 
676
741
  // src/components/pages/all-audits-page.tsx
677
- import * as React11 from "react";
742
+ import * as React12 from "react";
678
743
  import { Box as Box8 } from "@elementor/ui";
679
744
  import { __ as __12 } from "@wordpress/i18n";
680
745
 
@@ -686,7 +751,7 @@ import { Box as Box4, Chip, Collapse, IconButton as IconButton2 } from "@element
686
751
  import { __ as __7 } from "@wordpress/i18n";
687
752
  function StatusSection({ label, count, color = "default", defaultExpanded = false, children }) {
688
753
  const [expanded, setExpanded] = useState2(defaultExpanded);
689
- if (count === 0) {
754
+ if (React5.Children.count(children) === 0) {
690
755
  return null;
691
756
  }
692
757
  return /* @__PURE__ */ React5.createElement(Box4, { sx: { paddingBlock: 1 } }, /* @__PURE__ */ React5.createElement(
@@ -727,7 +792,7 @@ function SubpageHeader({ title, onBack, backLabel, icon }) {
727
792
  }
728
793
 
729
794
  // src/components/violation-row.tsx
730
- import * as React10 from "react";
795
+ import * as React11 from "react";
731
796
  import { useState as useState3 } from "react";
732
797
  import { getElementIcon, getElementTitle } from "@elementor/editor-elements";
733
798
  import { AlertCircleIcon as AlertCircleIcon2, BulbIcon, CheckIcon, ChevronDownIcon as ChevronDownIcon2, EyeIcon, HelpIcon } from "@elementor/icons";
@@ -844,13 +909,25 @@ function SeverityIcon({ severity }) {
844
909
  return /* @__PURE__ */ React8.createElement(Icon, { fontSize: "small", color });
845
910
  }
846
911
 
847
- // src/components/violation-icons.tsx
912
+ // src/components/violation-cta-button.tsx
848
913
  import * as React9 from "react";
914
+ import { Button as Button3 } from "@elementor/ui";
915
+ function ViolationCtaButton({ ctaLabel, externalUrl }) {
916
+ const handleClick = (event) => {
917
+ event.stopPropagation();
918
+ event.preventDefault();
919
+ window.open(externalUrl, "_blank", "noopener");
920
+ };
921
+ return /* @__PURE__ */ React9.createElement(Button3, { variant: "outlined", color: "secondary", size: "small", onClick: handleClick }, ctaLabel);
922
+ }
923
+
924
+ // src/components/violation-icons.tsx
925
+ import * as React10 from "react";
849
926
  import { FileSettingsIcon, SettingsIcon, ShieldCheckIcon } from "@elementor/icons";
850
927
  import { Box as Box6 } from "@elementor/ui";
851
928
  function ViolationIcon({ violation, widgetIcon }) {
852
929
  if (widgetIcon) {
853
- return /* @__PURE__ */ React9.createElement(
930
+ return /* @__PURE__ */ React10.createElement(
854
931
  Box6,
855
932
  {
856
933
  component: "i",
@@ -861,28 +938,28 @@ function ViolationIcon({ violation, widgetIcon }) {
861
938
  );
862
939
  }
863
940
  if (violation.targetHint === "page-settings") {
864
- return /* @__PURE__ */ React9.createElement(FileSettingsIcon, { fontSize: "inherit", "aria-hidden": true });
941
+ return /* @__PURE__ */ React10.createElement(FileSettingsIcon, { fontSize: "inherit", "aria-hidden": true });
865
942
  }
866
943
  if (violation.targetHint === "site-settings" || violation.targetHint === "site-identity-settings") {
867
- return /* @__PURE__ */ React9.createElement(SettingsIcon, { fontSize: "inherit", "aria-hidden": true });
944
+ return /* @__PURE__ */ React10.createElement(SettingsIcon, { fontSize: "inherit", "aria-hidden": true });
868
945
  }
869
- return /* @__PURE__ */ React9.createElement(ShieldCheckIcon, { fontSize: "inherit", "aria-hidden": true });
946
+ return /* @__PURE__ */ React10.createElement(ShieldCheckIcon, { fontSize: "inherit", "aria-hidden": true });
870
947
  }
871
948
 
872
949
  // src/components/violation-row.tsx
873
950
  function SkipReasonTooltip({ reason }) {
874
- return /* @__PURE__ */ React10.createElement(Tooltip3, { title: reason, placement: "top" }, /* @__PURE__ */ React10.createElement(Box7, { "aria-label": reason, component: "span", sx: { display: "inline-flex", alignItems: "center" } }, /* @__PURE__ */ React10.createElement(HelpIcon, { fontSize: "small", color: "action" })));
951
+ return /* @__PURE__ */ React11.createElement(Tooltip3, { title: reason, placement: "top" }, /* @__PURE__ */ React11.createElement(Box7, { "aria-label": reason, component: "span", sx: { display: "inline-flex", alignItems: "center" } }, /* @__PURE__ */ React11.createElement(HelpIcon, { fontSize: "small", color: "action" })));
875
952
  }
876
- function StatusIndicator({ audit: audit21, violations }) {
953
+ function StatusIndicator({ audit: audit22, violations }) {
877
954
  if (violations) {
878
- return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Typography6, { variant: "caption", color: "text.secondary", fontWeight: "bold" }, violations.length), /* @__PURE__ */ React10.createElement(SeverityIcon, { severity: audit21.severity }));
955
+ return /* @__PURE__ */ React11.createElement(React11.Fragment, null, isScoredAudit(audit22) && /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", color: "text.secondary", fontWeight: "bold" }, violations.length), /* @__PURE__ */ React11.createElement(SeverityIcon, { severity: audit22.severity }));
879
956
  }
880
- return /* @__PURE__ */ React10.createElement(CheckIcon, { fontSize: "small", color: "success" });
957
+ return /* @__PURE__ */ React11.createElement(CheckIcon, { fontSize: "small", color: "success" });
881
958
  }
882
- function ViolationRow({ audit: audit21, skipReason, violations }) {
959
+ function ViolationRow({ audit: audit22, skipReason, violations }) {
883
960
  const [expanded, setExpanded] = useState3(false);
884
961
  const toggleExpanded = () => setExpanded((value) => !value);
885
- return /* @__PURE__ */ React10.createElement(Box7, { sx: { borderBottom: 1, borderColor: "divider", paddingBlock: 0.5 } }, /* @__PURE__ */ React10.createElement(Box7, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React10.createElement(
962
+ return /* @__PURE__ */ React11.createElement(Box7, { sx: { borderBottom: 1, borderColor: "divider", paddingBlock: 0.5 } }, /* @__PURE__ */ React11.createElement(Box7, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React11.createElement(
886
963
  Box7,
887
964
  {
888
965
  sx: {
@@ -895,16 +972,16 @@ function ViolationRow({ audit: audit21, skipReason, violations }) {
895
972
  },
896
973
  onClick: toggleExpanded
897
974
  },
898
- /* @__PURE__ */ React10.createElement(Typography6, { variant: "body2", sx: { flex: 1 } }, audit21.title),
899
- !skipReason && /* @__PURE__ */ React10.createElement(StatusIndicator, { audit: audit21, violations })
900
- ), skipReason && /* @__PURE__ */ React10.createElement(SkipReasonTooltip, { reason: skipReason }), /* @__PURE__ */ React10.createElement(
975
+ /* @__PURE__ */ React11.createElement(Typography6, { variant: "body2", sx: { flex: 1 } }, audit22.title),
976
+ !skipReason && /* @__PURE__ */ React11.createElement(StatusIndicator, { audit: audit22, violations })
977
+ ), skipReason && /* @__PURE__ */ React11.createElement(SkipReasonTooltip, { reason: skipReason }), /* @__PURE__ */ React11.createElement(
901
978
  IconButton5,
902
979
  {
903
980
  size: "small",
904
981
  "aria-label": expanded ? __11("Collapse", "elementor") : __11("Expand", "elementor"),
905
982
  onClick: toggleExpanded
906
983
  },
907
- /* @__PURE__ */ React10.createElement(
984
+ /* @__PURE__ */ React11.createElement(
908
985
  ChevronDownIcon2,
909
986
  {
910
987
  fontSize: "small",
@@ -914,29 +991,29 @@ function ViolationRow({ audit: audit21, skipReason, violations }) {
914
991
  }
915
992
  }
916
993
  )
917
- )), /* @__PURE__ */ React10.createElement(Collapse2, { in: expanded }, /* @__PURE__ */ React10.createElement(Box7, { sx: { display: "flex", flexDirection: "column", gap: 1, paddingBlock: 1 } }, /* @__PURE__ */ React10.createElement(
994
+ )), /* @__PURE__ */ React11.createElement(Collapse2, { in: expanded }, /* @__PURE__ */ React11.createElement(Box7, { sx: { display: "flex", flexDirection: "column", gap: 1, paddingBlock: 1 } }, /* @__PURE__ */ React11.createElement(
918
995
  Alert,
919
996
  {
920
997
  severity: "secondary",
921
998
  sx: { p: 1 },
922
- icon: /* @__PURE__ */ React10.createElement(AlertCircleIcon2, { fontSize: "small", color: "secondary", "aria-hidden": true })
999
+ icon: /* @__PURE__ */ React11.createElement(AlertCircleIcon2, { fontSize: "small", color: "secondary", "aria-hidden": true })
923
1000
  },
924
- /* @__PURE__ */ React10.createElement(AlertTitle, null, /* @__PURE__ */ React10.createElement(Typography6, { variant: "caption", component: "p", color: "text.primary", fontWeight: "bold" }, __11("What's the issue", "elementor"))),
925
- /* @__PURE__ */ React10.createElement(Typography6, { variant: "caption", component: "p", color: "text.secondary" }, audit21.description)
926
- ), /* @__PURE__ */ React10.createElement(
1001
+ /* @__PURE__ */ React11.createElement(AlertTitle, null, /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", component: "p", color: "text.primary", fontWeight: "bold" }, __11("What's the issue", "elementor"))),
1002
+ /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", component: "p", color: "text.secondary" }, audit22.description)
1003
+ ), /* @__PURE__ */ React11.createElement(
927
1004
  Alert,
928
1005
  {
929
1006
  severity: "info",
930
1007
  sx: { p: 1 },
931
- icon: /* @__PURE__ */ React10.createElement(BulbIcon, { fontSize: "small", color: "info", "aria-hidden": true })
1008
+ icon: /* @__PURE__ */ React11.createElement(BulbIcon, { fontSize: "small", color: "info", "aria-hidden": true })
932
1009
  },
933
- /* @__PURE__ */ React10.createElement(AlertTitle, null, /* @__PURE__ */ React10.createElement(Typography6, { variant: "caption", component: "p", color: "text.primary", fontWeight: "bold" }, __11("How to resolve", "elementor"))),
934
- /* @__PURE__ */ React10.createElement(Typography6, { variant: "caption", component: "p", color: "text.secondary" }, audit21.fixHint)
935
- )), violations && violations.length > 0 && /* @__PURE__ */ React10.createElement(Box7, { role: "list", sx: { paddingBlockEnd: 1, paddingInlineStart: 2 } }, violations.map((violation, idx) => {
1010
+ /* @__PURE__ */ React11.createElement(AlertTitle, null, /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", component: "p", color: "text.primary", fontWeight: "bold" }, __11("How to resolve", "elementor"))),
1011
+ /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", component: "p", color: "text.secondary" }, audit22.fixHint)
1012
+ )), violations && violations.length > 0 && /* @__PURE__ */ React11.createElement(Box7, { role: "list", sx: { paddingBlockEnd: 1, paddingInlineStart: 2 } }, violations.map((violation, idx) => {
936
1013
  const widgetIcon = violation.elementId ? getElementIcon(violation.elementId) : null;
937
1014
  const elementTitle = violation.elementId ? getElementTitle(violation.elementId) : null;
938
1015
  const rowLabel = elementTitle ? `${elementTitle} - ${violation.label}` : violation.label;
939
- return /* @__PURE__ */ React10.createElement(
1016
+ return /* @__PURE__ */ React11.createElement(
940
1017
  Box7,
941
1018
  {
942
1019
  key: idx,
@@ -959,10 +1036,23 @@ function ViolationRow({ audit: audit21, skipReason, violations }) {
959
1036
  }
960
1037
  }
961
1038
  },
962
- /* @__PURE__ */ React10.createElement(ViolationIcon, { violation, widgetIcon }),
963
- /* @__PURE__ */ React10.createElement(Box7, { sx: { flex: 1 } }, /* @__PURE__ */ React10.createElement(Typography6, { variant: "caption" }, rowLabel), violation.detail && /* @__PURE__ */ React10.createElement(Typography6, { variant: "caption", color: "text.secondary" }, violation.detail)),
964
- violation.angieFix && /* @__PURE__ */ React10.createElement(FixViolationWithAngie, { prompt: buildAngiePrompt(rowLabel) }),
965
- /* @__PURE__ */ React10.createElement(EyeIcon, { className: "violation-hover-icon", fontSize: "tiny", "aria-hidden": true })
1039
+ /* @__PURE__ */ React11.createElement(ViolationIcon, { violation, widgetIcon }),
1040
+ /* @__PURE__ */ React11.createElement(Box7, { sx: { flex: 1 } }, /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption" }, rowLabel), violation.detail && /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", color: "text.secondary" }, violation.detail)),
1041
+ violation.angieFix && /* @__PURE__ */ React11.createElement(FixViolationWithAngie, { prompt: buildAngiePrompt(rowLabel) }),
1042
+ violation.ctaLabel && violation.externalUrl ? /* @__PURE__ */ React11.createElement(
1043
+ ViolationCtaButton,
1044
+ {
1045
+ ctaLabel: violation.ctaLabel,
1046
+ externalUrl: violation.externalUrl
1047
+ }
1048
+ ) : /* @__PURE__ */ React11.createElement(
1049
+ EyeIcon,
1050
+ {
1051
+ className: "violation-hover-icon",
1052
+ fontSize: "tiny",
1053
+ "aria-hidden": true
1054
+ }
1055
+ )
966
1056
  );
967
1057
  }))));
968
1058
  }
@@ -973,7 +1063,7 @@ function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
973
1063
  const expandFail = !initialExpandedStatus || initialExpandedStatus === "fail";
974
1064
  const expandPass = initialExpandedStatus === "pass";
975
1065
  const expandSkipped = initialExpandedStatus === "skipped";
976
- return /* @__PURE__ */ React11.createElement(Box8, { key: initialExpandedStatus ?? "default" }, /* @__PURE__ */ React11.createElement(SubpageHeader, { title: __12("All audits", "elementor"), onBack }), /* @__PURE__ */ React11.createElement(Box8, { sx: { p: 1 } }, /* @__PURE__ */ React11.createElement(
1066
+ 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(
977
1067
  StatusSection,
978
1068
  {
979
1069
  label: auditStatusLabel("fail"),
@@ -981,8 +1071,8 @@ function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
981
1071
  color: auditStatusColor("fail"),
982
1072
  defaultExpanded: expandFail
983
1073
  },
984
- failed.map((r) => /* @__PURE__ */ React11.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, violations: r.result.violations }))
985
- ), /* @__PURE__ */ React11.createElement(
1074
+ failed.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, violations: r.result.violations }))
1075
+ ), /* @__PURE__ */ React12.createElement(
986
1076
  StatusSection,
987
1077
  {
988
1078
  label: auditStatusLabel("pass"),
@@ -990,8 +1080,8 @@ function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
990
1080
  color: auditStatusColor("pass"),
991
1081
  defaultExpanded: expandPass
992
1082
  },
993
- passed.map((r) => /* @__PURE__ */ React11.createElement(ViolationRow, { key: r.audit.id, audit: r.audit }))
994
- ), /* @__PURE__ */ React11.createElement(
1083
+ passed.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit }))
1084
+ ), /* @__PURE__ */ React12.createElement(
995
1085
  StatusSection,
996
1086
  {
997
1087
  label: auditStatusLabel("skipped"),
@@ -999,12 +1089,12 @@ function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
999
1089
  color: auditStatusColor("skipped"),
1000
1090
  defaultExpanded: expandSkipped
1001
1091
  },
1002
- skipped.map((r) => /* @__PURE__ */ React11.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, skipReason: r.result.reason }))
1092
+ skipped.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, skipReason: r.result.reason }))
1003
1093
  )));
1004
1094
  }
1005
1095
 
1006
1096
  // src/components/pages/category-page.tsx
1007
- import * as React12 from "react";
1097
+ import * as React13 from "react";
1008
1098
  import { Box as Box9 } from "@elementor/ui";
1009
1099
  import { __ as __13 } from "@wordpress/i18n";
1010
1100
 
@@ -1028,15 +1118,15 @@ var CATEGORY_ICONS = {
1028
1118
  function CategoryPage({ category, report, onBack }) {
1029
1119
  const Icon = CATEGORY_ICONS[category];
1030
1120
  const { failed, passed, totalViolations } = partitionAuditResults(report, { category });
1031
- return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(
1121
+ return /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(
1032
1122
  SubpageHeader,
1033
1123
  {
1034
1124
  title: CATEGORY_LABELS[category],
1035
1125
  onBack,
1036
1126
  backLabel: __13("Back to all issues", "elementor"),
1037
- icon: /* @__PURE__ */ React12.createElement(Icon, { fontSize: "small", color: "action" })
1127
+ icon: /* @__PURE__ */ React13.createElement(Icon, { fontSize: "small", color: "action" })
1038
1128
  }
1039
- ), /* @__PURE__ */ React12.createElement(Box9, { sx: { p: 1 } }, /* @__PURE__ */ React12.createElement(
1129
+ ), /* @__PURE__ */ React13.createElement(Box9, { sx: { p: 1 } }, /* @__PURE__ */ React13.createElement(
1040
1130
  StatusSection,
1041
1131
  {
1042
1132
  label: __13("Failed audits", "elementor"),
@@ -1044,12 +1134,12 @@ function CategoryPage({ category, report, onBack }) {
1044
1134
  color: "error",
1045
1135
  defaultExpanded: true
1046
1136
  },
1047
- failed.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, violations: r.result.violations }))
1048
- ), /* @__PURE__ */ React12.createElement(StatusSection, { label: __13("Passed audits", "elementor"), count: passed.length, color: "success" }, passed.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit })))));
1137
+ failed.map((r) => /* @__PURE__ */ React13.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, violations: r.result.violations }))
1138
+ ), /* @__PURE__ */ React13.createElement(StatusSection, { label: __13("Passed audits", "elementor"), count: passed.length, color: "success" }, passed.map((r) => /* @__PURE__ */ React13.createElement(ViolationRow, { key: r.audit.id, audit: r.audit })))));
1049
1139
  }
1050
1140
 
1051
1141
  // src/components/pages/issues-page.tsx
1052
- import * as React16 from "react";
1142
+ import * as React17 from "react";
1053
1143
  import { Box as Box13, Link, Typography as Typography10 } from "@elementor/ui";
1054
1144
  import { __ as __17 } from "@wordpress/i18n";
1055
1145
 
@@ -1058,14 +1148,17 @@ import { __ as __14, sprintf as sprintf2 } from "@wordpress/i18n";
1058
1148
  var ALL_SEVERITIES = ["error", "warning", "info"];
1059
1149
  function countSeverities(report, category) {
1060
1150
  const counts = { error: 0, warning: 0, info: 0 };
1061
- for (const { audit: audit21, result } of report.auditResults) {
1151
+ for (const { audit: audit22, result } of report.auditResults) {
1062
1152
  if (result.status !== "fail") {
1063
1153
  continue;
1064
1154
  }
1065
- if (category && !audit21.categories.includes(category)) {
1155
+ if (category && !audit22.categories.includes(category)) {
1156
+ continue;
1157
+ }
1158
+ if (!isScoredAudit(audit22)) {
1066
1159
  continue;
1067
1160
  }
1068
- counts[audit21.severity] += result.violations.length;
1161
+ counts[audit22.severity] += result.violations.length;
1069
1162
  }
1070
1163
  return counts;
1071
1164
  }
@@ -1103,13 +1196,13 @@ function severityRemainingCountLabel(severity, count) {
1103
1196
  }
1104
1197
 
1105
1198
  // src/components/issues-category-row.tsx
1106
- import * as React13 from "react";
1199
+ import * as React14 from "react";
1107
1200
  import { ChevronRightIcon } from "@elementor/icons";
1108
1201
  import { Box as Box10, Rotate as Rotate2, Typography as Typography7, useTheme as useTheme2 } from "@elementor/ui";
1109
1202
  function IssuesCategoryRow({ category, label, counts, onClick }) {
1110
1203
  const isRtl = "rtl" === useTheme2().direction;
1111
1204
  const Icon = CATEGORY_ICONS[category];
1112
- return /* @__PURE__ */ React13.createElement(
1205
+ return /* @__PURE__ */ React14.createElement(
1113
1206
  Box10,
1114
1207
  {
1115
1208
  role: "button",
@@ -1131,15 +1224,15 @@ function IssuesCategoryRow({ category, label, counts, onClick }) {
1131
1224
  "&:focus-visible": { outline: "2px solid", outlineColor: "primary.main" }
1132
1225
  }
1133
1226
  },
1134
- /* @__PURE__ */ React13.createElement(Icon, { fontSize: "small", color: "action" }),
1135
- /* @__PURE__ */ React13.createElement(Typography7, { variant: "body2", fontWeight: "bold", sx: { flex: 1 } }, label),
1136
- /* @__PURE__ */ React13.createElement(Box10, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, ALL_SEVERITIES.filter((s) => counts[s] > 0).map((severity) => /* @__PURE__ */ React13.createElement(Box10, { key: severity, sx: { display: "flex", alignItems: "center", gap: 0.25 } }, /* @__PURE__ */ React13.createElement(SeverityIcon, { severity }), /* @__PURE__ */ React13.createElement(Typography7, { variant: "caption", color: "text.primary", fontWeight: "bold" }, counts[severity])))),
1137
- /* @__PURE__ */ React13.createElement(Rotate2, { in: isRtl }, /* @__PURE__ */ React13.createElement(ChevronRightIcon, { fontSize: "small", color: "action" }))
1227
+ /* @__PURE__ */ React14.createElement(Icon, { fontSize: "small", color: "action" }),
1228
+ /* @__PURE__ */ React14.createElement(Typography7, { variant: "body2", fontWeight: "bold", sx: { flex: 1 } }, label),
1229
+ /* @__PURE__ */ React14.createElement(Box10, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, ALL_SEVERITIES.filter((s) => counts[s] > 0).map((severity) => /* @__PURE__ */ React14.createElement(Box10, { 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])))),
1230
+ /* @__PURE__ */ React14.createElement(Rotate2, { in: isRtl }, /* @__PURE__ */ React14.createElement(ChevronRightIcon, { fontSize: "small", color: "action" }))
1138
1231
  );
1139
1232
  }
1140
1233
 
1141
1234
  // src/components/promotions.tsx
1142
- import * as React15 from "react";
1235
+ import * as React16 from "react";
1143
1236
  import { Box as Box12, Typography as Typography9 } from "@elementor/ui";
1144
1237
  import { __ as __16 } from "@wordpress/i18n";
1145
1238
 
@@ -1177,6 +1270,13 @@ var PROMOTIONS = [
1177
1270
  formatSubtitle: (run) => run.result.status === "fail" ? __15("Generate cookie policy", "elementor") : null,
1178
1271
  getCtaUrl: firstFailExternalUrl
1179
1272
  },
1273
+ {
1274
+ auditId: "audits/scan-for-cookies",
1275
+ icon: ElementorCookieIcon,
1276
+ ctaLabel: __15("Scan", "elementor"),
1277
+ formatSubtitle: (run) => run.result.status === "fail" ? __15("Scan this page for cookies", "elementor") : null,
1278
+ getCtaUrl: firstFailExternalUrl
1279
+ },
1180
1280
  {
1181
1281
  auditId: "audits/images-too-large",
1182
1282
  icon: ShieldHalfFilledIcon2,
@@ -1205,10 +1305,10 @@ function findAuditRun(report, auditId) {
1205
1305
  }
1206
1306
 
1207
1307
  // src/components/promotion-card.tsx
1208
- import * as React14 from "react";
1209
- import { Box as Box11, Button as Button3, Typography as Typography8 } from "@elementor/ui";
1308
+ import * as React15 from "react";
1309
+ import { Box as Box11, Button as Button4, Typography as Typography8 } from "@elementor/ui";
1210
1310
  function PromotionCard({ ctaDisabled, ctaLabel, icon: Icon, onCtaClick, subtitle, title }) {
1211
- return /* @__PURE__ */ React14.createElement(
1311
+ return /* @__PURE__ */ React15.createElement(
1212
1312
  Box11,
1213
1313
  {
1214
1314
  sx: {
@@ -1222,9 +1322,9 @@ function PromotionCard({ ctaDisabled, ctaLabel, icon: Icon, onCtaClick, subtitle
1222
1322
  py: 1.5
1223
1323
  }
1224
1324
  },
1225
- /* @__PURE__ */ React14.createElement(Icon, { fontSize: "small", color: "action" }),
1226
- /* @__PURE__ */ React14.createElement(Box11, { sx: { display: "flex", flex: 1, flexDirection: "column", gap: 0.25, minWidth: 0 } }, /* @__PURE__ */ React14.createElement(Typography8, { variant: "body2", fontWeight: "bold" }, title), /* @__PURE__ */ React14.createElement(Typography8, { variant: "caption", color: "text.secondary" }, subtitle)),
1227
- /* @__PURE__ */ React14.createElement(Button3, { variant: "outlined", color: "secondary", size: "small", disabled: ctaDisabled, onClick: onCtaClick }, ctaLabel)
1325
+ /* @__PURE__ */ React15.createElement(Icon, { fontSize: "small", color: "action" }),
1326
+ /* @__PURE__ */ React15.createElement(Box11, { 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)),
1327
+ /* @__PURE__ */ React15.createElement(Button4, { variant: "outlined", color: "secondary", size: "small", disabled: ctaDisabled, onClick: onCtaClick }, ctaLabel)
1228
1328
  );
1229
1329
  }
1230
1330
 
@@ -1253,7 +1353,7 @@ function Promotions({ report }) {
1253
1353
  if (cards.length === 0) {
1254
1354
  return null;
1255
1355
  }
1256
- return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Typography9, { variant: "subtitle1", fontWeight: "bold" }, __16("Quick wins", "elementor")), /* @__PURE__ */ React15.createElement(Box12, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, cards.map(({ config, ctaUrl, key, run, subtitle }) => /* @__PURE__ */ React15.createElement(
1356
+ return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Typography9, { variant: "subtitle1", fontWeight: "bold" }, __16("Quick wins", "elementor")), /* @__PURE__ */ React16.createElement(Box12, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, cards.map(({ config, ctaUrl, key, run, subtitle }) => /* @__PURE__ */ React16.createElement(
1257
1357
  PromotionCard,
1258
1358
  {
1259
1359
  key,
@@ -1274,7 +1374,7 @@ function Promotions({ report }) {
1274
1374
  // src/components/pages/issues-page.tsx
1275
1375
  function IssuesPage({ report, onCategoryClick, onAllAuditsClick }) {
1276
1376
  const populatedCategories = getPopulatedCategories(report.categories, ALL_CATEGORIES);
1277
- return /* @__PURE__ */ React16.createElement(Box13, { sx: { display: "flex", flexDirection: "column", gap: 4, p: 2 } }, /* @__PURE__ */ React16.createElement(
1377
+ return /* @__PURE__ */ React17.createElement(Box13, { sx: { display: "flex", flexDirection: "column", gap: 4, p: 2 } }, /* @__PURE__ */ React17.createElement(
1278
1378
  Link,
1279
1379
  {
1280
1380
  component: "button",
@@ -1283,8 +1383,8 @@ function IssuesPage({ report, onCategoryClick, onAllAuditsClick }) {
1283
1383
  onClick: onAllAuditsClick,
1284
1384
  sx: { textAlign: "start" }
1285
1385
  },
1286
- /* @__PURE__ */ React16.createElement(Typography10, { variant: "subtitle1", component: "h2" }, __17("All issues", "elementor"))
1287
- ), /* @__PURE__ */ React16.createElement(Box13, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, populatedCategories.map((category) => /* @__PURE__ */ React16.createElement(
1386
+ /* @__PURE__ */ React17.createElement(Typography10, { variant: "subtitle1", component: "h2" }, __17("All issues", "elementor"))
1387
+ ), /* @__PURE__ */ React17.createElement(Box13, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, populatedCategories.map((category) => /* @__PURE__ */ React17.createElement(
1288
1388
  IssuesCategoryRow,
1289
1389
  {
1290
1390
  key: category,
@@ -1293,11 +1393,11 @@ function IssuesPage({ report, onCategoryClick, onAllAuditsClick }) {
1293
1393
  counts: countSeverities(report, category),
1294
1394
  onClick: () => onCategoryClick(category)
1295
1395
  }
1296
- ))), /* @__PURE__ */ React16.createElement(Promotions, { report }));
1396
+ ))), /* @__PURE__ */ React17.createElement(Promotions, { report }));
1297
1397
  }
1298
1398
 
1299
1399
  // src/components/pages/overview-page.tsx
1300
- import * as React20 from "react";
1400
+ import * as React21 from "react";
1301
1401
  import { Box as Box17, Chip as Chip3, Divider, Typography as Typography14 } from "@elementor/ui";
1302
1402
  import { __ as __19, sprintf as sprintf4 } from "@wordpress/i18n";
1303
1403
 
@@ -1316,7 +1416,7 @@ function getScoreTier(score) {
1316
1416
  }
1317
1417
 
1318
1418
  // src/components/count-summary-circle.tsx
1319
- import * as React17 from "react";
1419
+ import * as React18 from "react";
1320
1420
  import { Box as Box14, Chip as Chip2, Typography as Typography11 } from "@elementor/ui";
1321
1421
  var COUNT_SUMMARY_CIRCLE_SIZE = 64;
1322
1422
  var COUNT_SUMMARY_BORDER_WIDTH = 4;
@@ -1327,7 +1427,7 @@ function chipBorderColor(theme, color) {
1327
1427
  return theme.palette[color].main;
1328
1428
  }
1329
1429
  function CountSummaryCircle({ ariaLabel, color, count, label, onClick }) {
1330
- return /* @__PURE__ */ React17.createElement(
1430
+ return /* @__PURE__ */ React18.createElement(
1331
1431
  Box14,
1332
1432
  {
1333
1433
  "aria-label": ariaLabel,
@@ -1346,7 +1446,7 @@ function CountSummaryCircle({ ariaLabel, color, count, label, onClick }) {
1346
1446
  padding: 0
1347
1447
  }
1348
1448
  },
1349
- /* @__PURE__ */ React17.createElement(
1449
+ /* @__PURE__ */ React18.createElement(
1350
1450
  Chip2,
1351
1451
  {
1352
1452
  color,
@@ -1368,17 +1468,17 @@ function CountSummaryCircle({ ariaLabel, color, count, label, onClick }) {
1368
1468
  })
1369
1469
  }
1370
1470
  ),
1371
- /* @__PURE__ */ React17.createElement(Typography11, { color: "text.secondary", sx: { textAlign: "center" }, variant: "caption" }, label)
1471
+ /* @__PURE__ */ React18.createElement(Typography11, { color: "text.secondary", sx: { textAlign: "center" }, variant: "caption" }, label)
1372
1472
  );
1373
1473
  }
1374
1474
 
1375
1475
  // src/components/score-bar.tsx
1376
- import * as React18 from "react";
1476
+ import * as React19 from "react";
1377
1477
  import { ChevronRightIcon as ChevronRightIcon2 } from "@elementor/icons";
1378
1478
  import { Box as Box15, LinearProgress, Rotate as Rotate3, Typography as Typography12, useTheme as useTheme3 } from "@elementor/ui";
1379
1479
  function ScoreBar({ label, score, onClick }) {
1380
1480
  const isRtl = "rtl" === useTheme3().direction;
1381
- return /* @__PURE__ */ React18.createElement(
1481
+ return /* @__PURE__ */ React19.createElement(
1382
1482
  Box15,
1383
1483
  {
1384
1484
  role: onClick ? "button" : void 0,
@@ -1395,8 +1495,8 @@ function ScoreBar({ label, score, onClick }) {
1395
1495
  py: 0.5
1396
1496
  }
1397
1497
  },
1398
- /* @__PURE__ */ React18.createElement(Typography12, { variant: "body2", sx: { minWidth: 96 } }, label),
1399
- /* @__PURE__ */ React18.createElement(
1498
+ /* @__PURE__ */ React19.createElement(Typography12, { variant: "body2", sx: { minWidth: 96 } }, label),
1499
+ /* @__PURE__ */ React19.createElement(
1400
1500
  LinearProgress,
1401
1501
  {
1402
1502
  variant: "determinate",
@@ -1405,7 +1505,7 @@ function ScoreBar({ label, score, onClick }) {
1405
1505
  sx: { flex: 1, height: 6, borderRadius: 4, bgcolor: "action.disabledBackground" }
1406
1506
  }
1407
1507
  ),
1408
- /* @__PURE__ */ React18.createElement(
1508
+ /* @__PURE__ */ React19.createElement(
1409
1509
  Typography12,
1410
1510
  {
1411
1511
  variant: "body2",
@@ -1414,18 +1514,18 @@ function ScoreBar({ label, score, onClick }) {
1414
1514
  },
1415
1515
  score
1416
1516
  ),
1417
- onClick && /* @__PURE__ */ React18.createElement(Rotate3, { in: isRtl }, /* @__PURE__ */ React18.createElement(ChevronRightIcon2, { fontSize: "small", color: "action" }))
1517
+ onClick && /* @__PURE__ */ React19.createElement(Rotate3, { in: isRtl }, /* @__PURE__ */ React19.createElement(ChevronRightIcon2, { fontSize: "small", color: "action" }))
1418
1518
  );
1419
1519
  }
1420
1520
 
1421
1521
  // src/components/score-circle.tsx
1422
- import * as React19 from "react";
1522
+ import * as React20 from "react";
1423
1523
  import { Box as Box16, CircularProgress as CircularProgress2, Typography as Typography13 } from "@elementor/ui";
1424
1524
  var SCORE_CIRCLE_SIZE = 88;
1425
1525
  var SCORE_CIRCLE_THICKNESS = 3;
1426
1526
  function ScoreCircle({ color, score }) {
1427
1527
  const progressColor = color ?? getScoreTier(score).color;
1428
- return /* @__PURE__ */ React19.createElement(
1528
+ return /* @__PURE__ */ React20.createElement(
1429
1529
  Box16,
1430
1530
  {
1431
1531
  role: "progressbar",
@@ -1434,7 +1534,7 @@ function ScoreCircle({ color, score }) {
1434
1534
  "aria-valuemax": 100,
1435
1535
  sx: { position: "relative", display: "inline-flex" }
1436
1536
  },
1437
- /* @__PURE__ */ React19.createElement(
1537
+ /* @__PURE__ */ React20.createElement(
1438
1538
  CircularProgress2,
1439
1539
  {
1440
1540
  variant: "determinate",
@@ -1444,7 +1544,7 @@ function ScoreCircle({ color, score }) {
1444
1544
  sx: { color: "action.disabledBackground" }
1445
1545
  }
1446
1546
  ),
1447
- /* @__PURE__ */ React19.createElement(
1547
+ /* @__PURE__ */ React20.createElement(
1448
1548
  CircularProgress2,
1449
1549
  {
1450
1550
  variant: "determinate",
@@ -1455,7 +1555,7 @@ function ScoreCircle({ color, score }) {
1455
1555
  sx: { position: "absolute", left: 0 }
1456
1556
  }
1457
1557
  ),
1458
- /* @__PURE__ */ React19.createElement(
1558
+ /* @__PURE__ */ React20.createElement(
1459
1559
  Box16,
1460
1560
  {
1461
1561
  sx: {
@@ -1466,7 +1566,7 @@ function ScoreCircle({ color, score }) {
1466
1566
  justifyContent: "center"
1467
1567
  }
1468
1568
  },
1469
- /* @__PURE__ */ React19.createElement(
1569
+ /* @__PURE__ */ React20.createElement(
1470
1570
  Typography13,
1471
1571
  {
1472
1572
  variant: "h4",
@@ -1504,7 +1604,7 @@ function OverviewPage({ onCategoryClick, onStatusClick, report }) {
1504
1604
  const severityCounts = countSeverities(report);
1505
1605
  const statusCounts = auditStatusDisplayCounts(report);
1506
1606
  const overallScore = getScoreTier(report.overall);
1507
- return /* @__PURE__ */ React20.createElement(Box17, { sx: { display: "flex", flexDirection: "column", gap: 4, p: 2 } }, /* @__PURE__ */ React20.createElement(Box17, { sx: { display: "flex", alignItems: "center", gap: 2 } }, /* @__PURE__ */ React20.createElement(ScoreCircle, { color: overallScore.color, score: report.overall }), /* @__PURE__ */ React20.createElement(Box17, { sx: { display: "flex", flexDirection: "column", gap: 0.5 } }, /* @__PURE__ */ React20.createElement(
1607
+ return /* @__PURE__ */ React21.createElement(Box17, { sx: { display: "flex", flexDirection: "column", gap: 4, p: 2 } }, /* @__PURE__ */ React21.createElement(Box17, { sx: { display: "flex", alignItems: "center", gap: 2 } }, /* @__PURE__ */ React21.createElement(ScoreCircle, { color: overallScore.color, score: report.overall }), /* @__PURE__ */ React21.createElement(Box17, { sx: { display: "flex", flexDirection: "column", gap: 0.5 } }, /* @__PURE__ */ React21.createElement(
1508
1608
  Chip3,
1509
1609
  {
1510
1610
  label: overallScore.label,
@@ -1513,7 +1613,7 @@ function OverviewPage({ onCategoryClick, onStatusClick, report }) {
1513
1613
  size: "small",
1514
1614
  sx: { fontWeight: 600, alignSelf: "flex-start" }
1515
1615
  }
1516
- ), /* @__PURE__ */ React20.createElement(Typography14, { variant: "body2", color: "text.secondary" }, __19("Overall score", "elementor")))), /* @__PURE__ */ React20.createElement(Box17, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, populatedCategories.map((category) => /* @__PURE__ */ React20.createElement(
1616
+ ), /* @__PURE__ */ React21.createElement(Typography14, { variant: "body2", color: "text.secondary" }, __19("Overall score", "elementor")))), /* @__PURE__ */ React21.createElement(Box17, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, populatedCategories.map((category) => /* @__PURE__ */ React21.createElement(
1517
1617
  ScoreBar,
1518
1618
  {
1519
1619
  key: category,
@@ -1521,7 +1621,7 @@ function OverviewPage({ onCategoryClick, onStatusClick, report }) {
1521
1621
  score: report.categories[category].score,
1522
1622
  onClick: () => onCategoryClick(category)
1523
1623
  }
1524
- ))), /* @__PURE__ */ React20.createElement(Divider, null), /* @__PURE__ */ React20.createElement(Typography14, { variant: "subtitle1", fontWeight: "bold" }, __19("Audit statuses", "elementor")), /* @__PURE__ */ React20.createElement(Box17, { sx: { display: "flex", justifyContent: "space-around", gap: 2 } }, STATUS_GROUPS.map((status) => /* @__PURE__ */ React20.createElement(
1624
+ ))), /* @__PURE__ */ React21.createElement(Divider, null), /* @__PURE__ */ React21.createElement(Typography14, { variant: "subtitle1", fontWeight: "bold" }, __19("Audit statuses", "elementor")), /* @__PURE__ */ React21.createElement(Box17, { sx: { display: "flex", justifyContent: "space-around", gap: 2 } }, STATUS_GROUPS.map((status) => /* @__PURE__ */ React21.createElement(
1525
1625
  CountSummaryCircle,
1526
1626
  {
1527
1627
  key: status,
@@ -1531,7 +1631,7 @@ function OverviewPage({ onCategoryClick, onStatusClick, report }) {
1531
1631
  label: auditStatusLabel(status),
1532
1632
  onClick: () => onStatusClick(status)
1533
1633
  }
1534
- ))), /* @__PURE__ */ React20.createElement(Divider, null), /* @__PURE__ */ React20.createElement(Typography14, { variant: "subtitle1", fontWeight: "bold" }, __19("Remaining issues", "elementor")), /* @__PURE__ */ React20.createElement(
1634
+ ))), /* @__PURE__ */ React21.createElement(Divider, null), /* @__PURE__ */ React21.createElement(Typography14, { variant: "subtitle1", fontWeight: "bold" }, __19("Remaining issues", "elementor")), /* @__PURE__ */ React21.createElement(
1535
1635
  Box17,
1536
1636
  {
1537
1637
  component: "ul",
@@ -1546,7 +1646,7 @@ function OverviewPage({ onCategoryClick, onStatusClick, report }) {
1546
1646
  },
1547
1647
  ALL_SEVERITIES.map((severity) => {
1548
1648
  const count = severityCounts[severity];
1549
- return /* @__PURE__ */ React20.createElement(
1649
+ return /* @__PURE__ */ React21.createElement(
1550
1650
  Box17,
1551
1651
  {
1552
1652
  "aria-label": severityRemainingCountLabel(severity, count),
@@ -1554,9 +1654,9 @@ function OverviewPage({ onCategoryClick, onStatusClick, report }) {
1554
1654
  key: severity,
1555
1655
  sx: { alignItems: "center", display: "flex", gap: 0.5 }
1556
1656
  },
1557
- /* @__PURE__ */ React20.createElement(SeverityIcon, { severity }),
1558
- /* @__PURE__ */ React20.createElement(Typography14, { variant: "body2", fontWeight: "bold" }, count),
1559
- /* @__PURE__ */ React20.createElement(Typography14, { variant: "body2" }, severityPluralLabel(severity))
1657
+ /* @__PURE__ */ React21.createElement(SeverityIcon, { severity }),
1658
+ /* @__PURE__ */ React21.createElement(Typography14, { variant: "body2", fontWeight: "bold" }, count),
1659
+ /* @__PURE__ */ React21.createElement(Typography14, { variant: "body2" }, severityPluralLabel(severity))
1560
1660
  );
1561
1661
  })
1562
1662
  ));
@@ -1595,7 +1695,7 @@ function ReportShell({ report }) {
1595
1695
  setActivePage(activePage.backTo);
1596
1696
  }
1597
1697
  };
1598
- return /* @__PURE__ */ React21.createElement(Box18, null, /* @__PURE__ */ React21.createElement(
1698
+ return /* @__PURE__ */ React22.createElement(Box18, null, /* @__PURE__ */ React22.createElement(
1599
1699
  Tabs,
1600
1700
  {
1601
1701
  "aria-label": __20("Audit navigation", "elementor"),
@@ -1607,30 +1707,30 @@ function ReportShell({ report }) {
1607
1707
  centered: true,
1608
1708
  variant: "fullWidth"
1609
1709
  },
1610
- /* @__PURE__ */ React21.createElement(Tab, { value: "overview", label: __20("Overview", "elementor") }),
1611
- /* @__PURE__ */ React21.createElement(Tab, { value: "issues", label: __20("Issues", "elementor") })
1612
- ), /* @__PURE__ */ React21.createElement(Divider2, null), activePage === "overview" && /* @__PURE__ */ React21.createElement(
1710
+ /* @__PURE__ */ React22.createElement(Tab, { value: "overview", label: __20("Overview", "elementor") }),
1711
+ /* @__PURE__ */ React22.createElement(Tab, { value: "issues", label: __20("Issues", "elementor") })
1712
+ ), /* @__PURE__ */ React22.createElement(Divider2, null), activePage === "overview" && /* @__PURE__ */ React22.createElement(
1613
1713
  OverviewPage,
1614
1714
  {
1615
1715
  report,
1616
1716
  onCategoryClick: (category) => openCategory(category, "overview"),
1617
1717
  onStatusClick: (status) => openAllAudits(status, "overview")
1618
1718
  }
1619
- ), activePage === "issues" && /* @__PURE__ */ React21.createElement(
1719
+ ), activePage === "issues" && /* @__PURE__ */ React22.createElement(
1620
1720
  IssuesPage,
1621
1721
  {
1622
1722
  report,
1623
1723
  onCategoryClick: (category) => openCategory(category, "issues"),
1624
1724
  onAllAuditsClick: () => openAllAudits()
1625
1725
  }
1626
- ), isAllAuditsPage(activePage) && /* @__PURE__ */ React21.createElement(
1726
+ ), isAllAuditsPage(activePage) && /* @__PURE__ */ React22.createElement(
1627
1727
  AllAuditsPage,
1628
1728
  {
1629
1729
  report,
1630
1730
  initialExpandedStatus: activePage.expand,
1631
1731
  onBack: backFromSubPage
1632
1732
  }
1633
- ), isCategoryPage(activePage) && /* @__PURE__ */ React21.createElement(CategoryPage, { category: activePage.category, report, onBack: backFromSubPage }));
1733
+ ), isCategoryPage(activePage) && /* @__PURE__ */ React22.createElement(CategoryPage, { category: activePage.category, report, onBack: backFromSubPage }));
1634
1734
  }
1635
1735
 
1636
1736
  // src/components/audit-panel.tsx
@@ -1639,7 +1739,7 @@ function AuditPanel() {
1639
1739
  const currentDocumentId = getCurrentDocumentId2() ?? 0;
1640
1740
  const onRun = () => run(currentDocumentId);
1641
1741
  const lastScanLabel = report ? new Date(report.runAt).toLocaleTimeString() : null;
1642
- return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(
1742
+ return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(
1643
1743
  FloatingPanelHeader,
1644
1744
  {
1645
1745
  panelId: "audit-panel",
@@ -1647,8 +1747,8 @@ function AuditPanel() {
1647
1747
  badge: __21("Beta", "elementor"),
1648
1748
  titleVariant: "subtitle2"
1649
1749
  }
1650
- ), /* @__PURE__ */ React22.createElement(FloatingPanelBody, null, status === "idle" && /* @__PURE__ */ React22.createElement(WelcomePage, null), status === "loading" && /* @__PURE__ */ React22.createElement(LoadingPage, null), status === "error" && /* @__PURE__ */ React22.createElement(ErrorPage, { message: error ?? "", onRetry: onRun }), status === "ready" && report && /* @__PURE__ */ React22.createElement(ReportShell, { report })), /* @__PURE__ */ React22.createElement(FloatingPanelFooter, null, lastScanLabel ? /* @__PURE__ */ React22.createElement(Typography15, { variant: "caption", sx: { flex: 1 } }, __21("Last scan:", "elementor"), " ", lastScanLabel) : /* @__PURE__ */ React22.createElement(Box19, { sx: { flex: 1 } }), lastScanLabel && /* @__PURE__ */ React22.createElement(AuditFeedback, null), /* @__PURE__ */ React22.createElement(
1651
- Button4,
1750
+ ), /* @__PURE__ */ React23.createElement(FloatingPanelBody, null, status === "idle" && /* @__PURE__ */ React23.createElement(WelcomePage, null), status === "loading" && /* @__PURE__ */ React23.createElement(LoadingPage, null), status === "error" && /* @__PURE__ */ React23.createElement(ErrorPage, { message: error ?? "", onRetry: onRun }), status === "ready" && report && /* @__PURE__ */ React23.createElement(ReportShell, { report })), /* @__PURE__ */ React23.createElement(FloatingPanelFooter, null, lastScanLabel ? /* @__PURE__ */ React23.createElement(Typography15, { variant: "caption", sx: { flex: 1 } }, __21("Last scan:", "elementor"), " ", lastScanLabel) : /* @__PURE__ */ React23.createElement(Box19, { sx: { flex: 1 } }), lastScanLabel && /* @__PURE__ */ React23.createElement(AuditFeedback, null), /* @__PURE__ */ React23.createElement(
1751
+ Button5,
1652
1752
  {
1653
1753
  variant: "contained",
1654
1754
  size: "small",
@@ -2595,7 +2695,8 @@ var audit16 = {
2595
2695
  {
2596
2696
  auditId: audit16.id,
2597
2697
  label: __38("No privacy policy page is set.", "elementor"),
2598
- externalUrl: ctx.pageContext.privacy_settings_url
2698
+ externalUrl: ctx.pageContext.privacy_settings_url,
2699
+ ctaLabel: __38("Create", "elementor")
2599
2700
  }
2600
2701
  ]
2601
2702
  };
@@ -2635,30 +2736,58 @@ var audit17 = {
2635
2736
  }
2636
2737
  };
2637
2738
 
2638
- // src/audits/sections-and-columns.ts
2739
+ // src/audits/scan-for-cookies.ts
2639
2740
  import { __ as __40 } from "@wordpress/i18n";
2640
2741
  var audit18 = {
2641
- id: "audits/sections-and-columns",
2642
- title: __40("Sections and columns", "elementor"),
2742
+ id: "audits/scan-for-cookies",
2743
+ title: __40("Scan for cookies", "elementor"),
2643
2744
  description: __40(
2745
+ "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.",
2746
+ "elementor"
2747
+ ),
2748
+ fixHint: __40("Run a Cookiez scan on this page to see which cookies need disclosure.", "elementor"),
2749
+ categories: ["compliance"],
2750
+ severity: "info",
2751
+ weight: 0,
2752
+ evaluate: (ctx) => {
2753
+ const isReady = ctx.pageContext.cookiez_plugin_installed && ctx.pageContext.cookiez_plugin_active;
2754
+ return {
2755
+ status: "fail",
2756
+ violations: [
2757
+ {
2758
+ auditId: audit18.id,
2759
+ label: __40("This page has not been scanned for cookies yet.", "elementor"),
2760
+ externalUrl: isReady ? ctx.pageContext.cookiez_scan_url : ctx.pageContext.cookiez_plugin_action_url
2761
+ }
2762
+ ]
2763
+ };
2764
+ }
2765
+ };
2766
+
2767
+ // src/audits/sections-and-columns.ts
2768
+ import { __ as __41 } from "@wordpress/i18n";
2769
+ var audit19 = {
2770
+ id: "audits/sections-and-columns",
2771
+ title: __41("Sections and columns", "elementor"),
2772
+ description: __41(
2644
2773
  "Sections and columns are legacy elements. Containers render fewer DOM nodes and are more flexible.",
2645
2774
  "elementor"
2646
2775
  ),
2647
- fixHint: __40("Use the Container Converter to replace each section/column with a container.", "elementor"),
2776
+ fixHint: __41("Use the Container Converter to replace each section/column with a container.", "elementor"),
2648
2777
  categories: ["best-practices", "performance"],
2649
2778
  severity: "warning",
2650
2779
  weight: 7,
2651
2780
  evaluate: (ctx) => {
2652
2781
  if (ctx.elements.tree.length === 0) {
2653
- return { status: "skipped", reason: __40("No elements", "elementor") };
2782
+ return { status: "skipped", reason: __41("No elements", "elementor") };
2654
2783
  }
2655
2784
  const violations = [];
2656
2785
  walkElements(ctx.elements.tree, (node) => {
2657
2786
  if (node.elType === "section" || node.elType === "column") {
2658
2787
  violations.push({
2659
- auditId: audit18.id,
2788
+ auditId: audit19.id,
2660
2789
  elementId: node.id,
2661
- label: node.elType === "section" ? __40("Section element", "elementor") : __40("Column element", "elementor")
2790
+ label: node.elType === "section" ? __41("Section element", "elementor") : __41("Column element", "elementor")
2662
2791
  });
2663
2792
  }
2664
2793
  });
@@ -2667,15 +2796,15 @@ var audit18 = {
2667
2796
  };
2668
2797
 
2669
2798
  // src/audits/site-identity.ts
2670
- import { __ as __41 } from "@wordpress/i18n";
2671
- var audit19 = {
2799
+ import { __ as __42 } from "@wordpress/i18n";
2800
+ var audit20 = {
2672
2801
  id: "audits/site-identity",
2673
- title: __41("Site identity", "elementor"),
2674
- description: __41(
2802
+ title: __42("Site identity", "elementor"),
2803
+ description: __42(
2675
2804
  "Site name, description, logo, and favicon establish your brand and appear in search results and browser tabs.",
2676
2805
  "elementor"
2677
2806
  ),
2678
- fixHint: __41("Open Site Settings \u2192 Site Identity and complete all the missing fields.", "elementor"),
2807
+ fixHint: __42("Open Site Settings \u2192 Site Identity and complete all the missing fields.", "elementor"),
2679
2808
  categories: ["best-practices", "seo"],
2680
2809
  severity: "info",
2681
2810
  weight: 7,
@@ -2684,30 +2813,30 @@ var audit19 = {
2684
2813
  const violations = [];
2685
2814
  if (!identity.site_name_set) {
2686
2815
  violations.push({
2687
- auditId: audit19.id,
2688
- label: __41("Site name is missing or still uses the default.", "elementor"),
2816
+ auditId: audit20.id,
2817
+ label: __42("Site name is missing or still uses the default.", "elementor"),
2689
2818
  targetHint: "site-identity-settings"
2690
2819
  });
2691
2820
  }
2692
2821
  if (!identity.site_description_set) {
2693
2822
  violations.push({
2694
- auditId: audit19.id,
2695
- label: __41("Site description is missing or still uses the default.", "elementor"),
2823
+ auditId: audit20.id,
2824
+ label: __42("Site description is missing or still uses the default.", "elementor"),
2696
2825
  targetHint: "site-identity-settings",
2697
2826
  angieFix: true
2698
2827
  });
2699
2828
  }
2700
2829
  if (!identity.site_logo_set) {
2701
2830
  violations.push({
2702
- auditId: audit19.id,
2703
- label: __41("Site logo is not set.", "elementor"),
2831
+ auditId: audit20.id,
2832
+ label: __42("Site logo is not set.", "elementor"),
2704
2833
  targetHint: "site-identity-settings"
2705
2834
  });
2706
2835
  }
2707
2836
  if (!identity.site_favicon_set) {
2708
2837
  violations.push({
2709
- auditId: audit19.id,
2710
- label: __41("Site favicon is not set.", "elementor"),
2838
+ auditId: audit20.id,
2839
+ label: __42("Site favicon is not set.", "elementor"),
2711
2840
  targetHint: "site-identity-settings"
2712
2841
  });
2713
2842
  }
@@ -2722,19 +2851,19 @@ var audit19 = {
2722
2851
  };
2723
2852
 
2724
2853
  // src/audits/too-many-widgets.ts
2725
- import { __ as __42 } from "@wordpress/i18n";
2854
+ import { __ as __43 } from "@wordpress/i18n";
2726
2855
  var WIDGET_COUNT_THRESHOLD = 100;
2727
- var audit20 = {
2856
+ var audit21 = {
2728
2857
  id: "audits/too-many-widgets",
2729
- title: __42("Too many widgets", "elementor"),
2730
- description: __42("Excessive DOM size caused by too many widgets degrades rendering performance.", "elementor"),
2731
- fixHint: __42("Reduce the number of widgets on the page by removing or combining elements.", "elementor"),
2858
+ title: __43("Too many widgets", "elementor"),
2859
+ description: __43("Excessive DOM size caused by too many widgets degrades rendering performance.", "elementor"),
2860
+ fixHint: __43("Reduce the number of widgets on the page by removing or combining elements.", "elementor"),
2732
2861
  categories: ["best-practices", "performance"],
2733
2862
  severity: "warning",
2734
2863
  weight: 5,
2735
2864
  evaluate: (ctx) => {
2736
2865
  if (ctx.elements.tree.length === 0) {
2737
- return { status: "skipped", reason: __42("No elements", "elementor") };
2866
+ return { status: "skipped", reason: __43("No elements", "elementor") };
2738
2867
  }
2739
2868
  let widgetCount = 0;
2740
2869
  walkElements(ctx.elements.tree, (node) => {
@@ -2749,8 +2878,8 @@ var audit20 = {
2749
2878
  status: "fail",
2750
2879
  violations: [
2751
2880
  {
2752
- auditId: audit20.id,
2753
- label: __42("Page has too many widgets.", "elementor")
2881
+ auditId: audit21.id,
2882
+ label: __43("Page has too many widgets.", "elementor")
2754
2883
  }
2755
2884
  ]
2756
2885
  };
@@ -2764,12 +2893,12 @@ var AUDITS = [
2764
2893
  audit12,
2765
2894
  audit7,
2766
2895
  audit5,
2767
- audit20,
2768
- audit18,
2896
+ audit21,
2897
+ audit19,
2769
2898
  audit3,
2770
2899
  audit10,
2771
2900
  audit4,
2772
- audit19,
2901
+ audit20,
2773
2902
  audit14,
2774
2903
  audit15,
2775
2904
  audit6,
@@ -2778,11 +2907,12 @@ var AUDITS = [
2778
2907
  audit17,
2779
2908
  audit16,
2780
2909
  audit,
2781
- audit2
2910
+ audit2,
2911
+ audit18
2782
2912
  ];
2783
2913
  function registerAllAudits() {
2784
- for (const audit21 of AUDITS) {
2785
- registerAudit(audit21);
2914
+ for (const audit22 of AUDITS) {
2915
+ registerAudit(audit22);
2786
2916
  }
2787
2917
  }
2788
2918