@code-pushup/axe-plugin 0.95.2 → 0.96.0

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/README.md CHANGED
@@ -159,6 +159,66 @@ The plugin organizes audits into category groups based on axe-core's accessibili
159
159
 
160
160
  Use `npx code-pushup print-config --onlyPlugins=axe` to list all audits and groups for your configuration.
161
161
 
162
+ ## Category integration
163
+
164
+ The plugin provides helpers to integrate Axe results into your categories.
165
+
166
+ ### Auto-generate accessibility category
167
+
168
+ Use `axeCategories` to automatically create an accessibility category from all plugin groups:
169
+
170
+ ```ts
171
+ import axePlugin, { axeCategories } from '@code-pushup/axe-plugin';
172
+
173
+ const axe = axePlugin('https://example.com');
174
+
175
+ export default {
176
+ plugins: [axe],
177
+ categories: axeCategories(axe),
178
+ };
179
+ ```
180
+
181
+ This configuration works with both single-URL and multi-URL configurations. For multi-URL setups, refs are automatically expanded for each URL with appropriate weights.
182
+
183
+ ### Custom categories
184
+
185
+ For fine-grained control, provide your own categories with specific groups:
186
+
187
+ ```ts
188
+ import axePlugin, { axeCategories, axeGroupRef } from '@code-pushup/axe-plugin';
189
+
190
+ const axe = axePlugin(['https://example.com', 'https://example.com/about']);
191
+
192
+ export default {
193
+ plugins: [axe],
194
+ categories: axeCategories(axe, [
195
+ {
196
+ slug: 'axe-a11y',
197
+ title: 'Axe Accessibility',
198
+ refs: [axeGroupRef('aria', 2), axeGroupRef('color'), axeGroupRef('keyboard')],
199
+ },
200
+ ]),
201
+ };
202
+ ```
203
+
204
+ ### Helper functions
205
+
206
+ | Function | Description |
207
+ | --------------- | -------------------------------------- |
208
+ | `axeCategories` | Auto-generates or expands categories |
209
+ | `axeGroupRef` | Creates a category ref to an Axe group |
210
+ | `axeAuditRef` | Creates a category ref to an Axe audit |
211
+
212
+ ### Type safety
213
+
214
+ The `AxeGroupSlug` type is exported for discovering valid group slugs:
215
+
216
+ ```ts
217
+ import type { AxeGroupSlug } from '@code-pushup/axe-plugin';
218
+
219
+ const group: AxeGroupSlug = 'aria';
220
+ ```
221
+
162
222
  ## Resources
163
223
 
164
224
  - **[Axe-core rules](https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md)** - Complete list of accessibility rules
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-pushup/axe-plugin",
3
- "version": "0.95.2",
3
+ "version": "0.96.0",
4
4
  "license": "MIT",
5
5
  "description": "Code PushUp plugin for detecting accessibility issues using Axe 🌐",
6
6
  "homepage": "https://github.com/code-pushup/cli/tree/main/packages/plugin-axe#readme",
@@ -42,8 +42,8 @@
42
42
  "type": "module",
43
43
  "dependencies": {
44
44
  "@axe-core/playwright": "^4.11.0",
45
- "@code-pushup/models": "0.95.2",
46
- "@code-pushup/utils": "0.95.2",
45
+ "@code-pushup/models": "0.96.0",
46
+ "@code-pushup/utils": "0.96.0",
47
47
  "axe-core": "^4.11.0",
48
48
  "playwright-core": "^1.56.1",
49
49
  "zod": "^4.1.12"
package/src/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { axePlugin } from './lib/axe-plugin.js';
2
2
  export default axePlugin;
3
- export type { AxePluginOptions } from './lib/config.js';
4
- export type { AxePreset } from './lib/config.js';
3
+ export type { AxePluginOptions, AxePreset } from './lib/config.js';
4
+ export type { AxeGroupSlug } from './lib/groups.js';
5
+ export { axeAuditRef, axeGroupRef } from './lib/utils.js';
6
+ export { axeCategories } from './lib/categories.js';
package/src/index.js CHANGED
@@ -1,3 +1,5 @@
1
1
  import { axePlugin } from './lib/axe-plugin.js';
2
2
  export default axePlugin;
3
+ export { axeAuditRef, axeGroupRef } from './lib/utils.js';
4
+ export { axeCategories } from './lib/categories.js';
3
5
  //# sourceMappingURL=index.js.map
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,eAAe,SAAS,CAAC;AAKzB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { CategoryConfig, Group, PluginConfig } from '@code-pushup/models';
2
+ import { type PluginUrlContext } from '@code-pushup/utils';
3
+ import { type AxeCategoryGroupSlug } from './groups.js';
4
+ /**
5
+ * Creates categories for the Axe plugin.
6
+ *
7
+ * @public
8
+ * @param plugin - {@link PluginConfig} object with groups and context
9
+ * @param categories - {@link CategoryConfig} optional user-defined categories
10
+ * @returns {CategoryConfig[]} - expanded and aggregated categories
11
+ *
12
+ * @example
13
+ * const axe = await axePlugin(urls);
14
+ * const axeCoreConfig = {
15
+ * plugins: [axe],
16
+ * categories: axeCategories(axe),
17
+ * };
18
+ */
19
+ export declare function axeCategories(plugin: Pick<PluginConfig, 'groups' | 'context'>, categories?: CategoryConfig[]): CategoryConfig[];
20
+ export declare function createAggregatedCategory(groups: Group[], context: PluginUrlContext): CategoryConfig;
21
+ export declare function expandAggregatedCategory(category: CategoryConfig, context: PluginUrlContext): CategoryConfig;
22
+ export declare function extractGroupSlugs(groups: Group[]): AxeCategoryGroupSlug[];
@@ -0,0 +1,56 @@
1
+ import { createCategoryRefs, expandCategoryRefs, removeIndex, shouldExpandForUrls, validateUrlContext, } from '@code-pushup/utils';
2
+ import { AXE_PLUGIN_SLUG } from './constants.js';
3
+ import { isAxeGroupSlug } from './groups.js';
4
+ /**
5
+ * Creates categories for the Axe plugin.
6
+ *
7
+ * @public
8
+ * @param plugin - {@link PluginConfig} object with groups and context
9
+ * @param categories - {@link CategoryConfig} optional user-defined categories
10
+ * @returns {CategoryConfig[]} - expanded and aggregated categories
11
+ *
12
+ * @example
13
+ * const axe = await axePlugin(urls);
14
+ * const axeCoreConfig = {
15
+ * plugins: [axe],
16
+ * categories: axeCategories(axe),
17
+ * };
18
+ */
19
+ export function axeCategories(plugin, categories) {
20
+ if (!plugin.groups || plugin.groups.length === 0) {
21
+ return categories ?? [];
22
+ }
23
+ validateUrlContext(plugin.context);
24
+ if (!categories) {
25
+ return createCategories(plugin.groups, plugin.context);
26
+ }
27
+ return expandCategories(categories, plugin.context);
28
+ }
29
+ function createCategories(groups, context) {
30
+ return [createAggregatedCategory(groups, context)];
31
+ }
32
+ function expandCategories(categories, context) {
33
+ if (!shouldExpandForUrls(context.urlCount)) {
34
+ return categories;
35
+ }
36
+ return categories.map(category => expandAggregatedCategory(category, context));
37
+ }
38
+ export function createAggregatedCategory(groups, context) {
39
+ const refs = extractGroupSlugs(groups).flatMap(slug => createCategoryRefs(slug, AXE_PLUGIN_SLUG, context));
40
+ return {
41
+ slug: 'axe-a11y',
42
+ title: 'Axe Accessibility',
43
+ refs,
44
+ };
45
+ }
46
+ export function expandAggregatedCategory(category, context) {
47
+ return {
48
+ ...category,
49
+ refs: category.refs.flatMap(ref => ref.plugin === AXE_PLUGIN_SLUG ? expandCategoryRefs(ref, context) : [ref]),
50
+ };
51
+ }
52
+ export function extractGroupSlugs(groups) {
53
+ const slugs = groups.map(({ slug }) => removeIndex(slug));
54
+ return [...new Set(slugs)].filter(isAxeGroupSlug);
55
+ }
56
+ //# sourceMappingURL=categories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"categories.js","sourceRoot":"","sources":["../../../src/lib/categories.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAA6B,cAAc,EAAE,MAAM,aAAa,CAAC;AAExE;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAgD,EAChD,UAA6B;IAE7B,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,OAAO,UAAU,IAAI,EAAE,CAAC;IAC1B,CAAC;IACD,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,gBAAgB,CACvB,MAAe,EACf,OAAyB;IAEzB,OAAO,CAAC,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,gBAAgB,CACvB,UAA4B,EAC5B,OAAyB;IAEzB,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3C,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAC/B,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAC5C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,MAAe,EACf,OAAyB;IAEzB,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CACpD,kBAAkB,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,CACnD,CAAC;IACF,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,mBAAmB;QAC1B,IAAI;KACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,QAAwB,EACxB,OAAyB;IAEzB,OAAO;QACL,GAAG,QAAQ;QACX,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAChC,GAAG,CAAC,MAAM,KAAK,eAAe,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAC1E;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAe;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AACpD,CAAC"}
@@ -30,6 +30,7 @@ export declare const axeCategoryGroupSlugSchema: z.ZodEnum<{
30
30
  }>;
31
31
  export type AxeCategoryGroupSlug = z.infer<typeof axeCategoryGroupSlugSchema>;
32
32
  export declare const CATEGORY_GROUPS: Record<AxeCategoryGroupSlug, string>;
33
+ export declare function isAxeGroupSlug(slug: unknown): slug is AxeCategoryGroupSlug;
33
34
  export declare const axeGroupSlugSchema: z.ZodEnum<{
34
35
  aria: "aria";
35
36
  color: "color";
package/src/lib/groups.js CHANGED
@@ -55,6 +55,9 @@ export const CATEGORY_GROUPS = {
55
55
  'text-alternatives': 'Text Alternatives',
56
56
  'time-and-media': 'Media',
57
57
  };
58
+ export function isAxeGroupSlug(slug) {
59
+ return axeCategoryGroupSlugSchema.safeParse(slug).success;
60
+ }
58
61
  /* Combined exports */
59
62
  export const axeGroupSlugSchema = axeCategoryGroupSlugSchema;
60
63
  //# sourceMappingURL=groups.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"groups.js","sourceRoot":"","sources":["../../../src/lib/groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,mCAAmC;AACnC,MAAM,WAAW,GAAG;IAClB,QAAQ;IACR,SAAS;IACT,SAAS;IACT,UAAU;IACV,UAAU;CACF,CAAC;AAEX,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC;KAC9B,IAAI,CAAC,WAAW,CAAC;KACjB,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;AAIjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,eAAe;KAC/C,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;KACjC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;AAIpC,MAAM,gBAAgB,GAAwC;IAC5D,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC;IACtD,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC;CACnE,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC;AAED,qCAAqC;AACrC,MAAM,qBAAqB,GAAG;IAC5B,MAAM;IACN,OAAO;IACP,OAAO;IACP,UAAU;IACV,UAAU;IACV,iBAAiB;IACjB,SAAS;IACT,WAAW;IACX,yBAAyB;IACzB,WAAW;IACX,QAAQ;IACR,mBAAmB;IACnB,gBAAgB;CACR,CAAC;AAEX,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC;KACxC,IAAI,CAAC,qBAAqB,CAAC;KAC3B,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;AAI3C,MAAM,CAAC,MAAM,eAAe,GAAyC;IACnE,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,kBAAkB;IACzB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IACpB,iBAAiB,EAAE,gBAAgB;IACnC,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,yBAAyB,EAAE,aAAa;IACxC,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,QAAQ;IAChB,mBAAmB,EAAE,mBAAmB;IACxC,gBAAgB,EAAE,OAAO;CAC1B,CAAC;AAEF,sBAAsB;AACtB,MAAM,CAAC,MAAM,kBAAkB,GAAG,0BAA0B,CAAC"}
1
+ {"version":3,"file":"groups.js","sourceRoot":"","sources":["../../../src/lib/groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,mCAAmC;AACnC,MAAM,WAAW,GAAG;IAClB,QAAQ;IACR,SAAS;IACT,SAAS;IACT,UAAU;IACV,UAAU;CACF,CAAC;AAEX,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC;KAC9B,IAAI,CAAC,WAAW,CAAC;KACjB,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;AAIjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,eAAe;KAC/C,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;KACjC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;AAIpC,MAAM,gBAAgB,GAAwC;IAC5D,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC;IACtD,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC;CACnE,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC;AAED,qCAAqC;AACrC,MAAM,qBAAqB,GAAG;IAC5B,MAAM;IACN,OAAO;IACP,OAAO;IACP,UAAU;IACV,UAAU;IACV,iBAAiB;IACjB,SAAS;IACT,WAAW;IACX,yBAAyB;IACzB,WAAW;IACX,QAAQ;IACR,mBAAmB;IACnB,gBAAgB;CACR,CAAC;AAEX,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC;KACxC,IAAI,CAAC,qBAAqB,CAAC;KAC3B,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;AAI3C,MAAM,CAAC,MAAM,eAAe,GAAyC;IACnE,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,kBAAkB;IACzB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IACpB,iBAAiB,EAAE,gBAAgB;IACnC,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,yBAAyB,EAAE,aAAa;IACxC,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,QAAQ;IAChB,mBAAmB,EAAE,mBAAmB;IACxC,gBAAgB,EAAE,OAAO;CAC1B,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,OAAO,0BAA0B,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AAC5D,CAAC;AAED,sBAAsB;AACtB,MAAM,CAAC,MAAM,kBAAkB,GAAG,0BAA0B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { CategoryRef } from '@code-pushup/models';
2
+ import type { AxeGroupSlug } from './groups.js';
3
+ export declare function axeGroupRef(groupSlug: AxeGroupSlug, weight?: number): CategoryRef;
4
+ export declare function axeAuditRef(auditSlug: string, weight?: number): CategoryRef;
@@ -0,0 +1,18 @@
1
+ import { AXE_PLUGIN_SLUG } from './constants.js';
2
+ export function axeGroupRef(groupSlug, weight = 1) {
3
+ return {
4
+ plugin: AXE_PLUGIN_SLUG,
5
+ slug: groupSlug,
6
+ type: 'group',
7
+ weight,
8
+ };
9
+ }
10
+ export function axeAuditRef(auditSlug, weight = 1) {
11
+ return {
12
+ plugin: AXE_PLUGIN_SLUG,
13
+ slug: auditSlug,
14
+ type: 'audit',
15
+ weight,
16
+ };
17
+ }
18
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,MAAM,UAAU,WAAW,CAAC,SAAuB,EAAE,MAAM,GAAG,CAAC;IAC7D,OAAO;QACL,MAAM,EAAE,eAAe;QACvB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,MAAM,GAAG,CAAC;IACvD,OAAO;QACL,MAAM,EAAE,eAAe;QACvB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,MAAM;KACP,CAAC;AACJ,CAAC"}