Repository: eslint/eslint
Pull request #15404 (2021-12-08 12:25:27)

docs: consistency changes
#### Prerequisites checklist

- [X] I have read the [contributing guidelines](https://github.com/eslint/eslint/blob/HEAD/CONTRIBUTING.md).

#### What is the purpose of this pull request? (put an "X" next to an item)

<!--
    The following template is intentionally not a markdown checkbox list for the reasons
    explained in https://github.com/eslint/eslint/pull/12848#issuecomment-580302888
-->

[X] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-change-proposal.md))
[ ] Add autofix to a rule
[ ] Add a CLI option
[ ] Add something to the core
[X] Other, please explain:

#### What changes did you make? (Give an overview)

I've made a bunch of consistency changes to the rules documentation, including:
* Fixed header casing (i.e. `options` -> `Options`)
* Fixed header levels (i.e. `## allow` -> `### allow`)
* Removed duplicate headers (i.e. multiple `## Rule Details` headers)
* Made all inter-rule links internal links if they weren't already (i.e. `[object-shorthand](https://eslint.org/docs/rules/object-shorthand)` -> `[object-shorthand](object-shorthand.md)`)
* Made unordered list style consistent (i.e. `- ` -> `* `). Almost everywhere `* ` was already used so fixed the few places it wasn't. I also added an entry to `markdownlint.yml` to ensure future consistency. This also resulted in a couple of changes outside of the `rules` directory.
* Made the order of sections consistent. The order is now always `"Rule Details", "Options", "Environments", "Examples", "Known Limitations", "When Not To Use It", "Related Rules", "Compatibility", "Further Reading"`. Especially those last three had quite a few permutations. The order is arbitrary, but made sense to me.
* Added a test to `Makefile.js` to validate those header names and their order
* Some typo fixes and similar minor changes.

#### Is there anything you'd like reviewers to focus on?

This is my first PR to `eslint` and I think I followed all guidelines, but I'm happy to make improvements to the PR if needed.

linux-foundation-easycla[bot]: <a href="https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19114526/11061773/15404/#/?version=2"><img src="https://s3.amazonaws.com/cla-project-logo-prod/cla-not-signed.svg" alt="CLA Not Signed" align="left" height="28" width="328" ></a><br/><br /><ul><li><a href='https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19114526/11061773/15404/#/?version=2' target='_blank'>:x:</a> - Bas Bosman The commit (925d3b68d9e9f0c07a38a07a9bb92cbee7338493) is not authorized under a signed CLA. <a href='https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19114526/11061773/15404/#/?version=2' target='_blank'>Please click here to be authorized</a>. For further assistance with EasyCLA, <a href='https://jira.linuxfoundation.org/servicedesk/customer/portal/4' target='_blank'>please submit a support request ticket</a>.</li></ul>
BBosman: @nzakas, I think I addressed all your comments.

Patch:
diff --git a/.github/ISSUE_TEMPLATE/NEW_SYNTAX.md b/.github/ISSUE_TEMPLATE/NEW_SYNTAX.md
index e03cb6e11..f3ac551f6 100644
--- a/.github/ISSUE_TEMPLATE/NEW_SYNTAX.md
+++ b/.github/ISSUE_TEMPLATE/NEW_SYNTAX.md
@@ -20,7 +20,7 @@ assignees: ''
 
 **Please provide the TC39 URL for the syntax proposal:**
 
-
+<!-- for example, <https://github.com/tc39/proposal-top-level-await> -->
 
 **Please provide some example code for the new syntax:**
 
@@ -41,3 +41,5 @@ Please check off all items that have already been completed. Be sure to paste th
 - [ ] `eslint` update: <!-- paste PR URL for this syntax here -->
 
 **Are you willing to submit a pull request to implement this syntax?**
+
+<!-- markdownlint-disable-file MD004 -->
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index e2d756628..593e8f784 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -42,5 +42,6 @@
 
 #### What changes did you make? (Give an overview)
 
-
 #### Is there anything you'd like reviewers to focus on?
+
+<!-- markdownlint-disable-file MD004 -->
diff --git a/.markdownlint.yml b/.markdownlint.yml
index c37cf77fb..a8478b2ae 100644
--- a/.markdownlint.yml
+++ b/.markdownlint.yml
@@ -2,6 +2,8 @@ default: true
 
 # Exclusions for deliberate/widespread violations
 MD002: false     # First header should be a h1 header
+MD004:           # Unordered list style
+    style: asterisk
 MD007:           # Unordered list indentation
     indent: 4
 MD013: false     # Line length
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1190eb26..a65d12a17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+v8.5.0 - December 17, 2021
+
+* [`7d832d4`](https://github.com/eslint/eslint/commit/7d832d4ad55f3c987aca8d858809cbcb77697648) fix: improve `prefer-template` fixer (#15230) (Nitin Kumar)
+* [`94e77a6`](https://github.com/eslint/eslint/commit/94e77a693fd5124c9057320310b41e92567d7e76) feat: Suggestions support for `prefer-regex-literals` (#15077) (Yash Singh)
+* [`314c84c`](https://github.com/eslint/eslint/commit/314c84c1b83b32e75587ce7a77130eac7e2a8f49) docs: add an incorrect code example in for-direction (#15434) (Holger Jeromin)
+* [`981fb48`](https://github.com/eslint/eslint/commit/981fb48991448bec171d7d4332d7dc514252f83f) fix: do not report global references in `id-match` rule (#15420) (Nitin Kumar)
+* [`3928175`](https://github.com/eslint/eslint/commit/3928175d01c6ac2b37147b3256c56df8faf2c6c4) docs: add destructuring examples for `computed-property-spacing` (#15423) (Nitin Kumar)
+* [`225f211`](https://github.com/eslint/eslint/commit/225f2111ebcfc6bcd2d475f5261c85eb00fb0191) test: add destructuring test cases for `computed-property-spacing` (#15424) (Nitin Kumar)
+* [`f13d4a6`](https://github.com/eslint/eslint/commit/f13d4a6cf7c7ff6160be7426fc6fe02e3e37a0b7) fix: improve autofix of `prefer-object-has-own` (#15419) (Nitin Kumar)
+* [`f4559a0`](https://github.com/eslint/eslint/commit/f4559a0f7150ad7494658bd5ea846cfca5073caf) fix: add helpful message when test case has non-string code/name (#15425) (Bryan Mishkin)
+* [`a53e59e`](https://github.com/eslint/eslint/commit/a53e59eab7da52e3df095a679a6fdab74a7bce6f) docs: add more examples for `array-element-newline` rule (#15427) (Nitin Kumar)
+* [`f2c7ba6`](https://github.com/eslint/eslint/commit/f2c7ba6c34c8943dc24a1c41317d536c1a63cb36) ci: use node v16 for `macOS` and `windows` jobs (#15418) (Nitin Kumar)
+* [`eafaf52`](https://github.com/eslint/eslint/commit/eafaf52464c01072fcf7be2bd2d91cd0b3ae67d0) feat: add `prefer-object-has-own` rule (#15346) (Nitin Kumar)
+* [`74cf0a0`](https://github.com/eslint/eslint/commit/74cf0a040e1a83990d8d7eb57e1f5ce919a11ebe) docs: update CLA info (#15370) (Nitin Kumar)
+* [`e84195e`](https://github.com/eslint/eslint/commit/e84195ea39b5cf54d7a551c62671af80b859f1ac) docs: fix heading level for an option in `class-methods-use-this` rule (#15399) (Takuya Fukuju)
+
 v8.4.1 - December 6, 2021
 
 * [`234e3d9`](https://github.com/eslint/eslint/commit/234e3d98eeab8956cefb14c982b9c348c21bb2d9) fix: revert changes to reported locations in max-lines-per-function (#15397) (Milos Djermanovic)
diff --git a/Makefile.js b/Makefile.js
index 3730e9b8d..10203f5ed 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -15,6 +15,7 @@ const checker = require("npm-license"),
     dateformat = require("dateformat"),
     fs = require("fs"),
     glob = require("glob"),
+    marked = require("marked"),
     markdownlint = require("markdownlint"),
     os = require("os"),
     path = require("path"),
@@ -790,7 +791,9 @@ target.checkRuleFiles = function() {
         const basename = path.basename(filename, ".js");
         const docFilename = `docs/rules/${basename}.md`;
         const docText = cat(docFilename);
+        const docMarkdown = marked.lexer(docText, { gfm: true, silent: false });
         const ruleCode = cat(filename);
+        const knownHeaders = ["Rule Details", "Options", "Environments", "Examples", "Known Limitations", "When Not To Use It", "Related Rules", "Compatibility", "Further Reading"];
 
         /**
          * Check if basename is present in rule-types.json file.
@@ -820,7 +823,35 @@ target.checkRuleFiles = function() {
         }
 
         /**
-         * Check if deprecated information is in rule code and READNE.md.
+         * Check if all H2 headers are known and in the expected order
+         * Only H2 headers are checked as H1 and H3 are variable and/or rule specific.
+         * @returns {boolean} true if all headers are known and in the right order
+         */
+        function hasKnownHeaders() {
+            const headers = docMarkdown.filter(token => token.type === "heading" && token.depth === 2).map(header => header.text);
+
+            for (const header of headers) {
+                if (!knownHeaders.includes(header)) {
+                    return false;
+                }
+            }
+
+            /*
+             * Check only the subset of used headers for the correct order
+             */
+            const presentHeaders = knownHeaders.filter(header => headers.includes(header));
+
+            for (let i = 0; i < presentHeaders.length; ++i) {
+                if (presentHeaders[i] !== headers[i]) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        /**
+         * Check if deprecated information is in rule code and README.md.
          * @returns {boolean} true if present
          * @private
          */
@@ -853,6 +884,12 @@ target.checkRuleFiles = function() {
                 console.error("Missing id in the doc page's title of rule %s", basename);
                 errors++;
             }
+
+            // check for proper doc headers
+            if (!hasKnownHeaders()) {
+                console.error("Unknown or misplaced header in the doc page of rule %s, allowed headers (and their order) are: '%s'", basename, knownHeaders.join("', '"));
+                errors++;
+            }
         }
 
         // check for recommended configuration
diff --git a/README.md b/README.md
index e8b005d7d..088e19694 100644
--- a/README.md
+++ b/README.md
@@ -294,7 +294,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
 <p><a href="https://contra.com"><img src="https://images.opencollective.com/contra1/c70f93f/logo.png" alt="Contra" height="96"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://coinbase.com"><img src="https://avatars.githubusercontent.com/u/1885080?v=4" alt="Coinbase" height="96"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://sumatosoft.com/"><img src="https://images.opencollective.com/sumatosoft1/cab6013/logo.png" alt="SumatoSoft" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
+<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/docs/developer-guide/working-with-custom-formatters.md b/docs/developer-guide/working-with-custom-formatters.md
index 54db66328..e157bb079 100644
--- a/docs/developer-guide/working-with-custom-formatters.md
+++ b/docs/developer-guide/working-with-custom-formatters.md
@@ -100,23 +100,23 @@ also be manually applied to that page. -->
 
 Each object in the `results` array is a `result` object. Each `result` object contains the path of the file that was linted and information about linting issues that were encountered. Here are the properties available on each `result` object:
 
-*   **filePath**: The absolute path to the file that was linted.
-*   **messages**: An array of `message` objects. See below for more info about messages.
-*   **errorCount**: The number of errors for the given file.
-*   **warningCount**: The number of warnings for the given file.
-*   **source**: The source code for the given file. This property is omitted if this file has no errors/warnings or if the `output` property is present.
-*   **output**: The source code for the given file with as many fixes applied as possible. This property is omitted if no fix is available.
+* **filePath**: The absolute path to the file that was linted.
+* **messages**: An array of `message` objects. See below for more info about messages.
+* **errorCount**: The number of errors for the given file.
+* **warningCount**: The number of warnings for the given file.
+* **source**: The source code for the given file. This property is omitted if this file has no errors/warnings or if the `output` property is present.
+* **output**: The source code for the given file with as many fixes applied as possible. This property is omitted if no fix is available.
 
 ### The `message` Object
 
 Each `message` object contains information about the ESLint rule that was triggered by some source code. The properties available on each `message` object are:
 
-*   **ruleId**: the ID of the rule that produced the error or warning.
-*   **severity**: the severity of the failure, `1` for warnings and `2` for errors.
-*   **message**: the human readable description of the error.
-*   **line**: the line where the issue is located.
-*   **column**: the column where the issue is located.
-*   **nodeType**: the type of the node in the [AST](https://github.com/estree/estree/blob/master/spec.md#node-objects)
+* **ruleId**: the ID of the rule that produced the error or warning.
+* **severity**: the severity of the failure, `1` for warnings and `2` for errors.
+* **message**: the human readable description of the error.
+* **line**: the line where the issue is located.
+* **column**: the column where the issue is located.
+* **nodeType**: the type of the node in the [AST](https://github.com/estree/estree/blob/master/spec.md#node-objects)
 
 ## The `context` Argument
 
diff --git a/docs/rules/accessor-pairs.md b/docs/rules/accessor-pairs.md
index 22cf28ab9..dd64562e6 100644
--- a/docs/rules/accessor-pairs.md
+++ b/docs/rules/accessor-pairs.md
@@ -281,6 +281,11 @@ See [no-dupe-class-members](no-dupe-class-members.md) if you also want to disall
 
 You can turn this rule off if you are not concerned with the simultaneous presence of setters and getters on objects.
 
+## Related Rules
+
+* [no-dupe-keys](no-dupe-keys.md)
+* [no-dupe-class-members](no-dupe-class-members.md)
+
 ## Further Reading
 
 * [Object Setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)
diff --git a/docs/rules/array-bracket-newline.md b/docs/rules/array-bracket-newline.md
index bb990c75b..d62b61e33 100644
--- a/docs/rules/array-bracket-newline.md
+++ b/docs/rules/array-bracket-newline.md
@@ -271,10 +271,10 @@ var e = [
 
 If you don't want to enforce line breaks after opening and before closing array brackets, don't enable this rule.
 
-## Compatibility
-
-* **JSCS:** [validateNewlineAfterArrayElements](https://jscs-dev.github.io/rule/validateNewlineAfterArrayElements)
-
 ## Related Rules
 
 * [array-bracket-spacing](array-bracket-spacing.md)
+
+## Compatibility
+
+* **JSCS:** [validateNewlineAfterArrayElements](https://jscs-dev.github.io/rule/validateNewlineAfterArrayElements)
diff --git a/docs/rules/array-element-newline.md b/docs/rules/array-element-newline.md
index 650a00892..dabb55423 100644
--- a/docs/rules/array-element-newline.md
+++ b/docs/rules/array-element-newline.md
@@ -374,10 +374,6 @@ var [i = function foo() {
 
 If you don't want to enforce linebreaks between array elements, don't enable this rule.
 
-## Compatibility
-
-* **JSCS:** [validateNewlineAfterArrayElements](https://jscs-dev.github.io/rule/validateNewlineAfterArrayElements)
-
 ## Related Rules
 
 * [array-bracket-spacing](array-bracket-spacing.md)
@@ -388,3 +384,7 @@ If you don't want to enforce linebreaks between array elements, don't enable thi
 * [max-statements-per-line](max-statements-per-line.md)
 * [block-spacing](block-spacing.md)
 * [brace-style](brace-style.md)
+
+## Compatibility
+
+* **JSCS:** [validateNewlineAfterArrayElements](https://jscs-dev.github.io/rule/validateNewlineAfterArrayElements)
diff --git a/docs/rules/callback-return.md b/docs/rules/callback-return.md
index c4e7277c4..b722e2975 100644
--- a/docs/rules/callback-return.md
+++ b/docs/rules/callback-return.md
@@ -165,11 +165,11 @@ There are some cases where you might want to call a callback function more than
  may lead to incorrect behavior. In those cases you may want to reserve a special name for those callbacks and
  not include that in the list of callbacks that trigger warnings.
 
+## Related Rules
+
+* [handle-callback-err](handle-callback-err.md)
+
 ## Further Reading
 
 * [The Art Of Node: Callbacks](https://github.com/maxogden/art-of-node#callbacks)
 * [Nodejitsu: What are the error conventions?](https://docs.nodejitsu.com/articles/errors/what-are-the-error-conventions/)
-
-## Related Rules
-
-* [handle-callback-err](handle-callback-err.md)
diff --git a/docs/rules/camelcase.md b/docs/rules/camelcase.md
index 164dfab7c..da9dcda50 100644
--- a/docs/rules/camelcase.md
+++ b/docs/rules/camelcase.md
@@ -241,7 +241,7 @@ Examples of **correct** code for this rule with the `{ "ignoreGlobals": true }`
 const foo = no_camelcased;
 ```
 
-## allow
+### allow
 
 Examples of **correct** code for this rule with the `allow` option:
 
diff --git a/docs/rules/comma-spacing.md b/docs/rules/comma-spacing.md
index 3160f86a8..d6a01563f 100644
--- a/docs/rules/comma-spacing.md
+++ b/docs/rules/comma-spacing.md
@@ -110,11 +110,6 @@ var arr = [,2 ,3]
 
 If your project will not be following a consistent comma-spacing pattern, turn this rule off.
 
-## Further Reading
-
-* [JavaScript](http://javascript.crockford.com/code.html)
-* [Dojo Style Guide](https://dojotoolkit.org/reference-guide/1.9/developer/styleguide.html)
-
 ## Related Rules
 
 * [array-bracket-spacing](array-bracket-spacing.md)
@@ -125,3 +120,8 @@ If your project will not be following a consistent comma-spacing pattern, turn t
 * [space-after-keywords](space-after-keywords.md)
 * [space-unary-ops](space-unary-ops.md)
 * [space-return-throw-case](space-return-throw-case.md)
+
+## Further Reading
+
+* [JavaScript](http://javascript.crockford.com/code.html)
+* [Dojo Style Guide](https://dojotoolkit.org/reference-guide/1.9/developer/styleguide.html)
diff --git a/docs/rules/comma-style.md b/docs/rules/comma-style.md
index f71e3105a..bae9a1495 100644
--- a/docs/rules/comma-style.md
+++ b/docs/rules/comma-style.md
@@ -157,13 +157,13 @@ var o = {fst:1,
 
 This rule can safely be turned off if your project does not care about enforcing a consistent comma style.
 
+## Related Rules
+
+* [operator-linebreak](operator-linebreak.md)
+
 ## Further Reading
 
 For more information on the Comma First style:
 
 * [A better coding convention for lists and object literals in JavaScript by isaacs](https://gist.github.com/isaacs/357981)
 * [npm coding style guideline](https://docs.npmjs.com/misc/coding-style)
-
-## Related Rules
-
-* [operator-linebreak](operator-linebreak.md)
diff --git a/docs/rules/complexity.md b/docs/rules/complexity.md
index 7955d1a28..5f33334a6 100644
--- a/docs/rules/complexity.md
+++ b/docs/rules/complexity.md
@@ -124,14 +124,6 @@ is equivalent to
 
 If you can't determine an appropriate complexity limit for your code, then it's best to disable this rule.
 
-## Further Reading
-
-* [Cyclomatic Complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity)
-* [Complexity Analysis of JavaScript Code](https://ariya.io/2012/12/complexity-analysis-of-javascript-code)
-* [More about Complexity in JavaScript](https://craftsmanshipforsoftware.com/2015/05/25/complexity-for-javascript/)
-* [About Complexity](https://web.archive.org/web/20160808115119/http://jscomplexity.org/complexity)
-* [Discussion about Complexity in ESLint and more links](https://github.com/eslint/eslint/issues/4808#issuecomment-167795140)
-
 ## Related Rules
 
 * [max-depth](max-depth.md)
@@ -141,3 +133,11 @@ If you can't determine an appropriate complexity limit for your code, then it's
 * [max-nested-callbacks](max-nested-callbacks.md)
 * [max-params](max-params.md)
 * [max-statements](max-statements.md)
+
+## Further Reading
+
+* [Cyclomatic Complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity)
+* [Complexity Analysis of JavaScript Code](https://ariya.io/2012/12/complexity-analysis-of-javascript-code)
+* [More about Complexity in JavaScript](https://craftsmanshipforsoftware.com/2015/05/25/complexity-for-javascript/)
+* [About Complexity](https://web.archive.org/web/20160808115119/http://jscomplexity.org/complexity)
+* [Discussion about Complexity in ESLint and more links](https://github.com/eslint/eslint/issues/4808#issuecomment-167795140)
diff --git a/docs/rules/default-case-last.md b/docs/rules/default-case-last.md
index c9eedbeec..a82530de1 100644
--- a/docs/rules/default-case-last.md
+++ b/docs/rules/default-case-last.md
@@ -116,10 +116,10 @@ if (foo !== 0) {
 doSomethingAnyway();
 ```
 
-## Further Reading
-
-* [MDN switch statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch)
-
 ## Related Rules
 
 * [default-case](default-case.md)
+
+## Further Reading
+
+* [MDN switch statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch)
diff --git a/docs/rules/for-direction.md b/docs/rules/for-direction.md
index be24f7f73..ecacabc2c 100644
--- a/docs/rules/for-direction.md
+++ b/docs/rules/for-direction.md
@@ -13,6 +13,9 @@ for (var i = 0; i < 10; i--) {
 
 for (var i = 10; i >= 0; i++) {
 }
+
+for (var i = 0; i > 10; i++) {
+}
 ```
 
 Examples of **correct** code for this rule:
diff --git a/docs/rules/func-call-spacing.md b/docs/rules/func-call-spacing.md
index 09829151e..45660fc44 100644
--- a/docs/rules/func-call-spacing.md
+++ b/docs/rules/func-call-spacing.md
@@ -17,12 +17,12 @@ new Date ();
 
 This rule requires or disallows spaces between the function name and the opening parenthesis that calls it.
 
-## options
+## Options
 
 This rule has a string option:
 
-- `"never"` (default) disallows space between the function name and the opening parenthesis.
-- `"always"` requires space between the function name and the opening parenthesis.
+* `"never"` (default) disallows space between the function name and the opening parenthesis.
+* `"always"` requires space between the function name and the opening parenthesis.
 
 Further, in `"always"` mode, a second object option is available that contains a single boolean `allowNewlines` property.
 
@@ -97,9 +97,9 @@ This rule can safely be turned off if your project does not care about enforcing
 
 ## Related Rules
 
-- [no-spaced-func](no-spaced-func.md) (deprecated)
+* [no-spaced-func](no-spaced-func.md) (deprecated)
 
 ## Compatibility
 
-- **JSCS**: [disallowSpacesInCallExpression](https://jscs-dev.github.io/rule/disallowSpacesInCallExpression)
-- **JSCS**: [requireSpacesInCallExpression](https://jscs-dev.github.io/rule/requireSpacesInCallExpression)
+* **JSCS**: [disallowSpacesInCallExpression](https://jscs-dev.github.io/rule/disallowSpacesInCallExpression)
+* **JSCS**: [requireSpacesInCallExpression](https://jscs-dev.github.io/rule/requireSpacesInCallExpression)
diff --git a/docs/rules/func-names.md b/docs/rules/func-names.md
index ea1ba617e..829cb99dd 100644
--- a/docs/rules/func-names.md
+++ b/docs/rules/func-names.md
@@ -206,12 +206,12 @@ Examples of **correct** code for this rule with the `"never", { "generators": "a
 var foo = bar(function *baz() {});
 ```
 
-## Further Reading
-
-* [Functions Explained](http://markdaggett.com/blog/2013/02/15/functions-explained/)
-* [Function Names in ES6](http://2ality.com/2015/09/function-names-es6.html)
-
 ## Compatibility
 
 * **JSCS**: [requireAnonymousFunctions](https://jscs-dev.github.io/rule/requireAnonymousFunctions)
 * **JSCS**: [disallowAnonymousFunctions](https://jscs-dev.github.io/rule/disallowAnonymousFunctions)
+
+## Further Reading
+
+* [Functions Explained](http://markdaggett.com/blog/2013/02/15/functions-explained/)
+* [Function Names in ES6](http://2ality.com/2015/09/function-names-es6.html)
diff --git a/docs/rules/grouped-accessor-pairs.md b/docs/rules/grouped-accessor-pairs.md
index 60848d1d0..d77c8abbf 100644
--- a/docs/rules/grouped-accessor-pairs.md
+++ b/docs/rules/grouped-accessor-pairs.md
@@ -313,14 +313,14 @@ See [no-dupe-keys](no-dupe-keys.md) if you also want to disallow duplicate keys
 
 See [no-dupe-class-members](no-dupe-class-members.md) if you also want to disallow duplicate names in class definitions.
 
-## Further Reading
-
-* [Object Setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)
-* [Object Getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
-* [Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
-
 ## Related Rules
 
 * [accessor-pairs](accessor-pairs.md)
 * [no-dupe-keys](no-dupe-keys.md)
 * [no-dupe-class-members](no-dupe-class-members.md)
+
+## Further Reading
+
+* [Object Setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)
+* [Object Getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
+* [Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
diff --git a/docs/rules/id-denylist.md b/docs/rules/id-denylist.md
index 071a34f79..1da92bb17 100644
--- a/docs/rules/id-denylist.md
+++ b/docs/rules/id-denylist.md
@@ -10,16 +10,16 @@ This rule disallows specified identifiers in assignments and `function` definiti
 
 This rule will catch disallowed identifiers that are:
 
-- variable declarations
-- function declarations
-- object properties assigned to during object creation
-- class fields
-- class methods
+* variable declarations
+* function declarations
+* object properties assigned to during object creation
+* class fields
+* class methods
 
 It will not catch disallowed identifiers that are:
 
-- function calls (so you can still use functions you do not have control over)
-- object properties (so you can still use objects you do not have control over)
+* function calls (so you can still use functions you do not have control over)
+* object properties (so you can still use objects you do not have control over)
 
 ## Options
 
diff --git a/docs/rules/implicit-arrow-linebreak.md b/docs/rules/implicit-arrow-linebreak.md
index a1a235535..5558dc503 100644
--- a/docs/rules/implicit-arrow-linebreak.md
+++ b/docs/rules/implicit-arrow-linebreak.md
@@ -6,16 +6,12 @@ An arrow function body can contain an implicit return as an expression instead o
 
 This rule aims to enforce a consistent location for an arrow function containing an implicit return.
 
-See Also:
-
-- [`brace-style`](https://eslint.org/docs/rules/brace-style) which enforces this behavior for arrow functions with block bodies.
-
 ### Options
 
 This rule accepts a string option:
 
-- `"beside"` (default) disallows a newline before an arrow function body.
-- `"below"` requires a newline before an arrow function body.
+* `"beside"` (default) disallows a newline before an arrow function body.
+* `"below"` requires a newline before an arrow function body.
 
 Examples of **incorrect** code for this rule with the default `"beside"` option:
 
@@ -98,4 +94,8 @@ Examples of **correct** code for this rule with the `"below"` option:
 
 If you're not concerned about consistent locations of implicitly returned arrow function expressions, you should not turn on this rule.
 
-You can also disable this rule if you are using the `"always"` option for the [`arrow-body-style`](https://eslint.org/docs/rules/arrow-body-style), since this will disable the use of implicit returns in arrow functions.
+You can also disable this rule if you are using the `"always"` option for the [`arrow-body-style`](arrow-body-style.md), since this will disable the use of implicit returns in arrow functions.
+
+## Related Rules
+
+* [`brace-style`](brace-style.md) which enforces this behavior for arrow functions with block bodies.
diff --git a/docs/rules/linebreak-style.md b/docs/rules/linebreak-style.md
index a4eb620ac..5143ae49d 100644
--- a/docs/rules/linebreak-style.md
+++ b/docs/rules/linebreak-style.md
@@ -66,7 +66,7 @@ function foo(params) { // \r\n
 } // \r\n
 ```
 
-## Using this rule with version control systems
+### Using this rule with version control systems
 
 Version control systems sometimes have special behavior for linebreaks. To make it easy for developers to contribute to your codebase from different platforms, you may want to configure your VCS to handle linebreaks appropriately.
 
diff --git a/docs/rules/max-classes-per-file.md b/docs/rules/max-classes-per-file.md
index 70f3348a0..dac65de9d 100644
--- a/docs/rules/max-classes-per-file.md
+++ b/docs/rules/max-classes-per-file.md
@@ -32,8 +32,8 @@ This rule may be configured with either an object or a number.
 
 If the option is an object, it may contain one or both of:
 
--   `ignoreExpressions`: a boolean option (defaulted to `false`) to ignore class expressions.
--   `max`: a numeric option (defaulted to 1) to specify the maximum number of classes.
+* `ignoreExpressions`: a boolean option (defaulted to `false`) to ignore class expressions.
+* `max`: a numeric option (defaulted to 1) to specify the maximum number of classes.
 
 For example:
 
diff --git a/docs/rules/max-lines-per-function.md b/docs/rules/max-lines-per-function.md
index f2af93b8d..3b01f7d24 100644
--- a/docs/rules/max-lines-per-function.md
+++ b/docs/rules/max-lines-per-function.md
@@ -6,7 +6,7 @@ Some people consider large functions a code smell. Large functions tend to do a
 
 This rule enforces a maximum number of lines per function, in order to aid in maintainability and reduce complexity.
 
-## Why not use `max-statements` or other complexity measurement rules instead?
+### Why not use `max-statements` or other complexity measurement rules instead?
 
 Nested long method chains like the below example are often broken onto separate lines for readability:
 
diff --git a/docs/rules/max-lines.md b/docs/rules/max-lines.md
index 74b9aada2..3842edc92 100644
--- a/docs/rules/max-lines.md
+++ b/docs/rules/max-lines.md
@@ -109,10 +109,6 @@ var a,
 
 You can turn this rule off if you are not concerned with the number of lines in your files.
 
-## Further reading
-
-* [Software Module size and file size](https://web.archive.org/web/20160725154648/http://www.mind2b.com/component/content/article/24-software-module-size-and-file-size)
-
 ## Related Rules
 
 * [complexity](complexity.md)
@@ -125,3 +121,7 @@ You can turn this rule off if you are not concerned with the number of lines in
 ## Compatibility
 
 * **JSCS**: [maximumNumberOfLines](https://jscs-dev.github.io/rule/maximumNumberOfLines)
+
+## Further Reading
+
+* [Software Module size and file size](https://web.archive.org/web/20160725154648/http://www.mind2b.com/component/content/article/24-software-module-size-and-file-size)
diff --git a/docs/rules/max-nested-callbacks.md b/docs/rules/max-nested-callbacks.md
index 24e4b907f..3b4ac5ee9 100644
--- a/docs/rules/max-nested-callbacks.md
+++ b/docs/rules/max-nested-callbacks.md
@@ -68,12 +68,6 @@ function handleFoo4() {
 }
 ```
 
-## Further Reading
-
-* [Control flow in Node.js](http://book.mixu.net/node/ch7.html)
-* [Control Flow in Node](https://howtonode.org/control-flow)
-* [Control Flow in Node Part II](https://howtonode.org/control-flow-part-ii)
-
 ## Related Rules
 
 * [complexity](complexity.md)
@@ -83,3 +77,9 @@ function handleFoo4() {
 * [max-lines-per-function](max-lines-per-function.md)
 * [max-params](max-params.md)
 * [max-statements](max-statements.md)
+
+## Further Reading
+
+* [Control flow in Node.js](http://book.mixu.net/node/ch7.html)
+* [Control Flow in Node](https://howtonode.org/control-flow)
+* [Control Flow in Node Part II](https://howtonode.org/control-flow-part-ii)
diff --git a/docs/rules/new-parens.md b/docs/rules/new-parens.md
index 0b2a49b7e..5237abdd4 100644
--- a/docs/rules/new-parens.md
+++ b/docs/rules/new-parens.md
@@ -14,8 +14,8 @@ This rule can enforce or disallow parentheses when invoking a constructor with n
 
 This rule takes one option.
 
-- `"always"` enforces parenthesis after a new constructor with no arguments (default)
-- `"never"` enforces no parenthesis after a new constructor with no arguments
+* `"always"` enforces parenthesis after a new constructor with no arguments (default)
+* `"never"` enforces no parenthesis after a new constructor with no arguments
 
 ### always
 
diff --git a/docs/rules/no-debugger.md b/docs/rules/no-debugger.md
index f8220bde8..5ff4da3fe 100644
--- a/docs/rules/no-debugger.md
+++ b/docs/rules/no-debugger.md
@@ -31,11 +31,11 @@ function isTruthy(x) {
 
 If your code is still very much in development and don't want to worry about stripping `debugger` statements, then turn this rule off. You'll generally want to turn it back on when testing code prior to deployment.
 
-## Further Reading
-
-* [Debugger](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger)
-
 ## Related Rules
 
 * [no-alert](no-alert.md)
 * [no-console](no-console.md)
+
+## Further Reading
+
+* [Debugger](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger)
diff --git a/docs/rules/no-eq-null.md b/docs/rules/no-eq-null.md
index 7b0f5df14..c06287fd8 100644
--- a/docs/rules/no-eq-null.md
+++ b/docs/rules/no-eq-null.md
@@ -40,10 +40,10 @@ while (qux !== null) {
 }
 ```
 
-## Compatibility
-
-* **JSHint**: This rule corresponds to `eqnull` rule of JSHint.
-
 ## When Not To Use It
 
 If you want to enforce type-checking operations in general, use the more powerful [eqeqeq](./eqeqeq) instead.
+
+## Compatibility
+
+* **JSHint**: This rule corresponds to `eqnull` rule of JSHint.
diff --git a/docs/rules/no-eval.md b/docs/rules/no-eval.md
index 4a2a3b797..eaa628f75 100644
--- a/docs/rules/no-eval.md
+++ b/docs/rules/no-eval.md
@@ -145,11 +145,11 @@ global.eval("var a = 0");
   foo.eval("var a = 0");
   ```
 
+## Related Rules
+
+* [no-implied-eval](no-implied-eval.md)
+
 ## Further Reading
 
 * [Eval is Evil, Part One](https://blogs.msdn.com/b/ericlippert/archive/2003/11/01/53329.aspx)
 * [How evil is eval](https://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/)
-
-## Related Rules
-
-* [no-implied-eval](no-implied-eval.md)
diff --git a/docs/rules/no-extra-parens.md b/docs/rules/no-extra-parens.md
index b521dcbe2..4b703a8d3 100644
--- a/docs/rules/no-extra-parens.md
+++ b/docs/rules/no-extra-parens.md
@@ -289,12 +289,12 @@ a = (b * c);
 typeof (a);
 ```
 
-## Further Reading
-
-* [MDN: Operator Precedence](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)
-
 ## Related Rules
 
 * [arrow-parens](arrow-parens.md)
 * [no-cond-assign](no-cond-assign.md)
 * [no-return-assign](no-return-assign.md)
+
+## Further Reading
+
+* [MDN: Operator Precedence](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)
diff --git a/docs/rules/no-implicit-coercion.md b/docs/rules/no-implicit-coercion.md
index 8ccee339f..9ad0b7710 100644
--- a/docs/rules/no-implicit-coercion.md
+++ b/docs/rules/no-implicit-coercion.md
@@ -33,11 +33,11 @@ This rule is aimed to flag shorter notations for the type conversion, then sugge
 
 This rule has three main options and one override option to allow some coercions as required.
 
--   `"boolean"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `boolean` type.
--   `"number"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `number` type.
--   `"string"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `string` type.
--   `"disallowTemplateShorthand"` (`false` by default) - When this is `true`, this rule warns `string` type conversions using `${expression}` form.
--   `"allow"` (`empty` by default) - Each entry in this array can be one of `~`, `!!`, `+` or `*` that are to be allowed.
+* `"boolean"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `boolean` type.
+* `"number"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `number` type.
+* `"string"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `string` type.
+* `"disallowTemplateShorthand"` (`false` by default) - When this is `true`, this rule warns `string` type conversions using `${expression}` form.
+* `"allow"` (`empty` by default) - Each entry in this array can be one of `~`, `!!`, `+` or `*` that are to be allowed.
 
 Note that operator `+` in `allow` list would allow `+foo` (number coercion) as well as `"" + foo` (string coercion).
 
diff --git a/docs/rules/no-implicit-globals.md b/docs/rules/no-implicit-globals.md
index 479d958d6..a7c03dc3b 100644
--- a/docs/rules/no-implicit-globals.md
+++ b/docs/rules/no-implicit-globals.md
@@ -214,13 +214,13 @@ and you also don't want this rule to warn you about the read-only globals, you c
 
 In the case of an ES module, if you don't want this rule to warn you about the read-only globals you can disable this rule.
 
+## Related Rules
+
+* [no-undef](no-undef.md)
+* [no-global-assign](no-global-assign.md)
+
 ## Further Reading
 
 * [Immediately-Invoked Function Expression (IIFE)](http://benalman.com/news/2010/11/immediately-invoked-function-expression/)
 * [ReferenceError: assignment to undeclared variable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Undeclared_var)
 * [Temporal Dead Zone](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone)
-
-## Related Rules
-
-* [no-undef](no-undef.md)
-* [no-global-assign](no-global-assign.md)
diff --git a/docs/rules/no-multiple-empty-lines.md b/docs/rules/no-multiple-empty-lines.md
index 1a0484182..2e1bd0e52 100644
--- a/docs/rules/no-multiple-empty-lines.md
+++ b/docs/rules/no-multiple-empty-lines.md
@@ -10,9 +10,9 @@ This rule aims to reduce the scrolling required when reading through your code.
 
 This rule has an object option:
 
--   `"max"` (default: `2`) enforces a maximum number of consecutive empty lines.
--   `"maxEOF"` enforces a maximum number of consecutive empty lines at the end of files.
--   `"maxBOF"` enforces a maximum number of consecutive empty lines at the beginning of files.
+* `"max"` (default: `2`) enforces a maximum number of consecutive empty lines.
+* `"maxEOF"` enforces a maximum number of consecutive empty lines at the end of files.
+* `"maxBOF"` enforces a maximum number of consecutive empty lines at the beginning of files.
 
 ### max
 
diff --git a/docs/rules/no-negated-in-lhs.md b/docs/rules/no-negated-in-lhs.md
index dd3d422f9..8961944ab 100644
--- a/docs/rules/no-negated-in-lhs.md
+++ b/docs/rules/no-negated-in-lhs.md
@@ -2,8 +2,6 @@
 
 This rule was **deprecated** in ESLint v3.3.0 and replaced by the [no-unsafe-negation](no-unsafe-negation.md) rule.
 
-## Rule Details
-
 Just as developers might type `-a + b` when they mean `-(a + b)` for the negative of a sum, they might type `!key in object` by mistake when they almost certainly mean `!(key in object)` to test that a key is not in an object.
 
 ## Rule Details
diff --git a/docs/rules/no-new-wrappers.md b/docs/rules/no-new-wrappers.md
index 45247e5ee..50fdacd78 100644
--- a/docs/rules/no-new-wrappers.md
+++ b/docs/rules/no-new-wrappers.md
@@ -68,11 +68,11 @@ var object = new MyString();
 
 If you want to allow the use of primitive wrapper objects, then you can safely disable this rule.
 
-## Further Reading
-
-* [Wrapper objects](https://www.inkling.com/read/javascript-definitive-guide-david-flanagan-6th/chapter-3/wrapper-objects)
-
 ## Related Rules
 
 * [no-array-constructor](no-array-constructor.md)
 * [no-new-object](no-new-object.md)
+
+## Further Reading
+
+* [Wrapper objects](https://www.inkling.com/read/javascript-definitive-guide-david-flanagan-6th/chapter-3/wrapper-objects)
diff --git a/docs/rules/no-nonoctal-decimal-escape.md b/docs/rules/no-nonoctal-decimal-escape.md
index 930b55560..ad210a737 100644
--- a/docs/rules/no-nonoctal-decimal-escape.md
+++ b/docs/rules/no-nonoctal-decimal-escape.md
@@ -53,10 +53,10 @@ var baz = "Don't use \\8 and \\9 escapes.";
 var quux = "\0\u0038";
 ```
 
-## Further Reading
-
-* [NonOctalDecimalEscapeSequence](https://tc39.es/ecma262/#prod-annexB-NonOctalDecimalEscapeSequence) in ECMAScript specification
-
 ## Related Rules
 
 * [no-octal-escape](no-octal-escape.md)
+
+## Further Reading
+
+* [NonOctalDecimalEscapeSequence](https://tc39.es/ecma262/#prod-annexB-NonOctalDecimalEscapeSequence) in ECMAScript specification
diff --git a/docs/rules/no-promise-executor-return.md b/docs/rules/no-promise-executor-return.md
index 1adfe37b1..87611c914 100644
--- a/docs/rules/no-promise-executor-return.md
+++ b/docs/rules/no-promise-executor-return.md
@@ -87,10 +87,10 @@ new Promise((resolve, reject) => {
 Promise.resolve(1);
 ```
 
-## Further Reading
-
-* [MDN Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
-
 ## Related Rules
 
 * [no-async-promise-executor](no-async-promise-executor.md)
+
+## Further Reading
+
+* [MDN Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
diff --git a/docs/rules/no-return-await.md b/docs/rules/no-return-await.md
index e3f7be259..fa7c7fc8e 100644
--- a/docs/rules/no-return-await.md
+++ b/docs/rules/no-return-await.md
@@ -50,9 +50,9 @@ async function foo() {
 
 There are a few reasons you might want to turn this rule off:
 
-- If you want to use `await` to denote a value that is a thenable
-- If you do not want the performance benefit of avoiding `return await`
-- If you want the functions to show up in stack traces (useful for debugging purposes)
+* If you want to use `await` to denote a value that is a thenable
+* If you do not want the performance benefit of avoiding `return await`
+* If you want the functions to show up in stack traces (useful for debugging purposes)
 
 ## Further Reading
 
diff --git a/docs/rules/no-self-assign.md b/docs/rules/no-self-assign.md
index 2991504e8..f7132e2b1 100644
--- a/docs/rules/no-self-assign.md
+++ b/docs/rules/no-self-assign.md
@@ -65,7 +65,7 @@ This rule has the option to check properties as well.
 }
 ```
 
-- `props` - if this is `true`, `no-self-assign` rule warns self-assignments of properties. Default is `true`.
+* `props` - if this is `true`, `no-self-assign` rule warns self-assignments of properties. Default is `true`.
 
 ### props
 
diff --git a/docs/rules/no-setter-return.md b/docs/rules/no-setter-return.md
index 53089746e..7e3b1323f 100644
--- a/docs/rules/no-setter-return.md
+++ b/docs/rules/no-setter-return.md
@@ -92,10 +92,10 @@ Object.defineProperty(foo, "bar", {
 });
 ```
 
-## Further Reading
-
-* [MDN setter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)
-
 ## Related Rules
 
 * [getter-return](getter-return.md)
+
+## Further Reading
+
+* [MDN setter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)
diff --git a/docs/rules/no-shadow-restricted-names.md b/docs/rules/no-shadow-restricted-names.md
index 890353da7..f7e6530d4 100644
--- a/docs/rules/no-shadow-restricted-names.md
+++ b/docs/rules/no-shadow-restricted-names.md
@@ -37,11 +37,11 @@ function f(a, b){}
 var undefined;
 ```
 
+## Related Rules
+
+* [no-shadow](no-shadow.md)
+
 ## Further Reading
 
 * [Annotated ES5 - §15.1.1](https://es5.github.io/#x15.1.1)
 * [Annotated ES5 - Annex C](https://es5.github.io/#C)
-
-## Related Rules
-
-* [no-shadow](no-shadow.md)
diff --git a/docs/rules/no-shadow.md b/docs/rules/no-shadow.md
index 3bf9783a9..bf8400a42 100644
--- a/docs/rules/no-shadow.md
+++ b/docs/rules/no-shadow.md
@@ -164,10 +164,10 @@ foo(function (err, result) {
 });
 ```
 
-## Further Reading
-
-* [Variable Shadowing](https://en.wikipedia.org/wiki/Variable_shadowing)
-
 ## Related Rules
 
 * [no-shadow-restricted-names](no-shadow-restricted-names.md)
+
+## Further Reading
+
+* [Variable Shadowing](https://en.wikipedia.org/wiki/Variable_shadowing)
diff --git a/docs/rules/no-undef.md b/docs/rules/no-undef.md
index a7de80523..f31f2877c 100644
--- a/docs/rules/no-undef.md
+++ b/docs/rules/no-undef.md
@@ -101,11 +101,11 @@ module.exports = function() {
 
 If explicit declaration of global variables is not to your taste.
 
-## Compatibility
-
-This rule provides compatibility with treatment of global variables in [JSHint](http://jshint.com/) and [JSLint](http://www.jslint.com).
-
 ## Related Rules
 
 * [no-global-assign](no-global-assign.md)
 * [no-redeclare](no-redeclare.md)
+
+## Compatibility
+
+This rule provides compatibility with treatment of global variables in [JSHint](http://jshint.com/) and [JSLint](http://www.jslint.com).
diff --git a/docs/rules/no-undefined.md b/docs/rules/no-undefined.md
index 0e67c21fd..3d97d5b1d 100644
--- a/docs/rules/no-undefined.md
+++ b/docs/rules/no-undefined.md
@@ -64,15 +64,15 @@ global.undefined = "foo";
 
 If you want to allow the use of `undefined` in your code, then you can safely turn this rule off.
 
-## Further Reading
-
-* [undefined - JavaScript \| MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)
-* [Understanding JavaScript’s ‘undefined’ \| JavaScript, JavaScript...](https://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/)
-* [ECMA262 edition 5.1 &sect;15.1.1.3: undefined](https://es5.github.io/#x15.1.1.3)
-
 ## Related Rules
 
 * [no-undef-init](no-undef-init.md)
 * [no-void](no-void.md)
 * [no-shadow-restricted-names](no-shadow-restricted-names.md)
 * [no-global-assign](no-global-assign.md)
+
+## Further Reading
+
+* [undefined - JavaScript \| MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)
+* [Understanding JavaScript’s ‘undefined’ \| JavaScript, JavaScript...](https://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/)
+* [ECMA262 edition 5.1 &sect;15.1.1.3: undefined](https://es5.github.io/#x15.1.1.3)
diff --git a/docs/rules/no-underscore-dangle.md b/docs/rules/no-underscore-dangle.md
index ded42815d..5e33ed5d0 100644
--- a/docs/rules/no-underscore-dangle.md
+++ b/docs/rules/no-underscore-dangle.md
@@ -42,12 +42,12 @@ const foo = (_bar) => {};
 
 This rule has an object option:
 
--  `"allow"` allows specified identifiers to have dangling underscores
--  `"allowAfterThis": false` (default) disallows dangling underscores in members of the `this` object
--  `"allowAfterSuper": false` (default) disallows dangling underscores in members of the `super` object
--  `"allowAfterThisConstructor": false` (default) disallows dangling underscores in members of the `this.constructor` object
--  `"enforceInMethodNames": false` (default) allows dangling underscores in method names
--  `"allowFunctionParams": true` (default) allows dangling underscores in function parameter names
+* `"allow"` allows specified identifiers to have dangling underscores
+* `"allowAfterThis": false` (default) disallows dangling underscores in members of the `this` object
+* `"allowAfterSuper": false` (default) disallows dangling underscores in members of the `super` object
+* `"allowAfterThisConstructor": false` (default) disallows dangling underscores in members of the `this.constructor` object
+* `"enforceInMethodNames": false` (default) allows dangling underscores in method names
+* `"allowFunctionParams": true` (default) allows dangling underscores in function parameter names
 
 ### allow
 
diff --git a/docs/rules/no-unreachable-loop.md b/docs/rules/no-unreachable-loop.md
index c58b97f38..88324df8d 100644
--- a/docs/rules/no-unreachable-loop.md
+++ b/docs/rules/no-unreachable-loop.md
@@ -146,7 +146,7 @@ This rule has an object option, with one option:
 
 * `"ignore"` - an optional array of loop types that will be ignored by this rule.
 
-## ignore
+### ignore
 
 You can specify up to 5 different elements in the `"ignore"` array:
 
diff --git a/docs/rules/no-unsafe-negation.md b/docs/rules/no-unsafe-negation.md
index 38bb9b02f..a87284745 100644
--- a/docs/rules/no-unsafe-negation.md
+++ b/docs/rules/no-unsafe-negation.md
@@ -6,8 +6,8 @@ Just as developers might type `-a + b` when they mean `-(a + b)` for the negativ
 
 This rule disallows negating the left operand of the following relational operators:
 
-- [`in` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in).
-- [`instanceof` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof).
+* [`in` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in).
+* [`instanceof` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof).
 
 Examples of **incorrect** code for this rule:
 
@@ -74,17 +74,17 @@ if (!(foo) in object) {
 
 This rule has an object option:
 
-- `"enforceForOrderingRelations": false` (default) allows negation of the left-hand side of ordering relational operators (`<`, `>`, `<=`, `>=`)
-- `"enforceForOrderingRelations": true` disallows negation of the left-hand side of ordering relational operators
+* `"enforceForOrderingRelations": false` (default) allows negation of the left-hand side of ordering relational operators (`<`, `>`, `<=`, `>=`)
+* `"enforceForOrderingRelations": true` disallows negation of the left-hand side of ordering relational operators
 
 ### enforceForOrderingRelations
 
 With this option set to `true` the rule is additionally enforced for:
 
-- `<` operator.
-- `>` operator.
-- `<=` operator.
-- `>=` operator.
+* `<` operator.
+* `>` operator.
+* `<=` operator.
+* `>=` operator.
 
 The purpose is to avoid expressions such as `! a < b` (which is equivalent to `(a ? 0 : 1) < b`) when what is really intended is `!(a < b)`.
 
diff --git a/docs/rules/no-unsafe-optional-chaining.md b/docs/rules/no-unsafe-optional-chaining.md
index 49fa415e0..28b4c4054 100644
--- a/docs/rules/no-unsafe-optional-chaining.md
+++ b/docs/rules/no-unsafe-optional-chaining.md
@@ -115,15 +115,15 @@ async function foo () {
 
 This rule has an object option:
 
-- `disallowArithmeticOperators`: Disallow arithmetic operations on optional chaining expressions (Default `false`). If this is `true`, this rule warns arithmetic operations on optional chaining expressions, which possibly result in `NaN`.
+* `disallowArithmeticOperators`: Disallow arithmetic operations on optional chaining expressions (Default `false`). If this is `true`, this rule warns arithmetic operations on optional chaining expressions, which possibly result in `NaN`.
 
 ### disallowArithmeticOperators
 
 With this option set to `true` the rule is enforced for:
 
-- Unary operators: `-`, `+`
-- Arithmetic operators: `+`, `-`, `/`, `*`, `%`, `**`
-- Assignment operators: `+=`, `-=`, `/=`, `*=`, `%=`, `**=`
+* Unary operators: `-`, `+`
+* Arithmetic operators: `+`, `-`, `/`, `*`, `%`, `**`
+* Assignment operators: `+=`, `-=`, `/=`, `*=`, `%=`, `**=`
 
 Examples of additional **incorrect** code for this rule with the `{ "disallowArithmeticOperators": true }` option:
 
diff --git a/docs/rules/no-useless-backreference.md b/docs/rules/no-useless-backreference.md
index d2360b395..e72b050d0 100644
--- a/docs/rules/no-useless-backreference.md
+++ b/docs/rules/no-useless-backreference.md
@@ -119,12 +119,12 @@ Examples of additional **correct** code for this rule:
 /^(a)\1\2$/.test("aa\x02"); // true. In this case, \1 is a backreference, \2 is an octal escape sequence.
 ```
 
-## Further Reading
-
-* [MDN: Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
-
 ## Related Rules
 
 * [no-control-regex](no-control-regex.md)
 * [no-empty-character-class](no-empty-character-class.md)
 * [no-invalid-regexp](no-invalid-regexp.md)
+
+## Further Reading
+
+* [MDN: Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
diff --git a/docs/rules/no-useless-escape.md b/docs/rules/no-useless-escape.md
index 6088c5cb0..1f54b588d 100644
--- a/docs/rules/no-useless-escape.md
+++ b/docs/rules/no-useless-escape.md
@@ -26,7 +26,8 @@ Examples of **incorrect** code for this rule:
 `\#{foo}`;
 /\!/;
 /\@/;
-
+/[\[]/;
+/[a-z\-]/;
 ```
 
 Examples of **correct** code for this rule:
@@ -46,7 +47,9 @@ Examples of **correct** code for this rule:
 /\\/g;
 /\t/g;
 /\w\$\*\^\./;
-
+/[[]/;
+/[\]]/;
+/[a-z-]/;
 ```
 
 ## When Not To Use It
diff --git a/docs/rules/no-useless-rename.md b/docs/rules/no-useless-rename.md
index ea38e844b..fba312332 100644
--- a/docs/rules/no-useless-rename.md
+++ b/docs/rules/no-useless-rename.md
@@ -28,17 +28,13 @@ let { foo } = bar;
 
 This rule disallows the renaming of import, export, and destructured assignments to the same name.
 
-See Also:
-
-- [`object-shorthand`](https://eslint.org/docs/rules/object-shorthand) which can enforce this behavior for properties in object literals.
-
 ## Options
 
 This rule allows for more fine-grained control with the following options:
 
-- `ignoreImport`: When set to `true`, this rule does not check imports
-- `ignoreExport`: When set to `true`, this rule does not check exports
-- `ignoreDestructuring`: When set to `true`, this rule does not check destructuring assignments
+* `ignoreImport`: When set to `true`, this rule does not check imports
+* `ignoreExport`: When set to `true`, this rule does not check exports
+* `ignoreDestructuring`: When set to `true`, this rule does not check destructuring assignments
 
 By default, all options are set to `false`:
 
@@ -119,6 +115,10 @@ function foo({ bar: bar }) {}
 
 You can safely disable this rule if you do not care about redundantly renaming import, export, and destructuring assignments.
 
+## Related Rules
+
+* [`object-shorthand`](object-shorthand.md) which can enforce this behavior for properties in object literals.
+
 ## Compatibility
 
-- **JSCS**: [disallowIdenticalDestructuringNames](https://jscs-dev.github.io/rule/disallowIdenticalDestructuringNames)
+* **JSCS**: [disallowIdenticalDestructuringNames](https://jscs-dev.github.io/rule/disallowIdenticalDestructuringNames)
diff --git a/docs/rules/no-void.md b/docs/rules/no-void.md
index 3f7837622..4f6a976f3 100644
--- a/docs/rules/no-void.md
+++ b/docs/rules/no-void.md
@@ -96,12 +96,12 @@ void someFunction();
 
 If you intentionally use the `void` operator then you can disable this rule.
 
-## Further Reading
-
-* [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void)
-* [Bad Parts: Appendix B - JavaScript: The Good Parts by Douglas Crockford](https://oreilly.com/javascript/excerpts/javascript-good-parts/bad-parts.html)
-
 ## Related Rules
 
 * [no-undef-init](no-undef-init.md)
 * [no-undefined](no-undefined.md)
+
+## Further Reading
+
+* [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void)
+* [Bad Parts: Appendix B - JavaScript: The Good Parts by Douglas Crockford](https://oreilly.com/javascript/excerpts/javascript-good-parts/bad-parts.html)
diff --git a/docs/rules/object-curly-newline.md b/docs/rules/object-curly-newline.md
index cc98b4293..e7089d291 100644
--- a/docs/rules/object-curly-newline.md
+++ b/docs/rules/object-curly-newline.md
@@ -531,11 +531,6 @@ export { foo, bar } from 'foo-bar';
 export { foo as f, bar } from 'foo-bar';
 ```
 
-## Compatibility
-
-* **JSCS**: [requirePaddingNewLinesInObjects](https://jscs-dev.github.io/rule/requirePaddingNewLinesInObjects)
-* **JSCS**: [disallowPaddingNewLinesInObjects](https://jscs-dev.github.io/rule/disallowPaddingNewLinesInObjects)
-
 ## When Not To Use It
 
 If you don't want to enforce consistent line breaks after opening and before closing braces, then it's safe to disable this rule.
@@ -546,3 +541,8 @@ If you don't want to enforce consistent line breaks after opening and before clo
 * [key-spacing](key-spacing.md)
 * [object-curly-spacing](object-curly-spacing.md)
 * [object-property-newline](object-property-newline.md)
+
+## Compatibility
+
+* **JSCS**: [requirePaddingNewLinesInObjects](https://jscs-dev.github.io/rule/requirePaddingNewLinesInObjects)
+* **JSCS**: [disallowPaddingNewLinesInObjects](https://jscs-dev.github.io/rule/disallowPaddingNewLinesInObjects)
diff --git a/docs/rules/object-property-newline.md b/docs/rules/object-property-newline.md
index 893e54f2e..8c18decb1 100644
--- a/docs/rules/object-property-newline.md
+++ b/docs/rules/object-property-newline.md
@@ -90,9 +90,9 @@ will be prohibited, because two properties, but not all properties, appear on th
 
 This rule applies equally to all property specifications, regardless of notation, including:
 
-- `a: 1` (ES5)
-- `a` (ES2015 shorthand property)
-- ``[`prop${a}`]`` (ES2015 computed property name)
+* `a: 1` (ES5)
+* `a` (ES2015 shorthand property)
+* ``[`prop${a}`]`` (ES2015 computed property name)
 
 Thus, the rule (without the object option) prohibits both of these:
 
@@ -258,13 +258,13 @@ const obj3 = {
 
 You can turn this rule off if you want to decide, case-by-case, whether to place property specifications on separate lines.
 
-## Compatibility
+## Related Rules
 
-- **JSCS**: This rule provides partial compatibility with [requireObjectKeysOnNewLine](https://jscs-dev.github.io/rule/requireObjectKeysOnNewLine).
+* [brace-style](brace-style.md)
+* [comma-dangle](comma-dangle.md)
+* [key-spacing](key-spacing.md)
+* [object-curly-spacing](object-curly-spacing.md)
 
-## Related Rules
+## Compatibility
 
-- [brace-style](brace-style.md)
-- [comma-dangle](comma-dangle.md)
-- [key-spacing](key-spacing.md)
-- [object-curly-spacing](object-curly-spacing.md)
+* **JSCS**: This rule provides partial compatibility with [requireObjectKeysOnNewLine](https://jscs-dev.github.io/rule/requireObjectKeysOnNewLine).
diff --git a/docs/rules/object-shorthand.md b/docs/rules/object-shorthand.md
index fee0e62f4..0cbf90b4b 100644
--- a/docs/rules/object-shorthand.md
+++ b/docs/rules/object-shorthand.md
@@ -81,20 +81,16 @@ var foo = {
 };
 ```
 
-See Also:
-
-- [`no-useless-rename`](https://eslint.org/docs/rules/no-useless-rename) which disallows renaming import, export, and destructured assignments to the same name.
-
 ## Options
 
 The rule takes an option which specifies when it should be applied. It can be set to one of the following values:
 
-- `"always"` (default) expects that the shorthand will be used whenever possible.
-- `"methods"` ensures the method shorthand is used (also applies to generators).
-- `"properties"` ensures the property shorthand is used (where the key and variable name match).
-- `"never"` ensures that no property or method shorthand is used in any object literal.
-- `"consistent"` ensures that either all shorthand or all long-form will be used in an object literal.
-- `"consistent-as-needed"` ensures that either all shorthand or all long-form will be used in an object literal, but ensures all shorthand whenever possible.
+* `"always"` (default) expects that the shorthand will be used whenever possible.
+* `"methods"` ensures the method shorthand is used (also applies to generators).
+* `"properties"` ensures the property shorthand is used (where the key and variable name match).
+* `"never"` ensures that no property or method shorthand is used in any object literal.
+* `"consistent"` ensures that either all shorthand or all long-form will be used in an object literal.
+* `"consistent-as-needed"` ensures that either all shorthand or all long-form will be used in an object literal, but ensures all shorthand whenever possible.
 
 You can set the option in configuration like this:
 
@@ -106,9 +102,9 @@ You can set the option in configuration like this:
 
 Additionally, the rule takes an optional object configuration:
 
-- `"avoidQuotes": true` indicates that long-form syntax is preferred whenever the object key is a string literal (default: `false`). Note that this option can only be enabled when the string option is set to `"always"`, `"methods"`, or `"properties"`.
-- `"ignoreConstructors": true` can be used to prevent the rule from reporting errors for constructor functions. (By default, the rule treats constructors the same way as other functions.) Note that this option can only be enabled when the string option is set to `"always"` or `"methods"`.
-- `"avoidExplicitReturnArrows": true` indicates that methods are preferred over explicit-return arrow functions for function properties. (By default, the rule allows either of these.) Note that this option can only be enabled when the string option is set to `"always"` or `"methods"`.
+* `"avoidQuotes": true` indicates that long-form syntax is preferred whenever the object key is a string literal (default: `false`). Note that this option can only be enabled when the string option is set to `"always"`, `"methods"`, or `"properties"`.
+* `"ignoreConstructors": true` can be used to prevent the rule from reporting errors for constructor functions. (By default, the rule treats constructors the same way as other functions.) Note that this option can only be enabled when the string option is set to `"always"` or `"methods"`.
+* `"avoidExplicitReturnArrows": true` indicates that methods are preferred over explicit-return arrow functions for function properties. (By default, the rule allows either of these.) Note that this option can only be enabled when the string option is set to `"always"` or `"methods"`.
 
 ### `avoidQuotes`
 
@@ -246,6 +242,10 @@ var foo = {
 Anyone not yet in an ES6 environment would not want to apply this rule. Others may find the terseness of the shorthand
 syntax harder to read and may not want to encourage it with this rule.
 
+## Related Rules
+
+* [`no-useless-rename`](no-useless-rename.md) which disallows renaming import, export, and destructured assignments to the same name.
+
 ## Further Reading
 
 [Object initializer - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer)
diff --git a/docs/rules/padding-line-between-statements.md b/docs/rules/padding-line-between-statements.md
index 065c7d937..9cf15fc37 100644
--- a/docs/rules/padding-line-between-statements.md
+++ b/docs/rules/padding-line-between-statements.md
@@ -38,54 +38,54 @@ You can supply any number of configurations. If a statement pair matches multipl
 }
 ```
 
-- `LINEBREAK_TYPE` is one of the following.
-    - `"any"` just ignores the statement pair.
-    - `"never"` disallows blank lines.
-    - `"always"` requires one or more blank lines. Note it does not count lines that comments exist as blank lines.
-
-- `STATEMENT_TYPE` is one of the following, or an array of the following.
-    - `"*"` is wildcard. This matches any statements.
-    - `"block"` is lonely blocks.
-    - `"block-like"` is block like statements. This matches statements that the last token is the closing brace of blocks; e.g. `{ }`, `if (a) { }`, and `while (a) { }`. Also matches immediately invoked function expression statements.
-    - `"break"` is `break` statements.
-    - `"case"` is `case` clauses in `switch` statements.
-    - `"cjs-export"` is `export` statements of CommonJS; e.g. `module.exports = 0`, `module.exports.foo = 1`, and `exports.foo = 2`. This is a special case of assignment.
-    - `"cjs-import"` is `import` statements of CommonJS; e.g. `const foo = require("foo")`. This is a special case of variable declarations.
-    - `"class"` is `class` declarations.
-    - `"const"` is `const` variable declarations, both single-line and multiline.
-    - `"continue"` is `continue` statements.
-    - `"debugger"` is `debugger` statements.
-    - `"default"` is `default` clauses in `switch` statements.
-    - `"directive"` is directive prologues. This matches directives; e.g. `"use strict"`.
-    - `"do"` is `do-while` statements. This matches all statements that the first token is `do` keyword.
-    - `"empty"` is empty statements.
-    - `"export"` is `export` declarations.
-    - `"expression"` is expression statements.
-    - `"for"` is `for` loop families. This matches all statements that the first token is `for` keyword.
-    - `"function"` is function declarations.
-    - `"if"` is `if` statements.
-    - `"iife"` is immediately invoked function expression statements. This matches calls on a function expression, optionally prefixed with a unary operator.
-    - `"import"` is `import` declarations.
-    - `"let"` is `let` variable declarations, both single-line and multiline.
-    - `"multiline-block-like"` is block like statements. This is the same as `block-like` type, but only if the block is multiline.
-    - `"multiline-const"` is multiline `const` variable declarations.
-    - `"multiline-expression"` is expression statements. This is the same as `expression` type, but only if the statement is multiline.
-    - `"multiline-let"` is multiline `let` variable declarations.
-    - `"multiline-var"` is multiline `var` variable declarations.
-    - `"return"` is `return` statements.
-    - `"singleline-const"` is single-line `const` variable declarations.
-    - `"singleline-let"` is single-line `let` variable declarations.
-    - `"singleline-var"` is single-line `var` variable declarations.
-    - `"switch"` is `switch` statements.
-    - `"throw"` is `throw` statements.
-    - `"try"` is `try` statements.
-    - `"var"` is `var` variable declarations, both single-line and multiline.
-    - `"while"` is `while` loop statements.
-    - `"with"` is `with` statements.
+* `LINEBREAK_TYPE` is one of the following.
+    * `"any"` just ignores the statement pair.
+    * `"never"` disallows blank lines.
+    * `"always"` requires one or more blank lines. Note it does not count lines that comments exist as blank lines.
+
+* `STATEMENT_TYPE` is one of the following, or an array of the following.
+    * `"*"` is wildcard. This matches any statements.
+    * `"block"` is lonely blocks.
+    * `"block-like"` is block like statements. This matches statements that the last token is the closing brace of blocks; e.g. `{ }`, `if (a) { }`, and `while (a) { }`. Also matches immediately invoked function expression statements.
+    * `"break"` is `break` statements.
+    * `"case"` is `case` clauses in `switch` statements.
+    * `"cjs-export"` is `export` statements of CommonJS; e.g. `module.exports = 0`, `module.exports.foo = 1`, and `exports.foo = 2`. This is a special case of assignment.
+    * `"cjs-import"` is `import` statements of CommonJS; e.g. `const foo = require("foo")`. This is a special case of variable declarations.
+    * `"class"` is `class` declarations.
+    * `"const"` is `const` variable declarations, both single-line and multiline.
+    * `"continue"` is `continue` statements.
+    * `"debugger"` is `debugger` statements.
+    * `"default"` is `default` clauses in `switch` statements.
+    * `"directive"` is directive prologues. This matches directives; e.g. `"use strict"`.
+    * `"do"` is `do-while` statements. This matches all statements that the first token is `do` keyword.
+    * `"empty"` is empty statements.
+    * `"export"` is `export` declarations.
+    * `"expression"` is expression statements.
+    * `"for"` is `for` loop families. This matches all statements that the first token is `for` keyword.
+    * `"function"` is function declarations.
+    * `"if"` is `if` statements.
+    * `"iife"` is immediately invoked function expression statements. This matches calls on a function expression, optionally prefixed with a unary operator.
+    * `"import"` is `import` declarations.
+    * `"let"` is `let` variable declarations, both single-line and multiline.
+    * `"multiline-block-like"` is block like statements. This is the same as `block-like` type, but only if the block is multiline.
+    * `"multiline-const"` is multiline `const` variable declarations.
+    * `"multiline-expression"` is expression statements. This is the same as `expression` type, but only if the statement is multiline.
+    * `"multiline-let"` is multiline `let` variable declarations.
+    * `"multiline-var"` is multiline `var` variable declarations.
+    * `"return"` is `return` statements.
+    * `"singleline-const"` is single-line `const` variable declarations.
+    * `"singleline-let"` is single-line `let` variable declarations.
+    * `"singleline-var"` is single-line `var` variable declarations.
+    * `"switch"` is `switch` statements.
+    * `"throw"` is `throw` statements.
+    * `"try"` is `try` statements.
+    * `"var"` is `var` variable declarations, both single-line and multiline.
+    * `"while"` is `while` loop statements.
+    * `"with"` is `with` statements.
 
 ## Examples
 
-This configuration would require blank lines before all `return` statements, like the [newline-before-return] rule.
+This configuration would require blank lines before all `return` statements, like the [newline-before-return](newline-before-return.md) rule.
 
 Examples of **incorrect** code for the `[{ blankLine: "always", prev: "*", next: "return" }]` configuration:
 
@@ -122,7 +122,7 @@ function foo() {
 
 ----
 
-This configuration would require blank lines after every sequence of variable declarations, like the [newline-after-var] rule.
+This configuration would require blank lines after every sequence of variable declarations, like the [newline-after-var](newline-after-var.md) rule.
 
 Examples of **incorrect** code for the `[{ blankLine: "always", prev: ["const", "let", "var"], next: "*"}, { blankLine: "any", prev: ["const", "let", "var"], next: ["const", "let", "var"]}]` configuration:
 
@@ -198,7 +198,7 @@ class C {
 
 ----
 
-This configuration would require blank lines after all directive prologues, like the [lines-around-directive] rule.
+This configuration would require blank lines after all directive prologues, like the [lines-around-directive](lines-around-directive.md) rule.
 
 Examples of **incorrect** code for the `[{ blankLine: "always", prev: "directive", next: "*" }, { blankLine: "any", prev: "directive", next: "directive" }]` configuration:
 
@@ -277,31 +277,18 @@ switch (foo) {
 }
 ```
 
-## Compatibility
-
-- **JSCS:** [requirePaddingNewLineAfterVariableDeclaration]
-- **JSCS:** [requirePaddingNewLinesAfterBlocks]
-- **JSCS:** [disallowPaddingNewLinesAfterBlocks]
-- **JSCS:** [requirePaddingNewLinesAfterUseStrict]
-- **JSCS:** [disallowPaddingNewLinesAfterUseStrict]
-- **JSCS:** [requirePaddingNewLinesBeforeExport]
-- **JSCS:** [disallowPaddingNewLinesBeforeExport]
-- **JSCS:** [requirePaddingNewlinesBeforeKeywords]
-- **JSCS:** [disallowPaddingNewlinesBeforeKeywords]
-
 ## When Not To Use It
 
 If you don't want to notify warnings about linebreaks, then it's safe to disable this rule.
 
-[lines-around-directive]: https://eslint.org/docs/rules/lines-around-directive
-[newline-after-var]: https://eslint.org/docs/rules/newline-after-var
-[newline-before-return]: https://eslint.org/docs/rules/newline-before-return
-[requirePaddingNewLineAfterVariableDeclaration]: https://jscs-dev.github.io/rule/requirePaddingNewLineAfterVariableDeclaration
-[requirePaddingNewLinesAfterBlocks]: https://jscs-dev.github.io/rule/requirePaddingNewLinesAfterBlocks
-[disallowPaddingNewLinesAfterBlocks]: https://jscs-dev.github.io/rule/disallowPaddingNewLinesAfterBlocks
-[requirePaddingNewLinesAfterUseStrict]: https://jscs-dev.github.io/rule/requirePaddingNewLinesAfterUseStrict
-[disallowPaddingNewLinesAfterUseStrict]: https://jscs-dev.github.io/rule/disallowPaddingNewLinesAfterUseStrict
-[requirePaddingNewLinesBeforeExport]: https://jscs-dev.github.io/rule/requirePaddingNewLinesBeforeExport
-[disallowPaddingNewLinesBeforeExport]: https://jscs-dev.github.io/rule/disallowPaddingNewLinesBeforeExport
-[requirePaddingNewlinesBeforeKeywords]: https://jscs-dev.github.io/rule/requirePaddingNewlinesBeforeKeywords
-[disallowPaddingNewlinesBeforeKeywords]: https://jscs-dev.github.io/rule/disallowPaddingNewlinesBeforeKeywords
+## Compatibility
+
+* **JSCS:** [requirePaddingNewLineAfterVariableDeclaration](https://jscs-dev.github.io/rule/requirePaddingNewLineAfterVariableDeclaration)
+* **JSCS:** [requirePaddingNewLinesAfterBlocks](https://jscs-dev.github.io/rule/requirePaddingNewLinesAfterBlocks)
+* **JSCS:** [disallowPaddingNewLinesAfterBlocks](https://jscs-dev.github.io/rule/disallowPaddingNewLinesAfterBlocks)
+* **JSCS:** [requirePaddingNewLinesAfterUseStrict](https://jscs-dev.github.io/rule/requirePaddingNewLinesAfterUseStrict)
+* **JSCS:** [disallowPaddingNewLinesAfterUseStrict](https://jscs-dev.github.io/rule/disallowPaddingNewLinesAfterUseStrict)
+* **JSCS:** [requirePaddingNewLinesBeforeExport](https://jscs-dev.github.io/rule/requirePaddingNewLinesBeforeExport)
+* **JSCS:** [disallowPaddingNewLinesBeforeExport](https://jscs-dev.github.io/rule/disallowPaddingNewLinesBeforeExport)
+* **JSCS:** [requirePaddingNewlinesBeforeKeywords](https://jscs-dev.github.io/rule/requirePaddingNewlinesBeforeKeywords)
+* **JSCS:** [disallowPaddingNewlinesBeforeKeywords](https://jscs-dev.github.io/rule/disallowPaddingNewlinesBeforeKeywords)
diff --git a/docs/rules/prefer-arrow-callback.md b/docs/rules/prefer-arrow-callback.md
index 7b98aa1f8..94020f809 100644
--- a/docs/rules/prefer-arrow-callback.md
+++ b/docs/rules/prefer-arrow-callback.md
@@ -6,9 +6,9 @@ For example, arrow functions are automatically bound to their surrounding scope/
 
 Additionally, arrow functions are:
 
-- less verbose, and easier to reason about.
+* less verbose, and easier to reason about.
 
-- bound lexically regardless of where or when they are invoked.
+* bound lexically regardless of where or when they are invoked.
 
 ## Rule Details
 
@@ -91,10 +91,10 @@ someArray.map(function(item) { return this.doSomething(item); }, someObject);
 
 ## When Not To Use It
 
-- In environments that have not yet adopted ES6 language features (ES3/5).
+* In environments that have not yet adopted ES6 language features (ES3/5).
 
-- In ES6+ environments that allow the use of function expressions when describing callbacks or function arguments.
+* In ES6+ environments that allow the use of function expressions when describing callbacks or function arguments.
 
 ## Further Reading
 
-- [More on ES6 arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
+* [More on ES6 arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
diff --git a/docs/rules/prefer-destructuring.md b/docs/rules/prefer-destructuring.md
index b0f887c13..f07c03b31 100644
--- a/docs/rules/prefer-destructuring.md
+++ b/docs/rules/prefer-destructuring.md
@@ -18,8 +18,8 @@ The rule has a second object with a single key, `enforceForRenamedProperties`, w
 
 **Note**: It is not possible to determine if a variable will be referring to an object or an array at runtime. This rule therefore guesses the assignment type by checking whether the key being accessed is an integer. This can lead to the following possibly confusing situations:
 
-- Accessing an object property whose key is an integer will fall under the category `array` destructuring.
-- Accessing an array element through a computed index will fall under the category `object` destructuring.
+* Accessing an object property whose key is an integer will fall under the category `array` destructuring.
+* Accessing an array element through a computed index will fall under the category `object` destructuring.
 
 The `--fix` option on the command line fixes only problems reported in variable declarations, and among them only those that fall under the category `object` destructuring. Furthermore, the name of the declared variable has to be the same as the name used for non-computed member access in the initializer. For example, `var foo = object.foo` can be automatically fixed by this rule. Problems that involve computed member access (e.g., `var foo = object[foo]`) or renamed properties (e.g., `var foo = object.bar`) are not automatically fixed.
 
@@ -183,5 +183,5 @@ var [bar] = $('body'); // fails with a TypeError
 
 If you want to learn more about destructuring, check out the links below:
 
-- [Destructuring Assignment (MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
-- [Destructuring and parameter handling in ECMAScript 6 (2ality blog)](http://2ality.com/2015/01/es6-destructuring.html)
+* [Destructuring Assignment (MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
+* [Destructuring and parameter handling in ECMAScript 6 (2ality blog)](http://2ality.com/2015/01/es6-destructuring.html)
diff --git a/docs/rules/prefer-promise-reject-errors.md b/docs/rules/prefer-promise-reject-errors.md
index 9740bc975..0cff0ea0a 100644
--- a/docs/rules/prefer-promise-reject-errors.md
+++ b/docs/rules/prefer-promise-reject-errors.md
@@ -66,13 +66,16 @@ new Promise(function(resolve, reject) {
 
 Due to the limits of static analysis, this rule cannot guarantee that you will only reject Promises with `Error` objects. While the rule will report cases where it can guarantee that the rejection reason is clearly not an `Error`, it will not report cases where there is uncertainty about whether a given reason is an `Error`. For more information on this caveat, see the [similar limitations](no-throw-literal.md#known-limitations) in the `no-throw-literal` rule.
 
-To avoid conflicts between rules, this rule does not report non-error values used in `throw` statements in async functions, even though these lead to Promise rejections. To lint for these cases, use the [`no-throw-literal`](https://eslint.org/docs/rules/no-throw-literal) rule.
+To avoid conflicts between rules, this rule does not report non-error values used in `throw` statements in async functions, even though these lead to Promise rejections. To lint for these cases, use the [`no-throw-literal`](no-throw-literal.md) rule.
 
 ## When Not To Use It
 
 If you're using custom non-error values as Promise rejection reasons, you can turn off this rule.
 
+## Related Rules
+
+* [`no-throw-literal`](no-throw-literal.md)
+
 ## Further Reading
 
-* [`no-throw-literal`](https://eslint.org/docs/rules/no-throw-literal)
 * [Warning: a promise was rejected with a non-error](http://bluebirdjs.com/docs/warning-explanations.html#warning-a-promise-was-rejected-with-a-non-error)
diff --git a/docs/rules/quotes.md b/docs/rules/quotes.md
index 25a09fd0d..7c113a836 100644
--- a/docs/rules/quotes.md
+++ b/docs/rules/quotes.md
@@ -147,7 +147,7 @@ var single = 'single';
 var single = `single`;
 ```
 
-`{ "allowTemplateLiterals": false }` will not disallow the usage of all template literals. If you want to forbid any instance of template literals, use [no-restricted-syntax](https://eslint.org/docs/rules/no-restricted-syntax) and target the `TemplateLiteral` selector.
+`{ "allowTemplateLiterals": false }` will not disallow the usage of all template literals. If you want to forbid any instance of template literals, use [no-restricted-syntax](no-restricted-syntax.md) and target the `TemplateLiteral` selector.
 
 ## When Not To Use It
 
diff --git a/docs/rules/semi-style.md b/docs/rules/semi-style.md
index 368bb532a..7d08d7665 100644
--- a/docs/rules/semi-style.md
+++ b/docs/rules/semi-style.md
@@ -14,8 +14,8 @@ This rule has an option.
 }
 ```
 
-- `"last"` (Default) enforces that semicolons are at the end of statements.
-- `"first"` enforces that semicolons are at the beginning of statements. Semicolons of `for` loop heads (`for(a;b;c){}`) should be at the end of lines even if you use this option.
+* `"last"` (Default) enforces that semicolons are at the end of statements.
+* `"first"` enforces that semicolons are at the beginning of statements. Semicolons of `for` loop heads (`for(a;b;c){}`) should be at the end of lines even if you use this option.
 
 Examples of **incorrect** code for this rule with `"last"` option:
 
@@ -117,8 +117,8 @@ class C {
 
 If you don't want to notify the location of semicolons, then it's safe to disable this rule.
 
-## Related rules
+## Related Rules
 
-- [no-extra-semi](./no-extra-semi.md)
-- [semi](./semi.md)
-- [semi-spacing](./semi-spacing.md)
+* [no-extra-semi](./no-extra-semi.md)
+* [semi](./semi.md)
+* [semi-spacing](./semi-spacing.md)
diff --git a/docs/rules/semi.md b/docs/rules/semi.md
index cb8e6dd0d..2e82a4509 100644
--- a/docs/rules/semi.md
+++ b/docs/rules/semi.md
@@ -210,13 +210,13 @@ import a from "a"
 
 If you do not want to enforce semicolon usage (or omission) in any particular way, then you can turn this rule off.
 
-## Further Reading
-
-* [An Open Letter to JavaScript Leaders Regarding Semicolons](http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding)
-* [JavaScript Semicolon Insertion](http://inimino.org/~inimino/blog/javascript_semicolons)
-
 ## Related Rules
 
 * [no-extra-semi](no-extra-semi.md)
 * [no-unexpected-multiline](no-unexpected-multiline.md)
 * [semi-spacing](semi-spacing.md)
+
+## Further Reading
+
+* [An Open Letter to JavaScript Leaders Regarding Semicolons](http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding)
+* [JavaScript Semicolon Insertion](http://inimino.org/~inimino/blog/javascript_semicolons)
diff --git a/docs/rules/switch-colon-spacing.md b/docs/rules/switch-colon-spacing.md
index b9872c2ad..094aef22c 100644
--- a/docs/rules/switch-colon-spacing.md
+++ b/docs/rules/switch-colon-spacing.md
@@ -15,10 +15,10 @@ This rule has 2 options that are boolean value.
 }
 ```
 
-- `"after": true` (Default) requires one or more spaces after colons.
-- `"after": false` disallows spaces after colons.
-- `"before": true` requires one or more spaces before colons.
-- `"before": false` (Default) disallows before colons.
+* `"after": true` (Default) requires one or more spaces after colons.
+* `"after": false` disallows spaces after colons.
+* `"before": true` requires one or more spaces before colons.
+* `"before": false` (Default) disallows before colons.
 
 Examples of **incorrect** code for this rule:
 
diff --git a/docs/rules/valid-jsdoc.md b/docs/rules/valid-jsdoc.md
index 2d503828f..5741402b5 100644
--- a/docs/rules/valid-jsdoc.md
+++ b/docs/rules/valid-jsdoc.md
@@ -384,10 +384,10 @@ function add(num1, num2) {
 
 If you aren't using JSDoc, then you can safely turn this rule off.
 
-## Further Reading
-
-* [JSDoc](http://usejsdoc.org)
-
 ## Related Rules
 
 * [require-jsdoc](require-jsdoc.md)
+
+## Further Reading
+
+* [JSDoc](http://usejsdoc.org)
diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md
index 1fcb0dfc1..63b7533f7 100644
--- a/docs/user-guide/README.md
+++ b/docs/user-guide/README.md
@@ -30,10 +30,10 @@ The ESLint team is committed to making upgrading as easy and painless as possibl
 
 If you were using a prior version of ESLint, you can get help with the transition by reading:
 
-- [migrating-to-1.0.0](migrating-to-1.0.0.md)
-- [migrating-to-2.0.0](migrating-to-2.0.0.md)
-- [migrating-to-3.0.0](migrating-to-3.0.0.md)
-- [migrating-to-4.0.0](migrating-to-4.0.0.md)
-- [migrating-to-5.0.0](migrating-to-5.0.0.md)
-- [migrating-to-6.0.0](migrating-to-6.0.0.md)
-- [migrating-to-7.0.0](migrating-to-7.0.0.md)
+* [migrating-to-1.0.0](migrating-to-1.0.0.md)
+* [migrating-to-2.0.0](migrating-to-2.0.0.md)
+* [migrating-to-3.0.0](migrating-to-3.0.0.md)
+* [migrating-to-4.0.0](migrating-to-4.0.0.md)
+* [migrating-to-5.0.0](migrating-to-5.0.0.md)
+* [migrating-to-6.0.0](migrating-to-6.0.0.md)
+* [migrating-to-7.0.0](migrating-to-7.0.0.md)
diff --git a/docs/user-guide/migrating-to-2.0.0.md b/docs/user-guide/migrating-to-2.0.0.md
index c5f50b3a1..4ca97cbe8 100644
--- a/docs/user-guide/migrating-to-2.0.0.md
+++ b/docs/user-guide/migrating-to-2.0.0.md
@@ -307,7 +307,7 @@ The rule `func-style` has a default configuration of `"expression"`, but in ESLi
 
 ESLint 2.0.0 removes these conflicting defaults, and so you may begin seeing linting errors related to these rules.
 
-**To address:**  If you would like to maintain the previous behavior, update your configuration for `no-multiple-empty-lines` by adding `{"max": 2}`, and change `func-style` to `"declaration"`. For example:
+**To address:** If you would like to maintain the previous behavior, update your configuration for `no-multiple-empty-lines` by adding `{"max": 2}`, and change `func-style` to `"declaration"`. For example:
 
 ```json
 {
diff --git a/docs/user-guide/migrating-to-7.0.0.md b/docs/user-guide/migrating-to-7.0.0.md
index 2a640a7ad..8b57df244 100644
--- a/docs/user-guide/migrating-to-7.0.0.md
+++ b/docs/user-guide/migrating-to-7.0.0.md
@@ -8,29 +8,29 @@ The lists below are ordered roughly by the number of users each change is expect
 
 ### Breaking changes for users
 
-- [Node.js 8 is no longer supported](#drop-node-8)
-- [Lint files matched by `overrides[].files` by default](#additional-lint-targets)
-- [The base path of `overrides` and `ignorePatterns` is changed if the config file is given by the `--config`/`--ignore-path` options](#base-path-change)
-- [The place where ESLint loads plugins from is changed](#plugin-loading-change)
-- [Runtime deprecation warnings for `~/.eslintrc.*` config files](#runtime-deprecation-on-personal-config-files)
-- [Default ignore patterns have changed](#default-ignore-patterns)
-- [Description in directive comments](#description-in-directive-comments)
-- [Node.js/CommonJS rules are deprecated](#deprecate-node-rules)
-- [Several rules have been updated to cover more cases](#rules-strict)
-- [`eslint:recommended` has been updated](#eslint-recommended)
+* [Node.js 8 is no longer supported](#drop-node-8)
+* [Lint files matched by `overrides[].files` by default](#additional-lint-targets)
+* [The base path of `overrides` and `ignorePatterns` is changed if the config file is given by the `--config`/`--ignore-path` options](#base-path-change)
+* [The place where ESLint loads plugins from is changed](#plugin-loading-change)
+* [Runtime deprecation warnings for `~/.eslintrc.*` config files](#runtime-deprecation-on-personal-config-files)
+* [Default ignore patterns have changed](#default-ignore-patterns)
+* [Description in directive comments](#description-in-directive-comments)
+* [Node.js/CommonJS rules are deprecated](#deprecate-node-rules)
+* [Several rules have been updated to cover more cases](#rules-strict)
+* [`eslint:recommended` has been updated](#eslint-recommended)
 
 ### Breaking changes for plugin developers
 
-- [Node.js 8 is no longer supported](#drop-node-8)
-- [Lint files matched by `overrides[].files` by default](#additional-lint-targets)
-- [Plugin resolution has been updated](#plugin-loading-change)
-- [Additional validation added to the `RuleTester` class](#rule-tester-strict)
+* [Node.js 8 is no longer supported](#drop-node-8)
+* [Lint files matched by `overrides[].files` by default](#additional-lint-targets)
+* [Plugin resolution has been updated](#plugin-loading-change)
+* [Additional validation added to the `RuleTester` class](#rule-tester-strict)
 
 ### Breaking changes for integration developers
 
-- [Node.js 8 is no longer supported](#drop-node-8)
-- [Plugin resolution has been updated](#plugin-loading-change)
-- [The `CLIEngine` class has been deprecated](#deprecate-cliengine)
+* [Node.js 8 is no longer supported](#drop-node-8)
+* [Plugin resolution has been updated](#plugin-loading-change)
+* [The `CLIEngine` class has been deprecated](#deprecate-cliengine)
 
 ---
 
@@ -38,8 +38,8 @@ The lists below are ordered roughly by the number of users each change is expect
 
 Node.js 8 reached EOL in December 2019, and we are officially dropping support for it in this release. ESLint now supports the following versions of Node.js:
 
-- Node.js 10 (`10.12.0` and above)
-- Node.js 12 and above
+* Node.js 10 (`10.12.0` and above)
+* Node.js 12 and above
 
 **To address:** Make sure you upgrade to at least Node.js `10.12.0` when using ESLint v7.0.0. One important thing to double check is the Node.js version supported by your editor when using ESLint via editor integrations. If you are unable to upgrade, we recommend continuing to use ESLint 6 until you are able to upgrade Node.js.
 
@@ -71,12 +71,12 @@ If you maintain plugins that check files with extensions other than `.js`, this
 
 Up until now, ESLint has resolved the following paths relative to the directory path of the _entry_ configuration file:
 
-- Configuration files (`.eslintrc.*`)
-    - relative paths in the `overrides[].files` setting
-    - relative paths in the `overrides[].excludedFiles` setting
-    - paths which start with `/` in the `ignorePatterns` setting
-- Ignore files (`.eslintignore`)
-    - paths which start with `/`
+* Configuration files (`.eslintrc.*`)
+    * relative paths in the `overrides[].files` setting
+    * relative paths in the `overrides[].excludedFiles` setting
+    * paths which start with `/` in the `ignorePatterns` setting
+* Ignore files (`.eslintignore`)
+    * paths which start with `/`
 
 Starting in ESLint v7.0.0, configuration files and ignore files passed to ESLint using the `--config path/to/a-config` and `--ignore-path path/to/a-ignore` CLI flags, respectively, will resolve from the current working directory rather than the file location. This allows for users to utilize shared plugins without having to install them directly in their project.
 
@@ -113,14 +113,14 @@ Personal config files have been deprecated since [v6.7.0](https://eslint.org/blo
 
 Up until now, ESLint has ignored the following files by default:
 
-- Dotfiles (`.*`)
-- `node_modules` in the current working directory (`/node_modules/*`)
-- `bower_components` in the current working directory (`/bower_components/*`)
+* Dotfiles (`.*`)
+* `node_modules` in the current working directory (`/node_modules/*`)
+* `bower_components` in the current working directory (`/bower_components/*`)
 
 ESLint v7.0.0 ignores `node_modules/*` of subdirectories as well, but no longer ignores `bower_components/*` and `.eslintrc.js`. Therefore, the new default ignore patterns are:
 
-- Dotfiles except `.eslintrc.*` (`.*` but not `.eslintrc.*`)
-- `node_modules` (`/**/node_modules/*`)
+* Dotfiles except `.eslintrc.*` (`.*` but not `.eslintrc.*`)
+* `node_modules` (`/**/node_modules/*`)
 
 **To address:** Modify your `.eslintignore` or the `ignorePatterns` property of your config file if you don't want to lint `bower_components/*` and `.eslintrc.js`.
 
@@ -165,16 +165,16 @@ The ten Node.js/CommonJS rules in core have been deprecated and moved to the [es
 
 Several rules have been enhanced and now report additional errors:
 
-- [accessor-pairs](https://eslint.org/docs/rules/accessor-pairs) rule now recognizes class members by default.
-- [array-callback-return](https://eslint.org/docs/rules/array-callback-return) rule now recognizes `flatMap` method.
-- [computed-property-spacing](https://eslint.org/docs/rules/computed-property-spacing) rule now recognizes class members by default.
-- [func-names](https://eslint.org/docs/rules/func-names) rule now recognizes function declarations in default exports.
-- [no-extra-parens](https://eslint.org/docs/rules/no-extra-parens) rule now recognizes parentheses in assignment targets.
-- [no-dupe-class-members](https://eslint.org/docs/rules/no-dupe-class-members) rule now recognizes computed keys for static class members.
-- [no-magic-numbers](https://eslint.org/docs/rules/no-magic-numbers) rule now recognizes bigint literals.
-- [radix](https://eslint.org/docs/rules/radix) rule now recognizes invalid numbers for the second parameter of `parseInt()`.
-- [use-isnan](https://eslint.org/docs/rules/use-isnan) rule now recognizes class members by default.
-- [yoda](https://eslint.org/docs/rules/yoda) rule now recognizes bigint literals.
+* [accessor-pairs](https://eslint.org/docs/rules/accessor-pairs) rule now recognizes class members by default.
+* [array-callback-return](https://eslint.org/docs/rules/array-callback-return) rule now recognizes `flatMap` method.
+* [computed-property-spacing](https://eslint.org/docs/rules/computed-property-spacing) rule now recognizes class members by default.
+* [func-names](https://eslint.org/docs/rules/func-names) rule now recognizes function declarations in default exports.
+* [no-extra-parens](https://eslint.org/docs/rules/no-extra-parens) rule now recognizes parentheses in assignment targets.
+* [no-dupe-class-members](https://eslint.org/docs/rules/no-dupe-class-members) rule now recognizes computed keys for static class members.
+* [no-magic-numbers](https://eslint.org/docs/rules/no-magic-numbers) rule now recognizes bigint literals.
+* [radix](https://eslint.org/docs/rules/radix) rule now recognizes invalid numbers for the second parameter of `parseInt()`.
+* [use-isnan](https://eslint.org/docs/rules/use-isnan) rule now recognizes class members by default.
+* [yoda](https://eslint.org/docs/rules/yoda) rule now recognizes bigint literals.
 
 **To address:** Fix errors or disable these rules.
 
@@ -184,9 +184,9 @@ Several rules have been enhanced and now report additional errors:
 
 Three new rules have been enabled in the `eslint:recommended` preset.
 
-- [no-dupe-else-if](https://eslint.org/docs/rules/no-dupe-else-if)
-- [no-import-assign](https://eslint.org/docs/rules/no-import-assign)
-- [no-setter-return](https://eslint.org/docs/rules/no-setter-return)
+* [no-dupe-else-if](https://eslint.org/docs/rules/no-dupe-else-if)
+* [no-import-assign](https://eslint.org/docs/rules/no-import-assign)
+* [no-setter-return](https://eslint.org/docs/rules/no-setter-return)
 
 **To address:** Fix errors or disable these rules.
 
@@ -196,9 +196,9 @@ Three new rules have been enabled in the `eslint:recommended` preset.
 
 The `RuleTester` now validates the following:
 
-- It fails test cases if the rule under test uses the non-standard `node.start` or `node.end` properties. Rules should use `node.range` instead.
-- It fails test cases if the rule under test provides an autofix but a test case doesn't have an `output` property. Add an `output` property to test cases to test the rule's autofix functionality.
-- It fails test cases if any unknown properties are found in the objects in the `errors` property.
+* It fails test cases if the rule under test uses the non-standard `node.start` or `node.end` properties. Rules should use `node.range` instead.
+* It fails test cases if the rule under test provides an autofix but a test case doesn't have an `output` property. Add an `output` property to test cases to test the rule's autofix functionality.
+* It fails test cases if any unknown properties are found in the objects in the `errors` property.
 
 **To address:** Modify your rule or test case if existing test cases fail.
 
@@ -226,7 +226,7 @@ The `CLIEngine` class provides a synchronous API that is blocking the implementa
 | `getRules()`                                 | (not implemented yet)              |
 | `resolveFileGlobPatterns()`                  | (removed ※2)                       |
 
-- ※1 The `engine.getFormatter()` method currently returns the object of loaded packages as-is, which made it difficult to add new features to formatters for backward compatibility reasons. The new `eslint.loadFormatter()` method returns an adapter object that wraps the object of loaded packages, to ease the process of adding new features. Additionally, the adapter object has access to the `ESLint` instance to calculate default data (using loaded plugin rules to make `rulesMeta`, for example). As a result, the `ESLint` class only implements an instance version of the `loadFormatter()` method.
-- ※2 Since ESLint 6, ESLint uses different logic from the `resolveFileGlobPatterns()` method to iterate files, making this method obsolete.
+* ※1 The `engine.getFormatter()` method currently returns the object of loaded packages as-is, which made it difficult to add new features to formatters for backward compatibility reasons. The new `eslint.loadFormatter()` method returns an adapter object that wraps the object of loaded packages, to ease the process of adding new features. Additionally, the adapter object has access to the `ESLint` instance to calculate default data (using loaded plugin rules to make `rulesMeta`, for example). As a result, the `ESLint` class only implements an instance version of the `loadFormatter()` method.
+* ※2 Since ESLint 6, ESLint uses different logic from the `resolveFileGlobPatterns()` method to iterate files, making this method obsolete.
 
 **Related issue(s):** [RFC40](https://github.com/eslint/rfcs/blob/master/designs/2019-move-to-async-api/README.md), [#12939](https://github.com/eslint/eslint/pull/12939)
diff --git a/docs/user-guide/migrating-to-8.0.0.md b/docs/user-guide/migrating-to-8.0.0.md
index 444ac124c..86c2bc757 100644
--- a/docs/user-guide/migrating-to-8.0.0.md
+++ b/docs/user-guide/migrating-to-8.0.0.md
@@ -8,26 +8,26 @@ The lists below are ordered roughly by the number of users each change is expect
 
 ### Breaking changes for users
 
-- [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
-- [Removed `codeframe` and `table` formatters](#removed-formatters)
-- [`comma-dangle` rule schema is stricter](#comma-dangle)
-- [Unused disable directives are now fixable](#directives)
-- [`eslint:recommended` has been updated](#eslint-recommended)
+* [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
+* [Removed `codeframe` and `table` formatters](#removed-formatters)
+* [`comma-dangle` rule schema is stricter](#comma-dangle)
+* [Unused disable directives are now fixable](#directives)
+* [`eslint:recommended` has been updated](#eslint-recommended)
 
 ### Breaking changes for plugin developers
 
-- [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
-- [Rules require `meta.hasSuggestions` to provide suggestions](#suggestions)
-- [Rules require `meta.fixable` to provide fixes](#fixes)
-- [`SourceCode#getComments()` fails in `RuleTester`](#get-comments)
-- [Changes to shorthand property AST format](#ast-format)
+* [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
+* [Rules require `meta.hasSuggestions` to provide suggestions](#suggestions)
+* [Rules require `meta.fixable` to provide fixes](#fixes)
+* [`SourceCode#getComments()` fails in `RuleTester`](#get-comments)
+* [Changes to shorthand property AST format](#ast-format)
 
 ### Breaking changes for integration developers
 
-- [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
-- [The `CLIEngine` class has been removed](#remove-cliengine)
-- [The `linter` object has been removed](#remove-linter)
-- [The `/lib` entrypoint has been removed](#remove-lib)
+* [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
+* [The `CLIEngine` class has been removed](#remove-cliengine)
+* [The `linter` object has been removed](#remove-linter)
+* [The `/lib` entrypoint has been removed](#remove-lib)
 
 ---
 
@@ -35,9 +35,9 @@ The lists below are ordered roughly by the number of users each change is expect
 
 Node.js 10, 13, 15 all reached end of life either in 2020 or early 2021. ESLint is officially dropping support for these versions of Node.js starting with ESLint v8.0.0. ESLint now supports the following versions of Node.js:
 
-- Node.js 12.22 and above
-- Node.js 14 and above
-- Node.js 16 and above
+* Node.js 12.22 and above
+* Node.js 14 and above
+* Node.js 16 and above
 
 **To address:** Make sure you upgrade to at least Node.js `12.22.0` when using ESLint v8.0.0. One important thing to double check is the Node.js version supported by your editor when using ESLint via editor integrations. If you are unable to upgrade, we recommend continuing to use ESLint 7 until you are able to upgrade Node.js.
 
@@ -95,10 +95,10 @@ In ESLint v7.0.0, using both `--report-unused-disable-directives` and `--fix` on
 
 Four new rules have been enabled in the `eslint:recommended` preset.
 
-- [`no-loss-of-precision`](https://eslint.org/docs/rules/no-loss-of-precision)
-- [`no-nonoctal-decimal-escape`](https://eslint.org/docs/rules/no-nonoctal-decimal-escape)
-- [`no-unsafe-optional-chaining`](https://eslint.org/docs/rules/no-unsafe-optional-chaining)
-- [`no-useless-backreference`](https://eslint.org/docs/rules/no-useless-backreference)
+* [`no-loss-of-precision`](https://eslint.org/docs/rules/no-loss-of-precision)
+* [`no-nonoctal-decimal-escape`](https://eslint.org/docs/rules/no-nonoctal-decimal-escape)
+* [`no-unsafe-optional-chaining`](https://eslint.org/docs/rules/no-unsafe-optional-chaining)
+* [`no-useless-backreference`](https://eslint.org/docs/rules/no-useless-backreference)
 
 **To address:** Fix errors or disable these rules.
 
@@ -237,9 +237,9 @@ The `CLIEngine` class has been removed and replaced by the [`ESLint` class](http
 | `getRules()`                                 | (removed ※2)                      |
 | `resolveFileGlobPatterns()`                  | (removed ※3)                      |
 
-- ※1 The `engine.getFormatter()` method currently returns the object of loaded packages as-is, which made it difficult to add new features to formatters for backward compatibility reasons. The new `eslint.loadFormatter()` method returns an adapter object that wraps the object of loaded packages, to ease the process of adding new features. Additionally, the adapter object has access to the `ESLint` instance to calculate default data (using loaded plugin rules to make `rulesMeta`, for example). As a result, the `ESLint` class only implements an instance version of the `loadFormatter()` method.
-- ※2 The `CLIEngine#getRules()` method had side effects and so was removed. If you were using `CLIEngine#getRules()` to retrieve meta information about rules based on linting results, use `ESLint#getRulesMetaForResults()` instead. If you were using `CLIEngine#getRules()` to retrieve all built-in rules, import `builtinRules` from `eslint/use-at-your-own-risk` for an unsupported API that allows access to internal rules.
-- ※3 Since ESLint v6.0.0, ESLint uses different logic from the `resolveFileGlobPatterns()` method to iterate files, making this method obsolete.
+* ※1 The `engine.getFormatter()` method currently returns the object of loaded packages as-is, which made it difficult to add new features to formatters for backward compatibility reasons. The new `eslint.loadFormatter()` method returns an adapter object that wraps the object of loaded packages, to ease the process of adding new features. Additionally, the adapter object has access to the `ESLint` instance to calculate default data (using loaded plugin rules to make `rulesMeta`, for example). As a result, the `ESLint` class only implements an instance version of the `loadFormatter()` method.
+* ※2 The `CLIEngine#getRules()` method had side effects and so was removed. If you were using `CLIEngine#getRules()` to retrieve meta information about rules based on linting results, use `ESLint#getRulesMetaForResults()` instead. If you were using `CLIEngine#getRules()` to retrieve all built-in rules, import `builtinRules` from `eslint/use-at-your-own-risk` for an unsupported API that allows access to internal rules.
+* ※3 Since ESLint v6.0.0, ESLint uses different logic from the `resolveFileGlobPatterns()` method to iterate files, making this method obsolete.
 
 **Related issue(s):** [RFC80](https://github.com/eslint/rfcs/tree/main/designs/2021-package-exports), [#14716](https://github.com/eslint/eslint/pull/14716), [#13654](https://github.com/eslint/eslint/issues/13654)
 
diff --git a/lib/linter/linter.js b/lib/linter/linter.js
index f897b8ddb..ae027aa2e 100644
--- a/lib/linter/linter.js
+++ b/lib/linter/linter.js
@@ -326,14 +326,13 @@ function stripDirectiveComment(value) {
  * Parses comments in file to extract file-specific config of rules, globals
  * and environments and merges them with global config; also code blocks
  * where reporting is disabled or enabled and merges them with reporting config.
- * @param {string} filename The file being checked.
  * @param {ASTNode} ast The top node of the AST.
  * @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
  * @param {string|null} warnInlineConfig If a string then it should warn directive comments as disabled. The string value is the config name what the setting came from.
  * @returns {{configuredRules: Object, enabledGlobals: {value:string,comment:Token}[], exportedVariables: Object, problems: Problem[], disableDirectives: DisableDirective[]}}
  * A collection of the directive comments that were found, along with any problems that occurred when parsing
  */
-function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
+function getDirectiveComments(ast, ruleMapper, warnInlineConfig) {
     const configuredRules = {};
     const enabledGlobals = Object.create(null);
     const exportedVariables = {};
@@ -1332,7 +1331,7 @@ class Linter {
 
         const sourceCode = slots.lastSourceCode;
         const commentDirectives = options.allowInlineConfig
-            ? getDirectiveComments(options.filename, sourceCode.ast, ruleId => getRule(slots, ruleId), options.warnInlineConfig)
+            ? getDirectiveComments(sourceCode.ast, ruleId => getRule(slots, ruleId), options.warnInlineConfig)
             : { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
 
         // augment global scope with declared global variables
@@ -1593,7 +1592,6 @@ class Linter {
         const sourceCode = slots.lastSourceCode;
         const commentDirectives = options.allowInlineConfig
             ? getDirectiveComments(
-                options.filename,
                 sourceCode.ast,
                 ruleId => getRuleFromConfig(ruleId, config),
                 options.warnInlineConfig
diff --git a/lib/rules/id-match.js b/lib/rules/id-match.js
index 15908da8c..977e66a26 100644
--- a/lib/rules/id-match.js
+++ b/lib/rules/id-match.js
@@ -211,6 +211,17 @@ module.exports = {
                         }
                     }
 
+                // For https://github.com/eslint/eslint/issues/15123
+                } else if (
+                    parent.type === "Property" &&
+                    parent.parent.type === "ObjectExpression" &&
+                    parent.key === node &&
+                    !parent.computed
+                ) {
+                    if (checkProperties && isInvalid(name)) {
+                        report(node);
+                    }
+
                 /*
                  * Properties have their own rules, and
                  * AssignmentPattern nodes can be treated like Properties:
diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js
index afd6a0139..158f84b94 100644
--- a/lib/rules/prefer-regex-literals.js
+++ b/lib/rules/prefer-regex-literals.js
@@ -11,11 +11,15 @@
 
 const astUtils = require("./utils/ast-utils");
 const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("eslint-utils");
+const { RegExpValidator, visitRegExpAST, RegExpParser } = require("regexpp");
+const { canTokensBeAdjacent } = require("./utils/ast-utils");
 
 //------------------------------------------------------------------------------
 // Helpers
 //------------------------------------------------------------------------------
 
+const REGEXPP_LATEST_ECMA_VERSION = 2022;
+
 /**
  * Determines whether the given node is a string literal.
  * @param {ASTNode} node Node to check.
@@ -43,6 +47,71 @@ function isStaticTemplateLiteral(node) {
     return node.type === "TemplateLiteral" && node.expressions.length === 0;
 }
 
+const validPrecedingTokens = [
+    "(",
+    ";",
+    "[",
+    ",",
+    "=",
+    "+",
+    "*",
+    "-",
+    "?",
+    "~",
+    "%",
+    "**",
+    "!",
+    "typeof",
+    "instanceof",
+    "&&",
+    "||",
+    "??",
+    "return",
+    "...",
+    "delete",
+    "void",
+    "in",
+    "<",
+    ">",
+    "<=",
+    ">=",
+    "==",
+    "===",
+    "!=",
+    "!==",
+    "<<",
+    ">>",
+    ">>>",
+    "&",
+    "|",
+    "^",
+    ":",
+    "{",
+    "=>",
+    "*=",
+    "<<=",
+    ">>=",
+    ">>>=",
+    "^=",
+    "|=",
+    "&=",
+    "??=",
+    "||=",
+    "&&=",
+    "**=",
+    "+=",
+    "-=",
+    "/=",
+    "%=",
+    "/",
+    "do",
+    "break",
+    "continue",
+    "debugger",
+    "case",
+    "throw"
+];
+
 
 //------------------------------------------------------------------------------
 // Rule Definition
@@ -59,6 +128,8 @@ module.exports = {
             url: "https://eslint.org/docs/rules/prefer-regex-literals"
         },
 
+        hasSuggestions: true,
+
         schema: [
             {
                 type: "object",
@@ -74,6 +145,7 @@ module.exports = {
 
         messages: {
             unexpectedRegExp: "Use a regular expression literal instead of the 'RegExp' constructor.",
+            replaceWithLiteral: "Replace with an equivalent regular expression literal.",
             unexpectedRedundantRegExp: "Regular expression literal is unnecessarily wrapped within a 'RegExp' constructor.",
             unexpectedRedundantRegExpWithFlags: "Use regular expression literal with flags instead of the 'RegExp' constructor."
         }
@@ -81,6 +153,7 @@ module.exports = {
 
     create(context) {
         const [{ disallowRedundantWrapping = false } = {}] = context.options;
+        const sourceCode = context.getSourceCode();
 
         /**
          * Determines whether the given identifier node is a reference to a global variable.
@@ -107,6 +180,27 @@ module.exports = {
                 isStaticTemplateLiteral(node.quasi);
         }
 
+        /**
+         * Gets the value of a string
+         * @param {ASTNode} node The node to get the string of.
+         * @returns {string|null} The value of the node.
+         */
+        function getStringValue(node) {
+            if (isStringLiteral(node)) {
+                return node.value;
+            }
+
+            if (isStaticTemplateLiteral(node)) {
+                return node.quasis[0].value.cooked;
+            }
+
+            if (isStringRawTaggedStaticTemplateLiteral(node)) {
+                return node.quasi.quasis[0].value.raw;
+            }
+
+            return null;
+        }
+
         /**
          * Determines whether the given node is considered to be a static string by the logic of this rule.
          * @param {ASTNode} node Node to check.
@@ -152,6 +246,53 @@ module.exports = {
             return false;
         }
 
+        /**
+         * Returns a ecmaVersion compatible for regexpp.
+         * @param {any} ecmaVersion The ecmaVersion to convert.
+         * @returns {import("regexpp/ecma-versions").EcmaVersion} The resulting ecmaVersion compatible for regexpp.
+         */
+        function getRegexppEcmaVersion(ecmaVersion) {
+            if (typeof ecmaVersion !== "number" || ecmaVersion <= 5) {
+                return 5;
+            }
+            return Math.min(ecmaVersion + 2009, REGEXPP_LATEST_ECMA_VERSION);
+        }
+
+        /**
+         * Makes a character escaped or else returns null.
+         * @param {string} character The character to escape.
+         * @returns {string} The resulting escaped character.
+         */
+        function resolveEscapes(character) {
+            switch (character) {
+                case "\n":
+                case "\\\n":
+                    return "\\n";
+
+                case "\r":
+                case "\\\r":
+                    return "\\r";
+
+                case "\t":
+                case "\\\t":
+                    return "\\t";
+
+                case "\v":
+                case "\\\v":
+                    return "\\v";
+
+                case "\f":
+                case "\\\f":
+                    return "\\f";
+
+                case "/":
+                    return "\\/";
+
+                default:
+                    return null;
+            }
+        }
+
         return {
             Program() {
                 const scope = context.getScope();
@@ -171,7 +312,82 @@ module.exports = {
                             context.report({ node, messageId: "unexpectedRedundantRegExp" });
                         }
                     } else if (hasOnlyStaticStringArguments(node)) {
-                        context.report({ node, messageId: "unexpectedRegExp" });
+                        let regexContent = getStringValue(node.arguments[0]);
+                        let noFix = false;
+                        let flags;
+
+                        if (node.arguments[1]) {
+                            flags = getStringValue(node.arguments[1]);
+                        }
+
+                        const regexppEcmaVersion = getRegexppEcmaVersion(context.parserOptions.ecmaVersion);
+                        const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: regexppEcmaVersion });
+
+                        try {
+                            RegExpValidatorInstance.validatePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false);
+                            if (flags) {
+                                RegExpValidatorInstance.validateFlags(flags);
+                            }
+                        } catch {
+                            noFix = true;
+                        }
+
+                        const tokenBefore = sourceCode.getTokenBefore(node);
+
+                        if (tokenBefore && !validPrecedingTokens.includes(tokenBefore.value)) {
+                            noFix = true;
+                        }
+
+                        if (!/^[-a-zA-Z0-9\\[\](){} \t\r\n\v\f!@#$%^&*+^_=/~`.><?,'"|:;]*$/u.test(regexContent)) {
+                            noFix = true;
+                        }
+
+                        if (sourceCode.getCommentsInside(node).length > 0) {
+                            noFix = true;
+                        }
+
+                        if (regexContent && !noFix) {
+                            let charIncrease = 0;
+
+                            const ast = new RegExpParser({ ecmaVersion: regexppEcmaVersion }).parsePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false);
+
+                            visitRegExpAST(ast, {
+                                onCharacterEnter(characterNode) {
+                                    const escaped = resolveEscapes(characterNode.raw);
+
+                                    if (escaped) {
+                                        regexContent =
+                                            regexContent.slice(0, characterNode.start + charIncrease) +
+                                            escaped +
+                                            regexContent.slice(characterNode.end + charIncrease);
+
+                                        if (characterNode.raw.length === 1) {
+                                            charIncrease += 1;
+                                        }
+                                    }
+                                }
+                            });
+                        }
+
+                        const newRegExpValue = `/${regexContent || "(?:)"}/${flags || ""}`;
+
+                        context.report({
+                            node,
+                            messageId: "unexpectedRegExp",
+                            suggest: noFix ? [] : [{
+                                messageId: "replaceWithLiteral",
+                                fix(fixer) {
+                                    const tokenAfter = sourceCode.getTokenAfter(node);
+
+                                    return fixer.replaceText(
+                                        node,
+                                        (tokenBefore && !canTokensBeAdjacent(tokenBefore, newRegExpValue) && tokenBefore.range[1] === node.range[0] ? " " : "") +
+                                            newRegExpValue +
+                                            (tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && node.range[1] === tokenAfter.range[0] ? " " : "")
+                                    );
+                                }
+                            }]
+                        });
                     }
                 }
             }
diff --git a/lib/rules/prefer-template.js b/lib/rules/prefer-template.js
index 953155d8f..e61eac1d6 100644
--- a/lib/rules/prefer-template.js
+++ b/lib/rules/prefer-template.js
@@ -188,7 +188,7 @@ module.exports = {
                 return sourceCode.getText(currentNode);
             }
 
-            if (isConcatenation(currentNode) && hasStringLiteral(currentNode) && hasNonStringLiteral(currentNode)) {
+            if (isConcatenation(currentNode) && hasStringLiteral(currentNode)) {
                 const plusSign = sourceCode.getFirstTokenBetween(currentNode.left, currentNode.right, token => token.value === "+");
                 const textBeforePlus = getTextBetween(currentNode.left, plusSign);
                 const textAfterPlus = getTextBetween(plusSign, currentNode.right);
diff --git a/package.json b/package.json
index 43a7138fc..974fc05cd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "8.4.1",
+  "version": "8.5.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
@@ -118,6 +118,7 @@
     "load-perf": "^0.2.0",
     "markdownlint": "^0.24.0",
     "markdownlint-cli": "^0.30.0",
+    "marked": "^4.0.8",
     "memfs": "^3.0.1",
     "mocha": "^8.3.2",
     "mocha-junit-reporter": "^2.0.0",


Test patch:
diff --git a/tests/lib/linter/linter.js b/tests/lib/linter/linter.js
index 334346146..eb25e677a 100644
--- a/tests/lib/linter/linter.js
+++ b/tests/lib/linter/linter.js
@@ -7352,6 +7352,123 @@ describe("Linter with FlatConfigArray", () => {
                     assert.strictEqual(messages.length, 0);
                 });
 
+                it("should not allow the use of reserved words as variable names in ES3", () => {
+                    const code = "var char;";
+                    const messages = linter.verify(code, {
+                        languageOptions: {
+                            ecmaVersion: 3,
+                            sourceType: "script"
+                        }
+                    }, filename);
+
+                    assert.strictEqual(messages.length, 1);
+                    assert.strictEqual(messages[0].severity, 2);
+                    assert.isTrue(messages[0].fatal);
+                    assert.match(messages[0].message, /^Parsing error:.*'char'/u);
+                });
+
+                it("should not allow the use of reserved words as property names in member expressions in ES3", () => {
+                    const code = "obj.char;";
+                    const messages = linter.verify(code, {
+                        languageOptions: {
+                            ecmaVersion: 3,
+                            sourceType: "script"
+                        }
+                    }, filename);
+
+                    assert.strictEqual(messages.length, 1);
+                    assert.strictEqual(messages[0].severity, 2);
+                    assert.isTrue(messages[0].fatal);
+                    assert.match(messages[0].message, /^Parsing error:.*'char'/u);
+                });
+
+                it("should not allow the use of reserved words as property names in object literals in ES3", () => {
+                    const code = "var obj = { char: 1 };";
+                    const messages = linter.verify(code, {
+                        languageOptions: {
+                            ecmaVersion: 3,
+                            sourceType: "script"
+                        }
+                    }, filename);
+
+                    assert.strictEqual(messages.length, 1);
+                    assert.strictEqual(messages[0].severity, 2);
+                    assert.isTrue(messages[0].fatal);
+                    assert.match(messages[0].message, /^Parsing error:.*'char'/u);
+                });
+
+                it("should allow the use of reserved words as variable and property names in ES3 when allowReserved is true", () => {
+                    const code = "var char; obj.char; var obj = { char: 1 };";
+                    const messages = linter.verify(code, {
+                        languageOptions: {
+                            ecmaVersion: 3,
+                            sourceType: "script",
+                            parserOptions: {
+                                allowReserved: true
+                            }
+                        }
+                    }, filename);
+
+                    assert.strictEqual(messages.length, 0);
+                });
+
+                it("should not allow the use of reserved words as variable names in ES > 3", () => {
+                    const ecmaVersions = [void 0, ...espree.supportedEcmaVersions.filter(ecmaVersion => ecmaVersion > 3)];
+
+                    ecmaVersions.forEach(ecmaVersion => {
+                        const code = "var enum;";
+                        const messages = linter.verify(code, {
+                            languageOptions: {
+                                ...ecmaVersion ? { ecmaVersion } : {},
+                                sourceType: "script"
+                            }
+                        }, filename);
+
+                        assert.strictEqual(messages.length, 1);
+                        assert.strictEqual(messages[0].severity, 2);
+                        assert.isTrue(messages[0].fatal);
+                        assert.match(messages[0].message, /^Parsing error:.*'enum'/u);
+                    });
+                });
+
+                it("should allow the use of reserved words as property names in ES > 3", () => {
+                    const ecmaVersions = [void 0, ...espree.supportedEcmaVersions.filter(ecmaVersion => ecmaVersion > 3)];
+
+                    ecmaVersions.forEach(ecmaVersion => {
+                        const code = "obj.enum; obj.function; var obj = { enum: 1, function: 2 };";
+                        const messages = linter.verify(code, {
+                            languageOptions: {
+                                ...ecmaVersion ? { ecmaVersion } : {},
+                                sourceType: "script"
+                            }
+                        }, filename);
+
+                        assert.strictEqual(messages.length, 0);
+                    });
+                });
+
+                it("should not allow `allowReserved: true` in ES > 3", () => {
+                    const ecmaVersions = [void 0, ...espree.supportedEcmaVersions.filter(ecmaVersion => ecmaVersion > 3)];
+
+                    ecmaVersions.forEach(ecmaVersion => {
+                        const code = "";
+                        const messages = linter.verify(code, {
+                            languageOptions: {
+                                ...ecmaVersion ? { ecmaVersion } : {},
+                                sourceType: "script",
+                                parserOptions: {
+                                    allowReserved: true
+                                }
+                            }
+                        }, filename);
+
+                        assert.strictEqual(messages.length, 1);
+                        assert.strictEqual(messages[0].severity, 2);
+                        assert.isTrue(messages[0].fatal);
+                        assert.match(messages[0].message, /^Parsing error:.*allowReserved/u);
+                    });
+                });
+
             });
 
         });
diff --git a/tests/lib/rules/id-match.js b/tests/lib/rules/id-match.js
index 2f48a4b2d..de66d8b8d 100644
--- a/tests/lib/rules/id-match.js
+++ b/tests/lib/rules/id-match.js
@@ -197,6 +197,58 @@ ruleTester.run("id-match", rule, {
             }],
             parserOptions: { ecmaVersion: 2022 }
         },
+        {
+            code: `
+            const foo = {
+                foo_one: 1,
+                bar_one: 2,
+                fooBar: 3
+            };
+            `,
+            options: ["^[^_]+$", {
+                properties: false
+            }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: `
+            const foo = {
+                foo_one: 1,
+                bar_one: 2,
+                fooBar: 3
+            };
+            `,
+            options: ["^[^_]+$", {
+                onlyDeclarations: true
+            }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: `
+            const foo = {
+                foo_one: 1,
+                bar_one: 2,
+                fooBar: 3
+            };
+            `,
+            options: ["^[^_]+$", {
+                properties: false,
+                onlyDeclarations: false
+            }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: `
+            const foo = {
+                [a]: 1,
+            };
+            `,
+            options: ["^[^a]", {
+                properties: true,
+                onlyDeclarations: true
+            }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
 
         // Class Methods
         {
@@ -774,7 +826,74 @@ ruleTester.run("id-match", rule, {
                     type: "PrivateIdentifier"
                 }
             ]
-        }
+        },
 
+        // https://github.com/eslint/eslint/issues/15123
+        {
+            code: `
+            const foo = {
+                foo_one: 1,
+                bar_one: 2,
+                fooBar: 3
+            };
+            `,
+            options: ["^[^_]+$", {
+                properties: true,
+                onlyDeclarations: true
+            }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    message: "Identifier 'foo_one' does not match the pattern '^[^_]+$'.",
+                    type: "Identifier"
+                },
+                {
+                    message: "Identifier 'bar_one' does not match the pattern '^[^_]+$'.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: `
+            const foo = {
+                foo_one: 1,
+                bar_one: 2,
+                fooBar: 3
+            };
+            `,
+            options: ["^[^_]+$", {
+                properties: true,
+                onlyDeclarations: false
+            }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    message: "Identifier 'foo_one' does not match the pattern '^[^_]+$'.",
+                    type: "Identifier"
+                },
+                {
+                    message: "Identifier 'bar_one' does not match the pattern '^[^_]+$'.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: `
+            const foo = {
+                [a]: 1,
+            };
+            `,
+            options: ["^[^a]", {
+                properties: true,
+                onlyDeclarations: false
+            }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    message: "Identifier 'a' does not match the pattern '^[^a]'.",
+                    type: "Identifier"
+                }
+            ]
+        }
     ]
 });
diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js
index ccd88ae74..f2982cbfb 100644
--- a/tests/lib/rules/prefer-regex-literals.js
+++ b/tests/lib/rules/prefer-regex-literals.js
@@ -26,6 +26,8 @@ ruleTester.run("prefer-regex-literals", rule, {
 
         // considered as dynamic
         "new RegExp(pattern)",
+        "new RegExp('\\\\p{Emoji_Presentation}\\\\P{Script_Extensions=Latin}' + '', `ug`)",
+        "new RegExp('\\\\cA' + '')",
         "RegExp(pattern, 'g')",
         "new RegExp(f('a'))",
         "RegExp(prefix + 'a')",
@@ -33,6 +35,7 @@ ruleTester.run("prefer-regex-literals", rule, {
         "RegExp(`a` + suffix);",
         "new RegExp(String.raw`a` + suffix);",
         "RegExp('a', flags)",
+        "const flags = 'gu';RegExp('a', flags)",
         "RegExp('a', 'g' + flags)",
         "new RegExp(String.raw`a`, flags);",
         "RegExp(`${prefix}abc`)",
@@ -42,8 +45,10 @@ ruleTester.run("prefer-regex-literals", rule, {
         "new RegExp(String.raw`a${''}c`);",
         "new RegExp('a' + 'b')",
         "RegExp(1)",
-        "new RegExp(/a/, 'u');",
-        "new RegExp(/a/);",
+        "new RegExp('(\\\\p{Emoji_Presentation})\\\\1' + '', `ug`)",
+        "RegExp(String.raw`\\78\\126` + '\\\\5934', '' + `g` + '')",
+        "func(new RegExp(String.raw`a${''}c\\d`, 'u'),new RegExp(String.raw`a${''}c\\d`, 'u'))",
+        "new RegExp('\\\\[' + \"b\\\\]\")",
         {
             code: "new RegExp(/a/, flags);",
             options: [{ disallowRedundantWrapping: true }]
@@ -134,124 +139,2338 @@ ruleTester.run("prefer-regex-literals", rule, {
     invalid: [
         {
             code: "new RegExp('abc');",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp('abc');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp('abc', 'g');",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp('abc', 'g');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(`abc`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(`abc`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(`abc`, `g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(`abc`, `g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String.raw`abc`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String.raw`abc\nabc`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc\\nabc/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String.raw`\tabc\nabc`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\tabc\\nabc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(String.raw`abc`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String.raw`abc`, String.raw`g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(String.raw`abc`, String.raw`g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String['raw']`a`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp('');",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/(?:)/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp('', '');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/(?:)/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String.raw``);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/(?:)/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp('a', `g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(`a`, 'g');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(String.raw`a`, 'g');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String.raw`\\d`, `g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\d/g;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String.raw`\\\\d`, `g`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\d/g;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String['raw']`\\\\d`, `g`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\d/g;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String[\"raw\"]`\\\\d`, `g`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\d/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp('a', String.raw`g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new globalThis.RegExp('a');",
-            env: { es2020: true },
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            env: {
+                es2020: true
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "globalThis.RegExp('a');",
-            env: { es2020: true },
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            env: {
+                es2020: true
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
         },
-
         {
             code: "new RegExp(/a/);",
-            options: [{ disallowRedundantWrapping: true }],
-            errors: [{ messageId: "unexpectedRedundantRegExp", type: "NewExpression", line: 1, column: 1 }]
+            options: [
+                {
+                    disallowRedundantWrapping: true
+                }
+            ],
+            errors: [
+                {
+                    messageId: "unexpectedRedundantRegExp",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 1
+                }
+            ]
         },
         {
             code: "new RegExp(/a/, 'u');",
-            options: [{ disallowRedundantWrapping: true }],
-            errors: [{ messageId: "unexpectedRedundantRegExpWithFlags", type: "NewExpression", line: 1, column: 1 }]
+            options: [
+                {
+                    disallowRedundantWrapping: true
+                }
+            ],
+            errors: [
+                {
+                    messageId: "unexpectedRedundantRegExpWithFlags",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 1
+                }
+            ]
         },
         {
             code: "new RegExp(/a/, `u`);",
-            options: [{ disallowRedundantWrapping: true }],
-            errors: [{ messageId: "unexpectedRedundantRegExpWithFlags", type: "NewExpression", line: 1, column: 1 }]
+            options: [
+                {
+                    disallowRedundantWrapping: true
+                }
+            ],
+            errors: [
+                {
+                    messageId: "unexpectedRedundantRegExpWithFlags",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 1
+                }
+            ]
+        },
+        {
+            code: "new RegExp(/a/, String.raw`u`);",
+            options: [
+                {
+                    disallowRedundantWrapping: true
+                }
+            ],
+            errors: [
+                {
+                    messageId: "unexpectedRedundantRegExpWithFlags",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 1
+                }
+            ]
         },
         {
             code: "new RegExp('a');",
-            options: [{ disallowRedundantWrapping: true }],
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression", line: 1, column: 1 }]
+            options: [
+                {
+                    disallowRedundantWrapping: true
+                }
+            ],
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 1,
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
         },
-
-        // Optional chaining
         {
             code: "new RegExp((String?.raw)`a`);",
-            errors: [{ messageId: "unexpectedRegExp" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('+');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "new RegExp('*');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('+');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('*');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "new RegExp('+', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "new RegExp('*', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('+', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('*', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('abc', 'u');",
+            parserOptions: {
+                ecmaVersion: 3
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "new RegExp('abc', 'd');",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('abc', 'd');",
+            parserOptions: {
+                ecmaVersion: 2022
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/d;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\\\\\', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\n', '');",
+            parserOptions: {
+                ecmaVersion: 2022
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\n\\n', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n\\n/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\t', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\t/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\t\\t', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\t\\t/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\r\\n', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\r\\n/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\u1234', 'g')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\u{1234}', 'g')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\u{11111}', 'g')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\v', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\v/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\v\\v', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\v\\v/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\f', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\f/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\f\\f', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\f\\f/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\b', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\b/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\b\\\\b', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\b\\b/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\\\B\\\\b', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\B\\b/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\w', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\w/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new globalThis.RegExp('\\\\W', '');",
+            globals: {
+                globalThis: "readonly"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\W/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\s', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\s/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\\\S', '')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\S/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "globalThis.RegExp('\\\\d', '');",
+            globals: {
+                globalThis: "readonly"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\d/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "globalThis.RegExp('\\\\D', '')",
+            globals: {
+                globalThis: "readonly"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\D/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "globalThis.RegExp('\\\\\\\\\\\\D', '')",
+            globals: {
+                globalThis: "readonly"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\\\D/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\\\D\\\\D', '')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\D\\D/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new globalThis.RegExp('\\\\0\\\\0', '');",
+            globals: {
+                globalThis: "writable"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\0\\0/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\\\0\\\\0', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\0\\0/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\0\\0', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\0\\\\0\\\\0', '')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\0\\0\\0/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\78\\\\126\\\\5934', '')",
+            parserOptions: {
+                ecmaVersion: 2022
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\78\\126\\5934/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new window['RegExp']('\\\\x56\\\\x78\\\\x45', '');",
+            env: {
+                browser: true
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\x56\\x78\\x45/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "a in(RegExp('abc'))",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "a in(/abc/)"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "x = y\n            RegExp(\"foo\").test(x) ? bar() : baz()",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "func(new RegExp(String.raw`\\w{1, 2`, 'u'),new RegExp(String.raw`\\w{1, 2`, 'u'))",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "x = y;\n            RegExp(\"foo\").test(x) ? bar() : baz()",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "x = y;\n            /foo/.test(x) ? bar() : baz()"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "typeof RegExp(\"foo\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "typeof /foo/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/foo/ instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "RegExp(\"foo\") instanceof /blahblah/g ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof /(\\p{Emoji_Presentation})\\1/ug : false"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "[   new RegExp(`someregular`)]",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "[   /someregular/]"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "const totallyValidatesEmails = new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")\n            if (typeof totallyValidatesEmails === 'object') {\n                runSomethingThatExists(Regexp('stuff'))\n            }",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "const totallyValidatesEmails = /\\S+@(\\S+\\.)+\\S+/\n            if (typeof totallyValidatesEmails === 'object') {\n                runSomethingThatExists(Regexp('stuff'))\n            }"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "!/^Hey, /u && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "!new RegExp('^Hey, ', 'u') && /jk$/ && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~/^Sup, / || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || /hi/ + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + /person/ === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -/hi again/ ? 5 * new RegExp('abc') : 'notregbutstring'"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * /abc/ : 'notregbutstring'"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "#!/usr/bin/sh\n            RegExp(\"foo\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "#!/usr/bin/sh\n            /foo/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "async function abc(){await new RegExp(\"foo\")}",
+            parserOptions: {
+                ecmaVersion: 8,
+                sourceType: "module"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "function* abc(){yield new RegExp(\"foo\")}",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "function* abc(){yield* new RegExp(\"foo\")}",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "function* abc(){yield* /foo/}"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "console.log({ ...new RegExp('a') })",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "console.log({ .../a/ })"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "delete RegExp('a');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "delete /a/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "void RegExp('a');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "void /a/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**RegExp('a')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\S+@(\\S+\\.)+\\S+/**RegExp('a')"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**/a/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%RegExp('a')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\S+@(\\S+\\.)+\\S+/%RegExp('a')"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%/a/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "a in RegExp('abc')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "a in /abc/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ == new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ == /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ === new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ === /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ != new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ != /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ !== new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ !== /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ > new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ > /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ < new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ < /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ >= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ >= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ <= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ <= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ << new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ << /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ >> new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ >> /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ >>> new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ >>> /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ ^ new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ ^ /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ & new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ & /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ | new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ | /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            null ?? new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            null ?? /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc *= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc *= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            console.log({a: new RegExp('sup')})\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            console.log({a: /sup/})\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            console.log(() => {new RegExp('sup')})\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            console.log(() => {/sup/})\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            function abc() {new RegExp('sup')}\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            function abc() {/sup/}\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            function abc() {return new RegExp('sup')}\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            function abc() {return /sup/}\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc <<= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc <<= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc >>= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc >>= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc >>>= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc >>>= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc ^= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc ^= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc &= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc &= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc |= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc |= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc ??= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc ??= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc &&= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc &&= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc ||= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc ||= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc **= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc **= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc /= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc /= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc += new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc += /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc -= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc -= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc %= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc %= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            () => new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            () => /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "a/RegExp(\"foo\")in b",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "a/ /foo/ in b"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "a/RegExp(\"foo\")instanceof b",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "a/ /foo/ instanceof b"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "do RegExp(\"foo\")\nwhile (true);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "do /foo/\nwhile (true);"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "for(let i;i<5;i++) { break\nnew RegExp('search')}",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "for(let i;i<5;i++) { break\n/search/}"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "for(let i;i<5;i++) { continue\nnew RegExp('search')}",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "for(let i;i<5;i++) { continue\n/search/}"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            switch (value) {\n                case \"possibility\":\n                    console.log('possibility matched')\n                case RegExp('myReg').toString():\n                    console.log('matches a regexp\\' toString value')\n                    break;\n            }\n            ",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            switch (value) {\n                case \"possibility\":\n                    console.log('possibility matched')\n                case /myReg/.toString():\n                    console.log('matches a regexp\\' toString value')\n                    break;\n            }\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "throw new RegExp('abcdefg') // fail with a regular expression",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "throw /abcdefg/ // fail with a regular expression"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "for (value of new RegExp('something being searched')) { console.log(value) }",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "(async function(){for await (value of new RegExp('something being searched')) { console.log(value) }})()",
+            parserOptions: {
+                ecmaVersion: 2018
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "for (value in new RegExp('something being searched')) { console.log(value) }",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "for (value in /something being searched/) { console.log(value) }"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "if (condition1 && condition2) new RegExp('avalue').test(str);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "debugger\nnew RegExp('myReg')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "debugger\n/myReg/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\n\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\t\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\t/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\f\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\f/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\v\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\v/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\r\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\r/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\t\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\t/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"/\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\//"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\.\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/./"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\.\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\./"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\\\n\\\\\\n\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n\\n/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\\\n\\\\\\f\\\\\\n\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n\\f\\n/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\u000A\\u000A\");",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n\\n/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('mysafereg' /* comment explaining its safety */)",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/prefer-template.js b/tests/lib/rules/prefer-template.js
index eea0255f1..a89a36a9d 100644
--- a/tests/lib/rules/prefer-template.js
+++ b/tests/lib/rules/prefer-template.js
@@ -223,6 +223,187 @@ ruleTester.run("prefer-template", rule, {
             code: "foo + '\\0'",
             output: "`${foo  }\\0`",
             errors
+        },
+
+        // https://github.com/eslint/eslint/issues/15083
+        {
+            code: `"default-src 'self' https://*.google.com;"
+            + "frame-ancestors 'none';"
+            + "report-to " + foo + ";"`,
+            output: `\`default-src 'self' https://*.google.com;\`
+            + \`frame-ancestors 'none';\`
+            + \`report-to \${  foo  };\``,
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo",
+            output: "`a` + `b${  foo}`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + 'c' + 'd'",
+            output: "`a` + `b${  foo  }c` + `d`",
+            errors
+        },
+        {
+            code: "'a' + 'b + c' + foo + 'd' + 'e'",
+            output: "`a` + `b + c${  foo  }d` + `e`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + 'd')",
+            output: "`a` + `b${  foo  }c` + `d`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('a' + 'b')",
+            output: "`a` + `b${  foo  }a` + `b`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + 'd') + ('e' + 'f')",
+            output: "`a` + `b${  foo  }c` + `d` + `e` + `f`",
+            errors
+        },
+        {
+            code: "foo + ('a' + 'b') + ('c' + 'd')",
+            output: "`${foo  }a` + `b` + `c` + `d`",
+            errors
+        },
+        {
+            code: "'a' + foo + ('b' + 'c') + ('d' + bar + 'e')",
+            output: "`a${  foo  }b` + `c` + `d${  bar  }e`",
+            errors
+        },
+        {
+            code: "foo + ('b' + 'c') + ('d' + bar + 'e')",
+            output: "`${foo  }b` + `c` + `d${  bar  }e`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + 'd' + 'e')",
+            output: "`a` + `b${  foo  }c` + `d` + `e`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + bar + 'd')",
+            output: "`a` + `b${  foo  }c${  bar  }d`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + bar + ('d' + 'e') + 'f')",
+            output: "`a` + `b${  foo  }c${  bar  }d` + `e` + `f`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + bar + 'e') + 'f' + test",
+            output: "`a` + `b${  foo  }c${  bar  }e` + `f${  test}`",
+            errors
+        },
+        {
+            code: "'a' + foo + ('b' + bar + 'c') + ('d' + test)",
+            output: "`a${  foo  }b${  bar  }c` + `d${  test}`",
+            errors
+        },
+        {
+            code: "'a' + foo + ('b' + 'c') + ('d' + bar)",
+            output: "`a${  foo  }b` + `c` + `d${  bar}`",
+            errors
+        },
+        {
+            code: "foo + ('a' + bar + 'b') + 'c' + test",
+            output: "`${foo  }a${  bar  }b` + `c${  test}`",
+            errors
+        },
+        {
+            code: "'a' + '`b`' + c",
+            output: "`a` + `\\`b\\`${  c}`",
+            errors
+        },
+        {
+            code: "'a' + '`b` + `c`' + d",
+            output: "`a` + `\\`b\\` + \\`c\\`${  d}`",
+            errors
+        },
+        {
+            code: "'a' + b + ('`c`' + '`d`')",
+            output: "`a${  b  }\\`c\\`` + `\\`d\\``",
+            errors
+        },
+        {
+            code: "'`a`' + b + ('`c`' + '`d`')",
+            output: "`\\`a\\`${  b  }\\`c\\`` + `\\`d\\``",
+            errors
+        },
+        {
+            code: "foo + ('`a`' + bar + '`b`') + '`c`' + test",
+            output: "`${foo  }\\`a\\`${  bar  }\\`b\\`` + `\\`c\\`${  test}`",
+            errors
+        },
+        {
+            code: "'a' + ('b' + 'c') + d",
+            output: "`a` + `b` + `c${  d}`",
+            errors
+        },
+        {
+            code: "'a' + ('`b`' + '`c`') + d",
+            output: "`a` + `\\`b\\`` + `\\`c\\`${  d}`",
+            errors
+        },
+        {
+            code: "a + ('b' + 'c') + d",
+            output: "`${a  }b` + `c${  d}`",
+            errors
+        },
+        {
+            code: "a + ('b' + 'c') + (d + 'e')",
+            output: "`${a  }b` + `c${  d  }e`",
+            errors
+        },
+        {
+            code: "a + ('`b`' + '`c`') + d",
+            output: "`${a  }\\`b\\`` + `\\`c\\`${  d}`",
+            errors
+        },
+        {
+            code: "a + ('`b` + `c`' + '`d`') + e",
+            output: "`${a  }\\`b\\` + \\`c\\`` + `\\`d\\`${  e}`",
+            errors
+        },
+        {
+            code: "'a' + ('b' + 'c' + 'd') + e",
+            output: "`a` + `b` + `c` + `d${  e}`",
+            errors
+        },
+        {
+            code: "'a' + ('b' + 'c' + 'd' + (e + 'f') + 'g' +'h' + 'i') + j",
+            output: "`a` + `b` + `c` + `d${  e  }fg` +`h` + `i${  j}`",
+            errors
+        },
+        {
+            code: "a + (('b' + 'c') + 'd')",
+            output: "`${a  }b` + `c` + `d`",
+            errors
+        },
+        {
+            code: "(a + 'b') + ('c' + 'd') + e",
+            output: "`${a  }b` + `c` + `d${  e}`",
+            errors
+        },
+        {
+            code: "var foo = \"Hello \" + \"world \" + \"another \" + test",
+            output: "var foo = `Hello ` + `world ` + `another ${  test}`",
+            errors
+        },
+        {
+            code: "'Hello ' + '\"world\" ' + test",
+            output: "`Hello ` + `\"world\" ${  test}`",
+            errors
+        },
+        {
+            code: "\"Hello \" + \"'world' \" + test",
+            output: "`Hello ` + `'world' ${  test}`",
+            errors
         }
     ]
 });