@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.
Files changed (68) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +42 -40
  3. package/skills/wix-app/references/BACKEND_API.md +151 -152
  4. package/skills/wix-app/references/DASHBOARD_PAGE.md +6 -10
  5. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +16 -7
  6. package/skills/wix-app/references/EXTENSION_REGISTRATION.md +12 -8
  7. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +53 -131
  8. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +1 -2
  9. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +83 -73
  10. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +3 -2
  11. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +9 -0
  12. package/skills/wix-app/references/editor-react-component/PARTS.md +5 -2
  13. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +1 -1
  14. package/skills/wix-app/scripts/pkg-root.cjs +73 -0
  15. package/skills/wix-app/scripts/scan-a11y-code.cjs +310 -40
  16. package/skills/wix-app/scripts/scan-a11y-eslint.cjs +118 -24
  17. package/skills/wix-app/scripts/scan-a11y-render.cjs +551 -0
  18. package/skills/wix-app/scripts/scan-a11y-review.cjs +373 -0
  19. package/skills/wix-base44-connector/SKILL.md +24 -22
  20. package/skills/wix-base44-connector/scripts/utils.cjs +39 -3
  21. package/skills/wix-docs/SKILL.md +47 -20
  22. package/skills/wix-headless/entry/bootstrap.mjs +106 -50
  23. package/skills/wix-headless/entry/skill.md +5 -3
  24. package/skills/wix-headless/references/managed/AUTHENTICATION.md +25 -5
  25. package/skills/wix-headless-fast/SKILL.md +25 -7
  26. package/skills/wix-headless-fast/entry/skill.md +23 -14
  27. package/skills/wix-headless-fast/install/fast-path.mjs +48 -5
  28. package/skills/wix-headless-fast/install/pin-agents-md.mjs +57 -0
  29. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +3 -3
  30. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +204 -35
  31. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +146 -36
  32. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +8 -2
  33. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +95 -20
  34. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +21 -2
  35. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +104 -18
  36. package/skills/wix-manage/SKILL.md +14 -8
  37. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +59 -33
  38. package/skills/wix-manage/references/bookings/bookings-staff-setup.md +45 -22
  39. package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +70 -12
  40. package/skills/wix-manage/references/calendar/configure-default-business-hours.md +53 -17
  41. package/skills/wix-manage/references/google-ads/billing-and-payment.md +3 -3
  42. package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +8 -8
  43. package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +4 -4
  44. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +1 -1
  45. package/skills/wix-manage/references/google-ads/install-and-create-account.md +9 -9
  46. package/skills/wix-manage/references/google-ads/query-campaign-analytics.md +7 -7
  47. package/skills/wix-manage/references/seo/manage-content-plan.md +181 -135
  48. package/skills/wix-manage/references/seo/manage-google-search-console.md +272 -0
  49. package/skills/wix-manage/references/sites/upload-static-site.md +53 -0
  50. package/skills/wix-manage/references/stores/change-store-currency.md +1 -1
  51. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +17 -1
  52. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +12 -9
  53. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +12 -9
  54. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +1 -1
  55. package/skills/wix-vibe-headless/platforms/base44.md +11 -3
  56. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +5 -1
  57. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +5 -4
  58. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.cjs +33 -5
  59. package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +0 -80
  60. package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +0 -140
  61. package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +0 -112
  62. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +0 -100
  63. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +0 -130
  64. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +0 -48
  65. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +0 -66
  66. package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +0 -103
  67. package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +0 -56
  68. 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
- 'jsx-a11y/no-noninteractive-tabindex': 'error',
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
- async function main() {
121
- const files = process.argv.slice(2);
122
- if (files.length === 0) {
123
- console.log(
124
- JSON.stringify(
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
- const output = {
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(output, null, 2));
285
+ console.log(JSON.stringify(await scan(files), null, 2));
196
286
  }
197
287
 
198
- main().catch((err) => {
199
- console.error(JSON.stringify({ error: err.message }, null, 2));
200
- process.exit(1);
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
+ }