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
react-a11y-accessible-headings
- react-a11y-iframes
- informative-docs
@@ -731,15 +713,6 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic
void-zero
- void 0
, which resolves to undefined
, can be confusing to newcomers. Exclusively use undefined
to reduce ambiguity.
- no-var-self
@@ -839,6 +812,15 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic
react-a11y-accessible-headings
+ react-a11y-anchors
@@ -886,6 +868,15 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic
react-a11y-iframes
+ react-a11y-image-button-has-alt
@@ -1004,6 +995,21 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic
react-a11y-role
+ react-a11y-role-has-required-aria-props
@@ -1039,21 +1045,6 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic
react-a11y-role
- react-a11y-tabindex-no-positive
@@ -1244,6 +1235,15 @@ We recommend you specify exact versions of lint libraries, including `tslint-mic
void-zero
+ void 0
, which resolves to undefined
, can be confusing to newcomers. Exclusively use undefined
to reduce ambiguity.
+ 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"
},