@elementor/editor-audits 4.4.0-1122 → 4.4.0-1123
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 +83 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +91 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -15
- package/src/audits/images-alt-text.ts +2 -1
- package/src/audits/images-inefficient-format.ts +4 -1
- package/src/audits/images-too-large.ts +4 -1
- package/src/audits/nested-boxed-containers.ts +5 -0
- package/src/components/fix-violation-with-angie.tsx +19 -2
- package/src/components/severity-icons.tsx +5 -1
- package/src/components/violation-row.tsx +68 -19
- package/src/types.ts +2 -0
package/dist/index.mjs
CHANGED
|
@@ -937,7 +937,7 @@ function SubpageHeader({ title, onBack, backLabel, icon }) {
|
|
|
937
937
|
import * as React12 from "react";
|
|
938
938
|
import { getElementIcon, getElementTitle } from "@elementor/editor-elements";
|
|
939
939
|
import { useFloatingPanelZIndex as useFloatingPanelZIndex2 } from "@elementor/editor-floating-panels";
|
|
940
|
-
import { CheckIcon, ChevronDownIcon as ChevronDownIcon2, HelpIcon, InfoCircleIcon
|
|
940
|
+
import { CheckIcon, ChevronDownIcon as ChevronDownIcon2, HelpIcon, InfoCircleIcon } from "@elementor/icons";
|
|
941
941
|
import { Alert, Box as Box7, Collapse as Collapse2, IconButton as IconButton5, Tooltip as Tooltip3, Typography as Typography6 } from "@elementor/ui";
|
|
942
942
|
import { __ as __10 } from "@wordpress/i18n";
|
|
943
943
|
|
|
@@ -1003,9 +1003,9 @@ function onKeyboardClick(callback) {
|
|
|
1003
1003
|
import * as React8 from "react";
|
|
1004
1004
|
import { isAngieAvailable, sendPromptToAngie } from "@elementor/editor-mcp";
|
|
1005
1005
|
import { AngieIcon } from "@elementor/icons";
|
|
1006
|
-
import { IconButton as IconButton4, Tooltip as Tooltip2 } from "@elementor/ui";
|
|
1006
|
+
import { Button as Button3, IconButton as IconButton4, Tooltip as Tooltip2 } from "@elementor/ui";
|
|
1007
1007
|
import { __ as __9 } from "@wordpress/i18n";
|
|
1008
|
-
function FixViolationWithAngie({ prompt, panelZIndex }) {
|
|
1008
|
+
function FixViolationWithAngie({ prompt, panelZIndex, variant = "icon" }) {
|
|
1009
1009
|
const label = __9("Fix with Angie", "elementor");
|
|
1010
1010
|
const href = `#angie-prompt=${encodeURIComponent(prompt)}`;
|
|
1011
1011
|
const handleClick = (event) => {
|
|
@@ -1024,6 +1024,21 @@ function FixViolationWithAngie({ prompt, panelZIndex }) {
|
|
|
1024
1024
|
})
|
|
1025
1025
|
);
|
|
1026
1026
|
};
|
|
1027
|
+
if (variant === "button") {
|
|
1028
|
+
return /* @__PURE__ */ React8.createElement(
|
|
1029
|
+
Button3,
|
|
1030
|
+
{
|
|
1031
|
+
component: "a",
|
|
1032
|
+
href,
|
|
1033
|
+
size: "small",
|
|
1034
|
+
color: "secondary",
|
|
1035
|
+
variant: "outlined",
|
|
1036
|
+
startIcon: /* @__PURE__ */ React8.createElement(AngieIcon, { fontSize: "tiny", "aria-hidden": true }),
|
|
1037
|
+
onClick: handleClick
|
|
1038
|
+
},
|
|
1039
|
+
label
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1027
1042
|
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" })));
|
|
1028
1043
|
}
|
|
1029
1044
|
|
|
@@ -1035,15 +1050,17 @@ var SEVERITY_CONFIG = {
|
|
|
1035
1050
|
warning: { Icon: AlertCircleIcon, color: "warning" },
|
|
1036
1051
|
info: { Icon: BulbIcon, color: "info" }
|
|
1037
1052
|
};
|
|
1053
|
+
var INFO_ICON_VERTICAL_NUDGE = "translateY(-2px)";
|
|
1038
1054
|
function SeverityIcon({ severity }) {
|
|
1039
1055
|
const { Icon, color } = SEVERITY_CONFIG[severity];
|
|
1040
|
-
|
|
1056
|
+
const sx = "info" === severity ? { transform: INFO_ICON_VERTICAL_NUDGE } : void 0;
|
|
1057
|
+
return /* @__PURE__ */ React9.createElement(Icon, { fontSize: "small", color, sx });
|
|
1041
1058
|
}
|
|
1042
1059
|
|
|
1043
1060
|
// src/components/violation-cta-button.tsx
|
|
1044
1061
|
import * as React10 from "react";
|
|
1045
1062
|
import { WandIcon } from "@elementor/icons";
|
|
1046
|
-
import { Button as
|
|
1063
|
+
import { Button as Button4 } from "@elementor/ui";
|
|
1047
1064
|
function ViolationCtaButton({ ctaLabel, externalUrl, variant = "outlined", withIcon = false }) {
|
|
1048
1065
|
const handleClick = (event) => {
|
|
1049
1066
|
event.stopPropagation();
|
|
@@ -1051,7 +1068,7 @@ function ViolationCtaButton({ ctaLabel, externalUrl, variant = "outlined", withI
|
|
|
1051
1068
|
window.open(externalUrl, "_blank", "noopener");
|
|
1052
1069
|
};
|
|
1053
1070
|
return /* @__PURE__ */ React10.createElement(
|
|
1054
|
-
|
|
1071
|
+
Button4,
|
|
1055
1072
|
{
|
|
1056
1073
|
variant,
|
|
1057
1074
|
color: "secondary",
|
|
@@ -1098,31 +1115,49 @@ function StatusIndicator({ audit: audit26, violations }) {
|
|
|
1098
1115
|
}
|
|
1099
1116
|
return /* @__PURE__ */ React12.createElement(CheckIcon, { fontSize: "small", color: "success" });
|
|
1100
1117
|
}
|
|
1101
|
-
function GuidanceAction({
|
|
1118
|
+
function GuidanceAction({
|
|
1119
|
+
violation,
|
|
1120
|
+
sharedAngiePrompt,
|
|
1121
|
+
panelZIndex
|
|
1122
|
+
}) {
|
|
1102
1123
|
const hasPrimaryCta = !!(violation.ctaLabel && violation.externalUrl);
|
|
1103
|
-
if (!hasPrimaryCta) {
|
|
1124
|
+
if (!hasPrimaryCta && !sharedAngiePrompt) {
|
|
1104
1125
|
return null;
|
|
1105
1126
|
}
|
|
1106
|
-
return /* @__PURE__ */ React12.createElement(Box7, { display: "flex", alignItems: "center", gap: 1, mt: 1 }, /* @__PURE__ */ React12.createElement(
|
|
1127
|
+
return /* @__PURE__ */ React12.createElement(Box7, { display: "flex", alignItems: "center", gap: 1, mt: 1 }, hasPrimaryCta && /* @__PURE__ */ React12.createElement(
|
|
1107
1128
|
ViolationCtaButton,
|
|
1108
1129
|
{
|
|
1109
1130
|
ctaLabel: violation.ctaLabel,
|
|
1110
1131
|
externalUrl: violation.externalUrl,
|
|
1111
1132
|
withIcon: true
|
|
1112
1133
|
}
|
|
1113
|
-
), violation.secondaryCtaLabel && violation.secondaryCtaUrl && /* @__PURE__ */ React12.createElement(
|
|
1134
|
+
), hasPrimaryCta && violation.secondaryCtaLabel && violation.secondaryCtaUrl && /* @__PURE__ */ React12.createElement(
|
|
1114
1135
|
ViolationCtaButton,
|
|
1115
1136
|
{
|
|
1116
1137
|
ctaLabel: violation.secondaryCtaLabel,
|
|
1117
1138
|
externalUrl: violation.secondaryCtaUrl,
|
|
1118
1139
|
variant: "text"
|
|
1119
1140
|
}
|
|
1120
|
-
));
|
|
1141
|
+
), sharedAngiePrompt && /* @__PURE__ */ React12.createElement(FixViolationWithAngie, { prompt: sharedAngiePrompt, panelZIndex, variant: "button" }));
|
|
1142
|
+
}
|
|
1143
|
+
function getSharedAngiePrompt(violations) {
|
|
1144
|
+
if (!violations || violations.length < 2) {
|
|
1145
|
+
return void 0;
|
|
1146
|
+
}
|
|
1147
|
+
const [first, ...rest] = violations;
|
|
1148
|
+
if (!first.angieFix || !first.angiePrompt) {
|
|
1149
|
+
return void 0;
|
|
1150
|
+
}
|
|
1151
|
+
const allShareTheSameFix = rest.every(
|
|
1152
|
+
(violation) => violation.angieFix && violation.angiePrompt === first.angiePrompt
|
|
1153
|
+
);
|
|
1154
|
+
return allShareTheSameFix ? first.angiePrompt : void 0;
|
|
1121
1155
|
}
|
|
1122
1156
|
function ViolationRow({ audit: audit26, expanded, onToggleExpand, skipReason, violations }) {
|
|
1123
1157
|
const primaryViolation = violations?.[0];
|
|
1124
1158
|
const isGuidanceFocusable = !!primaryViolation;
|
|
1125
1159
|
const panelZIndex = useFloatingPanelZIndex2(AUDIT_PANEL_ID);
|
|
1160
|
+
const sharedAngiePrompt = getSharedAngiePrompt(violations);
|
|
1126
1161
|
const handleGuidanceClick = () => {
|
|
1127
1162
|
if (isGuidanceFocusable && primaryViolation) {
|
|
1128
1163
|
focusViolation(primaryViolation);
|
|
@@ -1172,11 +1207,20 @@ function ViolationRow({ audit: audit26, expanded, onToggleExpand, skipReason, vi
|
|
|
1172
1207
|
onKeyDown: isGuidanceFocusable ? onKeyboardClick(handleGuidanceClick) : void 0
|
|
1173
1208
|
},
|
|
1174
1209
|
/* @__PURE__ */ React12.createElement(Typography6, { variant: "caption", component: "p", color: "text.secondary" }, audit26.description),
|
|
1175
|
-
primaryViolation && /* @__PURE__ */ React12.createElement(
|
|
1210
|
+
primaryViolation && /* @__PURE__ */ React12.createElement(
|
|
1211
|
+
GuidanceAction,
|
|
1212
|
+
{
|
|
1213
|
+
violation: primaryViolation,
|
|
1214
|
+
sharedAngiePrompt,
|
|
1215
|
+
panelZIndex
|
|
1216
|
+
}
|
|
1217
|
+
)
|
|
1176
1218
|
))), violations && violations.length > 0 && /* @__PURE__ */ React12.createElement(Box7, { role: "list", sx: { paddingBlockEnd: 1 } }, violations.map((violation, idx) => {
|
|
1177
1219
|
const widgetIcon = violation.elementId ? getElementIcon(violation.elementId) : null;
|
|
1178
1220
|
const elementTitle = violation.elementId ? getElementTitle(violation.elementId) : null;
|
|
1179
|
-
const
|
|
1221
|
+
const displayLabel = elementTitle ?? violation.label;
|
|
1222
|
+
const angiePromptContext = elementTitle ? `${elementTitle} - ${violation.label}` : violation.label;
|
|
1223
|
+
const showsOwnFixAction = !!violation.angieFix && !sharedAngiePrompt;
|
|
1180
1224
|
return /* @__PURE__ */ React12.createElement(
|
|
1181
1225
|
Box7,
|
|
1182
1226
|
{
|
|
@@ -1193,18 +1237,28 @@ function ViolationRow({ audit: audit26, expanded, onToggleExpand, skipReason, vi
|
|
|
1193
1237
|
paddingInline: 1,
|
|
1194
1238
|
borderRadius: 1,
|
|
1195
1239
|
cursor: "pointer",
|
|
1196
|
-
"&:hover": { bgcolor: "action.hover" }
|
|
1240
|
+
"&:hover": { bgcolor: "action.hover" },
|
|
1241
|
+
"&:hover .violation-row-fix-action, &:focus-visible .violation-row-fix-action": {
|
|
1242
|
+
opacity: 1
|
|
1243
|
+
}
|
|
1197
1244
|
}
|
|
1198
1245
|
},
|
|
1199
1246
|
/* @__PURE__ */ React12.createElement(ViolationIcon, { violation, widgetIcon }),
|
|
1200
|
-
/* @__PURE__ */ React12.createElement(Box7, { sx: { flex: 1 } }, /* @__PURE__ */ React12.createElement(Typography6, { variant: "caption" },
|
|
1201
|
-
|
|
1202
|
-
|
|
1247
|
+
/* @__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)),
|
|
1248
|
+
showsOwnFixAction && /* @__PURE__ */ React12.createElement(
|
|
1249
|
+
Box7,
|
|
1203
1250
|
{
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1251
|
+
className: "violation-row-fix-action",
|
|
1252
|
+
sx: { opacity: 0, transition: "opacity .15s" }
|
|
1253
|
+
},
|
|
1254
|
+
/* @__PURE__ */ React12.createElement(
|
|
1255
|
+
FixViolationWithAngie,
|
|
1256
|
+
{
|
|
1257
|
+
prompt: violation.angiePrompt ?? buildAngiePrompt(angiePromptContext),
|
|
1258
|
+
panelZIndex
|
|
1259
|
+
}
|
|
1260
|
+
)
|
|
1261
|
+
)
|
|
1208
1262
|
);
|
|
1209
1263
|
}))));
|
|
1210
1264
|
}
|
|
@@ -1406,7 +1460,7 @@ function findAuditRun(report, auditId) {
|
|
|
1406
1460
|
|
|
1407
1461
|
// src/components/promotion-card.tsx
|
|
1408
1462
|
import * as React15 from "react";
|
|
1409
|
-
import { Box as Box10, Button as
|
|
1463
|
+
import { Box as Box10, Button as Button5, Typography as Typography8 } from "@elementor/ui";
|
|
1410
1464
|
function PromotionCard({ ctaDisabled, ctaLabel, icon: Icon, onCtaClick, subtitle, title }) {
|
|
1411
1465
|
return /* @__PURE__ */ React15.createElement(
|
|
1412
1466
|
Box10,
|
|
@@ -1424,7 +1478,7 @@ function PromotionCard({ ctaDisabled, ctaLabel, icon: Icon, onCtaClick, subtitle
|
|
|
1424
1478
|
},
|
|
1425
1479
|
/* @__PURE__ */ React15.createElement(Icon, { fontSize: "small", color: "action" }),
|
|
1426
1480
|
/* @__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)),
|
|
1427
|
-
/* @__PURE__ */ React15.createElement(
|
|
1481
|
+
/* @__PURE__ */ React15.createElement(Button5, { variant: "outlined", color: "secondary", size: "small", disabled: ctaDisabled, onClick: onCtaClick }, ctaLabel)
|
|
1428
1482
|
);
|
|
1429
1483
|
}
|
|
1430
1484
|
|
|
@@ -1527,7 +1581,7 @@ function ReportShell({ report }) {
|
|
|
1527
1581
|
import * as React20 from "react";
|
|
1528
1582
|
import { useFloatingPanelZIndex as useFloatingPanelZIndex3 } from "@elementor/editor-floating-panels";
|
|
1529
1583
|
import { ReloadIcon } from "@elementor/icons";
|
|
1530
|
-
import { Badge as Badge2, Button as
|
|
1584
|
+
import { Badge as Badge2, Button as Button6, Tooltip as Tooltip4 } from "@elementor/ui";
|
|
1531
1585
|
import { __ as __16 } from "@wordpress/i18n";
|
|
1532
1586
|
function RescanButton({ hasScanned, isStale, disabled, onClick }) {
|
|
1533
1587
|
const panelZIndex = useFloatingPanelZIndex3(AUDIT_PANEL_ID);
|
|
@@ -1539,7 +1593,7 @@ function RescanButton({ hasScanned, isStale, disabled, onClick }) {
|
|
|
1539
1593
|
PopperProps: { sx: { zIndex: panelZIndex } }
|
|
1540
1594
|
},
|
|
1541
1595
|
/* @__PURE__ */ React20.createElement(Badge2, { variant: "dot", color: "warning", invisible: !isStale, overlap: "rectangular" }, /* @__PURE__ */ React20.createElement(
|
|
1542
|
-
|
|
1596
|
+
Button6,
|
|
1543
1597
|
{
|
|
1544
1598
|
variant: "contained",
|
|
1545
1599
|
size: "small",
|
|
@@ -2252,6 +2306,7 @@ var audit11 = {
|
|
|
2252
2306
|
if (!hasPageImages(ctx.elements.tree)) {
|
|
2253
2307
|
return { status: "skipped", reason: __29("No images", "elementor") };
|
|
2254
2308
|
}
|
|
2309
|
+
const isReady = ctx.pageContext.ally_plugin_active;
|
|
2255
2310
|
const violations = [];
|
|
2256
2311
|
const failedWidgetIds = /* @__PURE__ */ new Set();
|
|
2257
2312
|
let missingAltImageCount = 0;
|
|
@@ -2267,7 +2322,7 @@ var audit11 = {
|
|
|
2267
2322
|
elementId: node.id,
|
|
2268
2323
|
targetHint: "element-settings",
|
|
2269
2324
|
label: __29("Image is missing alt text.", "elementor"),
|
|
2270
|
-
externalUrl: ctx.pageContext.ally_plugin_url,
|
|
2325
|
+
externalUrl: isReady ? ctx.pageContext.ally_scan_url : ctx.pageContext.ally_plugin_url,
|
|
2271
2326
|
ctaLabel: __29("Fix with Ally", "elementor")
|
|
2272
2327
|
});
|
|
2273
2328
|
}
|
|
@@ -2288,6 +2343,7 @@ var audit12 = {
|
|
|
2288
2343
|
severity: "info",
|
|
2289
2344
|
weight: 1,
|
|
2290
2345
|
evaluate: (ctx) => {
|
|
2346
|
+
const isReady = ctx.pageContext.image_optimization_plugin_active;
|
|
2291
2347
|
const offendingElementIds = /* @__PURE__ */ new Set();
|
|
2292
2348
|
let hasAnyImage = false;
|
|
2293
2349
|
let inefficientImageFormatCount = 0;
|
|
@@ -2318,7 +2374,7 @@ var audit12 = {
|
|
|
2318
2374
|
elementId,
|
|
2319
2375
|
targetHint: "element-settings",
|
|
2320
2376
|
label: __30("Image isn't served in a modern format like WebP or AVIF.", "elementor"),
|
|
2321
|
-
externalUrl: ctx.pageContext.image_optimization_plugin_url,
|
|
2377
|
+
externalUrl: isReady ? ctx.pageContext.image_optimization_settings_url : ctx.pageContext.image_optimization_plugin_url,
|
|
2322
2378
|
ctaLabel: __30("Optimize all", "elementor")
|
|
2323
2379
|
}));
|
|
2324
2380
|
return violations.length === 0 ? { status: "pass" } : { status: "fail", violations, metadata: { inefficientImageFormatCount } };
|
|
@@ -2338,6 +2394,7 @@ var audit13 = {
|
|
|
2338
2394
|
severity: "warning",
|
|
2339
2395
|
weight: 7,
|
|
2340
2396
|
evaluate: (ctx) => {
|
|
2397
|
+
const isReady = ctx.pageContext.image_optimization_plugin_active;
|
|
2341
2398
|
const widgetMaxKb = /* @__PURE__ */ new Map();
|
|
2342
2399
|
let oversizedImageCount = 0;
|
|
2343
2400
|
let hasAnyImage = false;
|
|
@@ -2374,7 +2431,7 @@ var audit13 = {
|
|
|
2374
2431
|
__31("Image is %d KB (over 500 KB).", "elementor"),
|
|
2375
2432
|
kb
|
|
2376
2433
|
),
|
|
2377
|
-
externalUrl: ctx.pageContext.image_optimization_plugin_url,
|
|
2434
|
+
externalUrl: isReady ? ctx.pageContext.image_optimization_settings_url : ctx.pageContext.image_optimization_plugin_url,
|
|
2378
2435
|
ctaLabel: __31("Optimize all", "elementor")
|
|
2379
2436
|
}));
|
|
2380
2437
|
return violations.length === 0 ? { status: "pass" } : { status: "fail", violations, metadata: { oversizedImageCount } };
|
|
@@ -2409,7 +2466,12 @@ var audit14 = {
|
|
|
2409
2466
|
auditId: audit14.id,
|
|
2410
2467
|
elementId: node.id,
|
|
2411
2468
|
targetHint: "element-settings",
|
|
2412
|
-
label: __32("Nested boxed container.", "elementor")
|
|
2469
|
+
label: __32("Nested boxed container.", "elementor"),
|
|
2470
|
+
angieFix: true,
|
|
2471
|
+
angiePrompt: __32(
|
|
2472
|
+
"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.",
|
|
2473
|
+
"elementor"
|
|
2474
|
+
)
|
|
2413
2475
|
});
|
|
2414
2476
|
}
|
|
2415
2477
|
});
|