@wix/agent-skills 1.18.2 → 1.19.1
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/package.json +1 -1
- package/skills/wix-app/SKILL.md +42 -40
- package/skills/wix-app/references/BACKEND_API.md +151 -152
- package/skills/wix-app/references/DASHBOARD_PAGE.md +6 -10
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +16 -7
- package/skills/wix-app/references/EXTENSION_REGISTRATION.md +12 -8
- package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +53 -131
- package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +1 -2
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +83 -73
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +3 -2
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +9 -0
- package/skills/wix-app/references/editor-react-component/PARTS.md +5 -2
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +1 -1
- package/skills/wix-app/scripts/pkg-root.cjs +73 -0
- package/skills/wix-app/scripts/scan-a11y-code.cjs +310 -40
- package/skills/wix-app/scripts/scan-a11y-eslint.cjs +118 -24
- package/skills/wix-app/scripts/scan-a11y-render.cjs +551 -0
- package/skills/wix-app/scripts/scan-a11y-review.cjs +373 -0
- package/skills/wix-base44-connector/SKILL.md +24 -22
- package/skills/wix-base44-connector/scripts/utils.cjs +39 -3
- package/skills/wix-docs/SKILL.md +47 -20
- package/skills/wix-headless/entry/bootstrap.mjs +106 -50
- package/skills/wix-headless/entry/skill.md +5 -3
- package/skills/wix-headless/references/managed/AUTHENTICATION.md +25 -5
- package/skills/wix-headless-fast/SKILL.md +25 -7
- package/skills/wix-headless-fast/entry/skill.md +23 -14
- package/skills/wix-headless-fast/install/fast-path.mjs +48 -5
- package/skills/wix-headless-fast/install/pin-agents-md.mjs +57 -0
- package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +3 -3
- package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +204 -35
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +146 -36
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +8 -2
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +95 -20
- package/skills/wix-headless-fast/references/storefront/seed/SEED.md +21 -2
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +104 -18
- package/skills/wix-manage/SKILL.md +14 -8
- package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +59 -33
- package/skills/wix-manage/references/bookings/bookings-staff-setup.md +45 -22
- package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +70 -12
- package/skills/wix-manage/references/calendar/configure-default-business-hours.md +53 -17
- package/skills/wix-manage/references/google-ads/billing-and-payment.md +3 -3
- package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +8 -8
- package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +4 -4
- package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +1 -1
- package/skills/wix-manage/references/google-ads/install-and-create-account.md +9 -9
- package/skills/wix-manage/references/google-ads/query-campaign-analytics.md +7 -7
- package/skills/wix-manage/references/seo/manage-content-plan.md +181 -135
- package/skills/wix-manage/references/seo/manage-google-search-console.md +272 -0
- package/skills/wix-manage/references/sites/upload-static-site.md +53 -0
- package/skills/wix-manage/references/stores/change-store-currency.md +1 -1
- package/skills/wix-manage/references/stores/create-product-catalog-v3.md +17 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +12 -9
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +12 -9
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +1 -1
- package/skills/wix-vibe-headless/platforms/base44.md +11 -3
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +5 -1
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +5 -4
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.cjs +33 -5
- package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +0 -80
- package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +0 -140
- package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +0 -112
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +0 -100
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +0 -130
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +0 -48
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +0 -66
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +0 -103
- package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +0 -56
- package/skills/wix-headless-fast/references/storefront/app-astro/pages/shop.astro +0 -23
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
// oxlint-disable no-console preserve-caught-error
|
|
5
5
|
|
|
6
|
+
const fs = require('fs');
|
|
6
7
|
const path = require('path');
|
|
7
8
|
const { createRequire } = require('module');
|
|
8
9
|
|
|
@@ -34,10 +35,11 @@ const RULE_CONFIG = {
|
|
|
34
35
|
'jsx-a11y/no-aria-hidden-on-focusable': 'error',
|
|
35
36
|
'jsx-a11y/no-autofocus': 'error',
|
|
36
37
|
'jsx-a11y/no-distracting-elements': 'error',
|
|
37
|
-
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
|
|
38
|
+
'jsx-a11y/no-interactive-element-to-noninteractive-role': ['error', { canvas: ['img'] }],
|
|
38
39
|
'jsx-a11y/no-noninteractive-element-interactions': 'error',
|
|
39
40
|
'jsx-a11y/no-noninteractive-element-to-interactive-role': 'error',
|
|
40
|
-
|
|
41
|
+
// A tabpanel with no focusable content takes tabIndex=0 (ARIA Authoring Practices).
|
|
42
|
+
'jsx-a11y/no-noninteractive-tabindex': ['error', { roles: ['tabpanel'] }],
|
|
41
43
|
'jsx-a11y/no-redundant-roles': 'error',
|
|
42
44
|
'jsx-a11y/no-static-element-interactions': 'error',
|
|
43
45
|
'jsx-a11y/prefer-tag-over-role': 'error',
|
|
@@ -51,6 +53,86 @@ function toRelative(filePath) {
|
|
|
51
53
|
return path.relative(ROOT, filePath) || filePath;
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
/** DOM handler → SDK prop it forwards (FUNCTION-HANDLERS.md). */
|
|
57
|
+
const SDK_HANDLER_PROPS = {
|
|
58
|
+
onClick: 'onClick',
|
|
59
|
+
onDoubleClick: 'onDblClick',
|
|
60
|
+
onMouseEnter: 'onMouseIn',
|
|
61
|
+
onMouseLeave: 'onMouseOut',
|
|
62
|
+
};
|
|
63
|
+
const isSdkRoot = (tag) => /\bid=\{\s*(?:props\.)?id\s*\}/.test(tag);
|
|
64
|
+
|
|
65
|
+
/** Every handler on the tag forwards its SDK prop, `onClick={onClick}` or `onMouseEnter={props.onMouseIn}`; anything else makes the root a control. */
|
|
66
|
+
function forwardsOnlySdkHandlers(tag) {
|
|
67
|
+
const handlers = [...tag.matchAll(/\b(on[A-Z]\w*)=\{([^}]*)\}/g)];
|
|
68
|
+
return (
|
|
69
|
+
handlers.length > 0 &&
|
|
70
|
+
handlers.every(([, name, value]) => {
|
|
71
|
+
const sdkProp = SDK_HANDLER_PROPS[name];
|
|
72
|
+
return Boolean(sdkProp) && value.trim().replace(/^props\./, '') === sdkProp;
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Roles whose native element cannot express a styled component. */
|
|
78
|
+
const ROLES_WITHOUT_NATIVE_TAG = new Set(['img', 'presentation', 'none', 'group', 'status']);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* `role="img"` or `role={cond ? 'img' : undefined}`: every string literal in the role
|
|
82
|
+
* attribute must be an exempt role, so `role={cond ? 'button' : 'img'}` stays flagged.
|
|
83
|
+
*/
|
|
84
|
+
function roleHasNoNativeTag(tag) {
|
|
85
|
+
const attr = tag.match(/\brole=(?:"[^"]*"|'[^']*'|\{[^}]*\})/);
|
|
86
|
+
if (!attr) return false;
|
|
87
|
+
const literals = [...attr[0].slice(5).matchAll(/["']([^"']*)["']/g)].map((m) => m[1]);
|
|
88
|
+
return literals.length > 0 && literals.every((role) => ROLES_WITHOUT_NATIVE_TAG.has(role));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Editor React Component patterns that jsx-a11y reads as defects. A rule in
|
|
93
|
+
* `rules` is skipped when the opening tag of the reported element matches `tag`.
|
|
94
|
+
*/
|
|
95
|
+
const EXEMPTIONS = [
|
|
96
|
+
{
|
|
97
|
+
// SDK handlers (`onClick`, `onMouseIn`, ...) are forwarded on the root
|
|
98
|
+
// element, which carries `id={id}`; the root itself is not the control.
|
|
99
|
+
rules: new Set([
|
|
100
|
+
'jsx-a11y/click-events-have-key-events',
|
|
101
|
+
'jsx-a11y/mouse-events-have-key-events',
|
|
102
|
+
'jsx-a11y/no-noninteractive-element-interactions',
|
|
103
|
+
'jsx-a11y/no-static-element-interactions',
|
|
104
|
+
]),
|
|
105
|
+
tag: (tag) => isSdkRoot(tag) && forwardsOnlySdkHandlers(tag),
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
// Roles whose native element cannot express a styled component: graphics
|
|
109
|
+
// (svg, canvas, star ratings), decorative wrappers, widget groups, live
|
|
110
|
+
// regions. axe still requires their names (`role-img-alt`).
|
|
111
|
+
rules: new Set(['jsx-a11y/prefer-tag-over-role']),
|
|
112
|
+
tag: roleHasNoNativeTag,
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
/** Text of the opening tag that contains the reported range. */
|
|
117
|
+
function openingTag(source, msg) {
|
|
118
|
+
const lines = source.split('\n');
|
|
119
|
+
const offset =
|
|
120
|
+
lines.slice(0, msg.line - 1).reduce((n, line) => n + line.length + 1, 0) + msg.column - 1;
|
|
121
|
+
const start = source.lastIndexOf('<', offset);
|
|
122
|
+
if (start === -1) return '';
|
|
123
|
+
// The tag ends at the first `>` outside braces, so `=>` inside handlers does not count.
|
|
124
|
+
let depth = 0;
|
|
125
|
+
for (let i = start; i < source.length; i++) {
|
|
126
|
+
if (source[i] === '{') depth++;
|
|
127
|
+
else if (source[i] === '}') depth--;
|
|
128
|
+
else if (source[i] === '>' && depth === 0) return source.slice(start, i);
|
|
129
|
+
}
|
|
130
|
+
return '';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const isExempt = (source, msg) =>
|
|
134
|
+
EXEMPTIONS.some((x) => x.rules.has(msg.ruleId) && x.tag(openingTag(source, msg)));
|
|
135
|
+
|
|
54
136
|
function severityLabel(severity) {
|
|
55
137
|
if (severity === 2) return 'error';
|
|
56
138
|
if (severity === 1) return 'warning';
|
|
@@ -117,22 +199,11 @@ function createEslint() {
|
|
|
117
199
|
}
|
|
118
200
|
}
|
|
119
201
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
{
|
|
126
|
-
error: 'No files specified.',
|
|
127
|
-
usage: 'node <SKILL_ROOT>/scripts/scan-a11y-eslint.cjs <file1> [file2] ...',
|
|
128
|
-
},
|
|
129
|
-
null,
|
|
130
|
-
2,
|
|
131
|
-
),
|
|
132
|
-
);
|
|
133
|
-
process.exit(1);
|
|
134
|
-
}
|
|
135
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Lint the given files with the jsx-a11y rule set.
|
|
204
|
+
* Returns the same report shape the CLI prints.
|
|
205
|
+
*/
|
|
206
|
+
async function scan(files) {
|
|
136
207
|
const absoluteFiles = files.map((f) => path.resolve(f));
|
|
137
208
|
|
|
138
209
|
const eslint = createEslint();
|
|
@@ -144,6 +215,7 @@ async function main() {
|
|
|
144
215
|
|
|
145
216
|
for (const result of results) {
|
|
146
217
|
const relFile = toRelative(result.filePath);
|
|
218
|
+
const source = () => result.source || fs.readFileSync(result.filePath, 'utf8');
|
|
147
219
|
|
|
148
220
|
for (const msg of result.messages) {
|
|
149
221
|
if (msg.fatal) {
|
|
@@ -157,6 +229,7 @@ async function main() {
|
|
|
157
229
|
}
|
|
158
230
|
|
|
159
231
|
if (!msg.ruleId || !msg.ruleId.startsWith('jsx-a11y/')) continue;
|
|
232
|
+
if (isExempt(source(), msg)) continue;
|
|
160
233
|
|
|
161
234
|
findings.push({
|
|
162
235
|
file: relFile,
|
|
@@ -176,7 +249,7 @@ async function main() {
|
|
|
176
249
|
ruleBreakdown[f.rule] = (ruleBreakdown[f.rule] || 0) + 1;
|
|
177
250
|
}
|
|
178
251
|
|
|
179
|
-
|
|
252
|
+
return {
|
|
180
253
|
meta: {
|
|
181
254
|
filesScanned: files.length,
|
|
182
255
|
engine: 'eslint + eslint-plugin-jsx-a11y',
|
|
@@ -191,11 +264,32 @@ async function main() {
|
|
|
191
264
|
ruleBreakdown,
|
|
192
265
|
},
|
|
193
266
|
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async function main() {
|
|
270
|
+
const files = process.argv.slice(2);
|
|
271
|
+
if (files.length === 0) {
|
|
272
|
+
console.log(
|
|
273
|
+
JSON.stringify(
|
|
274
|
+
{
|
|
275
|
+
error: 'No files specified.',
|
|
276
|
+
usage: 'node <SKILL_ROOT>/scripts/scan-a11y-eslint.cjs <file1> [file2] ...',
|
|
277
|
+
},
|
|
278
|
+
null,
|
|
279
|
+
2,
|
|
280
|
+
),
|
|
281
|
+
);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
194
284
|
|
|
195
|
-
console.log(JSON.stringify(
|
|
285
|
+
console.log(JSON.stringify(await scan(files), null, 2));
|
|
196
286
|
}
|
|
197
287
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
288
|
+
module.exports = { scan, RULE_CONFIG };
|
|
289
|
+
|
|
290
|
+
if (require.main === module) {
|
|
291
|
+
main().catch((err) => {
|
|
292
|
+
console.error(JSON.stringify({ error: err.message }, null, 2));
|
|
293
|
+
process.exit(1);
|
|
294
|
+
});
|
|
295
|
+
}
|