Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Add infrastructure for auto-generating markdown table and list #837

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions .eslintrc
Expand Up @@ -23,6 +23,20 @@
"eslint-plugin/require-meta-type": "off",
},
},
{
"files": ["markdown.config.js"],
"parserOptions": {
"sourceType": "script",
},
"rules": {
"no-console": 0,
"import/no-extraneous-dependencies": [
"error",
{ "devDependencies": true },
],
"strict": ["error", "global"],
},
},
{
"files": ["__tests__/src/rules/*.js"],
"extends": ["plugin:eslint-plugin/tests-recommended"],
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/readme.yml
@@ -0,0 +1,15 @@
name: 'Tests: readme'

on: [pull_request, push]

jobs:
readme:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: ljharb/actions/node/install@main
name: 'nvm install lts/* && npm install'
with:
node-version: 'lts/*'
- run: npm run generate-list-of-rules:check
145 changes: 78 additions & 67 deletions README.md

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions markdown.config.js
@@ -0,0 +1,49 @@
'use strict';

require('@babel/register');

const { rules } = require('./src');

const ruleTableRows = Object.keys(rules)
.sort()
.map((id) => {
const { meta } = rules[id];
const { url, errorOptions } = meta.docs;
return [
`[${id}](${url})`,
errorOptions ? 'error, with options' : 'error',
'error',
].join(' | ');
});

const buildRulesTable = (rows) => {
const header = 'Rule | Recommended | Strict';
const separator = ':--- | :--- | :---';

return [header, separator].concat(rows)
.map((row) => `| ${row} |`)
.join('\n');
};

const ruleList = Object.keys(rules)
.sort()
.map((id) => {
const { meta } = rules[id];
const { description, url } = meta.docs;
return description ? [`- [${id}](${url}): ${description}`] : null;
});

const buildRuleList = (listItems) => listItems.join('\n');

const LIST = () => buildRuleList(ruleList);
const TABLE = () => buildRulesTable(ruleTableRows);

module.exports = {
transforms: {
TABLE,
LIST,
},
callback: () => {
console.log('The auto-generating of rules finished!');
},
};
8 changes: 6 additions & 2 deletions package.json
Expand Up @@ -28,13 +28,16 @@
"test": "npm run jest",
"posttest": "aud --production",
"test:ci": "npm run jest -- --ci --runInBand",
"jest": "jest --coverage __tests__/**/*"
"jest": "jest --coverage __tests__/**/*",
"generate-list-of-rules": "md-magic --path '**/*.md' --ignore 'node_modules'",
"generate-list-of-rules:check": "npm run generate-list-of-rules && git diff --exit-code README.md"
},
"devDependencies": {
"@babel/cli": "^7.17.0",
"@babel/core": "^7.17.0",
"@babel/core": "^7.17.5",
"@babel/eslint-parser": "^7.17.0",
"@babel/plugin-transform-flow-strip-types": "^7.16.7",
"@babel/register": "^7.17.0",
"ast-types-flow": "^0.0.7",
"aud": "^2.0.0",
"babel-jest": "^24.9.0",
Expand All @@ -51,6 +54,7 @@
"in-publish": "^2.0.1",
"jest": "^24.9.0",
"jscodeshift": "^0.7.1",
"markdown-magic": "^2.6.0",
"minimist": "^1.2.5",
"object.assign": "^4.1.2",
"rimraf": "^3.0.2",
Expand Down
1 change: 1 addition & 0 deletions src/rules/alt-text.js
Expand Up @@ -196,6 +196,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/alt-text.md',
description: 'Enforce all elements that require alternative text have meaningful information to relay back to end user.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/anchor-has-content.js
Expand Up @@ -19,6 +19,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/anchor-has-content.md',
description: 'Enforce all anchors to contain accessible content.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/anchor-is-valid.js
Expand Up @@ -31,6 +31,7 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/anchor-is-valid.md',
description: 'Enforce all anchors are valid, navigable elements.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/aria-activedescendant-has-tabindex.js
Expand Up @@ -23,6 +23,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/aria-activedescendant-has-tabindex.md',
description: 'Enforce elements with aria-activedescendant are tabbable.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/aria-props.js
Expand Up @@ -31,6 +31,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/aria-props.md',
description: 'Enforce all `aria-*` props are valid.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/aria-proptypes.js
Expand Up @@ -67,6 +67,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/aria-proptypes.md',
description: 'Enforce ARIA state and property values are valid.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/aria-role.js
Expand Up @@ -31,6 +31,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/aria-role.md',
description: 'Enforce that elements with ARIA roles must use a valid, non-abstract ARIA role.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/aria-unsupported-elements.js
Expand Up @@ -26,6 +26,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/aria-unsupported-elements.md',
description: 'Enforce that elements that do not support ARIA roles, states, and properties do not have those attributes.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/autocomplete-valid.js
Expand Up @@ -18,6 +18,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/autocomplete-valid.md',
description: 'Enforce that autocomplete attributes are used correctly.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/click-events-have-key-events.js
Expand Up @@ -24,6 +24,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/click-events-have-key-events.md',
description: 'Enforce a clickable non-interactive element has at least one keyboard event listener.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/heading-has-content.js
Expand Up @@ -29,6 +29,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/heading-has-content.md',
description: 'Enforce heading (`h1`, `h2`, etc) elements contain accessible content.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/html-has-lang.js
Expand Up @@ -18,6 +18,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/html-has-lang.md',
description: 'Enforce `<html>` element has `lang` prop.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/iframe-has-title.js
Expand Up @@ -18,6 +18,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/iframe-has-title.md',
description: 'Enforce iframe elements have a title attribute.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/img-redundant-alt.js
Expand Up @@ -28,6 +28,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/img-redundant-alt.md',
description: 'Enforce `<img>` alt prop does not contain the word "image", "picture", or "photo".',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/interactive-supports-focus.js
Expand Up @@ -51,6 +51,7 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/interactive-supports-focus.md',
description: 'Enforce that elements with interactive handlers like `onClick` must be focusable.',
},
schema: [schema],
},
Expand Down
5 changes: 4 additions & 1 deletion src/rules/label-has-associated-control.js
Expand Up @@ -43,7 +43,10 @@ const validateId = (node) => {

export default ({
meta: {
docs: {},
docs: {
description: 'Enforce that a `label` tag has a text label and an associated control.',
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/label-has-associated-control.md',
ljharb marked this conversation as resolved.
Show resolved Hide resolved
},
schema: [schema],
},

Expand Down
1 change: 1 addition & 0 deletions src/rules/lang.js
Expand Up @@ -19,6 +19,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/lang.md',
description: 'Enforce lang attribute has a valid value.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/media-has-caption.js
Expand Up @@ -39,6 +39,7 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/media-has-caption.md',
description: 'Enforces that `<audio>` and `<video>` elements must have a `<track>` for captions.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/mouse-events-have-key-events.js
Expand Up @@ -21,6 +21,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/mouse-events-have-key-events.md',
description: 'Enforce that `onMouseOver`/`onMouseOut` are accompanied by `onFocus`/`onBlur` for keyboard-only users.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-access-key.js
Expand Up @@ -18,6 +18,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-access-key.md',
description: 'Enforce that the `accessKey` prop is not used on any element to avoid complications with keyboard commands used by a screenreader.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-autofocus.js
Expand Up @@ -24,6 +24,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-autofocus.md',
description: 'Enforce autoFocus prop is not used.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-distracting-elements.js
Expand Up @@ -27,6 +27,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-distracting-elements.md',
description: 'Enforce distracting elements are not used.',
},
schema: [schema],
},
Expand Down
2 changes: 2 additions & 0 deletions src/rules/no-interactive-element-to-noninteractive-role.js
Expand Up @@ -33,6 +33,8 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-interactive-element-to-noninteractive-role.md',
description: 'Interactive elements should not be assigned non-interactive roles.',
errorOptions: true,
},
schema: [{
type: 'object',
Expand Down
2 changes: 2 additions & 0 deletions src/rules/no-noninteractive-element-interactions.js
Expand Up @@ -46,6 +46,8 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-noninteractive-element-interactions.md',
description: 'Non-interactive elements should not be assigned mouse or keyboard event listeners.',
errorOptions: true,
},
schema: [schema],
},
Expand Down
2 changes: 2 additions & 0 deletions src/rules/no-noninteractive-element-to-interactive-role.js
Expand Up @@ -31,6 +31,8 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-noninteractive-element-to-interactive-role.md',
description: 'Non-interactive elements should not be assigned interactive roles.',
errorOptions: true,
},
schema: [{
type: 'object',
Expand Down
2 changes: 2 additions & 0 deletions src/rules/no-noninteractive-tabindex.js
Expand Up @@ -40,6 +40,8 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-noninteractive-tabindex.md',
description: '`tabIndex` should only be declared on interactive elements.',
errorOptions: true,
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-onchange.js
Expand Up @@ -23,6 +23,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-onchange.md',
description: 'Enforce usage of `onBlur` over `onChange` on select menus for accessibility.',
},
deprecated: true,
schema: [schema],
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-redundant-roles.js
Expand Up @@ -27,6 +27,7 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-redundant-roles.md',
description: 'Enforce explicit role property is not the same as implicit/default role property on element.',
},
schema: [{
type: 'object',
Expand Down
2 changes: 2 additions & 0 deletions src/rules/no-static-element-interactions.js
Expand Up @@ -45,6 +45,8 @@ export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-static-element-interactions.md',
description: 'Enforce that non-interactive, visible elements (such as `<div>`) that have click handlers use the role attribute.',
errorOptions: true,
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/role-has-required-aria-props.js
Expand Up @@ -28,6 +28,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/role-has-required-aria-props.md',
description: 'Enforce that elements with ARIA roles must have all required attributes for that role.',
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/role-supports-aria-props.js
Expand Up @@ -37,6 +37,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/role-supports-aria-props.md',
description: 'Enforce that elements with explicit or implicit roles defined contain only `aria-*` properties supported by that `role`.',
},
schema: [schema],
},
Expand Down
2 changes: 2 additions & 0 deletions src/rules/scope.js
Expand Up @@ -19,6 +19,8 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/scope.md',
description: 'Enforce `scope` prop is only used on `<th>` elements.',
errorOptions: true,
},
schema: [schema],
},
Expand Down
1 change: 1 addition & 0 deletions src/rules/tabindex-no-positive.js
Expand Up @@ -18,6 +18,7 @@ export default {
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/tabindex-no-positive.md',
description: 'Enforce `tabIndex` value is not greater than zero.',
},
schema: [schema],
},
Expand Down