This commit is contained in:
201
node_modules/@eslint/config-array/LICENSE
generated
vendored
Normal file
201
node_modules/@eslint/config-array/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
369
node_modules/@eslint/config-array/README.md
generated
vendored
Normal file
369
node_modules/@eslint/config-array/README.md
generated
vendored
Normal file
@@ -0,0 +1,369 @@
|
||||
# Config Array
|
||||
|
||||
## Description
|
||||
|
||||
A config array is a way of managing configurations that are based on glob pattern matching of filenames. Each config array contains the information needed to determine the correct configuration for any file based on the filename.
|
||||
|
||||
**Note:** This is a generic package that can be used outside of ESLint. It contains no ESLint-specific functionality.
|
||||
|
||||
## Installation
|
||||
|
||||
For Node.js and compatible runtimes:
|
||||
|
||||
```shell
|
||||
npm install @eslint/config-array
|
||||
# or
|
||||
yarn add @eslint/config-array
|
||||
# or
|
||||
pnpm install @eslint/config-array
|
||||
# or
|
||||
bun add @eslint/config-array
|
||||
```
|
||||
|
||||
For Deno:
|
||||
|
||||
```shell
|
||||
deno add @eslint/config-array
|
||||
```
|
||||
|
||||
## Background
|
||||
|
||||
The basic idea is that all configuration, including overrides, can be represented by a single array where each item in the array is a config object. Config objects appearing later in the array override config objects appearing earlier in the array. You can calculate a config for a given file by traversing all config objects in the array to find the ones that match the filename. Matching is done by specifying glob patterns in `files` and `ignores` properties on each config object. Here's an example:
|
||||
|
||||
```js
|
||||
export default [
|
||||
// match all JSON files
|
||||
{
|
||||
name: "JSON Handler",
|
||||
files: ["**/*.json"],
|
||||
handler: jsonHandler,
|
||||
},
|
||||
|
||||
// match only package.json
|
||||
{
|
||||
name: "package.json Handler",
|
||||
files: ["package.json"],
|
||||
handler: packageJsonHandler,
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
In this example, there are two config objects: the first matches all JSON files in all directories and the second matches just `package.json` in the base path directory (all the globs are evaluated as relative to a base path that can be specified). When you retrieve a configuration for `foo.json`, only the first config object matches so `handler` is equal to `jsonHandler`; when you retrieve a configuration for `package.json`, `handler` is equal to `packageJsonHandler` (because both config objects match, the second one wins).
|
||||
|
||||
## Usage
|
||||
|
||||
First, import the `ConfigArray` constructor:
|
||||
|
||||
```js
|
||||
import { ConfigArray } from "@eslint/config-array";
|
||||
|
||||
// or using CommonJS
|
||||
|
||||
const { ConfigArray } = require("@eslint/config-array");
|
||||
```
|
||||
|
||||
When you create a new instance of `ConfigArray`, you must pass in two arguments: an array of configs and an options object. The array of configs is most likely read in from a configuration file, so here's a typical example:
|
||||
|
||||
```js
|
||||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { ConfigArray } from "@eslint/config-array";
|
||||
|
||||
const configFilename = path.resolve(process.cwd(), "my.config.js");
|
||||
const { default: rawConfigs } = await import(pathToFileURL(configFilename));
|
||||
|
||||
const configs = new ConfigArray(rawConfigs, {
|
||||
// the path to match filenames from
|
||||
basePath: process.cwd(),
|
||||
|
||||
// additional items in each config
|
||||
schema: mySchema,
|
||||
});
|
||||
```
|
||||
|
||||
This example reads in an object or array from `my.config.js` and passes it into the `ConfigArray` constructor as the first argument. The second argument is an object specifying the `basePath` (the directory in which `my.config.js` is found) and a `schema` to define the additional properties of a config object beyond `files`, `ignores`, `basePath`, and `name`.
|
||||
|
||||
### Specifying a Schema
|
||||
|
||||
The `schema` option is required for you to use additional properties in config objects. The schema is an object that follows the format of an [`ObjectSchema`](https://npmjs.com/package/@eslint/object-schema). The schema specifies both validation and merge rules that the `ConfigArray` instance needs to combine configs when there are multiple matches. Here's an example:
|
||||
|
||||
```js
|
||||
const configFilename = path.resolve(process.cwd(), "my.config.js");
|
||||
const { default: rawConfigs } = await import(pathToFileURL(configFilename));
|
||||
|
||||
const mySchema = {
|
||||
// define the handler key in configs
|
||||
handler: {
|
||||
required: true,
|
||||
merge(a, b) {
|
||||
return b ?? a;
|
||||
},
|
||||
validate(value) {
|
||||
if (typeof value !== "function") {
|
||||
throw new TypeError("Function expected.");
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const configs = new ConfigArray(rawConfigs, {
|
||||
// the path to match filenames from
|
||||
basePath: process.cwd(),
|
||||
|
||||
// additional item schemas in each config
|
||||
schema: mySchema,
|
||||
|
||||
// additional config types supported (default: [])
|
||||
extraConfigTypes: ["array", "function"],
|
||||
});
|
||||
```
|
||||
|
||||
### Config Arrays
|
||||
|
||||
Config arrays can be multidimensional, so it's possible for a config array to contain another config array when `extraConfigTypes` contains `"array"`, such as:
|
||||
|
||||
```js
|
||||
export default [
|
||||
// JS config
|
||||
{
|
||||
files: ["**/*.js"],
|
||||
handler: jsHandler,
|
||||
},
|
||||
|
||||
// JSON configs
|
||||
[
|
||||
// match all JSON files
|
||||
{
|
||||
name: "JSON Handler",
|
||||
files: ["**/*.json"],
|
||||
handler: jsonHandler,
|
||||
},
|
||||
|
||||
// match only package.json
|
||||
{
|
||||
name: "package.json Handler",
|
||||
files: ["package.json"],
|
||||
handler: packageJsonHandler,
|
||||
},
|
||||
],
|
||||
|
||||
// filename must match function
|
||||
{
|
||||
files: [filePath => filePath.endsWith(".md")],
|
||||
handler: markdownHandler,
|
||||
},
|
||||
|
||||
// filename must match all patterns in subarray
|
||||
{
|
||||
files: [["*.test.*", "*.js"]],
|
||||
handler: jsTestHandler,
|
||||
},
|
||||
|
||||
// filename must not match patterns beginning with !
|
||||
{
|
||||
name: "Non-JS files",
|
||||
files: ["!*.js"],
|
||||
settings: {
|
||||
js: false,
|
||||
},
|
||||
},
|
||||
|
||||
// specific settings for files inside `src` directory
|
||||
{
|
||||
name: "Source files",
|
||||
basePath: "src",
|
||||
files: ["**/*"],
|
||||
settings: {
|
||||
source: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
In this example, the array contains both config objects and a config array. When a config array is normalized (see details below), it is flattened so only config objects remain. However, the order of evaluation remains the same.
|
||||
|
||||
If the `files` array contains a function, then that function is called with the path of the file as it was passed in. The function is expected to return `true` if there is a match and `false` if not. (The `ignores` array can also contain functions.)
|
||||
|
||||
If the `files` array contains an item that is an array of strings and functions, then all patterns must match in order for the config to match. In the preceding examples, both `*.test.*` and `*.js` must match in order for the config object to be used.
|
||||
|
||||
If a pattern in the files array begins with `!` then it excludes that pattern. In the preceding example, any filename that doesn't end with `.js` will automatically get a `settings.js` property set to `false`.
|
||||
|
||||
You can also specify an `ignores` key that will force files matching those patterns to not be included. If the `ignores` key is in a config object without any other keys, then those ignores will always be applied; otherwise those ignores act as exclusions. Here's an example:
|
||||
|
||||
```js
|
||||
export default [
|
||||
// Always ignored
|
||||
{
|
||||
ignores: ["**/.git/**", "**/node_modules/**"],
|
||||
},
|
||||
|
||||
// .eslintrc.js file is ignored only when .js file matches
|
||||
{
|
||||
files: ["**/*.js"],
|
||||
ignores: [".eslintrc.js"],
|
||||
handler: jsHandler,
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
You can use negated patterns in `ignores` to exclude a file that was already ignored, such as:
|
||||
|
||||
```js
|
||||
export default [
|
||||
// Ignore all JSON files except tsconfig.json
|
||||
{
|
||||
files: ["**/*"],
|
||||
ignores: ["**/*.json", "!tsconfig.json"],
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
### Config Functions
|
||||
|
||||
Config arrays can also include config functions when `extraConfigTypes` contains `"function"`. A config function accepts a single parameter, `context` (defined by you), and must return either a config object or a config array (it cannot return another function). Config functions allow end users to execute code in the creation of appropriate config objects. Here's an example:
|
||||
|
||||
```js
|
||||
export default [
|
||||
// JS config
|
||||
{
|
||||
files: ["**/*.js"],
|
||||
handler: jsHandler,
|
||||
},
|
||||
|
||||
// JSON configs
|
||||
function (context) {
|
||||
return [
|
||||
// match all JSON files
|
||||
{
|
||||
name: context.name + " JSON Handler",
|
||||
files: ["**/*.json"],
|
||||
handler: jsonHandler,
|
||||
},
|
||||
|
||||
// match only package.json
|
||||
{
|
||||
name: context.name + " package.json Handler",
|
||||
files: ["package.json"],
|
||||
handler: packageJsonHandler,
|
||||
},
|
||||
];
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
When a config array is normalized, each function is executed and replaced in the config array with the return value.
|
||||
|
||||
**Note:** Config functions can also be async.
|
||||
|
||||
### Normalizing Config Arrays
|
||||
|
||||
Once a config array has been created and loaded with all of the raw config data, it must be normalized before it can be used. The normalization process goes through and flattens the config array as well as executing all config functions to get their final values.
|
||||
|
||||
To normalize a config array, call the `normalize()` method and pass in a context object:
|
||||
|
||||
```js
|
||||
await configs.normalize({
|
||||
name: "MyApp",
|
||||
});
|
||||
```
|
||||
|
||||
The `normalize()` method returns a promise, so be sure to use the `await` operator. The config array instance is normalized in-place, so you don't need to create a new variable.
|
||||
|
||||
If you want to disallow async config functions, you can call `normalizeSync()` instead. This method is completely synchronous and does not require using the `await` operator as it does not return a promise:
|
||||
|
||||
```js
|
||||
configs.normalizeSync({
|
||||
name: "MyApp",
|
||||
});
|
||||
```
|
||||
|
||||
**Important:** Once a `ConfigArray` is normalized, it cannot be changed further. You can, however, create a new `ConfigArray` and pass in the normalized instance to create an unnormalized copy.
|
||||
|
||||
### Getting Config for a File
|
||||
|
||||
To get the config for a file, use the `getConfig()` method on a normalized config array and pass in the filename to get a config for:
|
||||
|
||||
```js
|
||||
// pass in filename
|
||||
const fileConfig = configs.getConfig(
|
||||
path.resolve(process.cwd(), "package.json"),
|
||||
);
|
||||
```
|
||||
|
||||
The config array always returns an object, even if there are no configs matching the given filename. You can then inspect the returned config object to determine how to proceed.
|
||||
|
||||
A few things to keep in mind:
|
||||
|
||||
- If a filename is not an absolute path, it will be resolved relative to the base path directory.
|
||||
- The returned config object never has `files`, `ignores`, `basePath`, or `name` properties; the only properties on the object will be the other configuration options specified.
|
||||
- The config array caches configs, so subsequent calls to `getConfig()` with the same filename will return in a fast lookup rather than another calculation.
|
||||
- A config will only be generated if the filename matches an entry in a `files` key. A config will not be generated without matching a `files` key (configs without a `files` key are only applied when another config with a `files` key is applied; configs without `files` are never applied on their own). Any config with a `files` key entry that is `*` or ends with `/**` or `/*` will only be applied if another entry in the same `files` key matches or another config matches.
|
||||
|
||||
## Determining Ignored Paths
|
||||
|
||||
You can determine if a file is ignored by using the `isFileIgnored()` method and passing in the path of any file, as in this example:
|
||||
|
||||
```js
|
||||
const ignored = configs.isFileIgnored("/foo/bar/baz.txt");
|
||||
```
|
||||
|
||||
A file is considered ignored if any of the following is true:
|
||||
|
||||
- **Its parent directory is ignored.** For example, if `foo` is in `ignores`, then `foo/a.js` is considered ignored.
|
||||
- **It has an ancestor directory that is ignored.** For example, if `foo` is in `ignores`, then `foo/baz/a.js` is considered ignored.
|
||||
- **It matches an ignored file pattern.** For example, if `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
|
||||
- **If it matches an entry in `files` and also in `ignores`.** For example, if `**/*.js` is in `files` and `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
|
||||
- **The file is outside the `basePath`.** If the `basePath` is `/usr/me`, then `/foo/a.js` is considered ignored.
|
||||
|
||||
For directories, use the `isDirectoryIgnored()` method and pass in the path of any directory, as in this example:
|
||||
|
||||
```js
|
||||
const ignored = configs.isDirectoryIgnored("/foo/bar/");
|
||||
```
|
||||
|
||||
A directory is considered ignored if any of the following is true:
|
||||
|
||||
- **Its parent directory is ignored.** For example, if `foo` is in `ignores`, then `foo/baz` is considered ignored.
|
||||
- **It has an ancestor directory that is ignored.** For example, if `foo` is in `ignores`, then `foo/bar/baz/a.js` is considered ignored.
|
||||
- **It matches an ignored file pattern.** For example, if `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
|
||||
- **If it matches an entry in `files` and also in `ignores`.** For example, if `**/*.js` is in `files` and `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
|
||||
- **The file is outside the `basePath`.** If the `basePath` is `/usr/me`, then `/foo/a.js` is considered ignored.
|
||||
|
||||
**Important:** A pattern such as `foo/**` means that `foo` and `foo/` are _not_ ignored whereas `foo/bar` is ignored. If you want to ignore `foo` and all of its subdirectories, use the pattern `foo` or `foo/` in `ignores`.
|
||||
|
||||
## Caching Mechanisms
|
||||
|
||||
Each `ConfigArray` aggressively caches configuration objects to avoid unnecessary work. This caching occurs in two ways:
|
||||
|
||||
1. **File-based Caching.** For each filename that is passed into a method, the resulting config is cached against that filename so you're always guaranteed to get the same object returned from `getConfig()` whenever you pass the same filename in.
|
||||
2. **Index-based Caching.** Whenever a config is calculated, the config elements that were used to create the config are also cached. So if a given filename matches elements 1, 5, and 7, the resulting config is cached with a key of `1,5,7`. That way, if another file is passed that matches the same config elements, the result is already known and doesn't have to be recalculated. That means two files that match all the same elements will return the same config from `getConfig()`.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
The design of this project was influenced by feedback on the ESLint RFC, and incorporates ideas from:
|
||||
|
||||
- Teddy Katz (@not-an-aardvark)
|
||||
- Toru Nagashima (@mysticatea)
|
||||
- Kai Cataldo (@kaicataldo)
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0
|
||||
|
||||
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
||||
<!--sponsorsstart-->
|
||||
|
||||
## Sponsors
|
||||
|
||||
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
|
||||
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
||||
|
||||
<h3>Platinum Sponsors</h3>
|
||||
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a></p><h3>Gold Sponsors</h3>
|
||||
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a></p><h3>Silver Sponsors</h3>
|
||||
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/d472863/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
|
||||
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://opensource.sap.com"><img src="https://avatars.githubusercontent.com/u/2531208" alt="SAP" height="32"></a> <a href="https://www.crawljobs.com/"><img src="https://images.opencollective.com/crawljobs-poland/fa43a17/logo.png" alt="CrawlJobs" height="32"></a> <a href="#"><img src="https://images.opencollective.com/aeriusventilations-org/avatar.png" alt="aeriusventilation's Org" height="32"></a> <a href="https://depot.dev"><img src="https://images.opencollective.com/depot/39125a1/logo.png" alt="Depot" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="TestMu AI Open Source Office (Formerly LambdaTest)" height="32"></a></p>
|
||||
<h3>Technology Sponsors</h3>
|
||||
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
||||
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
||||
<!--sponsorsend-->
|
||||
1541
node_modules/@eslint/config-array/dist/cjs/index.cjs
generated
vendored
Normal file
1541
node_modules/@eslint/config-array/dist/cjs/index.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
151
node_modules/@eslint/config-array/dist/cjs/index.d.cts
generated
vendored
Normal file
151
node_modules/@eslint/config-array/dist/cjs/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
export { ObjectSchema } from "@eslint/object-schema";
|
||||
export type PropertyDefinition = $eslintobjectschema.PropertyDefinition;
|
||||
export type ObjectDefinition = $eslintobjectschema.ObjectDefinition;
|
||||
export type ConfigObject = $typests.ConfigObject;
|
||||
export type FileMatcher = $typests.FileMatcher;
|
||||
export type FilesMatcher = $typests.FilesMatcher;
|
||||
export type ExtraConfigType = $typests.ExtraConfigType;
|
||||
export type MinimatchOptions = $minimatch.MinimatchOptions;
|
||||
export type ObjectSchemaInstance = ObjectSchema;
|
||||
/**
|
||||
* Represents an array of config objects and provides method for working with
|
||||
* those config objects.
|
||||
*/
|
||||
export class ConfigArray extends Array<any> {
|
||||
/**
|
||||
* Creates a new instance of ConfigArray.
|
||||
* @param {Iterable|Function|Object} configs An iterable yielding config
|
||||
* objects, or a config function, or a config object.
|
||||
* @param {Object} options The options for the ConfigArray.
|
||||
* @param {string} [options.basePath="/"] The absolute path of the config file directory.
|
||||
* Defaults to `"/"`.
|
||||
* @param {boolean} [options.normalized=false] Flag indicating if the
|
||||
* configs have already been normalized.
|
||||
* @param {ObjectDefinition} [options.schema] The additional schema
|
||||
* definitions to use for the ConfigArray schema.
|
||||
* @param {ReadonlyArray<ExtraConfigType>} [options.extraConfigTypes] List of config types supported.
|
||||
* @throws {TypeError} When the `basePath` is not a non-empty string,
|
||||
*/
|
||||
constructor(configs: Iterable<any> | Function | any, { basePath, normalized, schema: customSchema, extraConfigTypes, }?: {
|
||||
basePath?: string;
|
||||
normalized?: boolean;
|
||||
schema?: ObjectDefinition;
|
||||
extraConfigTypes?: ReadonlyArray<ExtraConfigType>;
|
||||
});
|
||||
/**
|
||||
* The path of the config file that this array was loaded from.
|
||||
* This is used to calculate filename matches.
|
||||
* @property basePath
|
||||
* @type {string}
|
||||
*/
|
||||
basePath: string;
|
||||
/**
|
||||
* The supported config types.
|
||||
* @type {ReadonlyArray<ExtraConfigType>}
|
||||
*/
|
||||
extraConfigTypes: ReadonlyArray<ExtraConfigType>;
|
||||
/**
|
||||
* Returns the `files` globs from every config object in the array.
|
||||
* This can be used to determine which files will be matched by a
|
||||
* config array or to use as a glob pattern when no patterns are provided
|
||||
* for a command line interface.
|
||||
* @returns {Array<FilesMatcher>} An array of matchers.
|
||||
*/
|
||||
get files(): Array<FilesMatcher>;
|
||||
/**
|
||||
* Returns ignore matchers that should always be ignored regardless of
|
||||
* the matching `files` fields in any configs. This is necessary to mimic
|
||||
* the behavior of things like .gitignore and .eslintignore, allowing a
|
||||
* globbing operation to be faster.
|
||||
* @returns {Array<{ basePath?: string, name?: string, ignores: FileMatcher[] }>} An array of config objects representing global ignores.
|
||||
*/
|
||||
get ignores(): Array<{
|
||||
basePath?: string;
|
||||
name?: string;
|
||||
ignores: FileMatcher[];
|
||||
}>;
|
||||
/**
|
||||
* Indicates if the config array has been normalized.
|
||||
* @returns {boolean} True if the config array is normalized, false if not.
|
||||
*/
|
||||
isNormalized(): boolean;
|
||||
/**
|
||||
* Normalizes a config array by flattening embedded arrays and executing
|
||||
* config functions.
|
||||
* @param {Object} [context] The context object for config functions.
|
||||
* @returns {Promise<ConfigArray>} The current ConfigArray instance.
|
||||
*/
|
||||
normalize(context?: any): Promise<ConfigArray>;
|
||||
/**
|
||||
* Normalizes a config array by flattening embedded arrays and executing
|
||||
* config functions.
|
||||
* @param {Object} [context] The context object for config functions.
|
||||
* @returns {ConfigArray} The current ConfigArray instance.
|
||||
*/
|
||||
normalizeSync(context?: any): ConfigArray;
|
||||
/**
|
||||
* Returns the config object for a given file path and a status that can be used to determine why a file has no config.
|
||||
* @param {string} filePath The path of a file to get a config for.
|
||||
* @returns {{ config?: Object, status: "ignored"|"external"|"unconfigured"|"matched" }}
|
||||
* An object with an optional property `config` and property `status`.
|
||||
* `config` is the config object for the specified file as returned by {@linkcode ConfigArray.getConfig},
|
||||
* `status` a is one of the constants returned by {@linkcode ConfigArray.getConfigStatus}.
|
||||
*/
|
||||
getConfigWithStatus(filePath: string): {
|
||||
config?: any;
|
||||
status: "ignored" | "external" | "unconfigured" | "matched";
|
||||
};
|
||||
/**
|
||||
* Returns the config object for a given file path.
|
||||
* @param {string} filePath The path of a file to get a config for.
|
||||
* @returns {Object|undefined} The config object for this file or `undefined`.
|
||||
*/
|
||||
getConfig(filePath: string): any | undefined;
|
||||
/**
|
||||
* Determines whether a file has a config or why it doesn't.
|
||||
* @param {string} filePath The path of the file to check.
|
||||
* @returns {"ignored"|"external"|"unconfigured"|"matched"} One of the following values:
|
||||
* * `"ignored"`: the file is ignored
|
||||
* * `"external"`: the file is outside the base path
|
||||
* * `"unconfigured"`: the file is not matched by any config
|
||||
* * `"matched"`: the file has a matching config
|
||||
*/
|
||||
getConfigStatus(filePath: string): "ignored" | "external" | "unconfigured" | "matched";
|
||||
/**
|
||||
* Determines if the given filepath is ignored based on the configs.
|
||||
* @param {string} filePath The path of a file to check.
|
||||
* @returns {boolean} True if the path is ignored, false if not.
|
||||
* @deprecated Use `isFileIgnored` instead.
|
||||
*/
|
||||
isIgnored(filePath: string): boolean;
|
||||
/**
|
||||
* Determines if the given filepath is ignored based on the configs.
|
||||
* @param {string} filePath The path of a file to check.
|
||||
* @returns {boolean} True if the path is ignored, false if not.
|
||||
*/
|
||||
isFileIgnored(filePath: string): boolean;
|
||||
/**
|
||||
* Determines if the given directory is ignored based on the configs.
|
||||
* This checks only default `ignores` that don't have `files` in the
|
||||
* same config. A pattern such as `/foo` be considered to ignore the directory
|
||||
* while a pattern such as `/foo/**` is not considered to ignore the
|
||||
* directory because it is matching files.
|
||||
* @param {string} directoryPath The path of a directory to check.
|
||||
* @returns {boolean} True if the directory is ignored, false if not. Will
|
||||
* return true for any directory that is not inside of `basePath`.
|
||||
* @throws {Error} When the `ConfigArray` is not normalized.
|
||||
*/
|
||||
isDirectoryIgnored(directoryPath: string): boolean;
|
||||
#private;
|
||||
}
|
||||
export namespace ConfigArraySymbol {
|
||||
let isNormalized: symbol;
|
||||
let configCache: symbol;
|
||||
let schema: symbol;
|
||||
let finalizeConfig: symbol;
|
||||
let preprocessConfig: symbol;
|
||||
}
|
||||
import type * as $eslintobjectschema from "@eslint/object-schema";
|
||||
import type * as $typests from "./types.cts";
|
||||
import type * as $minimatch from "minimatch";
|
||||
import { ObjectSchema } from '@eslint/object-schema';
|
||||
1336
node_modules/@eslint/config-array/dist/cjs/std__path/posix.cjs
generated
vendored
Normal file
1336
node_modules/@eslint/config-array/dist/cjs/std__path/posix.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1678
node_modules/@eslint/config-array/dist/cjs/std__path/windows.cjs
generated
vendored
Normal file
1678
node_modules/@eslint/config-array/dist/cjs/std__path/windows.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
46
node_modules/@eslint/config-array/dist/cjs/types.cts
generated
vendored
Normal file
46
node_modules/@eslint/config-array/dist/cjs/types.cts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @fileoverview Types for the config-array package.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/**
|
||||
* A file matcher used in `files` and `ignores`.
|
||||
*/
|
||||
export type FileMatcher = string | ((filePath: string) => boolean);
|
||||
|
||||
/**
|
||||
* An entry in a config's `files` array.
|
||||
*
|
||||
* A subarray means all matchers must match.
|
||||
*/
|
||||
export type FilesMatcher = FileMatcher | FileMatcher[];
|
||||
|
||||
/**
|
||||
* The config types allowed in the `extraConfigTypes` option.
|
||||
*/
|
||||
export type ExtraConfigType = "array" | "function";
|
||||
|
||||
export interface ConfigObject {
|
||||
/**
|
||||
* The base path for files and ignores.
|
||||
*/
|
||||
basePath?: string;
|
||||
|
||||
/**
|
||||
* The files to include.
|
||||
*/
|
||||
files?: FilesMatcher[];
|
||||
|
||||
/**
|
||||
* The files to exclude.
|
||||
*/
|
||||
ignores?: FileMatcher[];
|
||||
|
||||
/**
|
||||
* The name of the config object.
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
// may also have any number of other properties
|
||||
[key: string]: unknown;
|
||||
}
|
||||
151
node_modules/@eslint/config-array/dist/esm/index.d.ts
generated
vendored
Normal file
151
node_modules/@eslint/config-array/dist/esm/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
export { ObjectSchema } from "@eslint/object-schema";
|
||||
export type PropertyDefinition = $eslintobjectschema.PropertyDefinition;
|
||||
export type ObjectDefinition = $eslintobjectschema.ObjectDefinition;
|
||||
export type ConfigObject = $typests.ConfigObject;
|
||||
export type FileMatcher = $typests.FileMatcher;
|
||||
export type FilesMatcher = $typests.FilesMatcher;
|
||||
export type ExtraConfigType = $typests.ExtraConfigType;
|
||||
export type MinimatchOptions = $minimatch.MinimatchOptions;
|
||||
export type ObjectSchemaInstance = ObjectSchema;
|
||||
/**
|
||||
* Represents an array of config objects and provides method for working with
|
||||
* those config objects.
|
||||
*/
|
||||
export class ConfigArray extends Array<any> {
|
||||
/**
|
||||
* Creates a new instance of ConfigArray.
|
||||
* @param {Iterable|Function|Object} configs An iterable yielding config
|
||||
* objects, or a config function, or a config object.
|
||||
* @param {Object} options The options for the ConfigArray.
|
||||
* @param {string} [options.basePath="/"] The absolute path of the config file directory.
|
||||
* Defaults to `"/"`.
|
||||
* @param {boolean} [options.normalized=false] Flag indicating if the
|
||||
* configs have already been normalized.
|
||||
* @param {ObjectDefinition} [options.schema] The additional schema
|
||||
* definitions to use for the ConfigArray schema.
|
||||
* @param {ReadonlyArray<ExtraConfigType>} [options.extraConfigTypes] List of config types supported.
|
||||
* @throws {TypeError} When the `basePath` is not a non-empty string,
|
||||
*/
|
||||
constructor(configs: Iterable<any> | Function | any, { basePath, normalized, schema: customSchema, extraConfigTypes, }?: {
|
||||
basePath?: string;
|
||||
normalized?: boolean;
|
||||
schema?: ObjectDefinition;
|
||||
extraConfigTypes?: ReadonlyArray<ExtraConfigType>;
|
||||
});
|
||||
/**
|
||||
* The path of the config file that this array was loaded from.
|
||||
* This is used to calculate filename matches.
|
||||
* @property basePath
|
||||
* @type {string}
|
||||
*/
|
||||
basePath: string;
|
||||
/**
|
||||
* The supported config types.
|
||||
* @type {ReadonlyArray<ExtraConfigType>}
|
||||
*/
|
||||
extraConfigTypes: ReadonlyArray<ExtraConfigType>;
|
||||
/**
|
||||
* Returns the `files` globs from every config object in the array.
|
||||
* This can be used to determine which files will be matched by a
|
||||
* config array or to use as a glob pattern when no patterns are provided
|
||||
* for a command line interface.
|
||||
* @returns {Array<FilesMatcher>} An array of matchers.
|
||||
*/
|
||||
get files(): Array<FilesMatcher>;
|
||||
/**
|
||||
* Returns ignore matchers that should always be ignored regardless of
|
||||
* the matching `files` fields in any configs. This is necessary to mimic
|
||||
* the behavior of things like .gitignore and .eslintignore, allowing a
|
||||
* globbing operation to be faster.
|
||||
* @returns {Array<{ basePath?: string, name?: string, ignores: FileMatcher[] }>} An array of config objects representing global ignores.
|
||||
*/
|
||||
get ignores(): Array<{
|
||||
basePath?: string;
|
||||
name?: string;
|
||||
ignores: FileMatcher[];
|
||||
}>;
|
||||
/**
|
||||
* Indicates if the config array has been normalized.
|
||||
* @returns {boolean} True if the config array is normalized, false if not.
|
||||
*/
|
||||
isNormalized(): boolean;
|
||||
/**
|
||||
* Normalizes a config array by flattening embedded arrays and executing
|
||||
* config functions.
|
||||
* @param {Object} [context] The context object for config functions.
|
||||
* @returns {Promise<ConfigArray>} The current ConfigArray instance.
|
||||
*/
|
||||
normalize(context?: any): Promise<ConfigArray>;
|
||||
/**
|
||||
* Normalizes a config array by flattening embedded arrays and executing
|
||||
* config functions.
|
||||
* @param {Object} [context] The context object for config functions.
|
||||
* @returns {ConfigArray} The current ConfigArray instance.
|
||||
*/
|
||||
normalizeSync(context?: any): ConfigArray;
|
||||
/**
|
||||
* Returns the config object for a given file path and a status that can be used to determine why a file has no config.
|
||||
* @param {string} filePath The path of a file to get a config for.
|
||||
* @returns {{ config?: Object, status: "ignored"|"external"|"unconfigured"|"matched" }}
|
||||
* An object with an optional property `config` and property `status`.
|
||||
* `config` is the config object for the specified file as returned by {@linkcode ConfigArray.getConfig},
|
||||
* `status` a is one of the constants returned by {@linkcode ConfigArray.getConfigStatus}.
|
||||
*/
|
||||
getConfigWithStatus(filePath: string): {
|
||||
config?: any;
|
||||
status: "ignored" | "external" | "unconfigured" | "matched";
|
||||
};
|
||||
/**
|
||||
* Returns the config object for a given file path.
|
||||
* @param {string} filePath The path of a file to get a config for.
|
||||
* @returns {Object|undefined} The config object for this file or `undefined`.
|
||||
*/
|
||||
getConfig(filePath: string): any | undefined;
|
||||
/**
|
||||
* Determines whether a file has a config or why it doesn't.
|
||||
* @param {string} filePath The path of the file to check.
|
||||
* @returns {"ignored"|"external"|"unconfigured"|"matched"} One of the following values:
|
||||
* * `"ignored"`: the file is ignored
|
||||
* * `"external"`: the file is outside the base path
|
||||
* * `"unconfigured"`: the file is not matched by any config
|
||||
* * `"matched"`: the file has a matching config
|
||||
*/
|
||||
getConfigStatus(filePath: string): "ignored" | "external" | "unconfigured" | "matched";
|
||||
/**
|
||||
* Determines if the given filepath is ignored based on the configs.
|
||||
* @param {string} filePath The path of a file to check.
|
||||
* @returns {boolean} True if the path is ignored, false if not.
|
||||
* @deprecated Use `isFileIgnored` instead.
|
||||
*/
|
||||
isIgnored(filePath: string): boolean;
|
||||
/**
|
||||
* Determines if the given filepath is ignored based on the configs.
|
||||
* @param {string} filePath The path of a file to check.
|
||||
* @returns {boolean} True if the path is ignored, false if not.
|
||||
*/
|
||||
isFileIgnored(filePath: string): boolean;
|
||||
/**
|
||||
* Determines if the given directory is ignored based on the configs.
|
||||
* This checks only default `ignores` that don't have `files` in the
|
||||
* same config. A pattern such as `/foo` be considered to ignore the directory
|
||||
* while a pattern such as `/foo/**` is not considered to ignore the
|
||||
* directory because it is matching files.
|
||||
* @param {string} directoryPath The path of a directory to check.
|
||||
* @returns {boolean} True if the directory is ignored, false if not. Will
|
||||
* return true for any directory that is not inside of `basePath`.
|
||||
* @throws {Error} When the `ConfigArray` is not normalized.
|
||||
*/
|
||||
isDirectoryIgnored(directoryPath: string): boolean;
|
||||
#private;
|
||||
}
|
||||
export namespace ConfigArraySymbol {
|
||||
let isNormalized: symbol;
|
||||
let configCache: symbol;
|
||||
let schema: symbol;
|
||||
let finalizeConfig: symbol;
|
||||
let preprocessConfig: symbol;
|
||||
}
|
||||
import type * as $eslintobjectschema from "@eslint/object-schema";
|
||||
import type * as $typests from "./types.ts";
|
||||
import type * as $minimatch from "minimatch";
|
||||
import { ObjectSchema } from '@eslint/object-schema';
|
||||
1516
node_modules/@eslint/config-array/dist/esm/index.js
generated
vendored
Normal file
1516
node_modules/@eslint/config-array/dist/esm/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1314
node_modules/@eslint/config-array/dist/esm/std__path/posix.js
generated
vendored
Normal file
1314
node_modules/@eslint/config-array/dist/esm/std__path/posix.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1656
node_modules/@eslint/config-array/dist/esm/std__path/windows.js
generated
vendored
Normal file
1656
node_modules/@eslint/config-array/dist/esm/std__path/windows.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
37
node_modules/@eslint/config-array/dist/esm/types.d.ts
generated
vendored
Normal file
37
node_modules/@eslint/config-array/dist/esm/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @fileoverview Types for the config-array package.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
/**
|
||||
* A file matcher used in `files` and `ignores`.
|
||||
*/
|
||||
export type FileMatcher = string | ((filePath: string) => boolean);
|
||||
/**
|
||||
* An entry in a config's `files` array.
|
||||
*
|
||||
* A subarray means all matchers must match.
|
||||
*/
|
||||
export type FilesMatcher = FileMatcher | FileMatcher[];
|
||||
/**
|
||||
* The config types allowed in the `extraConfigTypes` option.
|
||||
*/
|
||||
export type ExtraConfigType = "array" | "function";
|
||||
export interface ConfigObject {
|
||||
/**
|
||||
* The base path for files and ignores.
|
||||
*/
|
||||
basePath?: string;
|
||||
/**
|
||||
* The files to include.
|
||||
*/
|
||||
files?: FilesMatcher[];
|
||||
/**
|
||||
* The files to exclude.
|
||||
*/
|
||||
ignores?: FileMatcher[];
|
||||
/**
|
||||
* The name of the config object.
|
||||
*/
|
||||
name?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
46
node_modules/@eslint/config-array/dist/esm/types.ts
generated
vendored
Normal file
46
node_modules/@eslint/config-array/dist/esm/types.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @fileoverview Types for the config-array package.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/**
|
||||
* A file matcher used in `files` and `ignores`.
|
||||
*/
|
||||
export type FileMatcher = string | ((filePath: string) => boolean);
|
||||
|
||||
/**
|
||||
* An entry in a config's `files` array.
|
||||
*
|
||||
* A subarray means all matchers must match.
|
||||
*/
|
||||
export type FilesMatcher = FileMatcher | FileMatcher[];
|
||||
|
||||
/**
|
||||
* The config types allowed in the `extraConfigTypes` option.
|
||||
*/
|
||||
export type ExtraConfigType = "array" | "function";
|
||||
|
||||
export interface ConfigObject {
|
||||
/**
|
||||
* The base path for files and ignores.
|
||||
*/
|
||||
basePath?: string;
|
||||
|
||||
/**
|
||||
* The files to include.
|
||||
*/
|
||||
files?: FilesMatcher[];
|
||||
|
||||
/**
|
||||
* The files to exclude.
|
||||
*/
|
||||
ignores?: FileMatcher[];
|
||||
|
||||
/**
|
||||
* The name of the config object.
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
// may also have any number of other properties
|
||||
[key: string]: unknown;
|
||||
}
|
||||
65
node_modules/@eslint/config-array/package.json
generated
vendored
Normal file
65
node_modules/@eslint/config-array/package.json
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "@eslint/config-array",
|
||||
"version": "0.23.5",
|
||||
"description": "General purpose glob-based configuration matching.",
|
||||
"author": "Nicholas C. Zakas",
|
||||
"type": "module",
|
||||
"main": "dist/esm/index.js",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"exports": {
|
||||
"require": {
|
||||
"types": "./dist/cjs/index.d.cts",
|
||||
"default": "./dist/cjs/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/eslint/rewrite.git",
|
||||
"directory": "packages/config-array"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/eslint/rewrite/issues"
|
||||
},
|
||||
"homepage": "https://github.com/eslint/rewrite/tree/main/packages/config-array#readme",
|
||||
"scripts": {
|
||||
"build:dedupe-types": "node ../../tools/dedupe-types.js dist/cjs/index.cjs dist/esm/index.js",
|
||||
"build:cts": "node ../../tools/build-cts.js dist/esm/index.d.ts dist/cjs/index.d.cts",
|
||||
"build:std__path": "rollup -c rollup.std__path-config.js && node fix-std__path-imports",
|
||||
"build": "rollup -c && npm run build:dedupe-types && tsc -p tsconfig.esm.json && npm run build:cts && npm run build:std__path",
|
||||
"lint:types": "attw --pack",
|
||||
"pretest": "npm run build",
|
||||
"test": "npm run test:types && npm run test:unit",
|
||||
"test:coverage": "npm run build && c8 npm run test:unit",
|
||||
"test:jsr": "npx -y jsr@latest publish --dry-run",
|
||||
"test:types": "tsc -p tests/types/tsconfig.json",
|
||||
"test:unit": "mocha \"tests/**/*.test.js\""
|
||||
},
|
||||
"keywords": [
|
||||
"configuration",
|
||||
"configarray",
|
||||
"config file"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/object-schema": "^3.0.5",
|
||||
"debug": "^4.3.1",
|
||||
"minimatch": "^10.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jsr/std__path": "^1.0.4",
|
||||
"rollup-plugin-copy": "^3.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||
}
|
||||
}
|
||||
201
node_modules/@eslint/config-helpers/LICENSE
generated
vendored
Normal file
201
node_modules/@eslint/config-helpers/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
97
node_modules/@eslint/config-helpers/README.md
generated
vendored
Normal file
97
node_modules/@eslint/config-helpers/README.md
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
# @eslint/config-helpers
|
||||
|
||||
## Description
|
||||
|
||||
Helper utilities for creating ESLint configuration.
|
||||
|
||||
## Installation
|
||||
|
||||
For Node.js and compatible runtimes:
|
||||
|
||||
```shell
|
||||
npm install @eslint/config-helpers
|
||||
# or
|
||||
yarn add @eslint/config-helpers
|
||||
# or
|
||||
pnpm install @eslint/config-helpers
|
||||
# or
|
||||
bun add @eslint/config-helpers
|
||||
```
|
||||
|
||||
For Deno:
|
||||
|
||||
```shell
|
||||
deno add @eslint/config-helpers
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### `defineConfig()`
|
||||
|
||||
The `defineConfig()` function allows you to specify an ESLint configuration with full type checking and additional capabilities, such as `extends`. Here's an example:
|
||||
|
||||
```js
|
||||
// eslint.config.js
|
||||
import { defineConfig } from "@eslint/config-helpers";
|
||||
import js from "@eslint/js";
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
files: ["src/**/*.js"],
|
||||
plugins: { js },
|
||||
extends: ["js/recommended"],
|
||||
rules: {
|
||||
"no-var": "error",
|
||||
"prefer-const": "error",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["test/**/*.js"],
|
||||
rules: {
|
||||
"no-console": "off",
|
||||
},
|
||||
},
|
||||
]);
|
||||
```
|
||||
|
||||
### `globalIgnores()`
|
||||
|
||||
The `globalIgnores()` function allows you to specify patterns for files and directories that should be globally ignored by ESLint. This is useful for excluding files that you don't want to lint, such as build directories or third-party libraries. Here's an example:
|
||||
|
||||
```js
|
||||
// eslint.config.js
|
||||
import { defineConfig, globalIgnores } from "@eslint/config-helpers";
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
files: ["src/**/*.js"],
|
||||
rules: {
|
||||
"no-var": "error",
|
||||
"prefer-const": "error",
|
||||
},
|
||||
},
|
||||
globalIgnores(["node_modules/", "dist/", "coverage/"]),
|
||||
]);
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0
|
||||
|
||||
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
||||
<!--sponsorsstart-->
|
||||
|
||||
## Sponsors
|
||||
|
||||
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
|
||||
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
||||
|
||||
<h3>Platinum Sponsors</h3>
|
||||
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a></p><h3>Gold Sponsors</h3>
|
||||
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a></p><h3>Silver Sponsors</h3>
|
||||
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/d472863/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
|
||||
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://opensource.sap.com"><img src="https://avatars.githubusercontent.com/u/2531208" alt="SAP" height="32"></a> <a href="https://www.crawljobs.com/"><img src="https://images.opencollective.com/crawljobs-poland/fa43a17/logo.png" alt="CrawlJobs" height="32"></a> <a href="#"><img src="https://images.opencollective.com/aeriusventilations-org/avatar.png" alt="aeriusventilation's Org" height="32"></a> <a href="https://depot.dev"><img src="https://images.opencollective.com/depot/39125a1/logo.png" alt="Depot" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="TestMu AI Open Source Office (Formerly LambdaTest)" height="32"></a></p>
|
||||
<h3>Technology Sponsors</h3>
|
||||
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
||||
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
||||
<!--sponsorsend-->
|
||||
587
node_modules/@eslint/config-helpers/dist/cjs/index.cjs
generated
vendored
Normal file
587
node_modules/@eslint/config-helpers/dist/cjs/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,587 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @fileoverview defineConfig helper
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @import * as $eslintcore from "@eslint/core"; */
|
||||
/** @typedef {$eslintcore.ConfigObject} Config */
|
||||
/** @typedef {$eslintcore.LegacyConfigObject} LegacyConfig */
|
||||
/** @typedef {$eslintcore.Plugin} Plugin */
|
||||
/** @typedef {$eslintcore.RuleConfig} RuleConfig */
|
||||
/** @import * as $typests from "./types.ts"; */
|
||||
/** @typedef {$typests.ExtendsElement} ExtendsElement */
|
||||
/** @typedef {$typests.ExtensionConfigObject} ExtensionConfigObject */
|
||||
/** @typedef {$typests.SimpleExtendsElement} SimpleExtendsElement */
|
||||
/** @typedef {$typests.ConfigWithExtends} ConfigWithExtends */
|
||||
/** @typedef {$typests.InfiniteArray<Config>} InfiniteConfigArray */
|
||||
/** @typedef {$typests.ConfigWithExtendsArray} ConfigWithExtendsArray */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const eslintrcKeys = [
|
||||
"env",
|
||||
"extends",
|
||||
"globals",
|
||||
"ignorePatterns",
|
||||
"noInlineConfig",
|
||||
"overrides",
|
||||
"parser",
|
||||
"parserOptions",
|
||||
"reportUnusedDisableDirectives",
|
||||
"root",
|
||||
];
|
||||
|
||||
const allowedGlobalIgnoreKeys = new Set(["basePath", "ignores", "name"]);
|
||||
|
||||
/**
|
||||
* Gets the name of a config object.
|
||||
* @param {Config} config The config object.
|
||||
* @param {string} indexPath The index path of the config object.
|
||||
* @return {string} The name of the config object.
|
||||
*/
|
||||
function getConfigName(config, indexPath) {
|
||||
if (config.name) {
|
||||
return config.name;
|
||||
}
|
||||
|
||||
return `UserConfig${indexPath}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of an extension.
|
||||
* @param {SimpleExtendsElement} extension The extension.
|
||||
* @param {string} indexPath The index of the extension.
|
||||
* @return {string} The name of the extension.
|
||||
*/
|
||||
function getExtensionName(extension, indexPath) {
|
||||
if (typeof extension === "string") {
|
||||
return extension;
|
||||
}
|
||||
|
||||
if (extension.name) {
|
||||
return extension.name;
|
||||
}
|
||||
|
||||
return `ExtendedConfig${indexPath}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a config object is a legacy config.
|
||||
* @param {Config|LegacyConfig} config The config object to check.
|
||||
* @return {config is LegacyConfig} `true` if the config object is a legacy config.
|
||||
*/
|
||||
function isLegacyConfig(config) {
|
||||
// eslintrc's plugins must be an array; while flat config's must be an object.
|
||||
if (Array.isArray(config.plugins)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const key of eslintrcKeys) {
|
||||
if (key in config) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a config object is a global ignores config.
|
||||
* @param {Config} config The config object to check.
|
||||
* @return {boolean} `true` if the config object is a global ignores config.
|
||||
*/
|
||||
function isGlobalIgnores(config) {
|
||||
return Object.keys(config).every(key => allowedGlobalIgnoreKeys.has(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a plugin member ID (rule, processor, etc.) and returns
|
||||
* the namespace and member name.
|
||||
* @param {string} id The ID to parse.
|
||||
* @returns {{namespace:string, name:string}} The namespace and member name.
|
||||
*/
|
||||
function getPluginMember(id) {
|
||||
const firstSlashIndex = id.indexOf("/");
|
||||
|
||||
if (firstSlashIndex === -1) {
|
||||
return { namespace: "", name: id };
|
||||
}
|
||||
|
||||
let namespace = id.slice(0, firstSlashIndex);
|
||||
|
||||
/*
|
||||
* Special cases:
|
||||
* 1. The namespace is `@`, that means it's referring to the
|
||||
* core plugin so `@` is the full namespace.
|
||||
* 2. The namespace starts with `@`, that means it's referring to
|
||||
* an npm scoped package. That means the namespace is the scope
|
||||
* and the package name (i.e., `@eslint/core`).
|
||||
*/
|
||||
if (namespace[0] === "@" && namespace !== "@") {
|
||||
const secondSlashIndex = id.indexOf("/", firstSlashIndex + 1);
|
||||
if (secondSlashIndex !== -1) {
|
||||
namespace = id.slice(0, secondSlashIndex);
|
||||
return { namespace, name: id.slice(secondSlashIndex + 1) };
|
||||
}
|
||||
}
|
||||
|
||||
const name = id.slice(firstSlashIndex + 1);
|
||||
|
||||
return { namespace, name };
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the plugin config by replacing the namespace with the plugin namespace.
|
||||
* @param {string} userNamespace The namespace of the plugin.
|
||||
* @param {Plugin} plugin The plugin config object.
|
||||
* @param {Config} config The config object to normalize.
|
||||
* @return {Config} The normalized config object.
|
||||
*/
|
||||
function normalizePluginConfig(userNamespace, plugin, config) {
|
||||
const pluginNamespace = plugin.meta?.namespace;
|
||||
|
||||
// don't do anything if the plugin doesn't have a namespace or rules
|
||||
if (
|
||||
!pluginNamespace ||
|
||||
pluginNamespace === userNamespace ||
|
||||
(!config.rules && !config.processor && !config.language)
|
||||
) {
|
||||
return config;
|
||||
}
|
||||
|
||||
const result = { ...config };
|
||||
|
||||
// update the rules
|
||||
if (result.rules) {
|
||||
const ruleIds = Object.keys(result.rules);
|
||||
|
||||
/** @type {Record<string,RuleConfig|undefined>} */
|
||||
const newRules = {};
|
||||
|
||||
for (let i = 0; i < ruleIds.length; i++) {
|
||||
const ruleId = ruleIds[i];
|
||||
const { namespace: ruleNamespace, name: ruleName } =
|
||||
getPluginMember(ruleId);
|
||||
|
||||
if (ruleNamespace === pluginNamespace) {
|
||||
newRules[`${userNamespace}/${ruleName}`] = result.rules[ruleId];
|
||||
} else {
|
||||
newRules[ruleId] = result.rules[ruleId];
|
||||
}
|
||||
}
|
||||
|
||||
result.rules = newRules;
|
||||
}
|
||||
|
||||
// update the processor
|
||||
|
||||
if (typeof result.processor === "string") {
|
||||
const { namespace: processorNamespace, name: processorName } =
|
||||
getPluginMember(result.processor);
|
||||
|
||||
if (processorNamespace) {
|
||||
if (processorNamespace === pluginNamespace) {
|
||||
result.processor = `${userNamespace}/${processorName}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update the language
|
||||
if (typeof result.language === "string") {
|
||||
const { namespace: languageNamespace, name: languageName } =
|
||||
getPluginMember(result.language);
|
||||
|
||||
if (languageNamespace === pluginNamespace) {
|
||||
result.language = `${userNamespace}/${languageName}`;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deeply normalizes a plugin config, traversing recursively into an arrays.
|
||||
* @param {string} userPluginNamespace The namespace of the plugin.
|
||||
* @param {Plugin} plugin The plugin object.
|
||||
* @param {Config|LegacyConfig|(Config|LegacyConfig)[]} pluginConfig The plugin config to normalize.
|
||||
* @param {string} pluginConfigName The name of the plugin config.
|
||||
* @return {InfiniteConfigArray} The normalized plugin config.
|
||||
* @throws {TypeError} If the plugin config is a legacy config.
|
||||
*/
|
||||
function deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
pluginConfig,
|
||||
pluginConfigName,
|
||||
) {
|
||||
// if it's an array then it's definitely a new config
|
||||
if (Array.isArray(pluginConfig)) {
|
||||
return pluginConfig.map(pluginSubConfig =>
|
||||
deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
pluginSubConfig,
|
||||
pluginConfigName,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// if it's a legacy config, throw an error
|
||||
if (isLegacyConfig(pluginConfig)) {
|
||||
throw new TypeError(
|
||||
`Plugin config "${pluginConfigName}" is an eslintrc config and cannot be used in this context.`,
|
||||
);
|
||||
}
|
||||
|
||||
return normalizePluginConfig(userPluginNamespace, plugin, pluginConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a plugin config by name in the given config.
|
||||
* @param {Config} config The config object.
|
||||
* @param {string} pluginConfigName The name of the plugin config.
|
||||
* @return {InfiniteConfigArray} The plugin config.
|
||||
* @throws {TypeError} If the plugin config is not found or is a legacy config.
|
||||
*/
|
||||
function findPluginConfig(config, pluginConfigName) {
|
||||
const { namespace: userPluginNamespace, name: configName } =
|
||||
getPluginMember(pluginConfigName);
|
||||
const plugin = config.plugins?.[userPluginNamespace];
|
||||
|
||||
if (!plugin) {
|
||||
throw new TypeError(`Plugin "${userPluginNamespace}" not found.`);
|
||||
}
|
||||
|
||||
const directConfig = plugin.configs?.[configName];
|
||||
|
||||
// Prefer direct config, but fall back to flat config if available
|
||||
if (directConfig) {
|
||||
// Arrays are always flat configs, and non-legacy configs can be used directly
|
||||
if (Array.isArray(directConfig) || !isLegacyConfig(directConfig)) {
|
||||
return deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
directConfig,
|
||||
pluginConfigName,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a legacy config, or the config does not exist => look for the flat version
|
||||
const flatConfig = plugin.configs?.[`flat/${configName}`];
|
||||
if (
|
||||
flatConfig &&
|
||||
(Array.isArray(flatConfig) || !isLegacyConfig(flatConfig))
|
||||
) {
|
||||
return deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
flatConfig,
|
||||
pluginConfigName,
|
||||
);
|
||||
}
|
||||
|
||||
// If we get here, then the config was either not found or is a legacy config
|
||||
const message =
|
||||
directConfig || flatConfig
|
||||
? `Plugin config "${configName}" in plugin "${userPluginNamespace}" is an eslintrc config and cannot be used in this context.`
|
||||
: `Plugin config "${configName}" not found in plugin "${userPluginNamespace}".`;
|
||||
throw new TypeError(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens an array while keeping track of the index path.
|
||||
* @param {any[]} configList The array to traverse.
|
||||
* @param {string} indexPath The index path of the value in a multidimensional array.
|
||||
* @return {IterableIterator<{indexPath:string, value:any}>} The flattened list of values.
|
||||
*/
|
||||
function* flatTraverse(configList, indexPath = "") {
|
||||
for (let i = 0; i < configList.length; i++) {
|
||||
const newIndexPath = indexPath ? `${indexPath}[${i}]` : `[${i}]`;
|
||||
|
||||
// if it's an array then traverse it as well
|
||||
if (Array.isArray(configList[i])) {
|
||||
yield* flatTraverse(configList[i], newIndexPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
yield { indexPath: newIndexPath, value: configList[i] };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends a list of config files by creating every combination of base and extension files.
|
||||
* @param {(string|string[])[]} [baseFiles] The base files.
|
||||
* @param {(string|string[])[]} [extensionFiles] The extension files.
|
||||
* @return {(string|string[])[]} The extended files.
|
||||
*/
|
||||
function extendConfigFiles(baseFiles = [], extensionFiles = []) {
|
||||
if (!extensionFiles.length) {
|
||||
return baseFiles.concat();
|
||||
}
|
||||
|
||||
if (!baseFiles.length) {
|
||||
return extensionFiles.concat();
|
||||
}
|
||||
|
||||
/** @type {(string|string[])[]} */
|
||||
const result = [];
|
||||
|
||||
for (const baseFile of baseFiles) {
|
||||
for (const extensionFile of extensionFiles) {
|
||||
/*
|
||||
* Each entry can be a string or array of strings. The end result
|
||||
* needs to be an array of strings, so we need to be sure to include
|
||||
* all of the items when there's an array.
|
||||
*/
|
||||
|
||||
const entry = [];
|
||||
|
||||
if (Array.isArray(baseFile)) {
|
||||
entry.push(...baseFile);
|
||||
} else {
|
||||
entry.push(baseFile);
|
||||
}
|
||||
|
||||
if (Array.isArray(extensionFile)) {
|
||||
entry.push(...extensionFile);
|
||||
} else {
|
||||
entry.push(extensionFile);
|
||||
}
|
||||
|
||||
result.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends a config object with another config object.
|
||||
* @param {Config} baseConfig The base config object.
|
||||
* @param {string} baseConfigName The name of the base config object.
|
||||
* @param {Config} extension The extension config object.
|
||||
* @param {string} extensionName The index of the extension config object.
|
||||
* @return {Config} The extended config object.
|
||||
*/
|
||||
function extendConfig(baseConfig, baseConfigName, extension, extensionName) {
|
||||
const result = { ...extension };
|
||||
|
||||
// for global ignores there is no further work to be done, we just keep everything
|
||||
if (!isGlobalIgnores(extension)) {
|
||||
// for files we need to create every combination of base and extension files
|
||||
if (baseConfig.files) {
|
||||
result.files = extendConfigFiles(baseConfig.files, extension.files);
|
||||
}
|
||||
|
||||
// for ignores we just concatenation the extension ignores onto the base ignores
|
||||
if (baseConfig.ignores) {
|
||||
result.ignores = baseConfig.ignores.concat(extension.ignores ?? []);
|
||||
}
|
||||
}
|
||||
|
||||
result.name = `${baseConfigName} > ${extensionName}`;
|
||||
|
||||
if (baseConfig.basePath) {
|
||||
result.basePath = baseConfig.basePath;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a list of extends elements.
|
||||
* @param {ConfigWithExtends} config The config object.
|
||||
* @param {WeakMap<Config, string>} configNames The map of config objects to their names.
|
||||
* @return {Config[]} The flattened list of config objects.
|
||||
* @throws {TypeError} If the `extends` property is not an array or if nested `extends` is found.
|
||||
*/
|
||||
function processExtends(config, configNames) {
|
||||
if (!config.extends) {
|
||||
return [config];
|
||||
}
|
||||
|
||||
if (!Array.isArray(config.extends)) {
|
||||
throw new TypeError("The `extends` property must be an array.");
|
||||
}
|
||||
|
||||
const {
|
||||
/** @type {Config[]} */
|
||||
extends: extendsList,
|
||||
|
||||
/** @type {Config} */
|
||||
...configObject
|
||||
} = config;
|
||||
|
||||
const extensionNames = new WeakMap();
|
||||
|
||||
// replace strings with the actual configs
|
||||
const objectExtends = extendsList.map(extendsElement => {
|
||||
if (typeof extendsElement === "string") {
|
||||
const pluginConfig = findPluginConfig(config, extendsElement);
|
||||
|
||||
// assign names
|
||||
if (Array.isArray(pluginConfig)) {
|
||||
pluginConfig.forEach((pluginConfigElement, index) => {
|
||||
extensionNames.set(
|
||||
pluginConfigElement,
|
||||
`${extendsElement}[${index}]`,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
extensionNames.set(pluginConfig, extendsElement);
|
||||
}
|
||||
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
return /** @type {Config} */ (extendsElement);
|
||||
});
|
||||
|
||||
const result = [];
|
||||
|
||||
for (const { indexPath, value: extendsElement } of flatTraverse(
|
||||
objectExtends,
|
||||
)) {
|
||||
const extension = /** @type {Config} */ (extendsElement);
|
||||
|
||||
if ("basePath" in extension) {
|
||||
throw new TypeError("'basePath' in `extends` is not allowed.");
|
||||
}
|
||||
|
||||
if ("extends" in extension) {
|
||||
throw new TypeError("Nested 'extends' is not allowed.");
|
||||
}
|
||||
|
||||
const baseConfigName = /** @type {string} */ (configNames.get(config));
|
||||
const extensionName =
|
||||
extensionNames.get(extendsElement) ??
|
||||
getExtensionName(extendsElement, indexPath);
|
||||
|
||||
result.push(
|
||||
extendConfig(
|
||||
configObject,
|
||||
baseConfigName,
|
||||
extension,
|
||||
extensionName,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the base config object has only `ignores` and `extends`, then
|
||||
* removing `extends` turns it into a global ignores, which is not what
|
||||
* we want. So we need to check if the base config object is a global ignores
|
||||
* and if so, we don't add it to the array.
|
||||
*
|
||||
* (The other option would be to add a `files` entry, but that would result
|
||||
* in a config that didn't actually do anything because there are no
|
||||
* other keys in the config.)
|
||||
*/
|
||||
if (!isGlobalIgnores(configObject)) {
|
||||
result.push(configObject);
|
||||
}
|
||||
|
||||
return result.flat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a list of config objects and arrays.
|
||||
* @param {ConfigWithExtends[]} configList The list of config objects and arrays.
|
||||
* @param {WeakMap<Config, string>} configNames The map of config objects to their names.
|
||||
* @return {Config[]} The flattened list of config objects.
|
||||
*/
|
||||
function processConfigList(configList, configNames) {
|
||||
return configList.flatMap(config => processExtends(config, configNames));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helper function to define a config array.
|
||||
* @param {ConfigWithExtendsArray} args The arguments to the function.
|
||||
* @returns {Config[]} The config array.
|
||||
* @throws {TypeError} If no arguments are provided or if an argument is not an object.
|
||||
*/
|
||||
function defineConfig(...args) {
|
||||
const configNames = new WeakMap();
|
||||
const configs = [];
|
||||
|
||||
if (args.length === 0) {
|
||||
throw new TypeError("Expected one or more arguments.");
|
||||
}
|
||||
|
||||
// first flatten the list of configs and get the names
|
||||
for (const { indexPath, value } of flatTraverse(args)) {
|
||||
if (typeof value !== "object" || value === null) {
|
||||
throw new TypeError(
|
||||
`Expected an object but received ${String(value)}.`,
|
||||
);
|
||||
}
|
||||
|
||||
const config = /** @type {ConfigWithExtends} */ (value);
|
||||
|
||||
// save config name for easy reference later
|
||||
configNames.set(config, getConfigName(config, indexPath));
|
||||
configs.push(config);
|
||||
}
|
||||
|
||||
return processConfigList(configs, configNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview Global ignores helper function.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
let globalIgnoreCount = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a global ignores config with the given patterns.
|
||||
* @param {string[]} ignorePatterns The ignore patterns.
|
||||
* @param {string} [name] The name of the global ignores config.
|
||||
* @returns {Config} The global ignores config.
|
||||
* @throws {TypeError} If ignorePatterns is not an array or if it is empty.
|
||||
*/
|
||||
function globalIgnores(ignorePatterns, name) {
|
||||
if (!Array.isArray(ignorePatterns)) {
|
||||
throw new TypeError("ignorePatterns must be an array");
|
||||
}
|
||||
|
||||
if (ignorePatterns.length === 0) {
|
||||
throw new TypeError("ignorePatterns must contain at least one pattern");
|
||||
}
|
||||
|
||||
const id = globalIgnoreCount++;
|
||||
|
||||
return {
|
||||
name: name || `globalIgnores ${id}`,
|
||||
ignores: ignorePatterns,
|
||||
};
|
||||
}
|
||||
|
||||
exports.defineConfig = defineConfig;
|
||||
exports.globalIgnores = globalIgnores;
|
||||
27
node_modules/@eslint/config-helpers/dist/cjs/index.d.cts
generated
vendored
Normal file
27
node_modules/@eslint/config-helpers/dist/cjs/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
export type Config = $eslintcore.ConfigObject;
|
||||
export type LegacyConfig = $eslintcore.LegacyConfigObject;
|
||||
export type Plugin = $eslintcore.Plugin;
|
||||
export type RuleConfig = $eslintcore.RuleConfig;
|
||||
export type ExtendsElement = $typests.ExtendsElement;
|
||||
export type ExtensionConfigObject = $typests.ExtensionConfigObject;
|
||||
export type SimpleExtendsElement = $typests.SimpleExtendsElement;
|
||||
export type ConfigWithExtends = $typests.ConfigWithExtends;
|
||||
export type InfiniteConfigArray = $typests.InfiniteArray<Config>;
|
||||
export type ConfigWithExtendsArray = $typests.ConfigWithExtendsArray;
|
||||
/**
|
||||
* Helper function to define a config array.
|
||||
* @param {ConfigWithExtendsArray} args The arguments to the function.
|
||||
* @returns {Config[]} The config array.
|
||||
* @throws {TypeError} If no arguments are provided or if an argument is not an object.
|
||||
*/
|
||||
export function defineConfig(...args: ConfigWithExtendsArray): Config[];
|
||||
/**
|
||||
* Creates a global ignores config with the given patterns.
|
||||
* @param {string[]} ignorePatterns The ignore patterns.
|
||||
* @param {string} [name] The name of the global ignores config.
|
||||
* @returns {Config} The global ignores config.
|
||||
* @throws {TypeError} If ignorePatterns is not an array or if it is empty.
|
||||
*/
|
||||
export function globalIgnores(ignorePatterns: string[], name?: string): Config;
|
||||
import type * as $eslintcore from "@eslint/core";
|
||||
import type * as $typests from "./types.cts";
|
||||
39
node_modules/@eslint/config-helpers/dist/cjs/types.cts
generated
vendored
Normal file
39
node_modules/@eslint/config-helpers/dist/cjs/types.cts
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @fileoverview Types for this package.
|
||||
*/
|
||||
|
||||
import type { ConfigObject } from "@eslint/core";
|
||||
|
||||
/**
|
||||
* Infinite array type.
|
||||
*/
|
||||
export type InfiniteArray<T> = T | InfiniteArray<T>[];
|
||||
|
||||
/**
|
||||
* A config object that may appear inside of `extends`.
|
||||
* `basePath` and nested `extends` are not allowed on extension config objects.
|
||||
*/
|
||||
export type ExtensionConfigObject = Omit<ConfigObject, "basePath"> & {
|
||||
extends?: never;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of array element in the `extends` property after flattening.
|
||||
*/
|
||||
export type SimpleExtendsElement = string | ExtensionConfigObject;
|
||||
|
||||
/**
|
||||
* The type of array element in the `extends` property before flattening.
|
||||
*/
|
||||
export type ExtendsElement =
|
||||
| SimpleExtendsElement
|
||||
| InfiniteArray<ExtensionConfigObject>;
|
||||
|
||||
/**
|
||||
* Config with extends. Valid only inside of `defineConfig()`.
|
||||
*/
|
||||
export interface ConfigWithExtends extends ConfigObject {
|
||||
extends?: ExtendsElement[];
|
||||
}
|
||||
|
||||
export type ConfigWithExtendsArray = InfiniteArray<ConfigWithExtends>[];
|
||||
27
node_modules/@eslint/config-helpers/dist/esm/index.d.ts
generated
vendored
Normal file
27
node_modules/@eslint/config-helpers/dist/esm/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
export type Config = $eslintcore.ConfigObject;
|
||||
export type LegacyConfig = $eslintcore.LegacyConfigObject;
|
||||
export type Plugin = $eslintcore.Plugin;
|
||||
export type RuleConfig = $eslintcore.RuleConfig;
|
||||
export type ExtendsElement = $typests.ExtendsElement;
|
||||
export type ExtensionConfigObject = $typests.ExtensionConfigObject;
|
||||
export type SimpleExtendsElement = $typests.SimpleExtendsElement;
|
||||
export type ConfigWithExtends = $typests.ConfigWithExtends;
|
||||
export type InfiniteConfigArray = $typests.InfiniteArray<Config>;
|
||||
export type ConfigWithExtendsArray = $typests.ConfigWithExtendsArray;
|
||||
/**
|
||||
* Helper function to define a config array.
|
||||
* @param {ConfigWithExtendsArray} args The arguments to the function.
|
||||
* @returns {Config[]} The config array.
|
||||
* @throws {TypeError} If no arguments are provided or if an argument is not an object.
|
||||
*/
|
||||
export function defineConfig(...args: ConfigWithExtendsArray): Config[];
|
||||
/**
|
||||
* Creates a global ignores config with the given patterns.
|
||||
* @param {string[]} ignorePatterns The ignore patterns.
|
||||
* @param {string} [name] The name of the global ignores config.
|
||||
* @returns {Config} The global ignores config.
|
||||
* @throws {TypeError} If ignorePatterns is not an array or if it is empty.
|
||||
*/
|
||||
export function globalIgnores(ignorePatterns: string[], name?: string): Config;
|
||||
import type * as $eslintcore from "@eslint/core";
|
||||
import type * as $typests from "./types.ts";
|
||||
585
node_modules/@eslint/config-helpers/dist/esm/index.js
generated
vendored
Normal file
585
node_modules/@eslint/config-helpers/dist/esm/index.js
generated
vendored
Normal file
@@ -0,0 +1,585 @@
|
||||
// @ts-self-types="./index.d.ts"
|
||||
/**
|
||||
* @fileoverview defineConfig helper
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @import * as $eslintcore from "@eslint/core"; */
|
||||
/** @typedef {$eslintcore.ConfigObject} Config */
|
||||
/** @typedef {$eslintcore.LegacyConfigObject} LegacyConfig */
|
||||
/** @typedef {$eslintcore.Plugin} Plugin */
|
||||
/** @typedef {$eslintcore.RuleConfig} RuleConfig */
|
||||
/** @import * as $typests from "./types.ts"; */
|
||||
/** @typedef {$typests.ExtendsElement} ExtendsElement */
|
||||
/** @typedef {$typests.ExtensionConfigObject} ExtensionConfigObject */
|
||||
/** @typedef {$typests.SimpleExtendsElement} SimpleExtendsElement */
|
||||
/** @typedef {$typests.ConfigWithExtends} ConfigWithExtends */
|
||||
/** @typedef {$typests.InfiniteArray<Config>} InfiniteConfigArray */
|
||||
/** @typedef {$typests.ConfigWithExtendsArray} ConfigWithExtendsArray */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const eslintrcKeys = [
|
||||
"env",
|
||||
"extends",
|
||||
"globals",
|
||||
"ignorePatterns",
|
||||
"noInlineConfig",
|
||||
"overrides",
|
||||
"parser",
|
||||
"parserOptions",
|
||||
"reportUnusedDisableDirectives",
|
||||
"root",
|
||||
];
|
||||
|
||||
const allowedGlobalIgnoreKeys = new Set(["basePath", "ignores", "name"]);
|
||||
|
||||
/**
|
||||
* Gets the name of a config object.
|
||||
* @param {Config} config The config object.
|
||||
* @param {string} indexPath The index path of the config object.
|
||||
* @return {string} The name of the config object.
|
||||
*/
|
||||
function getConfigName(config, indexPath) {
|
||||
if (config.name) {
|
||||
return config.name;
|
||||
}
|
||||
|
||||
return `UserConfig${indexPath}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of an extension.
|
||||
* @param {SimpleExtendsElement} extension The extension.
|
||||
* @param {string} indexPath The index of the extension.
|
||||
* @return {string} The name of the extension.
|
||||
*/
|
||||
function getExtensionName(extension, indexPath) {
|
||||
if (typeof extension === "string") {
|
||||
return extension;
|
||||
}
|
||||
|
||||
if (extension.name) {
|
||||
return extension.name;
|
||||
}
|
||||
|
||||
return `ExtendedConfig${indexPath}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a config object is a legacy config.
|
||||
* @param {Config|LegacyConfig} config The config object to check.
|
||||
* @return {config is LegacyConfig} `true` if the config object is a legacy config.
|
||||
*/
|
||||
function isLegacyConfig(config) {
|
||||
// eslintrc's plugins must be an array; while flat config's must be an object.
|
||||
if (Array.isArray(config.plugins)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const key of eslintrcKeys) {
|
||||
if (key in config) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a config object is a global ignores config.
|
||||
* @param {Config} config The config object to check.
|
||||
* @return {boolean} `true` if the config object is a global ignores config.
|
||||
*/
|
||||
function isGlobalIgnores(config) {
|
||||
return Object.keys(config).every(key => allowedGlobalIgnoreKeys.has(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a plugin member ID (rule, processor, etc.) and returns
|
||||
* the namespace and member name.
|
||||
* @param {string} id The ID to parse.
|
||||
* @returns {{namespace:string, name:string}} The namespace and member name.
|
||||
*/
|
||||
function getPluginMember(id) {
|
||||
const firstSlashIndex = id.indexOf("/");
|
||||
|
||||
if (firstSlashIndex === -1) {
|
||||
return { namespace: "", name: id };
|
||||
}
|
||||
|
||||
let namespace = id.slice(0, firstSlashIndex);
|
||||
|
||||
/*
|
||||
* Special cases:
|
||||
* 1. The namespace is `@`, that means it's referring to the
|
||||
* core plugin so `@` is the full namespace.
|
||||
* 2. The namespace starts with `@`, that means it's referring to
|
||||
* an npm scoped package. That means the namespace is the scope
|
||||
* and the package name (i.e., `@eslint/core`).
|
||||
*/
|
||||
if (namespace[0] === "@" && namespace !== "@") {
|
||||
const secondSlashIndex = id.indexOf("/", firstSlashIndex + 1);
|
||||
if (secondSlashIndex !== -1) {
|
||||
namespace = id.slice(0, secondSlashIndex);
|
||||
return { namespace, name: id.slice(secondSlashIndex + 1) };
|
||||
}
|
||||
}
|
||||
|
||||
const name = id.slice(firstSlashIndex + 1);
|
||||
|
||||
return { namespace, name };
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the plugin config by replacing the namespace with the plugin namespace.
|
||||
* @param {string} userNamespace The namespace of the plugin.
|
||||
* @param {Plugin} plugin The plugin config object.
|
||||
* @param {Config} config The config object to normalize.
|
||||
* @return {Config} The normalized config object.
|
||||
*/
|
||||
function normalizePluginConfig(userNamespace, plugin, config) {
|
||||
const pluginNamespace = plugin.meta?.namespace;
|
||||
|
||||
// don't do anything if the plugin doesn't have a namespace or rules
|
||||
if (
|
||||
!pluginNamespace ||
|
||||
pluginNamespace === userNamespace ||
|
||||
(!config.rules && !config.processor && !config.language)
|
||||
) {
|
||||
return config;
|
||||
}
|
||||
|
||||
const result = { ...config };
|
||||
|
||||
// update the rules
|
||||
if (result.rules) {
|
||||
const ruleIds = Object.keys(result.rules);
|
||||
|
||||
/** @type {Record<string,RuleConfig|undefined>} */
|
||||
const newRules = {};
|
||||
|
||||
for (let i = 0; i < ruleIds.length; i++) {
|
||||
const ruleId = ruleIds[i];
|
||||
const { namespace: ruleNamespace, name: ruleName } =
|
||||
getPluginMember(ruleId);
|
||||
|
||||
if (ruleNamespace === pluginNamespace) {
|
||||
newRules[`${userNamespace}/${ruleName}`] = result.rules[ruleId];
|
||||
} else {
|
||||
newRules[ruleId] = result.rules[ruleId];
|
||||
}
|
||||
}
|
||||
|
||||
result.rules = newRules;
|
||||
}
|
||||
|
||||
// update the processor
|
||||
|
||||
if (typeof result.processor === "string") {
|
||||
const { namespace: processorNamespace, name: processorName } =
|
||||
getPluginMember(result.processor);
|
||||
|
||||
if (processorNamespace) {
|
||||
if (processorNamespace === pluginNamespace) {
|
||||
result.processor = `${userNamespace}/${processorName}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update the language
|
||||
if (typeof result.language === "string") {
|
||||
const { namespace: languageNamespace, name: languageName } =
|
||||
getPluginMember(result.language);
|
||||
|
||||
if (languageNamespace === pluginNamespace) {
|
||||
result.language = `${userNamespace}/${languageName}`;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deeply normalizes a plugin config, traversing recursively into an arrays.
|
||||
* @param {string} userPluginNamespace The namespace of the plugin.
|
||||
* @param {Plugin} plugin The plugin object.
|
||||
* @param {Config|LegacyConfig|(Config|LegacyConfig)[]} pluginConfig The plugin config to normalize.
|
||||
* @param {string} pluginConfigName The name of the plugin config.
|
||||
* @return {InfiniteConfigArray} The normalized plugin config.
|
||||
* @throws {TypeError} If the plugin config is a legacy config.
|
||||
*/
|
||||
function deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
pluginConfig,
|
||||
pluginConfigName,
|
||||
) {
|
||||
// if it's an array then it's definitely a new config
|
||||
if (Array.isArray(pluginConfig)) {
|
||||
return pluginConfig.map(pluginSubConfig =>
|
||||
deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
pluginSubConfig,
|
||||
pluginConfigName,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// if it's a legacy config, throw an error
|
||||
if (isLegacyConfig(pluginConfig)) {
|
||||
throw new TypeError(
|
||||
`Plugin config "${pluginConfigName}" is an eslintrc config and cannot be used in this context.`,
|
||||
);
|
||||
}
|
||||
|
||||
return normalizePluginConfig(userPluginNamespace, plugin, pluginConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a plugin config by name in the given config.
|
||||
* @param {Config} config The config object.
|
||||
* @param {string} pluginConfigName The name of the plugin config.
|
||||
* @return {InfiniteConfigArray} The plugin config.
|
||||
* @throws {TypeError} If the plugin config is not found or is a legacy config.
|
||||
*/
|
||||
function findPluginConfig(config, pluginConfigName) {
|
||||
const { namespace: userPluginNamespace, name: configName } =
|
||||
getPluginMember(pluginConfigName);
|
||||
const plugin = config.plugins?.[userPluginNamespace];
|
||||
|
||||
if (!plugin) {
|
||||
throw new TypeError(`Plugin "${userPluginNamespace}" not found.`);
|
||||
}
|
||||
|
||||
const directConfig = plugin.configs?.[configName];
|
||||
|
||||
// Prefer direct config, but fall back to flat config if available
|
||||
if (directConfig) {
|
||||
// Arrays are always flat configs, and non-legacy configs can be used directly
|
||||
if (Array.isArray(directConfig) || !isLegacyConfig(directConfig)) {
|
||||
return deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
directConfig,
|
||||
pluginConfigName,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a legacy config, or the config does not exist => look for the flat version
|
||||
const flatConfig = plugin.configs?.[`flat/${configName}`];
|
||||
if (
|
||||
flatConfig &&
|
||||
(Array.isArray(flatConfig) || !isLegacyConfig(flatConfig))
|
||||
) {
|
||||
return deepNormalizePluginConfig(
|
||||
userPluginNamespace,
|
||||
plugin,
|
||||
flatConfig,
|
||||
pluginConfigName,
|
||||
);
|
||||
}
|
||||
|
||||
// If we get here, then the config was either not found or is a legacy config
|
||||
const message =
|
||||
directConfig || flatConfig
|
||||
? `Plugin config "${configName}" in plugin "${userPluginNamespace}" is an eslintrc config and cannot be used in this context.`
|
||||
: `Plugin config "${configName}" not found in plugin "${userPluginNamespace}".`;
|
||||
throw new TypeError(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens an array while keeping track of the index path.
|
||||
* @param {any[]} configList The array to traverse.
|
||||
* @param {string} indexPath The index path of the value in a multidimensional array.
|
||||
* @return {IterableIterator<{indexPath:string, value:any}>} The flattened list of values.
|
||||
*/
|
||||
function* flatTraverse(configList, indexPath = "") {
|
||||
for (let i = 0; i < configList.length; i++) {
|
||||
const newIndexPath = indexPath ? `${indexPath}[${i}]` : `[${i}]`;
|
||||
|
||||
// if it's an array then traverse it as well
|
||||
if (Array.isArray(configList[i])) {
|
||||
yield* flatTraverse(configList[i], newIndexPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
yield { indexPath: newIndexPath, value: configList[i] };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends a list of config files by creating every combination of base and extension files.
|
||||
* @param {(string|string[])[]} [baseFiles] The base files.
|
||||
* @param {(string|string[])[]} [extensionFiles] The extension files.
|
||||
* @return {(string|string[])[]} The extended files.
|
||||
*/
|
||||
function extendConfigFiles(baseFiles = [], extensionFiles = []) {
|
||||
if (!extensionFiles.length) {
|
||||
return baseFiles.concat();
|
||||
}
|
||||
|
||||
if (!baseFiles.length) {
|
||||
return extensionFiles.concat();
|
||||
}
|
||||
|
||||
/** @type {(string|string[])[]} */
|
||||
const result = [];
|
||||
|
||||
for (const baseFile of baseFiles) {
|
||||
for (const extensionFile of extensionFiles) {
|
||||
/*
|
||||
* Each entry can be a string or array of strings. The end result
|
||||
* needs to be an array of strings, so we need to be sure to include
|
||||
* all of the items when there's an array.
|
||||
*/
|
||||
|
||||
const entry = [];
|
||||
|
||||
if (Array.isArray(baseFile)) {
|
||||
entry.push(...baseFile);
|
||||
} else {
|
||||
entry.push(baseFile);
|
||||
}
|
||||
|
||||
if (Array.isArray(extensionFile)) {
|
||||
entry.push(...extensionFile);
|
||||
} else {
|
||||
entry.push(extensionFile);
|
||||
}
|
||||
|
||||
result.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends a config object with another config object.
|
||||
* @param {Config} baseConfig The base config object.
|
||||
* @param {string} baseConfigName The name of the base config object.
|
||||
* @param {Config} extension The extension config object.
|
||||
* @param {string} extensionName The index of the extension config object.
|
||||
* @return {Config} The extended config object.
|
||||
*/
|
||||
function extendConfig(baseConfig, baseConfigName, extension, extensionName) {
|
||||
const result = { ...extension };
|
||||
|
||||
// for global ignores there is no further work to be done, we just keep everything
|
||||
if (!isGlobalIgnores(extension)) {
|
||||
// for files we need to create every combination of base and extension files
|
||||
if (baseConfig.files) {
|
||||
result.files = extendConfigFiles(baseConfig.files, extension.files);
|
||||
}
|
||||
|
||||
// for ignores we just concatenation the extension ignores onto the base ignores
|
||||
if (baseConfig.ignores) {
|
||||
result.ignores = baseConfig.ignores.concat(extension.ignores ?? []);
|
||||
}
|
||||
}
|
||||
|
||||
result.name = `${baseConfigName} > ${extensionName}`;
|
||||
|
||||
if (baseConfig.basePath) {
|
||||
result.basePath = baseConfig.basePath;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a list of extends elements.
|
||||
* @param {ConfigWithExtends} config The config object.
|
||||
* @param {WeakMap<Config, string>} configNames The map of config objects to their names.
|
||||
* @return {Config[]} The flattened list of config objects.
|
||||
* @throws {TypeError} If the `extends` property is not an array or if nested `extends` is found.
|
||||
*/
|
||||
function processExtends(config, configNames) {
|
||||
if (!config.extends) {
|
||||
return [config];
|
||||
}
|
||||
|
||||
if (!Array.isArray(config.extends)) {
|
||||
throw new TypeError("The `extends` property must be an array.");
|
||||
}
|
||||
|
||||
const {
|
||||
/** @type {Config[]} */
|
||||
extends: extendsList,
|
||||
|
||||
/** @type {Config} */
|
||||
...configObject
|
||||
} = config;
|
||||
|
||||
const extensionNames = new WeakMap();
|
||||
|
||||
// replace strings with the actual configs
|
||||
const objectExtends = extendsList.map(extendsElement => {
|
||||
if (typeof extendsElement === "string") {
|
||||
const pluginConfig = findPluginConfig(config, extendsElement);
|
||||
|
||||
// assign names
|
||||
if (Array.isArray(pluginConfig)) {
|
||||
pluginConfig.forEach((pluginConfigElement, index) => {
|
||||
extensionNames.set(
|
||||
pluginConfigElement,
|
||||
`${extendsElement}[${index}]`,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
extensionNames.set(pluginConfig, extendsElement);
|
||||
}
|
||||
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
return /** @type {Config} */ (extendsElement);
|
||||
});
|
||||
|
||||
const result = [];
|
||||
|
||||
for (const { indexPath, value: extendsElement } of flatTraverse(
|
||||
objectExtends,
|
||||
)) {
|
||||
const extension = /** @type {Config} */ (extendsElement);
|
||||
|
||||
if ("basePath" in extension) {
|
||||
throw new TypeError("'basePath' in `extends` is not allowed.");
|
||||
}
|
||||
|
||||
if ("extends" in extension) {
|
||||
throw new TypeError("Nested 'extends' is not allowed.");
|
||||
}
|
||||
|
||||
const baseConfigName = /** @type {string} */ (configNames.get(config));
|
||||
const extensionName =
|
||||
extensionNames.get(extendsElement) ??
|
||||
getExtensionName(extendsElement, indexPath);
|
||||
|
||||
result.push(
|
||||
extendConfig(
|
||||
configObject,
|
||||
baseConfigName,
|
||||
extension,
|
||||
extensionName,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the base config object has only `ignores` and `extends`, then
|
||||
* removing `extends` turns it into a global ignores, which is not what
|
||||
* we want. So we need to check if the base config object is a global ignores
|
||||
* and if so, we don't add it to the array.
|
||||
*
|
||||
* (The other option would be to add a `files` entry, but that would result
|
||||
* in a config that didn't actually do anything because there are no
|
||||
* other keys in the config.)
|
||||
*/
|
||||
if (!isGlobalIgnores(configObject)) {
|
||||
result.push(configObject);
|
||||
}
|
||||
|
||||
return result.flat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a list of config objects and arrays.
|
||||
* @param {ConfigWithExtends[]} configList The list of config objects and arrays.
|
||||
* @param {WeakMap<Config, string>} configNames The map of config objects to their names.
|
||||
* @return {Config[]} The flattened list of config objects.
|
||||
*/
|
||||
function processConfigList(configList, configNames) {
|
||||
return configList.flatMap(config => processExtends(config, configNames));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helper function to define a config array.
|
||||
* @param {ConfigWithExtendsArray} args The arguments to the function.
|
||||
* @returns {Config[]} The config array.
|
||||
* @throws {TypeError} If no arguments are provided or if an argument is not an object.
|
||||
*/
|
||||
function defineConfig(...args) {
|
||||
const configNames = new WeakMap();
|
||||
const configs = [];
|
||||
|
||||
if (args.length === 0) {
|
||||
throw new TypeError("Expected one or more arguments.");
|
||||
}
|
||||
|
||||
// first flatten the list of configs and get the names
|
||||
for (const { indexPath, value } of flatTraverse(args)) {
|
||||
if (typeof value !== "object" || value === null) {
|
||||
throw new TypeError(
|
||||
`Expected an object but received ${String(value)}.`,
|
||||
);
|
||||
}
|
||||
|
||||
const config = /** @type {ConfigWithExtends} */ (value);
|
||||
|
||||
// save config name for easy reference later
|
||||
configNames.set(config, getConfigName(config, indexPath));
|
||||
configs.push(config);
|
||||
}
|
||||
|
||||
return processConfigList(configs, configNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview Global ignores helper function.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
let globalIgnoreCount = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a global ignores config with the given patterns.
|
||||
* @param {string[]} ignorePatterns The ignore patterns.
|
||||
* @param {string} [name] The name of the global ignores config.
|
||||
* @returns {Config} The global ignores config.
|
||||
* @throws {TypeError} If ignorePatterns is not an array or if it is empty.
|
||||
*/
|
||||
function globalIgnores(ignorePatterns, name) {
|
||||
if (!Array.isArray(ignorePatterns)) {
|
||||
throw new TypeError("ignorePatterns must be an array");
|
||||
}
|
||||
|
||||
if (ignorePatterns.length === 0) {
|
||||
throw new TypeError("ignorePatterns must contain at least one pattern");
|
||||
}
|
||||
|
||||
const id = globalIgnoreCount++;
|
||||
|
||||
return {
|
||||
name: name || `globalIgnores ${id}`,
|
||||
ignores: ignorePatterns,
|
||||
};
|
||||
}
|
||||
|
||||
export { defineConfig, globalIgnores };
|
||||
30
node_modules/@eslint/config-helpers/dist/esm/types.d.ts
generated
vendored
Normal file
30
node_modules/@eslint/config-helpers/dist/esm/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @fileoverview Types for this package.
|
||||
*/
|
||||
import type { ConfigObject } from "@eslint/core";
|
||||
/**
|
||||
* Infinite array type.
|
||||
*/
|
||||
export type InfiniteArray<T> = T | InfiniteArray<T>[];
|
||||
/**
|
||||
* A config object that may appear inside of `extends`.
|
||||
* `basePath` and nested `extends` are not allowed on extension config objects.
|
||||
*/
|
||||
export type ExtensionConfigObject = Omit<ConfigObject, "basePath"> & {
|
||||
extends?: never;
|
||||
};
|
||||
/**
|
||||
* The type of array element in the `extends` property after flattening.
|
||||
*/
|
||||
export type SimpleExtendsElement = string | ExtensionConfigObject;
|
||||
/**
|
||||
* The type of array element in the `extends` property before flattening.
|
||||
*/
|
||||
export type ExtendsElement = SimpleExtendsElement | InfiniteArray<ExtensionConfigObject>;
|
||||
/**
|
||||
* Config with extends. Valid only inside of `defineConfig()`.
|
||||
*/
|
||||
export interface ConfigWithExtends extends ConfigObject {
|
||||
extends?: ExtendsElement[];
|
||||
}
|
||||
export type ConfigWithExtendsArray = InfiniteArray<ConfigWithExtends>[];
|
||||
39
node_modules/@eslint/config-helpers/dist/esm/types.ts
generated
vendored
Normal file
39
node_modules/@eslint/config-helpers/dist/esm/types.ts
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @fileoverview Types for this package.
|
||||
*/
|
||||
|
||||
import type { ConfigObject } from "@eslint/core";
|
||||
|
||||
/**
|
||||
* Infinite array type.
|
||||
*/
|
||||
export type InfiniteArray<T> = T | InfiniteArray<T>[];
|
||||
|
||||
/**
|
||||
* A config object that may appear inside of `extends`.
|
||||
* `basePath` and nested `extends` are not allowed on extension config objects.
|
||||
*/
|
||||
export type ExtensionConfigObject = Omit<ConfigObject, "basePath"> & {
|
||||
extends?: never;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of array element in the `extends` property after flattening.
|
||||
*/
|
||||
export type SimpleExtendsElement = string | ExtensionConfigObject;
|
||||
|
||||
/**
|
||||
* The type of array element in the `extends` property before flattening.
|
||||
*/
|
||||
export type ExtendsElement =
|
||||
| SimpleExtendsElement
|
||||
| InfiniteArray<ExtensionConfigObject>;
|
||||
|
||||
/**
|
||||
* Config with extends. Valid only inside of `defineConfig()`.
|
||||
*/
|
||||
export interface ConfigWithExtends extends ConfigObject {
|
||||
extends?: ExtendsElement[];
|
||||
}
|
||||
|
||||
export type ConfigWithExtendsArray = InfiniteArray<ConfigWithExtends>[];
|
||||
62
node_modules/@eslint/config-helpers/package.json
generated
vendored
Normal file
62
node_modules/@eslint/config-helpers/package.json
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "@eslint/config-helpers",
|
||||
"version": "0.5.5",
|
||||
"description": "Helper utilities for creating ESLint configuration",
|
||||
"type": "module",
|
||||
"main": "dist/esm/index.js",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"exports": {
|
||||
"require": {
|
||||
"types": "./dist/cjs/index.d.cts",
|
||||
"default": "./dist/cjs/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"build:dedupe-types": "node ../../tools/dedupe-types.js dist/cjs/index.cjs dist/esm/index.js",
|
||||
"build:cts": "node ../../tools/build-cts.js dist/esm/index.d.ts dist/cjs/index.d.cts",
|
||||
"build": "rollup -c && npm run build:dedupe-types && tsc -p tsconfig.esm.json && npm run build:cts",
|
||||
"lint:types": "attw --pack",
|
||||
"pretest": "npm run build",
|
||||
"test": "npm run test:types && npm run test:unit",
|
||||
"test:coverage": "c8 npm run test:unit",
|
||||
"test:jsr": "npx -y jsr@latest publish --dry-run",
|
||||
"test:pnpm": "cd tests/pnpm && pnpm install && pnpm exec tsc",
|
||||
"test:types": "tsc -p tests/types/tsconfig.json",
|
||||
"test:unit": "mocha \"tests/**/*.test.js\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/eslint/rewrite.git",
|
||||
"directory": "packages/config-helpers"
|
||||
},
|
||||
"keywords": [
|
||||
"eslint"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/eslint/rewrite/issues"
|
||||
},
|
||||
"homepage": "https://github.com/eslint/rewrite/tree/main/packages/config-helpers#readme",
|
||||
"dependencies": {
|
||||
"@eslint/core": "^1.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rollup-plugin-copy": "^3.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||
}
|
||||
}
|
||||
201
node_modules/@eslint/core/LICENSE
generated
vendored
Normal file
201
node_modules/@eslint/core/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
29
node_modules/@eslint/core/README.md
generated
vendored
Normal file
29
node_modules/@eslint/core/README.md
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# ESLint Core
|
||||
|
||||
## Overview
|
||||
|
||||
This package is the future home of the rewritten, runtime-agnostic ESLint core.
|
||||
|
||||
Right now, it exports the core types necessary to implement language plugins.
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0
|
||||
|
||||
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
||||
<!--sponsorsstart-->
|
||||
|
||||
## Sponsors
|
||||
|
||||
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
|
||||
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
||||
|
||||
<h3>Platinum Sponsors</h3>
|
||||
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a></p><h3>Gold Sponsors</h3>
|
||||
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a></p><h3>Silver Sponsors</h3>
|
||||
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/d472863/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
|
||||
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://opensource.sap.com"><img src="https://avatars.githubusercontent.com/u/2531208" alt="SAP" height="32"></a> <a href="https://www.crawljobs.com/"><img src="https://images.opencollective.com/crawljobs-poland/fa43a17/logo.png" alt="CrawlJobs" height="32"></a> <a href="#"><img src="https://images.opencollective.com/aeriusventilations-org/avatar.png" alt="aeriusventilation's Org" height="32"></a> <a href="https://depot.dev"><img src="https://images.opencollective.com/depot/39125a1/logo.png" alt="Depot" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="TestMu AI Open Source Office (Formerly LambdaTest)" height="32"></a></p>
|
||||
<h3>Technology Sponsors</h3>
|
||||
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
||||
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
||||
<!--sponsorsend-->
|
||||
1159
node_modules/@eslint/core/dist/cjs/types.d.cts
generated
vendored
Normal file
1159
node_modules/@eslint/core/dist/cjs/types.d.cts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1159
node_modules/@eslint/core/dist/esm/types.d.ts
generated
vendored
Normal file
1159
node_modules/@eslint/core/dist/esm/types.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
52
node_modules/@eslint/core/package.json
generated
vendored
Normal file
52
node_modules/@eslint/core/package.json
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "@eslint/core",
|
||||
"version": "1.2.1",
|
||||
"description": "Runtime-agnostic core of ESLint",
|
||||
"type": "module",
|
||||
"types": "./dist/esm/types.d.ts",
|
||||
"exports": {
|
||||
"types": {
|
||||
"import": "./dist/esm/types.d.ts",
|
||||
"require": "./dist/cjs/types.d.cts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"build:cts": "node -e \"fs.cpSync('dist/esm/types.d.ts', 'dist/cjs/types.d.cts')\"",
|
||||
"build": "tsc && npm run build:cts",
|
||||
"lint:types": "attw --pack",
|
||||
"pretest": "npm run build",
|
||||
"test": "npm run test:types",
|
||||
"test:jsr": "npx -y jsr@latest publish --dry-run",
|
||||
"test:types": "tsc -p tests/types/tsconfig.json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/eslint/rewrite.git",
|
||||
"directory": "packages/core"
|
||||
},
|
||||
"keywords": [
|
||||
"eslint",
|
||||
"core"
|
||||
],
|
||||
"author": "Nicholas C. Zakas",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/eslint/rewrite/issues"
|
||||
},
|
||||
"homepage": "https://github.com/eslint/rewrite/tree/main/packages/core#readme",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"json-schema": "^0.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||
}
|
||||
}
|
||||
19
node_modules/@eslint/js/LICENSE
generated
vendored
Normal file
19
node_modules/@eslint/js/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
103
node_modules/@eslint/js/README.md
generated
vendored
Normal file
103
node_modules/@eslint/js/README.md
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
[](https://www.npmjs.com/package/@eslint/js)
|
||||
[](https://www.npmjs.com/package/@eslint/js)
|
||||
[](https://github.com/eslint/eslint/actions)
|
||||
<br>
|
||||
[](https://opencollective.com/eslint)
|
||||
[](https://opencollective.com/eslint)
|
||||
|
||||
# ESLint JavaScript Plugin
|
||||
|
||||
[Website](https://eslint.org) |
|
||||
[Configure ESLint](https://eslint.org/docs/latest/use/configure) |
|
||||
[Rules](https://eslint.org/docs/rules/) |
|
||||
[Contribute to ESLint](https://eslint.org/docs/latest/contribute) |
|
||||
[Report Bugs](https://eslint.org/docs/latest/contribute/report-bugs) |
|
||||
[Code of Conduct](https://eslint.org/conduct) |
|
||||
[X](https://x.com/geteslint) |
|
||||
[Discord](https://eslint.org/chat) |
|
||||
[Mastodon](https://fosstodon.org/@eslint) |
|
||||
[Bluesky](https://bsky.app/profile/eslint.org)
|
||||
|
||||
The beginnings of separating out JavaScript-specific functionality from ESLint.
|
||||
|
||||
Right now, this plugin contains two configurations:
|
||||
|
||||
- `recommended` - enables the rules recommended by the ESLint team (the replacement for `"eslint:recommended"`)
|
||||
- `all` - enables all ESLint rules (the replacement for `"eslint:all"`)
|
||||
|
||||
## Installation
|
||||
|
||||
You can install ESLint using npm or other package managers:
|
||||
|
||||
```shell
|
||||
npm install eslint -D
|
||||
# or
|
||||
yarn add eslint -D
|
||||
# or
|
||||
pnpm install eslint -D
|
||||
# or
|
||||
bun add eslint -D
|
||||
```
|
||||
|
||||
Then install this plugin:
|
||||
|
||||
```shell
|
||||
npm install @eslint/js -D
|
||||
# or
|
||||
yarn add @eslint/js -D
|
||||
# or
|
||||
pnpm install @eslint/js -D
|
||||
# or
|
||||
bun add @eslint/js -D
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Use in your `eslint.config.js` file anytime you want to extend one of the configs:
|
||||
|
||||
```js
|
||||
import { defineConfig } from "eslint/config";
|
||||
import js from "@eslint/js";
|
||||
|
||||
export default defineConfig([
|
||||
// apply recommended rules to JS files
|
||||
{
|
||||
name: "your-project/recommended-rules",
|
||||
files: ["**/*.js"],
|
||||
plugins: {
|
||||
js,
|
||||
},
|
||||
extends: ["js/recommended"],
|
||||
},
|
||||
|
||||
// apply recommended rules to JS files with an override
|
||||
{
|
||||
name: "your-project/recommended-rules-with-override",
|
||||
files: ["**/*.js"],
|
||||
plugins: {
|
||||
js,
|
||||
},
|
||||
extends: ["js/recommended"],
|
||||
rules: {
|
||||
"no-unused-vars": "warn",
|
||||
},
|
||||
},
|
||||
|
||||
// apply all rules to JS files
|
||||
{
|
||||
name: "your-project/all-rules",
|
||||
files: ["**/*.js"],
|
||||
plugins: {
|
||||
js,
|
||||
},
|
||||
extends: ["js/all"],
|
||||
rules: {
|
||||
"no-unused-vars": "warn",
|
||||
},
|
||||
},
|
||||
]);
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
44
node_modules/@eslint/js/package.json
generated
vendored
Normal file
44
node_modules/@eslint/js/package.json
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@eslint/js",
|
||||
"version": "10.0.1",
|
||||
"description": "ESLint JavaScript language implementation",
|
||||
"funding": "https://eslint.org/donate",
|
||||
"main": "./src/index.js",
|
||||
"types": "./types/index.d.ts",
|
||||
"scripts": {
|
||||
"test:types": "tsc -p tests/types/tsconfig.json"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"src",
|
||||
"types"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/eslint/eslint.git",
|
||||
"directory": "packages/js"
|
||||
},
|
||||
"homepage": "https://eslint.org",
|
||||
"bugs": "https://github.com/eslint/eslint/issues/",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"eslint-plugin",
|
||||
"eslint"
|
||||
],
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"eslint": "^10.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"eslint": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||
}
|
||||
}
|
||||
210
node_modules/@eslint/js/src/configs/eslint-all.js
generated
vendored
Normal file
210
node_modules/@eslint/js/src/configs/eslint-all.js
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* WARNING: This file is autogenerated using the tools/update-eslint-all.js
|
||||
* script. Do not edit manually.
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
module.exports = Object.freeze({
|
||||
name: "@eslint/js/all",
|
||||
rules: Object.freeze({
|
||||
"accessor-pairs": "error",
|
||||
"array-callback-return": "error",
|
||||
"arrow-body-style": "error",
|
||||
"block-scoped-var": "error",
|
||||
"camelcase": "error",
|
||||
"capitalized-comments": "error",
|
||||
"class-methods-use-this": "error",
|
||||
"complexity": "error",
|
||||
"consistent-return": "error",
|
||||
"consistent-this": "error",
|
||||
"constructor-super": "error",
|
||||
"curly": "error",
|
||||
"default-case": "error",
|
||||
"default-case-last": "error",
|
||||
"default-param-last": "error",
|
||||
"dot-notation": "error",
|
||||
"eqeqeq": "error",
|
||||
"for-direction": "error",
|
||||
"func-name-matching": "error",
|
||||
"func-names": "error",
|
||||
"func-style": "error",
|
||||
"getter-return": "error",
|
||||
"grouped-accessor-pairs": "error",
|
||||
"guard-for-in": "error",
|
||||
"id-denylist": "error",
|
||||
"id-length": "error",
|
||||
"id-match": "error",
|
||||
"init-declarations": "error",
|
||||
"logical-assignment-operators": "error",
|
||||
"max-classes-per-file": "error",
|
||||
"max-depth": "error",
|
||||
"max-lines": "error",
|
||||
"max-lines-per-function": "error",
|
||||
"max-nested-callbacks": "error",
|
||||
"max-params": "error",
|
||||
"max-statements": "error",
|
||||
"new-cap": "error",
|
||||
"no-alert": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
"no-await-in-loop": "error",
|
||||
"no-bitwise": "error",
|
||||
"no-caller": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-class-assign": "error",
|
||||
"no-compare-neg-zero": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-console": "error",
|
||||
"no-const-assign": "error",
|
||||
"no-constant-binary-expression": "error",
|
||||
"no-constant-condition": "error",
|
||||
"no-constructor-return": "error",
|
||||
"no-continue": "error",
|
||||
"no-control-regex": "error",
|
||||
"no-debugger": "error",
|
||||
"no-delete-var": "error",
|
||||
"no-div-regex": "error",
|
||||
"no-dupe-args": "error",
|
||||
"no-dupe-class-members": "error",
|
||||
"no-dupe-else-if": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-else-return": "error",
|
||||
"no-empty": "error",
|
||||
"no-empty-character-class": "error",
|
||||
"no-empty-function": "error",
|
||||
"no-empty-pattern": "error",
|
||||
"no-empty-static-block": "error",
|
||||
"no-eq-null": "error",
|
||||
"no-eval": "error",
|
||||
"no-ex-assign": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-extra-boolean-cast": "error",
|
||||
"no-extra-label": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-global-assign": "error",
|
||||
"no-implicit-coercion": "error",
|
||||
"no-implicit-globals": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-import-assign": "error",
|
||||
"no-inline-comments": "error",
|
||||
"no-inner-declarations": "error",
|
||||
"no-invalid-regexp": "error",
|
||||
"no-invalid-this": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-iterator": "error",
|
||||
"no-label-var": "error",
|
||||
"no-labels": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-lonely-if": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-loss-of-precision": "error",
|
||||
"no-magic-numbers": "error",
|
||||
"no-misleading-character-class": "error",
|
||||
"no-multi-assign": "error",
|
||||
"no-multi-str": "error",
|
||||
"no-negated-condition": "error",
|
||||
"no-nested-ternary": "error",
|
||||
"no-new": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-native-nonconstructor": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-nonoctal-decimal-escape": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-object-constructor": "error",
|
||||
"no-octal": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": "error",
|
||||
"no-plusplus": "error",
|
||||
"no-promise-executor-return": "error",
|
||||
"no-proto": "error",
|
||||
"no-prototype-builtins": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-regex-spaces": "error",
|
||||
"no-restricted-exports": "error",
|
||||
"no-restricted-globals": "error",
|
||||
"no-restricted-imports": "error",
|
||||
"no-restricted-properties": "error",
|
||||
"no-restricted-syntax": "error",
|
||||
"no-return-assign": "error",
|
||||
"no-script-url": "error",
|
||||
"no-self-assign": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
"no-setter-return": "error",
|
||||
"no-shadow": "error",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-ternary": "error",
|
||||
"no-this-before-super": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-unassigned-vars": "error",
|
||||
"no-undef": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-undefined": "error",
|
||||
"no-underscore-dangle": "error",
|
||||
"no-unexpected-multiline": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unneeded-ternary": "error",
|
||||
"no-unreachable": "error",
|
||||
"no-unreachable-loop": "error",
|
||||
"no-unsafe-finally": "error",
|
||||
"no-unsafe-negation": "error",
|
||||
"no-unsafe-optional-chaining": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-unused-labels": "error",
|
||||
"no-unused-private-class-members": "error",
|
||||
"no-unused-vars": "error",
|
||||
"no-use-before-define": "error",
|
||||
"no-useless-assignment": "error",
|
||||
"no-useless-backreference": "error",
|
||||
"no-useless-call": "error",
|
||||
"no-useless-catch": "error",
|
||||
"no-useless-computed-key": "error",
|
||||
"no-useless-concat": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-useless-escape": "error",
|
||||
"no-useless-rename": "error",
|
||||
"no-useless-return": "error",
|
||||
"no-var": "error",
|
||||
"no-void": "error",
|
||||
"no-warning-comments": "error",
|
||||
"no-with": "error",
|
||||
"object-shorthand": "error",
|
||||
"one-var": "error",
|
||||
"operator-assignment": "error",
|
||||
"prefer-arrow-callback": "error",
|
||||
"prefer-const": "error",
|
||||
"prefer-destructuring": "error",
|
||||
"prefer-exponentiation-operator": "error",
|
||||
"prefer-named-capture-group": "error",
|
||||
"prefer-numeric-literals": "error",
|
||||
"prefer-object-has-own": "error",
|
||||
"prefer-object-spread": "error",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"prefer-regex-literals": "error",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error",
|
||||
"prefer-template": "error",
|
||||
"preserve-caught-error": "error",
|
||||
"radix": "error",
|
||||
"require-atomic-updates": "error",
|
||||
"require-await": "error",
|
||||
"require-unicode-regexp": "error",
|
||||
"require-yield": "error",
|
||||
"sort-imports": "error",
|
||||
"sort-keys": "error",
|
||||
"sort-vars": "error",
|
||||
"strict": "error",
|
||||
"symbol-description": "error",
|
||||
"unicode-bom": "error",
|
||||
"use-isnan": "error",
|
||||
"valid-typeof": "error",
|
||||
"vars-on-top": "error",
|
||||
"yoda": "error"
|
||||
})
|
||||
});
|
||||
75
node_modules/@eslint/js/src/configs/eslint-recommended.js
generated
vendored
Normal file
75
node_modules/@eslint/js/src/configs/eslint-recommended.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* WARNING: This file is autogenerated using the tools/update-eslint-recommended.js
|
||||
* script. Do not edit manually.
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
module.exports = Object.freeze({
|
||||
name: "@eslint/js/recommended",
|
||||
rules: Object.freeze({
|
||||
"constructor-super": "error",
|
||||
"for-direction": "error",
|
||||
"getter-return": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-class-assign": "error",
|
||||
"no-compare-neg-zero": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-const-assign": "error",
|
||||
"no-constant-binary-expression": "error",
|
||||
"no-constant-condition": "error",
|
||||
"no-control-regex": "error",
|
||||
"no-debugger": "error",
|
||||
"no-delete-var": "error",
|
||||
"no-dupe-args": "error",
|
||||
"no-dupe-class-members": "error",
|
||||
"no-dupe-else-if": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-empty": "error",
|
||||
"no-empty-character-class": "error",
|
||||
"no-empty-pattern": "error",
|
||||
"no-empty-static-block": "error",
|
||||
"no-ex-assign": "error",
|
||||
"no-extra-boolean-cast": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-global-assign": "error",
|
||||
"no-import-assign": "error",
|
||||
"no-invalid-regexp": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-loss-of-precision": "error",
|
||||
"no-misleading-character-class": "error",
|
||||
"no-new-native-nonconstructor": "error",
|
||||
"no-nonoctal-decimal-escape": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-octal": "error",
|
||||
"no-prototype-builtins": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-regex-spaces": "error",
|
||||
"no-self-assign": "error",
|
||||
"no-setter-return": "error",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-this-before-super": "error",
|
||||
"no-unassigned-vars": "error",
|
||||
"no-undef": "error",
|
||||
"no-unexpected-multiline": "error",
|
||||
"no-unreachable": "error",
|
||||
"no-unsafe-finally": "error",
|
||||
"no-unsafe-negation": "error",
|
||||
"no-unsafe-optional-chaining": "error",
|
||||
"no-unused-labels": "error",
|
||||
"no-unused-private-class-members": "error",
|
||||
"no-unused-vars": "error",
|
||||
"no-useless-assignment": "error",
|
||||
"no-useless-backreference": "error",
|
||||
"no-useless-catch": "error",
|
||||
"no-useless-escape": "error",
|
||||
"no-with": "error",
|
||||
"preserve-caught-error": "error",
|
||||
"require-yield": "error",
|
||||
"use-isnan": "error",
|
||||
"valid-typeof": "error"
|
||||
}),
|
||||
});
|
||||
23
node_modules/@eslint/js/src/index.js
generated
vendored
Normal file
23
node_modules/@eslint/js/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @fileoverview Main package entrypoint.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { name, version } = require("../package.json");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
name,
|
||||
version,
|
||||
},
|
||||
configs: {
|
||||
all: require("./configs/eslint-all"),
|
||||
recommended: require("./configs/eslint-recommended"),
|
||||
},
|
||||
};
|
||||
14
node_modules/@eslint/js/types/index.d.ts
generated
vendored
Normal file
14
node_modules/@eslint/js/types/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { Linter } from "eslint";
|
||||
|
||||
declare const js: {
|
||||
readonly meta: {
|
||||
readonly name: string;
|
||||
readonly version: string;
|
||||
};
|
||||
readonly configs: {
|
||||
readonly recommended: { readonly rules: Readonly<Linter.RulesRecord> };
|
||||
readonly all: { readonly rules: Readonly<Linter.RulesRecord> };
|
||||
};
|
||||
};
|
||||
|
||||
export = js;
|
||||
201
node_modules/@eslint/object-schema/LICENSE
generated
vendored
Normal file
201
node_modules/@eslint/object-schema/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
275
node_modules/@eslint/object-schema/README.md
generated
vendored
Normal file
275
node_modules/@eslint/object-schema/README.md
generated
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
# ObjectSchema Package
|
||||
|
||||
## Overview
|
||||
|
||||
A JavaScript object merge/validation utility where you can define a different merge and validation strategy for each key. This is helpful when you need to validate complex data structures and then merge them in a way that is more complex than `Object.assign()`. This is used in the [`@eslint/config-array`](https://npmjs.com/package/@eslint/config-array) package but can also be used on its own.
|
||||
|
||||
## Installation
|
||||
|
||||
For Node.js and compatible runtimes:
|
||||
|
||||
```shell
|
||||
npm install @eslint/object-schema
|
||||
# or
|
||||
yarn add @eslint/object-schema
|
||||
# or
|
||||
pnpm install @eslint/object-schema
|
||||
# or
|
||||
bun add @eslint/object-schema
|
||||
```
|
||||
|
||||
For Deno:
|
||||
|
||||
```shell
|
||||
deno add @eslint/object-schema
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Import the `ObjectSchema` constructor:
|
||||
|
||||
```js
|
||||
// using ESM
|
||||
import { ObjectSchema } from "@eslint/object-schema";
|
||||
|
||||
// using CommonJS
|
||||
const { ObjectSchema } = require("@eslint/object-schema");
|
||||
|
||||
const schema = new ObjectSchema({
|
||||
// define a definition for the "downloads" key
|
||||
downloads: {
|
||||
required: true,
|
||||
merge(value1 = 0, value2) {
|
||||
return value1 + value2;
|
||||
},
|
||||
validate(value) {
|
||||
if (typeof value !== "number") {
|
||||
throw new Error("Expected downloads to be a number.");
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// define a strategy for the "versions" key
|
||||
versions: {
|
||||
required: true,
|
||||
merge(value1 = [], value2) {
|
||||
return value1.concat(value2);
|
||||
},
|
||||
validate(value) {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error("Expected versions to be an array.");
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const record1 = {
|
||||
downloads: 25,
|
||||
versions: ["v1.0.0", "v1.1.0", "v1.2.0"],
|
||||
};
|
||||
|
||||
const record2 = {
|
||||
downloads: 125,
|
||||
versions: ["v2.0.0", "v2.1.0", "v3.0.0"],
|
||||
};
|
||||
|
||||
// make sure the records are valid
|
||||
schema.validate(record1);
|
||||
schema.validate(record2);
|
||||
|
||||
// merge together (schema.merge() accepts any number of objects)
|
||||
const result = schema.merge(record1, record2);
|
||||
|
||||
// result looks like this:
|
||||
// {
|
||||
// downloads: 150,
|
||||
// versions: ["v1.0.0", "v1.1.0", "v1.2.0", "v2.0.0", "v2.1.0", "v3.0.0"],
|
||||
// }
|
||||
```
|
||||
|
||||
## Tips and Tricks
|
||||
|
||||
### Named merge strategies
|
||||
|
||||
Instead of specifying a `merge()` method, you can specify one of the following strings to use a default merge strategy:
|
||||
|
||||
- `"assign"` - use `Object.assign()` to merge the two values into one object.
|
||||
- `"overwrite"` - the second value always replaces the first.
|
||||
- `"replace"` - the second value replaces the first if the second is not `undefined`.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
const schema = new ObjectSchema({
|
||||
name: {
|
||||
merge: "replace",
|
||||
validate() {},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Named validation strategies
|
||||
|
||||
Instead of specifying a `validate()` method, you can specify one of the following strings to use a default validation strategy:
|
||||
|
||||
- `"array"` - value must be an array.
|
||||
- `"boolean"` - value must be a boolean.
|
||||
- `"number"` - value must be a number.
|
||||
- `"object"` - value must be a non-null object, including arrays and non-plain objects.
|
||||
- `"object?"` - value must be an object or null, including arrays and non-plain objects.
|
||||
- `"string"` - value must be a string.
|
||||
- `"string!"` - value must be a non-empty string.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
const schema = new ObjectSchema({
|
||||
name: {
|
||||
merge: "replace",
|
||||
validate: "string",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Built-in strategy classes
|
||||
|
||||
The package also exports the built-in merge and validation strategies as two classes with static methods:
|
||||
|
||||
- `MergeStrategy` - built-in merge functions (`assign`, `overwrite`, `replace`).
|
||||
- `ValidationStrategy` - built-in validation functions (`array`, `boolean`, `number`, `object`, `object?`, `string`, `string!`).
|
||||
|
||||
These are the same strategies used when you specify a strategy by name (for example, `merge: "replace"`). You can reference the functions directly if you prefer passing a function instead of a string:
|
||||
|
||||
```js
|
||||
import {
|
||||
ObjectSchema,
|
||||
MergeStrategy,
|
||||
ValidationStrategy,
|
||||
} from "@eslint/object-schema";
|
||||
|
||||
const schema = new ObjectSchema({
|
||||
name: {
|
||||
required: true,
|
||||
merge: MergeStrategy.replace,
|
||||
validate: ValidationStrategy["string!"],
|
||||
},
|
||||
options: {
|
||||
required: false,
|
||||
merge: MergeStrategy.assign,
|
||||
validate: ValidationStrategy["object?"],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Note: Because `object?` and `string!` aren't valid identifiers, you must access them using bracket notation (for example, `ValidationStrategy["object?"]`).
|
||||
|
||||
### Subschemas
|
||||
|
||||
If you are defining a key that is, itself, an object, you can simplify the process by using a subschema. Instead of defining `merge()` and `validate()`, set a `schema` property that contains a schema definition, like this:
|
||||
|
||||
```js
|
||||
const schema = new ObjectSchema({
|
||||
name: {
|
||||
schema: {
|
||||
first: {
|
||||
merge: "replace",
|
||||
validate: "string",
|
||||
},
|
||||
last: {
|
||||
merge: "replace",
|
||||
validate: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
schema.validate({
|
||||
name: {
|
||||
first: "n",
|
||||
last: "z",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Remove Keys During Merge
|
||||
|
||||
If the merge strategy for a key returns `undefined`, then the key will not appear in the final object. For example:
|
||||
|
||||
```js
|
||||
const schema = new ObjectSchema({
|
||||
date: {
|
||||
merge() {
|
||||
return undefined;
|
||||
},
|
||||
validate(value) {
|
||||
if (isNaN(Date.parse(value))) {
|
||||
throw new Error("Invalid date.");
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const object1 = { date: "5/5/2005" };
|
||||
const object2 = { date: "6/6/2006" };
|
||||
|
||||
const result = schema.merge(object1, object2);
|
||||
|
||||
console.log("date" in result); // false
|
||||
```
|
||||
|
||||
### Requiring Another Key Be Present
|
||||
|
||||
If you'd like the presence of one key to require the presence of another key, you can use the `requires` property to specify an array of other properties that any key requires. For example:
|
||||
|
||||
```js
|
||||
const schema = new ObjectSchema({
|
||||
date: {
|
||||
merge() {
|
||||
return undefined;
|
||||
},
|
||||
validate(value) {
|
||||
if (isNaN(Date.parse(value))) {
|
||||
throw new Error("Invalid date.");
|
||||
}
|
||||
},
|
||||
},
|
||||
time: {
|
||||
requires: ["date"],
|
||||
merge(first, second) {
|
||||
return second;
|
||||
},
|
||||
validate(value) {
|
||||
// ...
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// throws error: Key "time" requires keys "date".
|
||||
schema.validate({
|
||||
time: "13:45",
|
||||
});
|
||||
```
|
||||
|
||||
In this example, even though `date` is an optional key, it is required to be present whenever `time` is present.
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0
|
||||
|
||||
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
||||
<!--sponsorsstart-->
|
||||
|
||||
## Sponsors
|
||||
|
||||
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
|
||||
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
||||
|
||||
<h3>Platinum Sponsors</h3>
|
||||
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a></p><h3>Gold Sponsors</h3>
|
||||
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a></p><h3>Silver Sponsors</h3>
|
||||
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/d472863/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
|
||||
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://opensource.sap.com"><img src="https://avatars.githubusercontent.com/u/2531208" alt="SAP" height="32"></a> <a href="https://www.crawljobs.com/"><img src="https://images.opencollective.com/crawljobs-poland/fa43a17/logo.png" alt="CrawlJobs" height="32"></a> <a href="#"><img src="https://images.opencollective.com/aeriusventilations-org/avatar.png" alt="aeriusventilation's Org" height="32"></a> <a href="https://depot.dev"><img src="https://images.opencollective.com/depot/39125a1/logo.png" alt="Depot" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="TestMu AI Open Source Office (Formerly LambdaTest)" height="32"></a></p>
|
||||
<h3>Technology Sponsors</h3>
|
||||
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
||||
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
||||
<!--sponsorsend-->
|
||||
470
node_modules/@eslint/object-schema/dist/cjs/index.cjs
generated
vendored
Normal file
470
node_modules/@eslint/object-schema/dist/cjs/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,470 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @fileoverview Merge Strategy
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Container class for several different merge strategies.
|
||||
*/
|
||||
class MergeStrategy {
|
||||
/**
|
||||
* Merges two keys by overwriting the first with the second.
|
||||
* @template TValue1 The type of the value from the first object key.
|
||||
* @template TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {TValue2} The second value.
|
||||
*/
|
||||
static overwrite(value1, value2) {
|
||||
return value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two keys by replacing the first with the second only if the
|
||||
* second is defined.
|
||||
* @template TValue1 The type of the value from the first object key.
|
||||
* @template TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {TValue1 | TValue2} The second value if it is defined.
|
||||
*/
|
||||
static replace(value1, value2) {
|
||||
if (typeof value2 !== "undefined") {
|
||||
return value2;
|
||||
}
|
||||
|
||||
return value1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two properties by assigning properties from the second to the first.
|
||||
* @template {Record<string | number | symbol, unknown> | undefined} TValue1 The type of the value from the first object key.
|
||||
* @template {Record<string | number | symbol, unknown>} TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {Omit<TValue1, keyof TValue2> & TValue2} A new object containing properties from both value1 and
|
||||
* value2.
|
||||
*/
|
||||
static assign(value1, value2) {
|
||||
return Object.assign({}, value1, value2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview Validation Strategy
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Container class for several different validation strategies.
|
||||
*/
|
||||
class ValidationStrategy {
|
||||
/**
|
||||
* Validates that a value is an array.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static array(value) {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new TypeError("Expected an array.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is a boolean.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static boolean(value) {
|
||||
if (typeof value !== "boolean") {
|
||||
throw new TypeError("Expected a boolean.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is a number.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static number(value) {
|
||||
if (typeof value !== "number") {
|
||||
throw new TypeError("Expected a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is an object.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static object(value) {
|
||||
if (!value || typeof value !== "object") {
|
||||
throw new TypeError("Expected an object.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is an object or null.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static "object?"(value) {
|
||||
if (typeof value !== "object") {
|
||||
throw new TypeError("Expected an object or null.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is a string.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static string(value) {
|
||||
if (typeof value !== "string") {
|
||||
throw new TypeError("Expected a string.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is a non-empty string.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static "string!"(value) {
|
||||
if (typeof value !== "string" || value.length === 0) {
|
||||
throw new TypeError("Expected a non-empty string.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview Object Schema
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @import * as $typests from "./types.ts"; */
|
||||
/** @typedef {$typests.BuiltInMergeStrategy} BuiltInMergeStrategy */
|
||||
/** @typedef {$typests.BuiltInValidationStrategy} BuiltInValidationStrategy */
|
||||
/** @typedef {$typests.CustomMergeStrategy} CustomMergeStrategy */
|
||||
/** @typedef {$typests.CustomValidationStrategy} CustomValidationStrategy */
|
||||
/** @typedef {$typests.ObjectDefinition} ObjectDefinition */
|
||||
/** @typedef {$typests.PropertyDefinition} PropertyDefinition */
|
||||
/** @typedef {$typests.PropertyDefinitionWithSchema} PropertyDefinitionWithSchema */
|
||||
/** @typedef {$typests.PropertyDefinitionWithStrategies} PropertyDefinitionWithStrategies */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Private
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validates a schema strategy.
|
||||
* @param {string} name The name of the key this strategy is for.
|
||||
* @param {PropertyDefinition} definition The strategy for the object key.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} When the strategy is missing a name.
|
||||
* @throws {TypeError} When the strategy is missing a merge() method.
|
||||
* @throws {TypeError} When the strategy is missing a validate() method.
|
||||
*/
|
||||
function validateDefinition(name, definition) {
|
||||
let hasSchema = false;
|
||||
if (definition.schema) {
|
||||
if (typeof definition.schema === "object") {
|
||||
hasSchema = true;
|
||||
} else {
|
||||
throw new TypeError("Schema must be an object.");
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof definition.merge === "string") {
|
||||
if (!(definition.merge in MergeStrategy)) {
|
||||
throw new TypeError(
|
||||
`Definition for key "${name}" missing valid merge strategy.`,
|
||||
);
|
||||
}
|
||||
} else if (!hasSchema && typeof definition.merge !== "function") {
|
||||
throw new TypeError(
|
||||
`Definition for key "${name}" must have a merge property.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof definition.validate === "string") {
|
||||
if (!(definition.validate in ValidationStrategy)) {
|
||||
throw new TypeError(
|
||||
`Definition for key "${name}" missing valid validation strategy.`,
|
||||
);
|
||||
}
|
||||
} else if (!hasSchema && typeof definition.validate !== "function") {
|
||||
throw new TypeError(
|
||||
`Definition for key "${name}" must have a validate() method.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Errors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Error when an unexpected key is found.
|
||||
*/
|
||||
class UnexpectedKeyError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} key The key that was unexpected.
|
||||
*/
|
||||
constructor(key) {
|
||||
super(`Unexpected key "${key}" found.`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error when a required key is missing.
|
||||
*/
|
||||
class MissingKeyError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} key The key that was missing.
|
||||
*/
|
||||
constructor(key) {
|
||||
super(`Missing required key "${key}".`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error when a key requires other keys that are missing.
|
||||
*/
|
||||
class MissingDependentKeysError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} key The key that was unexpected.
|
||||
* @param {Array<string>} requiredKeys The keys that are required.
|
||||
*/
|
||||
constructor(key, requiredKeys) {
|
||||
super(`Key "${key}" requires keys "${requiredKeys.join('", "')}".`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper error for errors occuring during a merge or validate operation.
|
||||
*/
|
||||
class WrapperError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} key The object key causing the error.
|
||||
* @param {Error} source The source error.
|
||||
*/
|
||||
constructor(key, source) {
|
||||
super(`Key "${key}": ${source.message}`, { cause: source });
|
||||
|
||||
// copy over custom properties that aren't represented
|
||||
for (const sourceKey of Object.keys(source)) {
|
||||
if (!(sourceKey in this)) {
|
||||
this[sourceKey] = source[sourceKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Represents an object validation/merging schema.
|
||||
*/
|
||||
class ObjectSchema {
|
||||
/**
|
||||
* Track all definitions in the schema by key.
|
||||
* @type {Map<string, PropertyDefinition>}
|
||||
*/
|
||||
#definitions = new Map();
|
||||
|
||||
/**
|
||||
* Separately track any keys that are required for faster validation.
|
||||
* @type {Map<string, PropertyDefinition>}
|
||||
*/
|
||||
#requiredKeys = new Map();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {ObjectDefinition} definitions The schema definitions.
|
||||
* @throws {Error} When the definitions are missing or invalid.
|
||||
*/
|
||||
constructor(definitions) {
|
||||
if (!definitions) {
|
||||
throw new Error("Schema definitions missing.");
|
||||
}
|
||||
|
||||
// add in all strategies
|
||||
for (const key of Object.keys(definitions)) {
|
||||
const definition = definitions[key];
|
||||
|
||||
validateDefinition(key, definition);
|
||||
|
||||
let normalizedDefinition = definition;
|
||||
|
||||
// normalize merge and validate methods if subschema is present
|
||||
if (typeof normalizedDefinition.schema === "object") {
|
||||
const schema = new ObjectSchema(normalizedDefinition.schema);
|
||||
normalizedDefinition = {
|
||||
...normalizedDefinition,
|
||||
merge(first = {}, second = {}) {
|
||||
return schema.merge(first, second);
|
||||
},
|
||||
validate(value) {
|
||||
ValidationStrategy.object(value);
|
||||
schema.validate(value);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// normalize the merge method in case there's a string
|
||||
if (typeof normalizedDefinition.merge === "string") {
|
||||
normalizedDefinition = {
|
||||
...normalizedDefinition,
|
||||
merge: MergeStrategy[normalizedDefinition.merge],
|
||||
};
|
||||
}
|
||||
|
||||
// normalize the validate method in case there's a string
|
||||
if (typeof normalizedDefinition.validate === "string") {
|
||||
normalizedDefinition = {
|
||||
...normalizedDefinition,
|
||||
validate: ValidationStrategy[normalizedDefinition.validate],
|
||||
};
|
||||
}
|
||||
|
||||
this.#definitions.set(key, normalizedDefinition);
|
||||
|
||||
if (normalizedDefinition.required) {
|
||||
this.#requiredKeys.set(key, normalizedDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a strategy has been registered for the given object key.
|
||||
* @param {string} key The object key to find a strategy for.
|
||||
* @returns {boolean} True if the key has a strategy registered, false if not.
|
||||
*/
|
||||
hasKey(key) {
|
||||
return this.#definitions.has(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges objects together to create a new object comprised of the keys
|
||||
* of the all objects. Keys are merged based on the each key's merge
|
||||
* strategy.
|
||||
* @param {...Object} objects The objects to merge.
|
||||
* @returns {Object} A new object with a mix of all objects' keys.
|
||||
* @throws {TypeError} If any object is invalid.
|
||||
*/
|
||||
merge(...objects) {
|
||||
// double check arguments
|
||||
if (objects.length < 2) {
|
||||
throw new TypeError("merge() requires at least two arguments.");
|
||||
}
|
||||
|
||||
if (
|
||||
objects.some(
|
||||
object => object === null || typeof object !== "object",
|
||||
)
|
||||
) {
|
||||
throw new TypeError("All arguments must be objects.");
|
||||
}
|
||||
|
||||
return objects.reduce((result, object) => {
|
||||
this.validate(object);
|
||||
|
||||
for (const [key, strategy] of this.#definitions) {
|
||||
try {
|
||||
if (key in result || key in object) {
|
||||
const merge = /** @type {Function} */ (strategy.merge);
|
||||
const value = merge.call(
|
||||
this,
|
||||
result[key],
|
||||
object[key],
|
||||
);
|
||||
if (value !== undefined) {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
throw new WrapperError(key, ex);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an object's keys based on the validate strategy for each key.
|
||||
* @param {Object} object The object to validate.
|
||||
* @returns {void}
|
||||
* @throws {Error} When the object is invalid.
|
||||
*/
|
||||
validate(object) {
|
||||
// check existing keys first
|
||||
for (const key of Object.keys(object)) {
|
||||
// check to see if the key is defined
|
||||
if (!this.hasKey(key)) {
|
||||
throw new UnexpectedKeyError(key);
|
||||
}
|
||||
|
||||
// validate existing keys
|
||||
const definition = /** @type {PropertyDefinition} */ (
|
||||
this.#definitions.get(key)
|
||||
); // `definition` is guaranteed to exist since we check with `hasKey()` above.
|
||||
|
||||
// first check to see if any other keys are required
|
||||
if (Array.isArray(definition.requires)) {
|
||||
if (
|
||||
!definition.requires.every(otherKey => otherKey in object)
|
||||
) {
|
||||
throw new MissingDependentKeysError(
|
||||
key,
|
||||
definition.requires,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// now apply remaining validation strategy
|
||||
try {
|
||||
const validate = /** @type {Function} */ (definition.validate);
|
||||
validate.call(definition, object[key]);
|
||||
} catch (ex) {
|
||||
throw new WrapperError(key, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure required keys aren't missing
|
||||
for (const [key] of this.#requiredKeys) {
|
||||
if (!(key in object)) {
|
||||
throw new MissingKeyError(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.MergeStrategy = MergeStrategy;
|
||||
exports.ObjectSchema = ObjectSchema;
|
||||
exports.ValidationStrategy = ValidationStrategy;
|
||||
137
node_modules/@eslint/object-schema/dist/cjs/index.d.cts
generated
vendored
Normal file
137
node_modules/@eslint/object-schema/dist/cjs/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
export type BuiltInMergeStrategy = $typests.BuiltInMergeStrategy;
|
||||
export type BuiltInValidationStrategy = $typests.BuiltInValidationStrategy;
|
||||
export type CustomMergeStrategy = $typests.CustomMergeStrategy;
|
||||
export type CustomValidationStrategy = $typests.CustomValidationStrategy;
|
||||
export type ObjectDefinition = $typests.ObjectDefinition;
|
||||
export type PropertyDefinition = $typests.PropertyDefinition;
|
||||
export type PropertyDefinitionWithSchema = $typests.PropertyDefinitionWithSchema;
|
||||
export type PropertyDefinitionWithStrategies = $typests.PropertyDefinitionWithStrategies;
|
||||
/**
|
||||
* @fileoverview Merge Strategy
|
||||
*/
|
||||
/**
|
||||
* Container class for several different merge strategies.
|
||||
*/
|
||||
export class MergeStrategy {
|
||||
/**
|
||||
* Merges two keys by overwriting the first with the second.
|
||||
* @template TValue1 The type of the value from the first object key.
|
||||
* @template TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {TValue2} The second value.
|
||||
*/
|
||||
static overwrite<TValue1, TValue2>(value1: TValue1, value2: TValue2): TValue2;
|
||||
/**
|
||||
* Merges two keys by replacing the first with the second only if the
|
||||
* second is defined.
|
||||
* @template TValue1 The type of the value from the first object key.
|
||||
* @template TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {TValue1 | TValue2} The second value if it is defined.
|
||||
*/
|
||||
static replace<TValue1, TValue2>(value1: TValue1, value2: TValue2): TValue1 | TValue2;
|
||||
/**
|
||||
* Merges two properties by assigning properties from the second to the first.
|
||||
* @template {Record<string | number | symbol, unknown> | undefined} TValue1 The type of the value from the first object key.
|
||||
* @template {Record<string | number | symbol, unknown>} TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {Omit<TValue1, keyof TValue2> & TValue2} A new object containing properties from both value1 and
|
||||
* value2.
|
||||
*/
|
||||
static assign<TValue1 extends Record<string | number | symbol, unknown> | undefined, TValue2 extends Record<string | number | symbol, unknown>>(value1: TValue1, value2: TValue2): Omit<TValue1, keyof TValue2> & TValue2;
|
||||
}
|
||||
/**
|
||||
* Represents an object validation/merging schema.
|
||||
*/
|
||||
export class ObjectSchema {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {ObjectDefinition} definitions The schema definitions.
|
||||
* @throws {Error} When the definitions are missing or invalid.
|
||||
*/
|
||||
constructor(definitions: ObjectDefinition);
|
||||
/**
|
||||
* Determines if a strategy has been registered for the given object key.
|
||||
* @param {string} key The object key to find a strategy for.
|
||||
* @returns {boolean} True if the key has a strategy registered, false if not.
|
||||
*/
|
||||
hasKey(key: string): boolean;
|
||||
/**
|
||||
* Merges objects together to create a new object comprised of the keys
|
||||
* of the all objects. Keys are merged based on the each key's merge
|
||||
* strategy.
|
||||
* @param {...Object} objects The objects to merge.
|
||||
* @returns {Object} A new object with a mix of all objects' keys.
|
||||
* @throws {TypeError} If any object is invalid.
|
||||
*/
|
||||
merge(...objects: any[]): any;
|
||||
/**
|
||||
* Validates an object's keys based on the validate strategy for each key.
|
||||
* @param {Object} object The object to validate.
|
||||
* @returns {void}
|
||||
* @throws {Error} When the object is invalid.
|
||||
*/
|
||||
validate(object: any): void;
|
||||
#private;
|
||||
}
|
||||
/**
|
||||
* @fileoverview Validation Strategy
|
||||
*/
|
||||
/**
|
||||
* Container class for several different validation strategies.
|
||||
*/
|
||||
export class ValidationStrategy {
|
||||
/**
|
||||
* Validates that a value is an array.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static array(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is a boolean.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static boolean(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is a number.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static number(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is an object.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static object(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is an object or null.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static "object?"(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is a string.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static string(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is a non-empty string.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static "string!"(value: unknown): void;
|
||||
}
|
||||
import type * as $typests from "./types.cts";
|
||||
98
node_modules/@eslint/object-schema/dist/cjs/types.cts
generated
vendored
Normal file
98
node_modules/@eslint/object-schema/dist/cjs/types.cts
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @fileoverview Types for object-schema package.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Built-in validation strategies.
|
||||
*/
|
||||
export type BuiltInValidationStrategy =
|
||||
| "array"
|
||||
| "boolean"
|
||||
| "number"
|
||||
| "object"
|
||||
| "object?"
|
||||
| "string"
|
||||
| "string!";
|
||||
|
||||
/**
|
||||
* Built-in merge strategies.
|
||||
*/
|
||||
export type BuiltInMergeStrategy = "assign" | "overwrite" | "replace";
|
||||
|
||||
/**
|
||||
* Custom merge strategy.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/eslint/rewrite/pull/90#discussion_r1687206213
|
||||
export type CustomMergeStrategy = (target: any, source: any) => any;
|
||||
|
||||
/**
|
||||
* Custom validation strategy.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/eslint/rewrite/pull/90#discussion_r1687206213
|
||||
export type CustomValidationStrategy = (value: any) => void;
|
||||
|
||||
interface BasePropertyDefinition {
|
||||
/**
|
||||
* Indicates if the property is required.
|
||||
*/
|
||||
required?: boolean;
|
||||
|
||||
/**
|
||||
* The other properties that must be present when this property is used.
|
||||
*/
|
||||
requires?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Property definition that specifies explicit merge and validation strategies.
|
||||
* This form cannot include a `schema`.
|
||||
*/
|
||||
export interface PropertyDefinitionWithStrategies extends BasePropertyDefinition {
|
||||
/**
|
||||
* The schema for the object value of this property.
|
||||
*/
|
||||
schema?: never;
|
||||
|
||||
/**
|
||||
* The strategy to merge the property.
|
||||
*/
|
||||
merge: BuiltInMergeStrategy | CustomMergeStrategy;
|
||||
|
||||
/**
|
||||
* The strategy to validate the property.
|
||||
*/
|
||||
validate: BuiltInValidationStrategy | CustomValidationStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property definition that uses a nested `schema`.
|
||||
* When `schema` is present, merge and validation strategies are optional.
|
||||
*/
|
||||
export interface PropertyDefinitionWithSchema extends BasePropertyDefinition {
|
||||
/**
|
||||
* The schema for the object value of this property.
|
||||
*/
|
||||
schema: ObjectDefinition;
|
||||
|
||||
/**
|
||||
* The strategy to merge the property.
|
||||
*/
|
||||
merge?: BuiltInMergeStrategy | CustomMergeStrategy;
|
||||
|
||||
/**
|
||||
* The strategy to validate the property.
|
||||
*/
|
||||
validate?: BuiltInValidationStrategy | CustomValidationStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property definition.
|
||||
*/
|
||||
export type PropertyDefinition =
|
||||
| PropertyDefinitionWithStrategies
|
||||
| PropertyDefinitionWithSchema;
|
||||
|
||||
/**
|
||||
* Object definition.
|
||||
*/
|
||||
export type ObjectDefinition = Record<string, PropertyDefinition>;
|
||||
137
node_modules/@eslint/object-schema/dist/esm/index.d.ts
generated
vendored
Normal file
137
node_modules/@eslint/object-schema/dist/esm/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
export type BuiltInMergeStrategy = $typests.BuiltInMergeStrategy;
|
||||
export type BuiltInValidationStrategy = $typests.BuiltInValidationStrategy;
|
||||
export type CustomMergeStrategy = $typests.CustomMergeStrategy;
|
||||
export type CustomValidationStrategy = $typests.CustomValidationStrategy;
|
||||
export type ObjectDefinition = $typests.ObjectDefinition;
|
||||
export type PropertyDefinition = $typests.PropertyDefinition;
|
||||
export type PropertyDefinitionWithSchema = $typests.PropertyDefinitionWithSchema;
|
||||
export type PropertyDefinitionWithStrategies = $typests.PropertyDefinitionWithStrategies;
|
||||
/**
|
||||
* @fileoverview Merge Strategy
|
||||
*/
|
||||
/**
|
||||
* Container class for several different merge strategies.
|
||||
*/
|
||||
export class MergeStrategy {
|
||||
/**
|
||||
* Merges two keys by overwriting the first with the second.
|
||||
* @template TValue1 The type of the value from the first object key.
|
||||
* @template TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {TValue2} The second value.
|
||||
*/
|
||||
static overwrite<TValue1, TValue2>(value1: TValue1, value2: TValue2): TValue2;
|
||||
/**
|
||||
* Merges two keys by replacing the first with the second only if the
|
||||
* second is defined.
|
||||
* @template TValue1 The type of the value from the first object key.
|
||||
* @template TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {TValue1 | TValue2} The second value if it is defined.
|
||||
*/
|
||||
static replace<TValue1, TValue2>(value1: TValue1, value2: TValue2): TValue1 | TValue2;
|
||||
/**
|
||||
* Merges two properties by assigning properties from the second to the first.
|
||||
* @template {Record<string | number | symbol, unknown> | undefined} TValue1 The type of the value from the first object key.
|
||||
* @template {Record<string | number | symbol, unknown>} TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {Omit<TValue1, keyof TValue2> & TValue2} A new object containing properties from both value1 and
|
||||
* value2.
|
||||
*/
|
||||
static assign<TValue1 extends Record<string | number | symbol, unknown> | undefined, TValue2 extends Record<string | number | symbol, unknown>>(value1: TValue1, value2: TValue2): Omit<TValue1, keyof TValue2> & TValue2;
|
||||
}
|
||||
/**
|
||||
* Represents an object validation/merging schema.
|
||||
*/
|
||||
export class ObjectSchema {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {ObjectDefinition} definitions The schema definitions.
|
||||
* @throws {Error} When the definitions are missing or invalid.
|
||||
*/
|
||||
constructor(definitions: ObjectDefinition);
|
||||
/**
|
||||
* Determines if a strategy has been registered for the given object key.
|
||||
* @param {string} key The object key to find a strategy for.
|
||||
* @returns {boolean} True if the key has a strategy registered, false if not.
|
||||
*/
|
||||
hasKey(key: string): boolean;
|
||||
/**
|
||||
* Merges objects together to create a new object comprised of the keys
|
||||
* of the all objects. Keys are merged based on the each key's merge
|
||||
* strategy.
|
||||
* @param {...Object} objects The objects to merge.
|
||||
* @returns {Object} A new object with a mix of all objects' keys.
|
||||
* @throws {TypeError} If any object is invalid.
|
||||
*/
|
||||
merge(...objects: any[]): any;
|
||||
/**
|
||||
* Validates an object's keys based on the validate strategy for each key.
|
||||
* @param {Object} object The object to validate.
|
||||
* @returns {void}
|
||||
* @throws {Error} When the object is invalid.
|
||||
*/
|
||||
validate(object: any): void;
|
||||
#private;
|
||||
}
|
||||
/**
|
||||
* @fileoverview Validation Strategy
|
||||
*/
|
||||
/**
|
||||
* Container class for several different validation strategies.
|
||||
*/
|
||||
export class ValidationStrategy {
|
||||
/**
|
||||
* Validates that a value is an array.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static array(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is a boolean.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static boolean(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is a number.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static number(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is an object.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static object(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is an object or null.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static "object?"(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is a string.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static string(value: unknown): void;
|
||||
/**
|
||||
* Validates that a value is a non-empty string.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static "string!"(value: unknown): void;
|
||||
}
|
||||
import type * as $typests from "./types.ts";
|
||||
467
node_modules/@eslint/object-schema/dist/esm/index.js
generated
vendored
Normal file
467
node_modules/@eslint/object-schema/dist/esm/index.js
generated
vendored
Normal file
@@ -0,0 +1,467 @@
|
||||
// @ts-self-types="./index.d.ts"
|
||||
/**
|
||||
* @fileoverview Merge Strategy
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Container class for several different merge strategies.
|
||||
*/
|
||||
class MergeStrategy {
|
||||
/**
|
||||
* Merges two keys by overwriting the first with the second.
|
||||
* @template TValue1 The type of the value from the first object key.
|
||||
* @template TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {TValue2} The second value.
|
||||
*/
|
||||
static overwrite(value1, value2) {
|
||||
return value2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two keys by replacing the first with the second only if the
|
||||
* second is defined.
|
||||
* @template TValue1 The type of the value from the first object key.
|
||||
* @template TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {TValue1 | TValue2} The second value if it is defined.
|
||||
*/
|
||||
static replace(value1, value2) {
|
||||
if (typeof value2 !== "undefined") {
|
||||
return value2;
|
||||
}
|
||||
|
||||
return value1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two properties by assigning properties from the second to the first.
|
||||
* @template {Record<string | number | symbol, unknown> | undefined} TValue1 The type of the value from the first object key.
|
||||
* @template {Record<string | number | symbol, unknown>} TValue2 The type of the value from the second object key.
|
||||
* @param {TValue1} value1 The value from the first object key.
|
||||
* @param {TValue2} value2 The value from the second object key.
|
||||
* @returns {Omit<TValue1, keyof TValue2> & TValue2} A new object containing properties from both value1 and
|
||||
* value2.
|
||||
*/
|
||||
static assign(value1, value2) {
|
||||
return Object.assign({}, value1, value2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview Validation Strategy
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Container class for several different validation strategies.
|
||||
*/
|
||||
class ValidationStrategy {
|
||||
/**
|
||||
* Validates that a value is an array.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static array(value) {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new TypeError("Expected an array.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is a boolean.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static boolean(value) {
|
||||
if (typeof value !== "boolean") {
|
||||
throw new TypeError("Expected a boolean.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is a number.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static number(value) {
|
||||
if (typeof value !== "number") {
|
||||
throw new TypeError("Expected a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is an object.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static object(value) {
|
||||
if (!value || typeof value !== "object") {
|
||||
throw new TypeError("Expected an object.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is an object or null.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static "object?"(value) {
|
||||
if (typeof value !== "object") {
|
||||
throw new TypeError("Expected an object or null.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is a string.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static string(value) {
|
||||
if (typeof value !== "string") {
|
||||
throw new TypeError("Expected a string.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is a non-empty string.
|
||||
* @param {unknown} value The value to validate.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value is invalid.
|
||||
*/
|
||||
static "string!"(value) {
|
||||
if (typeof value !== "string" || value.length === 0) {
|
||||
throw new TypeError("Expected a non-empty string.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview Object Schema
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @import * as $typests from "./types.ts"; */
|
||||
/** @typedef {$typests.BuiltInMergeStrategy} BuiltInMergeStrategy */
|
||||
/** @typedef {$typests.BuiltInValidationStrategy} BuiltInValidationStrategy */
|
||||
/** @typedef {$typests.CustomMergeStrategy} CustomMergeStrategy */
|
||||
/** @typedef {$typests.CustomValidationStrategy} CustomValidationStrategy */
|
||||
/** @typedef {$typests.ObjectDefinition} ObjectDefinition */
|
||||
/** @typedef {$typests.PropertyDefinition} PropertyDefinition */
|
||||
/** @typedef {$typests.PropertyDefinitionWithSchema} PropertyDefinitionWithSchema */
|
||||
/** @typedef {$typests.PropertyDefinitionWithStrategies} PropertyDefinitionWithStrategies */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Private
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validates a schema strategy.
|
||||
* @param {string} name The name of the key this strategy is for.
|
||||
* @param {PropertyDefinition} definition The strategy for the object key.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} When the strategy is missing a name.
|
||||
* @throws {TypeError} When the strategy is missing a merge() method.
|
||||
* @throws {TypeError} When the strategy is missing a validate() method.
|
||||
*/
|
||||
function validateDefinition(name, definition) {
|
||||
let hasSchema = false;
|
||||
if (definition.schema) {
|
||||
if (typeof definition.schema === "object") {
|
||||
hasSchema = true;
|
||||
} else {
|
||||
throw new TypeError("Schema must be an object.");
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof definition.merge === "string") {
|
||||
if (!(definition.merge in MergeStrategy)) {
|
||||
throw new TypeError(
|
||||
`Definition for key "${name}" missing valid merge strategy.`,
|
||||
);
|
||||
}
|
||||
} else if (!hasSchema && typeof definition.merge !== "function") {
|
||||
throw new TypeError(
|
||||
`Definition for key "${name}" must have a merge property.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof definition.validate === "string") {
|
||||
if (!(definition.validate in ValidationStrategy)) {
|
||||
throw new TypeError(
|
||||
`Definition for key "${name}" missing valid validation strategy.`,
|
||||
);
|
||||
}
|
||||
} else if (!hasSchema && typeof definition.validate !== "function") {
|
||||
throw new TypeError(
|
||||
`Definition for key "${name}" must have a validate() method.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Errors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Error when an unexpected key is found.
|
||||
*/
|
||||
class UnexpectedKeyError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} key The key that was unexpected.
|
||||
*/
|
||||
constructor(key) {
|
||||
super(`Unexpected key "${key}" found.`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error when a required key is missing.
|
||||
*/
|
||||
class MissingKeyError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} key The key that was missing.
|
||||
*/
|
||||
constructor(key) {
|
||||
super(`Missing required key "${key}".`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error when a key requires other keys that are missing.
|
||||
*/
|
||||
class MissingDependentKeysError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} key The key that was unexpected.
|
||||
* @param {Array<string>} requiredKeys The keys that are required.
|
||||
*/
|
||||
constructor(key, requiredKeys) {
|
||||
super(`Key "${key}" requires keys "${requiredKeys.join('", "')}".`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper error for errors occuring during a merge or validate operation.
|
||||
*/
|
||||
class WrapperError extends Error {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {string} key The object key causing the error.
|
||||
* @param {Error} source The source error.
|
||||
*/
|
||||
constructor(key, source) {
|
||||
super(`Key "${key}": ${source.message}`, { cause: source });
|
||||
|
||||
// copy over custom properties that aren't represented
|
||||
for (const sourceKey of Object.keys(source)) {
|
||||
if (!(sourceKey in this)) {
|
||||
this[sourceKey] = source[sourceKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Represents an object validation/merging schema.
|
||||
*/
|
||||
class ObjectSchema {
|
||||
/**
|
||||
* Track all definitions in the schema by key.
|
||||
* @type {Map<string, PropertyDefinition>}
|
||||
*/
|
||||
#definitions = new Map();
|
||||
|
||||
/**
|
||||
* Separately track any keys that are required for faster validation.
|
||||
* @type {Map<string, PropertyDefinition>}
|
||||
*/
|
||||
#requiredKeys = new Map();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {ObjectDefinition} definitions The schema definitions.
|
||||
* @throws {Error} When the definitions are missing or invalid.
|
||||
*/
|
||||
constructor(definitions) {
|
||||
if (!definitions) {
|
||||
throw new Error("Schema definitions missing.");
|
||||
}
|
||||
|
||||
// add in all strategies
|
||||
for (const key of Object.keys(definitions)) {
|
||||
const definition = definitions[key];
|
||||
|
||||
validateDefinition(key, definition);
|
||||
|
||||
let normalizedDefinition = definition;
|
||||
|
||||
// normalize merge and validate methods if subschema is present
|
||||
if (typeof normalizedDefinition.schema === "object") {
|
||||
const schema = new ObjectSchema(normalizedDefinition.schema);
|
||||
normalizedDefinition = {
|
||||
...normalizedDefinition,
|
||||
merge(first = {}, second = {}) {
|
||||
return schema.merge(first, second);
|
||||
},
|
||||
validate(value) {
|
||||
ValidationStrategy.object(value);
|
||||
schema.validate(value);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// normalize the merge method in case there's a string
|
||||
if (typeof normalizedDefinition.merge === "string") {
|
||||
normalizedDefinition = {
|
||||
...normalizedDefinition,
|
||||
merge: MergeStrategy[normalizedDefinition.merge],
|
||||
};
|
||||
}
|
||||
|
||||
// normalize the validate method in case there's a string
|
||||
if (typeof normalizedDefinition.validate === "string") {
|
||||
normalizedDefinition = {
|
||||
...normalizedDefinition,
|
||||
validate: ValidationStrategy[normalizedDefinition.validate],
|
||||
};
|
||||
}
|
||||
|
||||
this.#definitions.set(key, normalizedDefinition);
|
||||
|
||||
if (normalizedDefinition.required) {
|
||||
this.#requiredKeys.set(key, normalizedDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a strategy has been registered for the given object key.
|
||||
* @param {string} key The object key to find a strategy for.
|
||||
* @returns {boolean} True if the key has a strategy registered, false if not.
|
||||
*/
|
||||
hasKey(key) {
|
||||
return this.#definitions.has(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges objects together to create a new object comprised of the keys
|
||||
* of the all objects. Keys are merged based on the each key's merge
|
||||
* strategy.
|
||||
* @param {...Object} objects The objects to merge.
|
||||
* @returns {Object} A new object with a mix of all objects' keys.
|
||||
* @throws {TypeError} If any object is invalid.
|
||||
*/
|
||||
merge(...objects) {
|
||||
// double check arguments
|
||||
if (objects.length < 2) {
|
||||
throw new TypeError("merge() requires at least two arguments.");
|
||||
}
|
||||
|
||||
if (
|
||||
objects.some(
|
||||
object => object === null || typeof object !== "object",
|
||||
)
|
||||
) {
|
||||
throw new TypeError("All arguments must be objects.");
|
||||
}
|
||||
|
||||
return objects.reduce((result, object) => {
|
||||
this.validate(object);
|
||||
|
||||
for (const [key, strategy] of this.#definitions) {
|
||||
try {
|
||||
if (key in result || key in object) {
|
||||
const merge = /** @type {Function} */ (strategy.merge);
|
||||
const value = merge.call(
|
||||
this,
|
||||
result[key],
|
||||
object[key],
|
||||
);
|
||||
if (value !== undefined) {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
throw new WrapperError(key, ex);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an object's keys based on the validate strategy for each key.
|
||||
* @param {Object} object The object to validate.
|
||||
* @returns {void}
|
||||
* @throws {Error} When the object is invalid.
|
||||
*/
|
||||
validate(object) {
|
||||
// check existing keys first
|
||||
for (const key of Object.keys(object)) {
|
||||
// check to see if the key is defined
|
||||
if (!this.hasKey(key)) {
|
||||
throw new UnexpectedKeyError(key);
|
||||
}
|
||||
|
||||
// validate existing keys
|
||||
const definition = /** @type {PropertyDefinition} */ (
|
||||
this.#definitions.get(key)
|
||||
); // `definition` is guaranteed to exist since we check with `hasKey()` above.
|
||||
|
||||
// first check to see if any other keys are required
|
||||
if (Array.isArray(definition.requires)) {
|
||||
if (
|
||||
!definition.requires.every(otherKey => otherKey in object)
|
||||
) {
|
||||
throw new MissingDependentKeysError(
|
||||
key,
|
||||
definition.requires,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// now apply remaining validation strategy
|
||||
try {
|
||||
const validate = /** @type {Function} */ (definition.validate);
|
||||
validate.call(definition, object[key]);
|
||||
} catch (ex) {
|
||||
throw new WrapperError(key, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure required keys aren't missing
|
||||
for (const [key] of this.#requiredKeys) {
|
||||
if (!(key in object)) {
|
||||
throw new MissingKeyError(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { MergeStrategy, ObjectSchema, ValidationStrategy };
|
||||
74
node_modules/@eslint/object-schema/dist/esm/types.d.ts
generated
vendored
Normal file
74
node_modules/@eslint/object-schema/dist/esm/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @fileoverview Types for object-schema package.
|
||||
*/
|
||||
/**
|
||||
* Built-in validation strategies.
|
||||
*/
|
||||
export type BuiltInValidationStrategy = "array" | "boolean" | "number" | "object" | "object?" | "string" | "string!";
|
||||
/**
|
||||
* Built-in merge strategies.
|
||||
*/
|
||||
export type BuiltInMergeStrategy = "assign" | "overwrite" | "replace";
|
||||
/**
|
||||
* Custom merge strategy.
|
||||
*/
|
||||
export type CustomMergeStrategy = (target: any, source: any) => any;
|
||||
/**
|
||||
* Custom validation strategy.
|
||||
*/
|
||||
export type CustomValidationStrategy = (value: any) => void;
|
||||
interface BasePropertyDefinition {
|
||||
/**
|
||||
* Indicates if the property is required.
|
||||
*/
|
||||
required?: boolean;
|
||||
/**
|
||||
* The other properties that must be present when this property is used.
|
||||
*/
|
||||
requires?: string[];
|
||||
}
|
||||
/**
|
||||
* Property definition that specifies explicit merge and validation strategies.
|
||||
* This form cannot include a `schema`.
|
||||
*/
|
||||
export interface PropertyDefinitionWithStrategies extends BasePropertyDefinition {
|
||||
/**
|
||||
* The schema for the object value of this property.
|
||||
*/
|
||||
schema?: never;
|
||||
/**
|
||||
* The strategy to merge the property.
|
||||
*/
|
||||
merge: BuiltInMergeStrategy | CustomMergeStrategy;
|
||||
/**
|
||||
* The strategy to validate the property.
|
||||
*/
|
||||
validate: BuiltInValidationStrategy | CustomValidationStrategy;
|
||||
}
|
||||
/**
|
||||
* Property definition that uses a nested `schema`.
|
||||
* When `schema` is present, merge and validation strategies are optional.
|
||||
*/
|
||||
export interface PropertyDefinitionWithSchema extends BasePropertyDefinition {
|
||||
/**
|
||||
* The schema for the object value of this property.
|
||||
*/
|
||||
schema: ObjectDefinition;
|
||||
/**
|
||||
* The strategy to merge the property.
|
||||
*/
|
||||
merge?: BuiltInMergeStrategy | CustomMergeStrategy;
|
||||
/**
|
||||
* The strategy to validate the property.
|
||||
*/
|
||||
validate?: BuiltInValidationStrategy | CustomValidationStrategy;
|
||||
}
|
||||
/**
|
||||
* Property definition.
|
||||
*/
|
||||
export type PropertyDefinition = PropertyDefinitionWithStrategies | PropertyDefinitionWithSchema;
|
||||
/**
|
||||
* Object definition.
|
||||
*/
|
||||
export type ObjectDefinition = Record<string, PropertyDefinition>;
|
||||
export {};
|
||||
98
node_modules/@eslint/object-schema/dist/esm/types.ts
generated
vendored
Normal file
98
node_modules/@eslint/object-schema/dist/esm/types.ts
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @fileoverview Types for object-schema package.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Built-in validation strategies.
|
||||
*/
|
||||
export type BuiltInValidationStrategy =
|
||||
| "array"
|
||||
| "boolean"
|
||||
| "number"
|
||||
| "object"
|
||||
| "object?"
|
||||
| "string"
|
||||
| "string!";
|
||||
|
||||
/**
|
||||
* Built-in merge strategies.
|
||||
*/
|
||||
export type BuiltInMergeStrategy = "assign" | "overwrite" | "replace";
|
||||
|
||||
/**
|
||||
* Custom merge strategy.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/eslint/rewrite/pull/90#discussion_r1687206213
|
||||
export type CustomMergeStrategy = (target: any, source: any) => any;
|
||||
|
||||
/**
|
||||
* Custom validation strategy.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/eslint/rewrite/pull/90#discussion_r1687206213
|
||||
export type CustomValidationStrategy = (value: any) => void;
|
||||
|
||||
interface BasePropertyDefinition {
|
||||
/**
|
||||
* Indicates if the property is required.
|
||||
*/
|
||||
required?: boolean;
|
||||
|
||||
/**
|
||||
* The other properties that must be present when this property is used.
|
||||
*/
|
||||
requires?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Property definition that specifies explicit merge and validation strategies.
|
||||
* This form cannot include a `schema`.
|
||||
*/
|
||||
export interface PropertyDefinitionWithStrategies extends BasePropertyDefinition {
|
||||
/**
|
||||
* The schema for the object value of this property.
|
||||
*/
|
||||
schema?: never;
|
||||
|
||||
/**
|
||||
* The strategy to merge the property.
|
||||
*/
|
||||
merge: BuiltInMergeStrategy | CustomMergeStrategy;
|
||||
|
||||
/**
|
||||
* The strategy to validate the property.
|
||||
*/
|
||||
validate: BuiltInValidationStrategy | CustomValidationStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property definition that uses a nested `schema`.
|
||||
* When `schema` is present, merge and validation strategies are optional.
|
||||
*/
|
||||
export interface PropertyDefinitionWithSchema extends BasePropertyDefinition {
|
||||
/**
|
||||
* The schema for the object value of this property.
|
||||
*/
|
||||
schema: ObjectDefinition;
|
||||
|
||||
/**
|
||||
* The strategy to merge the property.
|
||||
*/
|
||||
merge?: BuiltInMergeStrategy | CustomMergeStrategy;
|
||||
|
||||
/**
|
||||
* The strategy to validate the property.
|
||||
*/
|
||||
validate?: BuiltInValidationStrategy | CustomValidationStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property definition.
|
||||
*/
|
||||
export type PropertyDefinition =
|
||||
| PropertyDefinitionWithStrategies
|
||||
| PropertyDefinitionWithSchema;
|
||||
|
||||
/**
|
||||
* Object definition.
|
||||
*/
|
||||
export type ObjectDefinition = Record<string, PropertyDefinition>;
|
||||
62
node_modules/@eslint/object-schema/package.json
generated
vendored
Normal file
62
node_modules/@eslint/object-schema/package.json
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "@eslint/object-schema",
|
||||
"version": "3.0.5",
|
||||
"description": "An object schema merger/validator",
|
||||
"type": "module",
|
||||
"main": "dist/esm/index.js",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"exports": {
|
||||
"require": {
|
||||
"types": "./dist/cjs/index.d.cts",
|
||||
"default": "./dist/cjs/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"build:dedupe-types": "node ../../tools/dedupe-types.js dist/cjs/index.cjs dist/esm/index.js",
|
||||
"build:cts": "node ../../tools/build-cts.js dist/esm/index.d.ts dist/cjs/index.d.cts",
|
||||
"build": "rollup -c && npm run build:dedupe-types && tsc -p tsconfig.esm.json && npm run build:cts",
|
||||
"lint:types": "attw --pack",
|
||||
"pretest": "npm run build",
|
||||
"test": "npm run test:types && npm run test:unit",
|
||||
"test:coverage": "c8 npm run test:unit",
|
||||
"test:jsr": "npx -y jsr@latest publish --dry-run",
|
||||
"test:types": "tsc -p tests/types/tsconfig.json",
|
||||
"test:unit": "mocha \"tests/**/*.test.js\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/eslint/rewrite.git",
|
||||
"directory": "packages/object-schema"
|
||||
},
|
||||
"keywords": [
|
||||
"object",
|
||||
"validation",
|
||||
"schema",
|
||||
"merge"
|
||||
],
|
||||
"author": "Nicholas C. Zakas",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/eslint/rewrite/issues"
|
||||
},
|
||||
"homepage": "https://github.com/eslint/rewrite/tree/main/packages/object-schema#readme",
|
||||
"devDependencies": {
|
||||
"rollup-plugin-copy": "^3.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||
}
|
||||
}
|
||||
201
node_modules/@eslint/plugin-kit/LICENSE
generated
vendored
Normal file
201
node_modules/@eslint/plugin-kit/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
273
node_modules/@eslint/plugin-kit/README.md
generated
vendored
Normal file
273
node_modules/@eslint/plugin-kit/README.md
generated
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
# ESLint Plugin Kit
|
||||
|
||||
## Description
|
||||
|
||||
A collection of utilities to help build ESLint plugins.
|
||||
|
||||
## Installation
|
||||
|
||||
For Node.js and compatible runtimes:
|
||||
|
||||
```shell
|
||||
npm install @eslint/plugin-kit
|
||||
# or
|
||||
yarn add @eslint/plugin-kit
|
||||
# or
|
||||
pnpm install @eslint/plugin-kit
|
||||
# or
|
||||
bun add @eslint/plugin-kit
|
||||
```
|
||||
|
||||
For Deno:
|
||||
|
||||
```shell
|
||||
deno add @eslint/plugin-kit
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
This package exports the following utilities:
|
||||
|
||||
- [`ConfigCommentParser`](#configcommentparser) - used to parse ESLint configuration comments (i.e., `/* eslint-disable rule */`)
|
||||
- [`VisitNodeStep` and `CallMethodStep`](#visitnodestep-and-callmethodstep) - used to help implement `SourceCode#traverse()`
|
||||
- [`Directive`](#directive) - used to help implement `SourceCode#getDisableDirectives()`
|
||||
- [`TextSourceCodeBase`](#textsourcecodebase) - base class to help implement the `SourceCode` interface
|
||||
|
||||
### `ConfigCommentParser`
|
||||
|
||||
To use the `ConfigCommentParser` class, import it from the package and create a new instance, such as:
|
||||
|
||||
```js
|
||||
import { ConfigCommentParser } from "@eslint/plugin-kit";
|
||||
|
||||
// create a new instance
|
||||
const commentParser = new ConfigCommentParser();
|
||||
|
||||
// pass in a comment string without the comment delimiters
|
||||
const directive = commentParser.parseDirective(
|
||||
"eslint-disable prefer-const, no-var -- I don't want to use these.",
|
||||
);
|
||||
|
||||
// will be undefined when a directive can't be parsed
|
||||
if (directive) {
|
||||
console.log(directive.label); // "eslint-disable"
|
||||
console.log(directive.value); // "prefer-const, no-var"
|
||||
console.log(directive.justification); // "I don't want to use these."
|
||||
}
|
||||
```
|
||||
|
||||
There are different styles of directive values that you'll need to parse separately to get the correct format:
|
||||
|
||||
```js
|
||||
import { ConfigCommentParser } from "@eslint/plugin-kit";
|
||||
|
||||
// create a new instance
|
||||
const commentParser = new ConfigCommentParser();
|
||||
|
||||
// list format
|
||||
const list = commentParser.parseListConfig("prefer-const, no-var");
|
||||
console.log(Object.entries(list)); // [["prefer-const", true], ["no-var", true]]
|
||||
|
||||
// string format
|
||||
const strings = commentParser.parseStringConfig("foo:off, bar");
|
||||
console.log(Object.entries(strings)); // [["foo", "off"], ["bar", null]]
|
||||
|
||||
// JSON-like config format
|
||||
const jsonLike = commentParser.parseJSONLikeConfig(
|
||||
"radix:[error, always], prefer-const: warn",
|
||||
);
|
||||
console.log(Object.entries(jsonLike.config)); // [["radix", ["error", "always"]], ["prefer-const", "warn"]]
|
||||
```
|
||||
|
||||
### `VisitNodeStep` and `CallMethodStep`
|
||||
|
||||
The `VisitNodeStep` and `CallMethodStep` classes represent steps in the traversal of source code. They implement the correct interfaces to return from the `SourceCode#traverse()` method.
|
||||
|
||||
The `VisitNodeStep` class is the more common of the two, where you are describing a visit to a particular node during the traversal. The constructor accepts three arguments:
|
||||
|
||||
- `target` - the node being visited. This is used to determine the method to call inside of a rule. For instance, if the node's type is `Literal` then ESLint will call a method named `Literal()` on the rule (if present).
|
||||
- `phase` - either 1 for enter or 2 for exit.
|
||||
- `args` - an array of arguments to pass into the visitor method of a rule.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
import { VisitNodeStep } from "@eslint/plugin-kit";
|
||||
|
||||
class MySourceCode {
|
||||
traverse() {
|
||||
const steps = [];
|
||||
|
||||
for (const { node, parent, phase } of iterator(this.ast)) {
|
||||
steps.push(
|
||||
new VisitNodeStep({
|
||||
target: node,
|
||||
phase: phase === "enter" ? 1 : 2,
|
||||
args: [node, parent],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `CallMethodStep` class is less common and is used to tell ESLint to call a specific method on the rule. The constructor accepts two arguments:
|
||||
|
||||
- `target` - the name of the method to call, frequently beginning with `"on"` such as `"onCodePathStart"`.
|
||||
- `args` - an array of arguments to pass to the method.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
import { VisitNodeStep, CallMethodStep } from "@eslint/plugin-kit";
|
||||
|
||||
class MySourceCode {
|
||||
traverse() {
|
||||
const steps = [];
|
||||
|
||||
for (const { node, parent, phase } of iterator(this.ast)) {
|
||||
steps.push(
|
||||
new VisitNodeStep({
|
||||
target: node,
|
||||
phase: phase === "enter" ? 1 : 2,
|
||||
args: [node, parent],
|
||||
}),
|
||||
);
|
||||
|
||||
// call a method indicating how many times we've been through the loop
|
||||
steps.push(
|
||||
new CallMethodStep({
|
||||
target: "onIteration",
|
||||
args: [steps.length]
|
||||
});
|
||||
)
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `Directive`
|
||||
|
||||
The `Directive` class represents a disable directive in the source code and implements the `Directive` interface from `@eslint/core`. You can tell ESLint about disable directives using the `SourceCode#getDisableDirectives()` method, where part of the return value is an array of `Directive` objects. Here's an example:
|
||||
|
||||
```js
|
||||
import { Directive, ConfigCommentParser } from "@eslint/plugin-kit";
|
||||
|
||||
class MySourceCode {
|
||||
getDisableDirectives() {
|
||||
const directives = [];
|
||||
const problems = [];
|
||||
const commentParser = new ConfigCommentParser();
|
||||
|
||||
// read in the inline config nodes to check each one
|
||||
this.getInlineConfigNodes().forEach(comment => {
|
||||
// Step 1: Parse the directive
|
||||
const { label, value, justification } =
|
||||
commentParser.parseDirective(comment.value);
|
||||
|
||||
// Step 2: Extract the directive value and create the `Directive` object
|
||||
switch (label) {
|
||||
case "eslint-disable":
|
||||
case "eslint-enable":
|
||||
case "eslint-disable-next-line":
|
||||
case "eslint-disable-line": {
|
||||
const directiveType = label.slice("eslint-".length);
|
||||
|
||||
directives.push(
|
||||
new Directive({
|
||||
type: directiveType,
|
||||
node: comment,
|
||||
value,
|
||||
justification,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// ignore any comments that don't begin with known labels
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
directives,
|
||||
problems,
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `TextSourceCodeBase`
|
||||
|
||||
The `TextSourceCodeBase` class is intended to be a base class that has several of the common members found in `SourceCode` objects already implemented. Those members are:
|
||||
|
||||
- `lines` - an array of text lines that is created automatically when the constructor is called.
|
||||
- `getLoc(nodeOrToken)` - gets the location of a node or token. Works for nodes that have the ESLint-style `loc` property and nodes that have the Unist-style [`position` property](https://github.com/syntax-tree/unist?tab=readme-ov-file#position). If you're using an AST with a different location format, you'll still need to implement this method yourself.
|
||||
- `getLocFromIndex(index)` - Converts a source text index into a `{ line: number, column: number }` pair. (For this method to work, the root node should always cover the entire source code text, and the `getLoc()` method needs to be implemented correctly.)
|
||||
- `getIndexFromLoc(loc)` - Converts a `{ line: number, column: number }` pair into a source text index. (For this method to work, the root node should always cover the entire source code text, and the `getLoc()` method needs to be implemented correctly.)
|
||||
- `getRange(nodeOrToken)` - gets the range of a node or token within the source text. Works for nodes that have the ESLint-style `range` property and nodes that have the Unist-style [`position` property](https://github.com/syntax-tree/unist?tab=readme-ov-file#position). If you're using an AST with a different range format, you'll still need to implement this method yourself.
|
||||
- `getText(node, beforeCount, afterCount)` - gets the source text for the given node that has range information attached. Optionally, can return additional characters before and after the given node. As long as `getRange()` is properly implemented, this method will just work.
|
||||
- `getAncestors(node)` - returns the ancestry of the node. In order for this to work, you must implement the `getParent()` method yourself.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```js
|
||||
import { TextSourceCodeBase } from "@eslint/plugin-kit";
|
||||
|
||||
export class MySourceCode extends TextSourceCodeBase {
|
||||
#parents = new Map();
|
||||
|
||||
constructor({ ast, text }) {
|
||||
super({ ast, text });
|
||||
}
|
||||
|
||||
getParent(node) {
|
||||
return this.#parents.get(node);
|
||||
}
|
||||
|
||||
traverse() {
|
||||
const steps = [];
|
||||
|
||||
for (const { node, parent, phase } of iterator(this.ast)) {
|
||||
//save the parent information
|
||||
this.#parent.set(node, parent);
|
||||
|
||||
steps.push(
|
||||
new VisitNodeStep({
|
||||
target: node,
|
||||
phase: phase === "enter" ? 1 : 2,
|
||||
args: [node, parent],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In general, it's safe to collect the parent information during the `traverse()` method as `getParent()` and `getAncestor()` will only be called from rules once the AST has been traversed at least once.
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0
|
||||
|
||||
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
||||
<!--sponsorsstart-->
|
||||
|
||||
## Sponsors
|
||||
|
||||
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
|
||||
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
||||
|
||||
<h3>Platinum Sponsors</h3>
|
||||
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a></p><h3>Gold Sponsors</h3>
|
||||
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a></p><h3>Silver Sponsors</h3>
|
||||
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/d472863/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
|
||||
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://opensource.sap.com"><img src="https://avatars.githubusercontent.com/u/2531208" alt="SAP" height="32"></a> <a href="https://www.crawljobs.com/"><img src="https://images.opencollective.com/crawljobs-poland/fa43a17/logo.png" alt="CrawlJobs" height="32"></a> <a href="#"><img src="https://images.opencollective.com/aeriusventilations-org/avatar.png" alt="aeriusventilation's Org" height="32"></a> <a href="https://depot.dev"><img src="https://images.opencollective.com/depot/39125a1/logo.png" alt="Depot" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="TestMu AI Open Source Office (Formerly LambdaTest)" height="32"></a></p>
|
||||
<h3>Technology Sponsors</h3>
|
||||
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
||||
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
||||
<!--sponsorsend-->
|
||||
895
node_modules/@eslint/plugin-kit/dist/cjs/index.cjs
generated
vendored
Normal file
895
node_modules/@eslint/plugin-kit/dist/cjs/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,895 @@
|
||||
'use strict';
|
||||
|
||||
var levn = require('levn');
|
||||
|
||||
/**
|
||||
* @fileoverview Config Comment Parser
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @import * as $eslintcore from "@eslint/core"; */
|
||||
/** @typedef {$eslintcore.RuleConfig} RuleConfig */
|
||||
/** @typedef {$eslintcore.RulesConfig} RulesConfig */
|
||||
/** @import * as $typests from "./types.ts"; */
|
||||
/** @typedef {$typests.StringConfig} StringConfig */
|
||||
/** @typedef {$typests.BooleanConfig} BooleanConfig */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const directivesPattern = /^([a-z]+(?:-[a-z]+)*)(?:\s|$)/u;
|
||||
const validSeverities = new Set([0, 1, 2, "off", "warn", "error"]);
|
||||
|
||||
/**
|
||||
* Determines if the severity in the rule configuration is valid.
|
||||
* @param {RuleConfig} ruleConfig A rule's configuration.
|
||||
* @returns {boolean} `true` if the severity is valid, otherwise `false`.
|
||||
*/
|
||||
function isSeverityValid(ruleConfig) {
|
||||
const severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
|
||||
return validSeverities.has(severity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if all severities in the rules configuration are valid.
|
||||
* @param {RulesConfig} rulesConfig The rules configuration to check.
|
||||
* @returns {boolean} `true` if all severities are valid, otherwise `false`.
|
||||
*/
|
||||
function isEverySeverityValid(rulesConfig) {
|
||||
return Object.values(rulesConfig).every(isSeverityValid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a directive comment.
|
||||
*/
|
||||
class DirectiveComment {
|
||||
/**
|
||||
* The label of the directive, such as "eslint", "eslint-disable", etc.
|
||||
* @type {string}
|
||||
*/
|
||||
label = "";
|
||||
|
||||
/**
|
||||
* The value of the directive (the string after the label).
|
||||
* @type {string}
|
||||
*/
|
||||
value = "";
|
||||
|
||||
/**
|
||||
* The justification of the directive (the string after the --).
|
||||
* @type {string}
|
||||
*/
|
||||
justification = "";
|
||||
|
||||
/**
|
||||
* Creates a new directive comment.
|
||||
* @param {string} label The label of the directive.
|
||||
* @param {string} value The value of the directive.
|
||||
* @param {string} justification The justification of the directive.
|
||||
*/
|
||||
constructor(label, value, justification) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
this.justification = justification;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Object to parse ESLint configuration comments.
|
||||
*/
|
||||
class ConfigCommentParser {
|
||||
/**
|
||||
* Parses a list of "name:string_value" or/and "name" options divided by comma or
|
||||
* whitespace. Used for "global" comments.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {StringConfig} Result map object of names and string values, or null values if no value was provided.
|
||||
*/
|
||||
parseStringConfig(string) {
|
||||
const items = /** @type {StringConfig} */ ({});
|
||||
|
||||
// Collapse whitespace around `:` and `,` to make parsing easier
|
||||
const trimmedString = string
|
||||
.trim()
|
||||
.replace(/(?<!\s)\s*([:,])\s*/gu, "$1");
|
||||
|
||||
trimmedString.split(/\s|,+/u).forEach(name => {
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
// value defaults to null (if not provided), e.g: "foo" => ["foo", null]
|
||||
const [key, value = null] = name.split(":");
|
||||
|
||||
items[key] = value;
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JSON-like config.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {({ok: true, config: RulesConfig}|{ok: false, error: {message: string}})} Result map object
|
||||
*/
|
||||
parseJSONLikeConfig(string) {
|
||||
// Parses a JSON-like comment by the same way as parsing CLI option.
|
||||
try {
|
||||
const items =
|
||||
/** @type {RulesConfig} */ (levn.parse("Object", string)) || {};
|
||||
|
||||
/*
|
||||
* When the configuration has any invalid severities, it should be completely
|
||||
* ignored. This is because the configuration is not valid and should not be
|
||||
* applied.
|
||||
*
|
||||
* For example, the following configuration is invalid:
|
||||
*
|
||||
* "no-alert: 2 no-console: 2"
|
||||
*
|
||||
* This results in a configuration of { "no-alert": "2 no-console: 2" }, which is
|
||||
* not valid. In this case, the configuration should be ignored.
|
||||
*/
|
||||
if (isEverySeverityValid(items)) {
|
||||
return {
|
||||
ok: true,
|
||||
config: items,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// levn parsing error: ignore to parse the string by a fallback.
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionator cannot parse commaless notations.
|
||||
* But we are supporting that. So this is a fallback for that.
|
||||
*/
|
||||
const normalizedString = string
|
||||
.replace(/(?<![-a-zA-Z0-9/])([-a-zA-Z0-9/]+):/gu, '"$1":')
|
||||
.replace(/([\]0-9])\s+(?=")/u, "$1,");
|
||||
|
||||
try {
|
||||
const items = JSON.parse(`{${normalizedString}}`);
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
config: items,
|
||||
};
|
||||
} catch (ex) {
|
||||
const errorMessage = ex instanceof Error ? ex.message : String(ex);
|
||||
|
||||
return {
|
||||
ok: false,
|
||||
error: {
|
||||
message: `Failed to parse JSON from '${normalizedString}': ${errorMessage}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a config of values separated by comma.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {BooleanConfig} Result map of values and true values
|
||||
*/
|
||||
parseListConfig(string) {
|
||||
const items = /** @type {BooleanConfig} */ ({});
|
||||
|
||||
string.split(",").forEach(name => {
|
||||
const trimmedName = name
|
||||
.trim()
|
||||
.replace(
|
||||
/^(?<quote>['"]?)(?<ruleId>.*)\k<quote>$/su,
|
||||
"$<ruleId>",
|
||||
);
|
||||
|
||||
if (trimmedName) {
|
||||
items[trimmedName] = true;
|
||||
}
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the directive and the justification from a given directive comment and trim them.
|
||||
* @param {string} value The comment text to extract.
|
||||
* @returns {{directivePart: string, justificationPart: string}} The extracted directive and justification.
|
||||
*/
|
||||
#extractDirectiveComment(value) {
|
||||
const match = /\s-{2,}\s/u.exec(value);
|
||||
|
||||
if (!match) {
|
||||
return { directivePart: value.trim(), justificationPart: "" };
|
||||
}
|
||||
|
||||
const directive = value.slice(0, match.index).trim();
|
||||
const justification = value.slice(match.index + match[0].length).trim();
|
||||
|
||||
return { directivePart: directive, justificationPart: justification };
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a directive comment into directive text and value.
|
||||
* @param {string} string The string with the directive to be parsed.
|
||||
* @returns {DirectiveComment|undefined} The parsed directive or `undefined` if the directive is invalid.
|
||||
*/
|
||||
parseDirective(string) {
|
||||
const { directivePart, justificationPart } =
|
||||
this.#extractDirectiveComment(string);
|
||||
const match = directivesPattern.exec(directivePart);
|
||||
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const directiveText = match[1];
|
||||
const directiveValue = directivePart.slice(
|
||||
match.index + directiveText.length,
|
||||
);
|
||||
|
||||
return new DirectiveComment(
|
||||
directiveText,
|
||||
directiveValue.trim(),
|
||||
justificationPart,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview A collection of helper classes for implementing `SourceCode`.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/* eslint class-methods-use-this: off -- Required to complete interface. */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @typedef {$eslintcore.VisitTraversalStep} VisitTraversalStep */
|
||||
/** @typedef {$eslintcore.CallTraversalStep} CallTraversalStep */
|
||||
/** @typedef {$eslintcore.TraversalStep} TraversalStep */
|
||||
/** @typedef {$eslintcore.SourceLocation} SourceLocation */
|
||||
/** @typedef {$eslintcore.SourceLocationWithOffset} SourceLocationWithOffset */
|
||||
/** @typedef {$eslintcore.SourceRange} SourceRange */
|
||||
/** @typedef {$eslintcore.Directive} IDirective */
|
||||
/** @typedef {$eslintcore.DirectiveType} DirectiveType */
|
||||
/** @typedef {$eslintcore.SourceCodeBaseTypeOptions} SourceCodeBaseTypeOptions */
|
||||
/**
|
||||
* @typedef {import("@eslint/core").TextSourceCode<Options>} TextSourceCode
|
||||
* @template {SourceCodeBaseTypeOptions} [Options=SourceCodeBaseTypeOptions]
|
||||
*/
|
||||
/** @typedef {$eslintcore.RuleVisitor} RuleVisitor */
|
||||
/**
|
||||
* @typedef {import("./types.ts").CustomRuleVisitorWithExit<RuleVisitorType>} CustomRuleVisitorWithExit
|
||||
* @template {RuleVisitor} RuleVisitorType
|
||||
*/
|
||||
/** @typedef {$typests.CustomRuleTypeDefinitions} CustomRuleTypeDefinitions */
|
||||
/**
|
||||
* @typedef {import("./types.ts").CustomRuleDefinitionType<LanguageSpecificOptions, Options>} CustomRuleDefinitionType
|
||||
* @template {Omit<import("@eslint/core").RuleDefinitionTypeOptions, keyof CustomRuleTypeDefinitions>} LanguageSpecificOptions
|
||||
* @template {Partial<CustomRuleTypeDefinitions>} Options
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines if a node has ESTree-style loc information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {loc:SourceLocation}} `true` if the node has ESTree-style loc information, `false` if not.
|
||||
*/
|
||||
function hasESTreeStyleLoc(node) {
|
||||
return "loc" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has position-style loc information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {position:SourceLocation}} `true` if the node has position-style range information, `false` if not.
|
||||
*/
|
||||
function hasPosStyleLoc(node) {
|
||||
return "position" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has ESTree-style range information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {range:SourceRange}} `true` if the node has ESTree-style range information, `false` if not.
|
||||
*/
|
||||
function hasESTreeStyleRange(node) {
|
||||
return "range" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has position-style range information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {position:SourceLocationWithOffset}} `true` if the node has position-style range information, `false` if not.
|
||||
*/
|
||||
function hasPosStyleRange(node) {
|
||||
return "position" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs binary search to find the line number containing a given target index.
|
||||
* Returns the lower bound - the index of the first element greater than the target.
|
||||
* **Please note that the `lineStartIndices` should be sorted in ascending order**.
|
||||
* - Time Complexity: O(log n) - Significantly faster than linear search for large files.
|
||||
* @param {number[]} lineStartIndices Sorted array of line start indices.
|
||||
* @param {number} targetIndex The target index to find the line number for.
|
||||
* @returns {number} The line number for the target index.
|
||||
*/
|
||||
function findLineNumberBinarySearch(lineStartIndices, targetIndex) {
|
||||
let low = 0;
|
||||
let high = lineStartIndices.length - 1;
|
||||
|
||||
while (low < high) {
|
||||
const mid = ((low + high) / 2) | 0; // Use bitwise OR to floor the division.
|
||||
|
||||
if (targetIndex < lineStartIndices[mid]) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a node is visited.
|
||||
* @implements {VisitTraversalStep}
|
||||
*/
|
||||
class VisitNodeStep {
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"visit"}
|
||||
* @readonly
|
||||
*/
|
||||
type = "visit";
|
||||
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {1}
|
||||
* @readonly
|
||||
*/
|
||||
kind = 1;
|
||||
|
||||
/**
|
||||
* The target of the step.
|
||||
* @type {object}
|
||||
*/
|
||||
target;
|
||||
|
||||
/**
|
||||
* The phase of the step.
|
||||
* @type {1|2}
|
||||
*/
|
||||
phase;
|
||||
|
||||
/**
|
||||
* The arguments of the step.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {object} options.target The target of the step.
|
||||
* @param {1|2} options.phase The phase of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, phase, args }) {
|
||||
this.target = target;
|
||||
this.phase = phase;
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a
|
||||
* method is called.
|
||||
* @implements {CallTraversalStep}
|
||||
*/
|
||||
class CallMethodStep {
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"call"}
|
||||
* @readonly
|
||||
*/
|
||||
type = "call";
|
||||
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {2}
|
||||
* @readonly
|
||||
*/
|
||||
kind = 2;
|
||||
|
||||
/**
|
||||
* The name of the method to call.
|
||||
* @type {string}
|
||||
*/
|
||||
target;
|
||||
|
||||
/**
|
||||
* The arguments to pass to the method.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {string} options.target The target of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, args }) {
|
||||
this.target = target;
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent a directive comment.
|
||||
* @implements {IDirective}
|
||||
*/
|
||||
class Directive {
|
||||
/**
|
||||
* The type of directive.
|
||||
* @type {DirectiveType}
|
||||
* @readonly
|
||||
*/
|
||||
type;
|
||||
|
||||
/**
|
||||
* The node representing the directive.
|
||||
* @type {unknown}
|
||||
* @readonly
|
||||
*/
|
||||
node;
|
||||
|
||||
/**
|
||||
* Everything after the "eslint-disable" portion of the directive,
|
||||
* but before the "--" that indicates the justification.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
value;
|
||||
|
||||
/**
|
||||
* The justification for the directive.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
justification;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the directive.
|
||||
* @param {"disable"|"enable"|"disable-next-line"|"disable-line"} options.type The type of directive.
|
||||
* @param {unknown} options.node The node representing the directive.
|
||||
* @param {string} options.value The value of the directive.
|
||||
* @param {string} options.justification The justification for the directive.
|
||||
*/
|
||||
constructor({ type, node, value, justification }) {
|
||||
this.type = type;
|
||||
this.node = node;
|
||||
this.value = value;
|
||||
this.justification = justification;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Source Code Base Object
|
||||
* @template {SourceCodeBaseTypeOptions & {RootNode: object, SyntaxElementWithLoc: object}} [Options=SourceCodeBaseTypeOptions & {RootNode: object, SyntaxElementWithLoc: object}]
|
||||
* @implements {TextSourceCode<Options>}
|
||||
*/
|
||||
class TextSourceCodeBase {
|
||||
/**
|
||||
* The lines of text in the source code.
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
#lines = [];
|
||||
|
||||
/**
|
||||
* The indices of the start of each line in the source code.
|
||||
* @type {Array<number>}
|
||||
*/
|
||||
#lineStartIndices = [0];
|
||||
|
||||
/**
|
||||
* The pattern to match lineEndings in the source code.
|
||||
* @type {RegExp}
|
||||
*/
|
||||
#lineEndingPattern;
|
||||
|
||||
/**
|
||||
* The AST of the source code.
|
||||
* @type {Options['RootNode']}
|
||||
*/
|
||||
ast;
|
||||
|
||||
/**
|
||||
* The text of the source code.
|
||||
* @type {string}
|
||||
*/
|
||||
text;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the instance.
|
||||
* @param {string} options.text The source code text.
|
||||
* @param {Options['RootNode']} options.ast The root AST node.
|
||||
* @param {RegExp} [options.lineEndingPattern] The pattern to match lineEndings in the source code. Defaults to `/\r?\n/u`.
|
||||
*/
|
||||
constructor({ text, ast, lineEndingPattern = /\r?\n/u }) {
|
||||
this.ast = ast;
|
||||
this.text = text;
|
||||
// Remove the global(`g`) and sticky(`y`) flags from the `lineEndingPattern` to avoid issues with lastIndex.
|
||||
this.#lineEndingPattern = new RegExp(
|
||||
lineEndingPattern.source,
|
||||
lineEndingPattern.flags.replace(/[gy]/gu, ""),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the next line in the source text and updates `#lines` and `#lineStartIndices`.
|
||||
* @param {string} text The text to search for the next line.
|
||||
* @returns {boolean} `true` if a next line was found, `false` otherwise.
|
||||
*/
|
||||
#findNextLine(text) {
|
||||
const match = this.#lineEndingPattern.exec(text);
|
||||
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.#lines.push(text.slice(0, match.index));
|
||||
this.#lineStartIndices.push(
|
||||
(this.#lineStartIndices.at(-1) ?? 0) +
|
||||
match.index +
|
||||
match[0].length,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures `#lines` is lazily calculated from the source text.
|
||||
* @returns {void}
|
||||
*/
|
||||
#ensureLines() {
|
||||
// If `#lines` has already been calculated, do nothing.
|
||||
if (this.#lines.length === this.#lineStartIndices.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (
|
||||
this.#findNextLine(this.text.slice(this.#lineStartIndices.at(-1)))
|
||||
) {
|
||||
// Continue parsing until no more matches are found.
|
||||
}
|
||||
|
||||
this.#lines.push(this.text.slice(this.#lineStartIndices.at(-1)));
|
||||
|
||||
Object.freeze(this.#lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures `#lineStartIndices` is lazily calculated up to the specified index.
|
||||
* @param {number} index The index of a character in a file.
|
||||
* @returns {void}
|
||||
*/
|
||||
#ensureLineStartIndicesFromIndex(index) {
|
||||
// If we've already parsed up to or beyond this index, do nothing.
|
||||
if (index <= (this.#lineStartIndices.at(-1) ?? 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (
|
||||
index > (this.#lineStartIndices.at(-1) ?? 0) &&
|
||||
this.#findNextLine(this.text.slice(this.#lineStartIndices.at(-1)))
|
||||
) {
|
||||
// Continue parsing until no more matches are found.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures `#lineStartIndices` is lazily calculated up to the specified loc.
|
||||
* @param {Object} loc A line/column location.
|
||||
* @param {number} loc.line The line number of the location. (0 or 1-indexed based on language.)
|
||||
* @param {number} lineStart The line number at which the parser starts counting.
|
||||
* @returns {void}
|
||||
*/
|
||||
#ensureLineStartIndicesFromLoc(loc, lineStart) {
|
||||
// Calculate line indices up to the potentially next line, as it is needed for the follow‑up calculation.
|
||||
const nextLocLineIndex = loc.line - lineStart + 1;
|
||||
const lastCalculatedLineIndex = this.#lineStartIndices.length - 1;
|
||||
let additionalLinesNeeded = nextLocLineIndex - lastCalculatedLineIndex;
|
||||
|
||||
// If we've already parsed up to or beyond this line, do nothing.
|
||||
if (additionalLinesNeeded <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (
|
||||
additionalLinesNeeded > 0 &&
|
||||
this.#findNextLine(this.text.slice(this.#lineStartIndices.at(-1)))
|
||||
) {
|
||||
// Continue parsing until no more matches are found or we have enough lines.
|
||||
additionalLinesNeeded -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the loc information for the given node or token.
|
||||
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the loc information for.
|
||||
* @returns {SourceLocation} The loc information for the node or token.
|
||||
* @throws {Error} If the node or token does not have loc information.
|
||||
*/
|
||||
getLoc(nodeOrToken) {
|
||||
if (hasESTreeStyleLoc(nodeOrToken)) {
|
||||
return nodeOrToken.loc;
|
||||
}
|
||||
|
||||
if (hasPosStyleLoc(nodeOrToken)) {
|
||||
return nodeOrToken.position;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"Custom getLoc() method must be implemented in the subclass.",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a source text index into a `{ line: number, column: number }` pair.
|
||||
* @param {number} index The index of a character in a file.
|
||||
* @throws {TypeError|RangeError} If non-numeric index or index out of range.
|
||||
* @returns {{line: number, column: number}} A `{ line: number, column: number }` location object with 0 or 1-indexed line and 0 or 1-indexed column based on language.
|
||||
* @public
|
||||
*/
|
||||
getLocFromIndex(index) {
|
||||
if (typeof index !== "number") {
|
||||
throw new TypeError("Expected `index` to be a number.");
|
||||
}
|
||||
|
||||
if (index < 0 || index > this.text.length) {
|
||||
throw new RangeError(
|
||||
`Index out of range (requested index ${index}, but source text has length ${this.text.length}).`,
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
start: { line: lineStart, column: columnStart },
|
||||
end: { line: lineEnd, column: columnEnd },
|
||||
} = this.getLoc(this.ast);
|
||||
|
||||
// If the index is at the start, return the start location of the root node.
|
||||
if (index === 0) {
|
||||
return {
|
||||
line: lineStart,
|
||||
column: columnStart,
|
||||
};
|
||||
}
|
||||
|
||||
// If the index is `this.text.length`, return the location one "spot" past the last character of the file.
|
||||
if (index === this.text.length) {
|
||||
return {
|
||||
line: lineEnd,
|
||||
column: columnEnd,
|
||||
};
|
||||
}
|
||||
|
||||
// Ensure `#lineStartIndices` are lazily calculated.
|
||||
this.#ensureLineStartIndicesFromIndex(index);
|
||||
|
||||
/*
|
||||
* To figure out which line `index` is on, determine the last place at which index could
|
||||
* be inserted into `#lineStartIndices` to keep the list sorted.
|
||||
*/
|
||||
const lineNumber =
|
||||
(index >= (this.#lineStartIndices.at(-1) ?? 0)
|
||||
? this.#lineStartIndices.length
|
||||
: findLineNumberBinarySearch(this.#lineStartIndices, index)) -
|
||||
1 +
|
||||
lineStart;
|
||||
|
||||
return {
|
||||
line: lineNumber,
|
||||
column:
|
||||
index -
|
||||
this.#lineStartIndices[lineNumber - lineStart] +
|
||||
columnStart,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a `{ line: number, column: number }` pair into a source text index.
|
||||
* @param {Object} loc A line/column location.
|
||||
* @param {number} loc.line The line number of the location. (0 or 1-indexed based on language.)
|
||||
* @param {number} loc.column The column number of the location. (0 or 1-indexed based on language.)
|
||||
* @throws {TypeError|RangeError} If `loc` is not an object with a numeric
|
||||
* `line` and `column`, if the `line` is less than or equal to zero or
|
||||
* the `line` or `column` is out of the expected range.
|
||||
* @returns {number} The index of the line/column location in a file.
|
||||
* @public
|
||||
*/
|
||||
getIndexFromLoc(loc) {
|
||||
if (
|
||||
loc === null ||
|
||||
typeof loc !== "object" ||
|
||||
typeof loc.line !== "number" ||
|
||||
typeof loc.column !== "number"
|
||||
) {
|
||||
throw new TypeError(
|
||||
"Expected `loc` to be an object with numeric `line` and `column` properties.",
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
start: { line: lineStart, column: columnStart },
|
||||
end: { line: lineEnd, column: columnEnd },
|
||||
} = this.getLoc(this.ast);
|
||||
|
||||
if (loc.line < lineStart || lineEnd < loc.line) {
|
||||
throw new RangeError(
|
||||
`Line number out of range (line ${loc.line} requested). Valid range: ${lineStart}-${lineEnd}`,
|
||||
);
|
||||
}
|
||||
|
||||
// If the loc is at the start, return the start index of the root node.
|
||||
if (loc.line === lineStart && loc.column === columnStart) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the loc is at the end, return the index one "spot" past the last character of the file.
|
||||
if (loc.line === lineEnd && loc.column === columnEnd) {
|
||||
return this.text.length;
|
||||
}
|
||||
|
||||
// Ensure `#lineStartIndices` are lazily calculated.
|
||||
this.#ensureLineStartIndicesFromLoc(loc, lineStart);
|
||||
|
||||
const isLastLine = loc.line === lineEnd;
|
||||
const lineStartIndex = this.#lineStartIndices[loc.line - lineStart];
|
||||
const lineEndIndex = isLastLine
|
||||
? this.text.length
|
||||
: this.#lineStartIndices[loc.line - lineStart + 1];
|
||||
const positionIndex = lineStartIndex + loc.column - columnStart;
|
||||
|
||||
if (
|
||||
loc.column < columnStart ||
|
||||
(isLastLine && positionIndex > lineEndIndex) ||
|
||||
(!isLastLine && positionIndex >= lineEndIndex)
|
||||
) {
|
||||
throw new RangeError(
|
||||
`Column number out of range (column ${loc.column} requested). Valid range for line ${loc.line}: ${columnStart}-${lineEndIndex - lineStartIndex + columnStart + (isLastLine ? 0 : -1)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return positionIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the range information for the given node or token.
|
||||
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the range information for.
|
||||
* @returns {SourceRange} The range information for the node or token.
|
||||
* @throws {Error} If the node or token does not have range information.
|
||||
*/
|
||||
getRange(nodeOrToken) {
|
||||
if (hasESTreeStyleRange(nodeOrToken)) {
|
||||
return nodeOrToken.range;
|
||||
}
|
||||
|
||||
if (hasPosStyleRange(nodeOrToken)) {
|
||||
return [
|
||||
nodeOrToken.position.start.offset,
|
||||
nodeOrToken.position.end.offset,
|
||||
];
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"Custom getRange() method must be implemented in the subclass.",
|
||||
);
|
||||
}
|
||||
|
||||
/* eslint-disable no-unused-vars -- Required to complete interface. */
|
||||
/**
|
||||
* Returns the parent of the given node.
|
||||
* @param {Options['SyntaxElementWithLoc']} node The node to get the parent of.
|
||||
* @returns {Options['SyntaxElementWithLoc']|undefined} The parent of the node.
|
||||
* @throws {Error} If the method is not implemented in the subclass.
|
||||
*/
|
||||
getParent(node) {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
/* eslint-enable no-unused-vars -- Required to complete interface. */
|
||||
|
||||
/**
|
||||
* Gets all the ancestors of a given node
|
||||
* @param {Options['SyntaxElementWithLoc']} node The node
|
||||
* @returns {Array<Options['SyntaxElementWithLoc']>} All the ancestor nodes in the AST, not including the provided node, starting
|
||||
* from the root node at index 0 and going inwards to the parent node.
|
||||
* @throws {TypeError} When `node` is missing.
|
||||
*/
|
||||
getAncestors(node) {
|
||||
if (!node) {
|
||||
throw new TypeError("Missing required argument: node.");
|
||||
}
|
||||
|
||||
const ancestorsStartingAtParent = [];
|
||||
|
||||
for (
|
||||
let ancestor = this.getParent(node);
|
||||
ancestor;
|
||||
ancestor = this.getParent(ancestor)
|
||||
) {
|
||||
ancestorsStartingAtParent.push(ancestor);
|
||||
}
|
||||
|
||||
return ancestorsStartingAtParent.reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source code for the given node.
|
||||
* @param {Options['SyntaxElementWithLoc']} [node] The AST node to get the text for.
|
||||
* @param {number} [beforeCount] The number of characters before the node to retrieve.
|
||||
* @param {number} [afterCount] The number of characters after the node to retrieve.
|
||||
* @returns {string} The text representing the AST node.
|
||||
* @public
|
||||
*/
|
||||
getText(node, beforeCount, afterCount) {
|
||||
if (node) {
|
||||
const range = this.getRange(node);
|
||||
return this.text.slice(
|
||||
Math.max(range[0] - (beforeCount || 0), 0),
|
||||
range[1] + (afterCount || 0),
|
||||
);
|
||||
}
|
||||
return this.text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entire source text split into an array of lines.
|
||||
* @returns {Array<string>} The source text as an array of lines.
|
||||
* @public
|
||||
*/
|
||||
get lines() {
|
||||
this.#ensureLines(); // Ensure `#lines` is lazily calculated.
|
||||
|
||||
return this.#lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse the source code and return the steps that were taken.
|
||||
* @returns {Iterable<TraversalStep>} The steps that were taken while traversing the source code.
|
||||
*/
|
||||
traverse() {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
exports.CallMethodStep = CallMethodStep;
|
||||
exports.ConfigCommentParser = ConfigCommentParser;
|
||||
exports.Directive = Directive;
|
||||
exports.TextSourceCodeBase = TextSourceCodeBase;
|
||||
exports.VisitNodeStep = VisitNodeStep;
|
||||
329
node_modules/@eslint/plugin-kit/dist/cjs/index.d.cts
generated
vendored
Normal file
329
node_modules/@eslint/plugin-kit/dist/cjs/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
export type VisitTraversalStep = $eslintcore.VisitTraversalStep;
|
||||
export type CallTraversalStep = $eslintcore.CallTraversalStep;
|
||||
export type TraversalStep = $eslintcore.TraversalStep;
|
||||
export type SourceLocation = $eslintcore.SourceLocation;
|
||||
export type SourceLocationWithOffset = $eslintcore.SourceLocationWithOffset;
|
||||
export type SourceRange = $eslintcore.SourceRange;
|
||||
export type IDirective = $eslintcore.Directive;
|
||||
export type DirectiveType = $eslintcore.DirectiveType;
|
||||
export type SourceCodeBaseTypeOptions = $eslintcore.SourceCodeBaseTypeOptions;
|
||||
export type TextSourceCode<Options extends SourceCodeBaseTypeOptions = $eslintcore.SourceCodeBaseTypeOptions> = import("@eslint/core").TextSourceCode<Options>;
|
||||
export type RuleVisitor = $eslintcore.RuleVisitor;
|
||||
export type CustomRuleVisitorWithExit<RuleVisitorType extends RuleVisitor> = import("./types.cts").CustomRuleVisitorWithExit<RuleVisitorType>;
|
||||
export type CustomRuleTypeDefinitions = $typests.CustomRuleTypeDefinitions;
|
||||
export type CustomRuleDefinitionType<LanguageSpecificOptions extends Omit<import("@eslint/core").RuleDefinitionTypeOptions, keyof CustomRuleTypeDefinitions>, Options extends Partial<CustomRuleTypeDefinitions>> = import("./types.cts").CustomRuleDefinitionType<LanguageSpecificOptions, Options>;
|
||||
export type RuleConfig = $eslintcore.RuleConfig;
|
||||
export type RulesConfig = $eslintcore.RulesConfig;
|
||||
export type StringConfig = $typests.StringConfig;
|
||||
export type BooleanConfig = $typests.BooleanConfig;
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a
|
||||
* method is called.
|
||||
* @implements {CallTraversalStep}
|
||||
*/
|
||||
export class CallMethodStep implements CallTraversalStep {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {string} options.target The target of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, args }: {
|
||||
target: string;
|
||||
args: Array<any>;
|
||||
});
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"call"}
|
||||
* @readonly
|
||||
*/
|
||||
readonly type: "call";
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {2}
|
||||
* @readonly
|
||||
*/
|
||||
readonly kind: 2;
|
||||
/**
|
||||
* The name of the method to call.
|
||||
* @type {string}
|
||||
*/
|
||||
target: string;
|
||||
/**
|
||||
* The arguments to pass to the method.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args: Array<any>;
|
||||
}
|
||||
/**
|
||||
* Object to parse ESLint configuration comments.
|
||||
*/
|
||||
export class ConfigCommentParser {
|
||||
/**
|
||||
* Parses a list of "name:string_value" or/and "name" options divided by comma or
|
||||
* whitespace. Used for "global" comments.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {StringConfig} Result map object of names and string values, or null values if no value was provided.
|
||||
*/
|
||||
parseStringConfig(string: string): StringConfig;
|
||||
/**
|
||||
* Parses a JSON-like config.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {({ok: true, config: RulesConfig}|{ok: false, error: {message: string}})} Result map object
|
||||
*/
|
||||
parseJSONLikeConfig(string: string): ({
|
||||
ok: true;
|
||||
config: RulesConfig;
|
||||
} | {
|
||||
ok: false;
|
||||
error: {
|
||||
message: string;
|
||||
};
|
||||
});
|
||||
/**
|
||||
* Parses a config of values separated by comma.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {BooleanConfig} Result map of values and true values
|
||||
*/
|
||||
parseListConfig(string: string): BooleanConfig;
|
||||
/**
|
||||
* Parses a directive comment into directive text and value.
|
||||
* @param {string} string The string with the directive to be parsed.
|
||||
* @returns {DirectiveComment|undefined} The parsed directive or `undefined` if the directive is invalid.
|
||||
*/
|
||||
parseDirective(string: string): DirectiveComment | undefined;
|
||||
#private;
|
||||
}
|
||||
/**
|
||||
* A class to represent a directive comment.
|
||||
* @implements {IDirective}
|
||||
*/
|
||||
export class Directive implements IDirective {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the directive.
|
||||
* @param {"disable"|"enable"|"disable-next-line"|"disable-line"} options.type The type of directive.
|
||||
* @param {unknown} options.node The node representing the directive.
|
||||
* @param {string} options.value The value of the directive.
|
||||
* @param {string} options.justification The justification for the directive.
|
||||
*/
|
||||
constructor({ type, node, value, justification }: {
|
||||
type: "disable" | "enable" | "disable-next-line" | "disable-line";
|
||||
node: unknown;
|
||||
value: string;
|
||||
justification: string;
|
||||
});
|
||||
/**
|
||||
* The type of directive.
|
||||
* @type {DirectiveType}
|
||||
* @readonly
|
||||
*/
|
||||
readonly type: DirectiveType;
|
||||
/**
|
||||
* The node representing the directive.
|
||||
* @type {unknown}
|
||||
* @readonly
|
||||
*/
|
||||
readonly node: unknown;
|
||||
/**
|
||||
* Everything after the "eslint-disable" portion of the directive,
|
||||
* but before the "--" that indicates the justification.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
readonly value: string;
|
||||
/**
|
||||
* The justification for the directive.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
readonly justification: string;
|
||||
}
|
||||
/**
|
||||
* Source Code Base Object
|
||||
* @template {SourceCodeBaseTypeOptions & {RootNode: object, SyntaxElementWithLoc: object}} [Options=SourceCodeBaseTypeOptions & {RootNode: object, SyntaxElementWithLoc: object}]
|
||||
* @implements {TextSourceCode<Options>}
|
||||
*/
|
||||
export class TextSourceCodeBase<Options extends SourceCodeBaseTypeOptions & {
|
||||
RootNode: object;
|
||||
SyntaxElementWithLoc: object;
|
||||
} = $eslintcore.SourceCodeBaseTypeOptions & {
|
||||
RootNode: object;
|
||||
SyntaxElementWithLoc: object;
|
||||
}> implements TextSourceCode<Options> {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the instance.
|
||||
* @param {string} options.text The source code text.
|
||||
* @param {Options['RootNode']} options.ast The root AST node.
|
||||
* @param {RegExp} [options.lineEndingPattern] The pattern to match lineEndings in the source code. Defaults to `/\r?\n/u`.
|
||||
*/
|
||||
constructor({ text, ast, lineEndingPattern }: {
|
||||
text: string;
|
||||
ast: Options["RootNode"];
|
||||
lineEndingPattern?: RegExp;
|
||||
});
|
||||
/**
|
||||
* The AST of the source code.
|
||||
* @type {Options['RootNode']}
|
||||
*/
|
||||
ast: Options["RootNode"];
|
||||
/**
|
||||
* The text of the source code.
|
||||
* @type {string}
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
* Returns the loc information for the given node or token.
|
||||
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the loc information for.
|
||||
* @returns {SourceLocation} The loc information for the node or token.
|
||||
* @throws {Error} If the node or token does not have loc information.
|
||||
*/
|
||||
getLoc(nodeOrToken: Options["SyntaxElementWithLoc"]): SourceLocation;
|
||||
/**
|
||||
* Converts a source text index into a `{ line: number, column: number }` pair.
|
||||
* @param {number} index The index of a character in a file.
|
||||
* @throws {TypeError|RangeError} If non-numeric index or index out of range.
|
||||
* @returns {{line: number, column: number}} A `{ line: number, column: number }` location object with 0 or 1-indexed line and 0 or 1-indexed column based on language.
|
||||
* @public
|
||||
*/
|
||||
public getLocFromIndex(index: number): {
|
||||
line: number;
|
||||
column: number;
|
||||
};
|
||||
/**
|
||||
* Converts a `{ line: number, column: number }` pair into a source text index.
|
||||
* @param {Object} loc A line/column location.
|
||||
* @param {number} loc.line The line number of the location. (0 or 1-indexed based on language.)
|
||||
* @param {number} loc.column The column number of the location. (0 or 1-indexed based on language.)
|
||||
* @throws {TypeError|RangeError} If `loc` is not an object with a numeric
|
||||
* `line` and `column`, if the `line` is less than or equal to zero or
|
||||
* the `line` or `column` is out of the expected range.
|
||||
* @returns {number} The index of the line/column location in a file.
|
||||
* @public
|
||||
*/
|
||||
public getIndexFromLoc(loc: {
|
||||
line: number;
|
||||
column: number;
|
||||
}): number;
|
||||
/**
|
||||
* Returns the range information for the given node or token.
|
||||
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the range information for.
|
||||
* @returns {SourceRange} The range information for the node or token.
|
||||
* @throws {Error} If the node or token does not have range information.
|
||||
*/
|
||||
getRange(nodeOrToken: Options["SyntaxElementWithLoc"]): SourceRange;
|
||||
/**
|
||||
* Returns the parent of the given node.
|
||||
* @param {Options['SyntaxElementWithLoc']} node The node to get the parent of.
|
||||
* @returns {Options['SyntaxElementWithLoc']|undefined} The parent of the node.
|
||||
* @throws {Error} If the method is not implemented in the subclass.
|
||||
*/
|
||||
getParent(node: Options["SyntaxElementWithLoc"]): Options["SyntaxElementWithLoc"] | undefined;
|
||||
/**
|
||||
* Gets all the ancestors of a given node
|
||||
* @param {Options['SyntaxElementWithLoc']} node The node
|
||||
* @returns {Array<Options['SyntaxElementWithLoc']>} All the ancestor nodes in the AST, not including the provided node, starting
|
||||
* from the root node at index 0 and going inwards to the parent node.
|
||||
* @throws {TypeError} When `node` is missing.
|
||||
*/
|
||||
getAncestors(node: Options["SyntaxElementWithLoc"]): Array<Options["SyntaxElementWithLoc"]>;
|
||||
/**
|
||||
* Gets the source code for the given node.
|
||||
* @param {Options['SyntaxElementWithLoc']} [node] The AST node to get the text for.
|
||||
* @param {number} [beforeCount] The number of characters before the node to retrieve.
|
||||
* @param {number} [afterCount] The number of characters after the node to retrieve.
|
||||
* @returns {string} The text representing the AST node.
|
||||
* @public
|
||||
*/
|
||||
public getText(node?: Options["SyntaxElementWithLoc"], beforeCount?: number, afterCount?: number): string;
|
||||
/**
|
||||
* Gets the entire source text split into an array of lines.
|
||||
* @returns {Array<string>} The source text as an array of lines.
|
||||
* @public
|
||||
*/
|
||||
public get lines(): Array<string>;
|
||||
/**
|
||||
* Traverse the source code and return the steps that were taken.
|
||||
* @returns {Iterable<TraversalStep>} The steps that were taken while traversing the source code.
|
||||
*/
|
||||
traverse(): Iterable<TraversalStep>;
|
||||
#private;
|
||||
}
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a node is visited.
|
||||
* @implements {VisitTraversalStep}
|
||||
*/
|
||||
export class VisitNodeStep implements VisitTraversalStep {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {object} options.target The target of the step.
|
||||
* @param {1|2} options.phase The phase of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, phase, args }: {
|
||||
target: object;
|
||||
phase: 1 | 2;
|
||||
args: Array<any>;
|
||||
});
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"visit"}
|
||||
* @readonly
|
||||
*/
|
||||
readonly type: "visit";
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {1}
|
||||
* @readonly
|
||||
*/
|
||||
readonly kind: 1;
|
||||
/**
|
||||
* The target of the step.
|
||||
* @type {object}
|
||||
*/
|
||||
target: object;
|
||||
/**
|
||||
* The phase of the step.
|
||||
* @type {1|2}
|
||||
*/
|
||||
phase: 1 | 2;
|
||||
/**
|
||||
* The arguments of the step.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args: Array<any>;
|
||||
}
|
||||
import type * as $eslintcore from "@eslint/core";
|
||||
import type * as $typests from "./types.cts";
|
||||
/**
|
||||
* Represents a directive comment.
|
||||
*/
|
||||
declare class DirectiveComment {
|
||||
/**
|
||||
* Creates a new directive comment.
|
||||
* @param {string} label The label of the directive.
|
||||
* @param {string} value The value of the directive.
|
||||
* @param {string} justification The justification of the directive.
|
||||
*/
|
||||
constructor(label: string, value: string, justification: string);
|
||||
/**
|
||||
* The label of the directive, such as "eslint", "eslint-disable", etc.
|
||||
* @type {string}
|
||||
*/
|
||||
label: string;
|
||||
/**
|
||||
* The value of the directive (the string after the label).
|
||||
* @type {string}
|
||||
*/
|
||||
value: string;
|
||||
/**
|
||||
* The justification of the directive (the string after the --).
|
||||
* @type {string}
|
||||
*/
|
||||
justification: string;
|
||||
}
|
||||
export {};
|
||||
81
node_modules/@eslint/plugin-kit/dist/cjs/types.cts
generated
vendored
Normal file
81
node_modules/@eslint/plugin-kit/dist/cjs/types.cts
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @fileoverview Types for the plugin-kit package.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Imports
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
import type {
|
||||
RuleDefinition,
|
||||
RuleDefinitionTypeOptions,
|
||||
RuleVisitor,
|
||||
} from "@eslint/core";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Exports
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Defaults for non-language-related `RuleDefinition` options.
|
||||
*/
|
||||
export interface CustomRuleTypeDefinitions {
|
||||
RuleOptions: unknown[];
|
||||
MessageIds: string;
|
||||
ExtRuleDocs: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper type to define language specific specializations of the `RuleDefinition` type.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* type YourRuleDefinition<
|
||||
* Options extends Partial<CustomRuleTypeDefinitions> = {},
|
||||
* > = CustomRuleDefinitionType<
|
||||
* {
|
||||
* LangOptions: YourLanguageOptions;
|
||||
* Code: YourSourceCode;
|
||||
* Visitor: YourRuleVisitor;
|
||||
* Node: YourNode;
|
||||
* },
|
||||
* Options
|
||||
* >;
|
||||
* ```
|
||||
*/
|
||||
export type CustomRuleDefinitionType<
|
||||
LanguageSpecificOptions extends Omit<
|
||||
RuleDefinitionTypeOptions,
|
||||
keyof CustomRuleTypeDefinitions
|
||||
>,
|
||||
Options extends Partial<CustomRuleTypeDefinitions>,
|
||||
> = RuleDefinition<
|
||||
// Language specific type options (non-configurable)
|
||||
LanguageSpecificOptions &
|
||||
Required<
|
||||
// Rule specific type options (custom)
|
||||
Options &
|
||||
// Rule specific type options (defaults)
|
||||
Omit<CustomRuleTypeDefinitions, keyof Options>
|
||||
>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Adds matching `:exit` selector properties for each key of a `RuleVisitor`.
|
||||
*/
|
||||
export type CustomRuleVisitorWithExit<RuleVisitorType extends RuleVisitor> = {
|
||||
[Key in keyof RuleVisitorType as
|
||||
| Key
|
||||
| `${Key & string}:exit`]: RuleVisitorType[Key];
|
||||
};
|
||||
|
||||
/**
|
||||
* A map of names to string values, or `null` when no value is provided.
|
||||
*/
|
||||
export type StringConfig = Record<string, string | null>;
|
||||
|
||||
/**
|
||||
* A map of names to boolean flags.
|
||||
*/
|
||||
export type BooleanConfig = Record<string, boolean>;
|
||||
329
node_modules/@eslint/plugin-kit/dist/esm/index.d.ts
generated
vendored
Normal file
329
node_modules/@eslint/plugin-kit/dist/esm/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
export type VisitTraversalStep = $eslintcore.VisitTraversalStep;
|
||||
export type CallTraversalStep = $eslintcore.CallTraversalStep;
|
||||
export type TraversalStep = $eslintcore.TraversalStep;
|
||||
export type SourceLocation = $eslintcore.SourceLocation;
|
||||
export type SourceLocationWithOffset = $eslintcore.SourceLocationWithOffset;
|
||||
export type SourceRange = $eslintcore.SourceRange;
|
||||
export type IDirective = $eslintcore.Directive;
|
||||
export type DirectiveType = $eslintcore.DirectiveType;
|
||||
export type SourceCodeBaseTypeOptions = $eslintcore.SourceCodeBaseTypeOptions;
|
||||
export type TextSourceCode<Options extends SourceCodeBaseTypeOptions = $eslintcore.SourceCodeBaseTypeOptions> = import("@eslint/core").TextSourceCode<Options>;
|
||||
export type RuleVisitor = $eslintcore.RuleVisitor;
|
||||
export type CustomRuleVisitorWithExit<RuleVisitorType extends RuleVisitor> = import("./types.ts").CustomRuleVisitorWithExit<RuleVisitorType>;
|
||||
export type CustomRuleTypeDefinitions = $typests.CustomRuleTypeDefinitions;
|
||||
export type CustomRuleDefinitionType<LanguageSpecificOptions extends Omit<import("@eslint/core").RuleDefinitionTypeOptions, keyof CustomRuleTypeDefinitions>, Options extends Partial<CustomRuleTypeDefinitions>> = import("./types.ts").CustomRuleDefinitionType<LanguageSpecificOptions, Options>;
|
||||
export type RuleConfig = $eslintcore.RuleConfig;
|
||||
export type RulesConfig = $eslintcore.RulesConfig;
|
||||
export type StringConfig = $typests.StringConfig;
|
||||
export type BooleanConfig = $typests.BooleanConfig;
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a
|
||||
* method is called.
|
||||
* @implements {CallTraversalStep}
|
||||
*/
|
||||
export class CallMethodStep implements CallTraversalStep {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {string} options.target The target of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, args }: {
|
||||
target: string;
|
||||
args: Array<any>;
|
||||
});
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"call"}
|
||||
* @readonly
|
||||
*/
|
||||
readonly type: "call";
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {2}
|
||||
* @readonly
|
||||
*/
|
||||
readonly kind: 2;
|
||||
/**
|
||||
* The name of the method to call.
|
||||
* @type {string}
|
||||
*/
|
||||
target: string;
|
||||
/**
|
||||
* The arguments to pass to the method.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args: Array<any>;
|
||||
}
|
||||
/**
|
||||
* Object to parse ESLint configuration comments.
|
||||
*/
|
||||
export class ConfigCommentParser {
|
||||
/**
|
||||
* Parses a list of "name:string_value" or/and "name" options divided by comma or
|
||||
* whitespace. Used for "global" comments.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {StringConfig} Result map object of names and string values, or null values if no value was provided.
|
||||
*/
|
||||
parseStringConfig(string: string): StringConfig;
|
||||
/**
|
||||
* Parses a JSON-like config.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {({ok: true, config: RulesConfig}|{ok: false, error: {message: string}})} Result map object
|
||||
*/
|
||||
parseJSONLikeConfig(string: string): ({
|
||||
ok: true;
|
||||
config: RulesConfig;
|
||||
} | {
|
||||
ok: false;
|
||||
error: {
|
||||
message: string;
|
||||
};
|
||||
});
|
||||
/**
|
||||
* Parses a config of values separated by comma.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {BooleanConfig} Result map of values and true values
|
||||
*/
|
||||
parseListConfig(string: string): BooleanConfig;
|
||||
/**
|
||||
* Parses a directive comment into directive text and value.
|
||||
* @param {string} string The string with the directive to be parsed.
|
||||
* @returns {DirectiveComment|undefined} The parsed directive or `undefined` if the directive is invalid.
|
||||
*/
|
||||
parseDirective(string: string): DirectiveComment | undefined;
|
||||
#private;
|
||||
}
|
||||
/**
|
||||
* A class to represent a directive comment.
|
||||
* @implements {IDirective}
|
||||
*/
|
||||
export class Directive implements IDirective {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the directive.
|
||||
* @param {"disable"|"enable"|"disable-next-line"|"disable-line"} options.type The type of directive.
|
||||
* @param {unknown} options.node The node representing the directive.
|
||||
* @param {string} options.value The value of the directive.
|
||||
* @param {string} options.justification The justification for the directive.
|
||||
*/
|
||||
constructor({ type, node, value, justification }: {
|
||||
type: "disable" | "enable" | "disable-next-line" | "disable-line";
|
||||
node: unknown;
|
||||
value: string;
|
||||
justification: string;
|
||||
});
|
||||
/**
|
||||
* The type of directive.
|
||||
* @type {DirectiveType}
|
||||
* @readonly
|
||||
*/
|
||||
readonly type: DirectiveType;
|
||||
/**
|
||||
* The node representing the directive.
|
||||
* @type {unknown}
|
||||
* @readonly
|
||||
*/
|
||||
readonly node: unknown;
|
||||
/**
|
||||
* Everything after the "eslint-disable" portion of the directive,
|
||||
* but before the "--" that indicates the justification.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
readonly value: string;
|
||||
/**
|
||||
* The justification for the directive.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
readonly justification: string;
|
||||
}
|
||||
/**
|
||||
* Source Code Base Object
|
||||
* @template {SourceCodeBaseTypeOptions & {RootNode: object, SyntaxElementWithLoc: object}} [Options=SourceCodeBaseTypeOptions & {RootNode: object, SyntaxElementWithLoc: object}]
|
||||
* @implements {TextSourceCode<Options>}
|
||||
*/
|
||||
export class TextSourceCodeBase<Options extends SourceCodeBaseTypeOptions & {
|
||||
RootNode: object;
|
||||
SyntaxElementWithLoc: object;
|
||||
} = $eslintcore.SourceCodeBaseTypeOptions & {
|
||||
RootNode: object;
|
||||
SyntaxElementWithLoc: object;
|
||||
}> implements TextSourceCode<Options> {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the instance.
|
||||
* @param {string} options.text The source code text.
|
||||
* @param {Options['RootNode']} options.ast The root AST node.
|
||||
* @param {RegExp} [options.lineEndingPattern] The pattern to match lineEndings in the source code. Defaults to `/\r?\n/u`.
|
||||
*/
|
||||
constructor({ text, ast, lineEndingPattern }: {
|
||||
text: string;
|
||||
ast: Options["RootNode"];
|
||||
lineEndingPattern?: RegExp;
|
||||
});
|
||||
/**
|
||||
* The AST of the source code.
|
||||
* @type {Options['RootNode']}
|
||||
*/
|
||||
ast: Options["RootNode"];
|
||||
/**
|
||||
* The text of the source code.
|
||||
* @type {string}
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
* Returns the loc information for the given node or token.
|
||||
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the loc information for.
|
||||
* @returns {SourceLocation} The loc information for the node or token.
|
||||
* @throws {Error} If the node or token does not have loc information.
|
||||
*/
|
||||
getLoc(nodeOrToken: Options["SyntaxElementWithLoc"]): SourceLocation;
|
||||
/**
|
||||
* Converts a source text index into a `{ line: number, column: number }` pair.
|
||||
* @param {number} index The index of a character in a file.
|
||||
* @throws {TypeError|RangeError} If non-numeric index or index out of range.
|
||||
* @returns {{line: number, column: number}} A `{ line: number, column: number }` location object with 0 or 1-indexed line and 0 or 1-indexed column based on language.
|
||||
* @public
|
||||
*/
|
||||
public getLocFromIndex(index: number): {
|
||||
line: number;
|
||||
column: number;
|
||||
};
|
||||
/**
|
||||
* Converts a `{ line: number, column: number }` pair into a source text index.
|
||||
* @param {Object} loc A line/column location.
|
||||
* @param {number} loc.line The line number of the location. (0 or 1-indexed based on language.)
|
||||
* @param {number} loc.column The column number of the location. (0 or 1-indexed based on language.)
|
||||
* @throws {TypeError|RangeError} If `loc` is not an object with a numeric
|
||||
* `line` and `column`, if the `line` is less than or equal to zero or
|
||||
* the `line` or `column` is out of the expected range.
|
||||
* @returns {number} The index of the line/column location in a file.
|
||||
* @public
|
||||
*/
|
||||
public getIndexFromLoc(loc: {
|
||||
line: number;
|
||||
column: number;
|
||||
}): number;
|
||||
/**
|
||||
* Returns the range information for the given node or token.
|
||||
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the range information for.
|
||||
* @returns {SourceRange} The range information for the node or token.
|
||||
* @throws {Error} If the node or token does not have range information.
|
||||
*/
|
||||
getRange(nodeOrToken: Options["SyntaxElementWithLoc"]): SourceRange;
|
||||
/**
|
||||
* Returns the parent of the given node.
|
||||
* @param {Options['SyntaxElementWithLoc']} node The node to get the parent of.
|
||||
* @returns {Options['SyntaxElementWithLoc']|undefined} The parent of the node.
|
||||
* @throws {Error} If the method is not implemented in the subclass.
|
||||
*/
|
||||
getParent(node: Options["SyntaxElementWithLoc"]): Options["SyntaxElementWithLoc"] | undefined;
|
||||
/**
|
||||
* Gets all the ancestors of a given node
|
||||
* @param {Options['SyntaxElementWithLoc']} node The node
|
||||
* @returns {Array<Options['SyntaxElementWithLoc']>} All the ancestor nodes in the AST, not including the provided node, starting
|
||||
* from the root node at index 0 and going inwards to the parent node.
|
||||
* @throws {TypeError} When `node` is missing.
|
||||
*/
|
||||
getAncestors(node: Options["SyntaxElementWithLoc"]): Array<Options["SyntaxElementWithLoc"]>;
|
||||
/**
|
||||
* Gets the source code for the given node.
|
||||
* @param {Options['SyntaxElementWithLoc']} [node] The AST node to get the text for.
|
||||
* @param {number} [beforeCount] The number of characters before the node to retrieve.
|
||||
* @param {number} [afterCount] The number of characters after the node to retrieve.
|
||||
* @returns {string} The text representing the AST node.
|
||||
* @public
|
||||
*/
|
||||
public getText(node?: Options["SyntaxElementWithLoc"], beforeCount?: number, afterCount?: number): string;
|
||||
/**
|
||||
* Gets the entire source text split into an array of lines.
|
||||
* @returns {Array<string>} The source text as an array of lines.
|
||||
* @public
|
||||
*/
|
||||
public get lines(): Array<string>;
|
||||
/**
|
||||
* Traverse the source code and return the steps that were taken.
|
||||
* @returns {Iterable<TraversalStep>} The steps that were taken while traversing the source code.
|
||||
*/
|
||||
traverse(): Iterable<TraversalStep>;
|
||||
#private;
|
||||
}
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a node is visited.
|
||||
* @implements {VisitTraversalStep}
|
||||
*/
|
||||
export class VisitNodeStep implements VisitTraversalStep {
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {object} options.target The target of the step.
|
||||
* @param {1|2} options.phase The phase of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, phase, args }: {
|
||||
target: object;
|
||||
phase: 1 | 2;
|
||||
args: Array<any>;
|
||||
});
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"visit"}
|
||||
* @readonly
|
||||
*/
|
||||
readonly type: "visit";
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {1}
|
||||
* @readonly
|
||||
*/
|
||||
readonly kind: 1;
|
||||
/**
|
||||
* The target of the step.
|
||||
* @type {object}
|
||||
*/
|
||||
target: object;
|
||||
/**
|
||||
* The phase of the step.
|
||||
* @type {1|2}
|
||||
*/
|
||||
phase: 1 | 2;
|
||||
/**
|
||||
* The arguments of the step.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args: Array<any>;
|
||||
}
|
||||
import type * as $eslintcore from "@eslint/core";
|
||||
import type * as $typests from "./types.ts";
|
||||
/**
|
||||
* Represents a directive comment.
|
||||
*/
|
||||
declare class DirectiveComment {
|
||||
/**
|
||||
* Creates a new directive comment.
|
||||
* @param {string} label The label of the directive.
|
||||
* @param {string} value The value of the directive.
|
||||
* @param {string} justification The justification of the directive.
|
||||
*/
|
||||
constructor(label: string, value: string, justification: string);
|
||||
/**
|
||||
* The label of the directive, such as "eslint", "eslint-disable", etc.
|
||||
* @type {string}
|
||||
*/
|
||||
label: string;
|
||||
/**
|
||||
* The value of the directive (the string after the label).
|
||||
* @type {string}
|
||||
*/
|
||||
value: string;
|
||||
/**
|
||||
* The justification of the directive (the string after the --).
|
||||
* @type {string}
|
||||
*/
|
||||
justification: string;
|
||||
}
|
||||
export {};
|
||||
890
node_modules/@eslint/plugin-kit/dist/esm/index.js
generated
vendored
Normal file
890
node_modules/@eslint/plugin-kit/dist/esm/index.js
generated
vendored
Normal file
@@ -0,0 +1,890 @@
|
||||
// @ts-self-types="./index.d.ts"
|
||||
import levn from 'levn';
|
||||
|
||||
/**
|
||||
* @fileoverview Config Comment Parser
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @import * as $eslintcore from "@eslint/core"; */
|
||||
/** @typedef {$eslintcore.RuleConfig} RuleConfig */
|
||||
/** @typedef {$eslintcore.RulesConfig} RulesConfig */
|
||||
/** @import * as $typests from "./types.ts"; */
|
||||
/** @typedef {$typests.StringConfig} StringConfig */
|
||||
/** @typedef {$typests.BooleanConfig} BooleanConfig */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const directivesPattern = /^([a-z]+(?:-[a-z]+)*)(?:\s|$)/u;
|
||||
const validSeverities = new Set([0, 1, 2, "off", "warn", "error"]);
|
||||
|
||||
/**
|
||||
* Determines if the severity in the rule configuration is valid.
|
||||
* @param {RuleConfig} ruleConfig A rule's configuration.
|
||||
* @returns {boolean} `true` if the severity is valid, otherwise `false`.
|
||||
*/
|
||||
function isSeverityValid(ruleConfig) {
|
||||
const severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
|
||||
return validSeverities.has(severity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if all severities in the rules configuration are valid.
|
||||
* @param {RulesConfig} rulesConfig The rules configuration to check.
|
||||
* @returns {boolean} `true` if all severities are valid, otherwise `false`.
|
||||
*/
|
||||
function isEverySeverityValid(rulesConfig) {
|
||||
return Object.values(rulesConfig).every(isSeverityValid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a directive comment.
|
||||
*/
|
||||
class DirectiveComment {
|
||||
/**
|
||||
* The label of the directive, such as "eslint", "eslint-disable", etc.
|
||||
* @type {string}
|
||||
*/
|
||||
label = "";
|
||||
|
||||
/**
|
||||
* The value of the directive (the string after the label).
|
||||
* @type {string}
|
||||
*/
|
||||
value = "";
|
||||
|
||||
/**
|
||||
* The justification of the directive (the string after the --).
|
||||
* @type {string}
|
||||
*/
|
||||
justification = "";
|
||||
|
||||
/**
|
||||
* Creates a new directive comment.
|
||||
* @param {string} label The label of the directive.
|
||||
* @param {string} value The value of the directive.
|
||||
* @param {string} justification The justification of the directive.
|
||||
*/
|
||||
constructor(label, value, justification) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
this.justification = justification;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Object to parse ESLint configuration comments.
|
||||
*/
|
||||
class ConfigCommentParser {
|
||||
/**
|
||||
* Parses a list of "name:string_value" or/and "name" options divided by comma or
|
||||
* whitespace. Used for "global" comments.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {StringConfig} Result map object of names and string values, or null values if no value was provided.
|
||||
*/
|
||||
parseStringConfig(string) {
|
||||
const items = /** @type {StringConfig} */ ({});
|
||||
|
||||
// Collapse whitespace around `:` and `,` to make parsing easier
|
||||
const trimmedString = string
|
||||
.trim()
|
||||
.replace(/(?<!\s)\s*([:,])\s*/gu, "$1");
|
||||
|
||||
trimmedString.split(/\s|,+/u).forEach(name => {
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
// value defaults to null (if not provided), e.g: "foo" => ["foo", null]
|
||||
const [key, value = null] = name.split(":");
|
||||
|
||||
items[key] = value;
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JSON-like config.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {({ok: true, config: RulesConfig}|{ok: false, error: {message: string}})} Result map object
|
||||
*/
|
||||
parseJSONLikeConfig(string) {
|
||||
// Parses a JSON-like comment by the same way as parsing CLI option.
|
||||
try {
|
||||
const items =
|
||||
/** @type {RulesConfig} */ (levn.parse("Object", string)) || {};
|
||||
|
||||
/*
|
||||
* When the configuration has any invalid severities, it should be completely
|
||||
* ignored. This is because the configuration is not valid and should not be
|
||||
* applied.
|
||||
*
|
||||
* For example, the following configuration is invalid:
|
||||
*
|
||||
* "no-alert: 2 no-console: 2"
|
||||
*
|
||||
* This results in a configuration of { "no-alert": "2 no-console: 2" }, which is
|
||||
* not valid. In this case, the configuration should be ignored.
|
||||
*/
|
||||
if (isEverySeverityValid(items)) {
|
||||
return {
|
||||
ok: true,
|
||||
config: items,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// levn parsing error: ignore to parse the string by a fallback.
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionator cannot parse commaless notations.
|
||||
* But we are supporting that. So this is a fallback for that.
|
||||
*/
|
||||
const normalizedString = string
|
||||
.replace(/(?<![-a-zA-Z0-9/])([-a-zA-Z0-9/]+):/gu, '"$1":')
|
||||
.replace(/([\]0-9])\s+(?=")/u, "$1,");
|
||||
|
||||
try {
|
||||
const items = JSON.parse(`{${normalizedString}}`);
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
config: items,
|
||||
};
|
||||
} catch (ex) {
|
||||
const errorMessage = ex instanceof Error ? ex.message : String(ex);
|
||||
|
||||
return {
|
||||
ok: false,
|
||||
error: {
|
||||
message: `Failed to parse JSON from '${normalizedString}': ${errorMessage}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a config of values separated by comma.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {BooleanConfig} Result map of values and true values
|
||||
*/
|
||||
parseListConfig(string) {
|
||||
const items = /** @type {BooleanConfig} */ ({});
|
||||
|
||||
string.split(",").forEach(name => {
|
||||
const trimmedName = name
|
||||
.trim()
|
||||
.replace(
|
||||
/^(?<quote>['"]?)(?<ruleId>.*)\k<quote>$/su,
|
||||
"$<ruleId>",
|
||||
);
|
||||
|
||||
if (trimmedName) {
|
||||
items[trimmedName] = true;
|
||||
}
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the directive and the justification from a given directive comment and trim them.
|
||||
* @param {string} value The comment text to extract.
|
||||
* @returns {{directivePart: string, justificationPart: string}} The extracted directive and justification.
|
||||
*/
|
||||
#extractDirectiveComment(value) {
|
||||
const match = /\s-{2,}\s/u.exec(value);
|
||||
|
||||
if (!match) {
|
||||
return { directivePart: value.trim(), justificationPart: "" };
|
||||
}
|
||||
|
||||
const directive = value.slice(0, match.index).trim();
|
||||
const justification = value.slice(match.index + match[0].length).trim();
|
||||
|
||||
return { directivePart: directive, justificationPart: justification };
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a directive comment into directive text and value.
|
||||
* @param {string} string The string with the directive to be parsed.
|
||||
* @returns {DirectiveComment|undefined} The parsed directive or `undefined` if the directive is invalid.
|
||||
*/
|
||||
parseDirective(string) {
|
||||
const { directivePart, justificationPart } =
|
||||
this.#extractDirectiveComment(string);
|
||||
const match = directivesPattern.exec(directivePart);
|
||||
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const directiveText = match[1];
|
||||
const directiveValue = directivePart.slice(
|
||||
match.index + directiveText.length,
|
||||
);
|
||||
|
||||
return new DirectiveComment(
|
||||
directiveText,
|
||||
directiveValue.trim(),
|
||||
justificationPart,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview A collection of helper classes for implementing `SourceCode`.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/* eslint class-methods-use-this: off -- Required to complete interface. */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @typedef {$eslintcore.VisitTraversalStep} VisitTraversalStep */
|
||||
/** @typedef {$eslintcore.CallTraversalStep} CallTraversalStep */
|
||||
/** @typedef {$eslintcore.TraversalStep} TraversalStep */
|
||||
/** @typedef {$eslintcore.SourceLocation} SourceLocation */
|
||||
/** @typedef {$eslintcore.SourceLocationWithOffset} SourceLocationWithOffset */
|
||||
/** @typedef {$eslintcore.SourceRange} SourceRange */
|
||||
/** @typedef {$eslintcore.Directive} IDirective */
|
||||
/** @typedef {$eslintcore.DirectiveType} DirectiveType */
|
||||
/** @typedef {$eslintcore.SourceCodeBaseTypeOptions} SourceCodeBaseTypeOptions */
|
||||
/**
|
||||
* @typedef {import("@eslint/core").TextSourceCode<Options>} TextSourceCode
|
||||
* @template {SourceCodeBaseTypeOptions} [Options=SourceCodeBaseTypeOptions]
|
||||
*/
|
||||
/** @typedef {$eslintcore.RuleVisitor} RuleVisitor */
|
||||
/**
|
||||
* @typedef {import("./types.ts").CustomRuleVisitorWithExit<RuleVisitorType>} CustomRuleVisitorWithExit
|
||||
* @template {RuleVisitor} RuleVisitorType
|
||||
*/
|
||||
/** @typedef {$typests.CustomRuleTypeDefinitions} CustomRuleTypeDefinitions */
|
||||
/**
|
||||
* @typedef {import("./types.ts").CustomRuleDefinitionType<LanguageSpecificOptions, Options>} CustomRuleDefinitionType
|
||||
* @template {Omit<import("@eslint/core").RuleDefinitionTypeOptions, keyof CustomRuleTypeDefinitions>} LanguageSpecificOptions
|
||||
* @template {Partial<CustomRuleTypeDefinitions>} Options
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines if a node has ESTree-style loc information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {loc:SourceLocation}} `true` if the node has ESTree-style loc information, `false` if not.
|
||||
*/
|
||||
function hasESTreeStyleLoc(node) {
|
||||
return "loc" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has position-style loc information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {position:SourceLocation}} `true` if the node has position-style range information, `false` if not.
|
||||
*/
|
||||
function hasPosStyleLoc(node) {
|
||||
return "position" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has ESTree-style range information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {range:SourceRange}} `true` if the node has ESTree-style range information, `false` if not.
|
||||
*/
|
||||
function hasESTreeStyleRange(node) {
|
||||
return "range" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has position-style range information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {position:SourceLocationWithOffset}} `true` if the node has position-style range information, `false` if not.
|
||||
*/
|
||||
function hasPosStyleRange(node) {
|
||||
return "position" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs binary search to find the line number containing a given target index.
|
||||
* Returns the lower bound - the index of the first element greater than the target.
|
||||
* **Please note that the `lineStartIndices` should be sorted in ascending order**.
|
||||
* - Time Complexity: O(log n) - Significantly faster than linear search for large files.
|
||||
* @param {number[]} lineStartIndices Sorted array of line start indices.
|
||||
* @param {number} targetIndex The target index to find the line number for.
|
||||
* @returns {number} The line number for the target index.
|
||||
*/
|
||||
function findLineNumberBinarySearch(lineStartIndices, targetIndex) {
|
||||
let low = 0;
|
||||
let high = lineStartIndices.length - 1;
|
||||
|
||||
while (low < high) {
|
||||
const mid = ((low + high) / 2) | 0; // Use bitwise OR to floor the division.
|
||||
|
||||
if (targetIndex < lineStartIndices[mid]) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a node is visited.
|
||||
* @implements {VisitTraversalStep}
|
||||
*/
|
||||
class VisitNodeStep {
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"visit"}
|
||||
* @readonly
|
||||
*/
|
||||
type = "visit";
|
||||
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {1}
|
||||
* @readonly
|
||||
*/
|
||||
kind = 1;
|
||||
|
||||
/**
|
||||
* The target of the step.
|
||||
* @type {object}
|
||||
*/
|
||||
target;
|
||||
|
||||
/**
|
||||
* The phase of the step.
|
||||
* @type {1|2}
|
||||
*/
|
||||
phase;
|
||||
|
||||
/**
|
||||
* The arguments of the step.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {object} options.target The target of the step.
|
||||
* @param {1|2} options.phase The phase of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, phase, args }) {
|
||||
this.target = target;
|
||||
this.phase = phase;
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a
|
||||
* method is called.
|
||||
* @implements {CallTraversalStep}
|
||||
*/
|
||||
class CallMethodStep {
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"call"}
|
||||
* @readonly
|
||||
*/
|
||||
type = "call";
|
||||
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {2}
|
||||
* @readonly
|
||||
*/
|
||||
kind = 2;
|
||||
|
||||
/**
|
||||
* The name of the method to call.
|
||||
* @type {string}
|
||||
*/
|
||||
target;
|
||||
|
||||
/**
|
||||
* The arguments to pass to the method.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {string} options.target The target of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, args }) {
|
||||
this.target = target;
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent a directive comment.
|
||||
* @implements {IDirective}
|
||||
*/
|
||||
class Directive {
|
||||
/**
|
||||
* The type of directive.
|
||||
* @type {DirectiveType}
|
||||
* @readonly
|
||||
*/
|
||||
type;
|
||||
|
||||
/**
|
||||
* The node representing the directive.
|
||||
* @type {unknown}
|
||||
* @readonly
|
||||
*/
|
||||
node;
|
||||
|
||||
/**
|
||||
* Everything after the "eslint-disable" portion of the directive,
|
||||
* but before the "--" that indicates the justification.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
value;
|
||||
|
||||
/**
|
||||
* The justification for the directive.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
justification;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the directive.
|
||||
* @param {"disable"|"enable"|"disable-next-line"|"disable-line"} options.type The type of directive.
|
||||
* @param {unknown} options.node The node representing the directive.
|
||||
* @param {string} options.value The value of the directive.
|
||||
* @param {string} options.justification The justification for the directive.
|
||||
*/
|
||||
constructor({ type, node, value, justification }) {
|
||||
this.type = type;
|
||||
this.node = node;
|
||||
this.value = value;
|
||||
this.justification = justification;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Source Code Base Object
|
||||
* @template {SourceCodeBaseTypeOptions & {RootNode: object, SyntaxElementWithLoc: object}} [Options=SourceCodeBaseTypeOptions & {RootNode: object, SyntaxElementWithLoc: object}]
|
||||
* @implements {TextSourceCode<Options>}
|
||||
*/
|
||||
class TextSourceCodeBase {
|
||||
/**
|
||||
* The lines of text in the source code.
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
#lines = [];
|
||||
|
||||
/**
|
||||
* The indices of the start of each line in the source code.
|
||||
* @type {Array<number>}
|
||||
*/
|
||||
#lineStartIndices = [0];
|
||||
|
||||
/**
|
||||
* The pattern to match lineEndings in the source code.
|
||||
* @type {RegExp}
|
||||
*/
|
||||
#lineEndingPattern;
|
||||
|
||||
/**
|
||||
* The AST of the source code.
|
||||
* @type {Options['RootNode']}
|
||||
*/
|
||||
ast;
|
||||
|
||||
/**
|
||||
* The text of the source code.
|
||||
* @type {string}
|
||||
*/
|
||||
text;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the instance.
|
||||
* @param {string} options.text The source code text.
|
||||
* @param {Options['RootNode']} options.ast The root AST node.
|
||||
* @param {RegExp} [options.lineEndingPattern] The pattern to match lineEndings in the source code. Defaults to `/\r?\n/u`.
|
||||
*/
|
||||
constructor({ text, ast, lineEndingPattern = /\r?\n/u }) {
|
||||
this.ast = ast;
|
||||
this.text = text;
|
||||
// Remove the global(`g`) and sticky(`y`) flags from the `lineEndingPattern` to avoid issues with lastIndex.
|
||||
this.#lineEndingPattern = new RegExp(
|
||||
lineEndingPattern.source,
|
||||
lineEndingPattern.flags.replace(/[gy]/gu, ""),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the next line in the source text and updates `#lines` and `#lineStartIndices`.
|
||||
* @param {string} text The text to search for the next line.
|
||||
* @returns {boolean} `true` if a next line was found, `false` otherwise.
|
||||
*/
|
||||
#findNextLine(text) {
|
||||
const match = this.#lineEndingPattern.exec(text);
|
||||
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.#lines.push(text.slice(0, match.index));
|
||||
this.#lineStartIndices.push(
|
||||
(this.#lineStartIndices.at(-1) ?? 0) +
|
||||
match.index +
|
||||
match[0].length,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures `#lines` is lazily calculated from the source text.
|
||||
* @returns {void}
|
||||
*/
|
||||
#ensureLines() {
|
||||
// If `#lines` has already been calculated, do nothing.
|
||||
if (this.#lines.length === this.#lineStartIndices.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (
|
||||
this.#findNextLine(this.text.slice(this.#lineStartIndices.at(-1)))
|
||||
) {
|
||||
// Continue parsing until no more matches are found.
|
||||
}
|
||||
|
||||
this.#lines.push(this.text.slice(this.#lineStartIndices.at(-1)));
|
||||
|
||||
Object.freeze(this.#lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures `#lineStartIndices` is lazily calculated up to the specified index.
|
||||
* @param {number} index The index of a character in a file.
|
||||
* @returns {void}
|
||||
*/
|
||||
#ensureLineStartIndicesFromIndex(index) {
|
||||
// If we've already parsed up to or beyond this index, do nothing.
|
||||
if (index <= (this.#lineStartIndices.at(-1) ?? 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (
|
||||
index > (this.#lineStartIndices.at(-1) ?? 0) &&
|
||||
this.#findNextLine(this.text.slice(this.#lineStartIndices.at(-1)))
|
||||
) {
|
||||
// Continue parsing until no more matches are found.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures `#lineStartIndices` is lazily calculated up to the specified loc.
|
||||
* @param {Object} loc A line/column location.
|
||||
* @param {number} loc.line The line number of the location. (0 or 1-indexed based on language.)
|
||||
* @param {number} lineStart The line number at which the parser starts counting.
|
||||
* @returns {void}
|
||||
*/
|
||||
#ensureLineStartIndicesFromLoc(loc, lineStart) {
|
||||
// Calculate line indices up to the potentially next line, as it is needed for the follow‑up calculation.
|
||||
const nextLocLineIndex = loc.line - lineStart + 1;
|
||||
const lastCalculatedLineIndex = this.#lineStartIndices.length - 1;
|
||||
let additionalLinesNeeded = nextLocLineIndex - lastCalculatedLineIndex;
|
||||
|
||||
// If we've already parsed up to or beyond this line, do nothing.
|
||||
if (additionalLinesNeeded <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (
|
||||
additionalLinesNeeded > 0 &&
|
||||
this.#findNextLine(this.text.slice(this.#lineStartIndices.at(-1)))
|
||||
) {
|
||||
// Continue parsing until no more matches are found or we have enough lines.
|
||||
additionalLinesNeeded -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the loc information for the given node or token.
|
||||
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the loc information for.
|
||||
* @returns {SourceLocation} The loc information for the node or token.
|
||||
* @throws {Error} If the node or token does not have loc information.
|
||||
*/
|
||||
getLoc(nodeOrToken) {
|
||||
if (hasESTreeStyleLoc(nodeOrToken)) {
|
||||
return nodeOrToken.loc;
|
||||
}
|
||||
|
||||
if (hasPosStyleLoc(nodeOrToken)) {
|
||||
return nodeOrToken.position;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"Custom getLoc() method must be implemented in the subclass.",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a source text index into a `{ line: number, column: number }` pair.
|
||||
* @param {number} index The index of a character in a file.
|
||||
* @throws {TypeError|RangeError} If non-numeric index or index out of range.
|
||||
* @returns {{line: number, column: number}} A `{ line: number, column: number }` location object with 0 or 1-indexed line and 0 or 1-indexed column based on language.
|
||||
* @public
|
||||
*/
|
||||
getLocFromIndex(index) {
|
||||
if (typeof index !== "number") {
|
||||
throw new TypeError("Expected `index` to be a number.");
|
||||
}
|
||||
|
||||
if (index < 0 || index > this.text.length) {
|
||||
throw new RangeError(
|
||||
`Index out of range (requested index ${index}, but source text has length ${this.text.length}).`,
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
start: { line: lineStart, column: columnStart },
|
||||
end: { line: lineEnd, column: columnEnd },
|
||||
} = this.getLoc(this.ast);
|
||||
|
||||
// If the index is at the start, return the start location of the root node.
|
||||
if (index === 0) {
|
||||
return {
|
||||
line: lineStart,
|
||||
column: columnStart,
|
||||
};
|
||||
}
|
||||
|
||||
// If the index is `this.text.length`, return the location one "spot" past the last character of the file.
|
||||
if (index === this.text.length) {
|
||||
return {
|
||||
line: lineEnd,
|
||||
column: columnEnd,
|
||||
};
|
||||
}
|
||||
|
||||
// Ensure `#lineStartIndices` are lazily calculated.
|
||||
this.#ensureLineStartIndicesFromIndex(index);
|
||||
|
||||
/*
|
||||
* To figure out which line `index` is on, determine the last place at which index could
|
||||
* be inserted into `#lineStartIndices` to keep the list sorted.
|
||||
*/
|
||||
const lineNumber =
|
||||
(index >= (this.#lineStartIndices.at(-1) ?? 0)
|
||||
? this.#lineStartIndices.length
|
||||
: findLineNumberBinarySearch(this.#lineStartIndices, index)) -
|
||||
1 +
|
||||
lineStart;
|
||||
|
||||
return {
|
||||
line: lineNumber,
|
||||
column:
|
||||
index -
|
||||
this.#lineStartIndices[lineNumber - lineStart] +
|
||||
columnStart,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a `{ line: number, column: number }` pair into a source text index.
|
||||
* @param {Object} loc A line/column location.
|
||||
* @param {number} loc.line The line number of the location. (0 or 1-indexed based on language.)
|
||||
* @param {number} loc.column The column number of the location. (0 or 1-indexed based on language.)
|
||||
* @throws {TypeError|RangeError} If `loc` is not an object with a numeric
|
||||
* `line` and `column`, if the `line` is less than or equal to zero or
|
||||
* the `line` or `column` is out of the expected range.
|
||||
* @returns {number} The index of the line/column location in a file.
|
||||
* @public
|
||||
*/
|
||||
getIndexFromLoc(loc) {
|
||||
if (
|
||||
loc === null ||
|
||||
typeof loc !== "object" ||
|
||||
typeof loc.line !== "number" ||
|
||||
typeof loc.column !== "number"
|
||||
) {
|
||||
throw new TypeError(
|
||||
"Expected `loc` to be an object with numeric `line` and `column` properties.",
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
start: { line: lineStart, column: columnStart },
|
||||
end: { line: lineEnd, column: columnEnd },
|
||||
} = this.getLoc(this.ast);
|
||||
|
||||
if (loc.line < lineStart || lineEnd < loc.line) {
|
||||
throw new RangeError(
|
||||
`Line number out of range (line ${loc.line} requested). Valid range: ${lineStart}-${lineEnd}`,
|
||||
);
|
||||
}
|
||||
|
||||
// If the loc is at the start, return the start index of the root node.
|
||||
if (loc.line === lineStart && loc.column === columnStart) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the loc is at the end, return the index one "spot" past the last character of the file.
|
||||
if (loc.line === lineEnd && loc.column === columnEnd) {
|
||||
return this.text.length;
|
||||
}
|
||||
|
||||
// Ensure `#lineStartIndices` are lazily calculated.
|
||||
this.#ensureLineStartIndicesFromLoc(loc, lineStart);
|
||||
|
||||
const isLastLine = loc.line === lineEnd;
|
||||
const lineStartIndex = this.#lineStartIndices[loc.line - lineStart];
|
||||
const lineEndIndex = isLastLine
|
||||
? this.text.length
|
||||
: this.#lineStartIndices[loc.line - lineStart + 1];
|
||||
const positionIndex = lineStartIndex + loc.column - columnStart;
|
||||
|
||||
if (
|
||||
loc.column < columnStart ||
|
||||
(isLastLine && positionIndex > lineEndIndex) ||
|
||||
(!isLastLine && positionIndex >= lineEndIndex)
|
||||
) {
|
||||
throw new RangeError(
|
||||
`Column number out of range (column ${loc.column} requested). Valid range for line ${loc.line}: ${columnStart}-${lineEndIndex - lineStartIndex + columnStart + (isLastLine ? 0 : -1)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return positionIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the range information for the given node or token.
|
||||
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the range information for.
|
||||
* @returns {SourceRange} The range information for the node or token.
|
||||
* @throws {Error} If the node or token does not have range information.
|
||||
*/
|
||||
getRange(nodeOrToken) {
|
||||
if (hasESTreeStyleRange(nodeOrToken)) {
|
||||
return nodeOrToken.range;
|
||||
}
|
||||
|
||||
if (hasPosStyleRange(nodeOrToken)) {
|
||||
return [
|
||||
nodeOrToken.position.start.offset,
|
||||
nodeOrToken.position.end.offset,
|
||||
];
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"Custom getRange() method must be implemented in the subclass.",
|
||||
);
|
||||
}
|
||||
|
||||
/* eslint-disable no-unused-vars -- Required to complete interface. */
|
||||
/**
|
||||
* Returns the parent of the given node.
|
||||
* @param {Options['SyntaxElementWithLoc']} node The node to get the parent of.
|
||||
* @returns {Options['SyntaxElementWithLoc']|undefined} The parent of the node.
|
||||
* @throws {Error} If the method is not implemented in the subclass.
|
||||
*/
|
||||
getParent(node) {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
/* eslint-enable no-unused-vars -- Required to complete interface. */
|
||||
|
||||
/**
|
||||
* Gets all the ancestors of a given node
|
||||
* @param {Options['SyntaxElementWithLoc']} node The node
|
||||
* @returns {Array<Options['SyntaxElementWithLoc']>} All the ancestor nodes in the AST, not including the provided node, starting
|
||||
* from the root node at index 0 and going inwards to the parent node.
|
||||
* @throws {TypeError} When `node` is missing.
|
||||
*/
|
||||
getAncestors(node) {
|
||||
if (!node) {
|
||||
throw new TypeError("Missing required argument: node.");
|
||||
}
|
||||
|
||||
const ancestorsStartingAtParent = [];
|
||||
|
||||
for (
|
||||
let ancestor = this.getParent(node);
|
||||
ancestor;
|
||||
ancestor = this.getParent(ancestor)
|
||||
) {
|
||||
ancestorsStartingAtParent.push(ancestor);
|
||||
}
|
||||
|
||||
return ancestorsStartingAtParent.reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source code for the given node.
|
||||
* @param {Options['SyntaxElementWithLoc']} [node] The AST node to get the text for.
|
||||
* @param {number} [beforeCount] The number of characters before the node to retrieve.
|
||||
* @param {number} [afterCount] The number of characters after the node to retrieve.
|
||||
* @returns {string} The text representing the AST node.
|
||||
* @public
|
||||
*/
|
||||
getText(node, beforeCount, afterCount) {
|
||||
if (node) {
|
||||
const range = this.getRange(node);
|
||||
return this.text.slice(
|
||||
Math.max(range[0] - (beforeCount || 0), 0),
|
||||
range[1] + (afterCount || 0),
|
||||
);
|
||||
}
|
||||
return this.text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entire source text split into an array of lines.
|
||||
* @returns {Array<string>} The source text as an array of lines.
|
||||
* @public
|
||||
*/
|
||||
get lines() {
|
||||
this.#ensureLines(); // Ensure `#lines` is lazily calculated.
|
||||
|
||||
return this.#lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse the source code and return the steps that were taken.
|
||||
* @returns {Iterable<TraversalStep>} The steps that were taken while traversing the source code.
|
||||
*/
|
||||
traverse() {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
export { CallMethodStep, ConfigCommentParser, Directive, TextSourceCodeBase, VisitNodeStep };
|
||||
46
node_modules/@eslint/plugin-kit/dist/esm/types.d.ts
generated
vendored
Normal file
46
node_modules/@eslint/plugin-kit/dist/esm/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @fileoverview Types for the plugin-kit package.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
import type { RuleDefinition, RuleDefinitionTypeOptions, RuleVisitor } from "@eslint/core";
|
||||
/**
|
||||
* Defaults for non-language-related `RuleDefinition` options.
|
||||
*/
|
||||
export interface CustomRuleTypeDefinitions {
|
||||
RuleOptions: unknown[];
|
||||
MessageIds: string;
|
||||
ExtRuleDocs: Record<string, unknown>;
|
||||
}
|
||||
/**
|
||||
* A helper type to define language specific specializations of the `RuleDefinition` type.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* type YourRuleDefinition<
|
||||
* Options extends Partial<CustomRuleTypeDefinitions> = {},
|
||||
* > = CustomRuleDefinitionType<
|
||||
* {
|
||||
* LangOptions: YourLanguageOptions;
|
||||
* Code: YourSourceCode;
|
||||
* Visitor: YourRuleVisitor;
|
||||
* Node: YourNode;
|
||||
* },
|
||||
* Options
|
||||
* >;
|
||||
* ```
|
||||
*/
|
||||
export type CustomRuleDefinitionType<LanguageSpecificOptions extends Omit<RuleDefinitionTypeOptions, keyof CustomRuleTypeDefinitions>, Options extends Partial<CustomRuleTypeDefinitions>> = RuleDefinition<LanguageSpecificOptions & Required<Options & Omit<CustomRuleTypeDefinitions, keyof Options>>>;
|
||||
/**
|
||||
* Adds matching `:exit` selector properties for each key of a `RuleVisitor`.
|
||||
*/
|
||||
export type CustomRuleVisitorWithExit<RuleVisitorType extends RuleVisitor> = {
|
||||
[Key in keyof RuleVisitorType as Key | `${Key & string}:exit`]: RuleVisitorType[Key];
|
||||
};
|
||||
/**
|
||||
* A map of names to string values, or `null` when no value is provided.
|
||||
*/
|
||||
export type StringConfig = Record<string, string | null>;
|
||||
/**
|
||||
* A map of names to boolean flags.
|
||||
*/
|
||||
export type BooleanConfig = Record<string, boolean>;
|
||||
81
node_modules/@eslint/plugin-kit/dist/esm/types.ts
generated
vendored
Normal file
81
node_modules/@eslint/plugin-kit/dist/esm/types.ts
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @fileoverview Types for the plugin-kit package.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Imports
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
import type {
|
||||
RuleDefinition,
|
||||
RuleDefinitionTypeOptions,
|
||||
RuleVisitor,
|
||||
} from "@eslint/core";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Exports
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Defaults for non-language-related `RuleDefinition` options.
|
||||
*/
|
||||
export interface CustomRuleTypeDefinitions {
|
||||
RuleOptions: unknown[];
|
||||
MessageIds: string;
|
||||
ExtRuleDocs: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper type to define language specific specializations of the `RuleDefinition` type.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* type YourRuleDefinition<
|
||||
* Options extends Partial<CustomRuleTypeDefinitions> = {},
|
||||
* > = CustomRuleDefinitionType<
|
||||
* {
|
||||
* LangOptions: YourLanguageOptions;
|
||||
* Code: YourSourceCode;
|
||||
* Visitor: YourRuleVisitor;
|
||||
* Node: YourNode;
|
||||
* },
|
||||
* Options
|
||||
* >;
|
||||
* ```
|
||||
*/
|
||||
export type CustomRuleDefinitionType<
|
||||
LanguageSpecificOptions extends Omit<
|
||||
RuleDefinitionTypeOptions,
|
||||
keyof CustomRuleTypeDefinitions
|
||||
>,
|
||||
Options extends Partial<CustomRuleTypeDefinitions>,
|
||||
> = RuleDefinition<
|
||||
// Language specific type options (non-configurable)
|
||||
LanguageSpecificOptions &
|
||||
Required<
|
||||
// Rule specific type options (custom)
|
||||
Options &
|
||||
// Rule specific type options (defaults)
|
||||
Omit<CustomRuleTypeDefinitions, keyof Options>
|
||||
>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Adds matching `:exit` selector properties for each key of a `RuleVisitor`.
|
||||
*/
|
||||
export type CustomRuleVisitorWithExit<RuleVisitorType extends RuleVisitor> = {
|
||||
[Key in keyof RuleVisitorType as
|
||||
| Key
|
||||
| `${Key & string}:exit`]: RuleVisitorType[Key];
|
||||
};
|
||||
|
||||
/**
|
||||
* A map of names to string values, or `null` when no value is provided.
|
||||
*/
|
||||
export type StringConfig = Record<string, string | null>;
|
||||
|
||||
/**
|
||||
* A map of names to boolean flags.
|
||||
*/
|
||||
export type BooleanConfig = Record<string, boolean>;
|
||||
63
node_modules/@eslint/plugin-kit/package.json
generated
vendored
Normal file
63
node_modules/@eslint/plugin-kit/package.json
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"name": "@eslint/plugin-kit",
|
||||
"version": "0.7.1",
|
||||
"description": "Utilities for building ESLint plugins.",
|
||||
"author": "Nicholas C. Zakas",
|
||||
"type": "module",
|
||||
"main": "dist/esm/index.js",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"exports": {
|
||||
"require": {
|
||||
"types": "./dist/cjs/index.d.cts",
|
||||
"default": "./dist/cjs/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/eslint/rewrite.git",
|
||||
"directory": "packages/plugin-kit"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/eslint/rewrite/issues"
|
||||
},
|
||||
"homepage": "https://github.com/eslint/rewrite/tree/main/packages/plugin-kit#readme",
|
||||
"scripts": {
|
||||
"build:dedupe-types": "node ../../tools/dedupe-types.js dist/cjs/index.cjs dist/esm/index.js",
|
||||
"build:cts": "node ../../tools/build-cts.js dist/esm/index.d.ts dist/cjs/index.d.cts",
|
||||
"build": "rollup -c && npm run build:dedupe-types && tsc -p tsconfig.esm.json && npm run build:cts",
|
||||
"lint:types": "attw --pack",
|
||||
"pretest": "npm run build",
|
||||
"test": "npm run test:types && npm run test:unit",
|
||||
"test:coverage": "npm run build && c8 npm run test:unit",
|
||||
"test:jsr": "npx -y jsr@latest publish --dry-run",
|
||||
"test:types": "tsc -p tests/types/tsconfig.json",
|
||||
"test:unit": "mocha \"tests/**/*.test.js\""
|
||||
},
|
||||
"keywords": [
|
||||
"eslint",
|
||||
"eslintplugin",
|
||||
"eslint-plugin"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/core": "^1.2.1",
|
||||
"levn": "^0.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/levn": "^0.4.0",
|
||||
"rollup-plugin-copy": "^3.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user