Repository: eslint/eslint (js)

Issue:
Clean up key-spacing documentation
As of ESLint v4.16.0, the [`key-spacing` documentation](https://eslint.org/docs/rules/key-spacing) is difficult to understand. All of the options are presented in a single list in the [Options section](https://eslint.org/docs/rules/key-spacing#options), but there are actually multiple categories of options, and some options can be nested under other options, and it's not clear what is allowed from reading the top of the file. I think we should reorganize the documentation to more clearly describe what configurations are allowed without relying so much on examples.

Pull request description:
Docs: clean up key-spacing docs (fixes #9900)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[x] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**
Categorized key-spacing options based on their values.


**Is there anything you'd like reviewers to focus on?**
No



Patch:
diff --git a/docs/developer-guide/nodejs-api.md b/docs/developer-guide/nodejs-api.md
index c774666e0..4988f2696 100644
--- a/docs/developer-guide/nodejs-api.md
+++ b/docs/developer-guide/nodejs-api.md
@@ -496,7 +496,7 @@ If the operation ends with a parsing error, you will get a single message for th
             warningCount: 0,
             fixableErrorCount: 0,
             fixableWarningCount: 0,
-            source: "fucntion foo() {}"
+            source: "function foo() {}"
         }
     ],
     errorCount: 1,
diff --git a/docs/rules/key-spacing.md b/docs/rules/key-spacing.md
index 2c4afae8c..6e2b90541 100644
--- a/docs/rules/key-spacing.md
+++ b/docs/rules/key-spacing.md
@@ -10,14 +10,18 @@ This rule enforces consistent spacing between keys and values in object literal
 
 This rule has an object option:
 
-* `"beforeColon": false` (default) disallows spaces between the key and the colon in object literals.
-* `"beforeColon": true` requires at least one space between the key and the colon in object literals.
-* `"afterColon": true` (default) requires at least one space between the colon and the value in object literals.
-* `"afterColon": false` disallows spaces between the colon and the value in object literals.
-* `"mode": "strict"` (default) enforces exactly one space before or after colons in object literals.
-* `"mode": "minimum"` enforces one or more spaces before or after colons in object literals.
-* `"align": "value"` enforces horizontal alignment of values in object literals.
-* `"align": "colon"` enforces horizontal alignment of both colons and values in object literals.
+* `"beforeColon": false (default) | true`
+    * `false`: disallows spaces between the key and the colon in object literals.
+    * `true`: requires at least one space between the key and the colon in object literals.
+* `"afterColon": true (default) | false`
+    * `true`: requires at least one space between the colon and the value in object literals.
+    * `false`: disallows spaces between the colon and the value in object literals.
+* `"mode": "strict" (default) | "miniumum"`
+    * `"strict"`: enforces exactly one space before or after colons in object literals.
+    * `"minimum"`: enforces one or more spaces before or after colons in object literals.
+* `"align": "value" | "colon"`
+    * `"value"`: enforces horizontal alignment of values in object literals.
+    * `"colon"` enforces horizontal alignment of both colons and values in object literals.
 * `"align"` with an object value allows for fine-grained spacing when values are being aligned in object literals.
 * `"singleLine"` specifies a spacing style for single-line object literals.
 * `"multiLine"` specifies a spacing style for multi-line object literals.
diff --git a/docs/rules/valid-typeof.md b/docs/rules/valid-typeof.md
index 2ce02b490..60539eecb 100644
--- a/docs/rules/valid-typeof.md
+++ b/docs/rules/valid-typeof.md
@@ -20,7 +20,7 @@ Examples of **incorrect** code for this rule:
 typeof foo === "strnig"
 typeof foo == "undefimed"
 typeof bar != "nunber"
-typeof bar !== "fucntion"
+typeof bar !== "function"
 ```
 
 Examples of **correct** code for this rule:
diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md
index 098fcdf43..5d4f93d55 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -394,13 +394,18 @@ You can also disable or enable specific rules for an entire file:
 alert('foo');
 ```
 
-To disable all rules on a specific line, use a line comment in one of the following formats:
+To disable all rules on a specific line, use a line or block comment in one of the following formats:
 
 ```js
 alert('foo'); // eslint-disable-line
 
 // eslint-disable-next-line
 alert('foo');
+
+/* eslint-disable-next-line */
+alert('foo');
+
+alert('foo'); /* eslint-disable-line */
 ```
 
 To disable a specific rule on a specific line:
@@ -410,6 +415,11 @@ alert('foo'); // eslint-disable-line no-alert
 
 // eslint-disable-next-line no-alert
 alert('foo');
+
+alert('foo'); /* eslint-disable-line no-alert */
+
+/* eslint-disable-next-line no-alert */
+alert('foo');
 ```
 
 To disable multiple rules on a specific line:
@@ -419,12 +429,18 @@ alert('foo'); // eslint-disable-line no-alert, quotes, semi
 
 // eslint-disable-next-line no-alert, quotes, semi
 alert('foo');
+
+alert('foo'); /* eslint-disable-line no-alert, quotes, semi */
+
+/* eslint-disable-next-line no-alert, quotes, semi */
+alert('foo');
 ```
 
 All of the above methods also work for plugin rules. For example, to disable `eslint-plugin-example`'s `rule-name` rule, combine the plugin's name (`example`) and the rule's name (`rule-name`) into `example/rule-name`:
 
 ```js
 foo(); // eslint-disable-line example/rule-name
+foo(); /* eslint-disable-line example/rule-name */
 ```
 
 **Note:** Comments that disable warnings for a portion of a file tell ESLint not to report rule violations for the disabled code. ESLint still parses the entire file, however, so disabled code still needs to be syntactically valid JavaScript.
diff --git a/lib/linter.js b/lib/linter.js
index d71a79a7c..8e95c3a71 100755
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -307,7 +307,6 @@ function modifyConfigsFromComments(filename, ast, config, ruleMapper) {
 
         if (match) {
             value = value.slice(match.index + match[1].length);
-
             if (comment.type === "Block") {
                 switch (match[1]) {
                     case "exported":
@@ -323,6 +322,18 @@ function modifyConfigsFromComments(filename, ast, config, ruleMapper) {
                         [].push.apply(disableDirectives, createDisableDirectives("disable", comment.loc.start, value));
                         break;
 
+                    case "eslint-disable-line":
+                        if (comment.loc.start.line === comment.loc.end.line) {
+                            [].push.apply(disableDirectives, createDisableDirectives("disable-line", comment.loc.start, value));
+                        }
+                        break;
+
+                    case "eslint-disable-next-line":
+                        if (comment.loc.start.line === comment.loc.end.line) {
+                            [].push.apply(disableDirectives, createDisableDirectives("disable-next-line", comment.loc.start, value));
+                        }
+                        break;
+
                     case "eslint-enable":
                         [].push.apply(disableDirectives, createDisableDirectives("enable", comment.loc.start, value));
                         break;


Test patch:
diff --git a/tests/lib/linter.js b/tests/lib/linter.js
index fc4298d56..5f42ffd9c 100644
--- a/tests/lib/linter.js
+++ b/tests/lib/linter.js
@@ -1889,7 +1889,7 @@ describe("Linter", () => {
         });
     });
 
-    describe("when evaluating code with comments to ignore reporting on of specific rules on a specific line", () => {
+    describe("when evaluating code with comments to ignore reporting on specific rules on a specific line", () => {
 
         describe("eslint-disable-line", () => {
             it("should report a violation", () => {
@@ -1931,14 +1931,15 @@ describe("Linter", () => {
                 assert.strictEqual(messages[0].ruleId, "no-alert");
             });
 
-            it("should report a violation", () => {
+            it("should report a violation if eslint-disable-line in a block comment is not on a single line", () => {
                 const code = [
-                    "alert('test'); // eslint-disable-line no-alert",
-                    "alert('test'); /*eslint-disable-line no-alert*/" // here
+                    "/* eslint-disable-line",
+                    "*",
+                    "*/ console.log('test');" // here
                 ].join("\n");
                 const config = {
                     rules: {
-                        "no-alert": 1
+                        "no-console": 1
                     }
                 };
 
@@ -1946,7 +1947,44 @@ describe("Linter", () => {
 
                 assert.strictEqual(messages.length, 1);
 
+                assert.strictEqual(messages[0].ruleId, "no-console");
+            });
+
+            it("should report a violation if eslint-disable-line in a block comment is not on a single line", () => {
+                const code = [
+                    "alert('test'); /* eslint-disable-line ",
+                    "no-alert */"
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1,
+                        quotes: [1, "double"],
+                        semi: [1, "always"]
+                    }
+                };
+
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 2);
+
                 assert.strictEqual(messages[0].ruleId, "no-alert");
+                assert.strictEqual(messages[1].ruleId, "quotes");
+            });
+
+            it("should not report a violation for eslint-disable-line in block comment", () => {
+                const code = [
+                    "alert('test'); // eslint-disable-line no-alert",
+                    "alert('test'); /*eslint-disable-line no-alert*/"
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1
+                    }
+                };
+
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 0);
             });
 
             it("should not report a violation", () => {
@@ -1984,6 +2022,40 @@ describe("Linter", () => {
 
                 assert.strictEqual(messages.length, 0);
             });
+
+            it("should not report a violation", () => {
+                const code = [
+                    "alert('test') /* eslint-disable-line no-alert, quotes, semi */",
+                    "console.log('test'); /* eslint-disable-line */"
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1,
+                        quotes: [1, "double"],
+                        semi: [1, "always"],
+                        "no-console": 1
+                    }
+                };
+
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 0);
+            });
+
+            it("should ignore violations of multiple rules when specified in mixed comments", () => {
+                const code = [
+                    " alert(\"test\"); /* eslint-disable-line no-alert */ // eslint-disable-line quotes"
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1,
+                        quotes: [1, "single"]
+                    }
+                };
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 0);
+            });
         });
 
         describe("eslint-disable-next-line", () => {
@@ -2005,6 +2077,54 @@ describe("Linter", () => {
                 assert.strictEqual(messages[0].ruleId, "no-console");
             });
 
+            it("should ignore violation of specified rule if eslint-disable-next-line is a block comment", () => {
+                const code = [
+                    "/* eslint-disable-next-line no-alert */",
+                    "alert('test');",
+                    "console.log('test');"
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1,
+                        "no-console": 1
+                    }
+                };
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 1);
+                assert.strictEqual(messages[0].ruleId, "no-console");
+            });
+            it("should ignore violation of specified rule if eslint-disable-next-line is a block comment", () => {
+                const code = [
+                    "/* eslint-disable-next-line no-alert */",
+                    "alert('test');"
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1
+                    }
+                };
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 0);
+            });
+
+            it("should not ignore violation if block comment is not on a single line", () => {
+                const code = [
+                    "/* eslint-disable-next-line",
+                    "no-alert */alert('test');"
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1
+                    }
+                };
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 1);
+                assert.strictEqual(messages[0].ruleId, "no-alert");
+            });
+
             it("should ignore violations only of specified rule", () => {
                 const code = [
                     "// eslint-disable-next-line no-console",
@@ -2043,6 +2163,22 @@ describe("Linter", () => {
                 assert.strictEqual(messages[0].ruleId, "no-console");
             });
 
+            it("should ignore violations of multiple rules when specified in mixed comments", () => {
+                const code = [
+                    "/* eslint-disable-next-line no-alert */ // eslint-disable-next-line quotes",
+                    "alert(\"test\");"
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1,
+                        quotes: [1, "single"]
+                    }
+                };
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 0);
+            });
+
             it("should ignore violations of only the specified rule on next line", () => {
                 const code = [
                     "// eslint-disable-next-line quotes",
@@ -2103,7 +2239,7 @@ describe("Linter", () => {
                 assert.strictEqual(messages[0].ruleId, "no-console");
             });
 
-            it("should not ignore violations if comment is in block quotes", () => {
+            it("should ignore violations if eslint-disable-next-line is a block comment", () => {
                 const code = [
                     "alert('test');",
                     "/* eslint-disable-next-line no-alert */",
@@ -2118,10 +2254,30 @@ describe("Linter", () => {
                 };
                 const messages = linter.verify(code, config, filename);
 
-                assert.strictEqual(messages.length, 3);
+                assert.strictEqual(messages.length, 2);
                 assert.strictEqual(messages[0].ruleId, "no-alert");
-                assert.strictEqual(messages[1].ruleId, "no-alert");
-                assert.strictEqual(messages[2].ruleId, "no-console");
+                assert.strictEqual(messages[1].ruleId, "no-console");
+            });
+
+            it("should report a violation", () => {
+                const code = [
+                    "/* eslint-disable-next-line",
+                    "*",
+                    "*/",
+                    "console.log('test');" // here
+                ].join("\n");
+                const config = {
+                    rules: {
+                        "no-alert": 1,
+                        "no-console": 1
+                    }
+                };
+
+                const messages = linter.verify(code, config, filename);
+
+                assert.strictEqual(messages.length, 1);
+
+                assert.strictEqual(messages[0].ruleId, "no-console");
             });
 
             it("should not ignore violations if comment is of the type Shebang", () => {