diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f1740aec1..0d0d5f17f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,9 @@ You can create a new rule from a template with the `create-rule` script: npm run create-rule ``` -This will prompt you to enter the details of the new rule. Once you're done, it will create a file for the rule implementation (inside `src`) as well as folder with rule tests (inside `test`). +This will prompt you to enter the details of the new rule. Once you're done, it will create a file for the rule implementation (inside `src`), folder with rule tests (inside `test`), and will add rule info to `README.md`. + +You should update rule entry in `README.md` with information about available options, more detailed description, and examples if needed. New rules should have `@next` placeholder in version column, which will be replaced with proper version during release process. More information about writing rule tests can be found in [TSLint documentation](https://palantir.github.io/tslint/develop/testing-rules/). diff --git a/README.md b/README.md index 99980dad4..9eac31133 100644 --- a/README.md +++ b/README.md @@ -142,24 +142,6 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic 2.0.5 - - - react-a11y-accessible-headings - - - For accessibility of your website, there should be no more than 2 H1 heading elements, HTML heading elements must be concise, used for structuring information on the page and non-empty. - - 6.0.0 - - - - react-a11y-iframes - - - Enforce that iframe elements are not empty, have title, and are unique. - - 6.1.0 - informative-docs @@ -731,15 +713,6 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic 4.0.2 - - - void-zero - - - void 0, which resolves to undefined, can be confusing to newcomers. Exclusively use undefined to reduce ambiguity. - - 6.1.0 - no-var-self @@ -839,6 +812,15 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic 1.0 + + + react-a11y-accessible-headings + + + For accessibility of your website, there should be no more than 2 H1 heading elements, HTML heading elements must be concise, used for structuring information on the page and non-empty. + + 6.0.0 + react-a11y-anchors @@ -886,6 +868,15 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic 2.0.11 + + + react-a11y-iframes + + + Enforce that iframe elements are not empty, have title, and are unique. + + 6.1.0 + react-a11y-image-button-has-alt @@ -1004,6 +995,21 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic 6.0.0-beta + + + react-a11y-role + + + For accessibility of your website, elements with aria roles must use a **valid**, **non-abstract** aria role. + A reference to role definitions can be found at [WAI-ARIA roles](https://www.w3.org/TR/wai-aria/roles#role_definitions). +
+ References: + + + 2.0.11 + react-a11y-role-has-required-aria-props @@ -1039,21 +1045,6 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic 2.0.11 - - - react-a11y-role - - - For accessibility of your website, elements with aria roles must use a **valid**, **non-abstract** aria role. - A reference to role definitions can be found at [WAI-ARIA roles](https://www.w3.org/TR/wai-aria/roles#role_definitions). -
- References: - - - 2.0.11 - react-a11y-tabindex-no-positive @@ -1244,6 +1235,15 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic 1.0 + + + void-zero + + + void 0, which resolves to undefined, can be confusing to newcomers. Exclusively use undefined to reduce ambiguity. + + 6.1.0 + diff --git a/build-tasks/common/readme-rules.js b/build-tasks/common/readme-rules.js new file mode 100644 index 000000000..d9971c93b --- /dev/null +++ b/build-tasks/common/readme-rules.js @@ -0,0 +1,50 @@ +const { readFile, writeFile } = require('./files'); + +// Matches , , and openning tags with only whitespace surrounding them +// Capturing group for rule name inside and tags with possible whitespace around it +const praseRe = /\s+\s*?\s*?\s*?([0-9a-z-]*?)\s*?<\/code>/g; +const README_NAME = 'README.md'; +const readmeContent = readFile(README_NAME); + +function getAllRules() { + const rules = []; + let match; + + while ((match = praseRe.exec(readmeContent))) { + rules.push(match[1]); + } + + return rules; +} + +function addNewRule(name, ruleMarkup) { + let match; + let insertPosition; + + while ((match = praseRe.exec(readmeContent))) { + const existingName = match[1]; + // Looks for first rule that should follow new rule. + // Match position will be used to insert new rule row + if (name < existingName) { + insertPosition = match.index; + break; + } + } + + // In case when new rule should be added to the end of the table - look for insret position before + if (insertPosition === undefined) { + insertPosition = readmeContent.match(/\s+<\/tbody>\s+<\/table>/).index; + } + const contentBeforeNewRule = readmeContent.slice(0, insertPosition); + const contentAfterNewRule = readmeContent.slice(insertPosition); + const newContent = contentBeforeNewRule + ruleMarkup + contentAfterNewRule; + writeFile(README_NAME, newContent); + + // To position cursor on the same line with new rule name should add 3 lines to match lines added with template + return `./${README_NAME}:${contentBeforeNewRule.split('\n').length + 3}`; +} + +module.exports = { + getAllRules, + addNewRule +}; diff --git a/build-tasks/create-rule.js b/build-tasks/create-rule.js index 830d6bc41..f982dcc6b 100644 --- a/build-tasks/create-rule.js +++ b/build-tasks/create-rule.js @@ -4,6 +4,8 @@ const fs = require('fs'); const inquirer = require('inquirer'); const path = require('path'); const { writeFile } = require('./common/files'); +const readmeTemplate = require('./templates/readme-rule-entry.template'); +const { addNewRule } = require('./common/readme-rules'); const questions = [ { @@ -88,13 +90,15 @@ const questions = [ inquirer.prompt(questions).then(answers => { const sourceFileName = createImplementationFile(answers); const testFileNames = createTestFiles(answers); + const readmePosition = createReadmeEntry(answers); console.log(`Rule '${answers.name}' created.`); console.log(`Source file: ${sourceFileName}`); - console.log(`Test files: ${testFileNames.join(', ')}`); + console.log(`Test files: ${testFileNames.join(' ')}`); + console.log(`README.md entry: ${readmePosition}`); // Attempt to open the files in the current editor. - tryOpenFiles([...testFileNames, sourceFileName]); + tryOpenFiles([...testFileNames, sourceFileName, readmePosition]); }); function createImplementationFile(answers) { @@ -139,6 +143,11 @@ function createTestFiles(answers) { return testFiles; } +function createReadmeEntry(answers) { + const content = readmeTemplate(answers); + return addNewRule(answers.name, content); +} + function camelCase(input) { return input.toLowerCase().replace(/-(.)/g, (match, group1) => group1.toUpperCase()); } diff --git a/build-tasks/templates/readme-rule-entry.template.js b/build-tasks/templates/readme-rule-entry.template.js new file mode 100644 index 000000000..657ebd0aa --- /dev/null +++ b/build-tasks/templates/readme-rule-entry.template.js @@ -0,0 +1,8 @@ +module.exports = ({ name, description }) => ` + + + ${name} + + ${description} + @next + `; diff --git a/build-tasks/validate-rules-order.js b/build-tasks/validate-rules-order.js new file mode 100644 index 000000000..f96fab6b4 --- /dev/null +++ b/build-tasks/validate-rules-order.js @@ -0,0 +1,18 @@ +const { yellowBright } = require('chalk'); +const { getAllRules } = require('./common/readme-rules'); + +const rules = getAllRules(); +const sortedRules = [].concat(rules).sort(); +const mismatchIndex = rules.findIndex((name, i) => name !== sortedRules[i]); + +if (mismatchIndex === -1) { + process.exit(0); +} + +const message = + mismatchIndex === 0 + ? `First rule expecteded to be ${sortedRules[0]} but found ${rules[0]}.` + : `Rule ${rules[mismatchIndex - 1]} should be followed by ${sortedRules[mismatchIndex]} but found ${rules[mismatchIndex]}.`; +console.log(yellowBright('Incorrect order of rules in README.md.')); +console.log(message); +process.exit(1); diff --git a/package.json b/package.json index 103a2c6d7..4aa173cee 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "tslint:check": "tslint-config-prettier-check ./tslint.json", "validate:config": "node build-tasks/validate-config.js", "validate:documentation": "node build-tasks/validate-documentation.js", + "validate:rules-order": "node build-tasks/validate-rules-order.js", "watch:run-tests": "node build-tasks/watch-run-tests.js", "watch:src": "tsc --watch" },