@github/axe-github
Advanced tools
| import type { Check, Rule } from 'axe-core'; | ||
| interface RuleOptions { | ||
| id: string; | ||
| excludeHidden?: boolean; | ||
| selector: string; | ||
| checks?: Array<(el: Element) => boolean>; | ||
| all?: string[]; | ||
| any?: string[]; | ||
| help: string; | ||
| helpUrl?: string; | ||
| } | ||
| export declare function createRule({ id, excludeHidden, selector, checks, all, any, help, helpUrl }: RuleOptions): void; | ||
| declare const _default: { | ||
| rules: Rule[]; | ||
| checks: Check[]; | ||
| }; | ||
| export default _default; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.createRule = void 0; | ||
| const interactiveElements = ['a[href]', 'button', 'summary', 'select', 'input:not([type=hidden])', 'textarea']; | ||
| const focusableElements = interactiveElements.concat(['[tabindex]']); | ||
| const generatedChecks = []; | ||
| const generatedRules = []; | ||
| createRule({ | ||
| id: 'menuitem-should-be-interactive', | ||
| selector: 'div[role="menuitem"], span[role="menuitem"], div[role="menuitemradio"], span[role="menuitemradio"], div[role="menuitemcheckbox"], span[role="menuitemcheckbox"]', | ||
| help: 'Menu items must be focusable. Use <button>, <a>, or <label tabindex="0">', | ||
| checks: [ | ||
| (el) => focusableElements.filter(s => el.matches(s)).length > 0 | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'empty-summary', | ||
| selector: 'summary', | ||
| help: 'Details summary element must have visible text', | ||
| any: ['has-visible-text', 'aria-label', 'aria-labelledby', 'role-presentation', 'role-none', 'non-empty-title'] | ||
| }); | ||
| createRule({ | ||
| id: 'submit-reset-button-must-be-in-form', | ||
| selector: 'button[type="submit"], button[type="reset"], input[type="submit"], input[type="reset"]', | ||
| help: 'Submit and reset buttons must be in a form', | ||
| checks: [ | ||
| el => { | ||
| const formId = el.getAttribute('form'); | ||
| return !!el.closest('form') || !!(formId && document.getElementById(formId)); | ||
| } | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'nested-forms', | ||
| selector: 'form', | ||
| help: 'Nested form is invalid HTML and should be avoided', | ||
| helpUrl: 'https://html.spec.whatwg.org/multipage/forms.html#the-form-element:concept-element-content-model', | ||
| checks: [ | ||
| el => { | ||
| return !(el.parentElement && el.parentElement.closest('form')); | ||
| } | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'avoid-both-disabled-and-aria-disabled', | ||
| selector: 'button, fieldset, input, optgroup, option, select, textarea', | ||
| help: '[aria-disabled] may be used in place of native HTML [disabled] to allow tab-focus on an otherwise ignored element. Setting both attributes is contradictory.', | ||
| helpUrl: 'https://www.w3.org/TR/html-aria/#docconformance-attr', | ||
| checks: [ | ||
| el => !(el.hasAttribute('aria-disabled') && el.hasAttribute('disabled')) | ||
| ] | ||
| }); | ||
| function createRule({ id, excludeHidden = true, selector, checks = [], all = [], any = [], help, helpUrl = '' }) { | ||
| if (/[^,] /.test(selector)) { | ||
| console.warn('Try to avoid nested CSS selectors in `createRule`: %o', selector); | ||
| } | ||
| if (checks) { | ||
| checks.map((func, i) => { | ||
| const checkId = `${id}_${i}`; | ||
| if (all) | ||
| all.push(checkId); | ||
| generatedChecks.push({ | ||
| id: checkId, | ||
| evaluate: func, | ||
| metadata: { impact: 'critical' } | ||
| }); | ||
| }); | ||
| } | ||
| generatedRules.push({ id, excludeHidden, selector, all, any, metadata: { help, helpUrl }, tags: ['custom-github-rule'] }); | ||
| } | ||
| exports.createRule = createRule; | ||
| exports.default = { | ||
| rules: generatedRules, | ||
| checks: generatedChecks | ||
| }; |
| import type { Check, Rule } from 'axe-core'; | ||
| interface RuleOptions { | ||
| id: string; | ||
| excludeHidden?: boolean; | ||
| selector: string; | ||
| checks?: Array<(el: Element) => boolean>; | ||
| all?: string[]; | ||
| any?: string[]; | ||
| help: string; | ||
| helpUrl?: string; | ||
| } | ||
| export declare function createRule({ id, excludeHidden, selector, checks, all, any, help, helpUrl }: RuleOptions): void; | ||
| declare const _default: { | ||
| rules: Rule[]; | ||
| checks: Check[]; | ||
| }; | ||
| export default _default; |
| const interactiveElements = ['a[href]', 'button', 'summary', 'select', 'input:not([type=hidden])', 'textarea']; | ||
| const focusableElements = interactiveElements.concat(['[tabindex]']); | ||
| const generatedChecks = []; | ||
| const generatedRules = []; | ||
| createRule({ | ||
| id: 'menuitem-should-be-interactive', | ||
| selector: 'div[role="menuitem"], span[role="menuitem"], div[role="menuitemradio"], span[role="menuitemradio"], div[role="menuitemcheckbox"], span[role="menuitemcheckbox"]', | ||
| help: 'Menu items must be focusable. Use <button>, <a>, or <label tabindex="0">', | ||
| checks: [ | ||
| (el) => focusableElements.filter(s => el.matches(s)).length > 0 | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'empty-summary', | ||
| selector: 'summary', | ||
| help: 'Details summary element must have visible text', | ||
| any: ['has-visible-text', 'aria-label', 'aria-labelledby', 'role-presentation', 'role-none', 'non-empty-title'] | ||
| }); | ||
| createRule({ | ||
| id: 'submit-reset-button-must-be-in-form', | ||
| selector: 'button[type="submit"], button[type="reset"], input[type="submit"], input[type="reset"]', | ||
| help: 'Submit and reset buttons must be in a form', | ||
| checks: [ | ||
| el => { | ||
| const formId = el.getAttribute('form'); | ||
| return !!el.closest('form') || !!(formId && document.getElementById(formId)); | ||
| } | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'nested-forms', | ||
| selector: 'form', | ||
| help: 'Nested form is invalid HTML and should be avoided', | ||
| helpUrl: 'https://html.spec.whatwg.org/multipage/forms.html#the-form-element:concept-element-content-model', | ||
| checks: [ | ||
| el => { | ||
| return !(el.parentElement && el.parentElement.closest('form')); | ||
| } | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'avoid-both-disabled-and-aria-disabled', | ||
| selector: 'button, fieldset, input, optgroup, option, select, textarea', | ||
| help: '[aria-disabled] may be used in place of native HTML [disabled] to allow tab-focus on an otherwise ignored element. Setting both attributes is contradictory.', | ||
| helpUrl: 'https://www.w3.org/TR/html-aria/#docconformance-attr', | ||
| checks: [ | ||
| el => !(el.hasAttribute('aria-disabled') && el.hasAttribute('disabled')) | ||
| ] | ||
| }); | ||
| export function createRule({ id, excludeHidden = true, selector, checks = [], all = [], any = [], help, helpUrl = '' }) { | ||
| if (/[^,] /.test(selector)) { | ||
| console.warn('Try to avoid nested CSS selectors in `createRule`: %o', selector); | ||
| } | ||
| if (checks) { | ||
| checks.map((func, i) => { | ||
| const checkId = `${id}_${i}`; | ||
| if (all) | ||
| all.push(checkId); | ||
| generatedChecks.push({ | ||
| id: checkId, | ||
| evaluate: func, | ||
| metadata: { impact: 'critical' } | ||
| }); | ||
| }); | ||
| } | ||
| generatedRules.push({ id, excludeHidden, selector, all, any, metadata: { help, helpUrl }, tags: ['custom-github-rule'] }); | ||
| } | ||
| export default { | ||
| rules: generatedRules, | ||
| checks: generatedChecks | ||
| }; |
| {"type": "module"} |
| import type { Check, Rule } from 'axe-core'; | ||
| interface RuleOptions { | ||
| id: string; | ||
| excludeHidden?: boolean; | ||
| selector: string; | ||
| checks?: Array<(el: Element) => boolean>; | ||
| all?: string[]; | ||
| any?: string[]; | ||
| help: string; | ||
| helpUrl?: string; | ||
| } | ||
| export declare function createRule({ id, excludeHidden, selector, checks, all, any, help, helpUrl }: RuleOptions): void; | ||
| declare const _default: { | ||
| rules: Rule[]; | ||
| checks: Check[]; | ||
| }; | ||
| export default _default; |
+18
-7
| { | ||
| "name": "@github/axe-github", | ||
| "version": "0.3.0", | ||
| "version": "0.4.0", | ||
| "description": "Custom rules and configuration recommendations for the `axe-core` library for GitHub projects", | ||
| "main": "dist/index.js", | ||
| "types": "dist/index.d.js", | ||
| "type": "module", | ||
| "main": "dist/esm/index.js", | ||
| "types": "dist/types/index.d.js", | ||
| "files": [ | ||
| "dist" | ||
| "dist/*" | ||
| ], | ||
@@ -18,3 +17,3 @@ "scripts": { | ||
| "prebuild": "npm run clean", | ||
| "build": "tsc", | ||
| "build": "tsc -b ./tsconfig.cjs.json ./tsconfig.esm.json ./tsconfig.types.json && node ./scripts/prepare-package-json", | ||
| "size-limit": "npm run build && size-limit", | ||
@@ -38,5 +37,17 @@ "prepublishOnly": "npm run build && size-limit" | ||
| "limit": "100kb", | ||
| "path": "dist/index.js" | ||
| "path": "dist/esm/index.js" | ||
| }, | ||
| { | ||
| "limit": "100kb", | ||
| "path": "dist/cjs/index.js" | ||
| } | ||
| ], | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/types/index.d.ts", | ||
| "require": "./dist/cjs/index.js", | ||
| "import": "./dist/esm/index.js", | ||
| "default": "./dist/esm/index.js" | ||
| } | ||
| }, | ||
| "devDependencies": { | ||
@@ -43,0 +54,0 @@ "axe-core": "4.6.2", |
| import type { Check, Rule } from 'axe-core'; | ||
| interface RuleOptions { | ||
| id: string; | ||
| excludeHidden?: boolean; | ||
| selector: string; | ||
| checks?: Array<(el: Element) => boolean>; | ||
| all?: string[]; | ||
| any?: string[]; | ||
| help: string; | ||
| helpUrl?: string; | ||
| } | ||
| export declare function createRule({ id, excludeHidden, selector, checks, all, any, help, helpUrl }: RuleOptions): void; | ||
| declare const _default: { | ||
| rules: Rule[]; | ||
| checks: Check[]; | ||
| }; | ||
| export default _default; |
| const interactiveElements = ['a[href]', 'button', 'summary', 'select', 'input:not([type=hidden])', 'textarea']; | ||
| const focusableElements = interactiveElements.concat(['[tabindex]']); | ||
| const generatedChecks = []; | ||
| const generatedRules = []; | ||
| createRule({ | ||
| id: 'menuitem-should-be-interactive', | ||
| selector: 'div[role="menuitem"], span[role="menuitem"], div[role="menuitemradio"], span[role="menuitemradio"], div[role="menuitemcheckbox"], span[role="menuitemcheckbox"]', | ||
| help: 'Menu items must be focusable. Use <button>, <a>, or <label tabindex="0">', | ||
| checks: [ | ||
| (el) => focusableElements.filter(s => el.matches(s)).length > 0 | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'empty-summary', | ||
| selector: 'summary', | ||
| help: 'Details summary element must have visible text', | ||
| any: ['has-visible-text', 'aria-label', 'aria-labelledby', 'role-presentation', 'role-none', 'non-empty-title'] | ||
| }); | ||
| createRule({ | ||
| id: 'submit-reset-button-must-be-in-form', | ||
| selector: 'button[type="submit"], button[type="reset"], input[type="submit"], input[type="reset"]', | ||
| help: 'Submit and reset buttons must be in a form', | ||
| checks: [ | ||
| el => { | ||
| const formId = el.getAttribute('form'); | ||
| return !!el.closest('form') || !!(formId && document.getElementById(formId)); | ||
| } | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'nested-forms', | ||
| selector: 'form', | ||
| help: 'Nested form is invalid HTML and should be avoided', | ||
| helpUrl: 'https://html.spec.whatwg.org/multipage/forms.html#the-form-element:concept-element-content-model', | ||
| checks: [ | ||
| el => { | ||
| return !(el.parentElement && el.parentElement.closest('form')); | ||
| } | ||
| ] | ||
| }); | ||
| createRule({ | ||
| id: 'avoid-both-disabled-and-aria-disabled', | ||
| selector: 'button, fieldset, input, optgroup, option, select, textarea', | ||
| help: '[aria-disabled] may be used in place of native HTML [disabled] to allow tab-focus on an otherwise ignored element. Setting both attributes is contradictory.', | ||
| helpUrl: 'https://www.w3.org/TR/html-aria/#docconformance-attr', | ||
| checks: [ | ||
| el => !(el.hasAttribute('aria-disabled') && el.hasAttribute('disabled')) | ||
| ] | ||
| }); | ||
| export function createRule({ id, excludeHidden = true, selector, checks = [], all = [], any = [], help, helpUrl = '' }) { | ||
| if (/[^,] /.test(selector)) { | ||
| console.warn('Try to avoid nested CSS selectors in `createRule`: %o', selector); | ||
| } | ||
| if (checks) { | ||
| checks.map((func, i) => { | ||
| const checkId = `${id}_${i}`; | ||
| if (all) | ||
| all.push(checkId); | ||
| generatedChecks.push({ | ||
| id: checkId, | ||
| evaluate: func, | ||
| metadata: { impact: 'critical' } | ||
| }); | ||
| }); | ||
| } | ||
| generatedRules.push({ id, excludeHidden, selector, all, any, metadata: { help, helpUrl }, tags: ['custom-github-rule'] }); | ||
| } | ||
| export default { | ||
| rules: generatedRules, | ||
| checks: generatedChecks | ||
| }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
11101
65.98%9
80%197
123.86%1
Infinity%No
NaN