if some problems reported by the rule are automatically fixable by the --fix command line option
if the "extends": "eslint:recommended" property in a configuration file enables the rule.
if some problems reported by the rule are automatically fixable by the --fix command line option
if the "extends": "eslint:recommended" property in a configuration file enables the rule.
if some problems reported by the rule are manually fixable by editor suggestions
-${result}`;
+ return `${result}`;
};
/**
@@ -61,33 +61,33 @@ const highlighter = function (md, str, lang) {
* @param {MarkdownIt} md
* @license MIT License. See file header.
*/
-const lineNumberPlugin = (md) => {
- const fence = md.renderer.rules.fence;
- md.renderer.rules.fence = (...args) => {
- const [tokens, idx] = args;
- const lang = tokens[idx].info.trim();
- const rawCode = fence(...args);
- const code = rawCode.slice(
- rawCode.indexOf(""),
- rawCode.indexOf("")
- );
- const lines = code.split("\n");
- const lineNumbersCode = [...Array(lines.length - 1)]
- .map(
- (line, index) =>
- `${index + 1}"),
+ rawCode.indexOf(""),
+ );
+ const lines = code.split("\n");
+ const lineNumbersCode = [...Array(lines.length - 1)]
+ .map(
+ (line, index) =>
+ `${index + 1}/, ``)
+ const finalCode = rawCode
+ .replace(/<\/pre>\n/, `${lineNumbersWrapperCode}`)
+ .replace(/"(language-\S*?)"/, '"$1 line-numbers-mode"')
+ .replace(//, ``);
- return finalCode;
- };
+ return finalCode;
+ };
};
module.exports.highlighter = highlighter;
diff --git a/docs/src/_plugins/pre-wrapper.js b/docs/src/_plugins/pre-wrapper.js
new file mode 100644
index 000000000000..beb227486366
--- /dev/null
+++ b/docs/src/_plugins/pre-wrapper.js
@@ -0,0 +1,23 @@
+module.exports = md => {
+ const defaultFenceRenderer = md.renderer.rules.fence;
+
+ md.renderer.rules.fence = (...args) => {
+ const [tokens, index] = args;
+
+ if (/^\s*(?:in)?correct(?!\S)/u.test(tokens[index - 1].info)) {
+ return defaultFenceRenderer(...args);
+ }
+
+ return `
+
+ ${defaultFenceRenderer(...args)}
+
+
+`;
+ };
+};
diff --git a/docs/src/about/index.md b/docs/src/about/index.md
index 49328d8285fe..11cafb0ed4f1 100644
--- a/docs/src/about/index.md
+++ b/docs/src/about/index.md
@@ -1,6 +1,5 @@
---
title: About
-
---
ESLint is an open source JavaScript linting utility originally created by Nicholas C. Zakas in June 2013. Code [linting][] is a type of static analysis that is frequently used to find problematic patterns or code that doesn't adhere to certain style guidelines. There are code linters for most programming languages, and compilers sometimes incorporate linting into the compilation process.
@@ -18,24 +17,24 @@ ESLint is written using Node.js to provide a fast runtime environment and easy i
Everything is pluggable:
-* Rule API is used both by bundled and custom rules.
-* Formatter API is used both by bundled and custom formatters.
-* Additional rules and formatters can be specified at runtime.
-* Rules and formatters don't have to be bundled to be used.
+- Rule API is used both by bundled and custom rules.
+- Formatter API is used both by bundled and custom formatters.
+- Additional rules and formatters can be specified at runtime.
+- Rules and formatters don't have to be bundled to be used.
Every rule:
-* Is standalone.
-* Can be turned off or on (nothing can be deemed "too important to turn off").
-* Can be set to a warning or error individually.
+- Is standalone.
+- Can be turned off or on (nothing can be deemed "too important to turn off").
+- Can be set to a warning or error individually.
Additionally:
-* Rules are "agenda free" - ESLint does not promote any particular coding style.
-* Any bundled rules are generalizable.
+- Rules are "agenda free" - ESLint does not promote any particular coding style.
+- Any bundled rules are generalizable.
The project:
-* Values documentation and clear communication.
-* Is as transparent as possible.
-* Believes in the importance of testing.
+- Values documentation and clear communication.
+- Is as transparent as possible.
+- Believes in the importance of testing.
diff --git a/docs/src/assets/images/404.png b/docs/src/assets/images/404.png
index 347d16086ef8..2663176abc42 100644
Binary files a/docs/src/assets/images/404.png and b/docs/src/assets/images/404.png differ
diff --git a/docs/src/assets/images/architecture/dependency.svg b/docs/src/assets/images/architecture/dependency.svg
index 1609b53e1d99..b4809cc5137e 100644
--- a/docs/src/assets/images/architecture/dependency.svg
+++ b/docs/src/assets/images/architecture/dependency.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-dowhilestatement.svg b/docs/src/assets/images/code-path-analysis/example-dowhilestatement.svg
index f81d36123c4a..c8c189697f83 100644
--- a/docs/src/assets/images/code-path-analysis/example-dowhilestatement.svg
+++ b/docs/src/assets/images/code-path-analysis/example-dowhilestatement.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-forinstatement.svg b/docs/src/assets/images/code-path-analysis/example-forinstatement.svg
index a6bc754b1be8..e9c6e60d0c92 100644
--- a/docs/src/assets/images/code-path-analysis/example-forinstatement.svg
+++ b/docs/src/assets/images/code-path-analysis/example-forinstatement.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-forstatement-for-ever.svg b/docs/src/assets/images/code-path-analysis/example-forstatement-for-ever.svg
index 4d334ca62d9e..603fe468c172 100644
--- a/docs/src/assets/images/code-path-analysis/example-forstatement-for-ever.svg
+++ b/docs/src/assets/images/code-path-analysis/example-forstatement-for-ever.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-forstatement.svg b/docs/src/assets/images/code-path-analysis/example-forstatement.svg
index aa0ccf0d82f1..7b06b6ab4a48 100644
--- a/docs/src/assets/images/code-path-analysis/example-forstatement.svg
+++ b/docs/src/assets/images/code-path-analysis/example-forstatement.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-hello-world.svg b/docs/src/assets/images/code-path-analysis/example-hello-world.svg
index fc28d1fdaf9c..7b0d775c6030 100644
--- a/docs/src/assets/images/code-path-analysis/example-hello-world.svg
+++ b/docs/src/assets/images/code-path-analysis/example-hello-world.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-ifstatement-chain.svg b/docs/src/assets/images/code-path-analysis/example-ifstatement-chain.svg
index 0944c3bcf59c..e21fd583f251 100644
--- a/docs/src/assets/images/code-path-analysis/example-ifstatement-chain.svg
+++ b/docs/src/assets/images/code-path-analysis/example-ifstatement-chain.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-ifstatement.svg b/docs/src/assets/images/code-path-analysis/example-ifstatement.svg
index b83c67b51061..25061c57b9f0 100644
--- a/docs/src/assets/images/code-path-analysis/example-ifstatement.svg
+++ b/docs/src/assets/images/code-path-analysis/example-ifstatement.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-switchstatement-has-default.svg b/docs/src/assets/images/code-path-analysis/example-switchstatement-has-default.svg
index 5d6d73998b37..2afa1c551838 100644
--- a/docs/src/assets/images/code-path-analysis/example-switchstatement-has-default.svg
+++ b/docs/src/assets/images/code-path-analysis/example-switchstatement-has-default.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-switchstatement.svg b/docs/src/assets/images/code-path-analysis/example-switchstatement.svg
index e43e5e11190b..4ec5982178c6 100644
--- a/docs/src/assets/images/code-path-analysis/example-switchstatement.svg
+++ b/docs/src/assets/images/code-path-analysis/example-switchstatement.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-trystatement-try-catch-finally.svg b/docs/src/assets/images/code-path-analysis/example-trystatement-try-catch-finally.svg
index 60ec1cdf69b6..fcd016cdc160 100644
--- a/docs/src/assets/images/code-path-analysis/example-trystatement-try-catch-finally.svg
+++ b/docs/src/assets/images/code-path-analysis/example-trystatement-try-catch-finally.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-trystatement-try-catch.svg b/docs/src/assets/images/code-path-analysis/example-trystatement-try-catch.svg
index a2a0c8af2507..611b290effad 100644
--- a/docs/src/assets/images/code-path-analysis/example-trystatement-try-catch.svg
+++ b/docs/src/assets/images/code-path-analysis/example-trystatement-try-catch.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-trystatement-try-finally.svg b/docs/src/assets/images/code-path-analysis/example-trystatement-try-finally.svg
index 68c7801b7cd8..5125c96f111c 100644
--- a/docs/src/assets/images/code-path-analysis/example-trystatement-try-finally.svg
+++ b/docs/src/assets/images/code-path-analysis/example-trystatement-try-finally.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-when-there-is-a-function-f.svg b/docs/src/assets/images/code-path-analysis/example-when-there-is-a-function-f.svg
index 53bb946cf162..bd527c0017ad 100644
--- a/docs/src/assets/images/code-path-analysis/example-when-there-is-a-function-f.svg
+++ b/docs/src/assets/images/code-path-analysis/example-when-there-is-a-function-f.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-when-there-is-a-function-g.svg b/docs/src/assets/images/code-path-analysis/example-when-there-is-a-function-g.svg
index 4d3fe12b4a8f..ca22f81e2a09 100644
--- a/docs/src/assets/images/code-path-analysis/example-when-there-is-a-function-g.svg
+++ b/docs/src/assets/images/code-path-analysis/example-when-there-is-a-function-g.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/example-whilestatement.svg b/docs/src/assets/images/code-path-analysis/example-whilestatement.svg
index f03944389cda..8f785b160af0 100644
--- a/docs/src/assets/images/code-path-analysis/example-whilestatement.svg
+++ b/docs/src/assets/images/code-path-analysis/example-whilestatement.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/helo.svg b/docs/src/assets/images/code-path-analysis/helo.svg
index cd72a37d9aff..00c84fbea56a 100644
--- a/docs/src/assets/images/code-path-analysis/helo.svg
+++ b/docs/src/assets/images/code-path-analysis/helo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/loop-event-example-for-1.svg b/docs/src/assets/images/code-path-analysis/loop-event-example-for-1.svg
index 727ec12b132d..8a09c3e80b9a 100644
--- a/docs/src/assets/images/code-path-analysis/loop-event-example-for-1.svg
+++ b/docs/src/assets/images/code-path-analysis/loop-event-example-for-1.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/loop-event-example-for-2.svg b/docs/src/assets/images/code-path-analysis/loop-event-example-for-2.svg
index 70d762f38bc1..06e4e7d15eba 100644
--- a/docs/src/assets/images/code-path-analysis/loop-event-example-for-2.svg
+++ b/docs/src/assets/images/code-path-analysis/loop-event-example-for-2.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/loop-event-example-for-3.svg b/docs/src/assets/images/code-path-analysis/loop-event-example-for-3.svg
index 5adea136b40e..78bb754d93f4 100644
--- a/docs/src/assets/images/code-path-analysis/loop-event-example-for-3.svg
+++ b/docs/src/assets/images/code-path-analysis/loop-event-example-for-3.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/loop-event-example-for-4.svg b/docs/src/assets/images/code-path-analysis/loop-event-example-for-4.svg
index 99389751f340..433dec08d24c 100644
--- a/docs/src/assets/images/code-path-analysis/loop-event-example-for-4.svg
+++ b/docs/src/assets/images/code-path-analysis/loop-event-example-for-4.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/loop-event-example-for-5.svg b/docs/src/assets/images/code-path-analysis/loop-event-example-for-5.svg
index 070decb12924..e5f32155b70d 100644
--- a/docs/src/assets/images/code-path-analysis/loop-event-example-for-5.svg
+++ b/docs/src/assets/images/code-path-analysis/loop-event-example-for-5.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/loop-event-example-while-1.svg b/docs/src/assets/images/code-path-analysis/loop-event-example-while-1.svg
index 7d0c1a02d686..2db2fa29193f 100644
--- a/docs/src/assets/images/code-path-analysis/loop-event-example-while-1.svg
+++ b/docs/src/assets/images/code-path-analysis/loop-event-example-while-1.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/loop-event-example-while-2.svg b/docs/src/assets/images/code-path-analysis/loop-event-example-while-2.svg
index d5c31e276ca9..88c61fc4f51f 100644
--- a/docs/src/assets/images/code-path-analysis/loop-event-example-while-2.svg
+++ b/docs/src/assets/images/code-path-analysis/loop-event-example-while-2.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/code-path-analysis/loop-event-example-while-3.svg b/docs/src/assets/images/code-path-analysis/loop-event-example-while-3.svg
index 3f4e02c17db2..a372021d71a4 100644
--- a/docs/src/assets/images/code-path-analysis/loop-event-example-while-3.svg
+++ b/docs/src/assets/images/code-path-analysis/loop-event-example-while-3.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/configure/config-inspector.png b/docs/src/assets/images/configure/config-inspector.png
index 68e731f864bb..b5faf7928190 100644
Binary files a/docs/src/assets/images/configure/config-inspector.png and b/docs/src/assets/images/configure/config-inspector.png differ
diff --git a/docs/src/assets/images/icons/arrow-left.svg b/docs/src/assets/images/icons/arrow-left.svg
index 83483a7f256a..c5e777a8bba4 100644
--- a/docs/src/assets/images/icons/arrow-left.svg
+++ b/docs/src/assets/images/icons/arrow-left.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/arrow-right.svg b/docs/src/assets/images/icons/arrow-right.svg
index 22bb24fc3d4d..c1117a5cd29c 100644
--- a/docs/src/assets/images/icons/arrow-right.svg
+++ b/docs/src/assets/images/icons/arrow-right.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/arrow-top-right.svg b/docs/src/assets/images/icons/arrow-top-right.svg
index 58bbed85264f..37705b13cbc5 100644
--- a/docs/src/assets/images/icons/arrow-top-right.svg
+++ b/docs/src/assets/images/icons/arrow-top-right.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/chevron-down.svg b/docs/src/assets/images/icons/chevron-down.svg
index b09f7f73216a..46788a0f8626 100644
--- a/docs/src/assets/images/icons/chevron-down.svg
+++ b/docs/src/assets/images/icons/chevron-down.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/copy.svg b/docs/src/assets/images/icons/copy.svg
index 24fc6afae9c7..29fd98808f9f 100644
--- a/docs/src/assets/images/icons/copy.svg
+++ b/docs/src/assets/images/icons/copy.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/correct.svg b/docs/src/assets/images/icons/correct.svg
index 4f589241cb28..a99d10ca0dac 100644
--- a/docs/src/assets/images/icons/correct.svg
+++ b/docs/src/assets/images/icons/correct.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/discord.svg b/docs/src/assets/images/icons/discord.svg
index 16bae7b3c46e..03032099b171 100644
--- a/docs/src/assets/images/icons/discord.svg
+++ b/docs/src/assets/images/icons/discord.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/facebook.svg b/docs/src/assets/images/icons/facebook.svg
index 194c83485029..1fe1fbeef8ae 100644
--- a/docs/src/assets/images/icons/facebook.svg
+++ b/docs/src/assets/images/icons/facebook.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/features-list-icon.svg b/docs/src/assets/images/icons/features-list-icon.svg
index 2e576cff9fd8..9a09f471be6f 100644
--- a/docs/src/assets/images/icons/features-list-icon.svg
+++ b/docs/src/assets/images/icons/features-list-icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/github-icon-mono.svg b/docs/src/assets/images/icons/github-icon-mono.svg
index f73b88b55b4f..2aca9b078599 100644
--- a/docs/src/assets/images/icons/github-icon-mono.svg
+++ b/docs/src/assets/images/icons/github-icon-mono.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/github-img.svg b/docs/src/assets/images/icons/github-img.svg
index 51ad25a46eb8..3144d364f9d8 100644
--- a/docs/src/assets/images/icons/github-img.svg
+++ b/docs/src/assets/images/icons/github-img.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/github-large.svg b/docs/src/assets/images/icons/github-large.svg
index c540e36168fc..14905d7e65d9 100644
--- a/docs/src/assets/images/icons/github-large.svg
+++ b/docs/src/assets/images/icons/github-large.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/github-small.svg b/docs/src/assets/images/icons/github-small.svg
index b410d3adcdff..31621c7815bf 100644
--- a/docs/src/assets/images/icons/github-small.svg
+++ b/docs/src/assets/images/icons/github-small.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/github.svg b/docs/src/assets/images/icons/github.svg
index 0f3149634b9e..fe7c60f0836f 100644
--- a/docs/src/assets/images/icons/github.svg
+++ b/docs/src/assets/images/icons/github.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/google.svg b/docs/src/assets/images/icons/google.svg
index 8b149df54a95..3675e9cd20f1 100644
--- a/docs/src/assets/images/icons/google.svg
+++ b/docs/src/assets/images/icons/google.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/incorrect.svg b/docs/src/assets/images/icons/incorrect.svg
index 666811ebe475..e58babe33c7e 100644
--- a/docs/src/assets/images/icons/incorrect.svg
+++ b/docs/src/assets/images/icons/incorrect.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/languages.svg b/docs/src/assets/images/icons/languages.svg
index 2653515fe681..7ab95865e607 100644
--- a/docs/src/assets/images/icons/languages.svg
+++ b/docs/src/assets/images/icons/languages.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/learn-more-arrow.svg b/docs/src/assets/images/icons/learn-more-arrow.svg
index 8aab0b95e408..de1617f34e09 100644
--- a/docs/src/assets/images/icons/learn-more-arrow.svg
+++ b/docs/src/assets/images/icons/learn-more-arrow.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/link.svg b/docs/src/assets/images/icons/link.svg
index 6dfe15866b02..7301ad7a097a 100644
--- a/docs/src/assets/images/icons/link.svg
+++ b/docs/src/assets/images/icons/link.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/linkedin.svg b/docs/src/assets/images/icons/linkedin.svg
index a7c36f64e258..84b8f078499f 100644
--- a/docs/src/assets/images/icons/linkedin.svg
+++ b/docs/src/assets/images/icons/linkedin.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/menu.svg b/docs/src/assets/images/icons/menu.svg
index d068dbd04db0..83648a811009 100644
--- a/docs/src/assets/images/icons/menu.svg
+++ b/docs/src/assets/images/icons/menu.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/minus-circle.svg b/docs/src/assets/images/icons/minus-circle.svg
index f8e8023389a0..6f4a04b93be1 100644
--- a/docs/src/assets/images/icons/minus-circle.svg
+++ b/docs/src/assets/images/icons/minus-circle.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/npm.svg b/docs/src/assets/images/icons/npm.svg
index c9baf323174d..1a40a8c8aab9 100644
--- a/docs/src/assets/images/icons/npm.svg
+++ b/docs/src/assets/images/icons/npm.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/open-collectione-mono.svg b/docs/src/assets/images/icons/open-collectione-mono.svg
index 660478343ac0..2d042792a152 100644
--- a/docs/src/assets/images/icons/open-collectione-mono.svg
+++ b/docs/src/assets/images/icons/open-collectione-mono.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/opencollective-img.svg b/docs/src/assets/images/icons/opencollective-img.svg
index a3b46dcd5d4b..c6f318c77ae0 100644
--- a/docs/src/assets/images/icons/opencollective-img.svg
+++ b/docs/src/assets/images/icons/opencollective-img.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/plus-circle.svg b/docs/src/assets/images/icons/plus-circle.svg
index 58533a0b7bdf..54b257e96c76 100644
--- a/docs/src/assets/images/icons/plus-circle.svg
+++ b/docs/src/assets/images/icons/plus-circle.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/search.svg b/docs/src/assets/images/icons/search.svg
index 6c70237669ba..76d7735d1f40 100644
--- a/docs/src/assets/images/icons/search.svg
+++ b/docs/src/assets/images/icons/search.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/icons/twitter.svg b/docs/src/assets/images/icons/twitter.svg
index ffee249edaed..4aa1168ccf2d 100644
--- a/docs/src/assets/images/icons/twitter.svg
+++ b/docs/src/assets/images/icons/twitter.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/logo/brand-colors.svg b/docs/src/assets/images/logo/brand-colors.svg
index 2c2048de281d..3b9f9a78c760 100644
--- a/docs/src/assets/images/logo/brand-colors.svg
+++ b/docs/src/assets/images/logo/brand-colors.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/logo/eslint-logo-color.png b/docs/src/assets/images/logo/eslint-logo-color.png
index efa54ec778d2..27c0be651419 100644
Binary files a/docs/src/assets/images/logo/eslint-logo-color.png and b/docs/src/assets/images/logo/eslint-logo-color.png differ
diff --git a/docs/src/assets/images/logo/eslint-logo-color.svg b/docs/src/assets/images/logo/eslint-logo-color.svg
index 5a8dbfc6818f..5f780a8f73c4 100644
--- a/docs/src/assets/images/logo/eslint-logo-color.svg
+++ b/docs/src/assets/images/logo/eslint-logo-color.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/images/logo/eslint-logo-white.svg b/docs/src/assets/images/logo/eslint-logo-white.svg
index 2493dc4cfdfc..b9608ce950e7 100644
--- a/docs/src/assets/images/logo/eslint-logo-white.svg
+++ b/docs/src/assets/images/logo/eslint-logo-white.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/assets/js/components-index.js b/docs/src/assets/js/components-index.js
index 9e3bc0f5cf9c..3e26526a3e8e 100644
--- a/docs/src/assets/js/components-index.js
+++ b/docs/src/assets/js/components-index.js
@@ -1,35 +1,35 @@
-(function() {
- var index_trigger = document.getElementById("js-index-toggle"),
- index = document.getElementById("js-index-list"),
- body = document.getElementsByTagName("body")[0],
- open = false;
+(function () {
+ var index_trigger = document.getElementById("js-index-toggle"),
+ index = document.getElementById("js-index-list"),
+ body = document.getElementsByTagName("body")[0],
+ open = false;
- if (matchMedia) {
- const mq = window.matchMedia("(max-width: 1023px)");
- mq.addEventListener('change', WidthChange);
- WidthChange(mq);
- }
+ if (matchMedia) {
+ const mq = window.matchMedia("(max-width: 1023px)");
+ mq.addEventListener("change", WidthChange);
+ WidthChange(mq);
+ }
- function WidthChange(mq) {
- initIndex();
- }
+ function WidthChange(mq) {
+ initIndex();
+ }
- function toggleindex(e) {
- if (!open) {
- this.setAttribute("aria-expanded", "true");
- index.setAttribute("data-open", "true");
- open = true;
- } else {
- this.setAttribute("aria-expanded", "false");
- index.setAttribute("data-open", "false");
- open = false;
- }
- }
+ function toggleindex(e) {
+ if (!open) {
+ this.setAttribute("aria-expanded", "true");
+ index.setAttribute("data-open", "true");
+ open = true;
+ } else {
+ this.setAttribute("aria-expanded", "false");
+ index.setAttribute("data-open", "false");
+ open = false;
+ }
+ }
- function initIndex() {
- index_trigger.removeAttribute("hidden");
- index_trigger.setAttribute("aria-expanded", "false");
- index.setAttribute("data-open", "false");
- index_trigger.addEventListener("click", toggleindex, false);
- }
+ function initIndex() {
+ index_trigger.removeAttribute("hidden");
+ index_trigger.setAttribute("aria-expanded", "false");
+ index.setAttribute("data-open", "false");
+ index_trigger.addEventListener("click", toggleindex, false);
+ }
})();
diff --git a/docs/src/assets/js/css-vars-ponyfill@2.js b/docs/src/assets/js/css-vars-ponyfill@2.js
index 3285a577a2a9..7a8d79b7a822 100644
--- a/docs/src/assets/js/css-vars-ponyfill@2.js
+++ b/docs/src/assets/js/css-vars-ponyfill@2.js
@@ -5,43 +5,1494 @@
* (c) 2018-2019 John Hildenbiddle
* MIT license
*/
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).cssVars=t()}(this,function(){"use strict";function e(){return(e=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},r={mimeType:t.mimeType||null,onBeforeSend:t.onBeforeSend||Function.prototype,onSuccess:t.onSuccess||Function.prototype,onError:t.onError||Function.prototype,onComplete:t.onComplete||Function.prototype},n=Array.isArray(e)?e:[e],o=Array.apply(null,Array(n.length)).map(function(e){return null});function s(){return!("<"===(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").trim().charAt(0))}function a(e,t){r.onError(e,n[t],t)}function c(e,t){var s=r.onSuccess(e,n[t],t);e=!1===s?"":s||e,o[t]=e,-1===o.indexOf(null)&&r.onComplete(o)}var i=document.createElement("a");n.forEach(function(e,t){if(i.setAttribute("href",e),i.href=String(i.href),Boolean(document.all&&!window.atob)&&i.host.split(":")[0]!==location.host.split(":")[0]){if(i.protocol===location.protocol){var n=new XDomainRequest;n.open("GET",e),n.timeout=0,n.onprogress=Function.prototype,n.ontimeout=Function.prototype,n.onload=function(){s(n.responseText)?c(n.responseText,t):a(n,t)},n.onerror=function(e){a(n,t)},setTimeout(function(){n.send()},0)}else console.warn("Internet Explorer 9 Cross-Origin (CORS) requests must use the same protocol (".concat(e,")")),a(null,t)}else{var o=new XMLHttpRequest;o.open("GET",e),r.mimeType&&o.overrideMimeType&&o.overrideMimeType(r.mimeType),r.onBeforeSend(o,e,t),o.onreadystatechange=function(){4===o.readyState&&(200===o.status&&s(o.responseText)?c(o.responseText,t):a(o,t))},o.send()}})}function n(e){var t={cssComments:/\/\*[\s\S]+?\*\//g,cssImports:/(?:@import\s*)(?:url\(\s*)?(?:['"])([^'"]*)(?:['"])(?:\s*\))?(?:[^;]*;)/g},n={rootElement:e.rootElement||document,include:e.include||'style,link[rel="stylesheet"]',exclude:e.exclude||null,filter:e.filter||null,useCSSOM:e.useCSSOM||!1,onBeforeSend:e.onBeforeSend||Function.prototype,onSuccess:e.onSuccess||Function.prototype,onError:e.onError||Function.prototype,onComplete:e.onComplete||Function.prototype},s=Array.apply(null,n.rootElement.querySelectorAll(n.include)).filter(function(e){return t=e,r=n.exclude,!(t.matches||t.matchesSelector||t.webkitMatchesSelector||t.mozMatchesSelector||t.msMatchesSelector||t.oMatchesSelector).call(t,r);var t,r}),a=Array.apply(null,Array(s.length)).map(function(e){return null});function c(){if(-1===a.indexOf(null)){var e=a.join("");n.onComplete(e,a,s)}}function i(e,t,o,s){var i=n.onSuccess(e,o,s);(function e(t,o,s,a){var c=arguments.length>4&&void 0!==arguments[4]?arguments[4]:[];var i=arguments.length>5&&void 0!==arguments[5]?arguments[5]:[];var l=u(t,s,i);l.rules.length?r(l.absoluteUrls,{onBeforeSend:function(e,t,r){n.onBeforeSend(e,o,t)},onSuccess:function(e,t,r){var s=n.onSuccess(e,o,t),a=u(e=!1===s?"":s||e,t,i);return a.rules.forEach(function(t,r){e=e.replace(t,a.absoluteRules[r])}),e},onError:function(r,n,u){c.push({xhr:r,url:n}),i.push(l.rules[u]),e(t,o,s,a,c,i)},onComplete:function(r){r.forEach(function(e,r){t=t.replace(l.rules[r],e)}),e(t,o,s,a,c,i)}}):a(t,c)})(e=void 0!==i&&!1===Boolean(i)?"":i||e,o,s,function(e,r){null===a[t]&&(r.forEach(function(e){return n.onError(e.xhr,o,e.url)}),!n.filter||n.filter.test(e)?a[t]=e:a[t]="",c())})}function u(e,r){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],s={};return s.rules=(e.replace(t.cssComments,"").match(t.cssImports)||[]).filter(function(e){return-1===n.indexOf(e)}),s.urls=s.rules.map(function(e){return e.replace(t.cssImports,"$1")}),s.absoluteUrls=s.urls.map(function(e){return o(e,r)}),s.absoluteRules=s.rules.map(function(e,t){var n=s.urls[t],a=o(s.absoluteUrls[t],r);return e.replace(n,a)}),s}s.length?s.forEach(function(e,t){var s=e.getAttribute("href"),u=e.getAttribute("rel"),l="LINK"===e.nodeName&&s&&u&&"stylesheet"===u.toLowerCase(),f="STYLE"===e.nodeName;if(l)r(s,{mimeType:"text/css",onBeforeSend:function(t,r,o){n.onBeforeSend(t,e,r)},onSuccess:function(r,n,a){var c=o(s,location.href);i(r,t,e,c)},onError:function(r,o,s){a[t]="",n.onError(r,e,o),c()}});else if(f){var d=e.textContent;n.useCSSOM&&(d=Array.apply(null,e.sheet.cssRules).map(function(e){return e.cssText}).join("")),i(d,t,e,location.href)}else a[t]="",c()}):n.onComplete("",[])}function o(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:location.href,r=document.implementation.createHTMLDocument(""),n=r.createElement("base"),o=r.createElement("a");return r.head.appendChild(n),r.body.appendChild(o),n.href=t,o.href=e,o.href}var s=a;function a(e,t,r){e instanceof RegExp&&(e=c(e,r)),t instanceof RegExp&&(t=c(t,r));var n=i(e,t,r);return n&&{start:n[0],end:n[1],pre:r.slice(0,n[0]),body:r.slice(n[0]+e.length,n[1]),post:r.slice(n[1]+t.length)}}function c(e,t){var r=t.match(e);return r?r[0]:null}function i(e,t,r){var n,o,s,a,c,i=r.indexOf(e),u=r.indexOf(t,i+1),l=i;if(i>=0&&u>0){for(n=[],s=r.length;l>=0&&!c;)l==i?(n.push(l),i=r.indexOf(e,l+1)):1==n.length?c=[n.pop(),u]:((o=n.pop())=0?i:u;n.length&&(c=[s,a])}return c}function u(t){var r=e({},{preserveStatic:!0,removeComments:!1},arguments.length>1&&void 0!==arguments[1]?arguments[1]:{});function n(e){throw new Error("CSS parse error: ".concat(e))}function o(e){var r=e.exec(t);if(r)return t=t.slice(r[0].length),r}function a(){return o(/^{\s*/)}function c(){return o(/^}/)}function i(){o(/^\s*/)}function u(){if(i(),"/"===t[0]&&"*"===t[1]){for(var e=2;t[e]&&("*"!==t[e]||"/"!==t[e+1]);)e++;if(!t[e])return n("end of comment is missing");var r=t.slice(2,e);return t=t.slice(e+2),{type:"comment",comment:r}}}function l(){for(var e,t=[];e=u();)t.push(e);return r.removeComments?[]:t}function f(){for(i();"}"===t[0];)n("extra closing bracket");var e=o(/^(("(?:\\"|[^"])*"|'(?:\\'|[^'])*'|[^{])+)/);if(e)return e[0].trim().replace(/\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*\/+/g,"").replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g,function(e){return e.replace(/,/g,"â")}).split(/\s*(?![^(]*\)),\s*/).map(function(e){return e.replace(/\u200C/g,",")})}function d(){o(/^([;\s]*)+/);var e=/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//g,t=o(/^(\*?[-#\/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/);if(t){if(t=t[0].trim(),!o(/^:\s*/))return n("property missing ':'");var r=o(/^((?:\/\*.*?\*\/|'(?:\\'|.)*?'|"(?:\\"|.)*?"|\((\s*'(?:\\'|.)*?'|"(?:\\"|.)*?"|[^)]*?)\s*\)|[^};])+)/),s={type:"declaration",property:t.replace(e,""),value:r?r[0].replace(e,"").trim():""};return o(/^[;\s]*/),s}}function p(){if(!a())return n("missing '{'");for(var e,t=l();e=d();)t.push(e),t=t.concat(l());return c()?t:n("missing '}'")}function m(){i();for(var e,t=[];e=o(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/);)t.push(e[1]),o(/^,\s*/);if(t.length)return{type:"keyframe",values:t,declarations:p()}}function v(){if(i(),"@"===t[0]){var e=function(){var e=o(/^@([-\w]+)?keyframes\s*/);if(e){var t=e[1];if(!(e=o(/^([-\w]+)\s*/)))return n("@keyframes missing name");var r,s=e[1];if(!a())return n("@keyframes missing '{'");for(var i=l();r=m();)i.push(r),i=i.concat(l());return c()?{type:"keyframes",name:s,vendor:t,keyframes:i}:n("@keyframes missing '}'")}}()||function(){var e=o(/^@supports *([^{]+)/);if(e)return{type:"supports",supports:e[1].trim(),rules:y()}}()||function(){if(o(/^@host\s*/))return{type:"host",rules:y()}}()||function(){var e=o(/^@media([^{]+)*/);if(e)return{type:"media",media:(e[1]||"").trim(),rules:y()}}()||function(){var e=o(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/);if(e)return{type:"custom-media",name:e[1].trim(),media:e[2].trim()}}()||function(){if(o(/^@page */))return{type:"page",selectors:f()||[],declarations:p()}}()||function(){var e=o(/^@([-\w]+)?document *([^{]+)/);if(e)return{type:"document",document:e[2].trim(),vendor:e[1]?e[1].trim():null,rules:y()}}()||function(){if(o(/^@font-face\s*/))return{type:"font-face",declarations:p()}}()||function(){var e=o(/^@(import|charset|namespace)\s*([^;]+);/);if(e)return{type:e[1],name:e[2].trim()}}();if(e&&!r.preserveStatic){var s=!1;if(e.declarations)s=e.declarations.some(function(e){return/var\(/.test(e.value)});else s=(e.keyframes||e.rules||[]).some(function(e){return(e.declarations||[]).some(function(e){return/var\(/.test(e.value)})});return s?e:{}}return e}}function h(){if(!r.preserveStatic){var e=s("{","}",t);if(e){var o=/:(?:root|host)(?![.:#(])/.test(e.pre)&&/--\S*\s*:/.test(e.body),a=/var\(/.test(e.body);if(!o&&!a)return t=t.slice(e.end+1),{}}}var c=f()||[],i=r.preserveStatic?p():p().filter(function(e){var t=c.some(function(e){return/:(?:root|host)(?![.:#(])/.test(e)})&&/^--\S/.test(e.property),r=/var\(/.test(e.value);return t||r});return c.length||n("selector missing"),{type:"rule",selectors:c,declarations:i}}function y(e){if(!e&&!a())return n("missing '{'");for(var r,o=l();t.length&&(e||"}"!==t[0])&&(r=v()||h());)r.type&&o.push(r),o=o.concat(l());return e||c()?o:n("missing '}'")}return{type:"stylesheet",stylesheet:{rules:y(!0),errors:[]}}}function l(t){var r=e({},{parseHost:!1,store:{},onWarning:function(){}},arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}),n=new RegExp(":".concat(r.parseHost?"host":"root","(?![.:#(])"));return"string"==typeof t&&(t=u(t,r)),t.stylesheet.rules.forEach(function(e){"rule"===e.type&&e.selectors.some(function(e){return n.test(e)})&&e.declarations.forEach(function(e,t){var n=e.property,o=e.value;n&&0===n.indexOf("--")&&(r.store[n]=o)})}),r.store}function f(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2?arguments[2]:void 0,n={charset:function(e){return"@charset "+e.name+";"},comment:function(e){return 0===e.comment.indexOf("__CSSVARSPONYFILL")?"/*"+e.comment+"*/":""},"custom-media":function(e){return"@custom-media "+e.name+" "+e.media+";"},declaration:function(e){return e.property+":"+e.value+";"},document:function(e){return"@"+(e.vendor||"")+"document "+e.document+"{"+o(e.rules)+"}"},"font-face":function(e){return"@font-face{"+o(e.declarations)+"}"},host:function(e){return"@host{"+o(e.rules)+"}"},import:function(e){return"@import "+e.name+";"},keyframe:function(e){return e.values.join(",")+"{"+o(e.declarations)+"}"},keyframes:function(e){return"@"+(e.vendor||"")+"keyframes "+e.name+"{"+o(e.keyframes)+"}"},media:function(e){return"@media "+e.media+"{"+o(e.rules)+"}"},namespace:function(e){return"@namespace "+e.name+";"},page:function(e){return"@page "+(e.selectors.length?e.selectors.join(", "):"")+"{"+o(e.declarations)+"}"},rule:function(e){var t=e.declarations;if(t.length)return e.selectors.join(",")+"{"+o(t)+"}"},supports:function(e){return"@supports "+e.supports+"{"+o(e.rules)+"}"}};function o(e){for(var o="",s=0;s1&&void 0!==arguments[1]?arguments[1]:{});return"string"==typeof t&&(t=u(t,r)),function e(t,r){t.rules.forEach(function(n){n.rules?e(n,r):n.keyframes?n.keyframes.forEach(function(e){"keyframe"===e.type&&r(e.declarations,n)}):n.declarations&&r(n.declarations,t)})}(t.stylesheet,function(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2?arguments[2]:void 0;if(-1===e.indexOf("var("))return e;var n=s("(",")",e);return n?"var"===n.pre.slice(-3)?0===n.body.trim().length?(t.onWarning("var() must contain a non-whitespace string"),e):n.pre.slice(0,-3)+function(e){var n=e.split(",")[0].replace(/[\s\n\t]/g,""),o=(e.match(/(?:\s*,\s*){1}(.*)?/)||[])[1],s=Object.prototype.hasOwnProperty.call(t.variables,n)?String(t.variables[n]):void 0,a=s||(o?String(o):void 0),c=r||e;return s||t.onWarning('variable "'.concat(n,'" is undefined')),a&&"undefined"!==a&&a.length>0?h(a,t,c):"var(".concat(c,")")}(n.body)+h(n.post,t):n.pre+"(".concat(h(n.body,t),")")+h(n.post,t):(-1!==e.indexOf("var(")&&t.onWarning('missing closing ")" in the value "'.concat(e,'"')),e)}var y="undefined"!=typeof window,g=y&&window.CSS&&window.CSS.supports&&window.CSS.supports("(--a: 0)"),S={group:0,job:0},b={rootElement:y?document:null,shadowDOM:!1,include:"style,link[rel=stylesheet]",exclude:"",variables:{},onlyLegacy:!0,preserveStatic:!0,preserveVars:!1,silent:!1,updateDOM:!0,updateURLs:!0,watch:null,onBeforeSend:function(){},onWarning:function(){},onError:function(){},onSuccess:function(){},onComplete:function(){}},E={cssComments:/\/\*[\s\S]+?\*\//g,cssKeyframes:/@(?:-\w*-)?keyframes/,cssMediaQueries:/@media[^{]+\{([\s\S]+?})\s*}/g,cssUrls:/url\((?!['"]?(?:data|http|\/\/):)['"]?([^'")]*)['"]?\)/g,cssVarDeclRules:/(?::(?:root|host)(?![.:#(])[\s,]*[^{]*{\s*[^}]*})/g,cssVarDecls:/(?:[\s;]*)(-{2}\w[\w-]*)(?:\s*:\s*)([^;]*);/g,cssVarFunc:/var\(\s*--[\w-]/,cssVars:/(?:(?::(?:root|host)(?![.:#(])[\s,]*[^{]*{\s*[^;]*;*\s*)|(?:var\(\s*))(--[^:)]+)(?:\s*[:)])/},w={dom:{},job:{},user:{}},C=!1,O=null,A=0,x=null,j=!1;function k(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},o="cssVars(): ",s=e({},b,r);function a(e,t,r,n){!s.silent&&window.console&&console.error("".concat(o).concat(e,"\n"),t),s.onError(e,t,r,n)}function c(e){!s.silent&&window.console&&console.warn("".concat(o).concat(e)),s.onWarning(e)}if(y){if(s.watch)return s.watch=b.watch,function(e){function t(e){return"LINK"===e.tagName&&-1!==(e.getAttribute("rel")||"").indexOf("stylesheet")&&!e.disabled}if(!window.MutationObserver)return;O&&(O.disconnect(),O=null);(O=new MutationObserver(function(r){r.some(function(r){var n,o=!1;return"attributes"===r.type?o=t(r.target):"childList"===r.type&&(n=r.addedNodes,o=Array.apply(null,n).some(function(e){var r=1===e.nodeType&&e.hasAttribute("data-cssvars"),n=function(e){return"STYLE"===e.tagName&&!e.disabled}(e)&&E.cssVars.test(e.textContent);return!r&&(t(e)||n)})||function(t){return Array.apply(null,t).some(function(t){var r=1===t.nodeType,n=r&&"out"===t.getAttribute("data-cssvars"),o=r&&"src"===t.getAttribute("data-cssvars"),s=o;if(o||n){var a=t.getAttribute("data-cssvars-group"),c=e.rootElement.querySelector('[data-cssvars-group="'.concat(a,'"]'));o&&(L(e.rootElement),w.dom={}),c&&c.parentNode.removeChild(c)}return s})}(r.removedNodes)),o})&&k(e)})).observe(document.documentElement,{attributes:!0,attributeFilter:["disabled","href"],childList:!0,subtree:!0})}(s),void k(s);if(!1===s.watch&&O&&(O.disconnect(),O=null),!s.__benchmark){if(C===s.rootElement)return void function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100;clearTimeout(x),x=setTimeout(function(){e.__benchmark=null,k(e)},t)}(r);if(s.__benchmark=T(),s.exclude=[O?'[data-cssvars]:not([data-cssvars=""])':'[data-cssvars="out"]',s.exclude].filter(function(e){return e}).join(","),s.variables=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=/^-{2}/;return Object.keys(e).reduce(function(r,n){return r[t.test(n)?n:"--".concat(n.replace(/^-+/,""))]=e[n],r},{})}(s.variables),!O)if(Array.apply(null,s.rootElement.querySelectorAll('[data-cssvars="out"]')).forEach(function(e){var t=e.getAttribute("data-cssvars-group");(t?s.rootElement.querySelector('[data-cssvars="src"][data-cssvars-group="'.concat(t,'"]')):null)||e.parentNode.removeChild(e)}),A){var i=s.rootElement.querySelectorAll('[data-cssvars]:not([data-cssvars="out"])');i.length2&&void 0!==arguments[2]?arguments[2]:[],i={},d=s.updateDOM?w.dom:Object.keys(w.job).length?w.job:w.job=JSON.parse(JSON.stringify(w.dom)),p=!1;if(o.forEach(function(e,t){if(E.cssVars.test(n[t]))try{var r=u(n[t],{preserveStatic:s.preserveStatic,removeComments:!0});l(r,{parseHost:Boolean(s.rootElement.host),store:i,onWarning:c}),e.__cssVars={tree:r}}catch(t){a(t.message,e)}}),s.updateDOM&&e(w.user,s.variables),e(i,s.variables),p=Boolean((document.querySelector("[data-cssvars]")||Object.keys(w.dom).length)&&Object.keys(i).some(function(e){return i[e]!==d[e]})),e(d,w.user,i),p)L(s.rootElement),k(s);else{var v=[],h=[],y=!1;if(w.job={},s.updateDOM&&S.job++,o.forEach(function(t){var r=!t.__cssVars;if(t.__cssVars)try{m(t.__cssVars.tree,e({},s,{variables:d,onWarning:c}));var n=f(t.__cssVars.tree);if(s.updateDOM){if(t.getAttribute("data-cssvars")||t.setAttribute("data-cssvars","src"),n.length){var o=t.getAttribute("data-cssvars-group")||++S.group,i=n.replace(/\s/g,""),u=s.rootElement.querySelector('[data-cssvars="out"][data-cssvars-group="'.concat(o,'"]'))||document.createElement("style");y=y||E.cssKeyframes.test(n),u.hasAttribute("data-cssvars")||u.setAttribute("data-cssvars","out"),i===t.textContent.replace(/\s/g,"")?(r=!0,u&&u.parentNode&&(t.removeAttribute("data-cssvars-group"),u.parentNode.removeChild(u))):i!==u.textContent.replace(/\s/g,"")&&([t,u].forEach(function(e){e.setAttribute("data-cssvars-job",S.job),e.setAttribute("data-cssvars-group",o)}),u.textContent=n,v.push(n),h.push(u),u.parentNode||t.parentNode.insertBefore(u,t.nextSibling))}}else t.textContent.replace(/\s/g,"")!==n&&v.push(n)}catch(e){a(e.message,t)}r&&t.setAttribute("data-cssvars","skip"),t.hasAttribute("data-cssvars-job")||t.setAttribute("data-cssvars-job",S.job)}),A=s.rootElement.querySelectorAll('[data-cssvars]:not([data-cssvars="out"])').length,s.shadowDOM)for(var g,b=[s.rootElement].concat(t(s.rootElement.querySelectorAll("*"))),O=0;g=b[O];++O)if(g.shadowRoot&&g.shadowRoot.querySelector("style")){var x=e({},s,{rootElement:g.shadowRoot});k(x)}s.updateDOM&&y&&M(s.rootElement),C=!1,s.onComplete(v.join(""),h,JSON.parse(JSON.stringify(d)),T()-s.__benchmark)}}}));else document.addEventListener("DOMContentLoaded",function e(t){k(r),document.removeEventListener("DOMContentLoaded",e)})}}function M(e){var t=["animation-name","-moz-animation-name","-webkit-animation-name"].filter(function(e){return getComputedStyle(document.body)[e]})[0];if(t){for(var r=e.getElementsByTagName("*"),n=[],o=0,s=r.length;o1&&void 0!==arguments[1]?arguments[1]:location.href,r=document.implementation.createHTMLDocument(""),n=r.createElement("base"),o=r.createElement("a");return r.head.appendChild(n),r.body.appendChild(o),n.href=t,o.href=e,o.href}function T(){return y&&(window.performance||{}).now?window.performance.now():(new Date).getTime()}function L(e){Array.apply(null,e.querySelectorAll('[data-cssvars="skip"],[data-cssvars="src"]')).forEach(function(e){return e.setAttribute("data-cssvars","")})}return k.reset=function(){for(var e in C=!1,O&&(O.disconnect(),O=null),A=0,x=null,j=!1,w)w[e]={}},k});
+!(function (e, t) {
+ "object" == typeof exports && "undefined" != typeof module
+ ? (module.exports = t())
+ : "function" == typeof define && define.amd
+ ? define(t)
+ : ((e = e || self).cssVars = t());
+})(this, function () {
+ "use strict";
+ function e() {
+ return (e =
+ Object.assign ||
+ function (e) {
+ for (var t = 1; t < arguments.length; t++) {
+ var r = arguments[t];
+ for (var n in r)
+ Object.prototype.hasOwnProperty.call(r, n) &&
+ (e[n] = r[n]);
+ }
+ return e;
+ }).apply(this, arguments);
+ }
+ function t(e) {
+ return (
+ (function (e) {
+ if (Array.isArray(e)) {
+ for (var t = 0, r = new Array(e.length); t < e.length; t++)
+ r[t] = e[t];
+ return r;
+ }
+ })(e) ||
+ (function (e) {
+ if (
+ Symbol.iterator in Object(e) ||
+ "[object Arguments]" === Object.prototype.toString.call(e)
+ )
+ return Array.from(e);
+ })(e) ||
+ (function () {
+ throw new TypeError(
+ "Invalid attempt to spread non-iterable instance",
+ );
+ })()
+ );
+ }
+ function r(e) {
+ var t =
+ arguments.length > 1 && void 0 !== arguments[1]
+ ? arguments[1]
+ : {},
+ r = {
+ mimeType: t.mimeType || null,
+ onBeforeSend: t.onBeforeSend || Function.prototype,
+ onSuccess: t.onSuccess || Function.prototype,
+ onError: t.onError || Function.prototype,
+ onComplete: t.onComplete || Function.prototype,
+ },
+ n = Array.isArray(e) ? e : [e],
+ o = Array.apply(null, Array(n.length)).map(function (e) {
+ return null;
+ });
+ function s() {
+ return !(
+ "<" ===
+ (arguments.length > 0 && void 0 !== arguments[0]
+ ? arguments[0]
+ : ""
+ )
+ .trim()
+ .charAt(0)
+ );
+ }
+ function a(e, t) {
+ r.onError(e, n[t], t);
+ }
+ function c(e, t) {
+ var s = r.onSuccess(e, n[t], t);
+ (e = !1 === s ? "" : s || e),
+ (o[t] = e),
+ -1 === o.indexOf(null) && r.onComplete(o);
+ }
+ var i = document.createElement("a");
+ n.forEach(function (e, t) {
+ if (
+ (i.setAttribute("href", e),
+ (i.href = String(i.href)),
+ Boolean(document.all && !window.atob) &&
+ i.host.split(":")[0] !== location.host.split(":")[0])
+ ) {
+ if (i.protocol === location.protocol) {
+ var n = new XDomainRequest();
+ n.open("GET", e),
+ (n.timeout = 0),
+ (n.onprogress = Function.prototype),
+ (n.ontimeout = Function.prototype),
+ (n.onload = function () {
+ s(n.responseText) ? c(n.responseText, t) : a(n, t);
+ }),
+ (n.onerror = function (e) {
+ a(n, t);
+ }),
+ setTimeout(function () {
+ n.send();
+ }, 0);
+ } else
+ console.warn(
+ "Internet Explorer 9 Cross-Origin (CORS) requests must use the same protocol (".concat(
+ e,
+ ")",
+ ),
+ ),
+ a(null, t);
+ } else {
+ var o = new XMLHttpRequest();
+ o.open("GET", e),
+ r.mimeType &&
+ o.overrideMimeType &&
+ o.overrideMimeType(r.mimeType),
+ r.onBeforeSend(o, e, t),
+ (o.onreadystatechange = function () {
+ 4 === o.readyState &&
+ (200 === o.status && s(o.responseText)
+ ? c(o.responseText, t)
+ : a(o, t));
+ }),
+ o.send();
+ }
+ });
+ }
+ function n(e) {
+ var t = {
+ cssComments: /\/\*[\s\S]+?\*\//g,
+ cssImports:
+ /(?:@import\s*)(?:url\(\s*)?(?:['"])([^'"]*)(?:['"])(?:\s*\))?(?:[^;]*;)/g,
+ },
+ n = {
+ rootElement: e.rootElement || document,
+ include: e.include || 'style,link[rel="stylesheet"]',
+ exclude: e.exclude || null,
+ filter: e.filter || null,
+ useCSSOM: e.useCSSOM || !1,
+ onBeforeSend: e.onBeforeSend || Function.prototype,
+ onSuccess: e.onSuccess || Function.prototype,
+ onError: e.onError || Function.prototype,
+ onComplete: e.onComplete || Function.prototype,
+ },
+ s = Array.apply(
+ null,
+ n.rootElement.querySelectorAll(n.include),
+ ).filter(function (e) {
+ return (
+ (t = e),
+ (r = n.exclude),
+ !(
+ t.matches ||
+ t.matchesSelector ||
+ t.webkitMatchesSelector ||
+ t.mozMatchesSelector ||
+ t.msMatchesSelector ||
+ t.oMatchesSelector
+ ).call(t, r)
+ );
+ var t, r;
+ }),
+ a = Array.apply(null, Array(s.length)).map(function (e) {
+ return null;
+ });
+ function c() {
+ if (-1 === a.indexOf(null)) {
+ var e = a.join("");
+ n.onComplete(e, a, s);
+ }
+ }
+ function i(e, t, o, s) {
+ var i = n.onSuccess(e, o, s);
+ (function e(t, o, s, a) {
+ var c =
+ arguments.length > 4 && void 0 !== arguments[4]
+ ? arguments[4]
+ : [];
+ var i =
+ arguments.length > 5 && void 0 !== arguments[5]
+ ? arguments[5]
+ : [];
+ var l = u(t, s, i);
+ l.rules.length
+ ? r(l.absoluteUrls, {
+ onBeforeSend: function (e, t, r) {
+ n.onBeforeSend(e, o, t);
+ },
+ onSuccess: function (e, t, r) {
+ var s = n.onSuccess(e, o, t),
+ a = u((e = !1 === s ? "" : s || e), t, i);
+ return (
+ a.rules.forEach(function (t, r) {
+ e = e.replace(t, a.absoluteRules[r]);
+ }),
+ e
+ );
+ },
+ onError: function (r, n, u) {
+ c.push({ xhr: r, url: n }),
+ i.push(l.rules[u]),
+ e(t, o, s, a, c, i);
+ },
+ onComplete: function (r) {
+ r.forEach(function (e, r) {
+ t = t.replace(l.rules[r], e);
+ }),
+ e(t, o, s, a, c, i);
+ },
+ })
+ : a(t, c);
+ })(
+ (e = void 0 !== i && !1 === Boolean(i) ? "" : i || e),
+ o,
+ s,
+ function (e, r) {
+ null === a[t] &&
+ (r.forEach(function (e) {
+ return n.onError(e.xhr, o, e.url);
+ }),
+ !n.filter || n.filter.test(e)
+ ? (a[t] = e)
+ : (a[t] = ""),
+ c());
+ },
+ );
+ }
+ function u(e, r) {
+ var n =
+ arguments.length > 2 && void 0 !== arguments[2]
+ ? arguments[2]
+ : [],
+ s = {};
+ return (
+ (s.rules = (
+ e.replace(t.cssComments, "").match(t.cssImports) || []
+ ).filter(function (e) {
+ return -1 === n.indexOf(e);
+ })),
+ (s.urls = s.rules.map(function (e) {
+ return e.replace(t.cssImports, "$1");
+ })),
+ (s.absoluteUrls = s.urls.map(function (e) {
+ return o(e, r);
+ })),
+ (s.absoluteRules = s.rules.map(function (e, t) {
+ var n = s.urls[t],
+ a = o(s.absoluteUrls[t], r);
+ return e.replace(n, a);
+ })),
+ s
+ );
+ }
+ s.length
+ ? s.forEach(function (e, t) {
+ var s = e.getAttribute("href"),
+ u = e.getAttribute("rel"),
+ l =
+ "LINK" === e.nodeName &&
+ s &&
+ u &&
+ "stylesheet" === u.toLowerCase(),
+ f = "STYLE" === e.nodeName;
+ if (l)
+ r(s, {
+ mimeType: "text/css",
+ onBeforeSend: function (t, r, o) {
+ n.onBeforeSend(t, e, r);
+ },
+ onSuccess: function (r, n, a) {
+ var c = o(s, location.href);
+ i(r, t, e, c);
+ },
+ onError: function (r, o, s) {
+ (a[t] = ""), n.onError(r, e, o), c();
+ },
+ });
+ else if (f) {
+ var d = e.textContent;
+ n.useCSSOM &&
+ (d = Array.apply(null, e.sheet.cssRules)
+ .map(function (e) {
+ return e.cssText;
+ })
+ .join("")),
+ i(d, t, e, location.href);
+ } else (a[t] = ""), c();
+ })
+ : n.onComplete("", []);
+ }
+ function o(e) {
+ var t =
+ arguments.length > 1 && void 0 !== arguments[1]
+ ? arguments[1]
+ : location.href,
+ r = document.implementation.createHTMLDocument(""),
+ n = r.createElement("base"),
+ o = r.createElement("a");
+ return (
+ r.head.appendChild(n),
+ r.body.appendChild(o),
+ (n.href = t),
+ (o.href = e),
+ o.href
+ );
+ }
+ var s = a;
+ function a(e, t, r) {
+ e instanceof RegExp && (e = c(e, r)),
+ t instanceof RegExp && (t = c(t, r));
+ var n = i(e, t, r);
+ return (
+ n && {
+ start: n[0],
+ end: n[1],
+ pre: r.slice(0, n[0]),
+ body: r.slice(n[0] + e.length, n[1]),
+ post: r.slice(n[1] + t.length),
+ }
+ );
+ }
+ function c(e, t) {
+ var r = t.match(e);
+ return r ? r[0] : null;
+ }
+ function i(e, t, r) {
+ var n,
+ o,
+ s,
+ a,
+ c,
+ i = r.indexOf(e),
+ u = r.indexOf(t, i + 1),
+ l = i;
+ if (i >= 0 && u > 0) {
+ for (n = [], s = r.length; l >= 0 && !c; )
+ l == i
+ ? (n.push(l), (i = r.indexOf(e, l + 1)))
+ : 1 == n.length
+ ? (c = [n.pop(), u])
+ : ((o = n.pop()) < s && ((s = o), (a = u)),
+ (u = r.indexOf(t, l + 1))),
+ (l = i < u && i >= 0 ? i : u);
+ n.length && (c = [s, a]);
+ }
+ return c;
+ }
+ function u(t) {
+ var r = e(
+ {},
+ { preserveStatic: !0, removeComments: !1 },
+ arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {},
+ );
+ function n(e) {
+ throw new Error("CSS parse error: ".concat(e));
+ }
+ function o(e) {
+ var r = e.exec(t);
+ if (r) return (t = t.slice(r[0].length)), r;
+ }
+ function a() {
+ return o(/^{\s*/);
+ }
+ function c() {
+ return o(/^}/);
+ }
+ function i() {
+ o(/^\s*/);
+ }
+ function u() {
+ if ((i(), "/" === t[0] && "*" === t[1])) {
+ for (var e = 2; t[e] && ("*" !== t[e] || "/" !== t[e + 1]); )
+ e++;
+ if (!t[e]) return n("end of comment is missing");
+ var r = t.slice(2, e);
+ return (t = t.slice(e + 2)), { type: "comment", comment: r };
+ }
+ }
+ function l() {
+ for (var e, t = []; (e = u()); ) t.push(e);
+ return r.removeComments ? [] : t;
+ }
+ function f() {
+ for (i(); "}" === t[0]; ) n("extra closing bracket");
+ var e = o(/^(("(?:\\"|[^"])*"|'(?:\\'|[^'])*'|[^{])+)/);
+ if (e)
+ return e[0]
+ .trim()
+ .replace(
+ /\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*\/+/g,
+ "",
+ )
+ .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (e) {
+ return e.replace(/,/g, "â");
+ })
+ .split(/\s*(?![^(]*\)),\s*/)
+ .map(function (e) {
+ return e.replace(/\u200C/g, ",");
+ });
+ }
+ function d() {
+ o(/^([;\s]*)+/);
+ var e = /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//g,
+ t = o(/^(\*?[-#\/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/);
+ if (t) {
+ if (((t = t[0].trim()), !o(/^:\s*/)))
+ return n("property missing ':'");
+ var r = o(
+ /^((?:\/\*.*?\*\/|'(?:\\'|.)*?'|"(?:\\"|.)*?"|\((\s*'(?:\\'|.)*?'|"(?:\\"|.)*?"|[^)]*?)\s*\)|[^};])+)/,
+ ),
+ s = {
+ type: "declaration",
+ property: t.replace(e, ""),
+ value: r ? r[0].replace(e, "").trim() : "",
+ };
+ return o(/^[;\s]*/), s;
+ }
+ }
+ function p() {
+ if (!a()) return n("missing '{'");
+ for (var e, t = l(); (e = d()); ) t.push(e), (t = t.concat(l()));
+ return c() ? t : n("missing '}'");
+ }
+ function m() {
+ i();
+ for (
+ var e, t = [];
+ (e = o(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/));
+ )
+ t.push(e[1]), o(/^,\s*/);
+ if (t.length)
+ return { type: "keyframe", values: t, declarations: p() };
+ }
+ function v() {
+ if ((i(), "@" === t[0])) {
+ var e =
+ (function () {
+ var e = o(/^@([-\w]+)?keyframes\s*/);
+ if (e) {
+ var t = e[1];
+ if (!(e = o(/^([-\w]+)\s*/)))
+ return n("@keyframes missing name");
+ var r,
+ s = e[1];
+ if (!a()) return n("@keyframes missing '{'");
+ for (var i = l(); (r = m()); )
+ i.push(r), (i = i.concat(l()));
+ return c()
+ ? {
+ type: "keyframes",
+ name: s,
+ vendor: t,
+ keyframes: i,
+ }
+ : n("@keyframes missing '}'");
+ }
+ })() ||
+ (function () {
+ var e = o(/^@supports *([^{]+)/);
+ if (e)
+ return {
+ type: "supports",
+ supports: e[1].trim(),
+ rules: y(),
+ };
+ })() ||
+ (function () {
+ if (o(/^@host\s*/)) return { type: "host", rules: y() };
+ })() ||
+ (function () {
+ var e = o(/^@media([^{]+)*/);
+ if (e)
+ return {
+ type: "media",
+ media: (e[1] || "").trim(),
+ rules: y(),
+ };
+ })() ||
+ (function () {
+ var e = o(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/);
+ if (e)
+ return {
+ type: "custom-media",
+ name: e[1].trim(),
+ media: e[2].trim(),
+ };
+ })() ||
+ (function () {
+ if (o(/^@page */))
+ return {
+ type: "page",
+ selectors: f() || [],
+ declarations: p(),
+ };
+ })() ||
+ (function () {
+ var e = o(/^@([-\w]+)?document *([^{]+)/);
+ if (e)
+ return {
+ type: "document",
+ document: e[2].trim(),
+ vendor: e[1] ? e[1].trim() : null,
+ rules: y(),
+ };
+ })() ||
+ (function () {
+ if (o(/^@font-face\s*/))
+ return { type: "font-face", declarations: p() };
+ })() ||
+ (function () {
+ var e = o(/^@(import|charset|namespace)\s*([^;]+);/);
+ if (e) return { type: e[1], name: e[2].trim() };
+ })();
+ if (e && !r.preserveStatic) {
+ var s = !1;
+ if (e.declarations)
+ s = e.declarations.some(function (e) {
+ return /var\(/.test(e.value);
+ });
+ else
+ s = (e.keyframes || e.rules || []).some(function (e) {
+ return (e.declarations || []).some(function (e) {
+ return /var\(/.test(e.value);
+ });
+ });
+ return s ? e : {};
+ }
+ return e;
+ }
+ }
+ function h() {
+ if (!r.preserveStatic) {
+ var e = s("{", "}", t);
+ if (e) {
+ var o =
+ /:(?:root|host)(?![.:#(])/.test(e.pre) &&
+ /--\S*\s*:/.test(e.body),
+ a = /var\(/.test(e.body);
+ if (!o && !a) return (t = t.slice(e.end + 1)), {};
+ }
+ }
+ var c = f() || [],
+ i = r.preserveStatic
+ ? p()
+ : p().filter(function (e) {
+ var t =
+ c.some(function (e) {
+ return /:(?:root|host)(?![.:#(])/.test(
+ e,
+ );
+ }) && /^--\S/.test(e.property),
+ r = /var\(/.test(e.value);
+ return t || r;
+ });
+ return (
+ c.length || n("selector missing"),
+ { type: "rule", selectors: c, declarations: i }
+ );
+ }
+ function y(e) {
+ if (!e && !a()) return n("missing '{'");
+ for (
+ var r, o = l();
+ t.length && (e || "}" !== t[0]) && (r = v() || h());
+
+ )
+ r.type && o.push(r), (o = o.concat(l()));
+ return e || c() ? o : n("missing '}'");
+ }
+ return { type: "stylesheet", stylesheet: { rules: y(!0), errors: [] } };
+ }
+ function l(t) {
+ var r = e(
+ {},
+ { parseHost: !1, store: {}, onWarning: function () {} },
+ arguments.length > 1 && void 0 !== arguments[1]
+ ? arguments[1]
+ : {},
+ ),
+ n = new RegExp(
+ ":".concat(r.parseHost ? "host" : "root", "(?![.:#(])"),
+ );
+ return (
+ "string" == typeof t && (t = u(t, r)),
+ t.stylesheet.rules.forEach(function (e) {
+ "rule" === e.type &&
+ e.selectors.some(function (e) {
+ return n.test(e);
+ }) &&
+ e.declarations.forEach(function (e, t) {
+ var n = e.property,
+ o = e.value;
+ n && 0 === n.indexOf("--") && (r.store[n] = o);
+ });
+ }),
+ r.store
+ );
+ }
+ function f(e) {
+ var t =
+ arguments.length > 1 && void 0 !== arguments[1]
+ ? arguments[1]
+ : "",
+ r = arguments.length > 2 ? arguments[2] : void 0,
+ n = {
+ charset: function (e) {
+ return "@charset " + e.name + ";";
+ },
+ comment: function (e) {
+ return 0 === e.comment.indexOf("__CSSVARSPONYFILL")
+ ? "/*" + e.comment + "*/"
+ : "";
+ },
+ "custom-media": function (e) {
+ return "@custom-media " + e.name + " " + e.media + ";";
+ },
+ declaration: function (e) {
+ return e.property + ":" + e.value + ";";
+ },
+ document: function (e) {
+ return (
+ "@" +
+ (e.vendor || "") +
+ "document " +
+ e.document +
+ "{" +
+ o(e.rules) +
+ "}"
+ );
+ },
+ "font-face": function (e) {
+ return "@font-face{" + o(e.declarations) + "}";
+ },
+ host: function (e) {
+ return "@host{" + o(e.rules) + "}";
+ },
+ import: function (e) {
+ return "@import " + e.name + ";";
+ },
+ keyframe: function (e) {
+ return e.values.join(",") + "{" + o(e.declarations) + "}";
+ },
+ keyframes: function (e) {
+ return (
+ "@" +
+ (e.vendor || "") +
+ "keyframes " +
+ e.name +
+ "{" +
+ o(e.keyframes) +
+ "}"
+ );
+ },
+ media: function (e) {
+ return "@media " + e.media + "{" + o(e.rules) + "}";
+ },
+ namespace: function (e) {
+ return "@namespace " + e.name + ";";
+ },
+ page: function (e) {
+ return (
+ "@page " +
+ (e.selectors.length ? e.selectors.join(", ") : "") +
+ "{" +
+ o(e.declarations) +
+ "}"
+ );
+ },
+ rule: function (e) {
+ var t = e.declarations;
+ if (t.length)
+ return e.selectors.join(",") + "{" + o(t) + "}";
+ },
+ supports: function (e) {
+ return "@supports " + e.supports + "{" + o(e.rules) + "}";
+ },
+ };
+ function o(e) {
+ for (var o = "", s = 0; s < e.length; s++) {
+ var a = e[s];
+ r && r(a);
+ var c = n[a.type](a);
+ c && ((o += c), c.length && a.selectors && (o += t));
+ }
+ return o;
+ }
+ return o(e.stylesheet.rules);
+ }
+ a.range = i;
+ var d = "--",
+ p = "var";
+ function m(t) {
+ var r = e(
+ {},
+ {
+ preserveStatic: !0,
+ preserveVars: !1,
+ variables: {},
+ onWarning: function () {},
+ },
+ arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {},
+ );
+ return (
+ "string" == typeof t && (t = u(t, r)),
+ (function e(t, r) {
+ t.rules.forEach(function (n) {
+ n.rules
+ ? e(n, r)
+ : n.keyframes
+ ? n.keyframes.forEach(function (e) {
+ "keyframe" === e.type &&
+ r(e.declarations, n);
+ })
+ : n.declarations && r(n.declarations, t);
+ });
+ })(t.stylesheet, function (e, t) {
+ for (var n = 0; n < e.length; n++) {
+ var o = e[n],
+ s = o.type,
+ a = o.property,
+ c = o.value;
+ if ("declaration" === s)
+ if (r.preserveVars || !a || 0 !== a.indexOf(d)) {
+ if (-1 !== c.indexOf(p + "(")) {
+ var i = h(c, r);
+ i !== o.value &&
+ ((i = v(i)),
+ r.preserveVars
+ ? (e.splice(n, 0, {
+ type: s,
+ property: a,
+ value: i,
+ }),
+ n++)
+ : (o.value = i));
+ }
+ } else e.splice(n, 1), n--;
+ }
+ }),
+ f(t)
+ );
+ }
+ function v(e) {
+ return (
+ (e.match(/calc\(([^)]+)\)/g) || []).forEach(function (t) {
+ var r = "calc".concat(t.split("calc").join(""));
+ e = e.replace(t, r);
+ }),
+ e
+ );
+ }
+ function h(e) {
+ var t =
+ arguments.length > 1 && void 0 !== arguments[1]
+ ? arguments[1]
+ : {},
+ r = arguments.length > 2 ? arguments[2] : void 0;
+ if (-1 === e.indexOf("var(")) return e;
+ var n = s("(", ")", e);
+ return n
+ ? "var" === n.pre.slice(-3)
+ ? 0 === n.body.trim().length
+ ? (t.onWarning(
+ "var() must contain a non-whitespace string",
+ ),
+ e)
+ : n.pre.slice(0, -3) +
+ (function (e) {
+ var n = e.split(",")[0].replace(/[\s\n\t]/g, ""),
+ o = (e.match(/(?:\s*,\s*){1}(.*)?/) || [])[1],
+ s = Object.prototype.hasOwnProperty.call(
+ t.variables,
+ n,
+ )
+ ? String(t.variables[n])
+ : void 0,
+ a = s || (o ? String(o) : void 0),
+ c = r || e;
+ return (
+ s ||
+ t.onWarning(
+ 'variable "'.concat(
+ n,
+ '" is undefined',
+ ),
+ ),
+ a && "undefined" !== a && a.length > 0
+ ? h(a, t, c)
+ : "var(".concat(c, ")")
+ );
+ })(n.body) +
+ h(n.post, t)
+ : n.pre + "(".concat(h(n.body, t), ")") + h(n.post, t)
+ : (-1 !== e.indexOf("var(") &&
+ t.onWarning(
+ 'missing closing ")" in the value "'.concat(e, '"'),
+ ),
+ e);
+ }
+ var y = "undefined" != typeof window,
+ g =
+ y &&
+ window.CSS &&
+ window.CSS.supports &&
+ window.CSS.supports("(--a: 0)"),
+ S = { group: 0, job: 0 },
+ b = {
+ rootElement: y ? document : null,
+ shadowDOM: !1,
+ include: "style,link[rel=stylesheet]",
+ exclude: "",
+ variables: {},
+ onlyLegacy: !0,
+ preserveStatic: !0,
+ preserveVars: !1,
+ silent: !1,
+ updateDOM: !0,
+ updateURLs: !0,
+ watch: null,
+ onBeforeSend: function () {},
+ onWarning: function () {},
+ onError: function () {},
+ onSuccess: function () {},
+ onComplete: function () {},
+ },
+ E = {
+ cssComments: /\/\*[\s\S]+?\*\//g,
+ cssKeyframes: /@(?:-\w*-)?keyframes/,
+ cssMediaQueries: /@media[^{]+\{([\s\S]+?})\s*}/g,
+ cssUrls: /url\((?!['"]?(?:data|http|\/\/):)['"]?([^'")]*)['"]?\)/g,
+ cssVarDeclRules:
+ /(?::(?:root|host)(?![.:#(])[\s,]*[^{]*{\s*[^}]*})/g,
+ cssVarDecls: /(?:[\s;]*)(-{2}\w[\w-]*)(?:\s*:\s*)([^;]*);/g,
+ cssVarFunc: /var\(\s*--[\w-]/,
+ cssVars:
+ /(?:(?::(?:root|host)(?![.:#(])[\s,]*[^{]*{\s*[^;]*;*\s*)|(?:var\(\s*))(--[^:)]+)(?:\s*[:)])/,
+ },
+ w = { dom: {}, job: {}, user: {} },
+ C = !1,
+ O = null,
+ A = 0,
+ x = null,
+ j = !1;
+ function k() {
+ var r =
+ arguments.length > 0 && void 0 !== arguments[0]
+ ? arguments[0]
+ : {},
+ o = "cssVars(): ",
+ s = e({}, b, r);
+ function a(e, t, r, n) {
+ !s.silent &&
+ window.console &&
+ console.error("".concat(o).concat(e, "\n"), t),
+ s.onError(e, t, r, n);
+ }
+ function c(e) {
+ !s.silent && window.console && console.warn("".concat(o).concat(e)),
+ s.onWarning(e);
+ }
+ if (y) {
+ if (s.watch)
+ return (
+ (s.watch = b.watch),
+ (function (e) {
+ function t(e) {
+ return (
+ "LINK" === e.tagName &&
+ -1 !==
+ (e.getAttribute("rel") || "").indexOf(
+ "stylesheet",
+ ) &&
+ !e.disabled
+ );
+ }
+ if (!window.MutationObserver) return;
+ O && (O.disconnect(), (O = null));
+ (O = new MutationObserver(function (r) {
+ r.some(function (r) {
+ var n,
+ o = !1;
+ return (
+ "attributes" === r.type
+ ? (o = t(r.target))
+ : "childList" === r.type &&
+ ((n = r.addedNodes),
+ (o =
+ Array.apply(null, n).some(
+ function (e) {
+ var r =
+ 1 ===
+ e.nodeType &&
+ e.hasAttribute(
+ "data-cssvars",
+ ),
+ n =
+ (function (e) {
+ return (
+ "STYLE" ===
+ e.tagName &&
+ !e.disabled
+ );
+ })(e) &&
+ E.cssVars.test(
+ e.textContent,
+ );
+ return (
+ !r && (t(e) || n)
+ );
+ },
+ ) ||
+ (function (t) {
+ return Array.apply(
+ null,
+ t,
+ ).some(function (t) {
+ var r =
+ 1 ===
+ t.nodeType,
+ n =
+ r &&
+ "out" ===
+ t.getAttribute(
+ "data-cssvars",
+ ),
+ o =
+ r &&
+ "src" ===
+ t.getAttribute(
+ "data-cssvars",
+ ),
+ s = o;
+ if (o || n) {
+ var a =
+ t.getAttribute(
+ "data-cssvars-group",
+ ),
+ c =
+ e.rootElement.querySelector(
+ '[data-cssvars-group="'.concat(
+ a,
+ '"]',
+ ),
+ );
+ o &&
+ (L(
+ e.rootElement,
+ ),
+ (w.dom = {})),
+ c &&
+ c.parentNode.removeChild(
+ c,
+ );
+ }
+ return s;
+ });
+ })(r.removedNodes))),
+ o
+ );
+ }) && k(e);
+ })).observe(document.documentElement, {
+ attributes: !0,
+ attributeFilter: ["disabled", "href"],
+ childList: !0,
+ subtree: !0,
+ });
+ })(s),
+ void k(s)
+ );
+ if (
+ (!1 === s.watch && O && (O.disconnect(), (O = null)),
+ !s.__benchmark)
+ ) {
+ if (C === s.rootElement)
+ return void (function (e) {
+ var t =
+ arguments.length > 1 && void 0 !== arguments[1]
+ ? arguments[1]
+ : 100;
+ clearTimeout(x),
+ (x = setTimeout(function () {
+ (e.__benchmark = null), k(e);
+ }, t));
+ })(r);
+ if (
+ ((s.__benchmark = T()),
+ (s.exclude = [
+ O
+ ? '[data-cssvars]:not([data-cssvars=""])'
+ : '[data-cssvars="out"]',
+ s.exclude,
+ ]
+ .filter(function (e) {
+ return e;
+ })
+ .join(",")),
+ (s.variables = (function () {
+ var e =
+ arguments.length > 0 && void 0 !== arguments[0]
+ ? arguments[0]
+ : {},
+ t = /^-{2}/;
+ return Object.keys(e).reduce(function (r, n) {
+ return (
+ (r[
+ t.test(n)
+ ? n
+ : "--".concat(n.replace(/^-+/, ""))
+ ] = e[n]),
+ r
+ );
+ }, {});
+ })(s.variables)),
+ !O)
+ )
+ if (
+ (Array.apply(
+ null,
+ s.rootElement.querySelectorAll(
+ '[data-cssvars="out"]',
+ ),
+ ).forEach(function (e) {
+ var t = e.getAttribute("data-cssvars-group");
+ (t
+ ? s.rootElement.querySelector(
+ '[data-cssvars="src"][data-cssvars-group="'.concat(
+ t,
+ '"]',
+ ),
+ )
+ : null) || e.parentNode.removeChild(e);
+ }),
+ A)
+ ) {
+ var i = s.rootElement.querySelectorAll(
+ '[data-cssvars]:not([data-cssvars="out"])',
+ );
+ i.length < A && ((A = i.length), (w.dom = {}));
+ }
+ }
+ if ("loading" !== document.readyState)
+ if (g && s.onlyLegacy) {
+ if (s.updateDOM) {
+ var d =
+ s.rootElement.host ||
+ (s.rootElement === document
+ ? document.documentElement
+ : s.rootElement);
+ Object.keys(s.variables).forEach(function (e) {
+ d.style.setProperty(e, s.variables[e]);
+ });
+ }
+ } else
+ !j &&
+ (s.shadowDOM ||
+ s.rootElement.shadowRoot ||
+ s.rootElement.host)
+ ? n({
+ rootElement: b.rootElement,
+ include: b.include,
+ exclude: s.exclude,
+ onSuccess: function (e, t, r) {
+ return (
+ (e = (
+ (e = e
+ .replace(E.cssComments, "")
+ .replace(
+ E.cssMediaQueries,
+ "",
+ )).match(E.cssVarDeclRules) ||
+ []
+ ).join("")) || !1
+ );
+ },
+ onComplete: function (e, t, r) {
+ l(e, { store: w.dom, onWarning: c }),
+ (j = !0),
+ k(s);
+ },
+ })
+ : ((C = s.rootElement),
+ n({
+ rootElement: s.rootElement,
+ include: s.include,
+ exclude: s.exclude,
+ onBeforeSend: s.onBeforeSend,
+ onError: function (e, t, r) {
+ var n =
+ e.responseURL ||
+ _(r, location.href),
+ o = e.statusText
+ ? "(".concat(e.statusText, ")")
+ : "Unspecified Error" +
+ (0 === e.status
+ ? " (possibly CORS related)"
+ : "");
+ a(
+ "CSS XHR Error: "
+ .concat(n, " ")
+ .concat(e.status, " ")
+ .concat(o),
+ t,
+ e,
+ n,
+ );
+ },
+ onSuccess: function (e, t, r) {
+ var n = s.onSuccess(e, t, r);
+ return (
+ (e =
+ void 0 !== n && !1 === Boolean(n)
+ ? ""
+ : n || e),
+ s.updateURLs &&
+ (e = (function (e, t) {
+ return (
+ (
+ e
+ .replace(
+ E.cssComments,
+ "",
+ )
+ .match(E.cssUrls) ||
+ []
+ ).forEach(function (r) {
+ var n = r.replace(
+ E.cssUrls,
+ "$1",
+ ),
+ o = _(n, t);
+ e = e.replace(
+ r,
+ r.replace(n, o),
+ );
+ }),
+ e
+ );
+ })(e, r)),
+ e
+ );
+ },
+ onComplete: function (r, n) {
+ var o =
+ arguments.length > 2 &&
+ void 0 !== arguments[2]
+ ? arguments[2]
+ : [],
+ i = {},
+ d = s.updateDOM
+ ? w.dom
+ : Object.keys(w.job).length
+ ? w.job
+ : (w.job = JSON.parse(
+ JSON.stringify(w.dom),
+ )),
+ p = !1;
+ if (
+ (o.forEach(function (e, t) {
+ if (E.cssVars.test(n[t]))
+ try {
+ var r = u(n[t], {
+ preserveStatic:
+ s.preserveStatic,
+ removeComments: !0,
+ });
+ l(r, {
+ parseHost: Boolean(
+ s.rootElement.host,
+ ),
+ store: i,
+ onWarning: c,
+ }),
+ (e.__cssVars = {
+ tree: r,
+ });
+ } catch (t) {
+ a(t.message, e);
+ }
+ }),
+ s.updateDOM && e(w.user, s.variables),
+ e(i, s.variables),
+ (p = Boolean(
+ (document.querySelector(
+ "[data-cssvars]",
+ ) ||
+ Object.keys(w.dom).length) &&
+ Object.keys(i).some(
+ function (e) {
+ return i[e] !== d[e];
+ },
+ ),
+ )),
+ e(d, w.user, i),
+ p)
+ )
+ L(s.rootElement), k(s);
+ else {
+ var v = [],
+ h = [],
+ y = !1;
+ if (
+ ((w.job = {}),
+ s.updateDOM && S.job++,
+ o.forEach(function (t) {
+ var r = !t.__cssVars;
+ if (t.__cssVars)
+ try {
+ m(
+ t.__cssVars.tree,
+ e({}, s, {
+ variables: d,
+ onWarning: c,
+ }),
+ );
+ var n = f(
+ t.__cssVars.tree,
+ );
+ if (s.updateDOM) {
+ if (
+ (t.getAttribute(
+ "data-cssvars",
+ ) ||
+ t.setAttribute(
+ "data-cssvars",
+ "src",
+ ),
+ n.length)
+ ) {
+ var o =
+ t.getAttribute(
+ "data-cssvars-group",
+ ) ||
+ ++S.group,
+ i =
+ n.replace(
+ /\s/g,
+ "",
+ ),
+ u =
+ s.rootElement.querySelector(
+ '[data-cssvars="out"][data-cssvars-group="'.concat(
+ o,
+ '"]',
+ ),
+ ) ||
+ document.createElement(
+ "style",
+ );
+ (y =
+ y ||
+ E.cssKeyframes.test(
+ n,
+ )),
+ u.hasAttribute(
+ "data-cssvars",
+ ) ||
+ u.setAttribute(
+ "data-cssvars",
+ "out",
+ ),
+ i ===
+ t.textContent.replace(
+ /\s/g,
+ "",
+ )
+ ? ((r =
+ !0),
+ u &&
+ u.parentNode &&
+ (t.removeAttribute(
+ "data-cssvars-group",
+ ),
+ u.parentNode.removeChild(
+ u,
+ )))
+ : i !==
+ u.textContent.replace(
+ /\s/g,
+ "",
+ ) &&
+ ([
+ t,
+ u,
+ ].forEach(
+ function (
+ e,
+ ) {
+ e.setAttribute(
+ "data-cssvars-job",
+ S.job,
+ ),
+ e.setAttribute(
+ "data-cssvars-group",
+ o,
+ );
+ },
+ ),
+ (u.textContent =
+ n),
+ v.push(
+ n,
+ ),
+ h.push(
+ u,
+ ),
+ u.parentNode ||
+ t.parentNode.insertBefore(
+ u,
+ t.nextSibling,
+ ));
+ }
+ } else
+ t.textContent.replace(
+ /\s/g,
+ "",
+ ) !== n &&
+ v.push(n);
+ } catch (e) {
+ a(e.message, t);
+ }
+ r &&
+ t.setAttribute(
+ "data-cssvars",
+ "skip",
+ ),
+ t.hasAttribute(
+ "data-cssvars-job",
+ ) ||
+ t.setAttribute(
+ "data-cssvars-job",
+ S.job,
+ );
+ }),
+ (A = s.rootElement.querySelectorAll(
+ '[data-cssvars]:not([data-cssvars="out"])',
+ ).length),
+ s.shadowDOM)
+ )
+ for (
+ var g,
+ b = [s.rootElement].concat(
+ t(
+ s.rootElement.querySelectorAll(
+ "*",
+ ),
+ ),
+ ),
+ O = 0;
+ (g = b[O]);
+ ++O
+ )
+ if (
+ g.shadowRoot &&
+ g.shadowRoot.querySelector(
+ "style",
+ )
+ ) {
+ var x = e({}, s, {
+ rootElement:
+ g.shadowRoot,
+ });
+ k(x);
+ }
+ s.updateDOM && y && M(s.rootElement),
+ (C = !1),
+ s.onComplete(
+ v.join(""),
+ h,
+ JSON.parse(JSON.stringify(d)),
+ T() - s.__benchmark,
+ );
+ }
+ },
+ }));
+ else
+ document.addEventListener("DOMContentLoaded", function e(t) {
+ k(r), document.removeEventListener("DOMContentLoaded", e);
+ });
+ }
+ }
+ function M(e) {
+ var t = [
+ "animation-name",
+ "-moz-animation-name",
+ "-webkit-animation-name",
+ ].filter(function (e) {
+ return getComputedStyle(document.body)[e];
+ })[0];
+ if (t) {
+ for (
+ var r = e.getElementsByTagName("*"),
+ n = [],
+ o = 0,
+ s = r.length;
+ o < s;
+ o++
+ ) {
+ var a = r[o];
+ "none" !== getComputedStyle(a)[t] &&
+ ((a.style[t] += "__CSSVARSPONYFILL-KEYFRAMES__"),
+ n.push(a));
+ }
+ document.body.offsetHeight;
+ for (var c = 0, i = n.length; c < i; c++) {
+ var u = n[c].style;
+ u[t] = u[t].replace("__CSSVARSPONYFILL-KEYFRAMES__", "");
+ }
+ }
+ }
+ function _(e) {
+ var t =
+ arguments.length > 1 && void 0 !== arguments[1]
+ ? arguments[1]
+ : location.href,
+ r = document.implementation.createHTMLDocument(""),
+ n = r.createElement("base"),
+ o = r.createElement("a");
+ return (
+ r.head.appendChild(n),
+ r.body.appendChild(o),
+ (n.href = t),
+ (o.href = e),
+ o.href
+ );
+ }
+ function T() {
+ return y && (window.performance || {}).now
+ ? window.performance.now()
+ : new Date().getTime();
+ }
+ function L(e) {
+ Array.apply(
+ null,
+ e.querySelectorAll('[data-cssvars="skip"],[data-cssvars="src"]'),
+ ).forEach(function (e) {
+ return e.setAttribute("data-cssvars", "");
+ });
+ }
+ return (
+ (k.reset = function () {
+ for (var e in ((C = !1),
+ O && (O.disconnect(), (O = null)),
+ (A = 0),
+ (x = null),
+ (j = !1),
+ w))
+ w[e] = {};
+ }),
+ k
+ );
+});
// Default values
cssVars({
- // Targets
- rootElement: document,
- shadowDOM: false,
+ // Targets
+ rootElement: document,
+ shadowDOM: false,
- // Sources
- include: 'link[rel=stylesheet],style',
- exclude: '',
- variables: {},
+ // Sources
+ include: "link[rel=stylesheet],style",
+ exclude: "",
+ variables: {},
- // Options
- onlyLegacy: true,
- preserveStatic: true,
- preserveVars: false,
- silent: false,
- updateDOM: true,
- updateURLs: true,
- watch: false,
+ // Options
+ onlyLegacy: true,
+ preserveStatic: true,
+ preserveVars: false,
+ silent: false,
+ updateDOM: true,
+ updateURLs: true,
+ watch: false,
- // Callbacks
- onBeforeSend(xhr, elm, url) {
- // ...
- },
- onWarning(message) {
- // ...
- },
- onError(message, elm, xhr, url) {
- // ...
- },
- onSuccess(cssText, elm, url) {
- // ...
- },
- onComplete(cssText, styleElms, cssVariables, benchmark) {
- // ...
- }
+ // Callbacks
+ onBeforeSend(xhr, elm, url) {
+ // ...
+ },
+ onWarning(message) {
+ // ...
+ },
+ onError(message, elm, xhr, url) {
+ // ...
+ },
+ onSuccess(cssText, elm, url) {
+ // ...
+ },
+ onComplete(cssText, styleElms, cssVariables, benchmark) {
+ // ...
+ },
});
diff --git a/docs/src/assets/js/focus-visible.js b/docs/src/assets/js/focus-visible.js
index c95845112cf4..da377d4b3331 100644
--- a/docs/src/assets/js/focus-visible.js
+++ b/docs/src/assets/js/focus-visible.js
@@ -1,4 +1,3 @@
-
/**
* Applies the :focus-visible polyfill at the given scope.
* A scope in this case is either the top-level Document or a Shadow Root.
@@ -7,299 +6,299 @@
* @see https://github.com/WICG/focus-visible
*/
function applyFocusVisiblePolyfill(scope) {
- var hadKeyboardEvent = true;
- var hadFocusVisibleRecently = false;
- var hadFocusVisibleRecentlyTimeout = null;
-
- var inputTypesWhitelist = {
- text: true,
- search: true,
- url: true,
- tel: true,
- email: true,
- password: true,
- number: true,
- date: true,
- month: true,
- week: true,
- time: true,
- datetime: true,
- 'datetime-local': true
- };
-
- /**
- * Helper function for legacy browsers and iframes which sometimes focus
- * elements like document, body, and non-interactive SVG.
- * @param {Element} el
- */
- function isValidFocusTarget(el) {
- if (
- el &&
- el !== document &&
- el.nodeName !== 'HTML' &&
- el.nodeName !== 'BODY' &&
- 'classList' in el &&
- 'contains' in el.classList
- ) {
- return true;
- }
- return false;
- }
-
- /**
- * Computes whether the given element should automatically trigger the
- * `focus-visible` class being added, i.e. whether it should always match
- * `:focus-visible` when focused.
- * @param {Element} el
- * @return {boolean}
- */
- function focusTriggersKeyboardModality(el) {
- var type = el.type;
- var tagName = el.tagName;
-
- if (tagName === 'INPUT' && inputTypesWhitelist[type] && !el.readOnly) {
- return true;
- }
-
- if (tagName === 'TEXTAREA' && !el.readOnly) {
- return true;
- }
-
- if (el.isContentEditable) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Add the `focus-visible` class to the given element if it was not added by
- * the author.
- * @param {Element} el
- */
- function addFocusVisibleClass(el) {
- if (el.classList.contains('focus-visible')) {
- return;
- }
- el.classList.add('focus-visible');
- el.setAttribute('data-focus-visible-added', '');
- }
-
- /**
- * Remove the `focus-visible` class from the given element if it was not
- * originally added by the author.
- * @param {Element} el
- */
- function removeFocusVisibleClass(el) {
- if (!el.hasAttribute('data-focus-visible-added')) {
- return;
- }
- el.classList.remove('focus-visible');
- el.removeAttribute('data-focus-visible-added');
- }
-
- /**
- * If the most recent user interaction was via the keyboard;
- * and the key press did not include a meta, alt/option, or control key;
- * then the modality is keyboard. Otherwise, the modality is not keyboard.
- * Apply `focus-visible` to any current active element and keep track
- * of our keyboard modality state with `hadKeyboardEvent`.
- * @param {KeyboardEvent} e
- */
- function onKeyDown(e) {
- if (e.metaKey || e.altKey || e.ctrlKey) {
- return;
- }
-
- if (isValidFocusTarget(scope.activeElement)) {
- addFocusVisibleClass(scope.activeElement);
- }
-
- hadKeyboardEvent = true;
- }
-
- /**
- * If at any point a user clicks with a pointing device, ensure that we change
- * the modality away from keyboard.
- * This avoids the situation where a user presses a key on an already focused
- * element, and then clicks on a different element, focusing it with a
- * pointing device, while we still think we're in keyboard modality.
- * @param {Event} e
- */
- function onPointerDown(e) {
- hadKeyboardEvent = false;
- }
-
- /**
- * On `focus`, add the `focus-visible` class to the target if:
- * - the target received focus as a result of keyboard navigation, or
- * - the event target is an element that will likely require interaction
- * via the keyboard (e.g. a text box)
- * @param {Event} e
- */
- function onFocus(e) {
- // Prevent IE from focusing the document or HTML element.
- if (!isValidFocusTarget(e.target)) {
- return;
- }
-
- if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {
- addFocusVisibleClass(e.target);
- }
- }
-
- /**
- * On `blur`, remove the `focus-visible` class from the target.
- * @param {Event} e
- */
- function onBlur(e) {
- if (!isValidFocusTarget(e.target)) {
- return;
- }
-
- if (
- e.target.classList.contains('focus-visible') ||
- e.target.hasAttribute('data-focus-visible-added')
- ) {
- // To detect a tab/window switch, we look for a blur event followed
- // rapidly by a visibility change.
- // If we don't see a visibility change within 100ms, it's probably a
- // regular focus change.
- hadFocusVisibleRecently = true;
- window.clearTimeout(hadFocusVisibleRecentlyTimeout);
- hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {
- hadFocusVisibleRecently = false;
- window.clearTimeout(hadFocusVisibleRecentlyTimeout);
- }, 100);
- removeFocusVisibleClass(e.target);
- }
- }
-
- /**
- * If the user changes tabs, keep track of whether or not the previously
- * focused element had .focus-visible.
- * @param {Event} e
- */
- function onVisibilityChange(e) {
- if (document.visibilityState === 'hidden') {
- // If the tab becomes active again, the browser will handle calling focus
- // on the element (Safari actually calls it twice).
- // If this tab change caused a blur on an element with focus-visible,
- // re-apply the class when the user switches back to the tab.
- if (hadFocusVisibleRecently) {
- hadKeyboardEvent = true;
- }
- addInitialPointerMoveListeners();
- }
- }
-
- /**
- * Add a group of listeners to detect usage of any pointing devices.
- * These listeners will be added when the polyfill first loads, and anytime
- * the window is blurred, so that they are active when the window regains
- * focus.
- */
- function addInitialPointerMoveListeners() {
- document.addEventListener('mousemove', onInitialPointerMove);
- document.addEventListener('mousedown', onInitialPointerMove);
- document.addEventListener('mouseup', onInitialPointerMove);
- document.addEventListener('pointermove', onInitialPointerMove);
- document.addEventListener('pointerdown', onInitialPointerMove);
- document.addEventListener('pointerup', onInitialPointerMove);
- document.addEventListener('touchmove', onInitialPointerMove);
- document.addEventListener('touchstart', onInitialPointerMove);
- document.addEventListener('touchend', onInitialPointerMove);
- }
-
- function removeInitialPointerMoveListeners() {
- document.removeEventListener('mousemove', onInitialPointerMove);
- document.removeEventListener('mousedown', onInitialPointerMove);
- document.removeEventListener('mouseup', onInitialPointerMove);
- document.removeEventListener('pointermove', onInitialPointerMove);
- document.removeEventListener('pointerdown', onInitialPointerMove);
- document.removeEventListener('pointerup', onInitialPointerMove);
- document.removeEventListener('touchmove', onInitialPointerMove);
- document.removeEventListener('touchstart', onInitialPointerMove);
- document.removeEventListener('touchend', onInitialPointerMove);
- }
-
- /**
- * When the polyfill first loads, assume the user is in keyboard modality.
- * If any event is received from a pointing device (e.g. mouse, pointer,
- * touch), turn off keyboard modality.
- * This accounts for situations where focus enters the page from the URL bar.
- * @param {Event} e
- */
- function onInitialPointerMove(e) {
- // Work around a Safari quirk that fires a mousemove on whenever the
- // window blurs, even if you're tabbing out of the page. ¯\_(ã)_/¯
- if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {
- return;
- }
-
- hadKeyboardEvent = false;
- removeInitialPointerMoveListeners();
- }
-
- // For some kinds of state, we are interested in changes at the global scope
- // only. For example, global pointer input, global key presses and global
- // visibility change should affect the state at every scope:
- document.addEventListener('keydown', onKeyDown, true);
- document.addEventListener('mousedown', onPointerDown, true);
- document.addEventListener('pointerdown', onPointerDown, true);
- document.addEventListener('touchstart', onPointerDown, true);
- document.addEventListener('visibilitychange', onVisibilityChange, true);
-
- addInitialPointerMoveListeners();
-
- // For focus and blur, we specifically care about state changes in the local
- // scope. This is because focus / blur events that originate from within a
- // shadow root are not re-dispatched from the host element if it was already
- // the active element in its own scope:
- scope.addEventListener('focus', onFocus, true);
- scope.addEventListener('blur', onBlur, true);
-
- // We detect that a node is a ShadowRoot by ensuring that it is a
- // DocumentFragment and also has a host property. This check covers native
- // implementation and polyfill implementation transparently. If we only cared
- // about the native implementation, we could just check if the scope was
- // an instance of a ShadowRoot.
- if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {
- // Since a ShadowRoot is a special kind of DocumentFragment, it does not
- // have a root element to add a class to. So, we add this attribute to the
- // host element instead:
- scope.host.setAttribute('data-js-focus-visible', '');
- } else if (scope.nodeType === Node.DOCUMENT_NODE) {
- document.documentElement.classList.add('js-focus-visible');
- }
+ var hadKeyboardEvent = true;
+ var hadFocusVisibleRecently = false;
+ var hadFocusVisibleRecentlyTimeout = null;
+
+ var inputTypesWhitelist = {
+ text: true,
+ search: true,
+ url: true,
+ tel: true,
+ email: true,
+ password: true,
+ number: true,
+ date: true,
+ month: true,
+ week: true,
+ time: true,
+ datetime: true,
+ "datetime-local": true,
+ };
+
+ /**
+ * Helper function for legacy browsers and iframes which sometimes focus
+ * elements like document, body, and non-interactive SVG.
+ * @param {Element} el
+ */
+ function isValidFocusTarget(el) {
+ if (
+ el &&
+ el !== document &&
+ el.nodeName !== "HTML" &&
+ el.nodeName !== "BODY" &&
+ "classList" in el &&
+ "contains" in el.classList
+ ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Computes whether the given element should automatically trigger the
+ * `focus-visible` class being added, i.e. whether it should always match
+ * `:focus-visible` when focused.
+ * @param {Element} el
+ * @return {boolean}
+ */
+ function focusTriggersKeyboardModality(el) {
+ var type = el.type;
+ var tagName = el.tagName;
+
+ if (tagName === "INPUT" && inputTypesWhitelist[type] && !el.readOnly) {
+ return true;
+ }
+
+ if (tagName === "TEXTAREA" && !el.readOnly) {
+ return true;
+ }
+
+ if (el.isContentEditable) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Add the `focus-visible` class to the given element if it was not added by
+ * the author.
+ * @param {Element} el
+ */
+ function addFocusVisibleClass(el) {
+ if (el.classList.contains("focus-visible")) {
+ return;
+ }
+ el.classList.add("focus-visible");
+ el.setAttribute("data-focus-visible-added", "");
+ }
+
+ /**
+ * Remove the `focus-visible` class from the given element if it was not
+ * originally added by the author.
+ * @param {Element} el
+ */
+ function removeFocusVisibleClass(el) {
+ if (!el.hasAttribute("data-focus-visible-added")) {
+ return;
+ }
+ el.classList.remove("focus-visible");
+ el.removeAttribute("data-focus-visible-added");
+ }
+
+ /**
+ * If the most recent user interaction was via the keyboard;
+ * and the key press did not include a meta, alt/option, or control key;
+ * then the modality is keyboard. Otherwise, the modality is not keyboard.
+ * Apply `focus-visible` to any current active element and keep track
+ * of our keyboard modality state with `hadKeyboardEvent`.
+ * @param {KeyboardEvent} e
+ */
+ function onKeyDown(e) {
+ if (e.metaKey || e.altKey || e.ctrlKey) {
+ return;
+ }
+
+ if (isValidFocusTarget(scope.activeElement)) {
+ addFocusVisibleClass(scope.activeElement);
+ }
+
+ hadKeyboardEvent = true;
+ }
+
+ /**
+ * If at any point a user clicks with a pointing device, ensure that we change
+ * the modality away from keyboard.
+ * This avoids the situation where a user presses a key on an already focused
+ * element, and then clicks on a different element, focusing it with a
+ * pointing device, while we still think we're in keyboard modality.
+ * @param {Event} e
+ */
+ function onPointerDown(e) {
+ hadKeyboardEvent = false;
+ }
+
+ /**
+ * On `focus`, add the `focus-visible` class to the target if:
+ * - the target received focus as a result of keyboard navigation, or
+ * - the event target is an element that will likely require interaction
+ * via the keyboard (e.g. a text box)
+ * @param {Event} e
+ */
+ function onFocus(e) {
+ // Prevent IE from focusing the document or HTML element.
+ if (!isValidFocusTarget(e.target)) {
+ return;
+ }
+
+ if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {
+ addFocusVisibleClass(e.target);
+ }
+ }
+
+ /**
+ * On `blur`, remove the `focus-visible` class from the target.
+ * @param {Event} e
+ */
+ function onBlur(e) {
+ if (!isValidFocusTarget(e.target)) {
+ return;
+ }
+
+ if (
+ e.target.classList.contains("focus-visible") ||
+ e.target.hasAttribute("data-focus-visible-added")
+ ) {
+ // To detect a tab/window switch, we look for a blur event followed
+ // rapidly by a visibility change.
+ // If we don't see a visibility change within 100ms, it's probably a
+ // regular focus change.
+ hadFocusVisibleRecently = true;
+ window.clearTimeout(hadFocusVisibleRecentlyTimeout);
+ hadFocusVisibleRecentlyTimeout = window.setTimeout(function () {
+ hadFocusVisibleRecently = false;
+ window.clearTimeout(hadFocusVisibleRecentlyTimeout);
+ }, 100);
+ removeFocusVisibleClass(e.target);
+ }
+ }
+
+ /**
+ * If the user changes tabs, keep track of whether or not the previously
+ * focused element had .focus-visible.
+ * @param {Event} e
+ */
+ function onVisibilityChange(e) {
+ if (document.visibilityState === "hidden") {
+ // If the tab becomes active again, the browser will handle calling focus
+ // on the element (Safari actually calls it twice).
+ // If this tab change caused a blur on an element with focus-visible,
+ // re-apply the class when the user switches back to the tab.
+ if (hadFocusVisibleRecently) {
+ hadKeyboardEvent = true;
+ }
+ addInitialPointerMoveListeners();
+ }
+ }
+
+ /**
+ * Add a group of listeners to detect usage of any pointing devices.
+ * These listeners will be added when the polyfill first loads, and anytime
+ * the window is blurred, so that they are active when the window regains
+ * focus.
+ */
+ function addInitialPointerMoveListeners() {
+ document.addEventListener("mousemove", onInitialPointerMove);
+ document.addEventListener("mousedown", onInitialPointerMove);
+ document.addEventListener("mouseup", onInitialPointerMove);
+ document.addEventListener("pointermove", onInitialPointerMove);
+ document.addEventListener("pointerdown", onInitialPointerMove);
+ document.addEventListener("pointerup", onInitialPointerMove);
+ document.addEventListener("touchmove", onInitialPointerMove);
+ document.addEventListener("touchstart", onInitialPointerMove);
+ document.addEventListener("touchend", onInitialPointerMove);
+ }
+
+ function removeInitialPointerMoveListeners() {
+ document.removeEventListener("mousemove", onInitialPointerMove);
+ document.removeEventListener("mousedown", onInitialPointerMove);
+ document.removeEventListener("mouseup", onInitialPointerMove);
+ document.removeEventListener("pointermove", onInitialPointerMove);
+ document.removeEventListener("pointerdown", onInitialPointerMove);
+ document.removeEventListener("pointerup", onInitialPointerMove);
+ document.removeEventListener("touchmove", onInitialPointerMove);
+ document.removeEventListener("touchstart", onInitialPointerMove);
+ document.removeEventListener("touchend", onInitialPointerMove);
+ }
+
+ /**
+ * When the polyfill first loads, assume the user is in keyboard modality.
+ * If any event is received from a pointing device (e.g. mouse, pointer,
+ * touch), turn off keyboard modality.
+ * This accounts for situations where focus enters the page from the URL bar.
+ * @param {Event} e
+ */
+ function onInitialPointerMove(e) {
+ // Work around a Safari quirk that fires a mousemove on whenever the
+ // window blurs, even if you're tabbing out of the page. ¯\_(ã)_/¯
+ if (e.target.nodeName && e.target.nodeName.toLowerCase() === "html") {
+ return;
+ }
+
+ hadKeyboardEvent = false;
+ removeInitialPointerMoveListeners();
+ }
+
+ // For some kinds of state, we are interested in changes at the global scope
+ // only. For example, global pointer input, global key presses and global
+ // visibility change should affect the state at every scope:
+ document.addEventListener("keydown", onKeyDown, true);
+ document.addEventListener("mousedown", onPointerDown, true);
+ document.addEventListener("pointerdown", onPointerDown, true);
+ document.addEventListener("touchstart", onPointerDown, true);
+ document.addEventListener("visibilitychange", onVisibilityChange, true);
+
+ addInitialPointerMoveListeners();
+
+ // For focus and blur, we specifically care about state changes in the local
+ // scope. This is because focus / blur events that originate from within a
+ // shadow root are not re-dispatched from the host element if it was already
+ // the active element in its own scope:
+ scope.addEventListener("focus", onFocus, true);
+ scope.addEventListener("blur", onBlur, true);
+
+ // We detect that a node is a ShadowRoot by ensuring that it is a
+ // DocumentFragment and also has a host property. This check covers native
+ // implementation and polyfill implementation transparently. If we only cared
+ // about the native implementation, we could just check if the scope was
+ // an instance of a ShadowRoot.
+ if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {
+ // Since a ShadowRoot is a special kind of DocumentFragment, it does not
+ // have a root element to add a class to. So, we add this attribute to the
+ // host element instead:
+ scope.host.setAttribute("data-js-focus-visible", "");
+ } else if (scope.nodeType === Node.DOCUMENT_NODE) {
+ document.documentElement.classList.add("js-focus-visible");
+ }
}
// It is important to wrap all references to global window and document in
// these checks to support server-side rendering use cases
// @see https://github.com/WICG/focus-visible/issues/199
-if (typeof window !== 'undefined' && typeof document !== 'undefined') {
- // Make the polyfill helper globally available. This can be used as a signal
- // to interested libraries that wish to coordinate with the polyfill for e.g.,
- // applying the polyfill to a shadow root:
- window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;
-
- // Notify interested libraries of the polyfill's presence, in case the
- // polyfill was loaded lazily:
- var event;
-
- try {
- event = new CustomEvent('focus-visible-polyfill-ready');
- } catch (error) {
- // IE11 does not support using CustomEvent as a constructor directly:
- event = document.createEvent('CustomEvent');
- event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});
- }
-
- window.dispatchEvent(event);
+if (typeof window !== "undefined" && typeof document !== "undefined") {
+ // Make the polyfill helper globally available. This can be used as a signal
+ // to interested libraries that wish to coordinate with the polyfill for e.g.,
+ // applying the polyfill to a shadow root:
+ window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;
+
+ // Notify interested libraries of the polyfill's presence, in case the
+ // polyfill was loaded lazily:
+ var event;
+
+ try {
+ event = new CustomEvent("focus-visible-polyfill-ready");
+ } catch (error) {
+ // IE11 does not support using CustomEvent as a constructor directly:
+ event = document.createEvent("CustomEvent");
+ event.initCustomEvent("focus-visible-polyfill-ready", false, false, {});
+ }
+
+ window.dispatchEvent(event);
}
-if (typeof document !== 'undefined') {
- // Apply the polyfill to the global document, so that no JavaScript
- // coordination is required to use the polyfill in the top-level document:
- applyFocusVisiblePolyfill(document);
+if (typeof document !== "undefined") {
+ // Apply the polyfill to the global document, so that no JavaScript
+ // coordination is required to use the polyfill in the top-level document:
+ applyFocusVisiblePolyfill(document);
}
diff --git a/docs/src/assets/js/inert-polyfill.js b/docs/src/assets/js/inert-polyfill.js
index 11ae095ccf60..34e90291d3e4 100644
--- a/docs/src/assets/js/inert-polyfill.js
+++ b/docs/src/assets/js/inert-polyfill.js
@@ -1,23 +1,96 @@
-/* inert polyfill
+/* inert polyfill
* source: https://cdn.rawgit.com/GoogleChrome/inert-polyfill/v0.1.0/inert-polyfill.min.js
*/
window.addEventListener("load", function () {
- function h(a, b, c) { if (0 > b) { if (a.previousElementSibling) { for (a = a.previousElementSibling; a.lastElementChild;)a = a.lastElementChild; return a } return a.parentElement } if (a != c && a.firstElementChild) return a.firstElementChild; for (; null != a;) { if (a.nextElementSibling) return a.nextElementSibling; a = a.parentElement } return null } function g(a) { for (; a && a !== document.documentElement;) { if (a.hasAttribute("inert")) return a; a = a.parentElement } return null } (function (a) {
- var b = document.createElement("style");
- b.type = "text/css"; b.styleSheet ? b.styleSheet.cssText = a : b.appendChild(document.createTextNode(a)); document.body.appendChild(b)
- })("/*[inert]*/[inert]{position:relative!important;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}[inert]::before{content:'';display:block;position:absolute;top:0;left:0;right:0;bottom:0}"); var c = 0; document.addEventListener("keydown", function (a) { c = 9 === a.keyCode ? a.shiftKey ? -1 : 1 : 0 }); document.addEventListener("mousedown",
- function () { c = 0 }); document.body.addEventListener("focus", function (a) {
- var b = a.target, f = g(b); if (f) {
- if (document.hasFocus() && 0 !== c) {
- var d = document.activeElement, e = new KeyboardEvent("keydown", { keyCode: 9, which: 9, key: "Tab", code: "Tab", keyIdentifier: "U+0009", shiftKey: !!(0 > c), bubbles: !0 }); Object.defineProperty(e, "keyCode", { value: 9 }); document.activeElement.dispatchEvent(e); if (d != document.activeElement) return; for (d = f; ;) {
- d = h(d, c, f); if (!d) break; a: {
- e = b; if (!(0 > d.tabIndex) && (d.focus(), document.activeElement !== e)) {
- e =
- !0; break a
- } e = !1
- } if (e) return
- }
- } b.blur(); a.preventDefault(); a.stopPropagation()
- }
- }, !0); document.addEventListener("click", function (a) { g(a.target) && (a.preventDefault(), a.stopPropagation()) }, !0)
-});
\ No newline at end of file
+ function h(a, b, c) {
+ if (0 > b) {
+ if (a.previousElementSibling) {
+ for (a = a.previousElementSibling; a.lastElementChild; )
+ a = a.lastElementChild;
+ return a;
+ }
+ return a.parentElement;
+ }
+ if (a != c && a.firstElementChild) return a.firstElementChild;
+ for (; null != a; ) {
+ if (a.nextElementSibling) return a.nextElementSibling;
+ a = a.parentElement;
+ }
+ return null;
+ }
+ function g(a) {
+ for (; a && a !== document.documentElement; ) {
+ if (a.hasAttribute("inert")) return a;
+ a = a.parentElement;
+ }
+ return null;
+ }
+ (function (a) {
+ var b = document.createElement("style");
+ b.type = "text/css";
+ b.styleSheet
+ ? (b.styleSheet.cssText = a)
+ : b.appendChild(document.createTextNode(a));
+ document.body.appendChild(b);
+ })(
+ "/*[inert]*/[inert]{position:relative!important;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}[inert]::before{content:'';display:block;position:absolute;top:0;left:0;right:0;bottom:0}",
+ );
+ var c = 0;
+ document.addEventListener("keydown", function (a) {
+ c = 9 === a.keyCode ? (a.shiftKey ? -1 : 1) : 0;
+ });
+ document.addEventListener("mousedown", function () {
+ c = 0;
+ });
+ document.body.addEventListener(
+ "focus",
+ function (a) {
+ var b = a.target,
+ f = g(b);
+ if (f) {
+ if (document.hasFocus() && 0 !== c) {
+ var d = document.activeElement,
+ e = new KeyboardEvent("keydown", {
+ keyCode: 9,
+ which: 9,
+ key: "Tab",
+ code: "Tab",
+ keyIdentifier: "U+0009",
+ shiftKey: !!(0 > c),
+ bubbles: !0,
+ });
+ Object.defineProperty(e, "keyCode", { value: 9 });
+ document.activeElement.dispatchEvent(e);
+ if (d != document.activeElement) return;
+ for (d = f; ; ) {
+ d = h(d, c, f);
+ if (!d) break;
+ a: {
+ e = b;
+ if (
+ !(0 > d.tabIndex) &&
+ (d.focus(), document.activeElement !== e)
+ ) {
+ e = !0;
+ break a;
+ }
+ e = !1;
+ }
+ if (e) return;
+ }
+ }
+ b.blur();
+ a.preventDefault();
+ a.stopPropagation();
+ }
+ },
+ !0,
+ );
+ document.addEventListener(
+ "click",
+ function (a) {
+ g(a.target) && (a.preventDefault(), a.stopPropagation());
+ },
+ !0,
+ );
+});
diff --git a/docs/src/assets/js/main.js b/docs/src/assets/js/main.js
index 80168a136c91..83599a5d32d1 100644
--- a/docs/src/assets/js/main.js
+++ b/docs/src/assets/js/main.js
@@ -1,303 +1,304 @@
(function () {
- // for sticky table of contents
- const tocBody = document.querySelector(".docs-aside #js-toc-panel");
- const options = {
- root: null,
- rootMargin: `0px 0px -90% 0px`,
- threshold: 1.0,
- };
- const activeClassName = "active";
- const observer = new IntersectionObserver((entries) => {
- entries.forEach((entry) => {
- if (entry.isIntersecting) {
- const activeAnchor = tocBody.querySelector(
- `a.${activeClassName}`
- );
- if (activeAnchor) {
- activeAnchor.parentNode.classList.remove(activeClassName);
- activeAnchor.classList.remove(activeClassName);
- }
-
- const nextActiveAnchor = tocBody.querySelector(
- `a[href="#${entry.target.id}"]`
- );
- if (nextActiveAnchor) {
- nextActiveAnchor.parentNode.classList.add(activeClassName);
- nextActiveAnchor.classList.add(activeClassName);
- }
- }
- });
- }, options);
- if (window.matchMedia("(min-width: 1400px)").matches) {
- document
- .querySelectorAll(
- "#main > div > h2[id], #main > div > h3[id], #main > div > h4[id]" // only h2, h3, h4 are shown in toc
- )
- .forEach((el) => observer.observe(el));
- }
+ // for sticky table of contents
+ const tocBody = document.querySelector(".docs-aside #js-toc-panel");
+ const options = {
+ root: null,
+ rootMargin: `0px 0px -90% 0px`,
+ threshold: 1.0,
+ };
+ const activeClassName = "active";
+ const observer = new IntersectionObserver(entries => {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ const activeAnchor = tocBody.querySelector(
+ `a.${activeClassName}`,
+ );
+ if (activeAnchor) {
+ activeAnchor.parentNode.classList.remove(activeClassName);
+ activeAnchor.classList.remove(activeClassName);
+ }
+
+ const nextActiveAnchor = tocBody.querySelector(
+ `a[href="#${entry.target.id}"]`,
+ );
+ if (nextActiveAnchor) {
+ nextActiveAnchor.parentNode.classList.add(activeClassName);
+ nextActiveAnchor.classList.add(activeClassName);
+ }
+ }
+ });
+ }, options);
+ if (window.matchMedia("(min-width: 1400px)").matches) {
+ document
+ .querySelectorAll(
+ "#main > div > h2[id], #main > div > h3[id], #main > div > h4[id]", // only h2, h3, h4 are shown in toc
+ )
+ .forEach(el => observer.observe(el));
+ }
})();
-(function() {
- var toc_trigger = document.getElementById("js-toc-label"),
- toc = document.getElementById("js-toc-panel"),
- body = document.getElementsByTagName("body")[0],
- open = false;
-
- if (toc && matchMedia) {
- const mq = window.matchMedia("(max-width: 1023px)");
- mq.addEventListener('change', WidthChange);
- WidthChange(mq);
- }
-
- // media query change
- function WidthChange(mq) {
- if (mq.matches && toc_trigger) {
- let text = toc_trigger.innerText;
- let headingButton = document.createElement("button");
- headingButton.setAttribute("aria-expanded", "false");
- headingButton.innerText = text;
- toc_trigger.innerHTML = "";
-
- toc_trigger.appendChild(headingButton);
- headingButton.innerHTML += ``;
-
- toc.setAttribute("data-open", "false");
- toc_trigger.setAttribute("aria-expanded", "false");
- headingButton.addEventListener("click", toggleTOC, true);
- } else {
- toc_trigger.innerHTML = 'Table of Contents';
- toc.setAttribute("data-open", "true");
- }
-
- }
-
- function toggleTOC(e) {
- if (!open) {
- this.setAttribute("aria-expanded", "true");
- toc.setAttribute("data-open", "true");
- open = true;
- } else {
- this.setAttribute("aria-expanded", "false");
- toc.setAttribute("data-open", "false");
- open = false;
- }
- }
+(function () {
+ var toc_trigger = document.getElementById("js-toc-label"),
+ toc = document.getElementById("js-toc-panel"),
+ body = document.getElementsByTagName("body")[0],
+ open = false;
+
+ if (toc && matchMedia) {
+ const mq = window.matchMedia("(max-width: 1023px)");
+ mq.addEventListener("change", WidthChange);
+ WidthChange(mq);
+ }
+
+ // media query change
+ function WidthChange(mq) {
+ if (mq.matches && toc_trigger) {
+ let text = toc_trigger.innerText;
+ let headingButton = document.createElement("button");
+ headingButton.setAttribute("aria-expanded", "false");
+ headingButton.innerText = text;
+ toc_trigger.innerHTML = "";
+
+ toc_trigger.appendChild(headingButton);
+ headingButton.innerHTML += ``;
+
+ toc.setAttribute("data-open", "false");
+ toc_trigger.setAttribute("aria-expanded", "false");
+ headingButton.addEventListener("click", toggleTOC, true);
+ } else {
+ toc_trigger.innerHTML = "Table of Contents";
+ toc.setAttribute("data-open", "true");
+ }
+ }
+
+ function toggleTOC(e) {
+ if (!open) {
+ this.setAttribute("aria-expanded", "true");
+ toc.setAttribute("data-open", "true");
+ open = true;
+ } else {
+ this.setAttribute("aria-expanded", "false");
+ toc.setAttribute("data-open", "false");
+ open = false;
+ }
+ }
})();
-(function() {
- var nav_trigger = document.getElementById("nav-toggle"),
- nav = document.getElementById("nav-panel"),
- body = document.getElementsByTagName("body")[0],
- open = false;
-
- if (matchMedia) {
- const mq = window.matchMedia("(max-width: 1023px)");
- mq.addEventListener('change', WidthChange);
- WidthChange(mq);
- }
-
- // media query change
- function WidthChange(mq) {
- if (mq.matches) {
- nav.setAttribute("data-open", "false");
- nav_trigger.removeAttribute("hidden");
- nav_trigger.setAttribute("aria-expanded", "false");
- nav_trigger.addEventListener("click", togglenav, false);
- } else {
- nav.setAttribute("data-open", "true");
- nav_trigger.setAttribute("hidden", "");
- nav_trigger.setAttribute("aria-expanded", "true");
- }
-
- }
-
- function togglenav(e) {
- if (!open) {
- this.setAttribute("aria-expanded", "true");
- nav.setAttribute("data-open", "true");
- open = true;
- } else {
- this.setAttribute("aria-expanded", "false");
- nav.setAttribute("data-open", "false");
- open = false;
- }
- }
+(function () {
+ var nav_trigger = document.getElementById("nav-toggle"),
+ nav = document.getElementById("nav-panel"),
+ body = document.getElementsByTagName("body")[0],
+ open = false;
+
+ if (matchMedia) {
+ const mq = window.matchMedia("(max-width: 1023px)");
+ mq.addEventListener("change", WidthChange);
+ WidthChange(mq);
+ }
+
+ // media query change
+ function WidthChange(mq) {
+ if (mq.matches) {
+ nav.setAttribute("data-open", "false");
+ nav_trigger.removeAttribute("hidden");
+ nav_trigger.setAttribute("aria-expanded", "false");
+ nav_trigger.addEventListener("click", togglenav, false);
+ } else {
+ nav.setAttribute("data-open", "true");
+ nav_trigger.setAttribute("hidden", "");
+ nav_trigger.setAttribute("aria-expanded", "true");
+ }
+ }
+
+ function togglenav(e) {
+ if (!open) {
+ this.setAttribute("aria-expanded", "true");
+ nav.setAttribute("data-open", "true");
+ open = true;
+ } else {
+ this.setAttribute("aria-expanded", "false");
+ nav.setAttribute("data-open", "false");
+ open = false;
+ }
+ }
})();
-(function() {
- var index_trigger = document.getElementById("js-docs-index-toggle"),
- index = document.getElementById("js-docs-index-panel"),
- body = document.getElementsByTagName("body")[0],
- open = false;
-
- if (matchMedia) {
- const mq = window.matchMedia("(max-width: 1023px)");
- mq.addEventListener('change', WidthChange);
- WidthChange(mq);
- }
-
- function WidthChange(mq) {
- initIndex();
- }
-
- function toggleindex(e) {
- if (!open) {
- this.setAttribute("aria-expanded", "true");
- index.setAttribute("data-open", "true");
- open = true;
- } else {
- this.setAttribute("aria-expanded", "false");
- index.setAttribute("data-open", "false");
- open = false;
- }
- }
-
- function initIndex() {
- if(index_trigger) {
-
- index_trigger.removeAttribute("hidden");
- index_trigger.setAttribute("aria-expanded", "false");
- index.setAttribute("data-open", "false");
-
- index.setAttribute("data-open", "false");
- index_trigger.addEventListener("click", toggleindex, false);
- }
- }
+(function () {
+ var index_trigger = document.getElementById("js-docs-index-toggle"),
+ index = document.getElementById("js-docs-index-panel"),
+ body = document.getElementsByTagName("body")[0],
+ open = false;
+
+ if (matchMedia) {
+ const mq = window.matchMedia("(max-width: 1023px)");
+ mq.addEventListener("change", WidthChange);
+ WidthChange(mq);
+ }
+
+ function WidthChange(mq) {
+ initIndex();
+ }
+
+ function toggleindex(e) {
+ if (!open) {
+ this.setAttribute("aria-expanded", "true");
+ index.setAttribute("data-open", "true");
+ open = true;
+ } else {
+ this.setAttribute("aria-expanded", "false");
+ index.setAttribute("data-open", "false");
+ open = false;
+ }
+ }
+
+ function initIndex() {
+ if (index_trigger) {
+ index_trigger.removeAttribute("hidden");
+ index_trigger.setAttribute("aria-expanded", "false");
+ index.setAttribute("data-open", "false");
+
+ index.setAttribute("data-open", "false");
+ index_trigger.addEventListener("click", toggleindex, false);
+ }
+ }
})();
-
-
-(function() {
- var switchers = document.querySelectorAll('.switcher'),
- fallbacks = document.querySelectorAll('.switcher-fallback');
-
- if (fallbacks != null) {
- fallbacks.forEach(el => {
- el.setAttribute('hidden', '');
- });
- }
-
- if (switchers != null) {
- switchers.forEach(element => {
- element.removeAttribute('hidden');
- const select = element.querySelector('select');
-
- select.addEventListener('change', function() {
- var selected = this.options[this.selectedIndex];
- url = selected.getAttribute('data-url');
-
- window.location.href = url;
- })
- });
- }
+(function () {
+ var switchers = document.querySelectorAll(".switcher"),
+ fallbacks = document.querySelectorAll(".switcher-fallback");
+
+ if (fallbacks != null) {
+ fallbacks.forEach(el => {
+ el.setAttribute("hidden", "");
+ });
+ }
+
+ if (switchers != null) {
+ switchers.forEach(element => {
+ element.removeAttribute("hidden");
+ const select = element.querySelector("select");
+
+ select.addEventListener("change", function () {
+ var selected = this.options[this.selectedIndex];
+ url = selected.getAttribute("data-url");
+
+ window.location.href = url;
+ });
+ });
+ }
})();
// add utilities
var util = {
- keyCodes: {
- UP: 38,
- DOWN: 40,
- LEFT: 37,
- RIGHT: 39,
- HOME: 36,
- END: 35,
- ENTER: 13,
- SPACE: 32,
- DELETE: 46,
- TAB: 9,
- },
-
- generateID: function(base) {
- return base + Math.floor(Math.random() * 999);
- },
-
- getDirectChildren: function(elm, selector) {
- return Array.prototype.filter.call(elm.children, function(child) {
- return child.matches(selector);
- });
- },
+ keyCodes: {
+ UP: 38,
+ DOWN: 40,
+ LEFT: 37,
+ RIGHT: 39,
+ HOME: 36,
+ END: 35,
+ ENTER: 13,
+ SPACE: 32,
+ DELETE: 46,
+ TAB: 9,
+ },
+
+ generateID: function (base) {
+ return base + Math.floor(Math.random() * 999);
+ },
+
+ getDirectChildren: function (elm, selector) {
+ return Array.prototype.filter.call(elm.children, function (child) {
+ return child.matches(selector);
+ });
+ },
};
-(function(w, doc, undefined) {
- var CollapsibleIndexOptions = {
- allCollapsed: false,
- icon: '',
- };
- var CollapsibleIndex = function(inst, options) {
- var _options = Object.assign(CollapsibleIndexOptions, options);
- var el = inst;
- var indexToggles = el.querySelectorAll(".docs-index .docs__index__panel > ul > .docs-index__item[data-has-children] > a"); // only top-most level
- var indexPanels = el.querySelectorAll(".docs-index .docs__index__panel > ul > .docs-index__item>[data-child-list]"); // the list
- var accID = util.generateID("c-index-");
-
- var init = function() {
- el.classList.add("index-js");
-
- setupindexToggles(indexToggles);
- setupindexPanels(indexPanels);
- };
-
-
- var setupindexToggles = function(indexToggles) {
- Array.from(indexToggles).forEach(function(item, index) {
- var $this = item;
-
- $this.setAttribute('role', 'button');
- $this.setAttribute("id", accID + "__item-" + index);
- $this.innerHTML += _options.icon;
-
- if (_options.allCollapsed) $this.setAttribute("aria-expanded", "false");
- else $this.setAttribute("aria-expanded", "true");
-
- $this.addEventListener("click", function(e) {
- e.preventDefault();
- togglePanel($this);
- });
- });
- };
-
- var setupindexPanels = function(indexPanels) {
- Array.from(indexPanels).forEach(function(item, index) {
- let $this = item;
-
- $this.setAttribute("id", accID + "__list-" + index);
- $this.setAttribute(
- "aria-labelledby",
- accID + "__item-" + index
- );
- if (_options.allCollapsed) $this.setAttribute("aria-hidden", "true");
- else $this.setAttribute("aria-hidden", "false");
- });
- };
-
- var togglePanel = function(toggleButton) {
- var thepanel = toggleButton.nextElementSibling;
-
- if (toggleButton.getAttribute("aria-expanded") == "true") {
- toggleButton.setAttribute("aria-expanded", "false");
- thepanel.setAttribute("aria-hidden", "true");
- } else {
- toggleButton.setAttribute("aria-expanded", "true");
- thepanel.setAttribute("aria-hidden", "false");
- }
- };
-
-
- init.call(this);
- return this;
- }; // CollapsibleIndex()
-
- w.CollapsibleIndex = CollapsibleIndex;
+(function (w, doc, undefined) {
+ var CollapsibleIndexOptions = {
+ allCollapsed: false,
+ icon: '',
+ };
+ var CollapsibleIndex = function (inst, options) {
+ var _options = Object.assign(CollapsibleIndexOptions, options);
+ var el = inst;
+ var indexToggles = el.querySelectorAll(
+ ".docs-index .docs__index__panel > ul > .docs-index__item[data-has-children] > a",
+ ); // only top-most level
+ var indexPanels = el.querySelectorAll(
+ ".docs-index .docs__index__panel > ul > .docs-index__item>[data-child-list]",
+ ); // the list
+ var accID = util.generateID("c-index-");
+
+ var init = function () {
+ el.classList.add("index-js");
+
+ setupindexToggles(indexToggles);
+ setupindexPanels(indexPanels);
+ };
+
+ var setupindexToggles = function (indexToggles) {
+ Array.from(indexToggles).forEach(function (item, index) {
+ var $this = item;
+
+ $this.setAttribute("role", "button");
+ $this.setAttribute("id", accID + "__item-" + index);
+ $this.innerHTML += _options.icon;
+
+ if (_options.allCollapsed)
+ $this.setAttribute("aria-expanded", "false");
+ else $this.setAttribute("aria-expanded", "true");
+
+ $this.addEventListener("click", function (e) {
+ e.preventDefault();
+ togglePanel($this);
+ });
+ });
+ };
+
+ var setupindexPanels = function (indexPanels) {
+ Array.from(indexPanels).forEach(function (item, index) {
+ let $this = item;
+
+ $this.setAttribute("id", accID + "__list-" + index);
+ $this.setAttribute(
+ "aria-labelledby",
+ accID + "__item-" + index,
+ );
+ if (_options.allCollapsed)
+ $this.setAttribute("aria-hidden", "true");
+ else $this.setAttribute("aria-hidden", "false");
+ });
+ };
+
+ var togglePanel = function (toggleButton) {
+ var thepanel = toggleButton.nextElementSibling;
+
+ if (toggleButton.getAttribute("aria-expanded") == "true") {
+ toggleButton.setAttribute("aria-expanded", "false");
+ thepanel.setAttribute("aria-hidden", "true");
+ } else {
+ toggleButton.setAttribute("aria-expanded", "true");
+ thepanel.setAttribute("aria-hidden", "false");
+ }
+ };
+
+ init.call(this);
+ return this;
+ }; // CollapsibleIndex()
+
+ w.CollapsibleIndex = CollapsibleIndex;
})(window, document);
// init
-var index = document.getElementById('docs-index');
+var index = document.getElementById("docs-index");
if (index) {
- index = new CollapsibleIndex(index, {
- allCollapsed: false
- });
+ index = new CollapsibleIndex(index, {
+ allCollapsed: false,
+ });
}
document.addEventListener("DOMContentLoaded", () => {
- anchors.add(".docs-content h2:not(.c-toc__label), .docs-content h3, .docs-content h4");
+ anchors.add(
+ ".docs-content h2:not(.c-toc__label), .docs-content h3, .docs-content h4",
+ );
});
diff --git a/docs/src/assets/js/scroll-up-btn.js b/docs/src/assets/js/scroll-up-btn.js
index cb77af1bcbe4..9a3cf4ed2ee5 100644
--- a/docs/src/assets/js/scroll-up-btn.js
+++ b/docs/src/assets/js/scroll-up-btn.js
@@ -1,13 +1,16 @@
(function () {
- const scrollUpBtn = document.getElementById("scroll-up-btn");
+ const scrollUpBtn = document.getElementById("scroll-up-btn");
- if(window.innerWidth < 1400) {
- window.addEventListener("scroll", function () {
- if(document.body.scrollTop > 500 || document.documentElement.scrollTop > 500) {
- scrollUpBtn.style.display = "flex";
- } else {
- scrollUpBtn.style.display = "none";
- }
- });
- }
-})();
\ No newline at end of file
+ if (window.innerWidth < 1400) {
+ window.addEventListener("scroll", function () {
+ if (
+ document.body.scrollTop > 500 ||
+ document.documentElement.scrollTop > 500
+ ) {
+ scrollUpBtn.style.display = "flex";
+ } else {
+ scrollUpBtn.style.display = "none";
+ }
+ });
+ }
+})();
diff --git a/docs/src/assets/js/search.js b/docs/src/assets/js/search.js
index 088809eb1b75..ac7a3492cbcb 100644
--- a/docs/src/assets/js/search.js
+++ b/docs/src/assets/js/search.js
@@ -14,15 +14,17 @@ import algoliasearch from "./algoliasearch.js";
//-----------------------------------------------------------------------------
// search
-const client = algoliasearch('L633P0C2IR', 'bb6bbd2940351f3afc18844a6b06a6e8');
-const index = client.initIndex('eslint');
+const client = algoliasearch("L633P0C2IR", "bb6bbd2940351f3afc18844a6b06a6e8");
+const index = client.initIndex("eslint");
// page
-const resultsElement = document.querySelector('#search-results');
-const resultsLiveRegion = document.querySelector('#search-results-announcement');
-const searchInput = document.querySelector('#search');
-const searchClearBtn = document.querySelector('#search__clear-btn');
-const poweredByLink = document.querySelector('.search_powered-by-wrapper');
+const resultsElement = document.querySelector("#search-results");
+const resultsLiveRegion = document.querySelector(
+ "#search-results-announcement",
+);
+const searchInput = document.querySelector("#search");
+const searchClearBtn = document.querySelector("#search__clear-btn");
+const poweredByLink = document.querySelector(".search_powered-by-wrapper");
let activeIndex = -1;
let searchQuery;
let caretPosition = 0;
@@ -37,9 +39,11 @@ let caretPosition = 0;
* @returns {Promise>} The search results.
*/
function fetchSearchResults(query) {
- return index.search(query, {
- facetFilters: ["tags:docs"]
- }).then(({ hits }) => hits);
+ return index
+ .search(query, {
+ facetFilters: ["tags:docs"],
+ })
+ .then(({ hits }) => hits);
}
/**
@@ -49,11 +53,11 @@ function fetchSearchResults(query) {
* @returns {void} - This function doesn't return anything.
*/
function clearSearchResults(removeEventListener = false) {
- resultsElement.innerHTML = "";
- if (removeEventListener && document.clickEventAdded) {
- document.removeEventListener('click', handleDocumentClick);
- document.clickEventAdded = false;
- }
+ resultsElement.innerHTML = "";
+ if (removeEventListener && document.clickEventAdded) {
+ document.removeEventListener("click", handleDocumentClick);
+ document.clickEventAdded = false;
+ }
}
/**
@@ -62,9 +66,9 @@ function clearSearchResults(removeEventListener = false) {
* @returns {void} - This function doesn't return anything.
*/
function showNoResults() {
- resultsLiveRegion.innerHTML = "No results found.";
- resultsElement.innerHTML = "No results found.";
- resultsElement.setAttribute('data-results', 'false');
+ resultsLiveRegion.innerHTML = "No results found.";
+ resultsElement.innerHTML = "No results found.";
+ resultsElement.setAttribute("data-results", "false");
}
/**
@@ -72,8 +76,8 @@ function showNoResults() {
* @returns {void} - This function doesn't return anything.
*/
function clearNoResults() {
- resultsLiveRegion.innerHTML = "";
- resultsElement.innerHTML = "";
+ resultsLiveRegion.innerHTML = "";
+ resultsElement.innerHTML = "";
}
/**
@@ -82,56 +86,53 @@ function clearNoResults() {
* @returns {void}
*/
function displaySearchResults(results) {
-
- clearSearchResults();
-
- if (results.length) {
-
- const list = document.createElement("ul");
- list.setAttribute('role', 'list');
- list.classList.add('search-results__list');
- resultsElement.append(list);
- resultsElement.setAttribute('data-results', 'true');
- activeIndex = -1;
-
- for (const result of results) {
- const listItem = document.createElement('li');
- listItem.classList.add('search-results__item');
- const maxLvl = Math.max(...Object.keys(result._highlightResult.hierarchy).map(k => Number(k.substring(3))));
- listItem.innerHTML = `
+ clearSearchResults();
+
+ if (results.length) {
+ const list = document.createElement("ul");
+ list.setAttribute("role", "list");
+ list.classList.add("search-results__list");
+ resultsElement.append(list);
+ resultsElement.setAttribute("data-results", "true");
+ activeIndex = -1;
+
+ for (const result of results) {
+ const listItem = document.createElement("li");
+ listItem.classList.add("search-results__item");
+ const maxLvl = Math.max(
+ ...Object.keys(result._highlightResult.hierarchy).map(k =>
+ Number(k.substring(3)),
+ ),
+ );
+ listItem.innerHTML = `
${result.hierarchy.lvl0}
- ${typeof result._highlightResult.content !== 'undefined' ? result._highlightResult.content.value : result._highlightResult.hierarchy[`lvl${maxLvl}`].value}
+ ${typeof result._highlightResult.content !== "undefined" ? result._highlightResult.content.value : result._highlightResult.hierarchy[`lvl${maxLvl}`].value}
`.trim();
- list.append(listItem);
- }
-
- } else {
- showNoResults();
- }
-
+ list.append(listItem);
+ }
+ } else {
+ showNoResults();
+ }
}
-
// Check if an element is currently scrollable
function isScrollable(element) {
- return element && element.clientHeight < element.scrollHeight;
+ return element && element.clientHeight < element.scrollHeight;
}
// Ensure given child element is within the parent's visible scroll area
function maintainScrollVisibility(activeElement, scrollParent) {
- const { offsetHeight, offsetTop } = activeElement;
- const { offsetHeight: parentOffsetHeight, scrollTop } = scrollParent;
+ const { offsetHeight, offsetTop } = activeElement;
+ const { offsetHeight: parentOffsetHeight, scrollTop } = scrollParent;
- const isAbove = offsetTop < scrollTop;
- const isBelow = (offsetTop + offsetHeight) > (scrollTop + parentOffsetHeight);
-
- if (isAbove) {
- scrollParent.scrollTo(0, offsetTop);
- }
- else if (isBelow) {
- scrollParent.scrollTo(0, offsetTop - parentOffsetHeight + offsetHeight);
- }
+ const isAbove = offsetTop < scrollTop;
+ const isBelow = offsetTop + offsetHeight > scrollTop + parentOffsetHeight;
+ if (isAbove) {
+ scrollParent.scrollTo(0, offsetTop);
+ } else if (isBelow) {
+ scrollParent.scrollTo(0, offsetTop - parentOffsetHeight + offsetHeight);
+ }
}
/**
@@ -141,11 +142,11 @@ function maintainScrollVisibility(activeElement, scrollParent) {
* @returns {Function} Returns the new debounced function.
*/
function debounce(callback, delay) {
- let timer;
- return (...args) => {
- if (timer) clearTimeout(timer);
- timer = setTimeout(() => callback.apply(this, args), delay);
- }
+ let timer;
+ return (...args) => {
+ if (timer) clearTimeout(timer);
+ timer = setTimeout(() => callback.apply(this, args), delay);
+ };
}
/**
@@ -156,24 +157,24 @@ function debounce(callback, delay) {
* @returns {void} - No return value.
* @see debounce - Limits the number of requests during rapid typing.
*/
-const debouncedFetchSearchResults = debounce((query) => {
- fetchSearchResults(query)
- .then(displaySearchResults)
- .catch(() => { clearSearchResults(true) });
+const debouncedFetchSearchResults = debounce(query => {
+ fetchSearchResults(query)
+ .then(displaySearchResults)
+ .catch(() => {
+ clearSearchResults(true);
+ });
}, 300);
-
/**
* Handles the document click event to clear search results if the user clicks outside of the search input or results element.
* @param {MouseEvent} e - The event object representing the click event.
* @returns {void} - This function does not return any value. It directly interacts with the UI by clearing search results.
*/
-const handleDocumentClick = (e) => {
- if (e.target !== resultsElement && e.target !== searchInput) {
- clearSearchResults(true);
- }
-}
-
+const handleDocumentClick = e => {
+ if (e.target !== resultsElement && e.target !== searchInput) {
+ clearSearchResults(true);
+ }
+};
//-----------------------------------------------------------------------------
// Event Handlers
@@ -181,102 +182,113 @@ const handleDocumentClick = (e) => {
// listen for input changes
if (searchInput)
- searchInput.addEventListener('keyup', function (e) {
- const query = searchInput.value;
+ searchInput.addEventListener("keyup", function (e) {
+ const query = searchInput.value;
- if (query === searchQuery) return;
+ if (query === searchQuery) return;
- if (query.length) searchClearBtn.removeAttribute('hidden');
- else searchClearBtn.setAttribute('hidden', '');
+ if (query.length) searchClearBtn.removeAttribute("hidden");
+ else searchClearBtn.setAttribute("hidden", "");
- if (query.length > 2) {
- debouncedFetchSearchResults(query);
- if (!document.clickEventAdded) {
- document.addEventListener('click', handleDocumentClick);
- document.clickEventAdded = true;
- }
- } else {
- clearSearchResults(true);
- }
-
- searchQuery = query
- });
+ if (query.length > 2) {
+ debouncedFetchSearchResults(query);
+ if (!document.clickEventAdded) {
+ document.addEventListener("click", handleDocumentClick);
+ document.clickEventAdded = true;
+ }
+ } else {
+ clearSearchResults(true);
+ }
+ searchQuery = query;
+ });
if (searchClearBtn) {
- searchClearBtn.addEventListener('click', function () {
- searchInput.value = '';
- searchInput.focus();
- clearSearchResults(true);
- searchClearBtn.setAttribute('hidden', '');
- });
-
- searchInput.addEventListener("blur", function () {
- caretPosition = searchInput.selectionStart;
- });
-
- searchInput.addEventListener("focus", function () {
- if (searchInput.selectionStart !== caretPosition) {
- searchInput.setSelectionRange(caretPosition, caretPosition);
- }
- });
-
+ searchClearBtn.addEventListener("click", function () {
+ searchInput.value = "";
+ searchInput.focus();
+ clearSearchResults(true);
+ searchClearBtn.setAttribute("hidden", "");
+ });
+
+ searchInput.addEventListener("blur", function () {
+ caretPosition = searchInput.selectionStart;
+ });
+
+ searchInput.addEventListener("focus", function () {
+ if (searchInput.selectionStart !== caretPosition) {
+ searchInput.setSelectionRange(caretPosition, caretPosition);
+ }
+ });
}
if (poweredByLink) {
- poweredByLink.addEventListener('focus', function () {
- clearSearchResults();
- });
+ poweredByLink.addEventListener("focus", function () {
+ clearSearchResults();
+ });
}
if (resultsElement) {
- resultsElement.addEventListener('keydown', (e) => {
- if (e.key !== "ArrowUp" && e.key !== "ArrowDown" && e.key !== "Tab" && e.key !== 'Shift') {
- searchInput.focus();
- }
- });
+ resultsElement.addEventListener("keydown", e => {
+ if (
+ e.key !== "ArrowUp" &&
+ e.key !== "ArrowDown" &&
+ e.key !== "Tab" &&
+ e.key !== "Shift" &&
+ e.key !== "Enter"
+ ) {
+ searchInput.focus();
+ }
+ });
}
-document.addEventListener('keydown', function (e) {
- const searchResults = Array.from(document.querySelectorAll('.search-results__item'));
- const isArrowKey = e.key === "ArrowUp" || e.key === "ArrowDown";
-
- if (e.key === "Escape") {
- e.preventDefault();
- if (searchResults.length) {
- clearSearchResults(true);
- searchInput.focus();
- } else if (document.activeElement === searchInput) {
- clearNoResults();
- searchInput.blur();
- }
- }
-
- if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
- e.preventDefault();
- searchInput.focus();
- document.querySelector('.search').scrollIntoView({ behavior: "smooth", block: "start" });
- }
-
- if (!searchResults.length) return;
-
- if (isArrowKey) {
- e.preventDefault();
-
- if (e.key === "ArrowUp") {
- activeIndex = activeIndex - 1 < 0 ? searchResults.length - 1 : activeIndex - 1;
- } else if (e.key === "ArrowDown") {
- activeIndex = activeIndex + 1 < searchResults.length ? activeIndex + 1 : 0;
- }
-
- if (activeIndex !== -1) {
- const activeSearchResult = searchResults[activeIndex];
- activeSearchResult.querySelector('a').focus();
-
- if (isScrollable(resultsElement)) {
- maintainScrollVisibility(activeSearchResult, resultsElement);
- }
- }
- }
+document.addEventListener("keydown", function (e) {
+ const searchResults = Array.from(
+ document.querySelectorAll(".search-results__item"),
+ );
+ const isArrowKey = e.key === "ArrowUp" || e.key === "ArrowDown";
+
+ if (e.key === "Escape") {
+ e.preventDefault();
+ if (searchResults.length) {
+ clearSearchResults(true);
+ searchInput.focus();
+ } else if (document.activeElement === searchInput) {
+ clearNoResults();
+ searchInput.blur();
+ }
+ }
+
+ if ((e.metaKey || e.ctrlKey) && e.key === "k") {
+ e.preventDefault();
+ searchInput.focus();
+ document
+ .querySelector(".search")
+ .scrollIntoView({ behavior: "smooth", block: "start" });
+ }
+
+ if (!searchResults.length) return;
+
+ if (isArrowKey) {
+ e.preventDefault();
+
+ if (e.key === "ArrowUp") {
+ activeIndex =
+ activeIndex - 1 < 0
+ ? searchResults.length - 1
+ : activeIndex - 1;
+ } else if (e.key === "ArrowDown") {
+ activeIndex =
+ activeIndex + 1 < searchResults.length ? activeIndex + 1 : 0;
+ }
+
+ if (activeIndex !== -1) {
+ const activeSearchResult = searchResults[activeIndex];
+ activeSearchResult.querySelector("a").focus();
+
+ if (isScrollable(resultsElement)) {
+ maintainScrollVisibility(activeSearchResult, resultsElement);
+ }
+ }
+ }
});
-
diff --git a/docs/src/assets/js/tabs.js b/docs/src/assets/js/tabs.js
index a22159385389..a8613c7a0d75 100644
--- a/docs/src/assets/js/tabs.js
+++ b/docs/src/assets/js/tabs.js
@@ -1,337 +1,339 @@
"use strict";
if (typeof Object.assign != "function") {
- // Must be writable: true, enumerable: false, configurable: true
- Object.defineProperty(Object, "assign", {
- value: function assign(target, varArgs) {
- // .length of function is 2
-
- if (target == null) {
- // TypeError if undefined or null
- throw new TypeError(
- "Cannot convert undefined or null to object"
- );
- }
-
- var to = Object(target);
-
- for (var index = 1; index < arguments.length; index++) {
- var nextSource = arguments[index];
-
- if (nextSource != null) {
- // Skip over if undefined or null
- for (var nextKey in nextSource) {
- // Avoid bugs when hasOwnProperty is shadowed
- if (
- Object.prototype.hasOwnProperty.call(
- nextSource,
- nextKey
- )
- ) {
- to[nextKey] = nextSource[nextKey];
- }
- }
- }
- }
- return to;
- },
- writable: true,
- configurable: true
- });
+ // Must be writable: true, enumerable: false, configurable: true
+ Object.defineProperty(Object, "assign", {
+ value: function assign(target, varArgs) {
+ // .length of function is 2
+
+ if (target == null) {
+ // TypeError if undefined or null
+ throw new TypeError(
+ "Cannot convert undefined or null to object",
+ );
+ }
+
+ var to = Object(target);
+
+ for (var index = 1; index < arguments.length; index++) {
+ var nextSource = arguments[index];
+
+ if (nextSource != null) {
+ // Skip over if undefined or null
+ for (var nextKey in nextSource) {
+ // Avoid bugs when hasOwnProperty is shadowed
+ if (
+ Object.prototype.hasOwnProperty.call(
+ nextSource,
+ nextKey,
+ )
+ ) {
+ to[nextKey] = nextSource[nextKey];
+ }
+ }
+ }
+ }
+ return to;
+ },
+ writable: true,
+ configurable: true,
+ });
}
// add utilities; borrowed from: https://scottaohara.github.io/a11y_tab_widget/
var util = {
- keyCodes: {
- UP: 38,
- DOWN: 40,
- LEFT: 37,
- RIGHT: 39,
- HOME: 36,
- END: 35,
- ENTER: 13,
- SPACE: 32,
- DELETE: 46,
- TAB: 9
- },
-
- generateID: function (base) {
- return base + Math.floor(Math.random() * 999);
- },
-
-
- getUrlHash: function () {
- return window.location.hash.replace('#', '');
- },
-
- /**
- * Use history.replaceState so clicking through Tabs
- * does not create dozens of new history entries.
- * Browser back should navigate to the previous page
- * regardless of how many Tabs were activated.
- *
- * @param {string} hash
- */
- setUrlHash: function (hash) {
- if (history.replaceState) {
- history.replaceState(null, '', '#' + hash);
- } else {
- location.hash = hash;
- }
- }
+ keyCodes: {
+ UP: 38,
+ DOWN: 40,
+ LEFT: 37,
+ RIGHT: 39,
+ HOME: 36,
+ END: 35,
+ ENTER: 13,
+ SPACE: 32,
+ DELETE: 46,
+ TAB: 9,
+ },
+
+ generateID: function (base) {
+ return base + Math.floor(Math.random() * 999);
+ },
+
+ getUrlHash: function () {
+ return window.location.hash.replace("#", "");
+ },
+
+ /**
+ * Use history.replaceState so clicking through Tabs
+ * does not create dozens of new history entries.
+ * Browser back should navigate to the previous page
+ * regardless of how many Tabs were activated.
+ *
+ * @param {string} hash
+ */
+ setUrlHash: function (hash) {
+ if (history.replaceState) {
+ history.replaceState(null, "", "#" + hash);
+ } else {
+ location.hash = hash;
+ }
+ },
};
-
-
-
(function (w, doc, undefined) {
-
- var ARIAaccOptions = {
- manual: true,
- open: 0
- }
-
- var ARIAtabs = function (inst, options) {
- var _options = Object.assign(ARIAaccOptions, options);
- var el = inst;
- var tablist = el.querySelector("[data-tablist]");
- var tabs = Array.from(el.querySelectorAll("[data-tab]"));
- var tabpanels = Array.from(el.querySelectorAll("[data-tabpanel]"));
- var tabsID = util.generateID('ps__tabs-');
- var orientation = el.getAttribute('data-tabs-orientation');
- var currentIndex = _options.open;
- var selectedTab = currentIndex;
- var manual = _options.manual;
-
- el.setAttribute('id', tabsID);
-
- var init = function () {
- el.classList.add('js-tabs');
- tablist.removeAttribute('hidden');
- setupTabList();
- setupTabs();
- setupTabPanels();
- };
-
- var setupTabList = function () {
- tablist.setAttribute("role", "tablist");
- if (orientation == 'vertical') tablist.setAttribute("aria-orientation", "vertical");
- }
-
- var setupTabs = function () {
-
- tabs.forEach((tab, index) => {
- tab.setAttribute('role', 'tab');
- // each tab needs an ID that will be used to label its corresponding panel
- tab.setAttribute('id', tabsID + '__tab-' + index);
- tab.setAttribute('data-controls', tabpanels[index].getAttribute('id'));
-
- // first tab is initially active
- if (index === currentIndex) {
- selectTab(tab);
- // updateUrlHash();
- }
-
- if (tab.getAttribute('data-controls') === util.getUrlHash()) {
- currentIndex = index;
- selectedTab = index;
- selectTab(tab);
- }
-
- tab.addEventListener('click', (e) => {
- e.preventDefault();
- currentIndex = index;
- selectedTab = index;
- focusCurrentTab();
- selectTab(tab);
- // updateUrlHash();
- }, false);
-
- tab.addEventListener('keydown', (e) => {
- tabKeyboardRespond(e, tab);
- }, false);
- });
- }
-
- var focusCurrentTab = function () {
- tabs[currentIndex].focus();
- }
-
- var updateUrlHash = function () {
- var active = tabs[selectedTab];
- util.setUrlHash(active.getAttribute('data-controls'));
- };
-
- var selectTab = function (tab) {
- // unactivate all other tabs
- tabs.forEach(tab => {
- tab.setAttribute('aria-selected', 'false');
- tab.setAttribute('tabindex', '-1');
- });
- //activate current tab
- tab.setAttribute('aria-selected', 'true');
- tab.setAttribute('tabindex', '0');
-
- // activate corresponding panel
- showTabpanel(tab);
- }
-
- var setupTabPanels = function () {
- tabpanels.forEach((tabpanel, index) => {
- tabpanel.setAttribute('role', 'tabpanel');
- tabpanel.setAttribute('tabindex', '-1');
- tabpanel.setAttribute('hidden', '');
-
- if (index == currentIndex) {
- tabpanel.removeAttribute('hidden');
- }
-
- tabpanel.addEventListener('keydown', (e) => {
- panelKeyboardRespond(e);
- }, false);
-
- tabpanel.addEventListener("blur", () => {
- tabpanel.setAttribute('tabindex', '-1');
- }, false);
- });
- }
-
-
- var panelKeyboardRespond = function (e) {
- var keyCode = e.keyCode || e.which;
-
- switch (keyCode) {
- case util.keyCodes.TAB:
- tabpanels[currentIndex].setAttribute('tabindex', '-1');
- break;
-
- default:
- break;
- }
- }
-
-
- var showTabpanel = function (tab) {
- tabpanels.forEach((tabpanel, index) => {
- tabpanel.setAttribute('hidden', '');
- tabpanel.removeAttribute('tabindex');
-
- if (index == currentIndex) {
- tabpanel.removeAttribute('hidden');
- tabpanel.setAttribute('aria-labelledby', tabs[currentIndex].getAttribute('id'));
- tabpanel.setAttribute('tabindex', '0');
- }
- });
- }
-
- var incrementcurrentIndex = function () {
- if (currentIndex < tabs.length - 1) {
- return ++currentIndex;
- }
- else {
- currentIndex = 0;
- return currentIndex;
- }
- };
-
-
- var decrementcurrentIndex = function () {
- if (currentIndex > 0) {
- return --currentIndex;
- }
- else {
- currentIndex = tabs.length - 1;
- return currentIndex;
- }
- };
-
-
-
- var tabKeyboardRespond = function (e, tab) {
- var firstTab = tabs[0];
- var lastTab = tabs[tabs.length - 1];
-
- var keyCode = e.keyCode || e.which;
-
- switch (keyCode) {
- case util.keyCodes.UP:
- case util.keyCodes.LEFT:
- e.preventDefault();
- decrementcurrentIndex();
- focusCurrentTab();
-
- if (!manual) {
- selectedTab = currentIndex;
- selectTab(tabs[selectedTab]);
- // updateUrlHash();
- }
-
- break;
-
-
- case util.keyCodes.DOWN:
- case util.keyCodes.RIGHT:
- e.preventDefault();
- incrementcurrentIndex();
- focusCurrentTab();
-
- if (!manual) {
- selectedTab = currentIndex;
- selectTab(tabs[selectedTab]);
- // updateUrlHash();
- }
-
- break;
-
-
- case util.keyCodes.ENTER:
- case util.keyCodes.SPACE:
- e.preventDefault();
- selectedTab = currentIndex;
- selectTab(tabs[selectedTab]);
- // updateUrlHash();
-
- break;
-
-
- case util.keyCodes.TAB:
- tabpanels[selectedTab].setAttribute('tabindex', '0');
- currentIndex = selectedTab;
-
- break;
-
-
- case util.keyCodes.HOME:
- e.preventDefault();
- firstTab.focus();
- // updateUrlHash();
-
- break;
-
-
- case util.keyCodes.END:
- e.preventDefault();
- lastTab.focus();
- // updateUrlHash();
-
- break;
- }
-
- }
-
- init.call(this);
- return this;
- }; // ARIAtabs()
-
- w.ARIAtabs = ARIAtabs;
-
+ var ARIAaccOptions = {
+ manual: true,
+ open: 0,
+ };
+
+ var ARIAtabs = function (inst, options) {
+ var _options = Object.assign(ARIAaccOptions, options);
+ var el = inst;
+ var tablist = el.querySelector("[data-tablist]");
+ var tabs = Array.from(el.querySelectorAll("[data-tab]"));
+ var tabpanels = Array.from(el.querySelectorAll("[data-tabpanel]"));
+ var tabsID = util.generateID("ps__tabs-");
+ var orientation = el.getAttribute("data-tabs-orientation");
+ var currentIndex = _options.open;
+ var selectedTab = currentIndex;
+ var manual = _options.manual;
+
+ el.setAttribute("id", tabsID);
+
+ var init = function () {
+ el.classList.add("js-tabs");
+ tablist.removeAttribute("hidden");
+ setupTabList();
+ setupTabs();
+ setupTabPanels();
+ };
+
+ var setupTabList = function () {
+ tablist.setAttribute("role", "tablist");
+ if (orientation == "vertical")
+ tablist.setAttribute("aria-orientation", "vertical");
+ };
+
+ var setupTabs = function () {
+ tabs.forEach((tab, index) => {
+ tab.setAttribute("role", "tab");
+ // each tab needs an ID that will be used to label its corresponding panel
+ tab.setAttribute("id", tabsID + "__tab-" + index);
+ tab.setAttribute(
+ "data-controls",
+ tabpanels[index].getAttribute("id"),
+ );
+
+ // first tab is initially active
+ if (index === currentIndex) {
+ selectTab(tab);
+ // updateUrlHash();
+ }
+
+ if (tab.getAttribute("data-controls") === util.getUrlHash()) {
+ currentIndex = index;
+ selectedTab = index;
+ selectTab(tab);
+ }
+
+ tab.addEventListener(
+ "click",
+ e => {
+ e.preventDefault();
+ currentIndex = index;
+ selectedTab = index;
+ focusCurrentTab();
+ selectTab(tab);
+ // updateUrlHash();
+ },
+ false,
+ );
+
+ tab.addEventListener(
+ "keydown",
+ e => {
+ tabKeyboardRespond(e, tab);
+ },
+ false,
+ );
+ });
+ };
+
+ var focusCurrentTab = function () {
+ tabs[currentIndex].focus();
+ };
+
+ var updateUrlHash = function () {
+ var active = tabs[selectedTab];
+ util.setUrlHash(active.getAttribute("data-controls"));
+ };
+
+ var selectTab = function (tab) {
+ // unactivate all other tabs
+ tabs.forEach(tab => {
+ tab.setAttribute("aria-selected", "false");
+ tab.setAttribute("tabindex", "-1");
+ });
+ //activate current tab
+ tab.setAttribute("aria-selected", "true");
+ tab.setAttribute("tabindex", "0");
+
+ // activate corresponding panel
+ showTabpanel(tab);
+ };
+
+ var setupTabPanels = function () {
+ tabpanels.forEach((tabpanel, index) => {
+ tabpanel.setAttribute("role", "tabpanel");
+ tabpanel.setAttribute("tabindex", "-1");
+ tabpanel.setAttribute("hidden", "");
+
+ if (index == currentIndex) {
+ tabpanel.removeAttribute("hidden");
+ }
+
+ tabpanel.addEventListener(
+ "keydown",
+ e => {
+ panelKeyboardRespond(e);
+ },
+ false,
+ );
+
+ tabpanel.addEventListener(
+ "blur",
+ () => {
+ tabpanel.setAttribute("tabindex", "-1");
+ },
+ false,
+ );
+ });
+ };
+
+ var panelKeyboardRespond = function (e) {
+ var keyCode = e.keyCode || e.which;
+
+ switch (keyCode) {
+ case util.keyCodes.TAB:
+ tabpanels[currentIndex].setAttribute("tabindex", "-1");
+ break;
+
+ default:
+ break;
+ }
+ };
+
+ var showTabpanel = function (tab) {
+ tabpanels.forEach((tabpanel, index) => {
+ tabpanel.setAttribute("hidden", "");
+ tabpanel.removeAttribute("tabindex");
+
+ if (index == currentIndex) {
+ tabpanel.removeAttribute("hidden");
+ tabpanel.setAttribute(
+ "aria-labelledby",
+ tabs[currentIndex].getAttribute("id"),
+ );
+ tabpanel.setAttribute("tabindex", "0");
+ }
+ });
+ };
+
+ var incrementcurrentIndex = function () {
+ if (currentIndex < tabs.length - 1) {
+ return ++currentIndex;
+ } else {
+ currentIndex = 0;
+ return currentIndex;
+ }
+ };
+
+ var decrementcurrentIndex = function () {
+ if (currentIndex > 0) {
+ return --currentIndex;
+ } else {
+ currentIndex = tabs.length - 1;
+ return currentIndex;
+ }
+ };
+
+ var tabKeyboardRespond = function (e, tab) {
+ var firstTab = tabs[0];
+ var lastTab = tabs[tabs.length - 1];
+
+ var keyCode = e.keyCode || e.which;
+
+ switch (keyCode) {
+ case util.keyCodes.UP:
+ case util.keyCodes.LEFT:
+ e.preventDefault();
+ decrementcurrentIndex();
+ focusCurrentTab();
+
+ if (!manual) {
+ selectedTab = currentIndex;
+ selectTab(tabs[selectedTab]);
+ // updateUrlHash();
+ }
+
+ break;
+
+ case util.keyCodes.DOWN:
+ case util.keyCodes.RIGHT:
+ e.preventDefault();
+ incrementcurrentIndex();
+ focusCurrentTab();
+
+ if (!manual) {
+ selectedTab = currentIndex;
+ selectTab(tabs[selectedTab]);
+ // updateUrlHash();
+ }
+
+ break;
+
+ case util.keyCodes.ENTER:
+ case util.keyCodes.SPACE:
+ e.preventDefault();
+ selectedTab = currentIndex;
+ selectTab(tabs[selectedTab]);
+ // updateUrlHash();
+
+ break;
+
+ case util.keyCodes.TAB:
+ tabpanels[selectedTab].setAttribute("tabindex", "0");
+ currentIndex = selectedTab;
+
+ break;
+
+ case util.keyCodes.HOME:
+ e.preventDefault();
+ firstTab.focus();
+ // updateUrlHash();
+
+ break;
+
+ case util.keyCodes.END:
+ e.preventDefault();
+ lastTab.focus();
+ // updateUrlHash();
+
+ break;
+ }
+ };
+
+ init.call(this);
+ return this;
+ }; // ARIAtabs()
+
+ w.ARIAtabs = ARIAtabs;
})(window, document);
-
var tabsInstance = "[data-tabs]";
var els = document.querySelectorAll(tabsInstance);
var allTabs = [];
// Generate all tabs instances
for (var i = 0; i < els.length; i++) {
- var nTabs = new ARIAtabs(els[i], { manual: true }); // if manual is set to false, the tabs open on focus without needing an ENTER or SPACE press
- allTabs.push(nTabs);
+ var nTabs = new ARIAtabs(els[i], { manual: true }); // if manual is set to false, the tabs open on focus without needing an ENTER or SPACE press
+ allTabs.push(nTabs);
}
diff --git a/docs/src/assets/js/themes.js b/docs/src/assets/js/themes.js
index 92d5e0cd40af..d63c9d4b4b6b 100644
--- a/docs/src/assets/js/themes.js
+++ b/docs/src/assets/js/themes.js
@@ -1,69 +1,78 @@
(function () {
- var enableToggle = function (btn) {
- btn.setAttribute("aria-pressed", "true");
- };
+ var enableToggle = function (btn) {
+ btn.setAttribute("aria-pressed", "true");
+ };
- var disableToggle = function (btns) {
- btns.forEach(btn => btn.setAttribute("aria-pressed", "false"));
- };
+ var disableToggle = function (btns) {
+ btns.forEach(btn => btn.setAttribute("aria-pressed", "false"));
+ };
- var setTheme = function (theme) {
- if (theme === "system") {
- var systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? "dark" : "light";
- document.documentElement.setAttribute('data-theme', systemTheme);
- } else {
- document.documentElement.setAttribute('data-theme', theme);
- }
- window.localStorage.setItem("theme", theme);
- };
+ var setTheme = function (theme) {
+ if (theme === "system") {
+ var systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
+ .matches
+ ? "dark"
+ : "light";
+ document.documentElement.setAttribute("data-theme", systemTheme);
+ } else {
+ document.documentElement.setAttribute("data-theme", theme);
+ }
+ window.localStorage.setItem("theme", theme);
+ };
- var initializeThemeSwitcher = function () {
- var theme = window.localStorage.getItem("theme") || "system";
- var switcher = document.getElementById('js-theme-switcher');
- switcher.removeAttribute('hidden');
+ var initializeThemeSwitcher = function () {
+ var theme = window.localStorage.getItem("theme") || "system";
+ var switcher = document.getElementById("js-theme-switcher");
+ switcher.removeAttribute("hidden");
- var lightThemeToggle = document.getElementById('light-theme-toggle');
- var darkThemeToggle = document.getElementById('dark-theme-toggle');
- var systemThemeToggle = document.getElementById('system-theme-toggle');
+ var lightThemeToggle = document.getElementById("light-theme-toggle");
+ var darkThemeToggle = document.getElementById("dark-theme-toggle");
+ var systemThemeToggle = document.getElementById("system-theme-toggle");
- var toggleButtons = [lightThemeToggle, darkThemeToggle, systemThemeToggle];
+ var toggleButtons = [
+ lightThemeToggle,
+ darkThemeToggle,
+ systemThemeToggle,
+ ];
- toggleButtons.forEach(function (btn) {
- btn.addEventListener("click", function () {
- enableToggle(btn);
- var theme = this.getAttribute('data-theme');
- setTheme(theme);
- if (btn === systemThemeToggle) {
- disableToggle([lightThemeToggle, darkThemeToggle]);
- } else if (btn === lightThemeToggle) {
- disableToggle([systemThemeToggle, darkThemeToggle]);
- } else if (btn === darkThemeToggle) {
- disableToggle([systemThemeToggle, lightThemeToggle]);
- }
- });
- });
+ toggleButtons.forEach(function (btn) {
+ btn.addEventListener("click", function () {
+ enableToggle(btn);
+ var theme = this.getAttribute("data-theme");
+ setTheme(theme);
+ if (btn === systemThemeToggle) {
+ disableToggle([lightThemeToggle, darkThemeToggle]);
+ } else if (btn === lightThemeToggle) {
+ disableToggle([systemThemeToggle, darkThemeToggle]);
+ } else if (btn === darkThemeToggle) {
+ disableToggle([systemThemeToggle, lightThemeToggle]);
+ }
+ });
+ });
- if (theme === "system") {
- enableToggle(systemThemeToggle);
- disableToggle([lightThemeToggle, darkThemeToggle]);
- } else if (theme === "light") {
- enableToggle(lightThemeToggle);
- disableToggle([systemThemeToggle, darkThemeToggle]);
- } else if (theme === "dark") {
- enableToggle(darkThemeToggle);
- disableToggle([systemThemeToggle, lightThemeToggle]);
- }
+ if (theme === "system") {
+ enableToggle(systemThemeToggle);
+ disableToggle([lightThemeToggle, darkThemeToggle]);
+ } else if (theme === "light") {
+ enableToggle(lightThemeToggle);
+ disableToggle([systemThemeToggle, darkThemeToggle]);
+ } else if (theme === "dark") {
+ enableToggle(darkThemeToggle);
+ disableToggle([systemThemeToggle, lightThemeToggle]);
+ }
- // Update theme on system preference change
- window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function () {
- var currentTheme = window.localStorage.getItem("theme");
- if (currentTheme === "system" || !currentTheme) {
- enableToggle(systemThemeToggle);
- disableToggle([lightThemeToggle, darkThemeToggle]);
- setTheme('system');
- }
- });
- };
+ // Update theme on system preference change
+ window
+ .matchMedia("(prefers-color-scheme: dark)")
+ .addEventListener("change", function () {
+ var currentTheme = window.localStorage.getItem("theme");
+ if (currentTheme === "system" || !currentTheme) {
+ enableToggle(systemThemeToggle);
+ disableToggle([lightThemeToggle, darkThemeToggle]);
+ setTheme("system");
+ }
+ });
+ };
- document.addEventListener('DOMContentLoaded', initializeThemeSwitcher);
+ document.addEventListener("DOMContentLoaded", initializeThemeSwitcher);
})();
diff --git a/docs/src/assets/scss/ads.scss b/docs/src/assets/scss/ads.scss
index 4b1b4e84e1b5..cc4ed68030c5 100644
--- a/docs/src/assets/scss/ads.scss
+++ b/docs/src/assets/scss/ads.scss
@@ -1,11 +1,11 @@
.hero-ad {
- @media all and (max-width: 800px) {
- display: none;
- }
+ @media all and (max-width: 800px) {
+ display: none;
+ }
}
.docs-ad {
- height: 290px;
+ height: 290px;
}
/*
@@ -14,113 +14,113 @@
*/
#carbonads * {
- margin: initial;
- padding: initial;
+ margin: initial;
+ padding: initial;
}
#carbonads {
- display: inline-block;
- margin: 2rem 0;
- padding: .6em;
- font-size: 1rem;
- overflow: hidden;
- background-color: var(--body-background-color);
- border: 1px solid var(--border-color);
- border-radius: 4px;
- border-radius: var(--border-radius);
- box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, 0.1);
-
- .docs-main & {
- margin: 0 0 2rem;
- }
-
- @media all and (max-width: 800px) {
- display: none !important;
- }
+ display: inline-block;
+ margin: 2rem 0;
+ padding: 0.6em;
+ font-size: 1rem;
+ overflow: hidden;
+ background-color: var(--body-background-color);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ border-radius: var(--border-radius);
+ box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, 0.1);
+
+ .docs-main & {
+ margin: 0 0 2rem;
+ }
+
+ @media all and (max-width: 800px) {
+ display: none !important;
+ }
}
.jumbotron #carbonads {
- border: solid 1px hsla(250, 20%, 50%, 0.6);
- background-color: hsla(0, 0%, 70%, 0.15);
+ border: solid 1px hsla(250, 20%, 50%, 0.6);
+ background-color: hsla(0, 0%, 70%, 0.15);
}
#carbonads a {
- font-weight: 500;
- color: inherit;
- text-decoration: none;
+ font-weight: 500;
+ color: inherit;
+ text-decoration: none;
}
#carbonads a:hover {
- text-decoration: none;
- color: var(--link-color);
+ text-decoration: none;
+ color: var(--link-color);
}
.jumbotron #carbonads a {
- color: #eee;
+ color: #eee;
}
.jumbotron #carbonads a:hover {
- color: #ccc;
+ color: #ccc;
}
#carbonads span {
- display: block;
- position: relative;
- overflow: hidden;
+ display: block;
+ position: relative;
+ overflow: hidden;
}
#carbonads .carbon-wrap {
- display: flex;
- flex-direction: column;
- max-width: 130px;
+ display: flex;
+ flex-direction: column;
+ max-width: 130px;
}
#carbonads .carbon-img img {
- display: block;
+ display: block;
}
#carbonads .carbon-text {
- margin-top: 10px;
- line-height: 1rem;
- font-size: .7em;
- font-weight: 500;
- text-align: left;
+ margin-top: 10px;
+ line-height: 1rem;
+ font-size: 0.7em;
+ font-weight: 500;
+ text-align: left;
}
#carbonads .carbon-poweredby {
- display: block;
- margin-top: 10px;
- font-size: 0.5rem;
- font-weight: 500;
- line-height: 1;
- letter-spacing: .1ch;
- text-transform: uppercase;
+ display: block;
+ margin-top: 10px;
+ font-size: 0.5rem;
+ font-weight: 500;
+ line-height: 1;
+ letter-spacing: 0.1ch;
+ text-transform: uppercase;
}
@media only screen and (min-width: 320px) and (max-width: 759px) {
- #carbonads {
- margin-top: 0;
- font-size: 12px;
- }
-
- #carbonads .carbon-wrap {
- display: flex;
- flex-direction: row;
- max-width: 330px;
- }
-
- #carbonads .carbon-text {
- margin: 0 0 14px 10px;
- font-size: 14px;
- text-align: left;
- }
-
- #carbonads .carbon-poweredby {
- position: absolute;
- bottom: 0;
- left: 142px;
- font-size: 8px;
- }
+ #carbonads {
+ margin-top: 0;
+ font-size: 12px;
+ }
+
+ #carbonads .carbon-wrap {
+ display: flex;
+ flex-direction: row;
+ max-width: 330px;
+ }
+
+ #carbonads .carbon-text {
+ margin: 0 0 14px 10px;
+ font-size: 14px;
+ text-align: left;
+ }
+
+ #carbonads .carbon-poweredby {
+ position: absolute;
+ bottom: 0;
+ left: 142px;
+ font-size: 8px;
+ }
}
/*
@@ -129,26 +129,26 @@
[data-ea-publisher].loaded .ea-content,
[data-ea-type].loaded .ea-content {
- background-color: var(--body-background-color) !important;
- border: 1px solid var(--border-color) !important;
+ background-color: var(--body-background-color) !important;
+ border: 1px solid var(--border-color) !important;
}
[data-ea-publisher].loaded .ea-content a:link,
[data-ea-type].loaded .ea-content a:link {
- color: var(--body-text-color) !important;
+ color: var(--body-text-color) !important;
}
[data-ea-publisher].loaded .ea-callout a:link,
[data-ea-type].loaded .ea-callout a:link {
- color: var(--body-text-color) !important;
+ color: var(--body-text-color) !important;
}
.jumbotron [data-ea-publisher].loaded .ea-content a,
.jumbotron [data-ea-type].loaded .ea-content a {
- color: #eee;
+ color: #eee;
}
.jumbotron [data-ea-publisher].loaded .ea-content a:hover,
.jumbotron [data-ea-type].loaded .ea-content a:hover {
- color: #ccc;
+ color: #ccc;
}
diff --git a/docs/src/assets/scss/components/alert.scss b/docs/src/assets/scss/components/alert.scss
index b71801a7beaf..1f61eeec3d68 100644
--- a/docs/src/assets/scss/components/alert.scss
+++ b/docs/src/assets/scss/components/alert.scss
@@ -1,89 +1,89 @@
.alert {
- position: relative;
- display: grid;
- grid-template-columns: auto 1fr;
- padding: 1rem;
- gap: .75rem;
- margin-bottom: 1.5rem;
- margin-block-end: 1.5rem;
- align-items: start;
- font-size: .875rem;
- border: 1px solid currentColor;
- border-radius: var(--border-radius);
-
- &.alert--warning {
- background-color: var(--alert-warning-background-color);
- color: var(--alert-warning-color);
- }
-
- &.alert--important {
- background-color: var(--alert-important-background-color);
- color: var(--alert-important-color);
- }
-
- &.alert--tip {
- background-color: var(--alert-tip-background-color);
- color: var(--alert-tip-color);
- }
+ position: relative;
+ display: grid;
+ grid-template-columns: auto 1fr;
+ padding: 1rem;
+ gap: 0.75rem;
+ margin-bottom: 1.5rem;
+ margin-block-end: 1.5rem;
+ align-items: start;
+ font-size: 0.875rem;
+ border: 1px solid currentColor;
+ border-radius: var(--border-radius);
+
+ &.alert--warning {
+ background-color: var(--alert-warning-background-color);
+ color: var(--alert-warning-color);
+ }
+
+ &.alert--important {
+ background-color: var(--alert-important-background-color);
+ color: var(--alert-important-color);
+ }
+
+ &.alert--tip {
+ background-color: var(--alert-tip-background-color);
+ color: var(--alert-tip-color);
+ }
}
.alert__icon {
- color: inherit;
- position: relative;
- top: 2px;
- offset-block-start: 2px;
+ color: inherit;
+ position: relative;
+ top: 2px;
+ offset-block-start: 2px;
}
.alert__text > p {
- margin: 0;
+ margin: 0;
}
.alert__type {
- display: block;
- font-weight: 500;
- margin-bottom: .25rem;
- margin-block-end: .25rem;
-
- .alert--warning & {
- color: var(--alert-warning-heading-color);
- }
-
- .alert--important & {
- color: var(--alert-important-heading-color);
- }
-
- .alert--tip & {
- color: var(--alert-tip-heading-color);
- }
+ display: block;
+ font-weight: 500;
+ margin-bottom: 0.25rem;
+ margin-block-end: 0.25rem;
+
+ .alert--warning & {
+ color: var(--alert-warning-heading-color);
+ }
+
+ .alert--important & {
+ color: var(--alert-important-heading-color);
+ }
+
+ .alert--tip & {
+ color: var(--alert-tip-heading-color);
+ }
}
.alert__learn-more {
- display: block;
- font-weight: 500;
- margin-top: .75rem;
- margin-block-start: .75rem;
-
- .alert--warning & {
- color: var(--color-rose-700);
-
- [data-theme="dark"] & {
- color: var(--color-rose-200);
- }
- }
-
- .alert--important & {
- color: var(--color-warning-700);
-
- [data-theme="dark"] & {
- color: var(--color-warning-200);
- }
- }
-
- .alert--tip & {
- color: var(--color-success-700);
-
- [data-theme="dark"] & {
- color: var(--color-success-200);
- }
- }
+ display: block;
+ font-weight: 500;
+ margin-top: 0.75rem;
+ margin-block-start: 0.75rem;
+
+ .alert--warning & {
+ color: var(--color-rose-700);
+
+ [data-theme="dark"] & {
+ color: var(--color-rose-200);
+ }
+ }
+
+ .alert--important & {
+ color: var(--color-warning-700);
+
+ [data-theme="dark"] & {
+ color: var(--color-warning-200);
+ }
+ }
+
+ .alert--tip & {
+ color: var(--color-success-700);
+
+ [data-theme="dark"] & {
+ color: var(--color-success-200);
+ }
+ }
}
diff --git a/docs/src/assets/scss/components/buttons.scss b/docs/src/assets/scss/components/buttons.scss
index ca0aa72a726c..f081cf87c632 100644
--- a/docs/src/assets/scss/components/buttons.scss
+++ b/docs/src/assets/scss/components/buttons.scss
@@ -1,77 +1,79 @@
button {
- border: none;
- background: none;
- font: inherit;
- cursor: pointer;
- line-height: inherit;
- display: inline-flex;
- align-items: center;
- justify-content: center;
+ border: none;
+ background: none;
+ font: inherit;
+ cursor: pointer;
+ line-height: inherit;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
}
.c-btn {
- background: none;
- border: none;
- font: inherit;
- font-family: var(--text-font);
- cursor: pointer;
- line-height: inherit;
- font-weight: 500;
- font-size: var(--step-0);
- display: inline-flex;
- padding: .75em 1.125em;
- align-items: center;
- justify-content: center;
- border-radius: var(--border-radius);
- transition: background-color .2s linear, border-color .2s linear;
+ background: none;
+ border: none;
+ font: inherit;
+ font-family: var(--text-font);
+ cursor: pointer;
+ line-height: inherit;
+ font-weight: 500;
+ font-size: var(--step-0);
+ display: inline-flex;
+ padding: 0.75em 1.125em;
+ align-items: center;
+ justify-content: center;
+ border-radius: var(--border-radius);
+ transition:
+ background-color 0.2s linear,
+ border-color 0.2s linear;
- svg {
- color: inherit;
- }
+ svg {
+ color: inherit;
+ }
}
.c-btn--large {
- font-size: 1.125rem;
- padding: .88em 1.5em;
+ font-size: 1.125rem;
+ padding: 0.88em 1.5em;
}
.c-btn--block {
- display: flex;
- width: 100%;
+ display: flex;
+ width: 100%;
}
a.c-btn {
- text-decoration: none;
- display: inline-flex;
- flex-wrap: wrap;
- gap: .5rem;
- align-items: center;
+ text-decoration: none;
+ display: inline-flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+ align-items: center;
}
.c-btn--primary {
- background-color: var(--primary-button-background-color);
- color: var(--primary-button-text-color);
+ background-color: var(--primary-button-background-color);
+ color: var(--primary-button-text-color);
- &:hover {
- background-color: var(--primary-button-hover-color);
- }
+ &:hover {
+ background-color: var(--primary-button-hover-color);
+ }
}
.c-btn--secondary {
- background-color: var(--secondary-button-background-color);
- color: var(--secondary-button-text-color);
- box-shadow: 0 1px 2px rgba(16, 24, 40, 0.1);
+ background-color: var(--secondary-button-background-color);
+ color: var(--secondary-button-text-color);
+ box-shadow: 0 1px 2px rgba(16, 24, 40, 0.1);
- &:hover {
- background-color: var(--secondary-button-hover-color);
- }
+ &:hover {
+ background-color: var(--secondary-button-hover-color);
+ }
}
.c-btn--ghost {
- color: var(--body-text-color);
- border: 1px solid var(--border-color);
+ color: var(--body-text-color);
+ border: 1px solid var(--border-color);
- &:hover {
- border-color: var(--link-color);
- }
+ &:hover {
+ border-color: var(--link-color);
+ }
}
diff --git a/docs/src/assets/scss/components/docs-index.scss b/docs/src/assets/scss/components/docs-index.scss
index 22e156eb39d8..0e0abbe4d911 100644
--- a/docs/src/assets/scss/components/docs-index.scss
+++ b/docs/src/assets/scss/components/docs-index.scss
@@ -1,164 +1,164 @@
.docs-index .docs-index__list {
- a {
- border-radius: var(--border-radius);
- text-decoration: none;
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: .5rem .75rem;
- margin-left: -.75rem;
- margin-inline-start: -.75rem;
- color: var(--headings-color);
-
- &:hover,
- &[aria-current="true"] {
- background-color: var(--docs-lightest-background-color);
- color: var(--link-color);
- }
-
- @media all and (max-width: 1023px) {
- padding: .5rem 1rem;
- margin-left: 0;
- margin-inline-start: 0;
- }
- }
+ a {
+ border-radius: var(--border-radius);
+ text-decoration: none;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.5rem 0.75rem;
+ margin-left: -0.75rem;
+ margin-inline-start: -0.75rem;
+ color: var(--headings-color);
+
+ &:hover,
+ &[aria-current="true"] {
+ background-color: var(--docs-lightest-background-color);
+ color: var(--link-color);
+ }
+
+ @media all and (max-width: 1023px) {
+ padding: 0.5rem 1rem;
+ margin-left: 0;
+ margin-inline-start: 0;
+ }
+ }
}
.docs-index__item {
- margin: 0;
+ margin: 0;
- ul ul {
- padding-left: .75rem;
- }
+ ul ul {
+ padding-left: 0.75rem;
+ }
- &[data-has-children] {
- margin-bottom: .5rem;
- }
+ &[data-has-children] {
+ margin-bottom: 0.5rem;
+ }
}
.docs-index__list > .docs-index__item {
- margin-top: 1.5rem;
- margin-block-start: 1.5rem;
-
- > a {
- color: var(--icon-color);
- text-transform: uppercase;
- letter-spacing: 1px;
- font-size: .875rem;
- font-weight: 500;
- }
+ margin-top: 1.5rem;
+ margin-block-start: 1.5rem;
+
+ > a {
+ color: var(--icon-color);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ font-size: 0.875rem;
+ font-weight: 500;
+ }
}
/* Styles for the accordion icon */
.index-js .index-icon {
- display: block !important;
- width: 0.75rem;
- height: 0.5rem;
- transform-origin: 50% 50%;
- transition: all 0.1s linear;
- color: inherit;
+ display: block !important;
+ width: 0.75rem;
+ height: 0.5rem;
+ transform-origin: 50% 50%;
+ transition: all 0.1s linear;
+ color: inherit;
}
.index-js [aria-expanded="true"] .index-icon {
- transform: rotate(180deg);
+ transform: rotate(180deg);
}
.index-js ul[aria-hidden="true"] {
- display: none;
+ display: none;
}
.index-js ul[aria-hidden="false"] {
- display: block;
+ display: block;
}
.docs__index__panel {
- &[data-open="false"] {
- display: none;
+ &[data-open="false"] {
+ display: none;
- @media all and (min-width: 1024px) {
- display: block;
- }
- }
+ @media all and (min-width: 1024px) {
+ display: block;
+ }
+ }
- &[data-open="true"] {
- display: block;
+ &[data-open="true"] {
+ display: block;
- @media all and (min-width: 1024px) {
- display: block;
- }
- }
+ @media all and (min-width: 1024px) {
+ display: block;
+ }
+ }
}
.docs-index-toggle {
- cursor: pointer;
- display: flex;
- width: 100%;
- padding: .75rem 1.125rem;
- align-items: center;
- justify-content: space-between;
- gap: .5rem;
- font-weight: 500;
- border: 1px solid var(--border-color);
- border-radius: var(--border-radius);
- background-color: var(--secondary-button-background-color);
- color: var(--secondary-button-text-color);
- box-shadow: 0 1px 2px rgba(16, 24, 40, 0.1);
-
- &:hover {
- background-color: var(--secondary-button-hover-color);
- }
-
- @media all and (min-width: 1024px) {
- display: none;
- }
-
- svg {
- width: 1.5em;
- height: 1.5em;
- color: inherit;
- fill: none;
- stroke-width: 4;
- stroke-linecap: round;
- stroke-linejoin: round;
- }
-
- #ham-top,
- #ham-middle,
- #ham-bottom {
- transition: all .2s linear;
- }
-
- #ham-top {
- transform-origin: 30px 37px;
- }
-
- #ham-bottom {
- transform-origin: 30px 63px;
- }
-
- &[aria-expanded="true"] {
- #ham-middle {
- opacity: 0;
- }
-
- #ham-top {
- transform: rotate(41deg);
- }
-
- #ham-bottom {
- transform: rotate(-41deg);
- }
- }
+ cursor: pointer;
+ display: flex;
+ width: 100%;
+ padding: 0.75rem 1.125rem;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.5rem;
+ font-weight: 500;
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ background-color: var(--secondary-button-background-color);
+ color: var(--secondary-button-text-color);
+ box-shadow: 0 1px 2px rgba(16, 24, 40, 0.1);
+
+ &:hover {
+ background-color: var(--secondary-button-hover-color);
+ }
+
+ @media all and (min-width: 1024px) {
+ display: none;
+ }
+
+ svg {
+ width: 1.5em;
+ height: 1.5em;
+ color: inherit;
+ fill: none;
+ stroke-width: 4;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+ }
+
+ #ham-top,
+ #ham-middle,
+ #ham-bottom {
+ transition: all 0.2s linear;
+ }
+
+ #ham-top {
+ transform-origin: 30px 37px;
+ }
+
+ #ham-bottom {
+ transform-origin: 30px 63px;
+ }
+
+ &[aria-expanded="true"] {
+ #ham-middle {
+ opacity: 0;
+ }
+
+ #ham-top {
+ transform: rotate(41deg);
+ }
+
+ #ham-bottom {
+ transform: rotate(-41deg);
+ }
+ }
}
.eslint-actions {
- display: inline-flex;
- flex-wrap: wrap;
- flex-direction: column;
- width: 100%;
- gap: 1rem;
-
- @media all and (min-width: 640px) {
- flex-direction: row;
- }
+ display: inline-flex;
+ flex-wrap: wrap;
+ flex-direction: column;
+ width: 100%;
+ gap: 1rem;
+
+ @media all and (min-width: 640px) {
+ flex-direction: row;
+ }
}
diff --git a/docs/src/assets/scss/components/docs-navigation.scss b/docs/src/assets/scss/components/docs-navigation.scss
index f47fce3a0a50..900fa1a3eee5 100644
--- a/docs/src/assets/scss/components/docs-navigation.scss
+++ b/docs/src/assets/scss/components/docs-navigation.scss
@@ -1,147 +1,147 @@
.docs-site-nav {
- display: flex;
- flex-direction: column;
- flex: 1;
- grid-column: 1 / -1;
- grid-row: 1;
-
- ul {
- list-style: none;
- font-size: var(--step-1);
- margin-top: 1rem;
- margin-block-start: 1rem;
- margin-bottom: 2rem;
- margin-block-end: 2rem;
-
- @media all and (min-width: 1024px) {
- font-size: var(--step-0);
- margin-top: 0;
- margin-block-start: 0;
- margin-bottom: 0;
- margin-block-end: 0;
- align-items: center;
- display: flex;
- }
- }
-
- .flexer {
- display: flex;
- justify-self: flex-end;
- align-self: flex-end;
- }
-
- a:not(.c-btn) {
- text-decoration: none;
- color: inherit;
- transition: color .2s linear;
- display: block;
-
- &:hover {
- color: var(--link-color);
- }
- }
-
- a:not(.c-btn)[aria-current="page"],
- a:not(.c-btn)[aria-current="true"] {
- color: var(--link-color);
- text-decoration: none;
- font-weight: 500;
- }
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ grid-column: 1 / -1;
+ grid-row: 1;
+
+ ul {
+ list-style: none;
+ font-size: var(--step-1);
+ margin-top: 1rem;
+ margin-block-start: 1rem;
+ margin-bottom: 2rem;
+ margin-block-end: 2rem;
+
+ @media all and (min-width: 1024px) {
+ font-size: var(--step-0);
+ margin-top: 0;
+ margin-block-start: 0;
+ margin-bottom: 0;
+ margin-block-end: 0;
+ align-items: center;
+ display: flex;
+ }
+ }
+
+ .flexer {
+ display: flex;
+ justify-self: flex-end;
+ align-self: flex-end;
+ }
+
+ a:not(.c-btn) {
+ text-decoration: none;
+ color: inherit;
+ transition: color 0.2s linear;
+ display: block;
+
+ &:hover {
+ color: var(--link-color);
+ }
+ }
+
+ a:not(.c-btn)[aria-current="page"],
+ a:not(.c-btn)[aria-current="true"] {
+ color: var(--link-color);
+ text-decoration: none;
+ font-weight: 500;
+ }
}
.docs-nav-panel {
- @media all and (min-width: 1024px) {
- display: flex;
- flex-direction: row;
- justify-content: center;
- }
-
- &[data-open="false"] {
- display: none;
- }
-
- &[data-open="true"] {
- @media all and (min-width: 1024px) {
- display: flex;
- flex-direction: row;
- justify-content: center;
- }
- }
+ @media all and (min-width: 1024px) {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ }
+
+ &[data-open="false"] {
+ display: none;
+ }
+
+ &[data-open="true"] {
+ @media all and (min-width: 1024px) {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ }
+ }
}
.docs-nav-panel .mobile-only {
- @media all and (min-width: 1024px) {
- display: none;
- }
+ @media all and (min-width: 1024px) {
+ display: none;
+ }
}
.docs-site-nav-toggle {
- cursor: pointer;
- display: inline-flex;
- align-items: center;
- margin-left: .5rem;
- margin-right: -10px;
- margin-inline-start: .5rem;
- margin-inline-end: -10px;
-
- svg {
- width: 40px;
- height: 40px;
- color: var(--headings-color);
- fill: none;
- stroke-width: 4;
- stroke-linecap: round;
- stroke-linejoin: round;
- }
-
- #ham-top,
- #ham-middle,
- #ham-bottom {
- transition: all .2s linear;
- }
-
- #ham-top {
- transform-origin: 30px 37px;
- }
-
- #ham-bottom {
- transform-origin: 30px 63px;
- }
-
- &[aria-expanded="true"] {
- #ham-middle {
- opacity: 0;
- }
-
- #ham-top {
- transform: rotate(41deg);
- }
-
- #ham-bottom {
- transform: rotate(-41deg);
- }
- }
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ margin-left: 0.5rem;
+ margin-right: -10px;
+ margin-inline-start: 0.5rem;
+ margin-inline-end: -10px;
+
+ svg {
+ width: 40px;
+ height: 40px;
+ color: var(--headings-color);
+ fill: none;
+ stroke-width: 4;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+ }
+
+ #ham-top,
+ #ham-middle,
+ #ham-bottom {
+ transition: all 0.2s linear;
+ }
+
+ #ham-top {
+ transform-origin: 30px 37px;
+ }
+
+ #ham-bottom {
+ transform-origin: 30px 63px;
+ }
+
+ &[aria-expanded="true"] {
+ #ham-middle {
+ opacity: 0;
+ }
+
+ #ham-top {
+ transform: rotate(41deg);
+ }
+
+ #ham-bottom {
+ transform: rotate(-41deg);
+ }
+ }
}
@media all and (min-width: 1024px) {
- .docs-site-nav {
- flex-direction: row;
- grid-column: auto;
- gap: 2rem;
-
- ul {
- display: flex;
- gap: 2rem;
- font-size: var(--step-0);
-
- li {
- margin-bottom: 0;
- margin-block-end: 0;
- }
- }
-
- .flexer {
- order: 1;
- }
- }
+ .docs-site-nav {
+ flex-direction: row;
+ grid-column: auto;
+ gap: 2rem;
+
+ ul {
+ display: flex;
+ gap: 2rem;
+ font-size: var(--step-0);
+
+ li {
+ margin-bottom: 0;
+ margin-block-end: 0;
+ }
+ }
+
+ .flexer {
+ order: 1;
+ }
+ }
}
diff --git a/docs/src/assets/scss/components/hero.scss b/docs/src/assets/scss/components/hero.scss
index 44a7390e0270..5a24c7348573 100644
--- a/docs/src/assets/scss/components/hero.scss
+++ b/docs/src/assets/scss/components/hero.scss
@@ -1,64 +1,64 @@
.hero .grid {
- @media all and (min-width: 800px) {
- display: grid;
- grid-template-columns: 2fr 1fr;
- grid-gap: 2rem;
- align-items: center;
- }
+ @media all and (min-width: 800px) {
+ display: grid;
+ grid-template-columns: 2fr 1fr;
+ grid-gap: 2rem;
+ align-items: center;
+ }
- .span-1-7 {
- grid-column: 1 / 2;
- }
+ .span-1-7 {
+ grid-column: 1 / 2;
+ }
- .span-10-12 {
- grid-column: 2 / 3;
- justify-self: end;
- }
+ .span-10-12 {
+ grid-column: 2 / 3;
+ justify-self: end;
+ }
}
.hero {
- border-bottom: 1px solid var(--divider-color);
- border-block-end: 1px solid var(--divider-color);
- background-color: var(--hero-background-color);
+ border-bottom: 1px solid var(--divider-color);
+ border-block-end: 1px solid var(--divider-color);
+ background-color: var(--hero-background-color);
- @media all and (min-width: 800px) {
- // when the ad is displayed
- min-height: calc(285px + var(--space-xl-4xl));
- }
+ @media all and (min-width: 800px) {
+ // when the ad is displayed
+ min-height: calc(285px + var(--space-xl-4xl));
+ }
- .content-container {
- padding: var(--space-xl-4xl) 0;
- margin: 0;
- }
+ .content-container {
+ padding: var(--space-xl-4xl) 0;
+ margin: 0;
+ }
- >.content-container {
- margin: 0 auto;
- padding: 0 calc(1rem + 1vw);
- padding-bottom: 0;
- align-items: center;
- max-width: 1700px;
+ > .content-container {
+ margin: 0 auto;
+ padding: 0 calc(1rem + 1vw);
+ padding-bottom: 0;
+ align-items: center;
+ max-width: 1700px;
- @media all and (min-width: 1700px) {
- margin: auto;
- }
- }
+ @media all and (min-width: 1700px) {
+ margin: auto;
+ }
+ }
}
.hero--homepage {
- .section-title {
- margin-bottom: 1.5rem;
- margin-block-end: 1.5rem;
- }
+ .section-title {
+ margin-bottom: 1.5rem;
+ margin-block-end: 1.5rem;
+ }
- .section-supporting-text {
- margin: 0;
- font-size: var(--step-1);
- text-align: left;
- }
+ .section-supporting-text {
+ margin: 0;
+ font-size: var(--step-1);
+ text-align: left;
+ }
- .eslint-actions {
- font-size: var(--step-1);
- margin-top: 3rem;
- margin-block-start: 3rem;
- }
+ .eslint-actions {
+ font-size: var(--step-1);
+ margin-top: 3rem;
+ margin-block-start: 3rem;
+ }
}
diff --git a/docs/src/assets/scss/components/index.scss b/docs/src/assets/scss/components/index.scss
index 5989e1f48e7a..e009644ac587 100644
--- a/docs/src/assets/scss/components/index.scss
+++ b/docs/src/assets/scss/components/index.scss
@@ -1,109 +1,109 @@
.index {
- margin-bottom: 4rem;
- margin-block-end: 4rem;
+ margin-bottom: 4rem;
+ margin-block-end: 4rem;
}
.index__item {
- margin: 0;
-
- a {
- display: block;
- color: inherit;
- text-decoration: none;
- padding: .625rem .875rem;
- font-size: var(--step-0);
- border-radius: var(--border-radius);
-
- &:hover {
- color: var(--link-color);
- }
- }
-
- a[aria-current="page"] {
- color: var(--link-color);
- background-color: var(--lightest-background-color);
- font-weight: 500;
- }
+ margin: 0;
+
+ a {
+ display: block;
+ color: inherit;
+ text-decoration: none;
+ padding: 0.625rem 0.875rem;
+ font-size: var(--step-0);
+ border-radius: var(--border-radius);
+
+ &:hover {
+ color: var(--link-color);
+ }
+ }
+
+ a[aria-current="page"] {
+ color: var(--link-color);
+ background-color: var(--lightest-background-color);
+ font-weight: 500;
+ }
}
.index__toggle {
- cursor: pointer;
- display: flex;
- width: 100%;
- padding: .75rem 1.125rem;
- align-items: center;
- justify-content: space-between;
- gap: .5rem;
- font-weight: 500;
- border: 1px solid var(--border-color);
- border-radius: var(--border-radius);
- background-color: var(--secondary-button-background-color);
- color: var(--secondary-button-text-color);
- box-shadow: 0 1px 2px rgba(16, 24, 40, 0.1);
-
- &:hover {
- background-color: var(--secondary-button-hover-color);
- }
-
- @media all and (min-width: 1024px) {
- display: none;
- }
-
- svg {
- width: 1.5em;
- height: 1.5em;
- color: inherit;
- fill: none;
- stroke-width: 4;
- stroke-linecap: round;
- stroke-linejoin: round;
- }
-
- #ham-top,
- #ham-middle,
- #ham-bottom {
- transition: all .2s linear;
- }
-
- #ham-top {
- transform-origin: 30px 37px;
- }
-
- #ham-bottom {
- transform-origin: 30px 63px;
- }
-
- &[aria-expanded="true"] {
- #ham-middle {
- opacity: 0;
- }
-
- #ham-top {
- transform: rotate(41deg);
- }
-
- #ham-bottom {
- transform: rotate(-41deg);
- }
- }
+ cursor: pointer;
+ display: flex;
+ width: 100%;
+ padding: 0.75rem 1.125rem;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.5rem;
+ font-weight: 500;
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ background-color: var(--secondary-button-background-color);
+ color: var(--secondary-button-text-color);
+ box-shadow: 0 1px 2px rgba(16, 24, 40, 0.1);
+
+ &:hover {
+ background-color: var(--secondary-button-hover-color);
+ }
+
+ @media all and (min-width: 1024px) {
+ display: none;
+ }
+
+ svg {
+ width: 1.5em;
+ height: 1.5em;
+ color: inherit;
+ fill: none;
+ stroke-width: 4;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+ }
+
+ #ham-top,
+ #ham-middle,
+ #ham-bottom {
+ transition: all 0.2s linear;
+ }
+
+ #ham-top {
+ transform-origin: 30px 37px;
+ }
+
+ #ham-bottom {
+ transform-origin: 30px 63px;
+ }
+
+ &[aria-expanded="true"] {
+ #ham-middle {
+ opacity: 0;
+ }
+
+ #ham-top {
+ transform: rotate(41deg);
+ }
+
+ #ham-bottom {
+ transform: rotate(-41deg);
+ }
+ }
}
.index__list {
- display: block;
+ display: block;
- &[data-open="false"] {
- display: none;
+ &[data-open="false"] {
+ display: none;
- @media all and (min-width: 1024px) {
- display: block;
- }
- }
+ @media all and (min-width: 1024px) {
+ display: block;
+ }
+ }
- &[data-open="true"] {
- display: block;
+ &[data-open="true"] {
+ display: block;
- @media all and (min-width: 1024px) {
- display: block;
- }
- }
+ @media all and (min-width: 1024px) {
+ display: block;
+ }
+ }
}
diff --git a/docs/src/assets/scss/components/language-switcher.scss b/docs/src/assets/scss/components/language-switcher.scss
index 364f23fed6cc..92c05f1e04ea 100644
--- a/docs/src/assets/scss/components/language-switcher.scss
+++ b/docs/src/assets/scss/components/language-switcher.scss
@@ -1,31 +1,31 @@
.switcher--language {
- display: flex;
- align-items: center;
- justify-content: center;
- flex-wrap: wrap;
- gap: .25rem .5rem;
- position: relative;
- width: 100%;
- padding: 0;
- font-size: inherit;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ gap: 0.25rem 0.5rem;
+ position: relative;
+ width: 100%;
+ padding: 0;
+ font-size: inherit;
- @media all and (min-width: 800px) {
- justify-content: flex-start;
- }
+ @media all and (min-width: 800px) {
+ justify-content: flex-start;
+ }
}
.switcher--language .label__text {
- flex: 1 0 10ch;
+ flex: 1 0 10ch;
}
.switcher--language .switcher__select {
- flex: 1 0 12rem;
+ flex: 1 0 12rem;
- @media all and (max-width: 799px) {
- max-width: 250px;
- }
+ @media all and (max-width: 799px) {
+ max-width: 250px;
+ }
}
.language-switcher {
- display: inline-flex;
+ display: inline-flex;
}
diff --git a/docs/src/assets/scss/components/logo.scss b/docs/src/assets/scss/components/logo.scss
index 3c514d2aee9b..351e6653dbe8 100644
--- a/docs/src/assets/scss/components/logo.scss
+++ b/docs/src/assets/scss/components/logo.scss
@@ -1,12 +1,12 @@
.logo-component {
- fill: var(--logo-color);
+ fill: var(--logo-color);
}
.logo-title {
- fill: var(--headings-color);
+ fill: var(--headings-color);
}
#logo-center {
- opacity: var(--logo-center-opacity);
- fill: var(--logo-center-color);
+ opacity: var(--logo-center-opacity);
+ fill: var(--logo-center-color);
}
diff --git a/docs/src/assets/scss/components/resources.scss b/docs/src/assets/scss/components/resources.scss
index 4ee2616d8db7..3a59d162c6b1 100644
--- a/docs/src/assets/scss/components/resources.scss
+++ b/docs/src/assets/scss/components/resources.scss
@@ -1,67 +1,68 @@
.resource {
- display: flex;
- border-radius: var(--border-radius);
- border: 1px solid var(--divider-color);
- background-color: var(--lightest-background-color);
- align-items: stretch;
- overflow: hidden;
- margin-bottom: .5rem;
- margin-block-end: .5rem;
- position: relative;
- transition: all .2s linear;
+ display: flex;
+ border-radius: var(--border-radius);
+ border: 1px solid var(--divider-color);
+ background-color: var(--lightest-background-color);
+ align-items: stretch;
+ overflow: hidden;
+ margin-bottom: 0.5rem;
+ margin-block-end: 0.5rem;
+ position: relative;
+ transition: all 0.2s linear;
- &:hover {
- background-color: var(--lighter-background-color);
- }
+ &:hover {
+ background-color: var(--lighter-background-color);
+ }
}
.resource__image {
- flex: 1 0 5.5rem;
- max-width: 5.5rem;
- overflow: hidden;
- padding: .25rem;
+ flex: 1 0 5.5rem;
+ max-width: 5.5rem;
+ overflow: hidden;
+ padding: 0.25rem;
- img {
- display: block;
- height: 100%;
- width: 100%;
- object-fit: contain;
- }
+ img {
+ display: block;
+ height: 100%;
+ width: 100%;
+ object-fit: contain;
+ }
}
.resource__content {
- flex: 4;
- padding: .75rem;
- align-self: center;
+ flex: 4;
+ padding: 0.75rem;
+ align-self: center;
}
-.resource__title { // a
- text-decoration: none;
- color: var(--headings-color);
- font-weight: 500;
- margin-bottom: .125rem;
+.resource__title {
+ // a
+ text-decoration: none;
+ color: var(--headings-color);
+ font-weight: 500;
+ margin-bottom: 0.125rem;
- &::after {
- content: "";
- position: absolute;
- left: 0;
- offset-inline-start: 0;
- top: 0;
- offset-block-start: 0;
- width: 100%;
- height: 100%;
- }
+ &::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ offset-inline-start: 0;
+ top: 0;
+ offset-block-start: 0;
+ width: 100%;
+ height: 100%;
+ }
}
.resource__domain,
.resource__domain a {
- text-decoration: none;
- color: var(--body-text-color);
- font-size: .875rem;
+ text-decoration: none;
+ color: var(--body-text-color);
+ font-size: 0.875rem;
}
.resource__icon {
- color: var(--headings-color);
- margin: 1rem;
- align-self: center;
+ color: var(--headings-color);
+ margin: 1rem;
+ align-self: center;
}
diff --git a/docs/src/assets/scss/components/rules.scss b/docs/src/assets/scss/components/rules.scss
index c510dfeb5663..6754851337fc 100644
--- a/docs/src/assets/scss/components/rules.scss
+++ b/docs/src/assets/scss/components/rules.scss
@@ -1,203 +1,207 @@
.rule-categories {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
- gap: 0;
- margin-bottom: 3rem;
- background-color: var(--lightest-background-color);
- border: 1px solid var(--divider-color);
- border-radius: var(--border-radius);
-
- .rule-category {
- margin: 0;
- padding: 1rem;
- background: none;
- border: none;
-
- @media screen and (min-width: 768px) {
- &:not(:first-child)::after {
- content: "";
- display: block;
- border-left: 1px solid var(--divider-color);
- left: 0;
- }
-
- &:nth-child(2)::after {
- height: 70%;
- position: absolute;
- }
- }
-
- @media screen and (min-width: 768px) and (max-width: 799px), screen and (min-width: 854px) and (max-width: 1023px), screen and (min-width: 1256px) {
- &:nth-child(3)::after {
- height: 70%;
- position: absolute;
- }
- }
-
- @media screen and (min-width: 800px) and (max-width: 853px), screen and (min-width: 1024px) and (max-width: 1255px), screen and (min-width: 1654px) and (max-width: 1982px) {
- &:nth-child(4)::after {
- height: 70%;
- position: absolute;
- }
- }
- }
-
- .rule-category__description {
- height: 100%;
- }
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 0;
+ margin-bottom: 3rem;
+ background-color: var(--lightest-background-color);
+ border: 1px solid var(--divider-color);
+ border-radius: var(--border-radius);
+
+ .rule-category {
+ margin: 0;
+ padding: 1rem;
+ background: none;
+ border: none;
+
+ @media screen and (min-width: 768px) {
+ &:not(:first-child)::after {
+ content: "";
+ display: block;
+ border-left: 1px solid var(--divider-color);
+ left: 0;
+ }
+
+ &:nth-child(2)::after {
+ height: 70%;
+ position: absolute;
+ }
+ }
+
+ @media screen and (min-width: 768px) and (max-width: 799px),
+ screen and (min-width: 854px) and (max-width: 1023px),
+ screen and (min-width: 1256px) {
+ &:nth-child(3)::after {
+ height: 70%;
+ position: absolute;
+ }
+ }
+
+ @media screen and (min-width: 800px) and (max-width: 853px),
+ screen and (min-width: 1024px) and (max-width: 1255px),
+ screen and (min-width: 1654px) and (max-width: 1982px) {
+ &:nth-child(4)::after {
+ height: 70%;
+ position: absolute;
+ }
+ }
+ }
+
+ .rule-category__description {
+ height: 100%;
+ }
}
.rule-category {
- font-size: var(--step--1);
- display: flex;
- position: relative;
- flex-wrap: wrap;
- align-items: flex-start;
- gap: 1rem;
- padding: 1rem;
- margin: 1.5rem 0;
- border-radius: var(--border-radius);
- border: 1px solid var(--divider-color);
- background-color: var(--lightest-background-color);
-
- p {
- margin: 0;
- }
+ font-size: var(--step--1);
+ display: flex;
+ position: relative;
+ flex-wrap: wrap;
+ align-items: flex-start;
+ gap: 1rem;
+ padding: 1rem;
+ margin: 1.5rem 0;
+ border-radius: var(--border-radius);
+ border: 1px solid var(--divider-color);
+ background-color: var(--lightest-background-color);
+
+ p {
+ margin: 0;
+ }
}
.rule:not(.token) {
- border-radius: var(--border-radius);
- background-color: var(--lightest-background-color);
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- gap: 1rem;
- padding: 1rem;
- margin: .5rem 0;
- position: relative;
-
- p:last-of-type {
- margin: 0;
- }
+ border-radius: var(--border-radius);
+ background-color: var(--lightest-background-color);
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 1rem;
+ padding: 1rem;
+ margin: 0.5rem 0;
+ position: relative;
+
+ p:last-of-type {
+ margin: 0;
+ }
}
.rule__content {
- flex: 1 1 35ch;
- overflow-x: auto;
+ flex: 1 1 35ch;
+ overflow-x: auto;
}
.rule__name_wrapper {
- display: flex;
- align-items: center;
- gap: 0.5rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
- .frozen {
- font-size: .875rem;
- }
+ .frozen {
+ font-size: 0.875rem;
+ }
}
.rule__name {
- font-weight: 500;
- font-size: .875rem;
- margin-bottom: .25rem;
- margin-block-end: .25rem;
+ font-weight: 500;
+ font-size: 0.875rem;
+ margin-bottom: 0.25rem;
+ margin-block-end: 0.25rem;
}
a.rule__name {
- text-decoration: none;
-
- &:hover {
- text-decoration: underline;
- }
-
- &::after {
- position: absolute;
- content: "";
- width: 100%;
- height: 100%;
- top: 0;
- offset-block-start: 0;
- left: 0;
- offset-inline-start: 0;
- }
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+
+ &::after {
+ position: absolute;
+ content: "";
+ width: 100%;
+ height: 100%;
+ top: 0;
+ offset-block-start: 0;
+ left: 0;
+ offset-inline-start: 0;
+ }
}
.rule__description {
- font-size: var(--step--1);
+ font-size: var(--step--1);
}
.rule__categories {
- font-size: .875rem;
- display: flex;
- align-items: center;
- gap: 1rem;
- border-radius: var(--border-radius);
- padding: 2px 4px;
-
- p {
- display: inline-flex;
- margin: 0;
- align-items: center;
- }
-
- [data-theme="dark"] & {
- background: var(--body-background-color);
- }
+ font-size: 0.875rem;
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ border-radius: var(--border-radius);
+ padding: 2px 4px;
+
+ p {
+ display: inline-flex;
+ margin: 0;
+ align-items: center;
+ }
+
+ [data-theme="dark"] & {
+ background: var(--body-background-color);
+ }
}
.rule__status {
- color: var(--color-rose-500);
- background: var(--rule-status-background-color);
- border-radius: var(--border-radius);
- display: inline-block;
- font-weight: normal;
- margin-left: .5rem;
- margin-inline-start: .5rem;
- font-size: var(--step--1);
- padding: 0 .5rem;
+ color: var(--color-rose-500);
+ background: var(--rule-status-background-color);
+ border-radius: var(--border-radius);
+ display: inline-block;
+ font-weight: normal;
+ margin-left: 0.5rem;
+ margin-inline-start: 0.5rem;
+ font-size: var(--step--1);
+ padding: 0 0.5rem;
}
.rule__categories__type {
- &[aria-hidden="true"] {
- opacity: .25;
- }
+ &[aria-hidden="true"] {
+ opacity: 0.25;
+ }
}
/* related rules */
.related-rules__list {
- display: flex;
- gap: .5rem;
- flex-wrap: wrap;
- justify-content: start;
+ display: flex;
+ gap: 0.5rem;
+ flex-wrap: wrap;
+ justify-content: start;
}
.related-rules__list__item {
- svg {
- color: inherit;
- }
-
- a {
- text-decoration: none;
- color: var(--headings-color);
- padding: .625rem;
- display: inline-flex;
- gap: .5rem;
- align-items: center;
- border: 1px solid var(--divider-color);
- border-radius: var(--border-radius);
- background-color: var(--lightest-background-color);
-
- &:hover {
- color: var(--link-color);
- background-color: var(--lighter-background-color);
- }
- }
+ svg {
+ color: inherit;
+ }
+
+ a {
+ text-decoration: none;
+ color: var(--headings-color);
+ padding: 0.625rem;
+ display: inline-flex;
+ gap: 0.5rem;
+ align-items: center;
+ border: 1px solid var(--divider-color);
+ border-radius: var(--border-radius);
+ background-color: var(--lightest-background-color);
+
+ &:hover {
+ color: var(--link-color);
+ background-color: var(--lighter-background-color);
+ }
+ }
}
a.rule-list-item + a.rule-list-item::before {
- content: ",";
- display: inline-block;
- margin-left: 5px;
- margin-right: 5px;
+ content: ",";
+ display: inline-block;
+ margin-left: 5px;
+ margin-right: 5px;
}
diff --git a/docs/src/assets/scss/components/search.scss b/docs/src/assets/scss/components/search.scss
index 20871924b337..9f942657e70f 100644
--- a/docs/src/assets/scss/components/search.scss
+++ b/docs/src/assets/scss/components/search.scss
@@ -1,184 +1,184 @@
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
- appearance: none;
+ appearance: none;
}
[type="search"]::-ms-clear,
[type="search"]::-ms-reveal {
- display: none;
- width: 0;
- height: 0;
+ display: none;
+ width: 0;
+ height: 0;
}
.search {
- margin: 1rem 0;
- position: relative;
+ margin: 1rem 0;
+ position: relative;
}
.search__input-wrapper,
.search__inner-input-wrapper {
- position: relative;
+ position: relative;
}
.search__clear-btn {
- color: var(--body-text-color);
- position: absolute;
- display: flex;
- top: 25%;
- offset-block-start: 25%;
- transform: translateY(-25%);
- right: 1rem;
- offset-inline-end: 1.5rem;
- z-index: 3;
- padding: 0;
-
- svg {
- color: inherit;
- width: 1rem;
- height: 1rem;
- border: 1px solid;
- border-radius: 50%;
- }
+ color: var(--body-text-color);
+ position: absolute;
+ display: flex;
+ top: 25%;
+ offset-block-start: 25%;
+ transform: translateY(-25%);
+ right: 1rem;
+ offset-inline-end: 1.5rem;
+ z-index: 3;
+ padding: 0;
+
+ svg {
+ color: inherit;
+ width: 1rem;
+ height: 1rem;
+ border: 1px solid;
+ border-radius: 50%;
+ }
}
.search__input {
- padding-left: 2.5rem;
- padding-inline-start: 2.5rem;
- outline-offset: 1px;
- width: 100%;
- padding-right: 2.5rem;
- padding-inline-end: 2.5rem;
+ padding-left: 2.5rem;
+ padding-inline-start: 2.5rem;
+ outline-offset: 1px;
+ width: 100%;
+ padding-right: 2.5rem;
+ padding-inline-end: 2.5rem;
}
.search__icon {
- color: var(--body-text-color);
- position: absolute;
- display: block;
- top: .75rem;
- left: .75rem;
- offset-inline-start: .75rem;
- z-index: 3;
+ color: var(--body-text-color);
+ position: absolute;
+ display: block;
+ top: 0.75rem;
+ left: 0.75rem;
+ offset-inline-start: 0.75rem;
+ z-index: 3;
}
.search__inner-input-wrapper {
- display: flex;
- flex-direction: column;
- align-items: flex-end;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
}
.search_powered-by-wrapper {
- text-decoration: none;
-
- .search__powered-by {
- display: flex;
- padding: 10px 6px 0 0;
- align-items: center;
-
- .powered_by-text {
- color: var(--body-text-color);
- margin-right: 5px;
- margin-top: -2px;
- }
-
- .algolia-logo {
- fill: var(--body-text-color);
- }
- }
+ text-decoration: none;
+
+ .search__powered-by {
+ display: flex;
+ padding: 10px 6px 0 0;
+ align-items: center;
+
+ .powered_by-text {
+ color: var(--body-text-color);
+ margin-right: 5px;
+ margin-top: -2px;
+ }
+
+ .algolia-logo {
+ fill: var(--body-text-color);
+ }
+ }
}
/* search results */
.search .search-results {
- font-size: .875rem;
- background-color: var(--body-background-color);
- z-index: 10;
- width: 100%;
- border-radius: 0 0 var(--border-radius) var(--border-radius);
- border: 1px solid var(--divider-color);
- position: absolute;
- top: calc(100% - 1.5rem);
- max-height: 400px;
- overflow-y: auto;
- box-shadow: var(--shadow-lg);
-
- &[data-results="true"] {
- padding: 0;
- }
-
- &[data-results="false"] {
- padding: 1rem;
- }
-
- &:empty {
- display: none;
- }
+ font-size: 0.875rem;
+ background-color: var(--body-background-color);
+ z-index: 10;
+ width: 100%;
+ border-radius: 0 0 var(--border-radius) var(--border-radius);
+ border: 1px solid var(--divider-color);
+ position: absolute;
+ top: calc(100% - 1.5rem);
+ max-height: 400px;
+ overflow-y: auto;
+ box-shadow: var(--shadow-lg);
+
+ &[data-results="true"] {
+ padding: 0;
+ }
+
+ &[data-results="false"] {
+ padding: 1rem;
+ }
+
+ &:empty {
+ display: none;
+ }
}
.search-results__list {
- list-style: none;
- margin: 0;
- padding: 0;
+ list-style: none;
+ margin: 0;
+ padding: 0;
}
.search .search-results__item {
- margin: 0;
- padding: .875rem;
- border-bottom: 1px solid var(--lightest-background-color);
- border-block-end: 1px solid var(--lightest-background-color);
- position: relative;
-
- &:hover {
- background-color: var(--lightest-background-color);
- }
-
- &:focus-within {
- background-color: var(--lightest-background-color);
- }
+ margin: 0;
+ padding: 0.875rem;
+ border-bottom: 1px solid var(--lightest-background-color);
+ border-block-end: 1px solid var(--lightest-background-color);
+ position: relative;
+
+ &:hover {
+ background-color: var(--lightest-background-color);
+ }
+
+ &:focus-within {
+ background-color: var(--lightest-background-color);
+ }
}
.search .search-results__item__title {
- font-size: var(--step-0);
- font-size: .875rem;
- margin-bottom: 0;
- font-family: var(--text-font);
-
- a {
- display: block;
- text-decoration: none;
- color: var(--link-color);
- font: inherit;
- padding: .25rem .75rem;
-
- &:hover {
- background-color: inherit;
- color: var(--link-color);
- }
-
- &::after {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- content: "";
- }
- }
+ font-size: var(--step-0);
+ font-size: 0.875rem;
+ margin-bottom: 0;
+ font-family: var(--text-font);
+
+ a {
+ display: block;
+ text-decoration: none;
+ color: var(--link-color);
+ font: inherit;
+ padding: 0.25rem 0.75rem;
+
+ &:hover {
+ background-color: inherit;
+ color: var(--link-color);
+ }
+
+ &::after {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ content: "";
+ }
+ }
}
.search-results__item__context {
- margin: 0;
- font-size: .875rem;
- padding-left: 1rem;
+ margin: 0;
+ font-size: 0.875rem;
+ padding-left: 1rem;
}
.algolia-docsearch-suggestion--highlight {
- background-color: var(--color-brand);
- color: #fff;
- display: inline-block;
- padding: 0 2px;
- border-radius: 2px;
-
- [data-theme="dark"] & {
- background-color: var(--link-color);
- color: var(--color-neutral-900);
- }
+ background-color: var(--color-brand);
+ color: #fff;
+ display: inline-block;
+ padding: 0 2px;
+ border-radius: 2px;
+
+ [data-theme="dark"] & {
+ background-color: var(--link-color);
+ color: var(--color-neutral-900);
+ }
}
diff --git a/docs/src/assets/scss/components/social-icons.scss b/docs/src/assets/scss/components/social-icons.scss
index 86ba6a27f6ff..24048d5ce7b9 100644
--- a/docs/src/assets/scss/components/social-icons.scss
+++ b/docs/src/assets/scss/components/social-icons.scss
@@ -1,26 +1,26 @@
.eslint-social-icons {
- margin-bottom: -1rem;
- margin-block-end: -1rem;
+ margin-bottom: -1rem;
+ margin-block-end: -1rem;
- ul {
- margin: 0;
- padding: 0;
- margin-left: -1rem;
- margin-inline-start: -1rem;
- display: inline-flex;
+ ul {
+ margin: 0;
+ padding: 0;
+ margin-left: -1rem;
+ margin-inline-start: -1rem;
+ display: inline-flex;
- li {
- margin: 0;
- align-items: center;
+ li {
+ margin: 0;
+ align-items: center;
- a {
- display: flex;
- padding: 1rem .75rem;
- }
- }
+ a {
+ display: flex;
+ padding: 1rem 0.75rem;
+ }
+ }
- @media screen and (min-width: 800px) and (max-width: 1500px) {
- flex-wrap: wrap;
- }
- }
+ @media screen and (min-width: 800px) and (max-width: 1500px) {
+ flex-wrap: wrap;
+ }
+ }
}
diff --git a/docs/src/assets/scss/components/tabs.scss b/docs/src/assets/scss/components/tabs.scss
index 8a7d866c514c..67cdfc89be0c 100644
--- a/docs/src/assets/scss/components/tabs.scss
+++ b/docs/src/assets/scss/components/tabs.scss
@@ -1,63 +1,66 @@
.c-tabs {
- pre {
- margin-top: 0;
- margin-block-start: 0;
- }
+ pre {
+ margin-top: 0;
+ margin-block-start: 0;
+ }
}
.c-tabs__tablist {
- .js-tabs & {
- display: flex;
- justify-content: start;
- }
+ .js-tabs & {
+ display: flex;
+ justify-content: start;
+ }
}
.c-tabs__tab {
- background: none;
- border: none;
- margin: 0;
- color: inherit;
- font: inherit;
- cursor: pointer;
- line-height: inherit;
- font-weight: 500;
- font-size: var(--step-0);
- display: inline-flex;
- padding: .75rem 1.125rem;
- align-items: center;
- justify-content: center;
- border-radius: var(--border-radius) var(--border-radius) 0 0;
- transition: background-color .2s linear, border-color .2s linear;
-
- &:hover {
- color: var(--link-color);
- }
-
- &[aria-selected="true"] {
- color: var(--link-color);
- background-color: var(--lightest-background-color);
- }
+ background: none;
+ border: none;
+ margin: 0;
+ color: inherit;
+ font: inherit;
+ cursor: pointer;
+ line-height: inherit;
+ font-weight: 500;
+ font-size: var(--step-0);
+ display: inline-flex;
+ padding: 0.75rem 1.125rem;
+ align-items: center;
+ justify-content: center;
+ border-radius: var(--border-radius) var(--border-radius) 0 0;
+ transition:
+ background-color 0.2s linear,
+ border-color 0.2s linear;
+
+ &:hover {
+ color: var(--link-color);
+ }
+
+ &[aria-selected="true"] {
+ color: var(--link-color);
+ background-color: var(--lightest-background-color);
+ }
}
.c-tabs__tabpanel {
- margin-bottom: 2rem;
- margin-block-end: 2rem;
- background-color: var(--lightest-background-color);
- border-radius: 0 var(--border-radius) var(--border-radius) var(--border-radius);
-
- .js-tabs & {
- margin-bottom: 0;
- margin-block-end: 0;
- }
+ margin-bottom: 2rem;
+ margin-block-end: 2rem;
+ background-color: var(--lightest-background-color);
+ border-radius: 0 var(--border-radius) var(--border-radius)
+ var(--border-radius);
+
+ .js-tabs & {
+ margin-bottom: 0;
+ margin-block-end: 0;
+ }
}
.c-tabs__tabpanel__title {
- margin-bottom: 1.5rem;
- margin-block-end: 1.5rem;
+ margin-bottom: 1.5rem;
+ margin-block-end: 1.5rem;
}
// when the js is enabled, the tabpanels are labelled by their tabs
// you may choose to hide or keep the headings inside of them visible
.js-tabs .c-tabs__tabpanel__title {
- display: none;
+ display: none;
}
diff --git a/docs/src/assets/scss/components/theme-switcher.scss b/docs/src/assets/scss/components/theme-switcher.scss
index 79c2db5f3f11..69277fa2c1f6 100644
--- a/docs/src/assets/scss/components/theme-switcher.scss
+++ b/docs/src/assets/scss/components/theme-switcher.scss
@@ -1,77 +1,77 @@
.theme-switcher {
- display: inline-flex;
- align-items: center;
- gap: .5rem;
- position: relative;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+ position: relative;
}
.theme-switcher-label.theme-switcher-label {
- color: inherit;
- font: inherit;
- font-family: var(--text-font);
- margin: 0;
+ color: inherit;
+ font: inherit;
+ font-family: var(--text-font);
+ margin: 0;
}
.theme-switcher__buttons {
- display: flex;
- border: 1px solid var(--border-color);
- border-radius: var(--border-radius);
- background-color: var(--body-background-color);
+ display: flex;
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ background-color: var(--body-background-color);
}
.theme-switcher__button {
- flex-wrap: wrap;
- box-shadow: var(--shadow-xs);
- padding: .625rem .675rem;
- display: inline-flex;
- align-items: center;
- margin: 0;
- gap: .25rem;
- color: inherit;
+ flex-wrap: wrap;
+ box-shadow: var(--shadow-xs);
+ padding: 0.625rem 0.675rem;
+ display: inline-flex;
+ align-items: center;
+ margin: 0;
+ gap: 0.25rem;
+ color: inherit;
- &:first-of-type {
- border-right: .5px solid var(--border-color);
- border-inline-end: .5px solid var(--border-color);
- }
+ &:first-of-type {
+ border-right: 0.5px solid var(--border-color);
+ border-inline-end: 0.5px solid var(--border-color);
+ }
- &:last-of-type {
- border-left: .5px solid var(--border-color);
- border-inline-start: .5px solid var(--border-color);
- }
+ &:last-of-type {
+ border-left: 0.5px solid var(--border-color);
+ border-inline-start: 0.5px solid var(--border-color);
+ }
- .theme-switcher__icon {
- color: var(--icon-color);
- }
+ .theme-switcher__icon {
+ color: var(--icon-color);
+ }
- &:hover {
- .theme-switcher__icon {
- color: var(--link-color);
- }
- }
+ &:hover {
+ .theme-switcher__icon {
+ color: var(--link-color);
+ }
+ }
}
.theme-switcher__button[aria-pressed="true"] {
- color: var(--link-color);
+ color: var(--link-color);
- .theme-switcher__icon {
- color: var(--link-color);
- }
+ .theme-switcher__icon {
+ color: var(--link-color);
+ }
- &:hover {
- .theme-switcher__icon {
- color: var(--link-color);
- }
- }
+ &:hover {
+ .theme-switcher__icon {
+ color: var(--link-color);
+ }
+ }
}
.theme-switcher__button[aria-pressed="false"] {
- .theme-switcher__icon {
- color: var(--icon-color);
- }
+ .theme-switcher__icon {
+ color: var(--icon-color);
+ }
- &:hover {
- .theme-switcher__icon {
- color: var(--link-color);
- }
- }
+ &:hover {
+ .theme-switcher__icon {
+ color: var(--link-color);
+ }
+ }
}
diff --git a/docs/src/assets/scss/components/toc.scss b/docs/src/assets/scss/components/toc.scss
index 96647b4c70f0..10440effd068 100644
--- a/docs/src/assets/scss/components/toc.scss
+++ b/docs/src/assets/scss/components/toc.scss
@@ -1,135 +1,135 @@
.docs-toc {
- margin: 2rem 0;
+ margin: 2rem 0;
- @media all and (min-width: 1400px) {
- display: none;
- }
+ @media all and (min-width: 1400px) {
+ display: none;
+ }
- .docs-aside & {
- display: none;
+ .docs-aside & {
+ display: none;
- @media all and (min-width: 1400px) {
- display: block;
- }
- }
+ @media all and (min-width: 1400px) {
+ display: block;
+ }
+ }
}
.docs-aside {
- // for sticky table of contents in sidebar
- .docs-toc.c-toc {
- background-color: var(--body-background-color);
- @media all and (min-width: 1400px) {
- position: sticky;
- top: 20px;
- overflow-y: auto; // show scrollbar when toc is higher than viewport
- padding-right: 5px; // push scrollbar away from content
- max-height: calc(100vh - 32px); // minus element's margin-top
- a.active {
- color: var(--link-color);
- font-weight: 500;
- }
- }
- }
-
- .c-toc ol li.active::before {
- @media all and (min-width: 1400px) {
- color: var(--link-color);
- }
- }
+ // for sticky table of contents in sidebar
+ .docs-toc.c-toc {
+ background-color: var(--body-background-color);
+ @media all and (min-width: 1400px) {
+ position: sticky;
+ top: 20px;
+ overflow-y: auto; // show scrollbar when toc is higher than viewport
+ padding-right: 5px; // push scrollbar away from content
+ max-height: calc(100vh - 32px); // minus element's margin-top
+ a.active {
+ color: var(--link-color);
+ font-weight: 500;
+ }
+ }
+ }
+
+ .c-toc ol li.active::before {
+ @media all and (min-width: 1400px) {
+ color: var(--link-color);
+ }
+ }
}
.c-toc {
- ol {
- margin: 0;
-
- li {
- position: relative;
- margin-bottom: .25rem;
- margin-block-end: .25rem;
- padding-left: 1rem;
- padding-inline-start: 1rem;
-
- >ol {
- margin-top: .25rem;
- }
- }
-
- li::before {
- content: "â";
- color: var(--icon-color);
- position: absolute;
- left: -.4rem;
- offset-inline-start: -.4rem;
- }
- }
-
- a {
- text-decoration: none;
- color: var(--headings-color);
-
- &:hover {
- color: var(--link-color);
- }
- }
+ ol {
+ margin: 0;
+
+ li {
+ position: relative;
+ margin-bottom: 0.25rem;
+ margin-block-end: 0.25rem;
+ padding-left: 1rem;
+ padding-inline-start: 1rem;
+
+ > ol {
+ margin-top: 0.25rem;
+ }
+ }
+
+ li::before {
+ content: "â";
+ color: var(--icon-color);
+ position: absolute;
+ left: -0.4rem;
+ offset-inline-start: -0.4rem;
+ }
+ }
+
+ a {
+ text-decoration: none;
+ color: var(--headings-color);
+
+ &:hover {
+ color: var(--link-color);
+ }
+ }
}
.c-toc__label.c-toc__label {
- font-size: var(--step-0);
- color: var(--body-text-color);
- font-family: var(--text-font);
- margin-bottom: .5rem;
- margin-block-end: .5rem;
+ font-size: var(--step-0);
+ color: var(--body-text-color);
+ font-family: var(--text-font);
+ margin-bottom: 0.5rem;
+ margin-block-end: 0.5rem;
}
.c-toc__label {
- width: fit-content;
-
- button {
- color: var(--link-color);
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font: inherit;
- font-size: inherit;
- font-weight: 500;
- width: 100%;
- height: 100%;
- text-align: left;
- line-height: 1.5;
- padding: 0;
- border-radius: 0;
- position: relative;
- transition: outline 0.1s linear;
-
- svg {
- flex: none;
- }
- }
+ width: fit-content;
+
+ button {
+ color: var(--link-color);
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font: inherit;
+ font-size: inherit;
+ font-weight: 500;
+ width: 100%;
+ height: 100%;
+ text-align: left;
+ line-height: 1.5;
+ padding: 0;
+ border-radius: 0;
+ position: relative;
+ transition: outline 0.1s linear;
+
+ svg {
+ flex: none;
+ }
+ }
}
/* Styles for the accordion icon */
.toc-trigger-icon {
- display: block !important; // to override aria-hidden
- width: 0.75rem;
- height: 0.5rem;
- transform-origin: 50% 50%;
- margin-left: 2rem;
- margin-inline-start: 2rem;
- transition: all 0.1s linear;
- color: var(--color-neutral-400);
-
- [aria-expanded="true"] & {
- transform: rotate(180deg);
- }
+ display: block !important; // to override aria-hidden
+ width: 0.75rem;
+ height: 0.5rem;
+ transform-origin: 50% 50%;
+ margin-left: 2rem;
+ margin-inline-start: 2rem;
+ transition: all 0.1s linear;
+ color: var(--color-neutral-400);
+
+ [aria-expanded="true"] & {
+ transform: rotate(180deg);
+ }
}
.c-toc__panel {
- &[data-open="false"] {
- display: none;
- }
+ &[data-open="false"] {
+ display: none;
+ }
- &[data-open="true"] {
- display: block;
- }
+ &[data-open="true"] {
+ display: block;
+ }
}
diff --git a/docs/src/assets/scss/components/version-switcher.scss b/docs/src/assets/scss/components/version-switcher.scss
index 606b802395cb..95079922f5d0 100644
--- a/docs/src/assets/scss/components/version-switcher.scss
+++ b/docs/src/assets/scss/components/version-switcher.scss
@@ -1,4 +1,4 @@
.version-switcher {
- margin-bottom: .5rem;
- margin-block-end: .5rem;
+ margin-bottom: 0.5rem;
+ margin-block-end: 0.5rem;
}
diff --git a/docs/src/assets/scss/docs-footer.scss b/docs/src/assets/scss/docs-footer.scss
index 347afd3978e6..994004fb3e3a 100644
--- a/docs/src/assets/scss/docs-footer.scss
+++ b/docs/src/assets/scss/docs-footer.scss
@@ -1,50 +1,50 @@
.docs-footer {
- display: flex;
- flex-direction: column;
- gap: 2rem;
- justify-content: space-between;
- align-items: baseline;
- font-size: .875rem;
-
- @media all and (max-width: 800px) {
- padding: 1.5rem 0 4rem;
- align-items: center;
- }
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+ justify-content: space-between;
+ align-items: baseline;
+ font-size: 0.875rem;
+
+ @media all and (max-width: 800px) {
+ padding: 1.5rem 0 4rem;
+ align-items: center;
+ }
}
.copyright p {
- margin: 0;
+ margin: 0;
}
.docs-socials-and-legal {
- display: flex;
- flex-direction: column;
- gap: 1rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
- @media all and (max-width: 800px) {
- text-align: center;
- }
+ @media all and (max-width: 800px) {
+ text-align: center;
+ }
}
.docs-switchers {
- display: flex;
- flex-wrap: wrap;
- gap: 1.5rem;
-
- .theme-switcher,
- .language-switcher {
- flex: 1 1 240px;
- }
-
- .theme-switcher {
- @media all and (max-width: 800px) {
- justify-content: center;
- }
- }
-
- .language-switcher {
- @media all and (max-width: 800px) {
- justify-content: center;
- }
- }
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1.5rem;
+
+ .theme-switcher,
+ .language-switcher {
+ flex: 1 1 240px;
+ }
+
+ .theme-switcher {
+ @media all and (max-width: 800px) {
+ justify-content: center;
+ }
+ }
+
+ .language-switcher {
+ @media all and (max-width: 800px) {
+ justify-content: center;
+ }
+ }
}
diff --git a/docs/src/assets/scss/docs-header.scss b/docs/src/assets/scss/docs-header.scss
index 15f21cf47eef..50cc4ad7bc3b 100644
--- a/docs/src/assets/scss/docs-header.scss
+++ b/docs/src/assets/scss/docs-header.scss
@@ -1,43 +1,43 @@
.site-header {
- padding: .75rem 0;
- border-top: 4px solid var(--link-color);
- border-bottom: 1px solid var(--divider-color);
- border-block-start: 4px solid var(--link-color);
- border-block-end: 1px solid var(--divider-color);
+ padding: 0.75rem 0;
+ border-top: 4px solid var(--link-color);
+ border-bottom: 1px solid var(--divider-color);
+ border-block-start: 4px solid var(--link-color);
+ border-block-end: 1px solid var(--divider-color);
- .docs-wrapper {
- display: grid;
- align-items: start;
- padding-top: 0;
- padding-bottom: 0;
- padding-block-start: 0;
- padding-block-end: 0;
- max-width: 1700px;
+ .docs-wrapper {
+ display: grid;
+ align-items: start;
+ padding-top: 0;
+ padding-bottom: 0;
+ padding-block-start: 0;
+ padding-block-end: 0;
+ max-width: 1700px;
- @media all and (min-width: 1024px) {
- justify-content: space-between;
- }
- @media all and (min-width: 1700px) {
- margin: auto;
- }
- }
+ @media all and (min-width: 1024px) {
+ justify-content: space-between;
+ }
+ @media all and (min-width: 1700px) {
+ margin: auto;
+ }
+ }
}
.logo-link {
- display: inline-flex;
- justify-self: start;
- flex: none;
- place-content: center;
- grid-column: 1 / -1;
- grid-row: 1;
- padding: .5rem 0;
+ display: inline-flex;
+ justify-self: start;
+ flex: none;
+ place-content: center;
+ grid-column: 1 / -1;
+ grid-row: 1;
+ padding: 0.5rem 0;
}
.logo svg {
- display: inline-block;
- margin-bottom: -4px;
- margin-block-end: -4px;
- width: 100%;
- max-width: 100px;
- height: auto;
+ display: inline-block;
+ margin-bottom: -4px;
+ margin-block-end: -4px;
+ width: 100%;
+ max-width: 100px;
+ height: auto;
}
diff --git a/docs/src/assets/scss/docs.scss b/docs/src/assets/scss/docs.scss
index e981d8cc6af3..5068172a4899 100644
--- a/docs/src/assets/scss/docs.scss
+++ b/docs/src/assets/scss/docs.scss
@@ -1,216 +1,274 @@
/* docs layout styles */
html {
- scroll-behavior: smooth;
+ scroll-behavior: smooth;
}
.docs-aside__content {
- flex: 1;
+ flex: 1;
}
.docs-wrapper {
- padding: 0 var(--space-s-l);
- flex: 1;
- display: flex;
- flex-direction: column;
- max-width: 1700px;
-
- @media all and (min-width: 1024px) {
- display: grid;
- grid-template-columns: minmax(250px, 1fr) minmax(0, 3.5fr);
- align-items: stretch;
- }
- @media all and (min-width: 1700px) {
- margin: auto;
- }
+ padding: 0 var(--space-s-l);
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ max-width: 1700px;
+
+ @media all and (min-width: 1024px) {
+ display: grid;
+ grid-template-columns: minmax(250px, 1fr) minmax(0, 3.5fr);
+ align-items: stretch;
+ }
+ @media all and (min-width: 1700px) {
+ margin: auto;
+ }
}
.docs-nav {
- grid-column: 1 / 2;
- grid-row: 1 / 2;
- padding-top: var(--space-l-xl);
- padding-block-start: var(--space-l-xl);
- font-size: 0.875rem;
- display: grid;
- grid-auto-rows: max-content;
- align-items: start;
-
- @media all and (min-width: 1024px) {
- padding: var(--space-l-xl) 0;
- padding-right: var(--space-s-l);
- padding-inline-end: var(--space-s-l);
- border-right: 1px solid var(--divider-color);
- border-inline-end: 1px solid var(--divider-color);
- }
+ grid-column: 1 / 2;
+ grid-row: 1 / 2;
+ padding-top: var(--space-l-xl);
+ padding-block-start: var(--space-l-xl);
+ font-size: 0.875rem;
+ display: grid;
+ grid-auto-rows: max-content;
+ align-items: start;
+
+ @media all and (min-width: 1024px) {
+ padding: var(--space-l-xl) 0;
+ padding-right: var(--space-s-l);
+ padding-inline-end: var(--space-s-l);
+ border-right: 1px solid var(--divider-color);
+ border-inline-end: 1px solid var(--divider-color);
+ }
}
.docs-content {
- grid-column: 2 / 3;
- padding: var(--space-l-xl) 0;
- flex: 1;
-
- @media all and (min-width: 800px) {
- display: grid;
- grid-template-columns: minmax(0, 4fr) minmax(160px, 1fr);
- grid-gap: 1rem;
- }
-
- @media all and (min-width: 1024px) {
- padding: 0;
- }
-
- @media all and (min-width: 1300px) {
- grid-gap: 2rem;
- }
+ grid-column: 2 / 3;
+ padding: var(--space-l-xl) 0;
+ flex: 1;
+
+ @media all and (min-width: 800px) {
+ display: grid;
+ grid-template-columns: minmax(0, 4fr) minmax(160px, 1fr);
+ grid-gap: 1rem;
+ }
+
+ @media all and (min-width: 1024px) {
+ padding: 0;
+ }
+
+ @media all and (min-width: 1300px) {
+ grid-gap: 2rem;
+ }
}
.docs-main {
- flex: 1 1 68ch;
-
- @media all and (min-width: 800px) {
- padding-right: var(--space-s-l);
- padding-inline-end: var(--space-s-l);
- border-right: 1px solid var(--divider-color);
- border-inline-end: 1px solid var(--divider-color);
- }
-
- @media all and (min-width: 1024px) {
- padding: var(--space-l-xl) var(--space-l-2xl);
- }
+ flex: 1 1 68ch;
+
+ @media all and (min-width: 800px) {
+ padding-right: var(--space-s-l);
+ padding-inline-end: var(--space-s-l);
+ border-right: 1px solid var(--divider-color);
+ border-inline-end: 1px solid var(--divider-color);
+ }
+
+ @media all and (min-width: 1024px) {
+ padding: var(--space-l-xl) var(--space-l-2xl);
+ }
}
.docs-aside {
- grid-column: 2 / 3;
- display: flex;
- flex-direction: column;
+ grid-column: 2 / 3;
+ display: flex;
+ flex-direction: column;
- @media all and (min-width: 800px) {
- padding: var(--space-l-xl) 0;
- }
+ @media all and (min-width: 800px) {
+ padding: var(--space-l-xl) 0;
+ }
}
.docs-toc {
- flex: 1;
- align-self: center;
+ flex: 1;
+ align-self: center;
}
.docs-edit-link {
- border-top: 1px solid var(--divider-color);
- padding-top: 1.5rem;
- padding-block-start: 1.5rem;
- margin: 3rem 0;
+ border-top: 1px solid var(--divider-color);
+ padding-top: 1.5rem;
+ padding-block-start: 1.5rem;
+ margin: 3rem 0;
}
div.correct,
div.incorrect {
- position: relative;
-
- &::after {
- position: absolute;
- top: -22px;
- right: -22px;
- offset-inline-end: -22px;
- offset-block-start: -22px;
- }
-
- // Add space to the bottom if there is a Playground button.
- .c-btn.c-btn--playground ~ pre.line-numbers-mode {
- padding-bottom: 4.5rem;
- }
+ position: relative;
+
+ &::after {
+ position: absolute;
+ top: -22px;
+ right: -22px;
+ offset-inline-end: -22px;
+ offset-block-start: -22px;
+ }
+
+ // Add space to the bottom if there is a Playground button.
+ .c-btn.c-btn--playground ~ pre.line-numbers-mode {
+ padding-bottom: 4.5rem;
+ }
}
div.correct {
- &::after {
- content: url("data:image/svg+xml,%3Csvg width='45' height='44' viewBox='0 0 45 44' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='1.5' y='1' width='42' height='42' rx='21' fill='%23ECFDF3'/%3E%3Cpath d='M30.5 16L19.5 27L14.5 22' stroke='%2312B76A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Crect x='1.5' y='1' width='42' height='42' rx='21' stroke='white' stroke-width='2'/%3E%3C/svg%3E%0A");
- }
+ &::after {
+ content: url("data:image/svg+xml,%3Csvg width='45' height='44' viewBox='0 0 45 44' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='1.5' y='1' width='42' height='42' rx='21' fill='%23ECFDF3'/%3E%3Cpath d='M30.5 16L19.5 27L14.5 22' stroke='%2312B76A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Crect x='1.5' y='1' width='42' height='42' rx='21' stroke='white' stroke-width='2'/%3E%3C/svg%3E%0A");
+ }
}
div.incorrect {
- &::after {
- content: url("data:image/svg+xml,%3Csvg width='45' height='44' viewBox='0 0 45 44' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='1.5' y='1' width='42' height='42' rx='21' fill='%23FFF1F3'/%3E%3Cpath d='M28.5 16L16.5 28M16.5 16L28.5 28' stroke='%23F63D68' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Crect x='1.5' y='1' width='42' height='42' rx='21' stroke='white' stroke-width='2'/%3E%3C/svg%3E%0A");
- }
+ &::after {
+ content: url("data:image/svg+xml,%3Csvg width='45' height='44' viewBox='0 0 45 44' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='1.5' y='1' width='42' height='42' rx='21' fill='%23FFF1F3'/%3E%3Cpath d='M28.5 16L16.5 28M16.5 16L28.5 28' stroke='%23F63D68' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Crect x='1.5' y='1' width='42' height='42' rx='21' stroke='white' stroke-width='2'/%3E%3C/svg%3E%0A");
+ }
}
div.img-container {
- background-color: var(--img-background-color);
- border-radius: var(--border-radius);
+ background-color: var(--img-background-color);
+ border-radius: var(--border-radius);
- img {
- margin: 0 auto;
- }
+ img {
+ margin: 0 auto;
+ }
}
pre[class*="language-"] {
- position: relative;
+ position: relative;
}
.c-btn.c-btn--playground {
- position: absolute;
- font-size: var(--step--1);
- bottom: 1rem;
- right: 1rem;
- z-index: 1;
-
- @media all and (min-width: 768px) {
- bottom: 1.5rem;
- }
+ position: absolute;
+ font-size: var(--step--1);
+ bottom: 1rem;
+ right: 1rem;
+ z-index: 1;
+
+ @media all and (min-width: 768px) {
+ bottom: 1.5rem;
+ }
}
@media (hover: none) {
- .anchorjs-link {
- opacity: 1;
- }
+ .anchorjs-link {
+ opacity: 1;
+ }
}
#scroll-up-btn {
- width: 50px;
- height: 50px;
- display: none;
- position: fixed;
- right: 19.8vw;
- bottom: 35px;
- z-index: 1;
- font-size: 1.5rem;
- border-radius: 50%;
- color: var(--body-background-color);
- text-decoration: none;
- justify-content: center;
- align-items: center;
- background-color: var(--link-color);
-
- @media (max-width: 1299px) {
- right: 18.99vw;
- }
-
- @media (max-width: 1100px) {
- right: 19.4vw;
- }
-
- @media (max-width: 1060px) {
- right: 19.9vw;
- }
-
- @media (max-width: 1024px) {
- right: 22vw;
- }
-
- @media (max-width: 860px) {
- right: 22.2vw;
- }
-
- @media (max-width: 850px) {
- right: 22.6vw;
- }
-
- @media (max-width: 820px) {
- right: 23.4vw;
- }
-
- @media (max-width: 799px) {
- right: 35px;
- }
-
- @media (max-width: 600px) {
- right: 25px;
- }
+ width: 50px;
+ height: 50px;
+ display: none;
+ position: fixed;
+ right: 19.8vw;
+ bottom: 35px;
+ z-index: 1;
+ font-size: 1.5rem;
+ border-radius: 50%;
+ color: var(--body-background-color);
+ text-decoration: none;
+ justify-content: center;
+ align-items: center;
+ background-color: var(--link-color);
+
+ @media (max-width: 1299px) {
+ right: 18.99vw;
+ }
+
+ @media (max-width: 1100px) {
+ right: 19.4vw;
+ }
+
+ @media (max-width: 1060px) {
+ right: 19.9vw;
+ }
+
+ @media (max-width: 1024px) {
+ right: 22vw;
+ }
+
+ @media (max-width: 860px) {
+ right: 22.2vw;
+ }
+
+ @media (max-width: 850px) {
+ right: 22.6vw;
+ }
+
+ @media (max-width: 820px) {
+ right: 23.4vw;
+ }
+
+ @media (max-width: 799px) {
+ right: 35px;
+ }
+
+ @media (max-width: 600px) {
+ right: 25px;
+ }
+}
+
+.code-wrapper {
+ position: relative;
+
+ > pre {
+ padding-right: 3.5rem;
+ }
+}
+
+.copy-btn {
+ position: absolute;
+ top: 1rem;
+ right: 1rem;
+ padding: 0.5rem;
+ border-radius: var(--border-radius);
+ color: var(--body-text-color);
+ background-color: var(--color-neutral-100);
+ border: 1px solid var(--border-color);
+ transition: background-color 0.1s linear;
+
+ &:hover {
+ background-color: var(--color-neutral-200);
+ }
+
+ [data-theme="dark"] & {
+ background-color: var(--color-neutral-700);
+
+ &:hover {
+ background-color: var(--color-neutral-600);
+ }
+ }
+
+ &::after {
+ content: "Copied!";
+ padding: 0.5rem 0.75rem;
+ font-size: var(--step--1);
+ border-radius: var(--border-radius);
+ position: absolute;
+ top: 0;
+ right: 2.5rem;
+ height: 2.25rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--color-neutral-100);
+ border: 1px solid var(--border-color);
+ opacity: 0;
+ pointer-events: none;
+
+ [data-theme="dark"] & {
+ background-color: var(--color-neutral-700);
+ }
+ }
+
+ &[data-copied="true"]::after {
+ opacity: 1;
+ }
}
diff --git a/docs/src/assets/scss/eslint-site-footer.scss b/docs/src/assets/scss/eslint-site-footer.scss
index 6ecb430c7038..e9b25d685b9d 100644
--- a/docs/src/assets/scss/eslint-site-footer.scss
+++ b/docs/src/assets/scss/eslint-site-footer.scss
@@ -1,64 +1,64 @@
.site-footer {
- text-align: center;
- background-color: var(--footer-background-color);
- border-top: 1px solid var(--divider-color);
- border-block-start: 1px solid var(--divider-color);
+ text-align: center;
+ background-color: var(--footer-background-color);
+ border-top: 1px solid var(--divider-color);
+ border-block-start: 1px solid var(--divider-color);
}
.footer-cta {
- .logo {
- margin-bottom: 2.5rem;
- margin-block-end: 2.5rem;
- }
+ .logo {
+ margin-bottom: 2.5rem;
+ margin-block-end: 2.5rem;
+ }
- .section-supporting-text {
- margin-bottom: 2.5rem;
- margin-block-end: 2.5rem;
- }
+ .section-supporting-text {
+ margin-bottom: 2.5rem;
+ margin-block-end: 2.5rem;
+ }
- .eslint-actions {
- justify-content: center;
- }
+ .eslint-actions {
+ justify-content: center;
+ }
}
.footer-legal-links {
- ul {
- li {
- display: inline-block;
- margin-right: .5rem;
- margin-inline-end: .5rem;
+ ul {
+ li {
+ display: inline-block;
+ margin-right: 0.5rem;
+ margin-inline-end: 0.5rem;
- &:not(:last-of-type)::after {
- content: "|";
- margin-left: .5rem;
- margin-inline-start: .5rem;
- }
- }
- }
+ &:not(:last-of-type)::after {
+ content: "|";
+ margin-left: 0.5rem;
+ margin-inline-start: 0.5rem;
+ }
+ }
+ }
}
.footer-legal-section {
- font-size: var(--step--1);
- padding: 2rem 1rem;
+ font-size: var(--step--1);
+ padding: 2rem 1rem;
}
.copyright {
- max-width: 1100px;
- margin: 0 auto;
+ max-width: 1100px;
+ margin: 0 auto;
}
.footer-middle {
- padding-top: 2rem;
- padding-bottom: 2rem;
- padding-block-start: 2rem;
- padding-block-end: 2rem;
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 2rem;
+ padding-top: 2rem;
+ padding-bottom: 2rem;
+ padding-block-start: 2rem;
+ padding-block-end: 2rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 2rem;
- @media all and (min-width: 768px) {
- flex-direction: row;
- justify-content: space-between;
- }
+ @media all and (min-width: 768px) {
+ flex-direction: row;
+ justify-content: space-between;
+ }
}
diff --git a/docs/src/assets/scss/eslint-site-header.scss b/docs/src/assets/scss/eslint-site-header.scss
index 892ebc7e6250..b970e673efea 100644
--- a/docs/src/assets/scss/eslint-site-header.scss
+++ b/docs/src/assets/scss/eslint-site-header.scss
@@ -1,40 +1,40 @@
.site-header {
- padding: .75rem 0;
- border-top: 4px solid var(--link-color);
- border-block-start: 4px solid var(--link-color);
- border-bottom: 1px solid var(--divider-color);
- border-block-end: 1px solid var(--divider-color);
+ padding: 0.75rem 0;
+ border-top: 4px solid var(--link-color);
+ border-block-start: 4px solid var(--link-color);
+ border-bottom: 1px solid var(--divider-color);
+ border-block-end: 1px solid var(--divider-color);
- .content-container {
- display: grid;
- align-items: start;
- padding-top: 0;
- padding-bottom: 0;
- padding-block-start: 0;
- padding-block-end: 0;
+ .content-container {
+ display: grid;
+ align-items: start;
+ padding-top: 0;
+ padding-bottom: 0;
+ padding-block-start: 0;
+ padding-block-end: 0;
- @media all and (min-width: 680px) {
- justify-content: space-between;
- }
- }
+ @media all and (min-width: 680px) {
+ justify-content: space-between;
+ }
+ }
}
.logo-link {
- display: inline-flex;
- justify-self: start;
- flex: none;
- place-content: center;
- grid-column: 1 / -1;
- grid-row: 1;
- padding: .5rem 0;
- z-index: 2;
+ display: inline-flex;
+ justify-self: start;
+ flex: none;
+ place-content: center;
+ grid-column: 1 / -1;
+ grid-row: 1;
+ padding: 0.5rem 0;
+ z-index: 2;
}
.logo svg {
- display: inline-block;
- margin-bottom: -4px;
- margin-block-end: -4px;
- width: 100%;
- max-width: 100px;
- height: auto;
+ display: inline-block;
+ margin-bottom: -4px;
+ margin-block-end: -4px;
+ width: 100%;
+ max-width: 100px;
+ height: auto;
}
diff --git a/docs/src/assets/scss/forms.scss b/docs/src/assets/scss/forms.scss
index 3ca145257342..28dfde5750b0 100644
--- a/docs/src/assets/scss/forms.scss
+++ b/docs/src/assets/scss/forms.scss
@@ -1,49 +1,58 @@
.c-custom-select {
- appearance: none;
- box-sizing: border-box;
- display: block;
- width: 100%;
- max-width: 100%;
- min-width: 0;
- padding: .625rem .875rem;
- padding-right: calc(.875rem * 2.5);
- padding-inline-end: calc(.875rem * 2.5);
- font: inherit;
- color: var(--body-text-color);
- line-height: 1.3;
- border: 1px solid var(--border-color);
- border-radius: var(--border-radius);
- box-shadow: var(--shadow-xs);
- background-color: var(--body-background-color);
- background-image: url("data:image/svg+xml,%3Csvg width='20' height='21' viewBox='0 0 20 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 7.60938L10 12.6094L15 7.60938' stroke='%23667085' stroke-width='1.66667' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A"), linear-gradient(to bottom, var(--body-background-color) 0%, var(--body-background-color) 100%);
- background-repeat: no-repeat, repeat;
- background-position: right .875rem top 50%, 0 0;
- background-size: 1em auto, 100%;
+ appearance: none;
+ box-sizing: border-box;
+ display: block;
+ width: 100%;
+ max-width: 100%;
+ min-width: 0;
+ padding: 0.625rem 0.875rem;
+ padding-right: calc(0.875rem * 2.5);
+ padding-inline-end: calc(0.875rem * 2.5);
+ font: inherit;
+ color: var(--body-text-color);
+ line-height: 1.3;
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ box-shadow: var(--shadow-xs);
+ background-color: var(--body-background-color);
+ background-image: url("data:image/svg+xml,%3Csvg width='20' height='21' viewBox='0 0 20 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 7.60938L10 12.6094L15 7.60938' stroke='%23667085' stroke-width='1.66667' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A"),
+ linear-gradient(
+ to bottom,
+ var(--body-background-color) 0%,
+ var(--body-background-color) 100%
+ );
+ background-repeat: no-repeat, repeat;
+ background-position:
+ right 0.875rem top 50%,
+ 0 0;
+ background-size:
+ 1em auto,
+ 100%;
}
.label__text.label__text {
- display: flex;
- align-items: center;
- gap: .5rem;
- font-size: .875rem;
- font-family: var(--text-font);
- color: inherit;
- font-weight: 400;
- line-height: 1.5;
- margin-bottom: .25rem;
- margin-block-end: .25rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-size: 0.875rem;
+ font-family: var(--text-font);
+ color: inherit;
+ font-weight: 400;
+ line-height: 1.5;
+ margin-bottom: 0.25rem;
+ margin-block-end: 0.25rem;
}
input {
- border: 1px solid var(--border-color);
- border-radius: var(--border-radius);
- padding: .625rem .875rem;
- font: inherit;
- font-size: 1rem;
- display: block;
- min-width: 0;
- line-height: 1.3;
- max-width: 100%;
- background-color: var(--body-background-color);
- color: inherit;
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ padding: 0.625rem 0.875rem;
+ font: inherit;
+ font-size: 1rem;
+ display: block;
+ min-width: 0;
+ line-height: 1.3;
+ max-width: 100%;
+ background-color: var(--body-background-color);
+ color: inherit;
}
diff --git a/docs/src/assets/scss/foundations.scss b/docs/src/assets/scss/foundations.scss
index 5d07a6de03a8..6237fef1d022 100644
--- a/docs/src/assets/scss/foundations.scss
+++ b/docs/src/assets/scss/foundations.scss
@@ -1,6 +1,6 @@
::selection {
- background-color: var(--color-brand);
- color: #fff;
+ background-color: var(--color-brand);
+ color: #fff;
}
h1:target,
@@ -9,231 +9,231 @@ h3:target,
h4:target,
h5:target,
h6:target {
- background-color: var(--lighter-background-color);
- border-radius: var(--border-radius);
+ background-color: var(--lighter-background-color);
+ border-radius: var(--border-radius);
}
*:focus {
- outline: none;
+ outline: none;
}
*:focus-visible {
- outline: 2px solid var(--outline-color);
- outline-offset: 3px;
+ outline: 2px solid var(--outline-color);
+ outline-offset: 3px;
}
*.focus-visible {
- outline: 2px solid var(--outline-color);
- outline-offset: 3px;
+ outline: 2px solid var(--outline-color);
+ outline-offset: 3px;
}
*:focus:not(:focus-visible) {
- outline: 1px solid transparent;
- box-shadow: none;
+ outline: 1px solid transparent;
+ box-shadow: none;
}
.js-focus-visible *:focus:not(.focus-visible) {
- outline: 1px solid transparent;
- box-shadow: none;
+ outline: 1px solid transparent;
+ box-shadow: none;
}
input:focus-visible {
- outline: 2px solid var(--link-color);
- border-color: var(--border-color);
+ outline: 2px solid var(--link-color);
+ border-color: var(--border-color);
}
input:focus {
- outline: 2px solid transparent;
- box-shadow: 0 0 0 2px var(--link-color);
+ outline: 2px solid transparent;
+ box-shadow: 0 0 0 2px var(--link-color);
}
*,
*::before,
*::after {
- box-sizing: border-box;
+ box-sizing: border-box;
}
html {
- accent-color: var(--link-color);
- background-color: var(--body-background-color);
- height: 100%;
- font-family: var(--text-font);
- overflow-x: hidden;
- caret-color: var(--link-color);
+ accent-color: var(--link-color);
+ background-color: var(--body-background-color);
+ height: 100%;
+ font-family: var(--text-font);
+ overflow-x: hidden;
+ caret-color: var(--link-color);
}
body {
- font-size: var(--step-0);
- position: relative;
- margin: 0 auto;
- line-height: 1.5;
- display: flex;
- flex-direction: column;
- min-height: 100%;
- background-color: var(--body-background-color);
- color: var(--body-text-color);
+ font-size: var(--step-0);
+ position: relative;
+ margin: 0 auto;
+ line-height: 1.5;
+ display: flex;
+ flex-direction: column;
+ min-height: 100%;
+ background-color: var(--body-background-color);
+ color: var(--body-text-color);
}
#skip-link {
- position: fixed;
- top: -30em;
- left: 0;
- right: auto;
- offset-block-start: -30em;
- offset-inline-start: 0;
- offset-inline-end: auto;
- z-index: 999;
- transition: top .1s linear;
-
- &:focus {
- outline: 2px solid transparent;
- top: 2px;
- offset-block-start: 2px;
- }
-
- &:focus-visible {
- outline: 2px solid transparent;
- top: 2px;
- offset-block-start: 2px;
- }
+ position: fixed;
+ top: -30em;
+ left: 0;
+ right: auto;
+ offset-block-start: -30em;
+ offset-inline-start: 0;
+ offset-inline-end: auto;
+ z-index: 999;
+ transition: top 0.1s linear;
+
+ &:focus {
+ outline: 2px solid transparent;
+ top: 2px;
+ offset-block-start: 2px;
+ }
+
+ &:focus-visible {
+ outline: 2px solid transparent;
+ top: 2px;
+ offset-block-start: 2px;
+ }
}
main {
- flex: 1;
+ flex: 1;
- &:focus {
- outline: none;
- }
+ &:focus {
+ outline: none;
+ }
- &:target {
- outline: none;
- }
+ &:target {
+ outline: none;
+ }
}
hr {
- border: none;
- border-top: 1px solid var(--divider-color);
- border-block-start: 1px solid var(--divider-color);
- background: none;
- height: 0;
- margin: 2rem 0;
+ border: none;
+ border-top: 1px solid var(--divider-color);
+ border-block-start: 1px solid var(--divider-color);
+ background: none;
+ height: 0;
+ margin: 2rem 0;
}
.content-container {
- width: 100%;
- margin: 0 auto;
- padding: var(--space-xl-3xl) calc(1rem + 1vw);
- max-width: 1700px;
+ width: 100%;
+ margin: 0 auto;
+ padding: var(--space-xl-3xl) calc(1rem + 1vw);
+ max-width: 1700px;
- @media all and (min-width: 1700px) {
- margin: auto;
- }
+ @media all and (min-width: 1700px) {
+ margin: auto;
+ }
}
.section-head {
- .section-supporting-text {
- text-align: center;
- max-width: 768px;
- margin: 0 auto var(--space-l-2xl);
- }
+ .section-supporting-text {
+ text-align: center;
+ max-width: 768px;
+ margin: 0 auto var(--space-l-2xl);
+ }
}
.section-foot {
- margin-top: var(--space-l-2xl);
- margin-block-start: var(--space-l-2xl);
+ margin-top: var(--space-l-2xl);
+ margin-block-start: var(--space-l-2xl);
- .section-supporting-text {
- text-align: center;
- font-size: var(--step--1);
- max-width: 768px;
- margin: 0 auto;
- }
+ .section-supporting-text {
+ text-align: center;
+ font-size: var(--step--1);
+ max-width: 768px;
+ margin: 0 auto;
+ }
}
.section-title {
- margin-bottom: 1rem;
- margin-block-end: 1rem;
+ margin-bottom: 1rem;
+ margin-block-end: 1rem;
}
.section-supporting-text {
- font-size: var(--step-1);
+ font-size: var(--step-1);
}
code,
pre {
- font-family: var(--mono-font);
- font-variant-ligatures: none;
+ font-family: var(--mono-font);
+ font-variant-ligatures: none;
}
code {
- color: var(--link-color);
+ color: var(--link-color);
- pre & {
- color: unset;
- }
+ pre & {
+ color: unset;
+ }
}
.c-icon {
- color: var(--icon-color);
- flex: none;
- transition: all .2s linear;
+ color: var(--icon-color);
+ flex: none;
+ transition: all 0.2s linear;
- @media (-ms-high-contrast: active) {
- color: windowText;
- }
+ @media (-ms-high-contrast: active) {
+ color: windowText;
+ }
- @media (forced-colors: active) {
- color: canvasText;
- }
+ @media (forced-colors: active) {
+ color: canvasText;
+ }
}
table {
- width: 100%;
- margin: 2.5rem 0;
- border-collapse: collapse;
- border: 1px solid var(--divider-color);
+ width: 100%;
+ margin: 2.5rem 0;
+ border-collapse: collapse;
+ border: 1px solid var(--divider-color);
- td {
- padding: .25rem .5rem;
- border: 1px solid var(--divider-color);
- }
+ td {
+ padding: 0.25rem 0.5rem;
+ border: 1px solid var(--divider-color);
+ }
- th {
- background-color: var(--lightest-background-color);
- padding: .25rem .5rem;
- }
+ th {
+ background-color: var(--lightest-background-color);
+ padding: 0.25rem 0.5rem;
+ }
}
.c-btn,
button,
a {
- .c-icon:hover {
- color: var(--link-color);
- }
+ .c-icon:hover {
+ color: var(--link-color);
+ }
}
a {
- color: var(--link-color);
- transition: color .1s linear;
+ color: var(--link-color);
+ transition: color 0.1s linear;
- .side-header & {
- color: inherit;
- text-decoration: none;
- }
+ .side-header & {
+ color: inherit;
+ text-decoration: none;
+ }
}
svg {
- flex: none;
- transition: color .1s linear;
+ flex: none;
+ transition: color 0.1s linear;
}
p {
- margin: 0 0 1.5em;
+ margin: 0 0 1.5em;
- :matches(nav, .posts-collection) & {
- margin-bottom: .75em;
- margin-block-end: .75em;
- }
+ :matches(nav, .posts-collection) & {
+ margin-bottom: 0.75em;
+ margin-block-end: 0.75em;
+ }
}
p,
@@ -243,114 +243,114 @@ h3,
h4,
h5,
h6 {
- overflow-wrap: break-word;
+ overflow-wrap: break-word;
}
ul,
ol {
- margin-top: 0;
- margin-block-start: 0;
+ margin-top: 0;
+ margin-block-start: 0;
- li {
- margin: 0 0 .75em;
- }
+ li {
+ margin: 0 0 0.75em;
+ }
- .person__bio & {
- padding-left: 1.5rem;
- padding-inline-start: 1.5rem;
- }
+ .person__bio & {
+ padding-left: 1.5rem;
+ padding-inline-start: 1.5rem;
+ }
}
.docs-main ul,
.post-main ul,
.docs-main ol,
.post-main ol {
- margin: 1rem 0;
+ margin: 1rem 0;
}
ul[role="list"] {
- list-style: none;
- margin: 0;
- padding: 0;
+ list-style: none;
+ margin: 0;
+ padding: 0;
- li {
- margin: 0;
- }
+ li {
+ margin: 0;
+ }
}
ol {
- list-style: decimal;
+ list-style: decimal;
- li::marker {
- color: var(--link-color);
- }
+ li::marker {
+ color: var(--link-color);
+ }
}
p:empty {
- margin: 0;
- display: none;
+ margin: 0;
+ display: none;
}
figure {
- margin-bottom: 4rem;
- margin-block-end: 4rem;
+ margin-bottom: 4rem;
+ margin-block-end: 4rem;
- img {
- margin-bottom: 1rem;
- margin-block-end: 1rem;
- }
+ img {
+ margin-bottom: 1rem;
+ margin-block-end: 1rem;
+ }
- figcaption {
- color: var(--grey);
- }
+ figcaption {
+ color: var(--grey);
+ }
}
img {
- display: block;
- position: relative;
- max-width: 100%;
- height: auto;
+ display: block;
+ position: relative;
+ max-width: 100%;
+ height: auto;
}
nav {
- /* rarely do we display bullets for lists in navigation */
- ol,
- ul {
- list-style: none;
- margin: 0;
- padding: 0;
- }
+ /* rarely do we display bullets for lists in navigation */
+ ol,
+ ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
}
.video {
- width: 90%;
- max-width: 1400px;
- margin: 2em auto;
+ width: 90%;
+ max-width: 1400px;
+ margin: 2em auto;
- iframe {
- aspect-ratio: 16 / 9;
- width: 100%;
- height: auto;
- }
+ iframe {
+ aspect-ratio: 16 / 9;
+ width: 100%;
+ height: auto;
+ }
}
@media (prefers-reduced-motion: no-preference) {
- *:focus-visible,
- *.focus-visible {
- transition: outline-offset .15s linear;
- outline-offset: 3px;
- }
+ *:focus-visible,
+ *.focus-visible {
+ transition: outline-offset 0.15s linear;
+ outline-offset: 3px;
+ }
}
/* typography */
.eyebrow {
- color: var(--link-color);
- font-size: 1rem;
- font-weight: 500;
- display: block;
- margin-bottom: 1.5rem;
- margin-block-end: 1.5rem;
+ color: var(--link-color);
+ font-size: 1rem;
+ font-weight: 500;
+ display: block;
+ margin-bottom: 1.5rem;
+ margin-block-end: 1.5rem;
}
h1,
@@ -359,12 +359,12 @@ h3,
h4,
h5,
h6 {
- font-family: var(--display-font);
- color: var(--headings-color);
- font-weight: 500;
- margin-top: 0;
- margin-block-start: 0;
- padding: 0.25rem 0;
+ font-family: var(--display-font);
+ color: var(--headings-color);
+ font-weight: 500;
+ margin-top: 0;
+ margin-block-start: 0;
+ padding: 0.25rem 0;
}
h2,
@@ -372,61 +372,61 @@ h3,
h4,
h5,
h6 {
- .docs-main &,
- .components-main & {
- margin-top: 3rem;
- margin-bottom: 1.5rem;
- margin-block-start: 3rem;
- margin-block-end: 1.5rem;
+ .docs-main &,
+ .components-main & {
+ margin-top: 3rem;
+ margin-bottom: 1.5rem;
+ margin-block-start: 3rem;
+ margin-block-end: 1.5rem;
- &:first-child {
- margin-top: 0;
- margin-block-start: 0;
- }
- }
+ &:first-child {
+ margin-top: 0;
+ margin-block-start: 0;
+ }
+ }
}
small,
caption,
cite,
figcaption {
- font-size: var(--step--1);
+ font-size: var(--step--1);
}
h6,
.h6 {
- font-size: var(--step-0);
+ font-size: var(--step-0);
}
h5,
.h5 {
- font-size: var(--step-0); // 20
+ font-size: var(--step-0); // 20
}
h4,
.h4 {
- font-size: var(--step-1); // 24
+ font-size: var(--step-1); // 24
}
h3,
.h3 {
- font-size: var(--step-2);
- line-height: 1.2;
+ font-size: var(--step-2);
+ line-height: 1.2;
}
h2,
.h2 {
- font-size: var(--step-3);
- line-height: 1.2;
+ font-size: var(--step-3);
+ line-height: 1.2;
}
h1,
.h1 {
- font-size: var(--step-4);
- line-height: 1.2;
+ font-size: var(--step-4);
+ line-height: 1.2;
}
.h0 {
- font-size: var(--step-6);
- line-height: 1.2;
+ font-size: var(--step-6);
+ line-height: 1.2;
}
diff --git a/docs/src/assets/scss/languages.scss b/docs/src/assets/scss/languages.scss
index 9b29097f0d49..468d55b319b4 100644
--- a/docs/src/assets/scss/languages.scss
+++ b/docs/src/assets/scss/languages.scss
@@ -1,55 +1,55 @@
.languages-list {
- margin: 0;
- padding: 0;
- font-size: var(--step-0);
-
- li {
- margin: 0;
-
- &:last-of-type a {
- border-bottom: 0;
- }
- }
-
- a {
- color: inherit;
- width: 100%;
- padding: .75rem .1rem;
- text-decoration: none;
- display: block;
- display: flex;
- align-items: center;
- border-bottom: 1px solid var(--divider-color);
- border-block-end: 1px solid var(--divider-color);
-
- &[aria-current="true"] {
- font-weight: 500;
- color: var(--link-color);
-
- &::after {
- content: " âī¸";
- white-space: pre;
- color: rgba(100%, 0%, 0%, 0);
- text-shadow: 0 0 0 var(--headings-color);
- }
- }
-
- &:hover {
- color: var(--link-color);
- }
- }
+ margin: 0;
+ padding: 0;
+ font-size: var(--step-0);
+
+ li {
+ margin: 0;
+
+ &:last-of-type a {
+ border-bottom: 0;
+ }
+ }
+
+ a {
+ color: inherit;
+ width: 100%;
+ padding: 0.75rem 0.1rem;
+ text-decoration: none;
+ display: block;
+ display: flex;
+ align-items: center;
+ border-bottom: 1px solid var(--divider-color);
+ border-block-end: 1px solid var(--divider-color);
+
+ &[aria-current="true"] {
+ font-weight: 500;
+ color: var(--link-color);
+
+ &::after {
+ content: " âī¸";
+ white-space: pre;
+ color: rgba(100%, 0%, 0%, 0);
+ text-shadow: 0 0 0 var(--headings-color);
+ }
+ }
+
+ &:hover {
+ color: var(--link-color);
+ }
+ }
}
.languages-section .flag {
- font-size: 2em;
- margin-right: .5rem;
- margin-inline-end: .5rem;
+ font-size: 2em;
+ margin-right: 0.5rem;
+ margin-inline-end: 0.5rem;
}
.languages-section .languages-list {
- font-size: var(--step-1);
- border-left: 4px solid var(--tab-border-color);
- padding-left: 1rem;
- border-inline-start: 4px solid var(--tab-border-color);
- padding-inline-start: 1rem;
+ font-size: var(--step-1);
+ border-left: 4px solid var(--tab-border-color);
+ padding-left: 1rem;
+ border-inline-start: 4px solid var(--tab-border-color);
+ padding-inline-start: 1rem;
}
diff --git a/docs/src/assets/scss/print.scss b/docs/src/assets/scss/print.scss
index 39dcc9470cde..b87f598cd837 100644
--- a/docs/src/assets/scss/print.scss
+++ b/docs/src/assets/scss/print.scss
@@ -6,34 +6,34 @@ p::first-line,
div::first-line,
blockquote::first-line,
li::first-line {
- background: transparent !important;
- color: #000 !important;
- box-shadow: none !important;
- text-shadow: none !important;
+ background: transparent !important;
+ color: #000 !important;
+ box-shadow: none !important;
+ text-shadow: none !important;
}
body {
- width: 100% !important;
- margin: 0 !important;
- padding: 0 !important;
- line-height: 1.45;
- font-family: Helvetica, sans-serif;
- color: #000;
- background: none;
- font-size: 14pt;
+ width: 100% !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ line-height: 1.45;
+ font-family: Helvetica, sans-serif;
+ color: #000;
+ background: none;
+ font-size: 14pt;
}
.grid {
- display: block;
+ display: block;
}
main,
.docs-content,
.docs-wrapper {
- display: block;
- width: 100%;
- max-width: 75ch;
- margin: 1cm auto;
+ display: block;
+ width: 100%;
+ max-width: 75ch;
+ margin: 1cm auto;
}
/* Headings */
@@ -43,64 +43,66 @@ h3,
h4,
h5,
h6 {
- page-break-after: avoid;
+ page-break-after: avoid;
}
h1 {
- font-size: 19pt;
+ font-size: 19pt;
}
h2 {
- font-size: 17pt;
+ font-size: 17pt;
}
h3 {
- font-size: 15pt;
+ font-size: 15pt;
}
h4,
h5,
h6 {
- font-size: 14pt;
+ font-size: 14pt;
}
p,
h2,
h3 {
- orphans: 3;
- widows: 3;
+ orphans: 3;
+ widows: 3;
}
code {
- font: 12pt Courier, monospace;
+ font:
+ 12pt Courier,
+ monospace;
}
blockquote {
- margin: 1.2em;
- padding: 1em;
- font-size: 12pt;
+ margin: 1.2em;
+ padding: 1em;
+ font-size: 12pt;
}
hr {
- background-color: #ccc;
+ background-color: #ccc;
}
/* Images */
img {
- max-width: 100% !important;
+ max-width: 100% !important;
}
a img {
- border: none;
+ border: none;
}
/* Links */
a:link,
a:visited {
- background: transparent;
- font-weight: 700;
- text-decoration: underline;
- color: #333;
+ background: transparent;
+ font-weight: 700;
+ text-decoration: underline;
+ color: #333;
}
// a:link[href^="http://"]:after,
@@ -110,104 +112,105 @@ a:visited {
// }
abbr[title]::after {
- content: " ("attr(title) ")";
+ content: " (" attr(title) ")";
}
/* Don't show linked images */
-a[href^="http://"] {
- color: #000;
+a[href^="http://"]
+{
+ color: #000;
}
a[href$=".jpg"]::after,
a[href$=".jpeg"]::after,
a[href$=".gif"]::after,
a[href$=".png"]::after {
- content: " ("attr(href) ") ";
- display: none;
+ content: " (" attr(href) ") ";
+ display: none;
}
/* Don't show links that are fragment identifiers, or use the `javascript:` pseudo protocol .. taken from html5boilerplate */
a[href^="#"]::after,
a[href^="javascript:"]::after {
- content: "";
+ content: "";
}
/* Table */
table {
- margin: 1px;
- text-align: left;
+ margin: 1px;
+ text-align: left;
}
th {
- border-bottom: 1px solid #333;
- font-weight: bold;
+ border-bottom: 1px solid #333;
+ font-weight: bold;
}
td {
- border-bottom: 1px solid #333;
+ border-bottom: 1px solid #333;
}
th,
td {
- padding: 4px 10px 4px 0;
+ padding: 4px 10px 4px 0;
}
tfoot {
- font-style: italic;
+ font-style: italic;
}
caption {
- background: #fff;
- margin-bottom: 2em;
- text-align: left;
+ background: #fff;
+ margin-bottom: 2em;
+ text-align: left;
}
thead {
- display: table-header-group;
+ display: table-header-group;
}
img,
tr {
- page-break-inside: avoid;
+ page-break-inside: avoid;
}
body > *:not(main),
aside,
*[class*="sidebar"] {
- display: none;
+ display: none;
}
button,
.c-btn.c-btn--playground,
.docs-edit-link {
- display: none;
+ display: none;
}
a[href^="http"]:not([href*="eslint.org"])::after {
- content: " ("attr(href) ")";
+ content: " (" attr(href) ")";
}
.resource a::after {
- display: none;
+ display: none;
}
ul {
- page-break-inside: avoid;
+ page-break-inside: avoid;
}
.docs-toc,
.docs-index,
.docs-aside,
#skip-link {
- display: none;
+ display: none;
}
@media print {
- @page {
- margin: 1cm;
- }
+ @page {
+ margin: 1cm;
+ }
}
#scroll-up-btn {
- display: none;
+ display: none;
}
diff --git a/docs/src/assets/scss/styles.scss b/docs/src/assets/scss/styles.scss
index 478b7ef1de12..7b4b4b43c5c9 100644
--- a/docs/src/assets/scss/styles.scss
+++ b/docs/src/assets/scss/styles.scss
@@ -1,37 +1,37 @@
-@import "tokens/themes";
-@import "tokens/spacing";
-@import "tokens/typography";
-@import "tokens/ui";
-@import "tokens/opacity";
+@use "tokens/themes";
+@use "tokens/spacing";
+@use "tokens/typography";
+@use "tokens/ui";
+@use "tokens/opacity";
-@import "foundations";
-@import "syntax-highlighter";
-@import "docs-header";
-@import "docs-footer";
-@import "eslint-site-footer";
-@import "eslint-site-header";
-@import "forms";
-@import "docs";
-@import "versions";
-@import "languages";
+@use "foundations";
+@use "syntax-highlighter";
+@use "docs-header";
+@use "docs-footer";
+@use "eslint-site-footer";
+@use "eslint-site-header";
+@use "forms";
+@use "docs";
+@use "versions";
+@use "languages";
-@import "components/buttons";
-@import "components/docs-navigation";
-@import "components/toc";
-@import "components/search";
-@import "components/alert";
-@import "components/rules";
-@import "components/social-icons";
-@import "components/hero";
-@import "components/theme-switcher";
-@import "components/version-switcher";
-@import "components/language-switcher";
-@import "components/docs-index"; // docs index on the main docs pages
-@import "components/index"; // used in component library
-@import "components/tabs";
-@import "components/resources";
-@import "components/logo";
+@use "components/buttons";
+@use "components/docs-navigation";
+@use "components/toc";
+@use "components/search";
+@use "components/alert";
+@use "components/rules";
+@use "components/social-icons";
+@use "components/hero";
+@use "components/theme-switcher";
+@use "components/version-switcher";
+@use "components/language-switcher";
+@use "components/docs-index"; // docs index on the main docs pages
+@use "components/index"; // used in component library
+@use "components/tabs";
+@use "components/resources";
+@use "components/logo";
-@import "ads";
+@use "ads";
-@import "utilities";
+@use "utilities";
diff --git a/docs/src/assets/scss/syntax-highlighter.scss b/docs/src/assets/scss/syntax-highlighter.scss
index 1e4c4348e9a3..868a96fcc722 100644
--- a/docs/src/assets/scss/syntax-highlighter.scss
+++ b/docs/src/assets/scss/syntax-highlighter.scss
@@ -1,66 +1,61 @@
code[class*="language-"],
pre[class*="language-"] {
- font-family:
- var(--mono-font),
- Consolas,
- Monaco,
- "Andale Mono",
- "Ubuntu Mono",
- monospace;
- font-size: 1em;
- text-align: left;
- white-space: pre;
- word-spacing: normal;
- word-break: normal;
- word-wrap: normal;
- line-height: 1.5;
- font-variant-ligatures: none;
- tab-size: 4;
- hyphens: none;
+ font-family: var(--mono-font), Consolas, Monaco, "Andale Mono",
+ "Ubuntu Mono", monospace;
+ font-size: 1em;
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+ word-break: normal;
+ word-wrap: normal;
+ line-height: 1.5;
+ font-variant-ligatures: none;
+ tab-size: 4;
+ hyphens: none;
}
@media print {
- code[class*="language-"],
- pre[class*="language-"] {
- text-shadow: none;
- }
+ code[class*="language-"],
+ pre[class*="language-"] {
+ text-shadow: none;
+ }
}
/* Code blocks */
pre[class*="language-"] {
- padding: 1.5rem;
- margin: 1.5rem 0;
- overflow: auto;
- border-radius: var(--border-radius);
- background-color: var(--lightest-background-color);
- color: var(--code-text-color);
+ padding: 1.5rem;
+ margin: 1.5rem 0;
+ overflow: auto;
+ border-radius: var(--border-radius);
+ background-color: var(--lightest-background-color);
+ color: var(--code-text-color);
- &.line-numbers-mode {
- padding-left: calc(1.5rem + 2.4em + 1.2rem);
- }
+ &.line-numbers-mode {
+ padding-left: calc(1.5rem + 2.4em + 1.2rem);
+ }
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
- background-color: var(--lightest-background-color);
+ background-color: var(--lightest-background-color);
}
/* Inline code */
:not(pre) > code[class*="language-"] {
- padding: 0.1em;
- border-radius: 0.3em;
- white-space: normal;
+ padding: 0.1em;
+ border-radius: 0.3em;
+ white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
- color: var(--code-comments-color);
+ color: var(--code-comments-color);
}
.token.namespace {
- opacity: 0.7;
+ opacity: 0.7;
}
.token.selector,
@@ -69,92 +64,91 @@ pre[class*="language-"] {
.token.char,
.token.builtin,
.token.inserted {
- color: var(--link-color);
+ color: var(--link-color);
}
.token.atrule,
.token.attr-value,
.token.keyword {
- color: var(--link-color);
+ color: var(--link-color);
}
.token.important,
.token.bold {
- font-weight: bold;
+ font-weight: bold;
}
.token.italic {
- font-style: italic;
+ font-style: italic;
}
.token.entity {
- cursor: help;
+ cursor: help;
}
.token.eslint-marked {
- /* Draw the wavy line. */
- background:
- url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23f14c4c'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")
- repeat-x
- bottom
- left;
-
- /*
+ /* Draw the wavy line. */
+ background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23f14c4c'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")
+ repeat-x bottom left;
+
+ /*
* Since the character width of the token span is not constant,
* if we use it as is, we may see a shift in the border.
* To make the border shift less noticeable, draw it with a smaller width.
*/
- background-size: 4.4px auto;
+ background-size: 4.4px auto;
}
.token.eslint-marked-on-line-feed {
- /* Use `padding` to give it width so the marker on line feed code is visible. */
- padding-right: 8px;
+ /* Use `padding` to give it width so the marker on line feed code is visible. */
+ padding-right: 8px;
}
-.token.eslint-marked:not(.eslint-marked-on-line-feed) + .token.eslint-marked-on-line-feed {
- /*
+.token.eslint-marked:not(.eslint-marked-on-line-feed)
+ + .token.eslint-marked-on-line-feed {
+ /*
* If there is a marker before the same line,
* there is no need to make visible the marker on the line feed code.
*/
- padding-right: 0;
+ padding-right: 0;
}
.token.eslint-marked-on-zero-width {
- position: relative;
+ position: relative;
- /* Delete the wavy line. */
- background: none;
+ /* Delete the wavy line. */
+ background: none;
}
.token.eslint-marked-on-zero-width::before {
- content: "";
- position: absolute;
- bottom: 0;
- left: -2px;
- border-left: 3px solid transparent;
- border-right: 3px solid transparent;
- border-bottom: 4px solid #d11;
+ content: "";
+ position: absolute;
+ bottom: 0;
+ left: -2px;
+ border-left: 3px solid transparent;
+ border-right: 3px solid transparent;
+ border-bottom: 4px solid #d11;
}
.line-numbers-wrapper {
- position: absolute;
- top: 0;
- left: 1.5rem;
- text-align: right;
- padding-top: 1.5rem;
- font-size: 1em;
- font-family: var(--mono-font), Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
- line-height: 1.5;
- color: var(--icon-color);
- font-variant-ligatures: none;
-
- .line-number {
- user-select: none;
- color: var(--icon-color);
- display: inline-block;
- font-variant-numeric: tabular-nums;
- text-align: right;
- width: 1.2em;
- }
+ position: absolute;
+ top: 0;
+ left: 1.5rem;
+ text-align: right;
+ padding-top: 1.5rem;
+ font-size: 1em;
+ font-family: var(--mono-font), Consolas, Monaco, "Andale Mono",
+ "Ubuntu Mono", monospace;
+ line-height: 1.5;
+ color: var(--icon-color);
+ font-variant-ligatures: none;
+
+ .line-number {
+ user-select: none;
+ color: var(--icon-color);
+ display: inline-block;
+ font-variant-numeric: tabular-nums;
+ text-align: right;
+ width: 1.2em;
+ }
}
diff --git a/docs/src/assets/scss/tokens/opacity.scss b/docs/src/assets/scss/tokens/opacity.scss
index c1f4ad9f488d..2a6fb240ed6f 100644
--- a/docs/src/assets/scss/tokens/opacity.scss
+++ b/docs/src/assets/scss/tokens/opacity.scss
@@ -1,18 +1,18 @@
:root {
- --opacity-100: 1;
- --opacity-60: 0.6;
+ --opacity-100: 1;
+ --opacity-60: 0.6;
}
@media (prefers-color-scheme: "dark") {
- :root {
- --logo-center-opacity: var(--opacity-60);
- }
+ :root {
+ --logo-center-opacity: var(--opacity-60);
+ }
}
html[data-theme="light"] {
- --logo-center-opacity: var(--opacity-100);
+ --logo-center-opacity: var(--opacity-100);
}
html[data-theme="dark"] {
- --logo-center-opacity: var(--opacity-60);
+ --logo-center-opacity: var(--opacity-60);
}
diff --git a/docs/src/assets/scss/tokens/spacing.scss b/docs/src/assets/scss/tokens/spacing.scss
index 2bc542459b52..47e63745c918 100644
--- a/docs/src/assets/scss/tokens/spacing.scss
+++ b/docs/src/assets/scss/tokens/spacing.scss
@@ -1,69 +1,144 @@
/* @link https://utopia.fyi/space/calculator?c=320,16,1.125,1023,16,1.25,6,2,&s=0.75|0.5|0.25,1.5|2|3|4|6|8,l-2xl|xl-3xl|xl-4xl|l-3xl|s-l */
:root {
- --fluid-min-width: 320;
- --fluid-max-width: 1023;
+ --fluid-min-width: 320;
+ --fluid-max-width: 1023;
- --fluid-screen: 100vw;
- --fluid-bp: calc((var(--fluid-screen) - var(--fluid-min-width) / 16 * 1rem) / (var(--fluid-max-width) - var(--fluid-min-width)));
+ --fluid-screen: 100vw;
+ --fluid-bp: calc(
+ (var(--fluid-screen) - var(--fluid-min-width) / 16 * 1rem) /
+ (var(--fluid-max-width) - var(--fluid-min-width))
+ );
- --fc-3xs-min: (var(--fc-s-min) * 0.25);
- --fc-3xs-max: (var(--fc-s-max) * 0.25);
+ --fc-3xs-min: (var(--fc-s-min) * 0.25);
+ --fc-3xs-max: (var(--fc-s-max) * 0.25);
- --fc-2xs-min: (var(--fc-s-min) * 0.5);
- --fc-2xs-max: (var(--fc-s-max) * 0.5);
+ --fc-2xs-min: (var(--fc-s-min) * 0.5);
+ --fc-2xs-max: (var(--fc-s-max) * 0.5);
- --fc-xs-min: (var(--fc-s-min) * 0.75);
- --fc-xs-max: (var(--fc-s-max) * 0.75);
+ --fc-xs-min: (var(--fc-s-min) * 0.75);
+ --fc-xs-max: (var(--fc-s-max) * 0.75);
- --fc-s-min: (var(--f-0-min, 16));
- --fc-s-max: (var(--f-0-max, 16));
+ --fc-s-min: (var(--f-0-min, 16));
+ --fc-s-max: (var(--f-0-max, 16));
- --fc-m-min: (var(--fc-s-min) * 1.5);
- --fc-m-max: (var(--fc-s-max) * 1.5);
+ --fc-m-min: (var(--fc-s-min) * 1.5);
+ --fc-m-max: (var(--fc-s-max) * 1.5);
- --fc-l-min: (var(--fc-s-min) * 2);
- --fc-l-max: (var(--fc-s-max) * 2);
+ --fc-l-min: (var(--fc-s-min) * 2);
+ --fc-l-max: (var(--fc-s-max) * 2);
- --fc-xl-min: (var(--fc-s-min) * 3);
- --fc-xl-max: (var(--fc-s-max) * 3);
+ --fc-xl-min: (var(--fc-s-min) * 3);
+ --fc-xl-max: (var(--fc-s-max) * 3);
- --fc-2xl-min: (var(--fc-s-min) * 4);
- --fc-2xl-max: (var(--fc-s-max) * 4);
+ --fc-2xl-min: (var(--fc-s-min) * 4);
+ --fc-2xl-max: (var(--fc-s-max) * 4);
- --fc-3xl-min: (var(--fc-s-min) * 6);
- --fc-3xl-max: (var(--fc-s-max) * 6);
+ --fc-3xl-min: (var(--fc-s-min) * 6);
+ --fc-3xl-max: (var(--fc-s-max) * 6);
- --fc-4xl-min: (var(--fc-s-min) * 8);
- --fc-4xl-max: (var(--fc-s-max) * 8);
+ --fc-4xl-min: (var(--fc-s-min) * 8);
+ --fc-4xl-max: (var(--fc-s-max) * 8);
- /* T-shirt sizes */
- --space-3xs: calc(((var(--fc-3xs-min) / 16) * 1rem) + (var(--fc-3xs-max) - var(--fc-3xs-min)) * var(--fluid-bp));
- --space-2xs: calc(((var(--fc-2xs-min) / 16) * 1rem) + (var(--fc-2xs-max) - var(--fc-2xs-min)) * var(--fluid-bp));
- --space-xs: calc(((var(--fc-xs-min) / 16) * 1rem) + (var(--fc-xs-max) - var(--fc-xs-min)) * var(--fluid-bp));
- --space-s: calc(((var(--fc-s-min) / 16) * 1rem) + (var(--fc-s-max) - var(--fc-s-min)) * var(--fluid-bp));
- --space-m: calc(((var(--fc-m-min) / 16) * 1rem) + (var(--fc-m-max) - var(--fc-m-min)) * var(--fluid-bp));
- --space-l: calc(((var(--fc-l-min) / 16) * 1rem) + (var(--fc-l-max) - var(--fc-l-min)) * var(--fluid-bp));
- --space-xl: calc(((var(--fc-xl-min) / 16) * 1rem) + (var(--fc-xl-max) - var(--fc-xl-min)) * var(--fluid-bp));
- --space-2xl: calc(((var(--fc-2xl-min) / 16) * 1rem) + (var(--fc-2xl-max) - var(--fc-2xl-min)) * var(--fluid-bp));
- --space-3xl: calc(((var(--fc-3xl-min) / 16) * 1rem) + (var(--fc-3xl-max) - var(--fc-3xl-min)) * var(--fluid-bp));
- --space-4xl: calc(((var(--fc-4xl-min) / 16) * 1rem) + (var(--fc-4xl-max) - var(--fc-4xl-min)) * var(--fluid-bp));
+ /* T-shirt sizes */
+ --space-3xs: calc(
+ ((var(--fc-3xs-min) / 16) * 1rem) +
+ (var(--fc-3xs-max) - var(--fc-3xs-min)) * var(--fluid-bp)
+ );
+ --space-2xs: calc(
+ ((var(--fc-2xs-min) / 16) * 1rem) +
+ (var(--fc-2xs-max) - var(--fc-2xs-min)) * var(--fluid-bp)
+ );
+ --space-xs: calc(
+ ((var(--fc-xs-min) / 16) * 1rem) + (var(--fc-xs-max) - var(--fc-xs-min)) *
+ var(--fluid-bp)
+ );
+ --space-s: calc(
+ ((var(--fc-s-min) / 16) * 1rem) + (var(--fc-s-max) - var(--fc-s-min)) *
+ var(--fluid-bp)
+ );
+ --space-m: calc(
+ ((var(--fc-m-min) / 16) * 1rem) + (var(--fc-m-max) - var(--fc-m-min)) *
+ var(--fluid-bp)
+ );
+ --space-l: calc(
+ ((var(--fc-l-min) / 16) * 1rem) + (var(--fc-l-max) - var(--fc-l-min)) *
+ var(--fluid-bp)
+ );
+ --space-xl: calc(
+ ((var(--fc-xl-min) / 16) * 1rem) + (var(--fc-xl-max) - var(--fc-xl-min)) *
+ var(--fluid-bp)
+ );
+ --space-2xl: calc(
+ ((var(--fc-2xl-min) / 16) * 1rem) +
+ (var(--fc-2xl-max) - var(--fc-2xl-min)) * var(--fluid-bp)
+ );
+ --space-3xl: calc(
+ ((var(--fc-3xl-min) / 16) * 1rem) +
+ (var(--fc-3xl-max) - var(--fc-3xl-min)) * var(--fluid-bp)
+ );
+ --space-4xl: calc(
+ ((var(--fc-4xl-min) / 16) * 1rem) +
+ (var(--fc-4xl-max) - var(--fc-4xl-min)) * var(--fluid-bp)
+ );
- /* One-up pairs */
- --space-3xs-2xs: calc(((var(--fc-3xs-min) / 16) * 1rem) + (var(--fc-2xs-max) - var(--fc-3xs-min)) * var(--fluid-bp));
- --space-2xs-xs: calc(((var(--fc-2xs-min) / 16) * 1rem) + (var(--fc-xs-max) - var(--fc-2xs-min)) * var(--fluid-bp));
- --space-xs-s: calc(((var(--fc-xs-min) / 16) * 1rem) + (var(--fc-s-max) - var(--fc-xs-min)) * var(--fluid-bp));
- --space-s-m: calc(((var(--fc-s-min) / 16) * 1rem) + (var(--fc-m-max) - var(--fc-s-min)) * var(--fluid-bp));
- --space-m-l: calc(((var(--fc-m-min) / 16) * 1rem) + (var(--fc-l-max) - var(--fc-m-min)) * var(--fluid-bp));
- --space-l-xl: calc(((var(--fc-l-min) / 16) * 1rem) + (var(--fc-xl-max) - var(--fc-l-min)) * var(--fluid-bp));
- --space-xl-2xl: calc(((var(--fc-xl-min) / 16) * 1rem) + (var(--fc-2xl-max) - var(--fc-xl-min)) * var(--fluid-bp));
- --space-2xl-3xl: calc(((var(--fc-2xl-min) / 16) * 1rem) + (var(--fc-3xl-max) - var(--fc-2xl-min)) * var(--fluid-bp));
- --space-3xl-4xl: calc(((var(--fc-3xl-min) / 16) * 1rem) + (var(--fc-4xl-max) - var(--fc-3xl-min)) * var(--fluid-bp));
+ /* One-up pairs */
+ --space-3xs-2xs: calc(
+ ((var(--fc-3xs-min) / 16) * 1rem) +
+ (var(--fc-2xs-max) - var(--fc-3xs-min)) * var(--fluid-bp)
+ );
+ --space-2xs-xs: calc(
+ ((var(--fc-2xs-min) / 16) * 1rem) +
+ (var(--fc-xs-max) - var(--fc-2xs-min)) * var(--fluid-bp)
+ );
+ --space-xs-s: calc(
+ ((var(--fc-xs-min) / 16) * 1rem) + (var(--fc-s-max) - var(--fc-xs-min)) *
+ var(--fluid-bp)
+ );
+ --space-s-m: calc(
+ ((var(--fc-s-min) / 16) * 1rem) + (var(--fc-m-max) - var(--fc-s-min)) *
+ var(--fluid-bp)
+ );
+ --space-m-l: calc(
+ ((var(--fc-m-min) / 16) * 1rem) + (var(--fc-l-max) - var(--fc-m-min)) *
+ var(--fluid-bp)
+ );
+ --space-l-xl: calc(
+ ((var(--fc-l-min) / 16) * 1rem) + (var(--fc-xl-max) - var(--fc-l-min)) *
+ var(--fluid-bp)
+ );
+ --space-xl-2xl: calc(
+ ((var(--fc-xl-min) / 16) * 1rem) +
+ (var(--fc-2xl-max) - var(--fc-xl-min)) * var(--fluid-bp)
+ );
+ --space-2xl-3xl: calc(
+ ((var(--fc-2xl-min) / 16) * 1rem) +
+ (var(--fc-3xl-max) - var(--fc-2xl-min)) * var(--fluid-bp)
+ );
+ --space-3xl-4xl: calc(
+ ((var(--fc-3xl-min) / 16) * 1rem) +
+ (var(--fc-4xl-max) - var(--fc-3xl-min)) * var(--fluid-bp)
+ );
- /* Custom pairs */
- --space-l-2xl: calc(((var(--fc-l-min) / 16) * 1rem) + (var(--fc-2xl-max) - var(--fc-l-min)) * var(--fluid-bp));
- --space-xl-3xl: calc(((var(--fc-xl-min) / 16) * 1rem) + (var(--fc-3xl-max) - var(--fc-xl-min)) * var(--fluid-bp));
- --space-xl-4xl: calc(((var(--fc-xl-min) / 16) * 1rem) + (var(--fc-4xl-max) - var(--fc-xl-min)) * var(--fluid-bp));
- --space-l-3xl: calc(((var(--fc-l-min) / 16) * 1rem) + (var(--fc-3xl-max) - var(--fc-l-min)) * var(--fluid-bp));
- --space-s-l: calc(((var(--fc-s-min) / 16) * 1rem) + (var(--fc-l-max) - var(--fc-s-min)) * var(--fluid-bp));
+ /* Custom pairs */
+ --space-l-2xl: calc(
+ ((var(--fc-l-min) / 16) * 1rem) + (var(--fc-2xl-max) - var(--fc-l-min)) *
+ var(--fluid-bp)
+ );
+ --space-xl-3xl: calc(
+ ((var(--fc-xl-min) / 16) * 1rem) +
+ (var(--fc-3xl-max) - var(--fc-xl-min)) * var(--fluid-bp)
+ );
+ --space-xl-4xl: calc(
+ ((var(--fc-xl-min) / 16) * 1rem) +
+ (var(--fc-4xl-max) - var(--fc-xl-min)) * var(--fluid-bp)
+ );
+ --space-l-3xl: calc(
+ ((var(--fc-l-min) / 16) * 1rem) + (var(--fc-3xl-max) - var(--fc-l-min)) *
+ var(--fluid-bp)
+ );
+ --space-s-l: calc(
+ ((var(--fc-s-min) / 16) * 1rem) + (var(--fc-l-max) - var(--fc-s-min)) *
+ var(--fluid-bp)
+ );
}
diff --git a/docs/src/assets/scss/tokens/themes.scss b/docs/src/assets/scss/tokens/themes.scss
index a48d2d742b56..6fb58f6bb43a 100644
--- a/docs/src/assets/scss/tokens/themes.scss
+++ b/docs/src/assets/scss/tokens/themes.scss
@@ -1,240 +1,240 @@
:root {
- /* Tier 1 variables */
- // colors
- --color-neutral-25: #fcfcfd;
- --color-neutral-50: #f9fafb;
- --color-neutral-100: #f2f4f7;
- --color-neutral-200: #e4e7ec;
- --color-neutral-300: #d0d5dd;
- --color-neutral-400: #98a2b3;
- --color-neutral-500: #667085;
- --color-neutral-600: #475467;
- --color-neutral-700: #344054;
- --color-neutral-800: #1d2939;
- --color-neutral-900: #101828;
-
- --color-primary-25: #fbfbff;
- --color-primary-50: #f6f6fe;
- --color-primary-100: #ececfd;
- --color-primary-200: #dedeff;
- --color-primary-300: #ccccfa;
- --color-primary-400: #b7b7ff;
- --color-primary-500: #a0a0f5;
- --color-primary-600: #8080f2;
- --color-primary-700: #6358d4;
- --color-primary-800: #4b32c3;
- --color-primary-900: #341bab;
-
- --color-warning-25: #fffcf5;
- --color-warning-50: #fffaeb;
- --color-warning-100: #fef0c7;
- --color-warning-200: #fedf89;
- --color-warning-300: #fec84b;
- --color-warning-400: #fdb022;
- --color-warning-500: #f79009;
- --color-warning-600: #dc6803;
- --color-warning-700: #b54708;
- --color-warning-800: #93370d;
- --color-warning-900: #7a2e0e;
-
- --color-success-25: #f6fef9;
- --color-success-50: #ecfdf3;
- --color-success-100: #d1fadf;
- --color-success-200: #a6f4c5;
- --color-success-300: #6ce9a6;
- --color-success-400: #32d583;
- --color-success-500: #12b76a;
- --color-success-600: #039855;
- --color-success-700: #027a48;
- --color-success-800: #05603a;
- --color-success-900: #054f31;
-
- --color-rose-25: #fff5f6;
- --color-rose-50: #fff1f3;
- --color-rose-100: #ffe4e8;
- --color-rose-200: #fecdd6;
- --color-rose-300: #fea3b4;
- --color-rose-400: #fd6f8e;
- --color-rose-500: #f63d68;
- --color-rose-600: #e31b54;
- --color-rose-700: #c01048;
- --color-rose-800: #a11043;
- --color-rose-900: #89123e;
-
- /* Tier 2 variables */
- --primary-button-background-color: var(--color-primary-800);
- --primary-button-hover-color: var(--color-primary-900);
- --primary-button-text-color: #fff;
- --secondary-button-background-color: var(--color-primary-50);
- --secondary-button-hover-color: var(--color-primary-100);
- --secondary-button-text-color: var(--color-brand);
- --ghost-button-background-color: var(--color-primary-50);
- --ghost-button-text-color: var(--color-brand);
-
- --color-brand: var(--color-primary-800);
- --body-background-color: #fff;
- --body-text-color: var(--color-neutral-500);
- --code-comments-color: var(--color-neutral-500);
- --headings-color: var(--color-neutral-900);
-
- --border-color: var(--color-neutral-300);
- --divider-color: var(--color-neutral-200);
-
- --icon-color: var(--color-neutral-400);
- --dark-icon-color: var(--color-neutral-500);
- --link-color: var(--color-primary-800);
-
- --lighter-background-color: var(--color-neutral-100);
- --lightest-background-color: var(--color-neutral-50);
- --docs-lightest-background-color: var(--color-primary-50);
- --hero-background-color: var(--color-neutral-25);
- --footer-background-color: var(--color-neutral-25);
- --outline-color: var(--color-brand);
- --img-background-color: #fff;
-
- --code-text-color: var(--color-neutral-900);
-
- --logo-color: var(--color-primary-800);
- --logo-center-color: var(--color-primary-600);
-
- --alert-tip-heading-color: var(--color-success-700);
- --alert-tip-color: var(--color-success-600);
- --alert-tip-background-color: var(--color-success-25);
-
- --alert-important-heading-color: var(--color-warning-700);
- --alert-important-color: var(--color-warning-600);
- --alert-important-background-color: var(--color-warning-25);
-
- --alert-warning-heading-color: var(--color-rose-700);
- --alert-warning-color: var(--color-rose-600);
- --alert-warning-background-color: var(--color-rose-25);
-
- --rule-status-background-color: var(--color-rose-50);
+ /* Tier 1 variables */
+ // colors
+ --color-neutral-25: #fcfcfd;
+ --color-neutral-50: #f9fafb;
+ --color-neutral-100: #f2f4f7;
+ --color-neutral-200: #e4e7ec;
+ --color-neutral-300: #d0d5dd;
+ --color-neutral-400: #98a2b3;
+ --color-neutral-500: #667085;
+ --color-neutral-600: #475467;
+ --color-neutral-700: #344054;
+ --color-neutral-800: #1d2939;
+ --color-neutral-900: #101828;
+
+ --color-primary-25: #fbfbff;
+ --color-primary-50: #f6f6fe;
+ --color-primary-100: #ececfd;
+ --color-primary-200: #dedeff;
+ --color-primary-300: #ccccfa;
+ --color-primary-400: #b7b7ff;
+ --color-primary-500: #a0a0f5;
+ --color-primary-600: #8080f2;
+ --color-primary-700: #6358d4;
+ --color-primary-800: #4b32c3;
+ --color-primary-900: #341bab;
+
+ --color-warning-25: #fffcf5;
+ --color-warning-50: #fffaeb;
+ --color-warning-100: #fef0c7;
+ --color-warning-200: #fedf89;
+ --color-warning-300: #fec84b;
+ --color-warning-400: #fdb022;
+ --color-warning-500: #f79009;
+ --color-warning-600: #dc6803;
+ --color-warning-700: #b54708;
+ --color-warning-800: #93370d;
+ --color-warning-900: #7a2e0e;
+
+ --color-success-25: #f6fef9;
+ --color-success-50: #ecfdf3;
+ --color-success-100: #d1fadf;
+ --color-success-200: #a6f4c5;
+ --color-success-300: #6ce9a6;
+ --color-success-400: #32d583;
+ --color-success-500: #12b76a;
+ --color-success-600: #039855;
+ --color-success-700: #027a48;
+ --color-success-800: #05603a;
+ --color-success-900: #054f31;
+
+ --color-rose-25: #fff5f6;
+ --color-rose-50: #fff1f3;
+ --color-rose-100: #ffe4e8;
+ --color-rose-200: #fecdd6;
+ --color-rose-300: #fea3b4;
+ --color-rose-400: #fd6f8e;
+ --color-rose-500: #f63d68;
+ --color-rose-600: #e31b54;
+ --color-rose-700: #c01048;
+ --color-rose-800: #a11043;
+ --color-rose-900: #89123e;
+
+ /* Tier 2 variables */
+ --primary-button-background-color: var(--color-primary-800);
+ --primary-button-hover-color: var(--color-primary-900);
+ --primary-button-text-color: #fff;
+ --secondary-button-background-color: var(--color-primary-50);
+ --secondary-button-hover-color: var(--color-primary-100);
+ --secondary-button-text-color: var(--color-brand);
+ --ghost-button-background-color: var(--color-primary-50);
+ --ghost-button-text-color: var(--color-brand);
+
+ --color-brand: var(--color-primary-800);
+ --body-background-color: #fff;
+ --body-text-color: var(--color-neutral-500);
+ --code-comments-color: var(--color-neutral-500);
+ --headings-color: var(--color-neutral-900);
+
+ --border-color: var(--color-neutral-300);
+ --divider-color: var(--color-neutral-200);
+
+ --icon-color: var(--color-neutral-400);
+ --dark-icon-color: var(--color-neutral-500);
+ --link-color: var(--color-primary-800);
+
+ --lighter-background-color: var(--color-neutral-100);
+ --lightest-background-color: var(--color-neutral-50);
+ --docs-lightest-background-color: var(--color-primary-50);
+ --hero-background-color: var(--color-neutral-25);
+ --footer-background-color: var(--color-neutral-25);
+ --outline-color: var(--color-brand);
+ --img-background-color: #fff;
+
+ --code-text-color: var(--color-neutral-900);
+
+ --logo-color: var(--color-primary-800);
+ --logo-center-color: var(--color-primary-600);
+
+ --alert-tip-heading-color: var(--color-success-700);
+ --alert-tip-color: var(--color-success-600);
+ --alert-tip-background-color: var(--color-success-25);
+
+ --alert-important-heading-color: var(--color-warning-700);
+ --alert-important-color: var(--color-warning-600);
+ --alert-important-background-color: var(--color-warning-25);
+
+ --alert-warning-heading-color: var(--color-rose-700);
+ --alert-warning-color: var(--color-rose-600);
+ --alert-warning-background-color: var(--color-rose-25);
+
+ --rule-status-background-color: var(--color-rose-50);
}
@media (prefers-color-scheme: dark) {
- :root {
- --body-background-color: var(--color-neutral-900);
- --body-text-color: var(--color-neutral-300);
- --code-comments-color: var(--color-neutral-400);
- --headings-color: #fff;
-
- --divider-color: var(--color-neutral-600);
- --border-color: var(--color-neutral-500);
-
- --icon-color: var(--body-text-color);
- --dark-icon-color: #fff;
- --link-color: var(--color-primary-400);
-
- --lighter-background-color: var(--color-neutral-800);
- --lightest-background-color: var(--color-neutral-800);
- --docs-lightest-background-color: var(--color-neutral-800);
- --hero-background-color: var(--color-neutral-800);
- --footer-background-color: var(--color-neutral-800);
- --outline-color: #fff;
- --img-background-color: var(--color-neutral-300);
-
- --code-text-color: var(--color-neutral-100);
-
- --logo-color: #fff;
- --logo-center-color: #fff;
-
- --alert-tip-heading-color: var(--color-success-200);
- --alert-tip-color: var(--color-success-300);
- --alert-tip-background-color: var(--color-success-900);
-
- --alert-important-heading-color: var(--color-warning-200);
- --alert-important-color: var(--color-warning-300);
- --alert-important-background-color: var(--color-warning-900);
-
- --alert-warning-heading-color: var(--color-rose-200);
- --alert-warning-color: var(--color-rose-300);
- --alert-warning-background-color: var(--color-rose-900);
-
- --rule-status-background-color: var(--color-neutral-900);
- }
+ :root {
+ --body-background-color: var(--color-neutral-900);
+ --body-text-color: var(--color-neutral-300);
+ --code-comments-color: var(--color-neutral-400);
+ --headings-color: #fff;
+
+ --divider-color: var(--color-neutral-600);
+ --border-color: var(--color-neutral-500);
+
+ --icon-color: var(--body-text-color);
+ --dark-icon-color: #fff;
+ --link-color: var(--color-primary-400);
+
+ --lighter-background-color: var(--color-neutral-800);
+ --lightest-background-color: var(--color-neutral-800);
+ --docs-lightest-background-color: var(--color-neutral-800);
+ --hero-background-color: var(--color-neutral-800);
+ --footer-background-color: var(--color-neutral-800);
+ --outline-color: #fff;
+ --img-background-color: var(--color-neutral-300);
+
+ --code-text-color: var(--color-neutral-100);
+
+ --logo-color: #fff;
+ --logo-center-color: #fff;
+
+ --alert-tip-heading-color: var(--color-success-200);
+ --alert-tip-color: var(--color-success-300);
+ --alert-tip-background-color: var(--color-success-900);
+
+ --alert-important-heading-color: var(--color-warning-200);
+ --alert-important-color: var(--color-warning-300);
+ --alert-important-background-color: var(--color-warning-900);
+
+ --alert-warning-heading-color: var(--color-rose-200);
+ --alert-warning-color: var(--color-rose-300);
+ --alert-warning-background-color: var(--color-rose-900);
+
+ --rule-status-background-color: var(--color-neutral-900);
+ }
}
html[data-theme="light"] {
- --body-background-color: #fff;
- --body-text-color: var(--color-neutral-500);
- --code-comments-color: var(--color-neutral-500);
- --headings-color: var(--color-neutral-900);
+ --body-background-color: #fff;
+ --body-text-color: var(--color-neutral-500);
+ --code-comments-color: var(--color-neutral-500);
+ --headings-color: var(--color-neutral-900);
- --border-color: var(--color-neutral-300);
- --divider-color: var(--color-neutral-200);
+ --border-color: var(--color-neutral-300);
+ --divider-color: var(--color-neutral-200);
- --icon-color: var(--color-neutral-400);
- --dark-icon-color: var(--color-neutral-500);
- --link-color: var(--color-primary-800);
+ --icon-color: var(--color-neutral-400);
+ --dark-icon-color: var(--color-neutral-500);
+ --link-color: var(--color-primary-800);
- --lighter-background-color: var(--color-neutral-100);
- --lightest-background-color: var(--color-neutral-50);
- --docs-lightest-background-color: var(--color-primary-50);
- --hero-background-color: var(--color-neutral-25);
- --footer-background-color: var(--color-neutral-25);
- --outline-color: var(--color-brand);
- --img-background-color: #fff;
+ --lighter-background-color: var(--color-neutral-100);
+ --lightest-background-color: var(--color-neutral-50);
+ --docs-lightest-background-color: var(--color-primary-50);
+ --hero-background-color: var(--color-neutral-25);
+ --footer-background-color: var(--color-neutral-25);
+ --outline-color: var(--color-brand);
+ --img-background-color: #fff;
- --code-text-color: var(--color-neutral-900);
+ --code-text-color: var(--color-neutral-900);
- --logo-color: var(--color-primary-800);
- --logo-center-color: var(--color-primary-600);
+ --logo-color: var(--color-primary-800);
+ --logo-center-color: var(--color-primary-600);
- --alert-tip-heading-color: var(--color-success-700);
- --alert-tip-color: var(--color-success-600);
- --alert-tip-background-color: var(--color-success-25);
+ --alert-tip-heading-color: var(--color-success-700);
+ --alert-tip-color: var(--color-success-600);
+ --alert-tip-background-color: var(--color-success-25);
- --alert-important-heading-color: var(--color-warning-700);
- --alert-important-color: var(--color-warning-600);
- --alert-important-background-color: var(--color-warning-25);
+ --alert-important-heading-color: var(--color-warning-700);
+ --alert-important-color: var(--color-warning-600);
+ --alert-important-background-color: var(--color-warning-25);
- --alert-warning-heading-color: var(--color-rose-700);
- --alert-warning-color: var(--color-rose-600);
- --alert-warning-background-color: var(--color-rose-25);
+ --alert-warning-heading-color: var(--color-rose-700);
+ --alert-warning-color: var(--color-rose-600);
+ --alert-warning-background-color: var(--color-rose-25);
- --rule-status-background-color: var(--color-rose-50);
+ --rule-status-background-color: var(--color-rose-50);
}
html[data-theme="dark"] {
- color-scheme: dark;
+ color-scheme: dark;
- --body-background-color: var(--color-neutral-900);
- --body-text-color: var(--color-neutral-300);
- --code-comments-color: var(--color-neutral-400);
- --headings-color: #fff;
+ --body-background-color: var(--color-neutral-900);
+ --body-text-color: var(--color-neutral-300);
+ --code-comments-color: var(--color-neutral-400);
+ --headings-color: #fff;
- --divider-color: var(--color-neutral-600);
- --border-color: var(--color-neutral-500);
+ --divider-color: var(--color-neutral-600);
+ --border-color: var(--color-neutral-500);
- --icon-color: var(--body-text-color);
- --dark-icon-color: #fff;
- --link-color: var(--color-primary-400);
+ --icon-color: var(--body-text-color);
+ --dark-icon-color: #fff;
+ --link-color: var(--color-primary-400);
- --lighter-background-color: var(--color-neutral-800);
- --lightest-background-color: var(--color-neutral-800);
- --docs-lightest-background-color: var(--color-neutral-800);
- --hero-background-color: var(--color-neutral-800);
- --footer-background-color: var(--color-neutral-800);
- --outline-color: #fff;
- --img-background-color: var(--color-neutral-300);
+ --lighter-background-color: var(--color-neutral-800);
+ --lightest-background-color: var(--color-neutral-800);
+ --docs-lightest-background-color: var(--color-neutral-800);
+ --hero-background-color: var(--color-neutral-800);
+ --footer-background-color: var(--color-neutral-800);
+ --outline-color: #fff;
+ --img-background-color: var(--color-neutral-300);
- --code-text-color: var(--color-neutral-100);
+ --code-text-color: var(--color-neutral-100);
- --logo-color: #fff;
- --logo-center-color: #fff;
+ --logo-color: #fff;
+ --logo-center-color: #fff;
- --alert-tip-heading-color: var(--color-success-200);
- --alert-tip-color: var(--color-success-300);
- --alert-tip-background-color: var(--color-success-900);
+ --alert-tip-heading-color: var(--color-success-200);
+ --alert-tip-color: var(--color-success-300);
+ --alert-tip-background-color: var(--color-success-900);
- --alert-important-heading-color: var(--color-warning-200);
- --alert-important-color: var(--color-warning-300);
- --alert-important-background-color: var(--color-warning-900);
+ --alert-important-heading-color: var(--color-warning-200);
+ --alert-important-color: var(--color-warning-300);
+ --alert-important-background-color: var(--color-warning-900);
- --alert-warning-heading-color: var(--color-rose-200);
- --alert-warning-color: var(--color-rose-300);
- --alert-warning-background-color: var(--color-rose-900);
+ --alert-warning-heading-color: var(--color-rose-200);
+ --alert-warning-color: var(--color-rose-300);
+ --alert-warning-background-color: var(--color-rose-900);
- --rule-status-background-color: var(--color-neutral-900);
+ --rule-status-background-color: var(--color-neutral-900);
}
diff --git a/docs/src/assets/scss/tokens/typography.scss b/docs/src/assets/scss/tokens/typography.scss
index a9e935b2a01f..a03390682767 100644
--- a/docs/src/assets/scss/tokens/typography.scss
+++ b/docs/src/assets/scss/tokens/typography.scss
@@ -1,78 +1,89 @@
/* @link https://utopia.fyi/type/calculator?c=320,16,1.125,1280,16,1.25,6,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l */
@media screen and (min-width: 1280px) {
- :root {
- --fluid-screen: calc(var(--fluid-max-width) * 1px);
- }
+ :root {
+ --fluid-screen: calc(var(--fluid-max-width) * 1px);
+ }
}
:root {
- --fluid-min-width: 320;
- --fluid-max-width: 1280;
+ --fluid-min-width: 320;
+ --fluid-max-width: 1280;
- --fluid-screen: 100vw;
- --fluid-bp: calc((var(--fluid-screen) - var(--fluid-min-width) / 16 * 1rem) / (var(--fluid-max-width) - var(--fluid-min-width)));
+ --fluid-screen: 100vw;
+ --fluid-bp: calc(
+ (var(--fluid-screen) - var(--fluid-min-width) / 16 * 1rem) /
+ (var(--fluid-max-width) - var(--fluid-min-width))
+ );
- --f--2-min: 12.64;
- --f--2-max: 10.24;
- --step--2: calc(((var(--f--2-min) / 16) * 1rem) + (var(--f--2-max) - var(--f--2-min)) * var(--fluid-bp));
+ --f--2-min: 12.64;
+ --f--2-max: 10.24;
+ --step--2: calc(
+ ((var(--f--2-min) / 16) * 1rem) + (var(--f--2-max) - var(--f--2-min)) *
+ var(--fluid-bp)
+ );
- --f--1-min: 14.22;
- --f--1-max: 12.80;
- --step--1: calc(((var(--f--1-min) / 16) * 1rem) + (var(--f--1-max) - var(--f--1-min)) * var(--fluid-bp));
+ --f--1-min: 14.22;
+ --f--1-max: 12.8;
+ --step--1: calc(
+ ((var(--f--1-min) / 16) * 1rem) + (var(--f--1-max) - var(--f--1-min)) *
+ var(--fluid-bp)
+ );
- --f-0-min: 16.00;
- --f-0-max: 16.00;
- --step-0: calc(((var(--f-0-min) / 16) * 1rem) + (var(--f-0-max) - var(--f-0-min)) * var(--fluid-bp));
+ --f-0-min: 16;
+ --f-0-max: 16;
+ --step-0: calc(
+ ((var(--f-0-min) / 16) * 1rem) + (var(--f-0-max) - var(--f-0-min)) *
+ var(--fluid-bp)
+ );
- --f-1-min: 18.00;
- --f-1-max: 20.00;
- --step-1: calc(((var(--f-1-min) / 16) * 1rem) + (var(--f-1-max) - var(--f-1-min)) * var(--fluid-bp));
+ --f-1-min: 18;
+ --f-1-max: 20;
+ --step-1: calc(
+ ((var(--f-1-min) / 16) * 1rem) + (var(--f-1-max) - var(--f-1-min)) *
+ var(--fluid-bp)
+ );
- --f-2-min: 20.25;
- --f-2-max: 25.00;
- --step-2: calc(((var(--f-2-min) / 16) * 1rem) + (var(--f-2-max) - var(--f-2-min)) * var(--fluid-bp));
+ --f-2-min: 20.25;
+ --f-2-max: 25;
+ --step-2: calc(
+ ((var(--f-2-min) / 16) * 1rem) + (var(--f-2-max) - var(--f-2-min)) *
+ var(--fluid-bp)
+ );
- --f-3-min: 22.78;
- --f-3-max: 31.25;
- --step-3: calc(((var(--f-3-min) / 16) * 1rem) + (var(--f-3-max) - var(--f-3-min)) * var(--fluid-bp));
+ --f-3-min: 22.78;
+ --f-3-max: 31.25;
+ --step-3: calc(
+ ((var(--f-3-min) / 16) * 1rem) + (var(--f-3-max) - var(--f-3-min)) *
+ var(--fluid-bp)
+ );
- --f-4-min: 25.63;
- --f-4-max: 39.06;
- --step-4: calc(((var(--f-4-min) / 16) * 1rem) + (var(--f-4-max) - var(--f-4-min)) * var(--fluid-bp));
+ --f-4-min: 25.63;
+ --f-4-max: 39.06;
+ --step-4: calc(
+ ((var(--f-4-min) / 16) * 1rem) + (var(--f-4-max) - var(--f-4-min)) *
+ var(--fluid-bp)
+ );
- --f-5-min: 28.83;
- --f-5-max: 48.83;
- --step-5: calc(((var(--f-5-min) / 16) * 1rem) + (var(--f-5-max) - var(--f-5-min)) * var(--fluid-bp));
+ --f-5-min: 28.83;
+ --f-5-max: 48.83;
+ --step-5: calc(
+ ((var(--f-5-min) / 16) * 1rem) + (var(--f-5-max) - var(--f-5-min)) *
+ var(--fluid-bp)
+ );
- --f-6-min: 32.44;
- --f-6-max: 61.04;
- --step-6: calc(((var(--f-6-min) / 16) * 1rem) + (var(--f-6-max) - var(--f-6-min)) * var(--fluid-bp));
+ --f-6-min: 32.44;
+ --f-6-max: 61.04;
+ --step-6: calc(
+ ((var(--f-6-min) / 16) * 1rem) + (var(--f-6-max) - var(--f-6-min)) *
+ var(--fluid-bp)
+ );
- --mono-font: "Mono Punctuators", "Space Mono", monospace;
- --text-font:
- "Inter",
- -apple-system,
- BlinkMacSystemFont,
- "Segoe UI",
- Roboto,
- Helvetica,
- Arial,
- sans-serif,
- "Apple Color Emoji",
- "Twemoji Country Flags",
- "Segoe UI Emoji",
- "Segoe UI Symbol";
- --display-font:
- "Space Grotesk",
- -apple-system,
- BlinkMacSystemFont,
- "Segoe UI",
- Roboto,
- Helvetica,
- Arial,
- sans-serif,
- "Apple Color Emoji",
- "Segoe UI Emoji",
- "Segoe UI Symbol";
+ --mono-font: "Mono Punctuators", "Space Mono", monospace;
+ --text-font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ Helvetica, Arial, sans-serif, "Apple Color Emoji",
+ "Twemoji Country Flags", "Segoe UI Emoji", "Segoe UI Symbol";
+ --display-font: "Space Grotesk", -apple-system, BlinkMacSystemFont,
+ "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
+ "Segoe UI Emoji", "Segoe UI Symbol";
}
diff --git a/docs/src/assets/scss/tokens/ui.scss b/docs/src/assets/scss/tokens/ui.scss
index 49380e12da85..7865467affa6 100644
--- a/docs/src/assets/scss/tokens/ui.scss
+++ b/docs/src/assets/scss/tokens/ui.scss
@@ -1,9 +1,8 @@
:root {
- // elevations
- --shadow-lg:
- 0 12px 16px -4px rgba(16, 24, 40, 0.1),
- 0 4px 6px -2px rgba(16, 24, 40, 0.05);
- --shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.05);
+ // elevations
+ --shadow-lg: 0 12px 16px -4px rgba(16, 24, 40, 0.1),
+ 0 4px 6px -2px rgba(16, 24, 40, 0.05);
+ --shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.05);
- --border-radius: .5rem;
+ --border-radius: 0.5rem;
}
diff --git a/docs/src/assets/scss/utilities.scss b/docs/src/assets/scss/utilities.scss
index c296358837ee..5705bed3a068 100644
--- a/docs/src/assets/scss/utilities.scss
+++ b/docs/src/assets/scss/utilities.scss
@@ -1,171 +1,171 @@
.grid {
- @media all and (min-width: 1024px) {
- display: grid;
- grid-template-columns: repeat(12, 1fr);
- grid-gap: 2rem;
- align-items: start;
- }
+ @media all and (min-width: 1024px) {
+ display: grid;
+ grid-template-columns: repeat(12, 1fr);
+ grid-gap: 2rem;
+ align-items: start;
+ }
}
.visually-hidden {
- clip: rect(0 0 0 0);
- clip-path: inset(100%);
- height: 1px;
- overflow: hidden;
- position: absolute;
- width: 1px;
- white-space: nowrap;
+ clip: rect(0 0 0 0);
+ clip-path: inset(100%);
+ height: 1px;
+ overflow: hidden;
+ position: absolute;
+ width: 1px;
+ white-space: nowrap;
}
[hidden] {
- display: none !important;
+ display: none !important;
}
.mobile-only {
- @media all and (min-width: 1024px) {
- display: none;
- }
+ @media all and (min-width: 1024px) {
+ display: none;
+ }
}
.desktop-only {
- @media all and (max-width: 1023px) {
- display: none;
- }
+ @media all and (max-width: 1023px) {
+ display: none;
+ }
}
.text.text {
- color: inherit;
- font: inherit;
- font-family: var(--text-font);
- margin: 0;
+ color: inherit;
+ font: inherit;
+ font-family: var(--text-font);
+ margin: 0;
}
.color-brand {
- color: var(--link-color);
+ color: var(--link-color);
}
.font-weight-medium {
- font-weight: 500;
+ font-weight: 500;
}
.center-text {
- text-align: center;
- grid-column: 1 / -1;
+ text-align: center;
+ grid-column: 1 / -1;
}
.text-dark {
- color: var(--headings-color);
+ color: var(--headings-color);
}
.divider {
- border-bottom: 1px solid var(--divider-color);
- border-block-end: 1px solid var(--divider-color);
+ border-bottom: 1px solid var(--divider-color);
+ border-block-end: 1px solid var(--divider-color);
}
.fs-step--1 {
- font-size: .875rem;
+ font-size: 0.875rem;
}
.fs-step-0 {
- font-size: var(--step-0);
+ font-size: var(--step-0);
}
.fs-step-1 {
- font-size: var(--step-1);
+ font-size: var(--step-1);
}
.fs-step-2 {
- font-size: var(--step-2);
+ font-size: var(--step-2);
}
.fs-step-3 {
- font-size: var(--step-3);
+ font-size: var(--step-3);
}
.fs-step-4 {
- font-size: var(--step-4);
+ font-size: var(--step-4);
}
.fs-step-5 {
- font-size: var(--step-5);
+ font-size: var(--step-5);
}
.fs-step-6 {
- font-size: var(--step-6);
+ font-size: var(--step-6);
}
.grid--center-items {
- align-items: center;
+ align-items: center;
}
.span-1-3 {
- grid-column: 1 / 4;
+ grid-column: 1 / 4;
}
.span-1-4 {
- grid-column: 1 / 5;
+ grid-column: 1 / 5;
}
.span-1-5 {
- grid-column: 1 / 6;
+ grid-column: 1 / 6;
}
.span-1-6 {
- grid-column: 1 / 7;
+ grid-column: 1 / 7;
}
.span-1-7 {
- grid-column: 1 / 8;
+ grid-column: 1 / 8;
}
.span-1-12 {
- grid-column: 1 / -1;
+ grid-column: 1 / -1;
}
.span-4-12 {
- grid-column: 4 / 13;
+ grid-column: 4 / 13;
}
.span-6-12 {
- grid-column: 6 / 13;
+ grid-column: 6 / 13;
}
.span-7-12 {
- grid-column: 7 / 13;
+ grid-column: 7 / 13;
}
.span-8-12 {
- grid-column: 8 / 13;
+ grid-column: 8 / 13;
}
.span-10-12 {
- grid-column: 10 / 13;
+ grid-column: 10 / 13;
}
.span-11-12 {
- grid-column: 11 / 13;
+ grid-column: 11 / 13;
}
.span-4-9 {
- grid-column: 4 / 10;
+ grid-column: 4 / 10;
}
.span-4-11 {
- grid-column: 4 / 11;
+ grid-column: 4 / 11;
}
.span-5-12 {
- grid-column: 5 / 12;
+ grid-column: 5 / 12;
}
.span-3-10 {
- grid-column: 3 / 11;
+ grid-column: 3 / 11;
}
.span-6-7 {
- grid-column: 6 / 8;
+ grid-column: 6 / 8;
}
.span-5-8 {
- grid-column: 5 / 9;
+ grid-column: 5 / 9;
}
diff --git a/docs/src/assets/scss/versions.scss b/docs/src/assets/scss/versions.scss
index f0979c64f4ea..bcaac9511469 100644
--- a/docs/src/assets/scss/versions.scss
+++ b/docs/src/assets/scss/versions.scss
@@ -1,50 +1,50 @@
.versions-list {
- margin: 0;
- padding: 0;
- font-size: var(--step-1);
+ margin: 0;
+ padding: 0;
+ font-size: var(--step-1);
- li {
- margin: 0;
+ li {
+ margin: 0;
- &:last-of-type a {
- border-bottom: 0;
- border-block-end: 0;
- }
- }
+ &:last-of-type a {
+ border-bottom: 0;
+ border-block-end: 0;
+ }
+ }
- a {
- color: var(--link-color);
- width: 100%;
- padding: 1rem .5rem;
- text-decoration: none;
- display: block;
- display: flex;
- align-items: center;
- border-bottom: 1px solid var(--divider-color);
- border-block-end: 1px solid var(--divider-color);
+ a {
+ color: var(--link-color);
+ width: 100%;
+ padding: 1rem 0.5rem;
+ text-decoration: none;
+ display: block;
+ display: flex;
+ align-items: center;
+ border-bottom: 1px solid var(--divider-color);
+ border-block-end: 1px solid var(--divider-color);
- &[data-current="true"] {
- font-weight: 500;
- color: var(--link-color);
+ &[data-current="true"] {
+ font-weight: 500;
+ color: var(--link-color);
- &::after {
- content: " âī¸";
- white-space: pre;
- color: rgba(100%, 0%, 0%, 0);
- text-shadow: 0 0 0 var(--headings-color);
- }
- }
+ &::after {
+ content: " âī¸";
+ white-space: pre;
+ color: rgba(100%, 0%, 0%, 0);
+ text-shadow: 0 0 0 var(--headings-color);
+ }
+ }
- &:hover {
- background-color: var(--lightest-background-color);
- }
- }
+ &:hover {
+ background-color: var(--lightest-background-color);
+ }
+ }
}
.versions-section .versions-list {
- font-size: var(--step-1);
- border-left: 4px solid var(--tab-border-color);
- padding-left: 1rem;
- border-inline-start: 4px solid var(--tab-border-color);
- padding-inline-start: 1rem;
+ font-size: var(--step-1);
+ border-left: 4px solid var(--tab-border-color);
+ padding-left: 1rem;
+ border-inline-start: 4px solid var(--tab-border-color);
+ padding-inline-start: 1rem;
}
diff --git a/docs/src/contribute/architecture/index.md b/docs/src/contribute/architecture/index.md
index 152bb195b53a..923e3ae14f13 100644
--- a/docs/src/contribute/architecture/index.md
+++ b/docs/src/contribute/architecture/index.md
@@ -13,14 +13,14 @@ eleventyNavigation:
At a high level, there are a few key parts to ESLint:
-* `bin/eslint.js` - this is the file that actually gets executed with the command line utility. It's a dumb wrapper that does nothing more than bootstrap ESLint, passing the command line arguments to `cli`. This is intentionally small so as not to require heavy testing.
-* `lib/api.js` - this is the entry point of `require("eslint")`. This file exposes an object that contains public classes `Linter`, `ESLint`, `RuleTester`, and `SourceCode`.
-* `lib/cli.js` - this is the heart of the ESLint CLI. It takes an array of arguments and then uses `eslint` to execute the commands. By keeping this as a separate utility, it allows others to effectively call ESLint from within another Node.js program as if it were done on the command line. The main call is `cli.execute()`. This is also the part that does all the file reading, directory traversing, input, and output.
-* `lib/cli-engine/` - this module is `CLIEngine` class that finds source code files and configuration files then does code verifying with the `Linter` class. This includes the loading logic of configuration files, parsers, plugins, and formatters.
-* `lib/linter/` - this module is the core `Linter` class that does code verifying based on configuration options. This file does no file I/O and does not interact with the `console` at all. For other Node.js programs that have JavaScript text to verify, they would be able to use this interface directly.
-* `lib/rule-tester/` - this module is `RuleTester` class that is a wrapper around Mocha so that rules can be unit tested. This class lets us write consistently formatted tests for each rule that is implemented and be confident that each of the rules work. The RuleTester interface was modeled after Mocha and works with Mocha's global testing methods. RuleTester can also be modified to work with other testing frameworks.
-* `lib/source-code/` - this module is `SourceCode` class that is used to represent the parsed source code. It takes in source code and the Program node of the AST representing the code.
-* `lib/rules/` - this contains built-in rules that verify source code.
+- `bin/eslint.js` - this is the file that actually gets executed with the command line utility. It's a dumb wrapper that does nothing more than bootstrap ESLint, passing the command line arguments to `cli`. This is intentionally small so as not to require heavy testing.
+- `lib/api.js` - this is the entry point of `require("eslint")`. This file exposes an object that contains public classes `Linter`, `ESLint`, `RuleTester`, and `SourceCode`.
+- `lib/cli.js` - this is the heart of the ESLint CLI. It takes an array of arguments and then uses `eslint` to execute the commands. By keeping this as a separate utility, it allows others to effectively call ESLint from within another Node.js program as if it were done on the command line. The main call is `cli.execute()`. This is also the part that does all the file reading, directory traversing, input, and output.
+- `lib/cli-engine/` - this module is `CLIEngine` class that finds source code files and configuration files then does code verifying with the `Linter` class. This includes the loading logic of configuration files, parsers, plugins, and formatters.
+- `lib/linter/` - this module is the core `Linter` class that does code verifying based on configuration options. This file does no file I/O and does not interact with the `console` at all. For other Node.js programs that have JavaScript text to verify, they would be able to use this interface directly.
+- `lib/rule-tester/` - this module is `RuleTester` class that is a wrapper around Mocha so that rules can be unit tested. This class lets us write consistently formatted tests for each rule that is implemented and be confident that each of the rules work. The RuleTester interface was modeled after Mocha and works with Mocha's global testing methods. RuleTester can also be modified to work with other testing frameworks.
+- `lib/source-code/` - this module is `SourceCode` class that is used to represent the parsed source code. It takes in source code and the Program node of the AST representing the code.
+- `lib/rules/` - this contains built-in rules that verify source code.
## The `cli` object
@@ -30,17 +30,17 @@ The main method is `cli.execute()`, which accepts an array of strings that repre
This object's responsibilities include:
-* Interpreting command line arguments.
-* Reading from the file system.
-* Outputting to the console.
-* Outputting to the filesystem.
-* Use a formatter.
-* Returning the correct exit code.
+- Interpreting command line arguments.
+- Reading from the file system.
+- Outputting to the console.
+- Outputting to the filesystem.
+- Use a formatter.
+- Returning the correct exit code.
This object may not:
-* Call `process.exit()` directly.
-* Perform any asynchronous operations.
+- Call `process.exit()` directly.
+- Perform any asynchronous operations.
## The `CLIEngine` object
@@ -50,16 +50,16 @@ The main method of the `CLIEngine` is `executeOnFiles()`, which accepts an array
This object's responsibilities include:
-* Managing the execution environment for `Linter`.
-* Reading from the file system.
-* Reading configuration information from config files (including `.eslintrc` and `package.json`).
+- Managing the execution environment for `Linter`.
+- Reading from the file system.
+- Reading configuration information from config files (including `.eslintrc` and `package.json`).
This object may not:
-* Call `process.exit()` directly.
-* Perform any asynchronous operations.
-* Output to the console.
-* Use formatters.
+- Call `process.exit()` directly.
+- Perform any asynchronous operations.
+- Output to the console.
+- Use formatters.
## The `Linter` object
@@ -69,18 +69,18 @@ Once the AST is available, `estraverse` is used to traverse the AST from top to
This object's responsibilities include:
-* Inspecting JavaScript code strings.
-* Creating an AST for the code.
-* Executing rules on the AST.
-* Reporting back the results of the execution.
+- Inspecting JavaScript code strings.
+- Creating an AST for the code.
+- Executing rules on the AST.
+- Reporting back the results of the execution.
This object may not:
-* Call `process.exit()` directly.
-* Perform any asynchronous operations.
-* Use Node.js-specific features.
-* Access the file system.
-* Call `console.log()` or any other similar method.
+- Call `process.exit()` directly.
+- Perform any asynchronous operations.
+- Use Node.js-specific features.
+- Access the file system.
+- Call `console.log()` or any other similar method.
## Rules
@@ -88,13 +88,13 @@ Individual rules are the most specialized part of the ESLint architecture. Rules
These objects' responsibilities are:
-* Inspect the AST for specific patterns.
-* Reporting warnings when certain patterns are found.
+- Inspect the AST for specific patterns.
+- Reporting warnings when certain patterns are found.
These objects may not:
-* Call `process.exit()` directly.
-* Perform any asynchronous operations.
-* Use Node.js-specific features.
-* Access the file system.
-* Call `console.log()` or any other similar method.
+- Call `process.exit()` directly.
+- Perform any asynchronous operations.
+- Use Node.js-specific features.
+- Access the file system.
+- Call `console.log()` or any other similar method.
diff --git a/docs/src/contribute/core-rules.md b/docs/src/contribute/core-rules.md
index 3422792738b8..d3efa4b49fe6 100644
--- a/docs/src/contribute/core-rules.md
+++ b/docs/src/contribute/core-rules.md
@@ -20,9 +20,9 @@ For full reference information on writing rules, refer to [Custom Rules](../exte
Each core rule in ESLint has three files named with its identifier (for example, `no-extra-semi`).
-* in the `lib/rules` directory: a source file (for example, `no-extra-semi.js`).
-* in the `tests/lib/rules` directory: a test file (for example, `no-extra-semi.js`).
-* in the `docs/src/rules` directory: a Markdown documentation file (for example, `no-extra-semi.md`).
+- in the `lib/rules` directory: a source file (for example, `no-extra-semi.js`).
+- in the `tests/lib/rules` directory: a test file (for example, `no-extra-semi.js`).
+- in the `docs/src/rules` directory: a Markdown documentation file (for example, `no-extra-semi.md`).
**Important:** If you submit a core rule to the ESLint repository, you **must** follow the conventions explained below.
@@ -42,22 +42,22 @@ Here is the basic format of the source file for a rule:
/** @type {import('../shared/types').Rule} */
module.exports = {
- meta: {
- type: "suggestion",
-
- docs: {
- description: "disallow unnecessary semicolons",
- recommended: true,
- url: "https://eslint.org/docs/rules/no-extra-semi"
- },
- fixable: "code",
- schema: [] // no options
- },
- create: function(context) {
- return {
- // callback functions
- };
- }
+ meta: {
+ type: "suggestion",
+
+ docs: {
+ description: "disallow unnecessary semicolons",
+ recommended: true,
+ url: "https://eslint.org/docs/rules/no-extra-semi",
+ },
+ fixable: "code",
+ schema: [], // no options
+ },
+ create: function (context) {
+ return {
+ // callback functions
+ };
+ },
};
```
@@ -105,9 +105,9 @@ Performance budget ok: 1443.736547ms (limit: 3409.090909090909ms)
The rule naming conventions for ESLint are as follows:
-* Use dashes between words.
-* If your rule only disallows something, prefix it with `no-` such as `no-eval` for disallowing `eval()` and `no-debugger` for disallowing `debugger`.
-* If your rule is enforcing the inclusion of something, use a short name without a special prefix.
+- Use dashes between words.
+- If your rule only disallows something, prefix it with `no-` such as `no-eval` for disallowing `eval()` and `no-debugger` for disallowing `debugger`.
+- If your rule is enforcing the inclusion of something, use a short name without a special prefix.
## Frozen Rules
@@ -115,8 +115,8 @@ When rules are feature complete, they are marked as frozen (indicated with â
When a rule is frozen, it means:
-* **Bug fixes**: We will still fix confirmed bugs.
-* **New ECMAScript features**: We will ensure compatibility with new ECMAScript features, meaning the rule will not break on new syntax.
-* **New options**: We will **not** add any new options unless an option is the only way to fix a bug or support a newly-added ECMAScript feature.
+- **Bug fixes**: We will still fix confirmed bugs.
+- **New ECMAScript features**: We will ensure compatibility with new ECMAScript features, meaning the rule will not break on new syntax.
+- **New options**: We will **not** add any new options unless an option is the only way to fix a bug or support a newly-added ECMAScript feature.
If you find that a frozen rule would work better for you with a change, we recommend copying the rule source code and modifying it to fit your needs.
diff --git a/docs/src/contribute/development-environment.md b/docs/src/contribute/development-environment.md
index ef1190c89a14..3baf835cbe86 100644
--- a/docs/src/contribute/development-environment.md
+++ b/docs/src/contribute/development-environment.md
@@ -45,7 +45,7 @@ You must be connected to the Internet for this step to work. You'll see a lot of
## Step 3: Add the Upstream Source
-The *upstream source* is the main ESLint repository where active development happens. While you won't have push access to upstream, you will have pull access, allowing you to pull in the latest code whenever you want.
+The _upstream source_ is the main ESLint repository where active development happens. While you won't have push access to upstream, you will have pull access, allowing you to pull in the latest code whenever you want.
To add the upstream source for ESLint, run the following in your repository:
@@ -91,16 +91,16 @@ The testing takes a few minutes to complete. If any tests fail, that likely mean
The ESLint directory and file structure is as follows:
-* `bin` - executable files that are available when ESLint is installed.
-* `conf` - default configuration information.
-* `docs` - documentation for the project.
-* `lib` - contains the source code.
- * `formatters` - all source files defining formatters.
- * `rules` - all source files defining rules.
-* `tests` - the main unit test folder.
- * `lib` - tests for the source code.
- * `formatters` - tests for the formatters.
- * `rules` - tests for the rules.
+- `bin` - executable files that are available when ESLint is installed.
+- `conf` - default configuration information.
+- `docs` - documentation for the project.
+- `lib` - contains the source code.
+ - `formatters` - all source files defining formatters.
+ - `rules` - all source files defining rules.
+- `tests` - the main unit test folder.
+ - `lib` - tests for the source code.
+ - `formatters` - tests for the formatters.
+ - `rules` - tests for the rules.
### Workflow
diff --git a/docs/src/contribute/governance.md b/docs/src/contribute/governance.md
index 694e5eb4f50c..de22605f05b4 100644
--- a/docs/src/contribute/governance.md
+++ b/docs/src/contribute/governance.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: contribute to eslint
title: Governance
order: 12
-
---
ESLint is an open source project that depends on contributions from the community. Anyone may contribute to the project at any time by submitting code, participating in discussions, making suggestions, or any other contribution they see fit. This document describes how various types of contributors work within the ESLint project.
@@ -30,25 +29,25 @@ As Contributors gain experience and familiarity with the project, their profile
Website Team Members are community members who have shown that they are committed to the continued maintenance of [eslint.org](https://eslint.org/) through ongoing engagement with the community. Website Team Members are given push access to the `eslint.org` GitHub repository and must abide by the project's [Contribution Guidelines](../contribute/).
- Website Team Members:
+Website Team Members:
-* Are expected to work at least one hour per week triaging issues and reviewing pull requests.
-* Are expected to work at least two hours total per week on ESLint.
-* May invoice for the hours they spend working on ESLint at a rate of $50 USD per hour.
-* Are expected to check in on the `#team` Discord channel once per week day (excluding holidays and other time off) for team updates.
-* Are expected to work on public branches of the source repository and submit pull requests from that branch to the master branch.
-* Are expected to delete their public branches when they are no longer necessary.
-* Must submit pull requests for all changes.
-* Have their work reviewed by Reviewers and TSC members before acceptance into the repository.
-* May label and close website-related issues (see [Manage Issues](../maintain/manage-issues)).
-* May merge some pull requests (see [Review Pull Requests](../maintain/review-pull-requests)).
-* May take time off whenever they want, and are expected to post in the `#team` Discord channel when they will be away for more than a couple of days.
+- Are expected to work at least one hour per week triaging issues and reviewing pull requests.
+- Are expected to work at least two hours total per week on ESLint.
+- May invoice for the hours they spend working on ESLint at a rate of $50 USD per hour.
+- Are expected to check in on the `#team` Discord channel once per week day (excluding holidays and other time off) for team updates.
+- Are expected to work on public branches of the source repository and submit pull requests from that branch to the master branch.
+- Are expected to delete their public branches when they are no longer necessary.
+- Must submit pull requests for all changes.
+- Have their work reviewed by Reviewers and TSC members before acceptance into the repository.
+- May label and close website-related issues (see [Manage Issues](../maintain/manage-issues)).
+- May merge some pull requests (see [Review Pull Requests](../maintain/review-pull-requests)).
+- May take time off whenever they want, and are expected to post in the `#team` Discord channel when they will be away for more than a couple of days.
-To become a Website Team Member:
+To become a Website Team Member:
-* One must have shown a willingness and ability to participate in the maintenance of [eslint.org](https://eslint.org/) as a team player. Typically, a potential Website Team Member will need to show that they have an understanding of the structure of the website and how it fits into the larger ESLint project's objectives and strategy.
-* Website Team Members are expected to be respectful of every community member and to work collaboratively in the spirit of inclusion.
-* Have submitted a minimum of 10 website-related pull requests. What's a website-related pull request? One that is made to the `eslint.org` repository or the `docs` directory in the `eslint` repository and requires little effort to accept because it's well documented and tested.
+- One must have shown a willingness and ability to participate in the maintenance of [eslint.org](https://eslint.org/) as a team player. Typically, a potential Website Team Member will need to show that they have an understanding of the structure of the website and how it fits into the larger ESLint project's objectives and strategy.
+- Website Team Members are expected to be respectful of every community member and to work collaboratively in the spirit of inclusion.
+- Have submitted a minimum of 10 website-related pull requests. What's a website-related pull request? One that is made to the `eslint.org` repository or the `docs` directory in the `eslint` repository and requires little effort to accept because it's well documented and tested.
New Website Team Members can be nominated by any existing Website Team Member or Committer. Once they have been nominated, there will be a vote by the TSC members.
@@ -60,25 +59,25 @@ Committers are community members who have shown that they are committed to the c
Committers:
-* Are expected to work at least one hour per week triaging issues and reviewing pull requests.
-* Are expected to work at least two hours total per week on ESLint.
-* May invoice for the hours they spend working on ESLint at a rate of $50 USD per hour.
-* Are expected to check in on the `#team` Discord channel once per week day (excluding holidays and other time off) for team updates.
-* Are expected to work on public branches of the source repository and submit pull requests from that branch to the master branch.
-* Are expected to delete their public branches when they are no longer necessary.
-* Are expected to provide feedback on issues in the "Feedback Needed" column of the [Triage Board](https://github.com/orgs/eslint/projects/3/views/1).
-* Are expected to work on at least one issue in the "Ready to Implement" column of the [Triage Board](https://github.com/orgs/eslint/projects/3/views/1) that they didn't create each month.
-* Must submit pull requests for all changes.
-* Have their work reviewed by TSC members before acceptance into the repository.
-* May label and close issues (see [Manage Issues](../maintain/manage-issues)).
-* May merge some pull requests (see [Review Pull Requests](../maintain/review-pull-requests)).
-* May take time off whenever they want, and are expected to post in the `#team` Discord channel when they will be away for more than a couple of days.
+- Are expected to work at least one hour per week triaging issues and reviewing pull requests.
+- Are expected to work at least two hours total per week on ESLint.
+- May invoice for the hours they spend working on ESLint at a rate of $50 USD per hour.
+- Are expected to check in on the `#team` Discord channel once per week day (excluding holidays and other time off) for team updates.
+- Are expected to work on public branches of the source repository and submit pull requests from that branch to the master branch.
+- Are expected to delete their public branches when they are no longer necessary.
+- Are expected to provide feedback on issues in the "Feedback Needed" column of the [Triage Board](https://github.com/orgs/eslint/projects/3/views/1).
+- Are expected to work on at least one issue in the "Ready to Implement" column of the [Triage Board](https://github.com/orgs/eslint/projects/3/views/1) that they didn't create each month.
+- Must submit pull requests for all changes.
+- Have their work reviewed by TSC members before acceptance into the repository.
+- May label and close issues (see [Manage Issues](../maintain/manage-issues)).
+- May merge some pull requests (see [Review Pull Requests](../maintain/review-pull-requests)).
+- May take time off whenever they want, and are expected to post in the `#team` Discord channel when they will be away for more than a couple of days.
To become a Committer:
-* One must have shown a willingness and ability to participate in the project as a team player. Typically, a potential Committer will need to show that they have an understanding of and alignment with the project, its objectives, and its strategy.
-* Committers are expected to be respectful of every community member and to work collaboratively in the spirit of inclusion.
-* Have submitted a minimum of 10 qualifying pull requests. What's a qualifying pull request? One that carries significant technical weight and requires little effort to accept because it's well documented and tested.
+- One must have shown a willingness and ability to participate in the project as a team player. Typically, a potential Committer will need to show that they have an understanding of and alignment with the project, its objectives, and its strategy.
+- Committers are expected to be respectful of every community member and to work collaboratively in the spirit of inclusion.
+- Have submitted a minimum of 10 qualifying pull requests. What's a qualifying pull request? One that carries significant technical weight and requires little effort to accept because it's well documented and tested.
New Committers can be nominated by any existing Committer. Once they have been nominated, there will be a vote by the TSC members.
@@ -92,16 +91,16 @@ Reviewers are community members who have contributed a significant amount of tim
Reviewers may perform all of the duties of Committers, and also:
-* May merge external pull requests for accepted issues upon reviewing and approving the changes.
-* May merge their own pull requests once they have collected the feedback they deem necessary. (No pull request should be merged without at least one Committer/Reviewer/TSC member comment stating they've looked at the code.)
-* May invoice for the hours they spend working on ESLint at a rate of $80 USD per hour.
+- May merge external pull requests for accepted issues upon reviewing and approving the changes.
+- May merge their own pull requests once they have collected the feedback they deem necessary. (No pull request should be merged without at least one Committer/Reviewer/TSC member comment stating they've looked at the code.)
+- May invoice for the hours they spend working on ESLint at a rate of $80 USD per hour.
To become a Reviewer:
-* Work in a helpful and collaborative way with the community.
-* Have given good feedback on others' submissions and displayed an overall understanding of the code quality standards for the project.
-* Commit to being a part of the community for the long-term.
-* Have submitted a minimum of 50 qualifying pull requests.
+- Work in a helpful and collaborative way with the community.
+- Have given good feedback on others' submissions and displayed an overall understanding of the code quality standards for the project.
+- Commit to being a part of the community for the long-term.
+- Have submitted a minimum of 50 qualifying pull requests.
A Committer is invited to become a Reviewer by existing Reviewers and TSC members. A nomination will result in discussion and then a decision by the TSC.
@@ -111,10 +110,10 @@ The ESLint project is jointly governed by a Technical Steering Committee (TSC) w
The TSC has final authority over this project including:
-* Technical direction
-* Project governance and process (including this policy)
-* Contribution policy
-* GitHub repository hosting
+- Technical direction
+- Project governance and process (including this policy)
+- Contribution policy
+- GitHub repository hosting
TSC seats are not time-limited. The size of the TSC can not be larger than five members. This size ensures adequate coverage of important areas of expertise balanced with the ability to make decisions efficiently.
@@ -130,10 +129,10 @@ TSC members have additional responsibilities over and above those of a Reviewer.
TSC members may perform all of the duties of Reviewers, and also:
-* May release new versions of all ESLint projects.
-* May participate in TSC meetings.
-* May propose budget items.
-* May propose new ESLint projects.
+- May release new versions of all ESLint projects.
+- May participate in TSC meetings.
+- May propose budget items.
+- May propose new ESLint projects.
There is no specific set of requirements or qualifications for TSC members beyond those that are expected of Reviewers.
@@ -185,7 +184,7 @@ either a closing vote or a vote to table the issue to the next
meeting. The call for a vote must be approved by a majority of the TSC
or else the discussion will continue. Simple majority wins.
-----
+---
This work is a derivative of [YUI Contributor Model](https://github.com/yui/yui3/wiki/Contributor-Model) and the [Node.js Project Governance Model](https://github.com/nodejs/node/blob/master/GOVERNANCE.md).
diff --git a/docs/src/contribute/pull-requests.md b/docs/src/contribute/pull-requests.md
index 5962c483c1e8..169a2a299035 100644
--- a/docs/src/contribute/pull-requests.md
+++ b/docs/src/contribute/pull-requests.md
@@ -53,7 +53,7 @@ git add -A
git commit
```
-All ESLint projects follow [Conventional Commits](https://www.conventionalcommits.org/) for our commit messages. (Note: we donât support the optional scope in messages.) Here's an example commit message:
+All ESLint projects follow [Conventional Commits](https://www.conventionalcommits.org/) for our commit messages. (Note: we donât support the optional scope in messages.) Here's an example commit message:
```txt
tag: Short description of what you did
@@ -67,17 +67,17 @@ The first line of the commit message (the summary) must have a specific format.
The `tag` is one of the following:
-* `fix` - for a bug fix.
-* `feat` - either for a backwards-compatible enhancement or for a rule change that adds reported problems.
-* `fix!` - for a backwards-incompatible bug fix.
-* `feat!` - for a backwards-incompatible enhancement or feature.
-* `docs` - changes to documentation only.
-* `chore` - for changes that aren't user-facing.
-* `build` - changes to build process only.
-* `refactor` - a change that doesn't affect APIs or user experience.
-* `test` - just changes to test files.
-* `ci` - changes to our CI configuration files and scripts.
-* `perf` - a code change that improves performance.
+- `fix` - for a bug fix.
+- `feat` - either for a backwards-compatible enhancement or for a rule change that adds reported problems.
+- `fix!` - for a backwards-incompatible bug fix.
+- `feat!` - for a backwards-incompatible enhancement or feature.
+- `docs` - changes to documentation only.
+- `chore` - for changes that aren't user-facing.
+- `build` - changes to build process only.
+- `refactor` - a change that doesn't affect APIs or user experience.
+- `test` - just changes to test files.
+- `ci` - changes to our CI configuration files and scripts.
+- `perf` - a code change that improves performance.
Use the [labels of the issue you are working on](work-on-issue#issue-labels) to determine the best tag.
@@ -114,12 +114,12 @@ If there are any failing tests, update your code until all tests pass.
With your code ready to go, this is a good time to double-check your submission to make sure it follows our conventions. Here are the things to check:
-* The commit message is properly formatted.
-* The change introduces no functional regression. Be sure to run `npm test` to verify your changes before submitting a pull request.
-* Make separate pull requests for unrelated changes. Large pull requests with multiple unrelated changes may be closed without merging.
-* All changes must be accompanied by tests, even if the feature you're working on previously had no tests.
-* All user-facing changes must be accompanied by appropriate documentation.
-* Follow the [Code Conventions](./code-conventions).
+- The commit message is properly formatted.
+- The change introduces no functional regression. Be sure to run `npm test` to verify your changes before submitting a pull request.
+- Make separate pull requests for unrelated changes. Large pull requests with multiple unrelated changes may be closed without merging.
+- All changes must be accompanied by tests, even if the feature you're working on previously had no tests.
+- All user-facing changes must be accompanied by appropriate documentation.
+- Follow the [Code Conventions](./code-conventions).
### Step 6: Push your changes
diff --git a/docs/src/contribute/tests.md b/docs/src/contribute/tests.md
index 9ad25500d82b..1fca848bc29b 100644
--- a/docs/src/contribute/tests.md
+++ b/docs/src/contribute/tests.md
@@ -29,18 +29,18 @@ If you want to run just one or a subset of `RuleTester` test cases, add `only: t
```js
ruleTester.run("my-rule", myRule, {
- valid: [
- RuleTester.only("const valid = 42;"),
- // Other valid cases
- ],
- invalid: [
- {
- code: "const invalid = 42;",
- only: true,
- },
- // Other invalid cases
- ]
-})
+ valid: [
+ RuleTester.only("const valid = 42;"),
+ // Other valid cases
+ ],
+ invalid: [
+ {
+ code: "const invalid = 42;",
+ only: true,
+ },
+ // Other invalid cases
+ ],
+});
```
Running individual tests is useful when you're working on a specific bug and iterating on the solution. You should be sure to run `npm test` before submitting a pull request. `npm test` uses Mocha's `--forbid-only` option to prevent `only` tests from passing full test runs.
diff --git a/docs/src/contribute/work-on-issue.md b/docs/src/contribute/work-on-issue.md
index d258aa4eb156..dd579f1764b0 100644
--- a/docs/src/contribute/work-on-issue.md
+++ b/docs/src/contribute/work-on-issue.md
@@ -29,15 +29,15 @@ We use labels to indicate the status of issues. The most complete documentation
If you're going to work on an issue, please add a comment to that issue saying so and indicating when you think you will complete it. It will help us to avoid duplication of effort. Some examples of good comments are:
-* "I'll take a look at this over the weekend."
-* "I'm going to do this, give me two weeks."
-* "Working on this" (as in, I'm working on it right now)
+- "I'll take a look at this over the weekend."
+- "I'm going to do this, give me two weeks."
+- "Working on this" (as in, I'm working on it right now)
If an issue has already been claimed by someone, please be respectful of that person's desire to complete the work and don't work on it unless you verify that they are no longer interested.
If you find you can't finish the work, then simply add a comment letting people know, for example:
-* "Sorry, it looks like I don't have time to do this."
-* "I thought I knew enough to fix this, but it turns out I don't."
+- "Sorry, it looks like I don't have time to do this."
+- "I thought I knew enough to fix this, but it turns out I don't."
No one will blame you for backing out of an issue if you are unable to complete it. We just want to keep the process moving along as efficiently as possible.
diff --git a/docs/src/extend/code-path-analysis.md b/docs/src/extend/code-path-analysis.md
index 1ce5ea3c0a91..fc08ea382d7f 100644
--- a/docs/src/extend/code-path-analysis.md
+++ b/docs/src/extend/code-path-analysis.md
@@ -1,6 +1,5 @@
---
title: Code Path Analysis Details
-
---
ESLint's rules can use code paths.
@@ -9,7 +8,7 @@ It forks/joins at such as `if` statements.
```js
if (a && b) {
- foo();
+ foo();
}
bar();
```
@@ -35,14 +34,14 @@ This has references of both the initial segment and the final segments of a code
`CodePath` has the following properties:
-* `id` (`string`) - A unique string. Respective rules can use `id` to save additional information for each code path.
-* `origin` (`string`) - The reason that the code path was started. May be `"program"`, `"function"`, `"class-field-initializer"`, or `"class-static-block"`.
-* `initialSegment` (`CodePathSegment`) - The initial segment of this code path.
-* `finalSegments` (`CodePathSegment[]`) - The final segments which includes both returned and thrown.
-* `returnedSegments` (`CodePathSegment[]`) - The final segments which includes only returned.
-* `thrownSegments` (`CodePathSegment[]`) - The final segments which includes only thrown.
-* `upper` (`CodePath|null`) - The code path of the upper function/global scope.
-* `childCodePaths` (`CodePath[]`) - Code paths of functions this code path contains.
+- `id` (`string`) - A unique string. Respective rules can use `id` to save additional information for each code path.
+- `origin` (`string`) - The reason that the code path was started. May be `"program"`, `"function"`, `"class-field-initializer"`, or `"class-static-block"`.
+- `initialSegment` (`CodePathSegment`) - The initial segment of this code path.
+- `finalSegments` (`CodePathSegment[]`) - The final segments which includes both returned and thrown.
+- `returnedSegments` (`CodePathSegment[]`) - The final segments which includes only returned.
+- `thrownSegments` (`CodePathSegment[]`) - The final segments which includes only thrown.
+- `upper` (`CodePath|null`) - The code path of the upper function/global scope.
+- `childCodePaths` (`CodePath[]`) - Code paths of functions this code path contains.
### `CodePathSegment`
@@ -52,10 +51,10 @@ Difference from doubly linked list is what there are forking and merging (the ne
`CodePathSegment` has the following properties:
-* `id` (`string`) - A unique string. Respective rules can use `id` to save additional information for each segment.
-* `nextSegments` (`CodePathSegment[]`) - The next segments. If forking, there are two or more. If final, there is nothing.
-* `prevSegments` (`CodePathSegment[]`) - The previous segments. If merging, there are two or more. If initial, there is nothing.
-* `reachable` (`boolean`) - A flag which shows whether or not it's reachable. This becomes `false` when preceded by `return`, `throw`, `break`, or `continue`.
+- `id` (`string`) - A unique string. Respective rules can use `id` to save additional information for each segment.
+- `nextSegments` (`CodePathSegment[]`) - The next segments. If forking, there are two or more. If final, there is nothing.
+- `prevSegments` (`CodePathSegment[]`) - The previous segments. If merging, there are two or more. If initial, there is nothing.
+- `reachable` (`boolean`) - A flag which shows whether or not it's reachable. This becomes `false` when preceded by `return`, `throw`, `break`, or `continue`.
## Events
@@ -63,106 +62,104 @@ There are seven events related to code paths, and you can define event handlers
```js
module.exports = {
- meta: {
- // ...
- },
- create(context) {
-
- return {
- /**
- * This is called at the start of analyzing a code path.
- * In this time, the code path object has only the initial segment.
- *
- * @param {CodePath} codePath - The new code path.
- * @param {ASTNode} node - The current node.
- * @returns {void}
- */
- onCodePathStart(codePath, node) {
- // do something with codePath
- },
-
- /**
- * This is called at the end of analyzing a code path.
- * In this time, the code path object is complete.
- *
- * @param {CodePath} codePath - The completed code path.
- * @param {ASTNode} node - The current node.
- * @returns {void}
- */
- onCodePathEnd(codePath, node) {
- // do something with codePath
- },
-
- /**
- * This is called when a reachable code path segment was created.
- * It meant the code path is forked or merged.
- * In this time, the segment has the previous segments and has been
- * judged reachable or not.
- *
- * @param {CodePathSegment} segment - The new code path segment.
- * @param {ASTNode} node - The current node.
- * @returns {void}
- */
- onCodePathSegmentStart(segment, node) {
- // do something with segment
- },
-
- /**
- * This is called when a reachable code path segment was left.
- * In this time, the segment does not have the next segments yet.
- *
- * @param {CodePathSegment} segment - The left code path segment.
- * @param {ASTNode} node - The current node.
- * @returns {void}
- */
- onCodePathSegmentEnd(segment, node) {
- // do something with segment
- },
-
- /**
- * This is called when an unreachable code path segment was created.
- * It meant the code path is forked or merged.
- * In this time, the segment has the previous segments and has been
- * judged reachable or not.
- *
- * @param {CodePathSegment} segment - The new code path segment.
- * @param {ASTNode} node - The current node.
- * @returns {void}
- */
- onUnreachableCodePathSegmentStart(segment, node) {
- // do something with segment
- },
-
- /**
- * This is called when an unreachable code path segment was left.
- * In this time, the segment does not have the next segments yet.
- *
- * @param {CodePathSegment} segment - The left code path segment.
- * @param {ASTNode} node - The current node.
- * @returns {void}
- */
- onUnreachableCodePathSegmentEnd(segment, node) {
- // do something with segment
- },
-
- /**
- * This is called when a code path segment was looped.
- * Usually segments have each previous segments when created,
- * but when looped, a segment is added as a new previous segment into a
- * existing segment.
- *
- * @param {CodePathSegment} fromSegment - A code path segment of source.
- * @param {CodePathSegment} toSegment - A code path segment of destination.
- * @param {ASTNode} node - The current node.
- * @returns {void}
- */
- onCodePathSegmentLoop(fromSegment, toSegment, node) {
- // do something with segment
- }
- };
-
- }
-}
+ meta: {
+ // ...
+ },
+ create(context) {
+ return {
+ /**
+ * This is called at the start of analyzing a code path.
+ * In this time, the code path object has only the initial segment.
+ *
+ * @param {CodePath} codePath - The new code path.
+ * @param {ASTNode} node - The current node.
+ * @returns {void}
+ */
+ onCodePathStart(codePath, node) {
+ // do something with codePath
+ },
+
+ /**
+ * This is called at the end of analyzing a code path.
+ * In this time, the code path object is complete.
+ *
+ * @param {CodePath} codePath - The completed code path.
+ * @param {ASTNode} node - The current node.
+ * @returns {void}
+ */
+ onCodePathEnd(codePath, node) {
+ // do something with codePath
+ },
+
+ /**
+ * This is called when a reachable code path segment was created.
+ * It meant the code path is forked or merged.
+ * In this time, the segment has the previous segments and has been
+ * judged reachable or not.
+ *
+ * @param {CodePathSegment} segment - The new code path segment.
+ * @param {ASTNode} node - The current node.
+ * @returns {void}
+ */
+ onCodePathSegmentStart(segment, node) {
+ // do something with segment
+ },
+
+ /**
+ * This is called when a reachable code path segment was left.
+ * In this time, the segment does not have the next segments yet.
+ *
+ * @param {CodePathSegment} segment - The left code path segment.
+ * @param {ASTNode} node - The current node.
+ * @returns {void}
+ */
+ onCodePathSegmentEnd(segment, node) {
+ // do something with segment
+ },
+
+ /**
+ * This is called when an unreachable code path segment was created.
+ * It meant the code path is forked or merged.
+ * In this time, the segment has the previous segments and has been
+ * judged reachable or not.
+ *
+ * @param {CodePathSegment} segment - The new code path segment.
+ * @param {ASTNode} node - The current node.
+ * @returns {void}
+ */
+ onUnreachableCodePathSegmentStart(segment, node) {
+ // do something with segment
+ },
+
+ /**
+ * This is called when an unreachable code path segment was left.
+ * In this time, the segment does not have the next segments yet.
+ *
+ * @param {CodePathSegment} segment - The left code path segment.
+ * @param {ASTNode} node - The current node.
+ * @returns {void}
+ */
+ onUnreachableCodePathSegmentEnd(segment, node) {
+ // do something with segment
+ },
+
+ /**
+ * This is called when a code path segment was looped.
+ * Usually segments have each previous segments when created,
+ * but when looped, a segment is added as a new previous segment into a
+ * existing segment.
+ *
+ * @param {CodePathSegment} fromSegment - A code path segment of source.
+ * @param {CodePathSegment} toSegment - A code path segment of destination.
+ * @param {ASTNode} node - The current node.
+ * @returns {void}
+ */
+ onCodePathSegmentLoop(fromSegment, toSegment, node) {
+ // do something with segment
+ },
+ };
+ },
+};
```
### About `onCodePathSegmentLoop`
@@ -174,7 +171,7 @@ For Example 1:
```js
while (a) {
- a = foo();
+ a = foo();
}
bar();
```
@@ -182,7 +179,7 @@ bar();
1. First, the analysis advances to the end of loop.
:::img-container
- 
+
:::
2. Second, it creates the looping path.
@@ -190,20 +187,20 @@ bar();
It fires `onCodePathSegmentLoop` instead.
:::img-container
- 
+
:::
3. Last, it advances to the end.
:::img-container
- 
+
:::
For example 2:
```js
for (let i = 0; i < 10; ++i) {
- foo(i);
+ foo(i);
}
bar();
```
@@ -213,7 +210,7 @@ bar();
The `update` segment is hovered at first.
:::img-container
- 
+
:::
2. Second, it advances to `ForStatement.body`.
@@ -221,7 +218,7 @@ bar();
It keeps the `update` segment hovering.
:::img-container
- 
+
:::
3. Third, it creates the looping path from `body` segment to `update` segment.
@@ -229,7 +226,7 @@ bar();
It fires `onCodePathSegmentLoop` instead.
:::img-container
- 
+
:::
4. Fourth, also it creates the looping path from `update` segment to `test` segment.
@@ -237,13 +234,13 @@ bar();
It fires `onCodePathSegmentLoop` instead.
:::img-container
- 
+
:::
5. Last, it advances to the end.
:::img-container
- 
+
:::
## Usage Examples
@@ -254,51 +251,48 @@ To track the current code path segment position, you can define a rule like this
```js
module.exports = {
- meta: {
- // ...
- },
- create(context) {
-
- // tracks the code path we are currently in
- let currentCodePath;
-
- // tracks the segments we've traversed in the current code path
- let currentSegments;
-
- // tracks all current segments for all open paths
- const allCurrentSegments = [];
-
- return {
-
- onCodePathStart(codePath) {
- currentCodePath = codePath;
- allCurrentSegments.push(currentSegments);
- currentSegments = new Set();
- },
-
- onCodePathEnd(codePath) {
- currentCodePath = codePath.upper;
- currentSegments = allCurrentSegments.pop();
- },
-
- onCodePathSegmentStart(segment) {
- currentSegments.add(segment);
- },
-
- onCodePathSegmentEnd(segment) {
- currentSegments.delete(segment);
- },
-
- onUnreachableCodePathSegmentStart(segment) {
- currentSegments.add(segment);
- },
-
- onUnreachableCodePathSegmentEnd(segment) {
- currentSegments.delete(segment);
- }
- };
-
- }
+ meta: {
+ // ...
+ },
+ create(context) {
+ // tracks the code path we are currently in
+ let currentCodePath;
+
+ // tracks the segments we've traversed in the current code path
+ let currentSegments;
+
+ // tracks all current segments for all open paths
+ const allCurrentSegments = [];
+
+ return {
+ onCodePathStart(codePath) {
+ currentCodePath = codePath;
+ allCurrentSegments.push(currentSegments);
+ currentSegments = new Set();
+ },
+
+ onCodePathEnd(codePath) {
+ currentCodePath = codePath.upper;
+ currentSegments = allCurrentSegments.pop();
+ },
+
+ onCodePathSegmentStart(segment) {
+ currentSegments.add(segment);
+ },
+
+ onCodePathSegmentEnd(segment) {
+ currentSegments.delete(segment);
+ },
+
+ onUnreachableCodePathSegmentStart(segment) {
+ currentSegments.add(segment);
+ },
+
+ onUnreachableCodePathSegmentEnd(segment) {
+ currentSegments.delete(segment);
+ },
+ };
+ },
};
```
@@ -312,70 +306,65 @@ To find an unreachable node, track the current segment position and then use a n
```js
function areAnySegmentsReachable(segments) {
- for (const segment of segments) {
- if (segment.reachable) {
- return true;
- }
- }
+ for (const segment of segments) {
+ if (segment.reachable) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
module.exports = {
- meta: {
- // ...
- },
- create(context) {
-
- // tracks the code path we are currently in
- let currentCodePath;
-
- // tracks the segments we've traversed in the current code path
- let currentSegments;
-
- // tracks all current segments for all open paths
- const allCurrentSegments = [];
-
- return {
-
- onCodePathStart(codePath) {
- currentCodePath = codePath;
- allCurrentSegments.push(currentSegments);
- currentSegments = new Set();
- },
-
- onCodePathEnd(codePath) {
- currentCodePath = codePath.upper;
- currentSegments = allCurrentSegments.pop();
- },
-
- onCodePathSegmentStart(segment) {
- currentSegments.add(segment);
- },
-
- onCodePathSegmentEnd(segment) {
- currentSegments.delete(segment);
- },
-
- onUnreachableCodePathSegmentStart(segment) {
- currentSegments.add(segment);
- },
-
- onUnreachableCodePathSegmentEnd(segment) {
- currentSegments.delete(segment);
- },
-
- ExpressionStatement(node) {
-
- // check all the code path segments that led to this node
- if (!areAnySegmentsReachable(currentSegments)) {
- context.report({ message: "Unreachable!", node });
- }
- }
-
- };
-
- }
+ meta: {
+ // ...
+ },
+ create(context) {
+ // tracks the code path we are currently in
+ let currentCodePath;
+
+ // tracks the segments we've traversed in the current code path
+ let currentSegments;
+
+ // tracks all current segments for all open paths
+ const allCurrentSegments = [];
+
+ return {
+ onCodePathStart(codePath) {
+ currentCodePath = codePath;
+ allCurrentSegments.push(currentSegments);
+ currentSegments = new Set();
+ },
+
+ onCodePathEnd(codePath) {
+ currentCodePath = codePath.upper;
+ currentSegments = allCurrentSegments.pop();
+ },
+
+ onCodePathSegmentStart(segment) {
+ currentSegments.add(segment);
+ },
+
+ onCodePathSegmentEnd(segment) {
+ currentSegments.delete(segment);
+ },
+
+ onUnreachableCodePathSegmentStart(segment) {
+ currentSegments.add(segment);
+ },
+
+ onUnreachableCodePathSegmentEnd(segment) {
+ currentSegments.delete(segment);
+ },
+
+ ExpressionStatement(node) {
+ // check all the code path segments that led to this node
+ if (!areAnySegmentsReachable(currentSegments)) {
+ context.report({ message: "Unreachable!", node });
+ }
+ },
+ };
+ },
};
```
@@ -393,114 +382,113 @@ Please use a map of information instead.
```js
function hasCb(node, context) {
- if (node.type.indexOf("Function") !== -1) {
- const sourceCode = context.sourceCode;
- return sourceCode.getDeclaredVariables(node).some(function(v) {
- return v.type === "Parameter" && v.name === "cb";
- });
- }
- return false;
+ if (node.type.indexOf("Function") !== -1) {
+ const sourceCode = context.sourceCode;
+ return sourceCode.getDeclaredVariables(node).some(function (v) {
+ return v.type === "Parameter" && v.name === "cb";
+ });
+ }
+ return false;
}
function isCbCalled(info) {
- return info.cbCalled;
+ return info.cbCalled;
}
module.exports = {
- meta: {
- // ...
- },
- create(context) {
-
- let funcInfo;
- const funcInfoStack = [];
- const segmentInfoMap = Object.create(null);
-
- return {
- // Checks `cb`.
- onCodePathStart(codePath, node) {
- funcInfoStack.push(funcInfo);
-
- funcInfo = {
- codePath: codePath,
- hasCb: hasCb(node, context),
- currentSegments: new Set()
- };
- },
-
- onCodePathEnd(codePath, node) {
- funcInfo = funcInfoStack.pop();
-
- // Checks `cb` was called in every paths.
- const cbCalled = codePath.finalSegments.every(function(segment) {
- const info = segmentInfoMap[segment.id];
- return info.cbCalled;
- });
-
- if (!cbCalled) {
- context.report({
- message: "`cb` should be called in every path.",
- node: node
- });
- }
- },
-
- // Manages state of code paths and tracks traversed segments
- onCodePathSegmentStart(segment) {
-
- funcInfo.currentSegments.add(segment);
-
- // Ignores if `cb` doesn't exist.
- if (!funcInfo.hasCb) {
- return;
- }
-
- // Initialize state of this path.
- const info = segmentInfoMap[segment.id] = {
- cbCalled: false
- };
-
- // If there are the previous paths, merges state.
- // Checks `cb` was called in every previous path.
- if (segment.prevSegments.length > 0) {
- info.cbCalled = segment.prevSegments.every(isCbCalled);
- }
- },
-
- // Tracks unreachable segment traversal
- onUnreachableCodePathSegmentStart(segment) {
- funcInfo.currentSegments.add(segment);
- },
-
- // Tracks reachable segment traversal
- onCodePathSegmentEnd(segment) {
- funcInfo.currentSegments.delete(segment);
- },
-
- // Tracks unreachable segment traversal
- onUnreachableCodePathSegmentEnd(segment) {
- funcInfo.currentSegments.delete(segment);
- },
-
- // Checks reachable or not.
- CallExpression(node) {
-
- // Ignores if `cb` doesn't exist.
- if (!funcInfo.hasCb) {
- return;
- }
-
- // Sets marks that `cb` was called.
- const callee = node.callee;
- if (callee.type === "Identifier" && callee.name === "cb") {
- funcInfo.currentSegments.forEach(segment => {
- const info = segmentInfoMap[segment.id];
- info.cbCalled = true;
- });
- }
- }
- };
- }
+ meta: {
+ // ...
+ },
+ create(context) {
+ let funcInfo;
+ const funcInfoStack = [];
+ const segmentInfoMap = Object.create(null);
+
+ return {
+ // Checks `cb`.
+ onCodePathStart(codePath, node) {
+ funcInfoStack.push(funcInfo);
+
+ funcInfo = {
+ codePath: codePath,
+ hasCb: hasCb(node, context),
+ currentSegments: new Set(),
+ };
+ },
+
+ onCodePathEnd(codePath, node) {
+ funcInfo = funcInfoStack.pop();
+
+ // Checks `cb` was called in every paths.
+ const cbCalled = codePath.finalSegments.every(
+ function (segment) {
+ const info = segmentInfoMap[segment.id];
+ return info.cbCalled;
+ },
+ );
+
+ if (!cbCalled) {
+ context.report({
+ message: "`cb` should be called in every path.",
+ node: node,
+ });
+ }
+ },
+
+ // Manages state of code paths and tracks traversed segments
+ onCodePathSegmentStart(segment) {
+ funcInfo.currentSegments.add(segment);
+
+ // Ignores if `cb` doesn't exist.
+ if (!funcInfo.hasCb) {
+ return;
+ }
+
+ // Initialize state of this path.
+ const info = (segmentInfoMap[segment.id] = {
+ cbCalled: false,
+ });
+
+ // If there are the previous paths, merges state.
+ // Checks `cb` was called in every previous path.
+ if (segment.prevSegments.length > 0) {
+ info.cbCalled = segment.prevSegments.every(isCbCalled);
+ }
+ },
+
+ // Tracks unreachable segment traversal
+ onUnreachableCodePathSegmentStart(segment) {
+ funcInfo.currentSegments.add(segment);
+ },
+
+ // Tracks reachable segment traversal
+ onCodePathSegmentEnd(segment) {
+ funcInfo.currentSegments.delete(segment);
+ },
+
+ // Tracks unreachable segment traversal
+ onUnreachableCodePathSegmentEnd(segment) {
+ funcInfo.currentSegments.delete(segment);
+ },
+
+ // Checks reachable or not.
+ CallExpression(node) {
+ // Ignores if `cb` doesn't exist.
+ if (!funcInfo.hasCb) {
+ return;
+ }
+
+ // Sets marks that `cb` was called.
+ const callee = node.callee;
+ if (callee.type === "Identifier" && callee.name === "cb") {
+ funcInfo.currentSegments.forEach(segment => {
+ const info = segmentInfoMap[segment.id];
+ info.cbCalled = true;
+ });
+ }
+ },
+ };
+ },
};
```
@@ -524,9 +512,9 @@ console.log("Hello world!");
```js
if (a) {
- foo();
+ foo();
} else {
- bar();
+ bar();
}
```
@@ -538,11 +526,11 @@ if (a) {
```js
if (a) {
- foo();
+ foo();
} else if (b) {
- bar();
+ bar();
} else if (c) {
- hoge();
+ hoge();
}
```
@@ -554,18 +542,18 @@ if (a) {
```js
switch (a) {
- case 0:
- foo();
- break;
-
- case 1:
- case 2:
- bar();
- // fallthrough
-
- case 3:
- hoge();
- break;
+ case 0:
+ foo();
+ break;
+
+ case 1:
+ case 2:
+ bar();
+ // fallthrough
+
+ case 3:
+ hoge();
+ break;
}
```
@@ -577,22 +565,22 @@ switch (a) {
```js
switch (a) {
- case 0:
- foo();
- break;
-
- case 1:
- case 2:
- bar();
- // fallthrough
-
- case 3:
- hoge();
- break;
-
- default:
- fuga();
- break;
+ case 0:
+ foo();
+ break;
+
+ case 1:
+ case 2:
+ bar();
+ // fallthrough
+
+ case 3:
+ hoge();
+ break;
+
+ default:
+ fuga();
+ break;
}
```
@@ -604,22 +592,22 @@ switch (a) {
```js
try {
- foo();
- if (a) {
- throw new Error();
- }
- bar();
+ foo();
+ if (a) {
+ throw new Error();
+ }
+ bar();
} catch (err) {
- hoge(err);
+ hoge(err);
}
last();
```
It creates the paths from `try` block to `catch` block at:
-* `throw` statements.
-* The first throwable node (e.g. a function call) in the `try` block.
-* The end of the `try` block.
+- `throw` statements.
+- The first throwable node (e.g. a function call) in the `try` block.
+- The end of the `try` block.
:::img-container

@@ -629,10 +617,10 @@ It creates the paths from `try` block to `catch` block at:
```js
try {
- foo();
- bar();
+ foo();
+ bar();
} finally {
- fuga();
+ fuga();
}
last();
```
@@ -649,12 +637,12 @@ One is the normal path, and another is the leaving path (`throw` or `return`).
```js
try {
- foo();
- bar();
+ foo();
+ bar();
} catch (err) {
- hoge(err);
+ hoge(err);
} finally {
- fuga();
+ fuga();
}
last();
```
@@ -667,11 +655,11 @@ last();
```js
while (a) {
- foo();
- if (b) {
- continue;
- }
- bar();
+ foo();
+ if (b) {
+ continue;
+ }
+ bar();
}
```
@@ -683,8 +671,8 @@ while (a) {
```js
do {
- foo();
- bar();
+ foo();
+ bar();
} while (a);
```
@@ -696,11 +684,11 @@ do {
```js
for (let i = 0; i < 10; ++i) {
- foo();
- if (b) {
- break;
- }
- bar();
+ foo();
+ if (b) {
+ break;
+ }
+ bar();
}
```
@@ -712,7 +700,7 @@ for (let i = 0; i < 10; ++i) {
```js
for (;;) {
- foo();
+ foo();
}
bar();
```
@@ -725,7 +713,7 @@ bar();
```js
for (let key in obj) {
- foo(key);
+ foo(key);
}
```
@@ -737,10 +725,10 @@ for (let key in obj) {
```js
function foo(a) {
- if (a) {
- return;
- }
- bar();
+ if (a) {
+ return;
+ }
+ bar();
}
foo(false);
@@ -748,14 +736,14 @@ foo(false);
It creates two code paths.
-* The global's
+- The global's
:::img-container
- 
+
:::
-* The function's
+- The function's
:::img-container
- 
+
:::
diff --git a/docs/src/extend/custom-formatters.md b/docs/src/extend/custom-formatters.md
index 827117ac4164..8acc68daa10c 100644
--- a/docs/src/extend/custom-formatters.md
+++ b/docs/src/extend/custom-formatters.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: extend eslint
title: Custom Formatters
order: 4
-
---
Custom formatters let you display linting results in a format that best fits your needs, whether that's in a specific file format, a certain display style, or a format optimized for a particular tool.
@@ -20,8 +19,8 @@ Each formatter is a function that receives a `results` object and a `context` as
```js
//my-awesome-formatter.js
-module.exports = function(results, context) {
- return JSON.stringify(results, null, 2);
+module.exports = function (results, context) {
+ return JSON.stringify(results, null, 2);
};
```
@@ -29,9 +28,9 @@ A formatter can also be an async function (from ESLint v8.4.0), the following sh
```js
//my-awesome-formatter.js
-module.exports = async function(results) {
- const formatted = await asyncTask();
- return formatted;
+module.exports = async function (results) {
+ const formatted = await asyncTask();
+ return formatted;
};
```
@@ -49,42 +48,41 @@ The `results` object passed into a formatter is an array of [`result`](#the-resu
```js
[
- {
- filePath: "/path/to/a/file.js",
- messages: [
- {
- ruleId: "curly",
- severity: 2,
- message: "Expected { after 'if' condition.",
- line: 2,
- column: 1,
- nodeType: "IfStatement"
- },
- {
- ruleId: "no-process-exit",
- severity: 2,
- message: "Don't use process.exit(); throw an error instead.",
- line: 3,
- column: 1,
- nodeType: "CallExpression"
- }
- ],
- errorCount: 2,
- warningCount: 0,
- fixableErrorCount: 0,
- fixableWarningCount: 0,
- source:
- "var err = doStuff();\nif (err) console.log('failed tests: ' + err);\nprocess.exit(1);\n"
- },
- {
- filePath: "/path/to/Gruntfile.js",
- messages: [],
- errorCount: 0,
- warningCount: 0,
- fixableErrorCount: 0,
- fixableWarningCount: 0
- }
-]
+ {
+ filePath: "/path/to/a/file.js",
+ messages: [
+ {
+ ruleId: "curly",
+ severity: 2,
+ message: "Expected { after 'if' condition.",
+ line: 2,
+ column: 1,
+ nodeType: "IfStatement",
+ },
+ {
+ ruleId: "no-process-exit",
+ severity: 2,
+ message: "Don't use process.exit(); throw an error instead.",
+ line: 3,
+ column: 1,
+ nodeType: "CallExpression",
+ },
+ ],
+ errorCount: 2,
+ warningCount: 0,
+ fixableErrorCount: 0,
+ fixableWarningCount: 0,
+ source: "var err = doStuff();\nif (err) console.log('failed tests: ' + err);\nprocess.exit(1);\n",
+ },
+ {
+ filePath: "/path/to/Gruntfile.js",
+ messages: [],
+ errorCount: 0,
+ warningCount: 0,
+ fixableErrorCount: 0,
+ fixableWarningCount: 0,
+ },
+];
```
#### The `result` Object
@@ -94,34 +92,34 @@ 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`](#the-message-object) 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.
-* **stats**: The optional [`stats`](./stats#-stats-type) object that only exists when the `stats` option is used.
-* **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`](#the-message-object) 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.
+- **stats**: The optional [`stats`](./stats#-stats-type) object that only exists when the `stats` option is used.
+- **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. If the error or warning was not produced by a rule (for example, if it's a parsing error), this is `null`.
-* **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**: (**Deprecated:** This property will be removed in a future version of ESLint.) the type of the node in the [AST](https://github.com/estree/estree/blob/master/es5.md#node-objects) or `null` if the issue isn't related to a particular AST node.
+- **ruleId**: the ID of the rule that produced the error or warning. If the error or warning was not produced by a rule (for example, if it's a parsing error), this is `null`.
+- **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**: (**Deprecated:** This property will be removed in a future version of ESLint.) the type of the node in the [AST](https://github.com/estree/estree/blob/master/es5.md#node-objects) or `null` if the issue isn't related to a particular AST node.
### The `context` Argument
The formatter function receives a `context` object as its second argument. The object has the following properties:
-* `cwd`: The current working directory. This value comes from the `cwd` constructor option of the [ESLint](../integrate/nodejs-api#-new-eslintoptions) class.
-* `maxWarningsExceeded` (optional): If `--max-warnings` was set and the number of warnings exceeded the limit, this property's value is an object containing two properties:
- * `maxWarnings`: the value of the `--max-warnings` option
- * `foundWarnings`: the number of lint warnings
-* `rulesMeta`: The `meta` property values of rules. See the [Custom Rules](custom-rules) page for more information about rules.
+- `cwd`: The current working directory. This value comes from the `cwd` constructor option of the [ESLint](../integrate/nodejs-api#-new-eslintoptions) class.
+- `maxWarningsExceeded` (optional): If `--max-warnings` was set and the number of warnings exceeded the limit, this property's value is an object containing two properties:
+ - `maxWarnings`: the value of the `--max-warnings` option
+ - `foundWarnings`: the number of lint warnings
+- `rulesMeta`: The `meta` property values of rules. See the [Custom Rules](custom-rules) page for more information about rules.
For example, here's what the object would look like if the rule `no-extra-semi` had been run:
@@ -163,61 +161,61 @@ Custom formatters have access to environment variables and so can change their b
Here's an example that uses a `FORMATTER_SKIP_WARNINGS` environment variable to determine whether to show warnings in the results:
```js
-module.exports = function(results) {
- var skipWarnings = process.env.FORMATTER_SKIP_WARNINGS === "true";
-
- var results = results || [];
- var summary = results.reduce(
- function(seq, current) {
- current.messages.forEach(function(msg) {
- var logMessage = {
- filePath: current.filePath,
- ruleId: msg.ruleId,
- message: msg.message,
- line: msg.line,
- column: msg.column
- };
-
- if (msg.severity === 1) {
- logMessage.type = "warning";
- seq.warnings.push(logMessage);
- }
- if (msg.severity === 2) {
- logMessage.type = "error";
- seq.errors.push(logMessage);
- }
- });
- return seq;
- },
- {
- errors: [],
- warnings: []
- }
- );
-
- if (summary.errors.length > 0 || summary.warnings.length > 0) {
- var warnings = !skipWarnings ? summary.warnings : []; // skip the warnings in that case
-
- var lines = summary.errors
- .concat(warnings)
- .map(function(msg) {
- return (
- "\n" +
- msg.type +
- " " +
- msg.ruleId +
- "\n " +
- msg.filePath +
- ":" +
- msg.line +
- ":" +
- msg.column
- );
- })
- .join("\n");
-
- return lines + "\n";
- }
+module.exports = function (results) {
+ var skipWarnings = process.env.FORMATTER_SKIP_WARNINGS === "true";
+
+ var results = results || [];
+ var summary = results.reduce(
+ function (seq, current) {
+ current.messages.forEach(function (msg) {
+ var logMessage = {
+ filePath: current.filePath,
+ ruleId: msg.ruleId,
+ message: msg.message,
+ line: msg.line,
+ column: msg.column,
+ };
+
+ if (msg.severity === 1) {
+ logMessage.type = "warning";
+ seq.warnings.push(logMessage);
+ }
+ if (msg.severity === 2) {
+ logMessage.type = "error";
+ seq.errors.push(logMessage);
+ }
+ });
+ return seq;
+ },
+ {
+ errors: [],
+ warnings: [],
+ },
+ );
+
+ if (summary.errors.length > 0 || summary.warnings.length > 0) {
+ var warnings = !skipWarnings ? summary.warnings : []; // skip the warnings in that case
+
+ var lines = summary.errors
+ .concat(warnings)
+ .map(function (msg) {
+ return (
+ "\n" +
+ msg.type +
+ " " +
+ msg.ruleId +
+ "\n " +
+ msg.filePath +
+ ":" +
+ msg.line +
+ ":" +
+ msg.column
+ );
+ })
+ .join("\n");
+
+ return lines + "\n";
+ }
};
```
@@ -267,11 +265,11 @@ Because ESLint knows to look for packages beginning with `eslint-formatter-` whe
Tips for the `package.json` of a custom formatter:
-* The [`main`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#main) entry point must be the JavaScript file implementing your custom formatter.
-* Add these [`keywords`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#keywords) to help users find your formatter:
- * `"eslint"`
- * `"eslint-formatter"`
- * `"eslintformatter"`
+- The [`main`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#main) entry point must be the JavaScript file implementing your custom formatter.
+- Add these [`keywords`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#keywords) to help users find your formatter:
+ - `"eslint"`
+ - `"eslint-formatter"`
+ - `"eslintformatter"`
See all [custom formatters on npm](https://www.npmjs.com/search?q=eslint-formatter).
@@ -282,28 +280,28 @@ See all [custom formatters on npm](https://www.npmjs.com/search?q=eslint-formatt
A formatter that only reports on the total count of errors and warnings will look like this:
```javascript
-module.exports = function(results, context) {
- // accumulate the errors and warnings
- var summary = results.reduce(
- function(seq, current) {
- seq.errors += current.errorCount;
- seq.warnings += current.warningCount;
- return seq;
- },
- { errors: 0, warnings: 0 }
- );
-
- if (summary.errors > 0 || summary.warnings > 0) {
- return (
- "Errors: " +
- summary.errors +
- ", Warnings: " +
- summary.warnings +
- "\n"
- );
- }
-
- return "";
+module.exports = function (results, context) {
+ // accumulate the errors and warnings
+ var summary = results.reduce(
+ function (seq, current) {
+ seq.errors += current.errorCount;
+ seq.warnings += current.warningCount;
+ return seq;
+ },
+ { errors: 0, warnings: 0 },
+ );
+
+ if (summary.errors > 0 || summary.warnings > 0) {
+ return (
+ "Errors: " +
+ summary.errors +
+ ", Warnings: " +
+ summary.warnings +
+ "\n"
+ );
+ }
+
+ return "";
};
```
@@ -324,59 +322,60 @@ Errors: 2, Warnings: 4
A more complex report could look like this:
```javascript
-module.exports = function(results, context) {
- var results = results || [];
-
- var summary = results.reduce(
- function(seq, current) {
- current.messages.forEach(function(msg) {
- var logMessage = {
- filePath: current.filePath,
- ruleId: msg.ruleId,
- ruleUrl: context.rulesMeta[msg.ruleId].docs.url,
- message: msg.message,
- line: msg.line,
- column: msg.column
- };
-
- if (msg.severity === 1) {
- logMessage.type = "warning";
- seq.warnings.push(logMessage);
- }
- if (msg.severity === 2) {
- logMessage.type = "error";
- seq.errors.push(logMessage);
- }
- });
- return seq;
- },
- {
- errors: [],
- warnings: []
- }
- );
-
- if (summary.errors.length > 0 || summary.warnings.length > 0) {
- var lines = summary.errors
- .concat(summary.warnings)
- .map(function(msg) {
- return (
- "\n" +
- msg.type +
- " " +
- msg.ruleId + (msg.ruleUrl ? " (" + msg.ruleUrl + ")" : "") +
- "\n " +
- msg.filePath +
- ":" +
- msg.line +
- ":" +
- msg.column
- );
- })
- .join("\n");
-
- return lines + "\n";
- }
+module.exports = function (results, context) {
+ var results = results || [];
+
+ var summary = results.reduce(
+ function (seq, current) {
+ current.messages.forEach(function (msg) {
+ var logMessage = {
+ filePath: current.filePath,
+ ruleId: msg.ruleId,
+ ruleUrl: context.rulesMeta[msg.ruleId].docs.url,
+ message: msg.message,
+ line: msg.line,
+ column: msg.column,
+ };
+
+ if (msg.severity === 1) {
+ logMessage.type = "warning";
+ seq.warnings.push(logMessage);
+ }
+ if (msg.severity === 2) {
+ logMessage.type = "error";
+ seq.errors.push(logMessage);
+ }
+ });
+ return seq;
+ },
+ {
+ errors: [],
+ warnings: [],
+ },
+ );
+
+ if (summary.errors.length > 0 || summary.warnings.length > 0) {
+ var lines = summary.errors
+ .concat(summary.warnings)
+ .map(function (msg) {
+ return (
+ "\n" +
+ msg.type +
+ " " +
+ msg.ruleId +
+ (msg.ruleUrl ? " (" + msg.ruleUrl + ")" : "") +
+ "\n " +
+ msg.filePath +
+ ":" +
+ msg.line +
+ ":" +
+ msg.column
+ );
+ })
+ .join("\n");
+
+ return lines + "\n";
+ }
};
```
diff --git a/docs/src/extend/custom-parsers.md b/docs/src/extend/custom-parsers.md
index fda2fa4276d5..9a2134b3c61e 100644
--- a/docs/src/extend/custom-parsers.md
+++ b/docs/src/extend/custom-parsers.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: extend eslint
title: Custom Parsers
order: 5
-
---
{%- from 'components/npm_tabs.macro.html' import npm_tabs with context %}
@@ -27,12 +26,12 @@ const espree = require("espree");
// Logs the duration it takes to parse each file.
function parse(code, options) {
- const label = `Parsing file "${options.filePath}"`;
- console.time(label);
- const ast = espree.parse(code, options);
- console.timeEnd(label);
- return ast; // Only the AST is returned.
-};
+ const label = `Parsing file "${options.filePath}"`;
+ console.time(label);
+ const ast = espree.parse(code, options);
+ console.timeEnd(label);
+ return ast; // Only the AST is returned.
+}
module.exports = { parse };
```
@@ -45,12 +44,12 @@ The `parse` method should simply return the [AST](#ast-specification) object.
The `parseForESLint` method should return an object that contains the required property `ast` and optional properties `services`, `scopeManager`, and `visitorKeys`.
-* `ast` should contain the [AST](#ast-specification) object.
-* `services` can contain any parser-dependent services (such as type checkers for nodes). The value of the `services` property is available to rules as `context.sourceCode.parserServices`. Default is an empty object.
-* `scopeManager` can be a [ScopeManager](./scope-manager-interface) object. Custom parsers can use customized scope analysis for experimental/enhancement syntaxes. The default is the `ScopeManager` object which is created by [eslint-scope](https://github.com/eslint/js/tree/main/packages/eslint-scope).
- * Support for `scopeManager` was added in ESLint v4.14.0. ESLint versions that support `scopeManager` will provide an `eslintScopeManager: true` property in `parserOptions`, which can be used for feature detection.
-* `visitorKeys` can be an object to customize AST traversal. The keys of the object are the type of AST nodes. Each value is an array of the property names which should be traversed. The default is [KEYS of `eslint-visitor-keys`](https://github.com/eslint/js/tree/main/packages/eslint-visitor-keys#evkkeys).
- * Support for `visitorKeys` was added in ESLint v4.14.0. ESLint versions that support `visitorKeys` will provide an `eslintVisitorKeys: true` property in `parserOptions`, which can be used for feature detection.
+- `ast` should contain the [AST](#ast-specification) object.
+- `services` can contain any parser-dependent services (such as type checkers for nodes). The value of the `services` property is available to rules as `context.sourceCode.parserServices`. Default is an empty object.
+- `scopeManager` can be a [ScopeManager](./scope-manager-interface) object. Custom parsers can use customized scope analysis for experimental/enhancement syntaxes. The default is the `ScopeManager` object which is created by [eslint-scope](https://github.com/eslint/js/tree/main/packages/eslint-scope).
+ - Support for `scopeManager` was added in ESLint v4.14.0. ESLint versions that support `scopeManager` will provide an `eslintScopeManager: true` property in `parserOptions`, which can be used for feature detection.
+- `visitorKeys` can be an object to customize AST traversal. The keys of the object are the type of AST nodes. Each value is an array of the property names which should be traversed. The default is [KEYS of `eslint-visitor-keys`](https://github.com/eslint/js/tree/main/packages/eslint-visitor-keys#evkkeys).
+ - Support for `visitorKeys` was added in ESLint v4.14.0. ESLint versions that support `visitorKeys` will provide an `eslintVisitorKeys: true` property in `parserOptions`, which can be used for feature detection.
### Meta Data in Custom Parsers
@@ -59,10 +58,10 @@ For easier debugging and more effective caching of custom parsers, it's recommen
```js
// preferred location of name and version
module.exports = {
- meta: {
- name: "eslint-parser-custom",
- version: "1.2.3"
- }
+ meta: {
+ name: "eslint-parser-custom",
+ version: "1.2.3",
+ },
};
```
@@ -76,8 +75,8 @@ The AST that custom parsers should create is based on [ESTree](https://github.co
All nodes must have `range` property.
-* `range` (`number[]`) is an array of two numbers. Both numbers are a 0-based index which is the position in the array of source code characters. The first is the start position of the node, the second is the end position of the node. `code.slice(node.range[0], node.range[1])` must be the text of the node. This range does not include spaces/parentheses which are around the node.
-* `loc` (`SourceLocation`) must not be `null`. [The `loc` property is defined as nullable by ESTree](https://github.com/estree/estree/blob/25834f7247d44d3156030f8e8a2d07644d771fdb/es5.md#node-objects), but ESLint requires this property. The `SourceLocation#source` property can be `undefined`. ESLint does not use the `SourceLocation#source` property.
+- `range` (`number[]`) is an array of two numbers. Both numbers are a 0-based index which is the position in the array of source code characters. The first is the start position of the node, the second is the end position of the node. `code.slice(node.range[0], node.range[1])` must be the text of the node. This range does not include spaces/parentheses which are around the node.
+- `loc` (`SourceLocation`) must not be `null`. [The `loc` property is defined as nullable by ESTree](https://github.com/estree/estree/blob/25834f7247d44d3156030f8e8a2d07644d771fdb/es5.md#node-objects), but ESLint requires this property. The `SourceLocation#source` property can be `undefined`. ESLint does not use the `SourceLocation#source` property.
The `parent` property of all nodes must be rewritable. Before any rules have access to the AST, ESLint sets each node's `parent` property to its parent node while traversing.
@@ -87,16 +86,16 @@ The `Program` node must have `tokens` and `comments` properties. Both properties
```ts
interface Token {
- type: string;
- loc: SourceLocation;
- // See the "All Nodes" section for details of the `range` property.
- range: [number, number];
- value: string;
+ type: string;
+ loc: SourceLocation;
+ // See the "All Nodes" section for details of the `range` property.
+ range: [number, number];
+ value: string;
}
```
-* `tokens` (`Token[]`) is the array of tokens which affect the behavior of programs. Arbitrary spaces can exist between tokens, so rules check the `Token#range` to detect spaces between tokens. This must be sorted by `Token#range[0]`.
-* `comments` (`Token[]`) is the array of comment tokens. This must be sorted by `Token#range[0]`.
+- `tokens` (`Token[]`) is the array of tokens which affect the behavior of programs. Arbitrary spaces can exist between tokens, so rules check the `Token#range` to detect spaces between tokens. This must be sorted by `Token#range[0]`.
+- `comments` (`Token[]`) is the array of comment tokens. This must be sorted by `Token#range[0]`.
The range indexes of all tokens and comments must not overlap with the range of other tokens and comments.
@@ -104,7 +103,7 @@ The range indexes of all tokens and comments must not overlap with the range of
The `Literal` node must have `raw` property.
-* `raw` (`string`) is the source code of this literal. This is the same as `code.slice(node.range[0], node.range[1])`.
+- `raw` (`string`) is the source code of this literal. This is the same as `code.slice(node.range[0], node.range[1])`.
## Packaging a Custom Parser
@@ -132,12 +131,14 @@ Then add the custom parser to your ESLint configuration file with the `languageO
const myparser = require("eslint-parser-myparser");
-module.exports = [{
- languageOptions: {
- parser: myparser
- },
- // ... rest of configuration
-}];
+module.exports = [
+ {
+ languageOptions: {
+ parser: myparser,
+ },
+ // ... rest of configuration
+ },
+];
```
When using legacy configuration, specify the `parser` property as a string:
@@ -146,8 +147,8 @@ When using legacy configuration, specify the `parser` property as a string:
// .eslintrc.js
module.exports = {
- parser: "eslint-parser-myparser",
- // ... rest of configuration
+ parser: "eslint-parser-myparser",
+ // ... rest of configuration
};
```
@@ -163,17 +164,17 @@ A simple custom parser that provides a `context.sourceCode.parserServices.foo()`
// awesome-custom-parser.js
var espree = require("espree");
function parseForESLint(code, options) {
- return {
- ast: espree.parse(code, options),
- services: {
- foo: function() {
- console.log("foo");
- }
- },
- scopeManager: null,
- visitorKeys: null
- };
-};
+ return {
+ ast: espree.parse(code, options),
+ services: {
+ foo: function () {
+ console.log("foo");
+ },
+ },
+ scopeManager: null,
+ visitorKeys: null,
+ };
+}
module.exports = { parseForESLint };
```
@@ -182,11 +183,13 @@ Include the custom parser in an ESLint configuration file:
```js
// eslint.config.js
-module.exports = [{
- languageOptions: {
- parser: require("./path/to/awesome-custom-parser")
- }
-}];
+module.exports = [
+ {
+ languageOptions: {
+ parser: require("./path/to/awesome-custom-parser"),
+ },
+ },
+];
```
Or if using legacy configuration:
diff --git a/docs/src/extend/custom-processors-deprecated.md b/docs/src/extend/custom-processors-deprecated.md
index 572e30e9f0ed..1de004e55bd8 100644
--- a/docs/src/extend/custom-processors-deprecated.md
+++ b/docs/src/extend/custom-processors-deprecated.md
@@ -14,36 +14,37 @@ In order to create a custom processor, the object exported from your module has
```js
module.exports = {
- processors: {
- "processor-name": {
- meta: {
- name: "eslint-processor-name",
- version: "1.2.3"
- },
- // takes text of the file and filename
- preprocess: function(text, filename) {
- // here, you can strip out any non-JS content
- // and split into multiple strings to lint
-
- return [ // return an array of code blocks to lint
- { text: code1, filename: "0.js" },
- { text: code2, filename: "1.js" },
- ];
- },
-
- // takes a Message[][] and filename
- postprocess: function(messages, filename) {
- // `messages` argument contains two-dimensional array of Message objects
- // where each top-level array item contains array of lint messages related
- // to the text that was returned in array from preprocess() method
-
- // you need to return a one-dimensional array of the messages you want to keep
- return [].concat(...messages);
- },
-
- supportsAutofix: true // (optional, defaults to false)
- }
- }
+ processors: {
+ "processor-name": {
+ meta: {
+ name: "eslint-processor-name",
+ version: "1.2.3",
+ },
+ // takes text of the file and filename
+ preprocess: function (text, filename) {
+ // here, you can strip out any non-JS content
+ // and split into multiple strings to lint
+
+ return [
+ // return an array of code blocks to lint
+ { text: code1, filename: "0.js" },
+ { text: code2, filename: "1.js" },
+ ];
+ },
+
+ // takes a Message[][] and filename
+ postprocess: function (messages, filename) {
+ // `messages` argument contains two-dimensional array of Message objects
+ // where each top-level array item contains array of lint messages related
+ // to the text that was returned in array from preprocess() method
+
+ // you need to return a one-dimensional array of the messages you want to keep
+ return [].concat(...messages);
+ },
+
+ supportsAutofix: true, // (optional, defaults to false)
+ },
+ },
};
```
@@ -59,49 +60,47 @@ Reported problems have the following location information in each lint message:
```typescript
type LintMessage = {
+ /// The 1-based line number where the message occurs.
+ line?: number;
- /// The 1-based line number where the message occurs.
- line?: number;
-
- /// The 1-based column number where the message occurs.
- column?: number;
+ /// The 1-based column number where the message occurs.
+ column?: number;
- /// The 1-based line number of the end location.
- endLine?: number;
+ /// The 1-based line number of the end location.
+ endLine?: number;
- /// The 1-based column number of the end location.
- endColumn?: number;
+ /// The 1-based column number of the end location.
+ endColumn?: number;
- /// If `true`, this is a fatal error.
- fatal?: boolean;
+ /// If `true`, this is a fatal error.
+ fatal?: boolean;
- /// Information for an autofix.
- fix: Fix;
+ /// Information for an autofix.
+ fix: Fix;
- /// The error message.
- message: string;
+ /// The error message.
+ message: string;
- /// The ID of the rule which generated the message, or `null` if not applicable.
- ruleId: string | null;
+ /// The ID of the rule which generated the message, or `null` if not applicable.
+ ruleId: string | null;
- /// The severity of the message.
- severity: 0 | 1 | 2;
+ /// The severity of the message.
+ severity: 0 | 1 | 2;
- /// Information for suggestions.
- suggestions?: Suggestion[];
+ /// Information for suggestions.
+ suggestions?: Suggestion[];
};
type Fix = {
- range: [number, number];
- text: string;
-}
+ range: [number, number];
+ text: string;
+};
type Suggestion = {
- desc?: string;
- messageId?: string;
- fix: Fix;
-}
-
+ desc?: string;
+ messageId?: string;
+ fix: Fix;
+};
```
By default, ESLint does not perform autofixes when a custom processor is used, even when the `--fix` flag is enabled on the command line. To allow ESLint to autofix code when using your processor, you should take the following additional steps:
@@ -133,10 +132,10 @@ For example:
```yml
plugins:
- - a-plugin
+ - a-plugin
overrides:
- - files: "*.md"
- processor: a-plugin/markdown
+ - files: "*.md"
+ processor: a-plugin/markdown
```
See [Specify a Processor](../use/configure/plugins#specify-a-processor) in the Plugin Configuration documentation for more details.
@@ -174,14 +173,16 @@ module.exports = {
You can also use the same custom processor with multiple filename extensions. The following example shows using the same processor for both `.md` and `.mdx` files:
```js
-const myCustomProcessor = { /* processor methods */ };
+const myCustomProcessor = {
+ /* processor methods */
+};
module.exports = {
- // The same custom processor is applied to both
- // `.md` and `.mdx` files.
- processors: {
- ".md": myCustomProcessor,
- ".mdx": myCustomProcessor
- }
-}
+ // The same custom processor is applied to both
+ // `.md` and `.mdx` files.
+ processors: {
+ ".md": myCustomProcessor,
+ ".mdx": myCustomProcessor,
+ },
+};
```
diff --git a/docs/src/extend/custom-processors.md b/docs/src/extend/custom-processors.md
index 715873a575e9..3c65dcfe9ea1 100644
--- a/docs/src/extend/custom-processors.md
+++ b/docs/src/extend/custom-processors.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: create plugins
title: Custom Processors
order: 3
-
---
You can also create custom processors that tell ESLint how to process files other than standard JavaScript. For example, you could write a custom processor to extract and process JavaScript from Markdown files ([@eslint/markdown](https://www.npmjs.com/package/@eslint/markdown) includes a custom processor for this).
@@ -20,41 +19,41 @@ In order to create a custom processor, the object exported from your module has
```js
const plugin = {
-
- meta: {
- name: "eslint-plugin-example",
- version: "1.2.3"
- },
- processors: {
- "processor-name": {
- meta: {
- name: "eslint-processor-name",
- version: "1.2.3"
- },
- // takes text of the file and filename
- preprocess(text, filename) {
- // here, you can strip out any non-JS content
- // and split into multiple strings to lint
-
- return [ // return an array of code blocks to lint
- { text: code1, filename: "0.js" },
- { text: code2, filename: "1.js" },
- ];
- },
-
- // takes a Message[][] and filename
- postprocess(messages, filename) {
- // `messages` argument contains two-dimensional array of Message objects
- // where each top-level array item contains array of lint messages related
- // to the text that was returned in array from preprocess() method
-
- // you need to return a one-dimensional array of the messages you want to keep
- return [].concat(...messages);
- },
-
- supportsAutofix: true // (optional, defaults to false)
- }
- }
+ meta: {
+ name: "eslint-plugin-example",
+ version: "1.2.3",
+ },
+ processors: {
+ "processor-name": {
+ meta: {
+ name: "eslint-processor-name",
+ version: "1.2.3",
+ },
+ // takes text of the file and filename
+ preprocess(text, filename) {
+ // here, you can strip out any non-JS content
+ // and split into multiple strings to lint
+
+ return [
+ // return an array of code blocks to lint
+ { text: code1, filename: "0.js" },
+ { text: code2, filename: "1.js" },
+ ];
+ },
+
+ // takes a Message[][] and filename
+ postprocess(messages, filename) {
+ // `messages` argument contains two-dimensional array of Message objects
+ // where each top-level array item contains array of lint messages related
+ // to the text that was returned in array from preprocess() method
+
+ // you need to return a one-dimensional array of the messages you want to keep
+ return [].concat(...messages);
+ },
+
+ supportsAutofix: true, // (optional, defaults to false)
+ },
+ },
};
// for ESM
@@ -76,49 +75,47 @@ Reported problems have the following location information in each lint message:
```typescript
type LintMessage = {
+ /// The 1-based line number where the message occurs.
+ line?: number;
- /// The 1-based line number where the message occurs.
- line?: number;
+ /// The 1-based column number where the message occurs.
+ column?: number;
- /// The 1-based column number where the message occurs.
- column?: number;
+ /// The 1-based line number of the end location.
+ endLine?: number;
- /// The 1-based line number of the end location.
- endLine?: number;
+ /// The 1-based column number of the end location.
+ endColumn?: number;
- /// The 1-based column number of the end location.
- endColumn?: number;
+ /// If `true`, this is a fatal error.
+ fatal?: boolean;
- /// If `true`, this is a fatal error.
- fatal?: boolean;
+ /// Information for an autofix.
+ fix: Fix;
- /// Information for an autofix.
- fix: Fix;
+ /// The error message.
+ message: string;
- /// The error message.
- message: string;
+ /// The ID of the rule which generated the message, or `null` if not applicable.
+ ruleId: string | null;
- /// The ID of the rule which generated the message, or `null` if not applicable.
- ruleId: string | null;
+ /// The severity of the message.
+ severity: 0 | 1 | 2;
- /// The severity of the message.
- severity: 0 | 1 | 2;
-
- /// Information for suggestions.
- suggestions?: Suggestion[];
+ /// Information for suggestions.
+ suggestions?: Suggestion[];
};
type Fix = {
- range: [number, number];
- text: string;
-}
+ range: [number, number];
+ text: string;
+};
type Suggestion = {
- desc?: string;
- messageId?: string;
- fix: Fix;
-}
-
+ desc?: string;
+ messageId?: string;
+ fix: Fix;
+};
```
By default, ESLint does not perform autofixes when a custom processor is used, even when the `--fix` flag is enabled on the command line. To allow ESLint to autofix code when using your processor, you should take the following additional steps:
@@ -152,17 +149,19 @@ Example:
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
- {
- plugins: {
- example
- },
- processor: "example/processor-name"
- },
- // ... other configs
-];
+export default defineConfig([
+ {
+ files: ["**/*.txt"], // apply processor to text files
+ plugins: {
+ example,
+ },
+ processor: "example/processor-name",
+ },
+ // ... other configs
+]);
```
In this example, the processor name is `"example/processor-name"`, and that's the value that will be used for serializing configurations.
@@ -175,14 +174,16 @@ Example:
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
- {
- processor: example.processors["processor-name"]
- },
- // ... other configs
-];
+export default defineConfig([
+ {
+ files: ["**/*.txt"],
+ processor: example.processors["processor-name"],
+ },
+ // ... other configs
+]);
```
In this example, specifying `example.processors["processor-name"]` directly uses the processor's own `meta` object, which must be defined to ensure proper handling when the processor is not referenced through the plugin name.
@@ -197,16 +198,18 @@ In order to use a processor from a plugin in a configuration file, import the pl
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
- {
- plugins: {
- example
- },
- processor: "example/processor-name"
- }
-];
+export default defineConfig([
+ {
+ files: ["**/*.txt"],
+ plugins: {
+ example,
+ },
+ processor: "example/processor-name",
+ },
+]);
```
See [Specify a Processor](../use/configure/plugins#specify-a-processor) in the Plugin Configuration documentation for more details.
diff --git a/docs/src/extend/custom-rule-tutorial.md b/docs/src/extend/custom-rule-tutorial.md
index cd5eb540e37c..f91ed15dc9b6 100644
--- a/docs/src/extend/custom-rule-tutorial.md
+++ b/docs/src/extend/custom-rule-tutorial.md
@@ -16,8 +16,8 @@ You can create custom rules to validate if your code meets a certain expectation
To learn more about custom rules and plugins refer to the following documentation:
-* [Custom Rules](custom-rules)
-* [Plugins](plugins)
+- [Custom Rules](custom-rules)
+- [Plugins](plugins)
## Why Create a Custom Rule?
@@ -29,8 +29,8 @@ Before creating a custom rule that isn't specific to your company or project, it
Before you begin, make sure you have the following installed in your development environment:
-* [Node.js](https://nodejs.org/en/download/)
-* [npm](https://www.npmjs.com/)
+- [Node.js](https://nodejs.org/en/download/)
+- [npm](https://www.npmjs.com/)
This tutorial also assumes that you have a basic understanding of ESLint and ESLint rules.
@@ -73,14 +73,14 @@ In the `enforce-foo-bar.js` file, add some scaffolding for the `enforce-foo-bar`
// enforce-foo-bar.js
module.exports = {
- meta: {
- // TODO: add metadata
- },
- create(context) {
- return {
- // TODO: add callback function(s)
- };
- }
+ meta: {
+ // TODO: add metadata
+ },
+ create(context) {
+ return {
+ // TODO: add callback function(s)
+ };
+ },
};
```
@@ -94,19 +94,20 @@ Start by exporting an object with a `meta` property containing the rule's metada
// enforce-foo-bar.js
module.exports = {
- meta: {
- type: "problem",
- docs: {
- description: "Enforce that a variable named `foo` can only be assigned a value of 'bar'.",
- },
- fixable: "code",
- schema: []
- },
- create(context) {
- return {
- // TODO: add callback function(s)
- };
- }
+ meta: {
+ type: "problem",
+ docs: {
+ description:
+ "Enforce that a variable named `foo` can only be assigned a value of 'bar'.",
+ },
+ fixable: "code",
+ schema: [],
+ },
+ create(context) {
+ return {
+ // TODO: add callback function(s)
+ };
+ },
};
```
@@ -221,31 +222,36 @@ The `RuleTester#run()` method tests the rule against valid and invalid test case
```javascript
// enforce-foo-bar.test.js
-const {RuleTester} = require("eslint");
+const { RuleTester } = require("eslint");
const fooBarRule = require("./enforce-foo-bar");
const ruleTester = new RuleTester({
- // Must use at least ecmaVersion 2015 because
- // that's when `const` variables were introduced.
- languageOptions: { ecmaVersion: 2015 }
+ // Must use at least ecmaVersion 2015 because
+ // that's when `const` variables were introduced.
+ languageOptions: { ecmaVersion: 2015 },
});
// Throws error if the tests in ruleTester.run() do not pass
ruleTester.run(
- "enforce-foo-bar", // rule name
- fooBarRule, // rule code
- { // checks
- // 'valid' checks cases that should pass
- valid: [{
- code: "const foo = 'bar';",
- }],
- // 'invalid' checks cases that should not pass
- invalid: [{
- code: "const foo = 'baz';",
- output: 'const foo = "bar";',
- errors: 1,
- }],
- }
+ "enforce-foo-bar", // rule name
+ fooBarRule, // rule code
+ {
+ // checks
+ // 'valid' checks cases that should pass
+ valid: [
+ {
+ code: "const foo = 'bar';",
+ },
+ ],
+ // 'invalid' checks cases that should not pass
+ invalid: [
+ {
+ code: "const foo = 'baz';",
+ output: 'const foo = "bar";',
+ errors: 1,
+ },
+ ],
+ },
);
console.log("All tests passed!");
@@ -291,8 +297,8 @@ You can use a locally defined plugin to execute the custom rule in your project.
You might want to use a locally defined plugin in one of the following scenarios:
-* You want to test the plugin before publishing it to npm.
-* You want to use a plugin, but do not want to publish it to npm.
+- You want to test the plugin before publishing it to npm.
+- You want to use a plugin, but do not want to publish it to npm.
Before you can add the plugin to the project, create an ESLint configuration for your project using a [flat configuration file](../use/configure/configuration-files), `eslint.config.js`:
@@ -310,19 +316,19 @@ Then, add the following code to `eslint.config.js`:
const eslintPluginExample = require("./eslint-plugin-example");
module.exports = [
- {
- files: ["**/*.js"],
- languageOptions: {
- sourceType: "commonjs",
- ecmaVersion: "latest",
- },
- // Using the eslint-plugin-example plugin defined locally
- plugins: {"example": eslintPluginExample},
- rules: {
- "example/enforce-foo-bar": "error",
- },
- }
-]
+ {
+ files: ["**/*.js"],
+ languageOptions: {
+ sourceType: "commonjs",
+ ecmaVersion: "latest",
+ },
+ // Using the eslint-plugin-example plugin defined locally
+ plugins: { example: eslintPluginExample },
+ rules: {
+ "example/enforce-foo-bar": "error",
+ },
+ },
+];
```
Before you can test the rule, you must create a file to test the rule on.
@@ -339,11 +345,11 @@ Add the following code to `example.js`:
// example.js
function correctFooBar() {
- const foo = "bar";
+ const foo = "bar";
}
-function incorrectFoo(){
- const foo = "baz"; // Problem!
+function incorrectFoo() {
+ const foo = "baz"; // Problem!
}
```
@@ -472,8 +478,8 @@ There is no error output in the terminal when you run this, but you can see the
// ... rest of file
-function incorrectFoo(){
- const foo = "bar"; // Fixed!
+function incorrectFoo() {
+ const foo = "bar"; // Fixed!
}
```
diff --git a/docs/src/extend/custom-rules-deprecated.md b/docs/src/extend/custom-rules-deprecated.md
index 8e94b6dd206b..33770091b86b 100644
--- a/docs/src/extend/custom-rules-deprecated.md
+++ b/docs/src/extend/custom-rules-deprecated.md
@@ -1,6 +1,5 @@
---
title: Working with Rules (Deprecated)
-
---
As of ESLint v9.0.0, the function-style rule format that was current in ESLint <= 2.13.1 is no longer supported.
diff --git a/docs/src/extend/custom-rules.md b/docs/src/extend/custom-rules.md
index 1bae4eebd1c8..4a04b4afb0cf 100644
--- a/docs/src/extend/custom-rules.md
+++ b/docs/src/extend/custom-rules.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: create plugins
title: Custom Rules
order: 2
-
---
You can create custom rules to use with ESLint. You might want to create a custom rule if the [core rules](../rules/) do not cover your use case.
@@ -16,19 +15,19 @@ Here's the basic format of a custom rule:
// customRule.js
module.exports = {
- meta: {
- type: "suggestion",
- docs: {
- description: "Description of the rule",
- },
- fixable: "code",
- schema: [] // no options
- },
- create: function(context) {
- return {
- // callback functions
- };
- }
+ meta: {
+ type: "suggestion",
+ docs: {
+ description: "Description of the rule",
+ },
+ fixable: "code",
+ schema: [], // no options
+ },
+ create: function (context) {
+ return {
+ // callback functions
+ };
+ },
};
```
@@ -42,40 +41,40 @@ The source file for a rule exports an object with the following properties. Both
`meta`: (`object`) Contains metadata for the rule:
-* `type`: (`string`) Indicates the type of rule, which is one of `"problem"`, `"suggestion"`, or `"layout"`:
+- `type`: (`string`) Indicates the type of rule, which is one of `"problem"`, `"suggestion"`, or `"layout"`:
- * `"problem"`: The rule is identifying code that either will cause an error or may cause a confusing behavior. Developers should consider this a high priority to resolve.
- * `"suggestion"`: The rule is identifying something that could be done in a better way but no errors will occur if the code isn't changed.
- * `"layout"`: The rule cares primarily about whitespace, semicolons, commas, and parentheses, all the parts of the program that determine how the code looks rather than how it executes. These rules work on parts of the code that aren't specified in the AST.
+ - `"problem"`: The rule is identifying code that either will cause an error or may cause a confusing behavior. Developers should consider this a high priority to resolve.
+ - `"suggestion"`: The rule is identifying something that could be done in a better way but no errors will occur if the code isn't changed.
+ - `"layout"`: The rule cares primarily about whitespace, semicolons, commas, and parentheses, all the parts of the program that determine how the code looks rather than how it executes. These rules work on parts of the code that aren't specified in the AST.
-* `docs`: (`object`) Properties often used for documentation generation and tooling. Required for core rules and optional for custom rules. Custom rules can include additional properties here as needed.
+- `docs`: (`object`) Properties often used for documentation generation and tooling. Required for core rules and optional for custom rules. Custom rules can include additional properties here as needed.
- * `description`: (`string`) Provides a short description of the rule. For core rules, this is used in [rules index](../rules/).
- * `recommended`: (`boolean`) For core rules, this specifies whether the rule is enabled by the `recommended` config from `@eslint/js`.
- * `url`: (`string`) Specifies the URL at which the full documentation can be accessed. Code editors often use this to provide a helpful link on highlighted rule violations.
+ - `description`: (`string`) Provides a short description of the rule. For core rules, this is used in [rules index](../rules/).
+ - `recommended`: (`boolean`) For core rules, this specifies whether the rule is enabled by the `recommended` config from `@eslint/js`.
+ - `url`: (`string`) Specifies the URL at which the full documentation can be accessed. Code editors often use this to provide a helpful link on highlighted rule violations.
-* `fixable`: (`string`) Either `"code"` or `"whitespace"` if the `--fix` option on the [command line](../use/command-line-interface#--fix) automatically fixes problems reported by the rule.
+- `fixable`: (`string`) Either `"code"` or `"whitespace"` if the `--fix` option on the [command line](../use/command-line-interface#--fix) automatically fixes problems reported by the rule.
- **Important:** the `fixable` property is mandatory for fixable rules. If this property isn't specified, ESLint will throw an error whenever the rule attempts to produce a fix. Omit the `fixable` property if the rule is not fixable.
+ **Important:** the `fixable` property is mandatory for fixable rules. If this property isn't specified, ESLint will throw an error whenever the rule attempts to produce a fix. Omit the `fixable` property if the rule is not fixable.
-* `hasSuggestions`: (`boolean`) Specifies whether rules can return suggestions (defaults to `false` if omitted).
+- `hasSuggestions`: (`boolean`) Specifies whether rules can return suggestions (defaults to `false` if omitted).
- **Important:** the `hasSuggestions` property is mandatory for rules that provide suggestions. If this property isn't set to `true`, ESLint will throw an error whenever the rule attempts to produce a suggestion. Omit the `hasSuggestions` property if the rule does not provide suggestions.
+ **Important:** the `hasSuggestions` property is mandatory for rules that provide suggestions. If this property isn't set to `true`, ESLint will throw an error whenever the rule attempts to produce a suggestion. Omit the `hasSuggestions` property if the rule does not provide suggestions.
-* `schema`: (`object | array | false`) Specifies the [options](#options-schemas) so ESLint can prevent invalid [rule configurations](../use/configure/rules). Mandatory when the rule has options.
+- `schema`: (`object | array | false`) Specifies the [options](#options-schemas) so ESLint can prevent invalid [rule configurations](../use/configure/rules). Mandatory when the rule has options.
-* `defaultOptions`: (`array`) Specifies [default options](#option-defaults) for the rule. If present, any user-provided options in their config will be merged on top of them recursively.
+- `defaultOptions`: (`array`) Specifies [default options](#option-defaults) for the rule. If present, any user-provided options in their config will be merged on top of them recursively.
-* `deprecated`: (`boolean | DeprecatedInfo`) Indicates whether the rule has been deprecated. You may omit the `deprecated` property if the rule has not been deprecated.
-There is a dedicated page for the [DeprecatedInfo](./rule-deprecation)
+- `deprecated`: (`boolean | DeprecatedInfo`) Indicates whether the rule has been deprecated. You may omit the `deprecated` property if the rule has not been deprecated.
+ There is a dedicated page for the [DeprecatedInfo](./rule-deprecation)
-* `replacedBy`: (`array`, **Deprecated** Use `meta.deprecated.replacedBy` instead.) In the case of a deprecated rule, specify replacement rule(s).
+- `replacedBy`: (`array`, **Deprecated** Use `meta.deprecated.replacedBy` instead.) In the case of a deprecated rule, specify replacement rule(s).
`create()`: Returns an object with methods that ESLint calls to "visit" nodes while traversing the abstract syntax tree (AST as defined by [ESTree](https://github.com/estree/estree)) of JavaScript code:
-* If a key is a node type or a [selector](./selectors), ESLint calls that **visitor** function while going **down** the tree.
-* If a key is a node type or a [selector](./selectors) plus `:exit`, ESLint calls that **visitor** function while going **up** the tree.
-* If a key is an event name, ESLint calls that **handler** function for [code path analysis](code-path-analysis).
+- If a key is a node type or a [selector](./selectors), ESLint calls that **visitor** function while going **down** the tree.
+- If a key is a node type or a [selector](./selectors) plus `:exit`, ESLint calls that **visitor** function while going **up** the tree.
+- If a key is an event name, ESLint calls that **handler** function for [code path analysis](code-path-analysis).
A rule can use the current node and its surrounding tree to report or fix problems.
@@ -132,29 +131,29 @@ As the name implies, the `context` object contains information that is relevant
The `context` object has the following properties:
-* `id`: (`string`) The rule ID.
-* `filename`: (`string`) The filename associated with the source.
-* `physicalFilename`: (`string`) When linting a file, it provides the full path of the file on disk without any code block information. When linting text, it provides the value passed to `âstdin-filename` or `` if not specified.
-* `cwd`: (`string`) The `cwd` option passed to the [Linter](../integrate/nodejs-api#linter). It is a path to a directory that should be considered the current working directory.
-* `options`: (`array`) An array of the [configured options](../use/configure/rules) for this rule. This array does not include the rule severity (see the [dedicated section](#accessing-options-passed-to-a-rule)).
-* `sourceCode`: (`object`) A `SourceCode` object that you can use to work with the source that was passed to ESLint (see [Accessing the Source Code](#accessing-the-source-code)).
-* `settings`: (`object`) The [shared settings](../use/configure/configuration-files#configuring-shared-settings) from the configuration.
-* `languageOptions`: (`object`) more details for each property [here](../use/configure/language-options)
- * `sourceType`: (`'script' | 'module' | 'commonjs'`) The mode for the current file.
- * `ecmaVersion`: (`number`) The ECMA version used to parse the current file.
- * `parser`: (`object`): The parser used to parse the current file.
- * `parserOptions`: (`object`) The parser options configured for this file.
- * `globals`: (`object`) The specified globals.
-* `parserPath`: (`string`, **Removed** Use `context.languageOptions.parser` instead.) The name of the `parser` from the configuration.
-* `parserOptions`: (**Deprecated** Use `context.languageOptions.parserOptions` instead.) The parser options configured for this run (more details [here](../use/configure/language-options#specifying-parser-options)).
+- `id`: (`string`) The rule ID.
+- `filename`: (`string`) The filename associated with the source.
+- `physicalFilename`: (`string`) When linting a file, it provides the full path of the file on disk without any code block information. When linting text, it provides the value passed to `âstdin-filename` or `` if not specified.
+- `cwd`: (`string`) The `cwd` option passed to the [Linter](../integrate/nodejs-api#linter). It is a path to a directory that should be considered the current working directory.
+- `options`: (`array`) An array of the [configured options](../use/configure/rules) for this rule. This array does not include the rule severity (see the [dedicated section](#accessing-options-passed-to-a-rule)).
+- `sourceCode`: (`object`) A `SourceCode` object that you can use to work with the source that was passed to ESLint (see [Accessing the Source Code](#accessing-the-source-code)).
+- `settings`: (`object`) The [shared settings](../use/configure/configuration-files#configuring-shared-settings) from the configuration.
+- `languageOptions`: (`object`) more details for each property [here](../use/configure/language-options)
+ - `sourceType`: (`'script' | 'module' | 'commonjs'`) The mode for the current file.
+ - `ecmaVersion`: (`number`) The ECMA version used to parse the current file.
+ - `parser`: (`object`): The parser used to parse the current file.
+ - `parserOptions`: (`object`) The parser options configured for this file.
+ - `globals`: (`object`) The specified globals.
+- `parserPath`: (`string`, **Removed** Use `context.languageOptions.parser` instead.) The name of the `parser` from the configuration.
+- `parserOptions`: (**Deprecated** Use `context.languageOptions.parserOptions` instead.) The parser options configured for this run (more details [here](../use/configure/language-options#specifying-parser-options)).
Additionally, the `context` object has the following methods:
-* `getCwd()`: (**Deprecated:** Use `context.cwd` instead.) Returns the `cwd` option passed to the [Linter](../integrate/nodejs-api#linter). It is a path to a directory that should be considered the current working directory.
-* `getFilename()`: (**Deprecated:** Use `context.filename` instead.) Returns the filename associated with the source.
-* `getPhysicalFilename()`: (**Deprecated:** Use `context.physicalFilename` instead.) When linting a file, it returns the full path of the file on disk without any code block information. When linting text, it returns the value passed to `âstdin-filename` or `` if not specified.
-* `getSourceCode()`: (**Deprecated:** Use `context.sourceCode` instead.) Returns a `SourceCode` object that you can use to work with the source that was passed to ESLint (see [Accessing the Source Code](#accessing-the-source-code)).
-* `report(descriptor)`. Reports a problem in the code (see the [dedicated section](#reporting-problems)).
+- `getCwd()`: (**Deprecated:** Use `context.cwd` instead.) Returns the `cwd` option passed to the [Linter](../integrate/nodejs-api#linter). It is a path to a directory that should be considered the current working directory.
+- `getFilename()`: (**Deprecated:** Use `context.filename` instead.) Returns the filename associated with the source.
+- `getPhysicalFilename()`: (**Deprecated:** Use `context.physicalFilename` instead.) When linting a file, it returns the full path of the file on disk without any code block information. When linting text, it returns the value passed to `âstdin-filename` or `` if not specified.
+- `getSourceCode()`: (**Deprecated:** Use `context.sourceCode` instead.) Returns a `SourceCode` object that you can use to work with the source that was passed to ESLint (see [Accessing the Source Code](#accessing-the-source-code)).
+- `report(descriptor)`. Reports a problem in the code (see the [dedicated section](#reporting-problems)).
**Note:** Earlier versions of ESLint supported additional methods on the `context` object. Those methods were removed in the new format and should not be relied upon.
@@ -162,18 +161,18 @@ Additionally, the `context` object has the following methods:
The main method you'll use when writing custom rules is `context.report()`, which publishes a warning or error (depending on the configuration being used). This method accepts a single argument, which is an object containing the following properties:
-* `messageId`: (`string`) The ID of the message (see [messageIds](#messageids)) (recommended over `message`).
-* `message`: (`string`) The problem message (alternative to `messageId`).
-* `node`: (optional `object`) The AST node related to the problem. If present and `loc` is not specified, then the starting location of the node is used as the location of the problem.
-* `loc`: (optional `object`) Specifies the location of the problem. If both `loc` and `node` are specified, then the location is used from `loc` instead of `node`.
- * `start`: An object of the start location.
- * `line`: (`number`) The 1-based line number at which the problem occurred.
- * `column`: (`number`) The 0-based column number at which the problem occurred.
- * `end`: An object of the end location.
- * `line`: (`number`) The 1-based line number at which the problem occurred.
- * `column`: (`number`) The 0-based column number at which the problem occurred.
-* `data`: (optional `object`) [Placeholder](#using-message-placeholders) data for `message`.
-* `fix(fixer)`: (optional `function`) Applies a [fix](#applying-fixes) to resolve the problem.
+- `messageId`: (`string`) The ID of the message (see [messageIds](#messageids)) (recommended over `message`).
+- `message`: (`string`) The problem message (alternative to `messageId`).
+- `node`: (optional `object`) The AST node related to the problem. If present and `loc` is not specified, then the starting location of the node is used as the location of the problem.
+- `loc`: (optional `object`) Specifies the location of the problem. If both `loc` and `node` are specified, then the location is used from `loc` instead of `node`.
+ - `start`: An object of the start location.
+ - `line`: (`number`) The 1-based line number at which the problem occurred.
+ - `column`: (`number`) The 0-based column number at which the problem occurred.
+ - `end`: An object of the end location.
+ - `line`: (`number`) The 1-based line number at which the problem occurred.
+ - `column`: (`number`) The 0-based column number at which the problem occurred.
+- `data`: (optional `object`) [Placeholder](#using-message-placeholders) data for `message`.
+- `fix(fixer)`: (optional `function`) Applies a [fix](#applying-fixes) to resolve the problem.
Note that at least one of `node` or `loc` is required.
@@ -181,8 +180,8 @@ The simplest example is to use just `node` and `message`:
```js
context.report({
- node: node,
- message: "Unexpected identifier"
+ node: node,
+ message: "Unexpected identifier",
});
```
@@ -212,9 +211,9 @@ The node contains all the information necessary to figure out the line and colum
`messageId`s are the recommended approach to reporting messages in `context.report()` calls because of the following benefits:
-* Rule violation messages can be stored in a central `meta.messages` object for convenient management.
-* Rule violation messages do not need to be repeated in both the rule file and rule test file.
-* As a result, the barrier for changing rule violation messages is lower, encouraging more frequent contributions to improve and optimize them for the greatest clarity and usefulness.
+- Rule violation messages can be stored in a central `meta.messages` object for convenient management.
+- Rule violation messages do not need to be repeated in both the rule file and rule test file.
+- As a result, the barrier for changing rule violation messages is lower, encouraging more frequent contributions to improve and optimize them for the greatest clarity and usefulness.
Rule file:
@@ -266,17 +265,17 @@ var RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
ruleTester.run("avoid-name", rule, {
- valid: ["bar", "baz"],
- invalid: [
- {
- code: "foo",
- errors: [
- {
- messageId: "avoidName"
- }
- ]
- }
- ]
+ valid: ["bar", "baz"],
+ invalid: [
+ {
+ code: "foo",
+ errors: [
+ {
+ messageId: "avoidName",
+ },
+ ],
+ },
+ ],
});
```
@@ -286,11 +285,11 @@ If you'd like ESLint to attempt to fix the problem you're reporting, you can do
```js
context.report({
- node: node,
- message: "Missing semicolon",
- fix(fixer) {
- return fixer.insertTextAfter(node, ";");
- }
+ node: node,
+ message: "Missing semicolon",
+ fix(fixer) {
+ return fixer.insertTextAfter(node, ";");
+ },
});
```
@@ -300,23 +299,23 @@ Here, the `fix()` function is used to insert a semicolon after the node. Note th
The `fixer` object has the following methods:
-* `insertTextAfter(nodeOrToken, text)`: Insert text after the given node or token.
-* `insertTextAfterRange(range, text)`: Insert text after the given range.
-* `insertTextBefore(nodeOrToken, text)`: Insert text before the given node or token.
-* `insertTextBeforeRange(range, text)`: Insert text before the given range.
-* `remove(nodeOrToken)`: Remove the given node or token.
-* `removeRange(range)`: Remove text in the given range.
-* `replaceText(nodeOrToken, text)`: Replace the text in the given node or token.
-* `replaceTextRange(range, text)`: Replace the text in the given range.
+- `insertTextAfter(nodeOrToken, text)`: Insert text after the given node or token.
+- `insertTextAfterRange(range, text)`: Insert text after the given range.
+- `insertTextBefore(nodeOrToken, text)`: Insert text before the given node or token.
+- `insertTextBeforeRange(range, text)`: Insert text before the given range.
+- `remove(nodeOrToken)`: Remove the given node or token.
+- `removeRange(range)`: Remove text in the given range.
+- `replaceText(nodeOrToken, text)`: Replace the text in the given node or token.
+- `replaceTextRange(range, text)`: Replace the text in the given range.
A `range` is a two-item array containing character indices inside the source code. The first item is the start of the range (inclusive) and the second item is the end of the range (exclusive). Every node and token has a `range` property to identify the source code range they represent.
The above methods return a `fixing` object.
The `fix()` function can return the following values:
-* A `fixing` object.
-* An array which includes `fixing` objects.
-* An iterable object which enumerates `fixing` objects. Especially, the `fix()` function can be a generator.
+- A `fixing` object.
+- An array which includes `fixing` objects.
+- An iterable object which enumerates `fixing` objects. Especially, the `fix()` function can be a generator.
If you make a `fix()` function which returns multiple `fixing` objects, those `fixing` objects must not overlap.
@@ -326,21 +325,22 @@ Best practices for fixes:
1. Make fixes as small as possible. Fixes that are unnecessarily large could conflict with other fixes, and prevent them from being applied.
1. Only make one fix per message. This is enforced because you must return the result of the fixer operation from `fix()`.
1. Since all rules are run again after the initial round of fixes is applied, it's not necessary for a rule to check whether the code style of a fix will cause errors to be reported by another rule.
- * For example, suppose a fixer would like to surround an object key with quotes, but it's not sure whether the user would prefer single or double quotes.
-
- ```js
- ({ foo : 1 })
- // should get fixed to either
+ - For example, suppose a fixer would like to surround an object key with quotes, but it's not sure whether the user would prefer single or double quotes.
- ({ 'foo': 1 })
+ ```js
+ ({ foo: 1 })(
+ // should get fixed to either
- // or
+ { foo: 1 },
+ )(
+ // or
- ({ "foo": 1 })
+ { foo: 1 },
+ );
```
- * This fixer can just select a quote type arbitrarily. If it guesses wrong, the resulting code will be automatically reported and fixed by the [`quotes`](../rules/quotes) rule.
+ - This fixer can just select a quote type arbitrarily. If it guesses wrong, the resulting code will be automatically reported and fixed by the [`quotes`](../rules/quotes) rule.
Note: Making fixes as small as possible is a best practice, but in some cases it may be correct to extend the range of the fix in order to intentionally prevent other rules from making fixes in a surrounding range in the same pass. For instance, if replacement text declares a new variable, it can be useful to prevent other changes in the scope of the variable as they might cause name collisions.
@@ -348,15 +348,15 @@ The following example replaces `node` and also ensures that no other fixes will
```js
context.report({
- node,
- message,
- *fix(fixer) {
- yield fixer.replaceText(node, replacementText);
-
- // extend range of the fix to the range of `node.parent`
- yield fixer.insertTextBefore(node.parent, "");
- yield fixer.insertTextAfter(node.parent, "");
- }
+ node,
+ message,
+ *fix(fixer) {
+ yield fixer.replaceText(node, replacementText);
+
+ // extend range of the fix to the range of `node.parent`
+ yield fixer.insertTextBefore(node.parent, "");
+ yield fixer.insertTextAfter(node.parent, "");
+ },
});
```
@@ -492,7 +492,7 @@ Some rules require options in order to function correctly. These options appear
```json
{
- "quotes": ["error", "double"]
+ "quotes": ["error", "double"]
}
```
@@ -500,18 +500,18 @@ The `quotes` rule in this example has one option, `"double"` (the `error` is the
```js
module.exports = {
- meta: {
- schema: [
- {
- enum: ["single", "double", "backtick"]
- }
- ]
- },
- create: function(context) {
- var isDouble = (context.options[0] === "double");
-
- // ...
- }
+ meta: {
+ schema: [
+ {
+ enum: ["single", "double", "backtick"],
+ },
+ ],
+ },
+ create: function (context) {
+ var isDouble = context.options[0] === "double";
+
+ // ...
+ },
};
```
@@ -527,11 +527,11 @@ The `SourceCode` object is the main object for getting more information about th
```js
module.exports = {
- create: function(context) {
- var sourceCode = context.sourceCode;
+ create: function (context) {
+ var sourceCode = context.sourceCode;
- // ...
- }
+ // ...
+ },
};
```
@@ -539,70 +539,70 @@ module.exports = {
Once you have an instance of `SourceCode`, you can use the following methods on it to work with the code:
-* `getText(node)`: Returns the source code for the given node. Omit `node` to get the whole source (see the [dedicated section](#accessing-the-source-text)).
-* `getAllComments()`: Returns an array of all comments in the source (see the [dedicated section](#accessing-comments)).
-* `getCommentsBefore(nodeOrToken)`: Returns an array of comment tokens that occur directly before the given node or token (see the [dedicated section](#accessing-comments)).
-* `getCommentsAfter(nodeOrToken)`: Returns an array of comment tokens that occur directly after the given node or token (see the [dedicated section](#accessing-comments)).
-* `getCommentsInside(node)`: Returns an array of all comment tokens inside a given node (see the [dedicated section](#accessing-comments)).
-* `isSpaceBetween(nodeOrToken, nodeOrToken)`: Returns true if there is a whitespace character between the two tokens or, if given a node, the last token of the first node and the first token of the second node.
-* `getFirstToken(node, skipOptions)`: Returns the first token representing the given node.
-* `getFirstTokens(node, countOptions)`: Returns the first `count` tokens representing the given node.
-* `getLastToken(node, skipOptions)`: Returns the last token representing the given node.
-* `getLastTokens(node, countOptions)`: Returns the last `count` tokens representing the given node.
-* `getTokenAfter(nodeOrToken, skipOptions)`: Returns the first token after the given node or token.
-* `getTokensAfter(nodeOrToken, countOptions)`: Returns `count` tokens after the given node or token.
-* `getTokenBefore(nodeOrToken, skipOptions)`: Returns the first token before the given node or token.
-* `getTokensBefore(nodeOrToken, countOptions)`: Returns `count` tokens before the given node or token.
-* `getFirstTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)`: Returns the first token between two nodes or tokens.
-* `getFirstTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)`: Returns the first `count` tokens between two nodes or tokens.
-* `getLastTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)`: Returns the last token between two nodes or tokens.
-* `getLastTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)`: Returns the last `count` tokens between two nodes or tokens.
-* `getTokens(node)`: Returns all tokens for the given node.
-* `getTokensBetween(nodeOrToken1, nodeOrToken2)`: Returns all tokens between two nodes.
-* `getTokenByRangeStart(index, rangeOptions)`: Returns the token whose range starts at the given index in the source.
-* `getNodeByRangeIndex(index)`: Returns the deepest node in the AST containing the given source index.
-* `getLocFromIndex(index)`: Returns an object with `line` and `column` properties, corresponding to the location of the given source index. `line` is 1-based and `column` is 0-based.
-* `getIndexFromLoc(loc)`: Returns the index of a given location in the source code, where `loc` is an object with a 1-based `line` key and a 0-based `column` key.
-* `commentsExistBetween(nodeOrToken1, nodeOrToken2)`: Returns `true` if comments exist between two nodes.
-* `getAncestors(node)`: Returns an array of the ancestors of the given node, starting at the root of the AST and continuing through the direct parent of the given node. This array does not include the given node itself.
-* `getDeclaredVariables(node)`: Returns a list of [variables](./scope-manager-interface#variable-interface) declared by the given node. This information can be used to track references to variables.
- * If the node is a `VariableDeclaration`, all variables declared in the declaration are returned.
- * If the node is a `VariableDeclarator`, all variables declared in the declarator are returned.
- * If the node is a `FunctionDeclaration` or `FunctionExpression`, the variable for the function name is returned, in addition to variables for the function parameters.
- * If the node is an `ArrowFunctionExpression`, variables for the parameters are returned.
- * If the node is a `ClassDeclaration` or a `ClassExpression`, the variable for the class name is returned.
- * If the node is a `CatchClause`, the variable for the exception is returned.
- * If the node is an `ImportDeclaration`, variables for all of its specifiers are returned.
- * If the node is an `ImportSpecifier`, `ImportDefaultSpecifier`, or `ImportNamespaceSpecifier`, the declared variable is returned.
- * Otherwise, if the node does not declare any variables, an empty array is returned.
-* `getScope(node)`: Returns the [scope](./scope-manager-interface#scope-interface) of the given node. This information can be used to track references to variables.
-* `markVariableAsUsed(name, refNode)`: Marks a variable with the given name in a scope indicated by the given reference node as used. This affects the [no-unused-vars](../rules/no-unused-vars) rule. Returns `true` if a variable with the given name was found and marked as used, otherwise `false`.
+- `getText(node)`: Returns the source code for the given node. Omit `node` to get the whole source (see the [dedicated section](#accessing-the-source-text)).
+- `getAllComments()`: Returns an array of all comments in the source (see the [dedicated section](#accessing-comments)).
+- `getCommentsBefore(nodeOrToken)`: Returns an array of comment tokens that occur directly before the given node or token (see the [dedicated section](#accessing-comments)).
+- `getCommentsAfter(nodeOrToken)`: Returns an array of comment tokens that occur directly after the given node or token (see the [dedicated section](#accessing-comments)).
+- `getCommentsInside(node)`: Returns an array of all comment tokens inside a given node (see the [dedicated section](#accessing-comments)).
+- `isSpaceBetween(nodeOrToken, nodeOrToken)`: Returns true if there is a whitespace character between the two tokens or, if given a node, the last token of the first node and the first token of the second node.
+- `getFirstToken(node, skipOptions)`: Returns the first token representing the given node.
+- `getFirstTokens(node, countOptions)`: Returns the first `count` tokens representing the given node.
+- `getLastToken(node, skipOptions)`: Returns the last token representing the given node.
+- `getLastTokens(node, countOptions)`: Returns the last `count` tokens representing the given node.
+- `getTokenAfter(nodeOrToken, skipOptions)`: Returns the first token after the given node or token.
+- `getTokensAfter(nodeOrToken, countOptions)`: Returns `count` tokens after the given node or token.
+- `getTokenBefore(nodeOrToken, skipOptions)`: Returns the first token before the given node or token.
+- `getTokensBefore(nodeOrToken, countOptions)`: Returns `count` tokens before the given node or token.
+- `getFirstTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)`: Returns the first token between two nodes or tokens.
+- `getFirstTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)`: Returns the first `count` tokens between two nodes or tokens.
+- `getLastTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)`: Returns the last token between two nodes or tokens.
+- `getLastTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)`: Returns the last `count` tokens between two nodes or tokens.
+- `getTokens(node)`: Returns all tokens for the given node.
+- `getTokensBetween(nodeOrToken1, nodeOrToken2)`: Returns all tokens between two nodes.
+- `getTokenByRangeStart(index, rangeOptions)`: Returns the token whose range starts at the given index in the source.
+- `getNodeByRangeIndex(index)`: Returns the deepest node in the AST containing the given source index.
+- `getLocFromIndex(index)`: Returns an object with `line` and `column` properties, corresponding to the location of the given source index. `line` is 1-based and `column` is 0-based.
+- `getIndexFromLoc(loc)`: Returns the index of a given location in the source code, where `loc` is an object with a 1-based `line` key and a 0-based `column` key.
+- `commentsExistBetween(nodeOrToken1, nodeOrToken2)`: Returns `true` if comments exist between two nodes.
+- `getAncestors(node)`: Returns an array of the ancestors of the given node, starting at the root of the AST and continuing through the direct parent of the given node. This array does not include the given node itself.
+- `getDeclaredVariables(node)`: Returns a list of [variables](./scope-manager-interface#variable-interface) declared by the given node. This information can be used to track references to variables.
+ - If the node is a `VariableDeclaration`, all variables declared in the declaration are returned.
+ - If the node is a `VariableDeclarator`, all variables declared in the declarator are returned.
+ - If the node is a `FunctionDeclaration` or `FunctionExpression`, the variable for the function name is returned, in addition to variables for the function parameters.
+ - If the node is an `ArrowFunctionExpression`, variables for the parameters are returned.
+ - If the node is a `ClassDeclaration` or a `ClassExpression`, the variable for the class name is returned.
+ - If the node is a `CatchClause`, the variable for the exception is returned.
+ - If the node is an `ImportDeclaration`, variables for all of its specifiers are returned.
+ - If the node is an `ImportSpecifier`, `ImportDefaultSpecifier`, or `ImportNamespaceSpecifier`, the declared variable is returned.
+ - Otherwise, if the node does not declare any variables, an empty array is returned.
+- `getScope(node)`: Returns the [scope](./scope-manager-interface#scope-interface) of the given node. This information can be used to track references to variables.
+- `markVariableAsUsed(name, refNode)`: Marks a variable with the given name in a scope indicated by the given reference node as used. This affects the [no-unused-vars](../rules/no-unused-vars) rule. Returns `true` if a variable with the given name was found and marked as used, otherwise `false`.
`skipOptions` is an object which has 3 properties; `skip`, `includeComments`, and `filter`. Default is `{skip: 0, includeComments: false, filter: null}`.
-* `skip`: (`number`) Positive integer, the number of skipping tokens. If `filter` option is given at the same time, it doesn't count filtered tokens as skipped.
-* `includeComments`: (`boolean`) The flag to include comment tokens into the result.
-* `filter(token)`: Function which gets a token as the first argument. If the function returns `false` then the result excludes the token.
+- `skip`: (`number`) Positive integer, the number of skipping tokens. If `filter` option is given at the same time, it doesn't count filtered tokens as skipped.
+- `includeComments`: (`boolean`) The flag to include comment tokens into the result.
+- `filter(token)`: Function which gets a token as the first argument. If the function returns `false` then the result excludes the token.
`countOptions` is an object which has 3 properties; `count`, `includeComments`, and `filter`. Default is `{count: 0, includeComments: false, filter: null}`.
-* `count`: (`number`) Positive integer, the maximum number of returning tokens.
-* `includeComments`: (`boolean`) The flag to include comment tokens into the result.
-* `filter(token)`: Function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
+- `count`: (`number`) Positive integer, the maximum number of returning tokens.
+- `includeComments`: (`boolean`) The flag to include comment tokens into the result.
+- `filter(token)`: Function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
`rangeOptions` is an object that has 1 property, `includeComments`. Default is `{includeComments: false}`.
-* `includeComments`: (`boolean`) The flag to include comment tokens into the result.
+- `includeComments`: (`boolean`) The flag to include comment tokens into the result.
There are also some properties you can access:
-* `hasBOM`: (`boolean`) The flag to indicate whether the source code has Unicode BOM.
-* `text`: (`string`) The full text of the code being linted. Unicode BOM has been stripped from this text.
-* `ast`: (`object`) `Program` node of the AST for the code being linted.
-* `scopeManager`: [ScopeManager](./scope-manager-interface#scopemanager-interface) object of the code.
-* `visitorKeys`: (`object`) Visitor keys to traverse this AST.
-* `parserServices`: (`object`) Contains parser-provided services for rules. The default parser does not provide any services. However, if a rule is intended to be used with a custom parser, it could use `parserServices` to access anything provided by that parser. (For example, a TypeScript parser could provide the ability to get the computed type of a given node.)
-* `lines`: (`array`) Array of lines, split according to the specification's definition of line breaks.
+- `hasBOM`: (`boolean`) The flag to indicate whether the source code has Unicode BOM.
+- `text`: (`string`) The full text of the code being linted. Unicode BOM has been stripped from this text.
+- `ast`: (`object`) `Program` node of the AST for the code being linted.
+- `scopeManager`: [ScopeManager](./scope-manager-interface#scopemanager-interface) object of the code.
+- `visitorKeys`: (`object`) Visitor keys to traverse this AST.
+- `parserServices`: (`object`) Contains parser-provided services for rules. The default parser does not provide any services. However, if a rule is intended to be used with a custom parser, it could use `parserServices` to access anything provided by that parser. (For example, a TypeScript parser could provide the ability to get the computed type of a given node.)
+- `lines`: (`array`) Array of lines, split according to the specification's definition of line breaks.
You should use a `SourceCode` object whenever you need to get more information about the code being linted.
@@ -611,7 +611,6 @@ You should use a `SourceCode` object whenever you need to get more information a
If your rule needs to get the actual JavaScript source to work with, then use the `sourceCode.getText()` method. This method works as follows:
```js
-
// get all source
var source = sourceCode.getText();
@@ -657,18 +656,18 @@ Note: this means that the rule schema cannot validate the severity. The rule sch
There are two formats for a rule's `schema`:
-* An array of JSON Schema objects
- * Each element will be checked against the same position in the `context.options` array.
- * If the `context.options` array has fewer elements than there are schemas, then the unmatched schemas are ignored.
- * If the `context.options` array has more elements than there are schemas, then the validation fails.
- * There are two important consequences to using this format:
- * It is _always valid_ for a user to provide no options to your rule (beyond severity).
- * If you specify an empty array, then it is _always an error_ for a user to provide any options to your rule (beyond severity).
-* A full JSON Schema object that will validate the `context.options` array
- * The schema should assume an array of options to validate even if your rule only accepts one option.
- * The schema can be arbitrarily complex, so you can validate completely different sets of potential options via `oneOf`, `anyOf` etc.
- * The supported version of JSON Schemas is [Draft-04](http://json-schema.org/draft-04/schema), so some newer features such as `if` or `$data` are unavailable.
- * At present, it is explicitly planned to not update schema support beyond this level due to ecosystem compatibility concerns. See [this comment](https://github.com/eslint/eslint/issues/13888#issuecomment-872591875) for further context.
+- An array of JSON Schema objects
+ - Each element will be checked against the same position in the `context.options` array.
+ - If the `context.options` array has fewer elements than there are schemas, then the unmatched schemas are ignored.
+ - If the `context.options` array has more elements than there are schemas, then the validation fails.
+ - There are two important consequences to using this format:
+ - It is _always valid_ for a user to provide no options to your rule (beyond severity).
+ - If you specify an empty array, then it is _always an error_ for a user to provide any options to your rule (beyond severity).
+- A full JSON Schema object that will validate the `context.options` array
+ - The schema should assume an array of options to validate even if your rule only accepts one option.
+ - The schema can be arbitrarily complex, so you can validate completely different sets of potential options via `oneOf`, `anyOf` etc.
+ - The supported version of JSON Schemas is [Draft-04](http://json-schema.org/draft-04/schema), so some newer features such as `if` or `$data` are unavailable.
+ - At present, it is explicitly planned to not update schema support beyond this level due to ecosystem compatibility concerns. See [this comment](https://github.com/eslint/eslint/issues/13888#issuecomment-872591875) for further context.
For example, the `yoda` rule accepts a primary mode argument of `"always"` or `"never"`, as well as an extra options object with an optional property `exceptRange`:
@@ -682,20 +681,20 @@ For example, the `yoda` rule accepts a primary mode argument of `"always"` or `"
// "yoda": ["warn", "never", { "exceptRange": true }, 5]
// "yoda": ["error", { "exceptRange": true }, "never"]
module.exports = {
- meta: {
- schema: [
- {
- enum: ["always", "never"]
- },
- {
- type: "object",
- properties: {
- exceptRange: { type: "boolean" }
- },
- additionalProperties: false
- }
- ]
- }
+ meta: {
+ schema: [
+ {
+ enum: ["always", "never"],
+ },
+ {
+ type: "object",
+ properties: {
+ exceptRange: { type: "boolean" },
+ },
+ additionalProperties: false,
+ },
+ ],
+ },
};
```
@@ -711,25 +710,25 @@ And here is the equivalent object-based schema:
// "yoda": ["warn", "never", { "exceptRange": true }, 5]
// "yoda": ["error", { "exceptRange": true }, "never"]
module.exports = {
- meta: {
- schema: {
- type: "array",
- minItems: 0,
- maxItems: 2,
- items: [
- {
- enum: ["always", "never"]
- },
- {
- type: "object",
- properties: {
- exceptRange: { type: "boolean" }
- },
- additionalProperties: false
- }
- ]
- }
- }
+ meta: {
+ schema: {
+ type: "array",
+ minItems: 0,
+ maxItems: 2,
+ items: [
+ {
+ enum: ["always", "never"],
+ },
+ {
+ type: "object",
+ properties: {
+ exceptRange: { type: "boolean" },
+ },
+ additionalProperties: false,
+ },
+ ],
+ },
+ },
};
```
@@ -749,36 +748,36 @@ Object schemas can be more precise and restrictive in what is permitted. For exa
// "someRule": ["warn", 7, { someOtherProperty: 5 }]
// "someRule": ["warn", 7, { someNonOptionalProperty: false, someOtherProperty: 5 }]
module.exports = {
- meta: {
- schema: {
- type: "array",
- minItems: 1, // Can't specify only severity!
- maxItems: 2,
- items: [
- {
- type: "number",
- minimum: 0,
- maximum: 10
- },
- {
- anyOf: [
- {
- type: "object",
- properties: {
- someNonOptionalProperty: { type: "boolean" }
- },
- required: ["someNonOptionalProperty"],
- additionalProperties: false
- },
- {
- enum: ["off", "strict"]
- }
- ]
- }
- ]
- }
- }
-}
+ meta: {
+ schema: {
+ type: "array",
+ minItems: 1, // Can't specify only severity!
+ maxItems: 2,
+ items: [
+ {
+ type: "number",
+ minimum: 0,
+ maximum: 10,
+ },
+ {
+ anyOf: [
+ {
+ type: "object",
+ properties: {
+ someNonOptionalProperty: { type: "boolean" },
+ },
+ required: ["someNonOptionalProperty"],
+ additionalProperties: false,
+ },
+ {
+ enum: ["off", "strict"],
+ },
+ ],
+ },
+ ],
+ },
+ },
+};
```
Remember, rule options are always an array, so be careful not to specify a schema for a non-array type at the top level. If your schema does not specify an array at the top-level, users can _never_ enable your rule, as their configuration will always be invalid when the rule is enabled.
@@ -789,18 +788,18 @@ Here's an example schema that will always fail validation:
// Possibly trying to validate ["error", { someOptionalProperty: true }]
// but when the rule is enabled, config will always fail validation because the options are an array which doesn't match "object"
module.exports = {
- meta: {
- schema: {
- type: "object",
- properties: {
- someOptionalProperty: {
- type: "boolean"
- }
- },
- additionalProperties: false
- }
- }
-}
+ meta: {
+ schema: {
+ type: "object",
+ properties: {
+ someOptionalProperty: {
+ type: "boolean",
+ },
+ },
+ additionalProperties: false,
+ },
+ },
+};
```
**Note:** If your rule schema uses JSON schema [`$ref`](https://json-schema.org/understanding-json-schema/structuring.html#ref) properties, you must use the full JSON Schema object rather than the array of positional property schemas. This is because ESLint transforms the array shorthand into a single schema without updating references that makes them incorrect (they are ignored).
@@ -816,35 +815,41 @@ For example, given the following defaults:
```js
export default {
- meta: {
- defaultOptions: [{
- alias: "basic",
- }],
- schema: [{
- type: "object",
- properties: {
- alias: {
- type: "string"
- }
- },
- additionalProperties: false
- }]
- },
- create(context) {
- const [{ alias }] = context.options;
-
- return { /* ... */ };
- }
-}
+ meta: {
+ defaultOptions: [
+ {
+ alias: "basic",
+ },
+ ],
+ schema: [
+ {
+ type: "object",
+ properties: {
+ alias: {
+ type: "string",
+ },
+ },
+ additionalProperties: false,
+ },
+ ],
+ },
+ create(context) {
+ const [{ alias }] = context.options;
+
+ return {
+ /* ... */
+ };
+ },
+};
```
The rule would have a runtime `alias` value of `"basic"` unless the user configuration specifies a different value, such as with `["error", { alias: "complex" }]`.
Each element of the options array is merged according to the following rules:
-* Any missing value or explicit user-provided `undefined` will fall back to a default option
-* User-provided arrays and primitive values other than `undefined` override a default option
-* User-provided objects will merge into a default option object and replace a non-object default otherwise
+- Any missing value or explicit user-provided `undefined` will fall back to a default option
+- User-provided arrays and primitive values other than `undefined` override a default option
+- User-provided objects will merge into a default option object and replace a non-object default otherwise
Option defaults will also be validated against the rule's `meta.schema`.
@@ -854,7 +859,7 @@ ESLint may disable Ajv's `useDefaults` in a future major version.
### Accessing Shebangs
-[Shebangs (#!)](https://en.wikipedia.org/wiki/Shebang_(Unix)) are represented by the unique tokens of type `"Shebang"`. They are treated as comments and can be accessed by the methods outlined in the [Accessing Comments](#accessing-comments) section, such as `sourceCode.getAllComments()`.
+[Shebangs (#!)]() are represented by the unique tokens of type `"Shebang"`. They are treated as comments and can be accessed by the methods outlined in the [Accessing Comments](#accessing-comments) section, such as `sourceCode.getAllComments()`.
### Accessing Variable Scopes
@@ -869,21 +874,21 @@ You can view scope information for any JavaScript code using [Code Explorer](htt
The following table contains a list of AST node types and the scope type that they correspond to. For more information about the scope types, refer to the [`Scope` object documentation](./scope-manager-interface#scope-interface).
| AST Node Type | Scope Type |
-|:--------------------------|:-----------|
+| :------------------------ | :--------- |
| `Program` | `global` |
| `FunctionDeclaration` | `function` |
| `FunctionExpression` | `function` |
| `ArrowFunctionExpression` | `function` |
| `ClassDeclaration` | `class` |
| `ClassExpression` | `class` |
-| `BlockStatement` âģ1 | `block` |
-| `SwitchStatement` âģ1 | `switch` |
-| `ForStatement` âģ2 | `for` |
-| `ForInStatement` âģ2 | `for` |
-| `ForOfStatement` âģ2 | `for` |
+| `BlockStatement` âģ1 | `block` |
+| `SwitchStatement` âģ1 | `switch` |
+| `ForStatement` âģ2 | `for` |
+| `ForInStatement` âģ2 | `for` |
+| `ForOfStatement` âģ2 | `for` |
| `WithStatement` | `with` |
| `CatchClause` | `catch` |
-| others | âģ3 |
+| others | âģ3 |
**âģ1** Only if the configured parser provided the block-scope feature. The default parser provides the block-scope feature if `parserOptions.ecmaVersion` is not less than `6`.
**âģ2** Only if the `for` statement defines the iteration variable as a block-scoped variable (E.g., `for (let i = 0;;) {}`).
@@ -899,15 +904,15 @@ Also inside of each `Variable`, the `Variable#defs` property contains an array o
Global variables have the following additional properties:
-* `Variable#writeable` (`boolean | undefined`) ... If `true`, this global variable can be assigned arbitrary value. If `false`, this global variable is read-only.
-* `Variable#eslintExplicitGlobal` (`boolean | undefined`) ... If `true`, this global variable was defined by a `/* globals */` directive comment in the source code file.
-* `Variable#eslintExplicitGlobalComments` (`Comment[] | undefined`) ... The array of `/* globals */` directive comments which defined this global variable in the source code file. This property is `undefined` if there are no `/* globals */` directive comments.
-* `Variable#eslintImplicitGlobalSetting` (`"readonly" | "writable" | undefined`) ... The configured value in config files. This can be different from `variable.writeable` if there are `/* globals */` directive comments.
+- `Variable#writeable` (`boolean | undefined`) ... If `true`, this global variable can be assigned arbitrary value. If `false`, this global variable is read-only.
+- `Variable#eslintExplicitGlobal` (`boolean | undefined`) ... If `true`, this global variable was defined by a `/* globals */` directive comment in the source code file.
+- `Variable#eslintExplicitGlobalComments` (`Comment[] | undefined`) ... The array of `/* globals */` directive comments which defined this global variable in the source code file. This property is `undefined` if there are no `/* globals */` directive comments.
+- `Variable#eslintImplicitGlobalSetting` (`"readonly" | "writable" | undefined`) ... The configured value in config files. This can be different from `variable.writeable` if there are `/* globals */` directive comments.
For examples of using `SourceCode#getScope()` to track variables, refer to the source code for the following built-in rules:
-* [no-shadow](https://github.com/eslint/eslint/blob/main/lib/rules/no-shadow.js): Calls `sourceCode.getScope()` at the `Program` node and inspects all child scopes to make sure a variable name is not reused at a lower scope. ([no-shadow](../rules/no-shadow) documentation)
-* [no-redeclare](https://github.com/eslint/eslint/blob/main/lib/rules/no-redeclare.js): Calls `sourceCode.getScope()` at each scope to make sure that a variable is not declared twice in the same scope. ([no-redeclare](../rules/no-redeclare) documentation)
+- [no-shadow](https://github.com/eslint/eslint/blob/main/lib/rules/no-shadow.js): Calls `sourceCode.getScope()` at the `Program` node and inspects all child scopes to make sure a variable name is not reused at a lower scope. ([no-shadow](../rules/no-shadow) documentation)
+- [no-redeclare](https://github.com/eslint/eslint/blob/main/lib/rules/no-redeclare.js): Calls `sourceCode.getScope()` at each scope to make sure that a variable is not declared twice in the same scope. ([no-redeclare](../rules/no-redeclare) documentation)
### Marking Variables as Used
@@ -917,21 +922,20 @@ To help with this, you can use the `sourceCode.markVariableAsUsed()` method. Thi
```js
module.exports = {
- create: function(context) {
- var sourceCode = context.sourceCode;
-
- return {
- ReturnStatement(node) {
-
- // look in the scope of the function for myCustomVar and mark as used
- sourceCode.markVariableAsUsed("myCustomVar", node);
-
- // or: look in the global scope for myCustomVar and mark as used
- sourceCode.markVariableAsUsed("myCustomVar");
- }
- }
- // ...
- }
+ create: function (context) {
+ var sourceCode = context.sourceCode;
+
+ return {
+ ReturnStatement(node) {
+ // look in the scope of the function for myCustomVar and mark as used
+ sourceCode.markVariableAsUsed("myCustomVar", node);
+
+ // or: look in the global scope for myCustomVar and mark as used
+ sourceCode.markVariableAsUsed("myCustomVar");
+ },
+ };
+ // ...
+ },
};
```
@@ -945,10 +949,10 @@ ESLint analyzes code paths while traversing AST. You can access code path object
Please note that the following `SourceCode` methods have been deprecated and will be removed in a future version of ESLint:
-* `getTokenOrCommentBefore()`: Replaced by `SourceCode#getTokenBefore()` with the `{ includeComments: true }` option.
-* `getTokenOrCommentAfter()`: Replaced by `SourceCode#getTokenAfter()` with the `{ includeComments: true }` option.
-* `isSpaceBetweenTokens()`: Replaced by `SourceCode#isSpaceBetween()`
-* `getJSDocComment()`
+- `getTokenOrCommentBefore()`: Replaced by `SourceCode#getTokenBefore()` with the `{ includeComments: true }` option.
+- `getTokenOrCommentAfter()`: Replaced by `SourceCode#getTokenAfter()` with the `{ includeComments: true }` option.
+- `isSpaceBetweenTokens()`: Replaced by `SourceCode#isSpaceBetween()`
+- `getJSDocComment()`
## Rule Unit Tests
diff --git a/docs/src/extend/index.md b/docs/src/extend/index.md
index 815a42b457bd..7109d4715af4 100644
--- a/docs/src/extend/index.md
+++ b/docs/src/extend/index.md
@@ -4,16 +4,15 @@ eleventyNavigation:
key: extend eslint
title: Extend ESLint
order: 2
-
---
This guide is intended for those who wish to extend the functionality of ESLint.
In order to extend ESLint, it's recommended that:
-* You know JavaScript, since ESLint is written in JavaScript.
-* You have some familiarity with Node.js, since ESLint runs on it.
-* You're comfortable with command-line programs.
+- You know JavaScript, since ESLint is written in JavaScript.
+- You have some familiarity with Node.js, since ESLint runs on it.
+- You're comfortable with command-line programs.
If that sounds like you, then continue reading to get started.
diff --git a/docs/src/extend/languages.md b/docs/src/extend/languages.md
index 2b993d575b4f..fc2abe6bd446 100644
--- a/docs/src/extend/languages.md
+++ b/docs/src/extend/languages.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: create plugins
title: Languages
order: 4
-
---
Starting with ESLint v9.7.0, you can extend ESLint with additional languages through plugins. While ESLint began as a linter strictly for JavaScript, the ESLint core is generic and can be used to lint any programming language. Each language is defined as an object that contains all of the parsing, evaluating, and traversal functionality required to lint a file. These languages are then distributed in plugins for use in user configurations.
@@ -26,12 +25,14 @@ While there is no specific structure an AST or CST must follow, it's easier to i
1. **Type** - A property on each node representing the node type is required. For example, in JavaScript, the `type` property contains this information for each node. ESLint rules use node types to define the visitor methods, so it's important that each node can be identified by a string. The name of the property doesn't matter (discussed further below) so long as one exists. This property is typically named `type` or `kind` by most parsers.
1. **Location** - A property on each node representing the location of the node in the original source code is required. The location must contain:
- * The line on which the node starts
- * The column on which the node starts
- * The line on which the node ends
- * The column on which the node ends
+
+ - The line on which the node starts
+ - The column on which the node starts
+ - The line on which the node ends
+ - The column on which the node ends
As with the node type, the property name doesn't matter. Two common property names are `loc` (as in [ESTree](https://github.com/estree/estree/blob/3851d4a6eae5e5473371893959b88b62007469e8/es5.md#node-objects)) and `position` (as in [Unist](https://github.com/syntax-tree/unist?tab=readme-ov-file#node)). This information is used by ESLint to report errors and rule violations.
+
1. **Range** - A property on each node representing the location of the node's source inside the source code is required. The range indicates the index at which the first character is found and the index after the last character, such that calling `code.slice(start, end)` returns the text that the node represents. Once again, no specific property name is required, and this information may even be merged with location information. ESTree uses the `range` property while Unist includes this information on `position` along with the location information. This information is used by ESLint to apply autofixes.
### The `SourceCode` Object
@@ -40,27 +41,27 @@ ESLint holds information about source code in a `SourceCode` object. This object
A basic `SourceCode` object must implement the following:
-* `ast` - a property containing the AST or CST for the source code.
-* `text` - the text of the source code.
-* `getLoc(nodeOrToken)` - a method that returns the location of a given node or token. This must match the `loc` structure that ESTree uses.
-* `getRange(nodeOrToken)` - a method that returns the range of a given node or token. This must return an array where the first item is the start index and the second is the end index.
-* `traverse()` - a method that returns an iterable for traversing the AST or CST. The iterator must return objects that implement either `VisitTraversalStep` or `CallTraversalStep` from `@eslint/core`.
+- `ast` - a property containing the AST or CST for the source code.
+- `text` - the text of the source code.
+- `getLoc(nodeOrToken)` - a method that returns the location of a given node or token. This must match the `loc` structure that ESTree uses.
+- `getRange(nodeOrToken)` - a method that returns the range of a given node or token. This must return an array where the first item is the start index and the second is the end index.
+- `traverse()` - a method that returns an iterable for traversing the AST or CST. The iterator must return objects that implement either `VisitTraversalStep` or `CallTraversalStep` from `@eslint/core`.
The following optional members allow you to customize how ESLint interacts with the object:
-* `visitorKeys` - visitor keys that are specific to just this `SourceCode` object. Typically not necessary as `Language#visitorKeys` is used most of the time.
-* `applyLanguageOptions(languageOptions)` - if you have specific language options that need to be applied after parsing, you can do so in this method.
-* `getDisableDirectives()` - returns any disable directives in the code. ESLint uses this to apply disable directives and track unused directives.
-* `getInlineConfigNodes()` - returns any inline config nodes. ESLint uses this to report errors when `noInlineConfig` is enabled.
-* `applyInlineConfig()` - returns inline configuration elements to ESLint. ESLint uses this to alter the configuration of the file being linted.
-* `finalize()` - this method is called just before linting begins and is your last chance to modify `SourceCode`. If you've defined `applyLanguageOptions()` or `applyInlineConfig()`, then you may have additional changes to apply before the `SourceCode` object is ready.
+- `visitorKeys` - visitor keys that are specific to just this `SourceCode` object. Typically not necessary as `Language#visitorKeys` is used most of the time.
+- `applyLanguageOptions(languageOptions)` - if you have specific language options that need to be applied after parsing, you can do so in this method.
+- `getDisableDirectives()` - returns any disable directives in the code. ESLint uses this to apply disable directives and track unused directives.
+- `getInlineConfigNodes()` - returns any inline config nodes. ESLint uses this to report errors when `noInlineConfig` is enabled.
+- `applyInlineConfig()` - returns inline configuration elements to ESLint. ESLint uses this to alter the configuration of the file being linted.
+- `finalize()` - this method is called just before linting begins and is your last chance to modify `SourceCode`. If you've defined `applyLanguageOptions()` or `applyInlineConfig()`, then you may have additional changes to apply before the `SourceCode` object is ready.
Additionally, the following members are common on `SourceCode` objects and are recommended to implement:
-* `lines` - the individual lines of the source code as an array of strings.
-* `getParent(node)` - returns the parent of the given node or `undefined` if the node is the root.
-* `getAncestors(node)` - returns an array of the ancestry of the node with the first item as the root of the tree and each subsequent item as the descendants of the root that lead to `node`.
-* `getText(node, beforeCount, afterCount)` - returns the string that represents the given node, and optionally, a specified number of characters before and after the node's range.
+- `lines` - the individual lines of the source code as an array of strings.
+- `getParent(node)` - returns the parent of the given node or `undefined` if the node is the root.
+- `getAncestors(node)` - returns an array of the ancestry of the node with the first item as the root of the tree and each subsequent item as the descendants of the root that lead to `node`.
+- `getText(node, beforeCount, afterCount)` - returns the string that represents the given node, and optionally, a specified number of characters before and after the node's range.
See [`JSONSourceCode`](https://github.com/eslint/json/blob/main/src/languages/json-source-code.js) as an example of a basic `SourceCode` class.
@@ -74,20 +75,20 @@ The `Language` object contains all of the information about the programming lang
A basic `Language` object must implement the following:
-* `fileType` - should be `"text"` (in the future, we will also support `"binary"`)
-* `lineStart` - either 0 or 1 to indicate how the AST represents the first line in the file. ESLint uses this to correctly display error locations.
-* `columnStart` - either 0 or 1 to indicate how the AST represents the first column in each line. ESLint uses this to correctly display error locations.
-* `nodeTypeKey` - the name of the property that indicates the node type (usually `"type"` or `"kind"`).
-* `validateLanguageOptions(languageOptions)` - validates language options for the language. This method is expected to throw a validation error when an expected language option doesn't have the correct type or value. Unexpected language options should be silently ignored and no error should be thrown. This method is required even if the language doesn't specify any options.
-* `parse(file, context)` - parses the given file into an AST or CST, and can also include additional values meant for use in rules. Called internally by ESLint.
-* `createSourceCode(file, parseResult, context)` - creates a `SourceCode` object. Call internally by ESLint after `parse()`, and the second argument is the exact return value from `parse()`.
+- `fileType` - should be `"text"` (in the future, we will also support `"binary"`)
+- `lineStart` - either 0 or 1 to indicate how the AST represents the first line in the file. ESLint uses this to correctly display error locations.
+- `columnStart` - either 0 or 1 to indicate how the AST represents the first column in each line. ESLint uses this to correctly display error locations.
+- `nodeTypeKey` - the name of the property that indicates the node type (usually `"type"` or `"kind"`).
+- `validateLanguageOptions(languageOptions)` - validates language options for the language. This method is expected to throw a validation error when an expected language option doesn't have the correct type or value. Unexpected language options should be silently ignored and no error should be thrown. This method is required even if the language doesn't specify any options.
+- `parse(file, context)` - parses the given file into an AST or CST, and can also include additional values meant for use in rules. Called internally by ESLint.
+- `createSourceCode(file, parseResult, context)` - creates a `SourceCode` object. Call internally by ESLint after `parse()`, and the second argument is the exact return value from `parse()`.
The following optional members allow you to customize how ESLint interacts with the object:
-* `visitorKeys` - visitor keys that are specific to the AST or CST. This is used to optimize traversal of the AST or CST inside of ESLint. While not required, it is strongly recommended, especially for AST or CST formats that deviate significantly from ESTree format.
-* `defaultLanguageOptions` - default `languageOptions` when the language is used. User-specified `languageOptions` are merged with this object when calculating the config for the file being linted.
-* `matchesSelectorClass(className, node, ancestry)` - allows you to specify selector classes, such as `:expression`, that match more than one node. This method is called whenever an [esquery](https://github.com/estools/esquery) selector contains a `:` followed by an identifier.
-* `normalizeLanguageOptions(languageOptions)` - takes a validated language options object and normalizes its values. This is helpful for backwards compatibility when language options properties change.
+- `visitorKeys` - visitor keys that are specific to the AST or CST. This is used to optimize traversal of the AST or CST inside of ESLint. While not required, it is strongly recommended, especially for AST or CST formats that deviate significantly from ESTree format.
+- `defaultLanguageOptions` - default `languageOptions` when the language is used. User-specified `languageOptions` are merged with this object when calculating the config for the file being linted.
+- `matchesSelectorClass(className, node, ancestry)` - allows you to specify selector classes, such as `:expression`, that match more than one node. This method is called whenever an [esquery](https://github.com/estools/esquery) selector contains a `:` followed by an identifier.
+- `normalizeLanguageOptions(languageOptions)` - takes a validated language options object and normalizes its values. This is helpful for backwards compatibility when language options properties change.
See [`JSONLanguage`](https://github.com/eslint/json/blob/main/src/languages/json-language.js) as an example of a basic `Language` class.
@@ -99,18 +100,17 @@ Languages are published in plugins similar to processors and rules. Define the `
import { myLanguage } from "../languages/my.js";
const plugin = {
-
- // preferred location of name and version
- meta: {
- name: "eslint-plugin-example",
- version: "1.2.3"
- },
- languages: {
- my: myLanguage
- },
- rules: {
- // add rules here
- }
+ // preferred location of name and version
+ meta: {
+ name: "eslint-plugin-example",
+ version: "1.2.3",
+ },
+ languages: {
+ my: myLanguage,
+ },
+ rules: {
+ // add rules here
+ },
};
// for ESM
@@ -124,16 +124,18 @@ In order to use a language from a plugin in a configuration file, import the plu
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
- {
- plugins: {
- example
- },
- language: "example/my"
- }
-];
+export default defineConfig([
+ {
+ files: ["**/*.my"],
+ plugins: {
+ example,
+ },
+ language: "example/my",
+ },
+]);
```
See [Specify a Language](../use/configure/plugins#specify-a-language) in the Plugin Configuration documentation for more details.
diff --git a/docs/src/extend/plugin-migration-flat-config.md b/docs/src/extend/plugin-migration-flat-config.md
index 742c0999d82a..1113d15a4723 100644
--- a/docs/src/extend/plugin-migration-flat-config.md
+++ b/docs/src/extend/plugin-migration-flat-config.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: create plugins
title: Migration to Flat Config
order: 5
-
---
Beginning in ESLint v9.0.0, the default configuration system will be the new flat config system. In order for your plugins to work with flat config files, you'll need to make some changes to your existing plugins.
@@ -16,10 +15,10 @@ To make it easier to work with your plugin in the flat config system, it's recom
```js
const plugin = {
- meta: {},
- configs: {},
- rules: {},
- processors: {}
+ meta: {},
+ configs: {},
+ rules: {},
+ processors: {},
};
// for ESM
@@ -37,13 +36,13 @@ With the old eslintrc configuration system, ESLint could pull information about
```js
const plugin = {
- meta: {
- name: "eslint-plugin-example",
- version: "1.0.0"
- },
- configs: {},
- rules: {},
- processors: {}
+ meta: {
+ name: "eslint-plugin-example",
+ version: "1.0.0",
+ },
+ configs: {},
+ rules: {},
+ processors: {},
};
// for ESM
@@ -69,16 +68,15 @@ No other changes are necessary for the `processors` key in your plugin as long a
```js
const plugin = {
- configs: {},
- rules: {},
- processors: {
-
- // no longer supported
- ".md": {
- preprocess() {},
- postprocess() {}
- }
- }
+ configs: {},
+ rules: {},
+ processors: {
+ // no longer supported
+ ".md": {
+ preprocess() {},
+ postprocess() {},
+ },
+ },
};
// for ESM
@@ -92,16 +90,15 @@ The name `".md"` is no longer valid for a processor, so it must be replaced with
```js
const plugin = {
- configs: {},
- rules: {},
- processors: {
-
- // works in both old and new config systems
- "markdown": {
- preprocess() {},
- postprocess() {}
- }
- }
+ configs: {},
+ rules: {},
+ processors: {
+ // works in both old and new config systems
+ markdown: {
+ preprocess() {},
+ postprocess() {},
+ },
+ },
};
// for ESM
@@ -114,16 +111,18 @@ module.exports = plugin;
In order to use this renamed processor, you'll also need to manually specify it inside of a config, such as:
```js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
- {
- plugins: {
- example
- },
- processor: "example/markdown"
- }
-];
+export default defineConfig([
+ {
+ files: ["**/*.md"],
+ plugins: {
+ example,
+ },
+ processor: "example/markdown",
+ },
+]);
```
You should update your plugin's documentation to advise your users if you have renamed a file extension-named processor.
@@ -157,23 +156,23 @@ To migrate to flat config format, you'll need to move the configs to after the d
```js
const plugin = {
- configs: {},
- rules: {},
- processors: {}
+ configs: {},
+ rules: {},
+ processors: {},
};
// assign configs here so we can reference `plugin`
Object.assign(plugin.configs, {
- recommended: {
- plugins: {
- example: plugin
- },
- rules: {
- "example/rule1": "error",
- "example/rule2": "error"
- }
- }
-})
+ recommended: {
+ plugins: {
+ example: plugin,
+ },
+ rules: {
+ "example/rule1": "error",
+ "example/rule2": "error",
+ },
+ },
+});
// for ESM
export default plugin;
@@ -185,20 +184,22 @@ module.exports = plugin;
Your users can then use this exported config like this:
```js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
-
- // use recommended config
- example.configs.recommended,
-
- // and provide your own overrides
- {
- rules: {
- "example/rule1": "warn"
- }
- }
-];
+export default defineConfig([
+ // use recommended config and provide your own overrides
+ {
+ files: ["**/*.js"],
+ plugins: {
+ example,
+ },
+ extends: ["example/recommended"],
+ rules: {
+ "example/rule1": "warn",
+ },
+ },
+]);
```
If your config extends other configs, you can export an array:
@@ -207,35 +208,22 @@ If your config extends other configs, you can export an array:
const baseConfig = require("./base-config");
module.exports = {
- configs: {
- extendedConfig: [
- baseConfig,
- {
- rules: {
- "example/rule1": "error",
- "example/rule2": "error"
- }
- }
- ],
- },
+ configs: {
+ extendedConfig: [
+ baseConfig,
+ {
+ rules: {
+ "example/rule1": "error",
+ "example/rule2": "error",
+ },
+ },
+ ],
+ },
};
```
You should update your documentation so your plugin users know how to reference the exported configs.
-If your exported config is an object, then your users can insert it directly into the config array; if your exported config is an array, then your users should use the spread operator (`...`) to insert the array's items into the config array.
-
-Here's an example with both an object config and an array config:
-
-```js
-import example from "eslint-plugin-example";
-
-export default [
- example.configs.recommended, // Object, so don't spread
- ...example.configs.extendedConfig, // Array, so needs spreading
-];
-```
-
For more information, see the [full documentation](https://eslint.org/docs/latest/extend/plugins#configs-in-plugins).
## Migrating Environments for Flat Config
@@ -266,24 +254,24 @@ To migrate this environment into a config, you need to add a new key in the `plu
```js
const plugin = {
- configs: {},
- rules: {},
- processors: {}
+ configs: {},
+ rules: {},
+ processors: {},
};
// assign configs here so we can reference `plugin`
Object.assign(plugin.configs, {
- mocha: {
- languageOptions: {
- globals: {
- it: "writeable",
- xit: "writeable",
- describe: "writeable",
- xdescribe: "writeable"
- }
- }
- }
-})
+ mocha: {
+ languageOptions: {
+ globals: {
+ it: "writeable",
+ xit: "writeable",
+ describe: "writeable",
+ xdescribe: "writeable",
+ },
+ },
+ },
+});
// for ESM
export default plugin;
@@ -295,22 +283,27 @@ module.exports = plugin;
Your users can then use this exported config like this:
```js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
-
- // use the mocha globals
- example.configs.mocha,
-
- // and provide your own overrides
- {
- languageOptions: {
- globals: {
- it: "readonly"
- }
- }
- }
-];
+export default defineConfig([
+ {
+ files: ["**/tests/*.js"],
+ plugins: {
+ example,
+ },
+
+ // use the mocha globals
+ extends: ["example/mocha"],
+
+ // and provide your own overrides
+ languageOptions: {
+ globals: {
+ it: "readonly",
+ },
+ },
+ },
+]);
```
You should update your documentation so your plugin users know how to reference the exported configs.
@@ -325,6 +318,6 @@ If your plugin needs to work with both the old and new configuration systems, th
## Further Reading
-* [Overview of the flat config file format blog post](https://eslint.org/blog/2022/08/new-config-system-part-2/)
-* [API usage of new configuration system blog post](https://eslint.org/blog/2022/08/new-config-system-part-3/)
-* [Background to new configuration system blog post](https://eslint.org/blog/2022/08/new-config-system-part-1/)
+- [Overview of the flat config file format blog post](https://eslint.org/blog/2022/08/new-config-system-part-2/)
+- [API usage of new configuration system blog post](https://eslint.org/blog/2022/08/new-config-system-part-3/)
+- [Background to new configuration system blog post](https://eslint.org/blog/2022/08/new-config-system-part-1/)
diff --git a/docs/src/extend/plugins.md b/docs/src/extend/plugins.md
index 65d5426d776b..54d9c3597074 100644
--- a/docs/src/extend/plugins.md
+++ b/docs/src/extend/plugins.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: extend eslint
title: Create Plugins
order: 2
-
---
ESLint plugins extend ESLint with additional functionality. In most cases, you'll extend ESLint by creating plugins that encapsulate the additional functionality you want to share across multiple projects.
@@ -14,19 +13,19 @@ ESLint plugins extend ESLint with additional functionality. In most cases, you'l
A plugin is a JavaScript object that exposes certain properties to ESLint:
-* `meta` - information about the plugin.
-* `configs` - an object containing named configurations.
-* `rules` - an object containing the definitions of custom rules.
-* `processors` - an object containing named processors.
+- `meta` - information about the plugin.
+- `configs` - an object containing named configurations.
+- `rules` - an object containing the definitions of custom rules.
+- `processors` - an object containing named processors.
To get started, create a JavaScript file and export an object containing the properties you'd like ESLint to use. To make your plugin as easy to maintain as possible, we recommend that you format your plugin entrypoint file to look like this:
```js
const plugin = {
- meta: {},
- configs: {},
- rules: {},
- processors: {}
+ meta: {},
+ configs: {},
+ rules: {},
+ processors: {},
};
// for ESM
@@ -44,15 +43,14 @@ For easier debugging and more effective caching of plugins, it's recommended to
```js
const plugin = {
-
- // preferred location of name and version
- meta: {
- name: "eslint-plugin-example",
- version: "1.2.3"
- },
- rules: {
- // add rules here
- }
+ // preferred location of name and version
+ meta: {
+ name: "eslint-plugin-example",
+ version: "1.2.3",
+ },
+ rules: {
+ // add rules here
+ },
};
// for ESM
@@ -67,18 +65,19 @@ The `meta.name` property should match the npm package name for your plugin and t
```js
import fs from "fs";
-const pkg = JSON.parse(fs.readFileSync(new URL("./package.json", import.meta.url), "utf8"));
+const pkg = JSON.parse(
+ fs.readFileSync(new URL("./package.json", import.meta.url), "utf8"),
+);
const plugin = {
-
- // preferred location of name and version
- meta: {
- name: pkg.name,
- version: pkg.version
- },
- rules: {
- // add rules here
- }
+ // preferred location of name and version
+ meta: {
+ name: pkg.name,
+ version: pkg.version,
+ },
+ rules: {
+ // add rules here
+ },
};
export default plugin;
@@ -87,21 +86,20 @@ export default plugin;
::: tip
While there are no restrictions on plugin names, it helps others to find your plugin on [npm](https://npmjs.com) when you follow these naming conventions:
-* **Unscoped:** If your npm package name won't be scoped (doesn't begin with `@`), then the plugin name should begin with `eslint-plugin-`, such as `eslint-plugin-example`.
-* **Scoped:** If your npm package name will be scoped, then the plugin name should be in the format of `@/eslint-plugin-` such as `@jquery/eslint-plugin-jquery` or even `@/eslint-plugin` such as `@jquery/eslint-plugin`.
-:::
+- **Unscoped:** If your npm package name won't be scoped (doesn't begin with `@`), then the plugin name should begin with `eslint-plugin-`, such as `eslint-plugin-example`.
+- **Scoped:** If your npm package name will be scoped, then the plugin name should be in the format of `@/eslint-plugin-` such as `@jquery/eslint-plugin-jquery` or even `@/eslint-plugin` such as `@jquery/eslint-plugin`.
+ :::
As an alternative, you can also expose `name` and `version` properties at the root of your plugin, such as:
```js
const plugin = {
-
- // alternate location of name and version
- name: "eslint-plugin-example",
- version: "1.2.3",
- rules: {
- // add rules here
- }
+ // alternate location of name and version
+ name: "eslint-plugin-example",
+ version: "1.2.3",
+ rules: {
+ // add rules here
+ },
};
// for ESM
@@ -121,17 +119,17 @@ Plugins can expose custom rules for use in ESLint. To do so, the plugin must exp
```js
const plugin = {
- meta: {
- name: "eslint-plugin-example",
- version: "1.2.3"
- },
- rules: {
- "dollar-sign": {
- create(context) {
- // rule implementation ...
- }
- }
- }
+ meta: {
+ name: "eslint-plugin-example",
+ version: "1.2.3",
+ },
+ rules: {
+ "dollar-sign": {
+ create(context) {
+ // rule implementation ...
+ },
+ },
+ },
};
// for ESM
@@ -145,18 +143,19 @@ In order to use a rule from a plugin in a configuration file, import the plugin
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
- {
- plugins: {
- example
- },
- rules: {
- "example/dollar-sign": "error"
- }
- }
-];
+export default defineConfig([
+ {
+ plugins: {
+ example,
+ },
+ rules: {
+ "example/dollar-sign": "error",
+ },
+ },
+]);
```
::: warning
@@ -169,16 +168,20 @@ Plugins can expose [processors](custom-processors) for use in configuration file
```js
const plugin = {
- meta: {
- name: "eslint-plugin-example",
- version: "1.2.3"
- },
- processors: {
- "processor-name": {
- preprocess(text, filename) {/* ... */},
- postprocess(messages, filename) { /* ... */ },
- }
- }
+ meta: {
+ name: "eslint-plugin-example",
+ version: "1.2.3",
+ },
+ processors: {
+ "processor-name": {
+ preprocess(text, filename) {
+ /* ... */
+ },
+ postprocess(messages, filename) {
+ /* ... */
+ },
+ },
+ },
};
// for ESM
@@ -192,16 +195,18 @@ In order to use a processor from a plugin in a configuration file, import the pl
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
- {
- plugins: {
- example
- },
- processor: "example/processor-name"
- }
-];
+export default defineConfig([
+ {
+ files: ["**/*.txt"],
+ plugins: {
+ example,
+ },
+ processor: "example/processor-name",
+ },
+]);
```
### Configs in Plugins
@@ -212,40 +217,42 @@ You can include individual rules from a plugin in a config that's also included
```js
const plugin = {
- meta: {
- name: "eslint-plugin-example",
- version: "1.2.3"
- },
- configs: {},
- rules: {
- "dollar-sign": {
- create(context) {
- // rule implementation ...
- }
- }
- }
+ meta: {
+ name: "eslint-plugin-example",
+ version: "1.2.3",
+ },
+ configs: {},
+ rules: {
+ "dollar-sign": {
+ create(context) {
+ // rule implementation ...
+ },
+ },
+ },
};
// assign configs here so we can reference `plugin`
Object.assign(plugin.configs, {
- recommended: [{
- plugins: {
- example: plugin
- },
- rules: {
- "example/dollar-sign": "error"
- },
- languageOptions: {
- globals: {
- myGlobal: "readonly"
- },
- parserOptions: {
- ecmaFeatures: {
- jsx: true
- }
- }
- }
- }]
+ recommended: [
+ {
+ plugins: {
+ example: plugin,
+ },
+ rules: {
+ "example/dollar-sign": "error",
+ },
+ languageOptions: {
+ globals: {
+ myGlobal: "readonly",
+ },
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ },
+ },
+ ],
});
// for ESM
@@ -257,21 +264,100 @@ module.exports = plugin;
This plugin exports a `recommended` config that is an array with one config object. When there is just one config object, you can also export just the object without an enclosing array.
-In order to use a config from a plugin in a configuration file, import the plugin and access the config directly through the plugin object. Assuming the config is an array, use the spread operator to add it into the array returned from the configuration file, like this:
+In order to use a config from a plugin in a configuration file, import the plugin and use the `extends` key to reference the name of the config, like this:
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
-export default [
- ...example.configs.recommended
-];
+export default defineConfig([
+ {
+ files: ["**/*.js"], // any patterns you want to apply the config to
+ plugins: {
+ example,
+ },
+ extends: ["example/recommended"],
+ },
+]);
```
::: important
Plugins cannot force a specific configuration to be used. Users must manually include a plugin's configurations in their configuration file.
:::
+#### Backwards Compatibility for Legacy Configs
+
+If your plugin needs to export configs that work both with the current (flat config) system and the old (eslintrc) system, you can export both config types from the `configs` key. When exporting legacy configs, we recommend prefixing the name with `"legacy-"` (for example, `"legacy-recommended"`) to make it clear how the config should be used.
+
+If you're working on a plugin that has existed prior to ESLint v9.0.0, then you may already have legacy configs with names such as `"recommended"`. If you don't want to update the config name, you can also create an additional entry in the `configs` object prefixed with `"flat/"` (for example, `"flat/recommended"`). Here's an example:
+
+```js
+const plugin = {
+ meta: {
+ name: "eslint-plugin-example",
+ version: "1.2.3",
+ },
+ configs: {},
+ rules: {
+ "dollar-sign": {
+ create(context) {
+ // rule implementation ...
+ },
+ },
+ },
+};
+
+// assign configs here so we can reference `plugin`
+Object.assign(plugin.configs, {
+ // flat config format
+ "flat/recommended": [
+ {
+ plugins: {
+ example: plugin,
+ },
+ rules: {
+ "example/dollar-sign": "error",
+ },
+ languageOptions: {
+ globals: {
+ myGlobal: "readonly",
+ },
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ },
+ },
+ ],
+
+ // eslintrc format
+ recommended: {
+ plugins: ["example"],
+ rules: {
+ "example/dollar-sign": "error",
+ },
+ globals: {
+ myGlobal: "readonly",
+ },
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ },
+});
+
+// for ESM
+export default plugin;
+
+// OR for CommonJS
+module.exports = plugin;
+```
+
+With this approach, both configuration systems recognize `"recommended"`. The old config system uses the `recommended` key while the current config system uses the `flat/recommended` key. The `defineConfig()` helper first looks at the `recommended` key, and if that is not in the correct format, it looks for the `flat/recommended` key. This allows you an upgrade path if you'd later like to rename `flat/recommended` to `recommended` when you no longer need to support the old config system.
+
## Testing a Plugin
ESLint provides the [`RuleTester`](../integrate/nodejs-api#ruletester) utility to make it easy to test the rules of your plugin.
@@ -280,9 +366,9 @@ ESLint provides the [`RuleTester`](../integrate/nodejs-api#ruletester) utility t
ESLint plugins should be linted too! It's suggested to lint your plugin with the `recommended` configurations of:
-* [eslint](https://www.npmjs.com/package/eslint)
-* [eslint-plugin-eslint-plugin](https://www.npmjs.com/package/eslint-plugin-eslint-plugin)
-* [eslint-plugin-n](https://www.npmjs.com/package/eslint-plugin-n)
+- [eslint](https://www.npmjs.com/package/eslint)
+- [eslint-plugin-eslint-plugin](https://www.npmjs.com/package/eslint-plugin-eslint-plugin)
+- [eslint-plugin-n](https://www.npmjs.com/package/eslint-plugin-n)
## Share Plugins
@@ -292,9 +378,9 @@ In order to make your plugin available publicly, you have to publish it on npm.
```json
{
- "peerDependencies": {
- "eslint": ">=9.0.0"
- }
+ "peerDependencies": {
+ "eslint": ">=9.0.0"
+ }
}
```
diff --git a/docs/src/extend/rule-deprecation.md b/docs/src/extend/rule-deprecation.md
index 4a64fdbb4b5f..ae49166335ff 100644
--- a/docs/src/extend/rule-deprecation.md
+++ b/docs/src/extend/rule-deprecation.md
@@ -1,7 +1,7 @@
---
title: Rule Deprecation
-
---
+
The rule deprecation metadata describes whether a rule is deprecated and how the rule can be replaced if there is a replacement.
The legacy format used the two top-level [rule meta](./custom-rules#rule-structure) properties `deprecated: true` and `replacedBy`.
In the new format `deprecated` is an object of type `DeprecatedInfo` and `replacedBy` should be defined inside `deprecated` instead of the top-level.
@@ -11,42 +11,42 @@ In the new format `deprecated` is an object of type `DeprecatedInfo` and `replac
This type represents general information about a rule deprecation.
Every property is optional.
-* `message` (`string`)
- A general message presentable to the user. May contain why this rule is deprecated or how to replace the rule.
-* `url` (`string`)
- An URL with more information about this rule deprecation.
-* `replacedBy` (`ReplacedByInfo[]`)
- Information about the available replacements for the rule.
- This may be an empty array to explicitly state there is no replacement.
-* `deprecatedSince` (`string`)
- [Semver](https://semver.org/) of the version deprecating the rule.
-* `availableUntil` (`string | null`)
- [Semver](https://semver.org/) of the version likely to remove the rule, e.g. the next major version.
- The special value `null` means the rule will no longer be changed but will be kept available.
+- `message` (`string`)
+ A general message presentable to the user. May contain why this rule is deprecated or how to replace the rule.
+- `url` (`string`)
+ An URL with more information about this rule deprecation.
+- `replacedBy` (`ReplacedByInfo[]`)
+ Information about the available replacements for the rule.
+ This may be an empty array to explicitly state there is no replacement.
+- `deprecatedSince` (`string`)
+ [Semver](https://semver.org/) of the version deprecating the rule.
+- `availableUntil` (`string | null`)
+ [Semver](https://semver.org/) of the version likely to remove the rule, e.g. the next major version.
+ The special value `null` means the rule will no longer be changed but will be kept available.
## â ReplacedByInfo type
The type describes a single possible replacement of a rule.
Every property is optional.
-* `message` (`string`)
- A general message about this rule replacement, e.g.
-* `url` (`string`)
- An URL with more information about this rule replacement.
-* `plugin` (`ExternalSpecifier`)
- Specifies which plugin has the replacement rule.
- The name should be the package name and should be "eslint" if the replacement is an ESLint core rule.
- This property should be omitted if the replacement is in the same plugin.
-* `rule` (`ExternalSpecifier`)
- Specifies the replacement rule.
- May be omitted if the plugin only contains a single rule or has the same name as the rule.
+- `message` (`string`)
+ A general message about this rule replacement, e.g.
+- `url` (`string`)
+ An URL with more information about this rule replacement.
+- `plugin` (`ExternalSpecifier`)
+ Specifies which plugin has the replacement rule.
+ The name should be the package name and should be "eslint" if the replacement is an ESLint core rule.
+ This property should be omitted if the replacement is in the same plugin.
+- `rule` (`ExternalSpecifier`)
+ Specifies the replacement rule.
+ May be omitted if the plugin only contains a single rule or has the same name as the rule.
### â ExternalSpecifier type
This type represents an external resource.
Every property is optional.
-* `name` (`string`)
- The package name for `plugin` and the rule id for `rule`.
-* `url` (`string`)
- An URL pointing to documentation for the plugin / rule..
+- `name` (`string`)
+ The package name for `plugin` and the rule id for `rule`.
+- `url` (`string`)
+ An URL pointing to documentation for the plugin / rule..
diff --git a/docs/src/extend/scope-manager-interface.md b/docs/src/extend/scope-manager-interface.md
index 65a9afda486b..7d09d5184a03 100644
--- a/docs/src/extend/scope-manager-interface.md
+++ b/docs/src/extend/scope-manager-interface.md
@@ -1,11 +1,10 @@
---
title: ScopeManager
-
---
This document was written based on the implementation of [eslint-scope](https://github.com/eslint/js/tree/main/packages/eslint-scope), a fork of [escope](https://github.com/estools/escope), and deprecates some members ESLint is not using.
-----
+---
## ScopeManager interface
@@ -15,30 +14,30 @@ This document was written based on the implementation of [eslint-scope](https://
#### scopes
-* **Type:** `Scope[]`
-* **Description:** All scopes.
+- **Type:** `Scope[]`
+- **Description:** All scopes.
#### globalScope
-* **Type:** `Scope`
-* **Description:** The root scope.
+- **Type:** `Scope`
+- **Description:** The root scope.
### Methods
#### acquire(node, inner = false)
-* **Parameters:**
- * `node` (`ASTNode`) ... An AST node to get their scope.
- * `inner` (`boolean`) ... If the node has multiple scope, this returns the outermost scope normally. If `inner` is `true` then this returns the innermost scope. Default is `false`.
-* **Return type:** `Scope | null`
-* **Description:** Get the scope of a given AST node. The gotten scope's `block` property is the node. This method never returns `function-expression-name` scope. If the node does not have their scope, this returns `null`.
+- **Parameters:**
+ - `node` (`ASTNode`) ... An AST node to get their scope.
+ - `inner` (`boolean`) ... If the node has multiple scope, this returns the outermost scope normally. If `inner` is `true` then this returns the innermost scope. Default is `false`.
+- **Return type:** `Scope | null`
+- **Description:** Get the scope of a given AST node. The gotten scope's `block` property is the node. This method never returns `function-expression-name` scope. If the node does not have their scope, this returns `null`.
#### getDeclaredVariables(node)
-* **Parameters:**
- * `node` (`ASTNode`) ... An AST node to get their variables.
-* **Return type:** `Variable[]`
-* **Description:** Get the variables that a given AST node defines. The gotten variables' `def[].node`/`def[].parent` property is the node. If the node does not define any variable, this returns an empty array.
+- **Parameters:**
+ - `node` (`ASTNode`) ... An AST node to get their variables.
+- **Return type:** `Variable[]`
+- **Description:** Get the variables that a given AST node defines. The gotten variables' `def[].node`/`def[].parent` property is the node. If the node does not define any variable, this returns an empty array.
### Deprecated members
@@ -46,30 +45,30 @@ Those members are defined but not used in ESLint.
#### isModule()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this program is module.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this program is module.
#### isImpliedStrict()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this program is strict mode implicitly. I.e., `options.impliedStrict === true`.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this program is strict mode implicitly. I.e., `options.impliedStrict === true`.
#### isStrictModeSupported()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this program supports strict mode. I.e., `options.ecmaVersion >= 5`.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this program supports strict mode. I.e., `options.ecmaVersion >= 5`.
#### acquireAll(node)
-* **Parameters:**
- * `node` (`ASTNode`) ... An AST node to get their scope.
-* **Return type:** `Scope[] | null`
-* **Description:** Get the scopes of a given AST node. The gotten scopes' `block` property is the node. If the node does not have their scope, this returns `null`.
+- **Parameters:**
+ - `node` (`ASTNode`) ... An AST node to get their scope.
+- **Return type:** `Scope[] | null`
+- **Description:** Get the scopes of a given AST node. The gotten scopes' `block` property is the node. If the node does not have their scope, this returns `null`.
-----
+---
## Scope interface
@@ -79,60 +78,60 @@ Those members are defined but not used in ESLint.
#### type
-* **Type:** `string`
-* **Description:** The type of this scope. This is one of `"block"`, `"catch"`, `"class"`, `"class-field-initializer"`, `"class-static-block"`, `"for"`, `"function"`, `"function-expression-name"`, `"global"`, `"module"`, `"switch"`, `"with"`.
+- **Type:** `string`
+- **Description:** The type of this scope. This is one of `"block"`, `"catch"`, `"class"`, `"class-field-initializer"`, `"class-static-block"`, `"for"`, `"function"`, `"function-expression-name"`, `"global"`, `"module"`, `"switch"`, `"with"`.
#### isStrict
-* **Type:** `boolean`
-* **Description:** `true` if this scope is strict mode.
+- **Type:** `boolean`
+- **Description:** `true` if this scope is strict mode.
#### upper
-* **Type:** `Scope | null`
-* **Description:** The parent scope. If this is the global scope then this property is `null`.
+- **Type:** `Scope | null`
+- **Description:** The parent scope. If this is the global scope then this property is `null`.
#### childScopes
-* **Type:** `Scope[]`
-* **Description:** The array of child scopes. This does not include grandchild scopes.
+- **Type:** `Scope[]`
+- **Description:** The array of child scopes. This does not include grandchild scopes.
#### variableScope
-* **Type:** `Scope`
-* **Description:** The nearest ancestor whose `type` is one of `"class-field-initializer"`, `"class-static-block"`, `"function"`, `"global"`, or `"module"`. For the aforementioned scopes this is a self-reference.
+- **Type:** `Scope`
+- **Description:** The nearest ancestor whose `type` is one of `"class-field-initializer"`, `"class-static-block"`, `"function"`, `"global"`, or `"module"`. For the aforementioned scopes this is a self-reference.
> This represents the lowest enclosing function or top-level scope. Class field initializers and class static blocks are implicit functions. Historically, this was the scope which hosts variables that are defined by `var` declarations, and thus the name `variableScope`.
#### block
-* **Type:** `ASTNode`
-* **Description:** The AST node which created this scope.
+- **Type:** `ASTNode`
+- **Description:** The AST node which created this scope.
#### variables
-* **Type:** `Variable[]`
-* **Description:** The array of all variables which are defined on this scope. This does not include variables which are defined in child scopes.
+- **Type:** `Variable[]`
+- **Description:** The array of all variables which are defined on this scope. This does not include variables which are defined in child scopes.
#### set
-* **Type:** `Map`
-* **Description:** The map from variable names to variable objects.
+- **Type:** `Map`
+- **Description:** The map from variable names to variable objects.
#### references
-* **Type:** `Reference[]`
-* **Description:** The array of all references on this scope. This does not include references in child scopes.
+- **Type:** `Reference[]`
+- **Description:** The array of all references on this scope. This does not include references in child scopes.
#### through
-* **Type:** `Reference[]`
-* **Description:** The array of references which could not be resolved in this scope.
+- **Type:** `Reference[]`
+- **Description:** The array of references which could not be resolved in this scope.
#### functionExpressionScope
-* **Type:** `boolean`
-* **Description:** `true` if this scope is `"function-expression-name"` scope.
+- **Type:** `boolean`
+- **Description:** `true` if this scope is `"function-expression-name"` scope.
### Deprecated members
@@ -140,57 +139,57 @@ Those members are defined but not used in ESLint.
#### taints
-* **Type:** `Map`
-* **Description:** The map from variable names to `tainted` flag.
+- **Type:** `Map`
+- **Description:** The map from variable names to `tainted` flag.
#### dynamic
-* **Type:** `boolean`
-* **Description:** `true` if this scope is dynamic. I.e., the type of this scope is `"global"` or `"with"`.
+- **Type:** `boolean`
+- **Description:** `true` if this scope is dynamic. I.e., the type of this scope is `"global"` or `"with"`.
#### directCallToEvalScope
-* **Type:** `boolean`
-* **Description:** `true` if this scope contains `eval()` invocations.
+- **Type:** `boolean`
+- **Description:** `true` if this scope contains `eval()` invocations.
#### thisFound
-* **Type:** `boolean`
-* **Description:** `true` if this scope contains `this`.
+- **Type:** `boolean`
+- **Description:** `true` if this scope contains `this`.
#### resolve(node)
-* **Parameters:**
- * `node` (`ASTNode`) ... An AST node to get their reference object. The type of the node must be `"Identifier"`.
-* **Return type:** `Reference | null`
-* **Description:** Returns `this.references.find(r => r.identifier === node)`.
+- **Parameters:**
+ - `node` (`ASTNode`) ... An AST node to get their reference object. The type of the node must be `"Identifier"`.
+- **Return type:** `Reference | null`
+- **Description:** Returns `this.references.find(r => r.identifier === node)`.
#### isStatic()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** Returns `!this.dynamic`.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** Returns `!this.dynamic`.
#### isArgumentsMaterialized()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this is a `"function"` scope which has used `arguments` variable.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this is a `"function"` scope which has used `arguments` variable.
#### isThisMaterialized()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** Returns `this.thisFound`.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** Returns `this.thisFound`.
#### isUsedName(name)
-* **Parameters:**
- * `name` (`string`) ... The name to check.
-* **Return type:** `boolean`
-* **Description:** `true` if a given name is used in variable names or reference names.
+- **Parameters:**
+ - `name` (`string`) ... The name to check.
+- **Return type:** `boolean`
+- **Description:** `true` if a given name is used in variable names or reference names.
-----
+---
## Variable interface
@@ -200,28 +199,28 @@ Those members are defined but not used in ESLint.
#### name
-* **Type:** `string`
-* **Description:** The name of this variable.
+- **Type:** `string`
+- **Description:** The name of this variable.
#### scope
-* **Type:** `Scope`
-* **Description:** The scope in which this variable is defined.
+- **Type:** `Scope`
+- **Description:** The scope in which this variable is defined.
#### identifiers
-* **Type:** `ASTNode[]`
-* **Description:** The array of `Identifier` nodes which define this variable. If this variable is redeclared, this array includes two or more nodes.
+- **Type:** `ASTNode[]`
+- **Description:** The array of `Identifier` nodes which define this variable. If this variable is redeclared, this array includes two or more nodes.
#### references
-* **Type:** `Reference[]`
-* **Description:** The array of the references of this variable.
+- **Type:** `Reference[]`
+- **Description:** The array of the references of this variable.
#### defs
-* **Type:** `Definition[]`
-* **Description:** The array of the definitions of this variable.
+- **Type:** `Definition[]`
+- **Description:** The array of the definitions of this variable.
### Deprecated members
@@ -229,15 +228,15 @@ Those members are defined but not used in ESLint.
#### tainted
-* **Type:** `boolean`
-* **Description:** The `tainted` flag. (always `false`)
+- **Type:** `boolean`
+- **Description:** The `tainted` flag. (always `false`)
#### stack
-* **Type:** `boolean`
-* **Description:** The `stack` flag. (I'm not sure what this means.)
+- **Type:** `boolean`
+- **Description:** The `stack` flag. (I'm not sure what this means.)
-----
+---
## Reference interface
@@ -247,60 +246,60 @@ Those members are defined but not used in ESLint.
#### identifier
-* **Type:** `ASTNode`
-* **Description:** The `Identifier` node of this reference.
+- **Type:** `ASTNode`
+- **Description:** The `Identifier` node of this reference.
#### from
-* **Type:** `Scope`
-* **Description:** The `Scope` object that this reference is on.
+- **Type:** `Scope`
+- **Description:** The `Scope` object that this reference is on.
#### resolved
-* **Type:** `Variable | null`
-* **Description:** The `Variable` object that this reference refers. If such variable was not defined, this is `null`.
+- **Type:** `Variable | null`
+- **Description:** The `Variable` object that this reference refers. If such variable was not defined, this is `null`.
#### writeExpr
-* **Type:** `ASTNode | null`
-* **Description:** The ASTNode object which is right-hand side.
+- **Type:** `ASTNode | null`
+- **Description:** The ASTNode object which is right-hand side.
#### init
-* **Type:** `boolean`
-* **Description:** `true` if this writing reference is a variable initializer or a default value.
+- **Type:** `boolean`
+- **Description:** `true` if this writing reference is a variable initializer or a default value.
### Methods
#### isWrite()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this reference is writing.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this reference is writing.
#### isRead()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this reference is reading.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this reference is reading.
#### isWriteOnly()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this reference is writing but not reading.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this reference is writing but not reading.
#### isReadOnly()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this reference is reading but not writing.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this reference is reading but not writing.
#### isReadWrite()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this reference is reading and writing.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this reference is reading and writing.
### Deprecated members
@@ -308,26 +307,26 @@ Those members are defined but not used in ESLint.
#### tainted
-* **Type:** `boolean`
-* **Description:** The `tainted` flag. (always `false`)
+- **Type:** `boolean`
+- **Description:** The `tainted` flag. (always `false`)
#### flag
-* **Type:** `number`
-* **Description:** `1` is reading, `2` is writing, `3` is reading/writing.
+- **Type:** `number`
+- **Description:** `1` is reading, `2` is writing, `3` is reading/writing.
#### partial
-* **Type:** `boolean`
-* **Description:** The `partial` flag.
+- **Type:** `boolean`
+- **Description:** The `partial` flag.
#### isStatic()
-* **Parameters:**
-* **Return type:** `boolean`
-* **Description:** `true` if this reference is resolved statically.
+- **Parameters:**
+- **Return type:** `boolean`
+- **Description:** `true` if this reference is resolved statically.
-----
+---
## Definition interface
@@ -337,42 +336,42 @@ Those members are defined but not used in ESLint.
#### type
-* **Type:** `string`
-* **Description:** The type of this definition. One of `"CatchClause"`, `"ClassName"`, `"FunctionName"`, `"ImplicitGlobalVariable"`, `"ImportBinding"`, `"Parameter"`, and `"Variable"`.
+- **Type:** `string`
+- **Description:** The type of this definition. One of `"CatchClause"`, `"ClassName"`, `"FunctionName"`, `"ImplicitGlobalVariable"`, `"ImportBinding"`, `"Parameter"`, and `"Variable"`.
#### name
-* **Type:** `ASTNode`
-* **Description:** The `Identifier` node of this definition.
+- **Type:** `ASTNode`
+- **Description:** The `Identifier` node of this definition.
#### node
-* **Type:** `ASTNode`
-* **Description:** The enclosing node of the name.
+- **Type:** `ASTNode`
+- **Description:** The enclosing node of the name.
-| type | node |
-|:---------------------------|:-----|
-| `"CatchClause"` | `CatchClause` |
-| `"ClassName"` | `ClassDeclaration` or `ClassExpression` |
-| `"FunctionName"` | `FunctionDeclaration` or `FunctionExpression` |
-| `"ImplicitGlobalVariable"` | `Program` |
+| type | node |
+| :------------------------- | :------------------------------------------------------------------------- |
+| `"CatchClause"` | `CatchClause` |
+| `"ClassName"` | `ClassDeclaration` or `ClassExpression` |
+| `"FunctionName"` | `FunctionDeclaration` or `FunctionExpression` |
+| `"ImplicitGlobalVariable"` | `Program` |
| `"ImportBinding"` | `ImportSpecifier`, `ImportDefaultSpecifier`, or `ImportNamespaceSpecifier` |
-| `"Parameter"` | `FunctionDeclaration`, `FunctionExpression`, or `ArrowFunctionExpression` |
-| `"Variable"` | `VariableDeclarator` |
+| `"Parameter"` | `FunctionDeclaration`, `FunctionExpression`, or `ArrowFunctionExpression` |
+| `"Variable"` | `VariableDeclarator` |
#### parent
-* **Type:** `ASTNode | undefined | null`
-* **Description:** The enclosing statement node of the name.
-
-| type | parent |
-|:---------------------------|:-------|
-| `"CatchClause"` | `null` |
-| `"ClassName"` | `null` |
-| `"FunctionName"` | `null` |
-| `"ImplicitGlobalVariable"` | `null` |
-| `"ImportBinding"` | `ImportDeclaration` |
-| `"Parameter"` | `null` |
+- **Type:** `ASTNode | undefined | null`
+- **Description:** The enclosing statement node of the name.
+
+| type | parent |
+| :------------------------- | :-------------------- |
+| `"CatchClause"` | `null` |
+| `"ClassName"` | `null` |
+| `"FunctionName"` | `null` |
+| `"ImplicitGlobalVariable"` | `null` |
+| `"ImportBinding"` | `ImportDeclaration` |
+| `"Parameter"` | `null` |
| `"Variable"` | `VariableDeclaration` |
### Deprecated members
@@ -381,10 +380,10 @@ Those members are defined but not used in ESLint.
#### index
-* **Type:** `number | undefined | null`
-* **Description:** The index in the declaration statement.
+- **Type:** `number | undefined | null`
+- **Description:** The index in the declaration statement.
#### kind
-* **Type:** `string | undefined | null`
-* **Description:** The kind of the declaration statement.
+- **Type:** `string | undefined | null`
+- **Description:** The kind of the declaration statement.
diff --git a/docs/src/extend/selectors.md b/docs/src/extend/selectors.md
index 5ea700dead10..a1079010b83b 100644
--- a/docs/src/extend/selectors.md
+++ b/docs/src/extend/selectors.md
@@ -1,6 +1,5 @@
---
title: Selectors
-
---
Some rules and APIs allow the use of selectors to query an AST. This page is intended to:
@@ -30,24 +29,24 @@ Selectors are not limited to matching against single node types. For example, th
The following selectors are supported:
-* AST node type: `ForStatement`
-* wildcard (matches all nodes): `*`
-* attribute existence: `[attr]`
-* attribute value: `[attr="foo"]` or `[attr=123]`
-* attribute regex: `[attr=/foo.*/]` (with some [known issues](#known-issues))
-* attribute conditions: `[attr!="foo"]`, `[attr>2]`, `[attr<3]`, `[attr>=2]`, or `[attr<=3]`
-* nested attribute: `[attr.level2="foo"]`
-* field: `FunctionDeclaration > Identifier.id`
-* First or last child: `:first-child` or `:last-child`
-* nth-child (no ax+b support): `:nth-child(2)`
-* nth-last-child (no ax+b support): `:nth-last-child(1)`
-* descendant: `FunctionExpression ReturnStatement`
-* child: `UnaryExpression > Literal`
-* following sibling: `VariableDeclaration ~ VariableDeclaration`
-* adjacent sibling: `ArrayExpression > Literal + SpreadElement`
-* negation: `:not(ForStatement)`
-* matches-any: `:matches([attr] > :first-child, :last-child)`
-* class of AST node: `:statement`, `:expression`, `:declaration`, `:function`, or `:pattern`
+- AST node type: `ForStatement`
+- wildcard (matches all nodes): `*`
+- attribute existence: `[attr]`
+- attribute value: `[attr="foo"]` or `[attr=123]`
+- attribute regex: `[attr=/foo.*/]` (with some [known issues](#known-issues))
+- attribute conditions: `[attr!="foo"]`, `[attr>2]`, `[attr<3]`, `[attr>=2]`, or `[attr<=3]`
+- nested attribute: `[attr.level2="foo"]`
+- field: `FunctionDeclaration > Identifier.id`
+- First or last child: `:first-child` or `:last-child`
+- nth-child (no ax+b support): `:nth-child(2)`
+- nth-last-child (no ax+b support): `:nth-last-child(1)`
+- descendant: `FunctionExpression ReturnStatement`
+- child: `UnaryExpression > Literal`
+- following sibling: `VariableDeclaration ~ VariableDeclaration`
+- adjacent sibling: `ArrayExpression > Literal + SpreadElement`
+- negation: `:not(ForStatement)`
+- matches-any: `:matches([attr] > :first-child, :last-child)`
+- class of AST node: `:statement`, `:expression`, `:declaration`, `:function`, or `:pattern`
This syntax is very powerful, and can be used to precisely select many syntactic patterns in your code.
@@ -63,22 +62,23 @@ When writing a custom ESLint rule, you can listen for nodes that match a particu
```js
module.exports = {
- create(context) {
- // ...
-
- return {
-
- // This listener will be called for all IfStatement nodes with blocks.
- "IfStatement > BlockStatement": function(blockStatementNode) {
- // ...your logic here
- },
-
- // This listener will be called for all function declarations with more than 3 parameters.
- "FunctionDeclaration[params.length>3]": function(functionDeclarationNode) {
- // ...your logic here
- }
- };
- }
+ create(context) {
+ // ...
+
+ return {
+ // This listener will be called for all IfStatement nodes with blocks.
+ "IfStatement > BlockStatement": function (blockStatementNode) {
+ // ...your logic here
+ },
+
+ // This listener will be called for all function declarations with more than 3 parameters.
+ "FunctionDeclaration[params.length>3]": function (
+ functionDeclarationNode,
+ ) {
+ // ...your logic here
+ },
+ };
+ },
};
```
@@ -86,8 +86,8 @@ Adding `:exit` to the end of a selector will cause the listener to be called whe
If two or more selectors match the same node, their listeners will be called in order of increasing specificity. The specificity of an AST selector is similar to the specificity of a CSS selector:
-* When comparing two selectors, the selector that contains more class selectors, attribute selectors, and pseudo-class selectors (excluding `:not()`) has higher specificity.
-* If the class/attribute/pseudo-class count is tied, the selector that contains more node type selectors has higher specificity.
+- When comparing two selectors, the selector that contains more class selectors, attribute selectors, and pseudo-class selectors (excluding `:not()`) has higher specificity.
+- If the class/attribute/pseudo-class count is tied, the selector that contains more node type selectors has higher specificity.
If multiple selectors have equal specificity, their listeners will be called in alphabetical order for that node.
@@ -97,9 +97,12 @@ With the [no-restricted-syntax](../rules/no-restricted-syntax) rule, you can res
```json
{
- "rules": {
- "no-restricted-syntax": ["error", "IfStatement > :not(BlockStatement).consequent"]
- }
+ "rules": {
+ "no-restricted-syntax": [
+ "error",
+ "IfStatement > :not(BlockStatement).consequent"
+ ]
+ }
}
```
@@ -107,9 +110,12 @@ With the [no-restricted-syntax](../rules/no-restricted-syntax) rule, you can res
```json
{
- "rules": {
- "no-restricted-syntax": ["error", "IfStatement[consequent.type!='BlockStatement']"]
- }
+ "rules": {
+ "no-restricted-syntax": [
+ "error",
+ "IfStatement[consequent.type!='BlockStatement']"
+ ]
+ }
}
```
@@ -117,9 +123,12 @@ As another example, you can disallow calls to `require()`:
```json
{
- "rules": {
- "no-restricted-syntax": ["error", "CallExpression[callee.name='require']"]
- }
+ "rules": {
+ "no-restricted-syntax": [
+ "error",
+ "CallExpression[callee.name='require']"
+ ]
+ }
}
```
@@ -127,9 +136,12 @@ Or you can enforce that calls to `setTimeout` always have two arguments:
```json
{
- "rules": {
- "no-restricted-syntax": ["error", "CallExpression[callee.name='setTimeout'][arguments.length!=2]"]
- }
+ "rules": {
+ "no-restricted-syntax": [
+ "error",
+ "CallExpression[callee.name='setTimeout'][arguments.length!=2]"
+ ]
+ }
}
```
@@ -143,9 +155,12 @@ For example, the following configuration disallows importing from `some/path`:
```json
{
- "rules": {
- "no-restricted-syntax": ["error", "ImportDeclaration[source.value=/^some\\u002Fpath$/]"]
- }
+ "rules": {
+ "no-restricted-syntax": [
+ "error",
+ "ImportDeclaration[source.value=/^some\\u002Fpath$/]"
+ ]
+ }
}
```
diff --git a/docs/src/extend/shareable-configs-deprecated.md b/docs/src/extend/shareable-configs-deprecated.md
index 9e73202bba69..ac602aafb858 100644
--- a/docs/src/extend/shareable-configs-deprecated.md
+++ b/docs/src/extend/shareable-configs-deprecated.md
@@ -16,23 +16,21 @@ Shareable configs are simply npm packages that export a configuration object. To
The module name must take one of the following forms:
-* Begin with `eslint-config-`, such as `eslint-config-myconfig`.
-* Be an npm [scoped module](https://docs.npmjs.com/misc/scope). To create a scoped module, name or prefix the module with `@scope/eslint-config`, such as `@scope/eslint-config` or `@scope/eslint-config-myconfig`.
+- Begin with `eslint-config-`, such as `eslint-config-myconfig`.
+- Be an npm [scoped module](https://docs.npmjs.com/misc/scope). To create a scoped module, name or prefix the module with `@scope/eslint-config`, such as `@scope/eslint-config` or `@scope/eslint-config-myconfig`.
In your module, export the shareable config from the module's [`main`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#main) entry point file. The default main entry point is `index.js`. For example:
```js
// index.js
module.exports = {
+ globals: {
+ MyGlobal: true,
+ },
- globals: {
- MyGlobal: true
- },
-
- rules: {
- semi: [2, "always"]
- }
-
+ rules: {
+ semi: [2, "always"],
+ },
};
```
@@ -46,9 +44,9 @@ You should declare your dependency on ESLint in the `package.json` using the [pe
```json
{
- "peerDependencies": {
- "eslint": ">= 3"
- }
+ "peerDependencies": {
+ "eslint": ">= 3"
+ }
}
```
@@ -74,7 +72,7 @@ To use a shareable config, include the config name in the `extends` field of a c
```json
{
- "extends": "eslint-config-myconfig"
+ "extends": "eslint-config-myconfig"
}
```
@@ -82,7 +80,7 @@ You can also omit the `eslint-config-` and it is automatically assumed by ESLint
```json
{
- "extends": "myconfig"
+ "extends": "myconfig"
}
```
@@ -96,7 +94,7 @@ You can use the module name:
```json
{
- "extends": "@scope/eslint-config"
+ "extends": "@scope/eslint-config"
}
```
@@ -104,7 +102,7 @@ You can also omit the `eslint-config` and it is automatically assumed by ESLint:
```json
{
- "extends": "@scope"
+ "extends": "@scope"
}
```
@@ -112,7 +110,7 @@ The module name can also be customized. For example, if you have a package named
```json
{
- "extends": "@scope/eslint-config-myconfig"
+ "extends": "@scope/eslint-config-myconfig"
}
```
@@ -120,7 +118,7 @@ You could also omit `eslint-config` to specify the configuration as:
```json
{
- "extends": "@scope/myconfig"
+ "extends": "@scope/myconfig"
}
```
@@ -137,9 +135,9 @@ As an example, you can create a file called `my-special-config.js` in the root o
```js
// my-special-config.js
module.exports = {
- rules: {
- quotes: [2, "double"]
- }
+ rules: {
+ quotes: [2, "double"],
+ },
};
```
@@ -147,7 +145,7 @@ Then, assuming you're using the package name `eslint-config-myconfig`, you can a
```json
{
- "extends": "myconfig/my-special-config"
+ "extends": "myconfig/my-special-config"
}
```
@@ -155,7 +153,7 @@ When using [scoped modules](https://docs.npmjs.com/misc/scope) it is not possibl
```json
{
- "extends": "@scope/eslint-config/my-special-config"
+ "extends": "@scope/eslint-config/my-special-config"
}
```
@@ -185,33 +183,33 @@ myconfig
In the `index.js` file, you can do something like this:
```js
-module.exports = require('./lib/ci.js');
+module.exports = require("./lib/ci.js");
```
Now inside the package you have `/lib/defaults.js`, which contains:
```js
module.exports = {
- rules: {
- 'no-console': 1
- }
+ rules: {
+ "no-console": 1,
+ },
};
```
Inside `/lib/ci.js` you have:
```js
-module.exports = require('./ci/backend');
+module.exports = require("./ci/backend");
```
Inside `/lib/ci/common.js`:
```js
module.exports = {
- rules: {
- 'no-alert': 2
- },
- extends: 'myconfig/lib/defaults'
+ rules: {
+ "no-alert": 2,
+ },
+ extends: "myconfig/lib/defaults",
};
```
@@ -221,10 +219,10 @@ Now inside `/lib/ci/backend.js`:
```js
module.exports = {
- rules: {
- 'no-console': 1
- },
- extends: 'myconfig/lib/ci/common'
+ rules: {
+ "no-console": 1,
+ },
+ extends: "myconfig/lib/ci/common",
};
```
@@ -232,4 +230,4 @@ In the last file, once again see that to properly resolve your config, you need
## Further Reading
-* [npm Developer Guide](https://docs.npmjs.com/misc/developers)
+- [npm Developer Guide](https://docs.npmjs.com/misc/developers)
diff --git a/docs/src/extend/shareable-configs.md b/docs/src/extend/shareable-configs.md
index 8076ce2be4aa..9ba3444adfc0 100644
--- a/docs/src/extend/shareable-configs.md
+++ b/docs/src/extend/shareable-configs.md
@@ -5,7 +5,6 @@ eleventyNavigation:
parent: extend eslint
title: Share Configurations
order: 3
-
---
To share your ESLint configuration, create a **shareable config**. You can publish your shareable config on [npm](https://www.npmjs.com/) so that others can download and use it in their ESLint projects.
@@ -22,26 +21,25 @@ Shareable configs are simply npm packages that export a configuration object or
While you can name the package in any way that you'd like, we recommend using one of the following conventions to make your package easier to identify:
-* Begin with `eslint-config-`, such as `eslint-config-myconfig`.
-* For an npm [scoped module](https://docs.npmjs.com/misc/scope), name or prefix the module with `@scope/eslint-config`, such as `@scope/eslint-config` or `@scope/eslint-config-myconfig`.
+- Begin with `eslint-config-`, such as `eslint-config-myconfig`.
+- For an npm [scoped module](https://docs.npmjs.com/misc/scope), name or prefix the module with `@scope/eslint-config`, such as `@scope/eslint-config` or `@scope/eslint-config-myconfig`.
In your module, export the shareable config from the module's [`main`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#main) entry point file. The default main entry point is `index.js`. For example:
```js
// index.js
export default [
- {
- languageOptions: {
- globals: {
- MyGlobal: true
- }
- },
-
- rules: {
- semi: [2, "always"]
- }
-
- }
+ {
+ languageOptions: {
+ globals: {
+ MyGlobal: true,
+ },
+ },
+
+ rules: {
+ semi: [2, "always"],
+ },
+ },
];
```
@@ -59,9 +57,9 @@ You should declare your dependency on ESLint in the `package.json` using the [pe
```json
{
- "peerDependencies": {
- "eslint": ">= 9"
- }
+ "peerDependencies": {
+ "eslint": ">= 9"
+ }
}
```
@@ -69,15 +67,19 @@ If your shareable config depends on a plugin or a custom parser, you should spec
## Using a Shareable Config
-To use a shareable config, import the package inside of an `eslint.config.js` file and add it into the exported array, like this:
+To use a shareable config, import the package inside of an `eslint.config.js` file and add it into the exported array using `extends`, like this:
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import myconfig from "eslint-config-myconfig";
-export default [
- ...myconfig
-];
+export default defineConfig([
+ {
+ files: ["**/*.js"],
+ extends: [myconfig],
+ },
+]);
```
::: warning
@@ -90,18 +92,20 @@ You can override settings from the shareable config by adding them directly into
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import myconfig from "eslint-config-myconfig";
-export default [
- ...myconfig,
-
- // anything from here will override myconfig
- {
- rules: {
- "no-unused-vars": "warn"
- }
- }
-];
+export default defineConfig([
+ {
+ files: ["**/*.js"],
+ extends: [myconfig],
+
+ // anything from here will override myconfig
+ rules: {
+ "no-unused-vars": "warn",
+ },
+ },
+]);
```
## Sharing Multiple Configs
@@ -113,9 +117,9 @@ As an example, you can create a file called `my-special-config.js` in the root o
```js
// my-special-config.js
export default {
- rules: {
- quotes: [2, "double"]
- }
+ rules: {
+ quotes: [2, "double"],
+ },
};
```
@@ -123,20 +127,21 @@ Then, assuming you're using the package name `eslint-config-myconfig`, you can a
```js
// eslint.config.js
+import { defineConfig } from "eslint/config";
import myconfig from "eslint-config-myconfig";
import mySpecialConfig from "eslint-config-myconfig/my-special-config.js";
-export default [
- ...myconfig,
- mySpecialConfig,
-
- // anything from here will override myconfig and mySpecialConfig
- {
- rules: {
- "no-unused-vars": "warn"
- }
- }
-];
+export default defineConfig([
+ {
+ files: ["**/*.js"],
+ extends: [myconfig, mySpecialConfig],
+
+ // anything from here will override myconfig
+ rules: {
+ "no-unused-vars": "warn",
+ },
+ },
+]);
```
::: important
@@ -145,4 +150,4 @@ We strongly recommend always including a default export for your package to avoi
## Further Reading
-* [npm Developer Guide](https://docs.npmjs.com/misc/developers)
+- [npm Developer Guide](https://docs.npmjs.com/misc/developers)
diff --git a/docs/src/extend/stats.md b/docs/src/extend/stats.md
index 1f5541d606f3..b46027a6be4d 100644
--- a/docs/src/extend/stats.md
+++ b/docs/src/extend/stats.md
@@ -9,7 +9,7 @@ eleventyNavigation:
{%- from 'components/npx_tabs.macro.html' import npx_tabs %}
-While an analysis of the overall rule performance for an ESLint run can be carried out by setting the [TIMING](./custom-rules#profile-rule-performance) environment variable, it can sometimes be useful to acquire more *granular* timing data (lint time per file per rule) or collect other measures of interest. In particular, when developing new [custom plugins](./plugins) and evaluating/benchmarking new languages or rule sets. For these use cases, you can optionally collect runtime statistics from ESLint.
+While an analysis of the overall rule performance for an ESLint run can be carried out by setting the [TIMING](./custom-rules#profile-rule-performance) environment variable, it can sometimes be useful to acquire more _granular_ timing data (lint time per file per rule) or collect other measures of interest. In particular, when developing new [custom plugins](./plugins) and evaluating/benchmarking new languages or rule sets. For these use cases, you can optionally collect runtime statistics from ESLint.
## Enable stats collection
@@ -26,18 +26,18 @@ As such, it is not available via stdout but made easily ingestible via a formatt
The `Stats` value is the timing information of each lint run. The `stats` property of the [LintResult](../integrate/nodejs-api#-lintresult-type) type contains it. It has the following properties:
-* `fixPasses` (`number`)
- The number of times ESLint has applied at least one fix after linting.
-* `times` (`{ passes: TimePass[] }`)
- The times spent on (parsing, fixing, linting) a file, where the linting refers to the timing information for each rule.
- * `TimePass` (`{ parse: ParseTime, rules?: Record, fix: FixTime, total: number }`)
- An object containing the times spent on (parsing, fixing, linting)
- * `ParseTime` (`{ total: number }`)
- The total time that is spent when parsing a file.
- * `RuleTime` (`{ total: number }`)
- The total time that is spent on a rule.
- * `FixTime` (`{ total: number }`)
- The total time that is spent on applying fixes to the code.
+- `fixPasses` (`number`)
+ The number of times ESLint has applied at least one fix after linting.
+- `times` (`{ passes: TimePass[] }`)
+ The times spent on (parsing, fixing, linting) a file, where the linting refers to the timing information for each rule.
+ - `TimePass` (`{ parse: ParseTime, rules?: Record, fix: FixTime, total: number }`)
+ An object containing the times spent on (parsing, fixing, linting)
+ - `ParseTime` (`{ total: number }`)
+ The total time that is spent when parsing a file.
+ - `RuleTime` (`{ total: number }`)
+ The total time that is spent on a rule.
+ - `FixTime` (`{ total: number }`)
+ The total time that is spent on applying fixes to the code.
### CLI usage
@@ -47,7 +47,7 @@ Let's consider the following example:
/*eslint no-regex-spaces: "error", wrap-regex: "error"*/
function a() {
- return / foo/.test("bar");
+ return / foo/.test("bar");
}
```
@@ -62,45 +62,45 @@ This yields the following `stats` entry as part of the formatted lint results ob
```json
{
- "times": {
- "passes": [
- {
- "parse": {
- "total": 3.975959
- },
- "rules": {
- "no-regex-spaces": {
- "total": 0.160792
- },
- "wrap-regex": {
- "total": 0.422626
- }
- },
- "fix": {
- "total": 0.080208
- },
- "total": 12.765959
- },
- {
- "parse": {
- "total": 0.623542
- },
- "rules": {
- "no-regex-spaces": {
- "total": 0.043084
- },
- "wrap-regex": {
- "total": 0.007959
- }
- },
- "fix": {
- "total": 0
- },
- "total": 1.148875
- }
- ]
- },
- "fixPasses": 1
+ "times": {
+ "passes": [
+ {
+ "parse": {
+ "total": 3.975959
+ },
+ "rules": {
+ "no-regex-spaces": {
+ "total": 0.160792
+ },
+ "wrap-regex": {
+ "total": 0.422626
+ }
+ },
+ "fix": {
+ "total": 0.080208
+ },
+ "total": 12.765959
+ },
+ {
+ "parse": {
+ "total": 0.623542
+ },
+ "rules": {
+ "no-regex-spaces": {
+ "total": 0.043084
+ },
+ "wrap-regex": {
+ "total": 0.007959
+ }
+ },
+ "fix": {
+ "total": 0
+ },
+ "total": 1.148875
+ }
+ ]
+ },
+ "fixPasses": 1
}
```
@@ -123,20 +123,20 @@ You can achieve the same thing using the Node.js API by passing`stats: true` as
const { ESLint } = require("eslint");
(async function main() {
- // 1. Create an instance.
- const eslint = new ESLint({ stats: true, fix: true });
+ // 1. Create an instance.
+ const eslint = new ESLint({ stats: true, fix: true });
- // 2. Lint files.
- const results = await eslint.lintFiles(["file-to-fix.js"]);
+ // 2. Lint files.
+ const results = await eslint.lintFiles(["file-to-fix.js"]);
- // 3. Format the results.
- const formatter = await eslint.loadFormatter("json");
- const resultText = formatter.format(results);
+ // 3. Format the results.
+ const formatter = await eslint.loadFormatter("json");
+ const resultText = formatter.format(results);
- // 4. Output it.
- console.log(resultText);
-})().catch((error) => {
- process.exitCode = 1;
- console.error(error);
+ // 4. Output it.
+ console.log(resultText);
+})().catch(error => {
+ process.exitCode = 1;
+ console.error(error);
});
```
diff --git a/docs/src/extend/ways-to-extend.md b/docs/src/extend/ways-to-extend.md
index 2684d340974a..9ec28e1513a3 100644
--- a/docs/src/extend/ways-to-extend.md
+++ b/docs/src/extend/ways-to-extend.md
@@ -23,9 +23,9 @@ For example, [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin
To learn more about creating the extensions you can include in a plugin, refer to the following documentation:
-* [Custom Rules](custom-rules)
-* [Custom Processors](custom-processors)
-* [Configs in Plugins](plugins#configs-in-plugins)
+- [Custom Rules](custom-rules)
+- [Custom Processors](custom-processors)
+- [Configs in Plugins](plugins#configs-in-plugins)
To learn more about bundling these extensions into a plugin, refer to [Plugins](plugins).
diff --git a/docs/src/integrate/index.md b/docs/src/integrate/index.md
index 19164a585308..045c4e65d1c7 100644
--- a/docs/src/integrate/index.md
+++ b/docs/src/integrate/index.md
@@ -4,15 +4,14 @@ eleventyNavigation:
key: integrate eslint
title: integrate ESLint
order: 3
-
---
This guide is intended for those who wish to integrate the functionality of ESLint into other applications by using the ESLint API.
In order to integrate ESLint, it's recommended that:
-* You know JavaScript since ESLint is written in JavaScript.
-* You have some familiarity with Node.js since ESLint runs on it.
+- You know JavaScript since ESLint is written in JavaScript.
+- You have some familiarity with Node.js since ESLint runs on it.
If that sounds like you, then continue reading to get started.
diff --git a/docs/src/integrate/integration-tutorial.md b/docs/src/integrate/integration-tutorial.md
index b4115bda1279..fa1957f839c3 100644
--- a/docs/src/integrate/integration-tutorial.md
+++ b/docs/src/integrate/integration-tutorial.md
@@ -18,28 +18,28 @@ projects.
You might want to create an ESLint integration if you're creating developer
tooling, such as the following:
-* **Code editors and IDEs**: Integrating ESLint with code editors and IDEs can
- provide real-time feedback on code quality and automatically highlight
- potential issues as you type. Many editors already have ESLint plugins
- available, but you may need to create a custom integration if the existing
- plugins do not meet your specific requirements.
+- **Code editors and IDEs**: Integrating ESLint with code editors and IDEs can
+ provide real-time feedback on code quality and automatically highlight
+ potential issues as you type. Many editors already have ESLint plugins
+ available, but you may need to create a custom integration if the existing
+ plugins do not meet your specific requirements.
-* **Custom linter tools**: If you're building a custom linter tool that combines
- multiple linters or adds specific functionality, you may want to integrate
- ESLint into your tool to provide JavaScript linting capabilities.
+- **Custom linter tools**: If you're building a custom linter tool that combines
+ multiple linters or adds specific functionality, you may want to integrate
+ ESLint into your tool to provide JavaScript linting capabilities.
-* **Code review tools**: Integrating ESLint with code review tools can help
- automate the process of identifying potential issues in the codebase.
+- **Code review tools**: Integrating ESLint with code review tools can help
+ automate the process of identifying potential issues in the codebase.
-* **Learning platforms**: If you are developing a learning platform or coding
- tutorial, integrating ESLint can provide real-time feedback to users as they
- learn JavaScript, helping them improve their coding skills and learn best
- practices.
+- **Learning platforms**: If you are developing a learning platform or coding
+ tutorial, integrating ESLint can provide real-time feedback to users as they
+ learn JavaScript, helping them improve their coding skills and learn best
+ practices.
-* **Developer tool integration**: If you're creating or extending a developer
- tool, such as a bundler or testing framework, you may want to integrate ESLint
- to provide linting capabilities. You can integrate ESLint directly into the
- tool or as a plugin.
+- **Developer tool integration**: If you're creating or extending a developer
+ tool, such as a bundler or testing framework, you may want to integrate ESLint
+ to provide linting capabilities. You can integrate ESLint directly into the
+ tool or as a plugin.
## What You'll Build
@@ -52,9 +52,9 @@ This tutorial assumes you are familiar with JavaScript and Node.js.
To follow this tutorial, you'll need to have the following:
-* Node.js (`^18.18.0`, `^20.9.0`, or `>=21.1.0`)
-* npm
-* A text editor
+- Node.js (`^18.18.0`, `^20.9.0`, or `>=21.1.0`)
+- npm
+- A text editor
## Step 1: Setup
@@ -101,11 +101,11 @@ const { ESLint } = require("eslint");
// Create an instance of ESLint with the configuration passed to the function
function createESLintInstance(overrideConfig) {
- return new ESLint({
- overrideConfigFile: true,
- overrideConfig,
- fix: true,
- });
+ return new ESLint({
+ overrideConfigFile: true,
+ overrideConfig,
+ fix: true,
+ });
}
```
@@ -127,12 +127,12 @@ files.
// Lint the specified files and return the results
async function lintAndFix(eslint, filePaths) {
- const results = await eslint.lintFiles(filePaths);
+ const results = await eslint.lintFiles(filePaths);
- // Apply automatic fixes and output fixed code
- await ESLint.outputFixes(results);
+ // Apply automatic fixes and output fixed code
+ await ESLint.outputFixes(results);
- return results;
+ return results;
}
```
@@ -152,19 +152,19 @@ In this example, we'll simply log the results to the console:
// Log results to console if there are any problems
function outputLintingResults(results) {
- // Identify the number of problems found
- const problems = results.reduce(
- (acc, result) => acc + result.errorCount + result.warningCount,
- 0,
- );
-
- if (problems > 0) {
- console.log("Linting errors found!");
- console.log(results);
- } else {
- console.log("No linting errors found.");
- }
- return results;
+ // Identify the number of problems found
+ const problems = results.reduce(
+ (acc, result) => acc + result.errorCount + result.warningCount,
+ 0,
+ );
+
+ if (problems > 0) {
+ console.log("Linting errors found!");
+ console.log(results);
+ } else {
+ console.log("No linting errors found.");
+ }
+ return results;
}
```
@@ -178,22 +178,22 @@ function will be the main entry point for your integration:
// Put previous functions all together
async function lintFiles(filePaths) {
- // The ESLint configuration. Alternatively, you could load the configuration
- // from a .eslintrc file or just use the default config.
- const overrideConfig = {
- languageOptions: {
- ecmaVersion: 2018,
- sourceType: "commonjs",
- },
- rules: {
- "no-console": "error",
- "no-unused-vars": "warn",
- },
- };
-
- const eslint = createESLintInstance(overrideConfig);
- const results = await lintAndFix(eslint, filePaths);
- return outputLintingResults(results);
+ // The ESLint configuration. Alternatively, you could load the configuration
+ // from a .eslintrc file or just use the default config.
+ const overrideConfig = {
+ languageOptions: {
+ ecmaVersion: 2018,
+ sourceType: "commonjs",
+ },
+ rules: {
+ "no-console": "error",
+ "no-unused-vars": "warn",
+ },
+ };
+
+ const eslint = createESLintInstance(overrideConfig);
+ const results = await lintAndFix(eslint, filePaths);
+ return outputLintingResults(results);
}
// Export integration
@@ -207,58 +207,58 @@ const { ESLint } = require("eslint");
// Create an instance of ESLint with the configuration passed to the function
function createESLintInstance(overrideConfig) {
- return new ESLint({
- overrideConfigFile: true,
- overrideConfig,
- fix: true,
- });
+ return new ESLint({
+ overrideConfigFile: true,
+ overrideConfig,
+ fix: true,
+ });
}
// Lint the specified files and return the results
async function lintAndFix(eslint, filePaths) {
- const results = await eslint.lintFiles(filePaths);
+ const results = await eslint.lintFiles(filePaths);
- // Apply automatic fixes and output fixed code
- await ESLint.outputFixes(results);
+ // Apply automatic fixes and output fixed code
+ await ESLint.outputFixes(results);
- return results;
+ return results;
}
// Log results to console if there are any problems
function outputLintingResults(results) {
- // Identify the number of problems found
- const problems = results.reduce(
- (acc, result) => acc + result.errorCount + result.warningCount,
- 0,
- );
-
- if (problems > 0) {
- console.log("Linting errors found!");
- console.log(results);
- } else {
- console.log("No linting errors found.");
- }
- return results;
+ // Identify the number of problems found
+ const problems = results.reduce(
+ (acc, result) => acc + result.errorCount + result.warningCount,
+ 0,
+ );
+
+ if (problems > 0) {
+ console.log("Linting errors found!");
+ console.log(results);
+ } else {
+ console.log("No linting errors found.");
+ }
+ return results;
}
// Put previous functions all together
async function lintFiles(filePaths) {
- // The ESLint configuration. Alternatively, you could load the configuration
- // from an eslint.config.js file or just use the default config.
- const overrideConfig = {
- languageOptions: {
- ecmaVersion: 2018,
- sourceType: "commonjs",
- },
- rules: {
- "no-console": "error",
- "no-unused-vars": "warn",
- },
- };
-
- const eslint = createESLintInstance(overrideConfig);
- const results = await lintAndFix(eslint, filePaths);
- return outputLintingResults(results);
+ // The ESLint configuration. Alternatively, you could load the configuration
+ // from an eslint.config.js file or just use the default config.
+ const overrideConfig = {
+ languageOptions: {
+ ecmaVersion: 2018,
+ sourceType: "commonjs",
+ },
+ rules: {
+ "no-console": "error",
+ "no-unused-vars": "warn",
+ },
+ };
+
+ const eslint = createESLintInstance(overrideConfig);
+ const results = await lintAndFix(eslint, filePaths);
+ return outputLintingResults(results);
}
// Export integration
diff --git a/docs/src/integrate/nodejs-api.md b/docs/src/integrate/nodejs-api.md
index 79b7e4111122..72760bcc050a 100644
--- a/docs/src/integrate/nodejs-api.md
+++ b/docs/src/integrate/nodejs-api.md
@@ -23,21 +23,21 @@ Here's a simple example of using the `ESLint` class:
const { ESLint } = require("eslint");
(async function main() {
- // 1. Create an instance.
- const eslint = new ESLint();
+ // 1. Create an instance.
+ const eslint = new ESLint();
- // 2. Lint files.
- const results = await eslint.lintFiles(["lib/**/*.js"]);
+ // 2. Lint files.
+ const results = await eslint.lintFiles(["lib/**/*.js"]);
- // 3. Format the results.
- const formatter = await eslint.loadFormatter("stylish");
- const resultText = formatter.format(results);
+ // 3. Format the results.
+ const formatter = await eslint.loadFormatter("stylish");
+ const resultText = formatter.format(results);
- // 4. Output it.
- console.log(resultText);
-})().catch((error) => {
- process.exitCode = 1;
- console.error(error);
+ // 4. Output it.
+ console.log(resultText);
+})().catch(error => {
+ process.exitCode = 1;
+ console.error(error);
});
```
@@ -47,24 +47,24 @@ Here's an example that autofixes lint problems:
const { ESLint } = require("eslint");
(async function main() {
- // 1. Create an instance with the `fix` option.
- const eslint = new ESLint({ fix: true });
+ // 1. Create an instance with the `fix` option.
+ const eslint = new ESLint({ fix: true });
- // 2. Lint files. This doesn't modify target files.
- const results = await eslint.lintFiles(["lib/**/*.js"]);
+ // 2. Lint files. This doesn't modify target files.
+ const results = await eslint.lintFiles(["lib/**/*.js"]);
- // 3. Modify the files with the fixed code.
- await ESLint.outputFixes(results);
+ // 3. Modify the files with the fixed code.
+ await ESLint.outputFixes(results);
- // 4. Format the results.
- const formatter = await eslint.loadFormatter("stylish");
- const resultText = formatter.format(results);
+ // 4. Format the results.
+ const formatter = await eslint.loadFormatter("stylish");
+ const resultText = formatter.format(results);
- // 5. Output it.
- console.log(resultText);
-})().catch((error) => {
- process.exitCode = 1;
- console.error(error);
+ // 5. Output it.
+ console.log(resultText);
+})().catch(error => {
+ process.exitCode = 1;
+ console.error(error);
});
```
@@ -81,29 +81,29 @@ const testCode = `
`;
(async function main() {
- // 1. Create an instance
- const eslint = new ESLint({
- overrideConfigFile: true,
- overrideConfig: {
- languageOptions: {
- ecmaVersion: 2018,
- sourceType: "commonjs"
- }
- },
- });
-
- // 2. Lint text.
- const results = await eslint.lintText(testCode);
-
- // 3. Format the results.
- const formatter = await eslint.loadFormatter("stylish");
- const resultText = formatter.format(results);
-
- // 4. Output it.
- console.log(resultText);
-})().catch((error) => {
- process.exitCode = 1;
- console.error(error);
+ // 1. Create an instance
+ const eslint = new ESLint({
+ overrideConfigFile: true,
+ overrideConfig: {
+ languageOptions: {
+ ecmaVersion: 2018,
+ sourceType: "commonjs",
+ },
+ },
+ });
+
+ // 2. Lint text.
+ const results = await eslint.lintText(testCode);
+
+ // 3. Format the results.
+ const formatter = await eslint.loadFormatter("stylish");
+ const resultText = formatter.format(results);
+
+ // 4. Output it.
+ console.log(resultText);
+})().catch(error => {
+ process.exitCode = 1;
+ console.error(error);
});
```
@@ -121,58 +121,58 @@ The `ESLint` constructor takes an `options` object. If you omit the `options` ob
##### File Enumeration
-* `options.cwd` (`string`)
- Default is `process.cwd()`. The working directory. This must be an absolute path.
-* `options.errorOnUnmatchedPattern` (`boolean`)
- Default is `true`. Unless set to `false`, the [`eslint.lintFiles()`][eslint-lintfiles] method will throw an error when no target files are found.
-* `options.globInputPaths` (`boolean`)
- Default is `true`. If `false` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method doesn't interpret glob patterns.
-* `options.ignore` (`boolean`)
- Default is `true`. If `false` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method doesn't respect `ignorePatterns` in your configuration.
-* `options.ignorePatterns` (`string[] | null`)
- Default is `null`. Ignore file patterns to use in addition to config ignores. These patterns are relative to `cwd`.
-* `options.passOnNoPatterns` (`boolean`)
- Default is `false`. When set to `true`, missing patterns cause the linting operation to short circuit and not report any failures.
-* `options.warnIgnored` (`boolean`)
- Default is `true`. Show warnings when the file list includes ignored files.
+- `options.cwd` (`string`)
+ Default is `process.cwd()`. The working directory. This must be an absolute path.
+- `options.errorOnUnmatchedPattern` (`boolean`)
+ Default is `true`. Unless set to `false`, the [`eslint.lintFiles()`][eslint-lintfiles] method will throw an error when no target files are found.
+- `options.globInputPaths` (`boolean`)
+ Default is `true`. If `false` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method doesn't interpret glob patterns.
+- `options.ignore` (`boolean`)
+ Default is `true`. If `false` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method doesn't respect `ignorePatterns` in your configuration.
+- `options.ignorePatterns` (`string[] | null`)
+ Default is `null`. Ignore file patterns to use in addition to config ignores. These patterns are relative to `cwd`.
+- `options.passOnNoPatterns` (`boolean`)
+ Default is `false`. When set to `true`, missing patterns cause the linting operation to short circuit and not report any failures.
+- `options.warnIgnored` (`boolean`)
+ Default is `true`. Show warnings when the file list includes ignored files.
##### Linting
-* `options.allowInlineConfig` (`boolean`)
- Default is `true`. If `false` is present, ESLint suppresses directive comments in source code. If this option is `false`, it overrides the `noInlineConfig` setting in your configurations.
-* `options.baseConfig` (`ConfigData | ConfigData[] | null`)
- Default is `null`. [Configuration object], extended by all configurations used with this instance. You can use this option to define the default settings that will be used if your configuration files don't configure it.
-* `options.overrideConfig` (`ConfigData | ConfigData[] | null`)
- Default is `null`. [Configuration object], added after any existing configuration and therefore applies after what's contained in your configuration file (if used).
-* `options.overrideConfigFile` (`null | true | string`)
- Default is `null`. By default, ESLint searches for a configuration file. When this option is set to `true`, ESLint does not search for a configuration file. When this option is set to a `string` value, ESLint does not search for a configuration file, and uses the provided value as the path to the configuration file.
-* `options.plugins` (`Record | null`)
- Default is `null`. The plugin implementations that ESLint uses for the `plugins` setting of your configuration. This is a map-like object. Those keys are plugin IDs and each value is implementation.
-* `options.ruleFilter` (`({ruleId: string, severity: number}) => boolean`)
- Default is `() => true`. A predicate function that filters rules to be run. This function is called with an object containing `ruleId` and `severity`, and returns `true` if the rule should be run.
-* `options.stats` (`boolean`)
- Default is `false`. When set to `true`, additional statistics are added to the lint results (see [Stats type](../extend/stats#-stats-type)).
+- `options.allowInlineConfig` (`boolean`)
+ Default is `true`. If `false` is present, ESLint suppresses directive comments in source code. If this option is `false`, it overrides the `noInlineConfig` setting in your configurations.
+- `options.baseConfig` (`ConfigData | ConfigData[] | null`)
+ Default is `null`. [Configuration object], extended by all configurations used with this instance. You can use this option to define the default settings that will be used if your configuration files don't configure it.
+- `options.overrideConfig` (`ConfigData | ConfigData[] | null`)
+ Default is `null`. [Configuration object], added after any existing configuration and therefore applies after what's contained in your configuration file (if used).
+- `options.overrideConfigFile` (`null | true | string`)
+ Default is `null`. By default, ESLint searches for a configuration file. When this option is set to `true`, ESLint does not search for a configuration file. When this option is set to a `string` value, ESLint does not search for a configuration file, and uses the provided value as the path to the configuration file.
+- `options.plugins` (`Record | null`)
+ Default is `null`. The plugin implementations that ESLint uses for the `plugins` setting of your configuration. This is a map-like object. Those keys are plugin IDs and each value is implementation.
+- `options.ruleFilter` (`({ruleId: string, severity: number}) => boolean`)
+ Default is `() => true`. A predicate function that filters rules to be run. This function is called with an object containing `ruleId` and `severity`, and returns `true` if the rule should be run.
+- `options.stats` (`boolean`)
+ Default is `false`. When set to `true`, additional statistics are added to the lint results (see [Stats type](../extend/stats#-stats-type)).
##### Autofix
-* `options.fix` (`boolean | (message: LintMessage) => boolean`)
- Default is `false`. If `true` is present, the [`eslint.lintFiles()`][eslint-lintfiles] and [`eslint.lintText()`][eslint-linttext] methods work in autofix mode. If a predicate function is present, the methods pass each lint message to the function, then use only the lint messages for which the function returned `true`.
-* `options.fixTypes` (`("directive" | "problem" | "suggestion" | "layout")[] | null`)
- Default is `null`. The types of the rules that the [`eslint.lintFiles()`][eslint-lintfiles] and [`eslint.lintText()`][eslint-linttext] methods use for autofix.
+- `options.fix` (`boolean | (message: LintMessage) => boolean`)
+ Default is `false`. If `true` is present, the [`eslint.lintFiles()`][eslint-lintfiles] and [`eslint.lintText()`][eslint-linttext] methods work in autofix mode. If a predicate function is present, the methods pass each lint message to the function, then use only the lint messages for which the function returned `true`.
+- `options.fixTypes` (`("directive" | "problem" | "suggestion" | "layout")[] | null`)
+ Default is `null`. The types of the rules that the [`eslint.lintFiles()`][eslint-lintfiles] and [`eslint.lintText()`][eslint-linttext] methods use for autofix.
##### Cache-related
-* `options.cache` (`boolean`)
- Default is `false`. If `true` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method caches lint results and uses it if each target file is not changed. Please mind that ESLint doesn't clear the cache when you upgrade ESLint plugins. In that case, you have to remove the cache file manually. The [`eslint.lintText()`][eslint-linttext] method doesn't use caches even if you pass the `options.filePath` to the method.
-* `options.cacheLocation` (`string`)
- Default is `.eslintcache`. The [`eslint.lintFiles()`][eslint-lintfiles] method writes caches into this file.
-* `options.cacheStrategy` (`string`)
- Default is `"metadata"`. Strategy for the cache to use for detecting changed files. Can be either `"metadata"` or `"content"`.
+- `options.cache` (`boolean`)
+ Default is `false`. If `true` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method caches lint results and uses it if each target file is not changed. Please mind that ESLint doesn't clear the cache when you upgrade ESLint plugins. In that case, you have to remove the cache file manually. The [`eslint.lintText()`][eslint-linttext] method doesn't use caches even if you pass the `options.filePath` to the method.
+- `options.cacheLocation` (`string`)
+ Default is `.eslintcache`. The [`eslint.lintFiles()`][eslint-lintfiles] method writes caches into this file.
+- `options.cacheStrategy` (`string`)
+ Default is `"metadata"`. Strategy for the cache to use for detecting changed files. Can be either `"metadata"` or `"content"`.
##### Other Options
-* `options.flags` (`string[]`)
- Default is `[]`. The feature flags to enable for this instance.
+- `options.flags` (`string[]`)
+ Default is `[]`. The feature flags to enable for this instance.
### â eslint.lintFiles(patterns)
@@ -184,13 +184,13 @@ This method lints the files that match the glob patterns and then returns the re
#### Parameters
-* `patterns` (`string | string[]`)
- The lint target files. This can contain any of file paths, directory paths, and glob patterns.
+- `patterns` (`string | string[]`)
+ The lint target files. This can contain any of file paths, directory paths, and glob patterns.
#### Return Value
-* (`Promise`)
- The promise that will be fulfilled with an array of [LintResult] objects.
+- (`Promise`)
+ The promise that will be fulfilled with an array of [LintResult] objects.
### â eslint.lintText(code, options)
@@ -208,17 +208,17 @@ If the `options.filePath` value is configured to be ignored, this method returns
The second parameter `options` is omittable.
-* `code` (`string`)
- The source code text to check.
-* `options.filePath` (`string`)
- Optional. The path to the file of the source code text. If omitted, the `result.filePath` becomes the string `""`.
-* `options.warnIgnored` (`boolean`)
- Optional, defaults to `options.warnIgnored` passed to the constructor. If `true` is present and the `options.filePath` is a file ESLint should ignore, this method returns a lint result contains a warning message.
+- `code` (`string`)
+ The source code text to check.
+- `options.filePath` (`string`)
+ Optional. The path to the file of the source code text. If omitted, the `result.filePath` becomes the string `""`.
+- `options.warnIgnored` (`boolean`)
+ Optional, defaults to `options.warnIgnored` passed to the constructor. If `true` is present and the `options.filePath` is a file ESLint should ignore, this method returns a lint result contains a warning message.
#### Return Value
-* (`Promise`)
- The promise that will be fulfilled with an array of [LintResult] objects. This is an array (despite there being only one lint result) in order to keep the interfaces between this and the [`eslint.lintFiles()`][eslint-lintfiles] method similar.
+- (`Promise`)
+ The promise that will be fulfilled with an array of [LintResult] objects. This is an array (despite there being only one lint result) in order to keep the interfaces between this and the [`eslint.lintFiles()`][eslint-lintfiles] method similar.
### â eslint.getRulesMetaForResults(results)
@@ -231,13 +231,13 @@ This method returns an object containing meta information for each rule that tri
#### Parameters
-* `results` (`LintResult[]`)
- An array of [LintResult] objects returned from a call to `ESLint#lintFiles()` or `ESLint#lintText()`.
+- `results` (`LintResult[]`)
+ An array of [LintResult] objects returned from a call to `ESLint#lintFiles()` or `ESLint#lintText()`.
#### Return Value
-* (`Object`)
- An object whose property names are the rule IDs from the `results` and whose property values are the rule's meta information (if available).
+- (`Object`)
+ An object whose property names are the rule IDs from the `results` and whose property values are the rule's meta information (if available).
### â eslint.calculateConfigForFile(filePath)
@@ -249,13 +249,13 @@ This method calculates the configuration for a given file, which can be useful f
#### Parameters
-* `filePath` (`string`)
- The path to the file whose configuration you would like to calculate. Directory paths are forbidden because ESLint cannot handle the `overrides` setting.
+- `filePath` (`string`)
+ The path to the file whose configuration you would like to calculate. Directory paths are forbidden because ESLint cannot handle the `overrides` setting.
#### Return Value
-* (`Promise