diff --git a/.eslint-doc-generatorrc.js b/.eslint-doc-generatorrc.js new file mode 100644 index 00000000..150d3496 --- /dev/null +++ b/.eslint-doc-generatorrc.js @@ -0,0 +1,25 @@ +/* eslint-disable unicorn/prevent-abbreviations */ +/** @type {import('eslint-doc-generator').GenerateOptions} */ +const config = { + // configEmoji: [['recommended', 'βœ…']], + // ignoreConfig: ['all', 'flat/all', 'flat/recommended'], + ignoreDeprecatedRules: true, + // ruleDocNotices: [], + // ruleDocSectionExclude: [], + // ruleDocSectionInclude: [], + ruleDocTitleFormat: "desc", + ruleListColumns: [ + "name", + "description", + "configsError", + "configsWarn", + "fixable", + "hasSuggestions", + "requiresTypeChecking", + ], + // ruleListSplit: [], + // urlConfigs: 'https://github.com/...#preset-configs-eslintconfigjs', +}; + +// eslint-disable-next-line no-undef +module.exports = config; diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 80b1e69d..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: build -on: [push] -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - # waiting on: https://github.com/actions/setup-node/issues/531 - - run: corepack enable - - uses: actions/setup-node@v4 - with: - node-version: 21 - cache: npm - - run: npm ci - - - name: test build package on node@21 (current) - run: | - node --version - npm --version - npm run test - - # Not using a matrix here since it's simpler - # to just duplicate it and not spawn new instances - - - uses: actions/setup-node@v4 - with: - node-version: 20 - - name: test build package on node@20 (LTS) - run: | - node --version - npm --version - npm run test - - - uses: actions/setup-node@v4 - with: - node-version: 18 - - name: test build package on node@18 (LTS) - run: | - node --version - npm --version - npm run test diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 00000000..db74b2df --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,29 @@ +on: + - push + +jobs: + run-tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + name: Install pnpm + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "pnpm" + + - name: Install dependencies + run: pnpm install + + - name: Run the tests + run: | + node --version + pnpm --version + pnpm run lint + pnpm run test diff --git a/.gitignore b/.gitignore index 22d59e5e..c4588cef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# Dependencies node_modules +.pnp +.pnp.js + +# Local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Testing +coverage + +# Turbo +.turbo + +# Vercel +.vercel + +# Build Outputs +.next/ +out/ +build +dist + + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Misc .DS_Store +*.pem .idea +/lib +*.tsbuildinfo diff --git a/.nvmrc b/.nvmrc index 9dfef472..016efd8a 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v18.12.0 +v20.10.0 \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index f82fc396..d8c6e084 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,10 @@ { + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true -} \ No newline at end of file + "editor.formatOnSave": true, + "files.associations": { + "*.css": "tailwindcss" + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9cbf0de0..cdf9975f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,8 +9,7 @@ Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in ## Development -You can use [Corepack](https://nodejs.org/api/corepack.html) to ensure you're using the same package -manager. Run `corepack enabled` before running `npm install`. +Latest version of the plugin uses `pnpm` instead of `npm` as package manager. ## Pull Request Process diff --git a/README.md b/README.md index 74cf5502..f755ad09 100644 --- a/README.md +++ b/README.md @@ -1,300 +1,124 @@ # eslint-plugin-tailwindcss -![npm latest version](https://img.shields.io/npm/v/eslint-plugin-tailwindcss?style=for-the-badge) ![license](https://img.shields.io/npm/l/eslint-plugin-tailwindcss?style=for-the-badge) ![downloads](https://img.shields.io/npm/dt/eslint-plugin-tailwindcss?style=for-the-badge) - ![eslint-plugin-tailwindcss logo](.github/logo.png) -Rules enforcing best practices and consistency using [Tailwind CSS](https://tailwindcss.com/). +Version 4 of the `eslint-plugin-tailwindcss` is: -While you can use the official plugin [`prettier-plugin-tailwindcss`](https://www.npmjs.com/package/prettier-plugin-tailwindcss) for ordering your classnames... +- re-written from scratch +- using TypeScript +- Based as much as possible on internal assets of Tailwind CSS: + - via the [`prettier-plugin-tailwindcss` plugin](https://www.npmjs.com/package/prettier-plugin-tailwindcss) + - via [`tailwind-api-utils`](https://github.com/hyoban/tailwind-api-utils) +- only compatible with: + - Tailwind CSS v4.x.x + - ESLint flat config format -**`eslint-plugin-tailwindcss` offers more than 5 other rules, that you can benefit from on top of `prettier-plugin-tailwindcss`. Sounds good ? Keep reading πŸ‘‡** +## Status -## Supported Rules +This branch was started back in 2024, and I was quickly stuck while trying to use the internal mechanics of the `tailwindcss` package. -Learn more about each supported rules by reading their documentation: +Simple tasks, like loading the CSS config, was impossible inside an ESLint plugin because ESLint plugins are synchronous by design while the tailwindcss package uses plenty of async functions. -- [`classnames-order`](docs/rules/classnames-order.md): order classnames for consistency and it makes merge conflict a bit easier to resolve -- [`enforces-negative-arbitrary-values`](docs/rules/enforces-negative-arbitrary-values.md): make sure to use negative arbitrary values classname without the negative classname e.g. `-top-[5px]` should become `top-[-5px]` -- [`enforces-shorthand`](docs/rules/enforces-shorthand.md): merge multiple classnames into shorthand if possible e.g. `mx-5 my-5` should become `m-5` -- [`migration-from-tailwind-2`](docs/rules/migration-from-tailwind-2.md) for easy upgrade from Tailwind CSS `v2` to `v3`. - Warning: at the moment you should [temporary turn off the `no-custom-classname`](https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/88) rule if you want to see the warning from `migration-from-tailwind-2` -- [`no-arbitrary-value`](docs/rules/no-arbitrary-value.md): forbid using arbitrary values in classnames (turned off by default) -- [`no-custom-classname`](docs/rules/no-custom-classname.md): only allow classnames from Tailwind CSS and the values from the `whitelist` option -- [`no-contradicting-classname`](docs/rules/no-contradicting-classname.md): e.g. avoid `p-2 p-3`, different Tailwind CSS classnames (`pt-2` & `pt-3`) but targeting the same property several times for the same variant. -- [`no-unnecessary-arbitrary-value`](docs/rules/no-unnecessary-arbitrary-value.md): e.g. replacing `m-[1.25rem]` by its configuration based classname `m-5` +πŸ˜‡ Hopefully, [hyoban](https://github.com/hyoban) made [`tailwind-api-utils`](https://github.com/hyoban/tailwind-api-utils) and [demonstrated in a PR](https://github.com/hyoban/eslint-plugin-tailwindcss/pull/3) how I could use it via [`synckit`](https://www.npmjs.com/package/synckit) πŸ‘. -Using ESLint extension for Visual Studio Code, you will get these messages -![detected-errors](.github/output.png) +## Work in progress -You can can the same information on your favorite command line software as well. +This version is far from finished, yet it is available and open for contributions. -## 🀝 Support `eslint-plugin-tailwindcss` +### Completed steps + +- restore the automated tests running on the merge requests of the repo +- implement and test the usage of `tailwind-api-utils` + +### Next steps + +- read the settings from eslint (shared settings & rules settings) +- create the config utility +- implement the `classnames-order` rule and its tests + +## Getting started + +I worked on this repo using `pnpm` but it should work with other package manager. + +### Install + +`pnpm i` + +### Build + +`pnpm build` + +### Test + +`pnpm test` + +or + +`pnpm test:jest` -| πŸ₯° How you can support us? | πŸ’ͺ They did it! | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Premium Sponsors**
Support us by becoming a sponsor.
[Become a recurring sponsor](https://github.com/sponsors/francoismassart?frequency=recurring) | | -| **Current Sponsors**
Any amount is appreciated. | @jonz94 @theMosaad @acewf @charkour @dailydotdev @codecov @sourcegraph | -| **Past sponsors**
Even if this is just a one-time thing.
[Become a backer](https://github.com/sponsors/francoismassart?frequency=one-time) | @aniravi24 @mongolyy @t3dotgg | -| **Contributors**
This project can evolve thanks to all the people who contribute.
You are welcome to [contribute](CONTRIBUTING.md) to this project by reporting issues, feature requests or even opening Pull Requests. | | -| **Supporters**
Talk about the plugin on your social networks | eslint-plugin-tailwindcss on Twitter | - -## Latest changelog - -- fix: [`no-arbitrary-value` rule is too broad](https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/318) -- fix: [support `tag.div` and `tag(Component)`](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/302) (by [nihalgonsalves](https://github.com/nihalgonsalves) πŸ™) -- feat: [**support flat config and ESLint 9**](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/330) (by [kazupon](https://github.com/kazupon) πŸ™) -- feat: new rule [**`no-unnecessary-arbitrary-value`**](docs/rules/no-unnecessary-arbitrary-value.md) πŸŽ‰ -- fix: retro compatibility for older Tailwind CSS (before typescript config) -- fix: [composable touch action classnames](https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/293) -- fix: [`shadow-md` + `shadow-[#color]`can be used together 🀝](https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/298) -- fix: [`tabular-nums` and `slashed-zero` can be used together 🀝](https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/316) -- fix: [`size-*` based `size`, `spacing`, `width` and `height` πŸ€“](https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/315) -- fix: [there is no `size-screen` πŸ˜…](https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/307) -- fix: [edge cases with whitespace in `enforces-shorthand`](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/308)(by [kachkaev](https://github.com/kachkaev) πŸ™) -- fix: [parsing spreads in function call returns](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/285)(by [egorpavlikhin](https://github.com/egorpavlikhin) πŸ™) -- feat: [support for Tailwind CSS 3.4.0](https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/297) -- ci: [add github actions workflow](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/303) (by [nihalgonsalves](https://github.com/nihalgonsalves) πŸ™) -- fix: [bg-center mark as conflicting with bg-[image:xxx]](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/260) -- feat: [support enforcing truncate shorthand](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/255) (by [bezbac](https://github.com/bezbac) πŸ™) -- fix: [parsing spreads in object expressions](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/251) (by [bezbac](https://github.com/bezbac) πŸ™) -- fix: [do not handle non-ASCII whitespace as separator](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/246) (by [uhyo](https://github.com/uhyo) πŸ™) -- fix: [prefix support for named group/peer syntax](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/244) (by [bezbac](https://github.com/bezbac) πŸ™) -- feat: [support tailwind config in typescript](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/242) (by [quesabe](https://github.com/quesabe) πŸ™) - **You may have to upgrade your Tailwind CSS version to `3.3.2`** - -[View all releases on github](https://github.com/francoismassart/eslint-plugin-tailwindcss/releases) - -## Screencasts on our YouTube Channel - -| YouTube Channel | [ESLint plugin Tailwind CSS](https://www.youtube.com/@eslint-plugin-tailwind-css)
youtube.com/@eslint-plugin-tailwindcss | -| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | - -## Installation - -### 1. Install `eslint` and `eslint-plugin-tailwindcss` - -You'll first need to install [ESLint](http://eslint.org): - -``` -$ npm i -D eslint eslint-plugin-tailwindcss - -``` - -### 2. Create Configuration file - -#### `.eslintrc` - -Use .eslintrc.\* file to configure rules in ESLint < v9. See also: https://eslint.org/docs/latest/use/configure/. - -```js -module.exports = { - root: true, - extends: ["plugin:tailwindcss/recommended"], -}; -``` - -If you would like to know about configuration, Learn more in [ESLint docs](https://eslint.org/docs/latest/use/configure/configuration-files) - -#### `eslint.config.js` - -Use `eslint.config.js` file to configure rules. This is the default in ESLint v9, but can be used starting from ESLint v8.57.0. See also: https://eslint.org/docs/latest/use/configure/configuration-files-new. - -```js -import tailwind from "eslint-plugin-tailwindcss"; - -export default [...tailwind.configs["flat/recommended"]]; -``` - -If you would like to know about configuration, Learn more in [ESLint docs](https://eslint.org/docs/latest/use/configure/configuration-files-new) - -### 3. Configure ESLint parsers - -Depending on the languages you are using in your project you must tell which parser will analyze your source files. - -Our recommendations: - -#### For `.eslintrc` - -- For `js[x]`, `react`, `ts[x]`: - - Install the parser: `npm i -D @typescript-eslint/parser` - - Assign it to your files in `eslintrc`: - ```json5 - overrides: [ - { - files: ['*.ts', '*.tsx', '*.js'], - parser: '@typescript-eslint/parser', - }, - ], - ``` -- For `vue.js`: - - Install the parser: `npm i -D vue-eslint-parser` - - Assign it to your files in `eslintrc`: - ```json5 - overrides: [ - { - files: ['*.vue'], - parser: 'vue-eslint-parser', - }, - ], - ``` -- For `HTML` and similar: - - Install the parser: `npm i -D @angular-eslint/template-parser` - - Assign it to your files in `eslintrc`: - ```json5 - overrides: [ - { - files: ['*.html', '*.blade.php'], - parser: '@angular-eslint/template-parser', - }, - ], - ``` - -> We removed the default parsers which were added to `v3.8.2` because it created negative impact on dependencies resolution, bundle size increase and possible conflicts with existing configurations. - -#### For `eslint.config.js` - -- For `js[x]`, `ts[x]`: +#### `jest` or `vitest` - - Install the parser: `npm i -D @eslint/js typescript-eslint` - - Assign it to your files in `eslint.config.js`: +Tests were setup to work with `jest` and `vitest` both comes with pros and cons... - ```js - import js from "@eslint/js"; - import ts from "typescript-eslint"; - import tailwind from "eslint-plugin-tailwindcss"; +I would recommend Vitest but I also added Jest in case you want it. - export default [ - // add eslint built-in - js.configs.recommended, - // add `typescript-eslint` flat config simply - // if you would like use more another configuration, - // see the section: https://typescript-eslint.io/getting-started#details - ...ts.configs.recommended, - ...tailwind.configs["flat/recommended"], - ]; - ``` - -- For `vue.js`: - - - Install the parser: `npm i -D eslint-plugin-vue` - - Assign it to your files in `eslint.config.js`: - - ```js - import vue from "eslint-plugin-vue"; - import tailwind from "eslint-plugin-tailwindcss"; - - export default [ - // add `eslint-plugin-vue` flat config simply - // if you would like use more another configuration, - // see the section: https://eslint.vuejs.org/user-guide/#bundle-configurations-eslint-config-js - ...vue.configs["flat/recommended"], - ...tailwind.configs["flat/recommended"], - ]; - ``` - -### 4. Add a npm script - -In your `package.json` add one or more script(s) to run eslint targeting your source files: - -```json5 -"scripts": { - "lint": "eslint ./src", - "lint:debug": "eslint ./src --debug", - "lint:fix": "eslint ./src --fix" -}, -``` - -### 5. Run the linting task - -`npm run lint` can do the job on demand but you can also get live feedback using [VS Code ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint), **just make sure you restart VS Code** as it can be required for the plugin to work as expected. - -## More settings - -The rules accept settings meant to fit your own choices, make sure to read the [documentation of each rule](https://github.com/francoismassart/eslint-plugin-tailwindcss/tree/master/docs/rules). - -### Optional shared settings - -Most rules share the same settings, instead of duplicating the options all over the place... - -You should define the [shared settings](https://eslint.org/docs/user-guide/configuring#adding-shared-settings) that will be shared across all the plugin rules. - -All these settings already have nice default values that are explained in the documentation. - -#### For `.eslintrc` - -FYI, here are the `default` values: - -```json5 -{ - settings: { - tailwindcss: { - // These are the default values but feel free to customize - callees: ["classnames", "clsx", "ctl"], - config: "tailwind.config.js", // returned from `loadConfig()` utility if not provided - cssFiles: [ - "**/*.css", - "!**/node_modules", - "!**/.*", - "!**/dist", - "!**/build", - ], - cssFilesRefreshRate: 5_000, - removeDuplicates: true, - skipClassAttribute: false, - whitelist: [], - tags: [], // can be set to e.g. ['tw'] for use in tw`bg-blue` - classRegex: "^class(Name)?$", // can be modified to support custom attributes. E.g. "^tw$" for `twin.macro` - }, - }, -} -``` +| Jest | Vitest | +| :----------------------- | :--------------------------------------------- | +| Based on `commonjs` | Based on `ESM` | +| βœ… Mocking | βœ… Mocking | +| βœ… Snapshots | βœ… Snapshots | +| βœ… Parallel testing | βœ… Parallel testing | +| βœ… Fast | βœ… Often faster | +| - | βœ… Support benches | +| ❌ Require `ts-jest` lib | ❌ Requires `setupFile` and `vitest.config.ts` | -#### For `eslint.config.js` +NB: In order to use, the [`RuleTester`](https://typescript-eslint.io/packages/rule-tester) from `@typescript-eslint/rule-tester`, we must: -```js -import tailwind from "eslint-plugin-tailwindcss"; - -export default [ - ...tailwind.configs["flat/recommended"], +- Have a `tsconfig.json` with: + ``` { - settings: { - tailwindcss: { - // These are the default values but feel free to customize - callees: ["classnames", "clsx", "ctl"], - config: "tailwind.config.js", // returned from `loadConfig()` utility if not provided - cssFiles: [ - "**/*.css", - "!**/node_modules", - "!**/.*", - "!**/dist", - "!**/build", - ], - cssFilesRefreshRate: 5_000, - removeDuplicates: true, - skipClassAttribute: false, - whitelist: [], - tags: [], // can be set to e.g. ['tw'] for use in tw`bg-blue` - classRegex: "^class(Name)?$", // can be modified to support custom attributes. E.g. "^tw$" for `twin.macro` - }, - }, - }, -]; -``` - -The plugin will look for each setting in this order and stops searching as soon as it finds the settings: - -1. In the rule option argument (rule level) -2. In the shared settings (plugin level) -3. Default value of the requested setting (plugin level)... - -## Upcoming Rules - -- `validate-modifiers`: I don't know if possible, but I'd like to make sure all the modifiers prefixes of a classname are valid e.g. `yolo:bg-red` should throw an error... - -- `no-redundant-variant`: e.g. avoid `mx-5 sm:mx-5`, no need to redefine `mx` in `sm:` variant as it uses the same value (`5`) - -- `only-valid-arbitrary-values`: - - - e.g. avoid `top-[42]`, only `0` value can be unitless. - - e.g. avoid `text-[rgba(10%,20%,30,50%)]`, can't mix `%` and `0-255`. + "compilerOptions": { + "module": "nodenext", + "moduleResolution": "nodenext" + } + } + ``` + More info can be found on [`v6`: Cannot find module `@typescript-eslint/*` or its corresponding type declarations](https://github.com/typescript-eslint/typescript-eslint/issues/7284). + > You can use `bundler`, `node16`, or `nodenext` for `moduleResolution`. +- Use `eslint` with `v8`, [`typescript-eslint` does not support `v9` yet](https://github.com/typescript-eslint/typescript-eslint/issues/8211) + +### Docs + +`pnpm docs:init` will create new files for each rule if necessary. + +`pnpm docs:update` will update existing files and the rules list. + +You can see an example of generated documentation in the next section. + +### Rules + + + +πŸ’‘ Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). + +| Name | Description | πŸ’‘ | +| :------------------------------- | :--------------------- | :- | +| [my-rule](docs/rules/my-rule.md) | An example ESLint rule | πŸ’‘ | + + + +## Additional resources + +See [`eslint-plugin-example-typed-linting`](https://github.com/typescript-eslint/examples/tree/main/packages/eslint-plugin-example-typed-linting) for an example plugin that supports typed linting. + +Another example of eslint-plugin using `typescript-eslint` is [`eslint-plugin-vitest`](https://github.com/vitest-dev/eslint-plugin-vitest)... + +## 🀝 Support `eslint-plugin-tailwindcss` + +| πŸ₯° How you can support us? | πŸ’ͺ They did it! | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Premium Sponsors**
Support us by becoming a sponsor.
[Become a recurring sponsor](https://github.com/sponsors/francoismassart?frequency=recurring) | daily.dev Sent.dm | +| **Current Sponsors**
Any amount is appreciated. | @kylemh @theMosaad @acewf @dailydotdev @codecov @sourcegraph @getsentry | +| **Past sponsors**
Even if this is just a one-time thing.
[Become a backer](https://github.com/sponsors/francoismassart?frequency=one-time) | @hyoban @charkour @aniravi24 @amotarao @mongolyy @t3dotgg @fongandrew @nivalis-studio @jonz94 | +| **Contributors**
This project can evolve thanks to all the people who contribute.
You are welcome to [contribute](CONTRIBUTING.md) to this project by reporting issues, feature requests or even opening Pull Requests. | | +| **Supporters**
Talk about the plugin on your social networks | [Share the word on Bluesky](https://bsky.app/search?q=eslint-plugin-tailwindcss) or [Reach my profile](https://bsky.app/profile/francoismassart.be) | diff --git a/docs/rules/README.md b/docs/rules/README.md new file mode 100644 index 00000000..9df70a32 --- /dev/null +++ b/docs/rules/README.md @@ -0,0 +1,11 @@ +# Be careful when you edit the docs + +## Each rule's documentation is partially generated + +Running `pnpm docs:init` will create new files if needed. + +Running `pnpm docs:update` will update the existing docs. + +## Generated sections + +The generated sections are surrounded by HTML comments mentioning "auto-generated". diff --git a/docs/rules/classnames-order.md b/docs/rules/classnames-order.md deleted file mode 100644 index 5fb6f922..00000000 --- a/docs/rules/classnames-order.md +++ /dev/null @@ -1,77 +0,0 @@ -# Use a consistent orders for the Tailwind CSS classnames, based on the official order (tailwindcss/classnames-order) - -Enforces a consistent order of the Tailwind CSS classnames and its variants. - -> **Note**: Since version `3.6.0`, the ordering is solely done using the [order process from the official `prettier-plugin-tailwindcss`](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) - -## Rule Details - -Examples of **incorrect** code for this rule: - -```html -
-``` - -Examples of **correct** code for this rule: - -```html -
-``` - -### Options - -```js -... -"tailwindcss/classnames-order": [, { - "callees": Array, - "config": |, - "removeDuplicates": , - "skipClassAttribute": , - "tags": Array, -}] -... -``` - -### `callees` (default: `["classnames", "clsx", "ctl", "cva", "tv"]`) - -If you use some utility library like [@netlify/classnames-template-literals](https://github.com/netlify/classnames-template-literals), you can add its name to the list to make sure it gets parsed by this rule. - -For best results, gather the declarative classnames together, avoid mixing conditional classnames in between, move them at the end. - -### `ignoredKeys` (default: `["compoundVariants", "defaultVariants"]`) - -Using libraries like `cva`, some of its object keys are not meant to contain classnames in its value(s). -You can specify which key(s) won't be parsed by the plugin using this setting. -For example, `cva` has `compoundVariants` and `defaultVariants`. -NB: As `compoundVariants` can have classnames inside its `class` property, you can also use a callee to make sure this inner part gets parsed while its parent is ignored. - -### `config` (default: generated by `tailwindcss/lib/lib/load-config`) - -By default the plugin will try to load the file returned by the official `loadConfig()` utility. - -This allows the plugin to use your customized `colors`, `spacing`, `screens`... - -You can provide another path or filename for your Tailwind CSS config file like `"config/tailwind.js"`. - -If the external file cannot be loaded (e.g. incorrect path or deleted file), an empty object `{}` will be used instead. - -It is also possible to directly inject a configuration as plain `object` like `{ prefix: "tw-", theme: { ... } }`. - -Finally, the plugin will [merge the provided configuration](https://tailwindcss.com/docs/configuration#referencing-in-java-script) with [Tailwind CSS's default configuration](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js). - -### `removeDuplicates` (default: `true`) - -Duplicate classnames are automatically removed but you can always disable this behavior by setting `removeDuplicates` to `false`. - -### `skipClassAttribute` (default: `false`) - -Set `skipClassAttribute` to `true` if you only want to lint the classnames inside one of the `callees`. -While, this will avoid linting the `class` and `className` attributes, it will still lint matching `callees` inside of these attributes. - -### `tags` (default: `[]`) - -Optional, if you are using tagged templates, you should provide the tags in this array. - -### `classRegex` (default: `"^class(Name)?$"`) - -Optional, can be used to support custom attributes diff --git a/docs/rules/enforces-negative-arbitrary-values.md b/docs/rules/enforces-negative-arbitrary-values.md deleted file mode 100644 index 48f4632e..00000000 --- a/docs/rules/enforces-negative-arbitrary-values.md +++ /dev/null @@ -1,91 +0,0 @@ -# Warns about `-` prefixed classnames using arbitrary values (enforces-negative-arbitrary-values) - -There are 2 ways to declare **negative arbitrary values**: - -a) Dash prefixed classname with absolute arbitrary value like `-top-[1px]` ❌ - -b) Unprefixed classname (no dash) with negative value inside the square brackets like `top-[-1px]` βœ… - -I believe, **we should always prefer the (b) approach "Unprefixed classname"** for few reasons: - -- In Tailwind CSS **v2.x.x** the (a) **was not supported** (example: https://play.tailwindcss.com/fsS91hkyKx) -- You can get nasty using (a) like `-top-[-1px]` πŸ₯΄ -- Using `var()` you simply don't know if you are dealing with a negative or positive value -- [Adam recommends the unprefixed approach πŸŽ‰](https://twitter.com/adamwathan/status/1487895306847105038) - -## Rule Details - -Examples of **incorrect** code for this rule: - -```html -
- Negative arbitrary values -
-``` - -`-right-[var(--my-var)*-1]` will generate this non sense: `right: calc(var(--my-var) * -1 * -1);` - -Examples of **correct** code for this rule: - -```html -
- Negative arbitrary values -
-``` - -### Options - -```js -... -"tailwindcss/enforces-negative-arbitrary-values": [, { - "callees": Array, - "config": |, - "skipClassAttribute": , - "tags": Array, -}] -... -``` - -### `callees` (default: `["classnames", "clsx", "ctl", "cva", "tv"]`) - -If you use some utility library like [@netlify/classnames-template-literals](https://github.com/netlify/classnames-template-literals), you can add its name to the list to make sure it gets parsed by this rule. - -For best results, gather the declarative classnames together, avoid mixing conditional classnames in between, move them at the end. - -### `ignoredKeys` (default: `["compoundVariants", "defaultVariants"]`) - -Using libraries like `cva`, some of its object keys are not meant to contain classnames in its value(s). -You can specify which key(s) won't be parsed by the plugin using this setting. -For example, `cva` has `compoundVariants` and `defaultVariants`. -NB: As `compoundVariants` can have classnames inside its `class` property, you can also use a callee to make sure this inner part gets parsed while its parent is ignored. - -### `config` (default: generated by `tailwindcss/lib/lib/load-config`) - -By default the plugin will try to load the file returned by the official `loadConfig()` utility. - -This allows the plugin to use your customized `colors`, `spacing`, `screens`... - -You can provide another path or filename for your Tailwind CSS config file like `"config/tailwind.js"`. - -If the external file cannot be loaded (e.g. incorrect path or deleted file), an empty object `{}` will be used instead. - -It is also possible to directly inject a configuration as plain `object` like `{ prefix: "tw-", theme: { ... } }`. - -Finally, the plugin will [merge the provided configuration](https://tailwindcss.com/docs/configuration#referencing-in-java-script) with [Tailwind CSS's default configuration](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js). - -### `skipClassAttribute` (default: `false`) - -Set `skipClassAttribute` to `true` if you only want to lint the classnames inside one of the `callees`. -While, this will avoid linting the `class` and `className` attributes, it will still lint matching `callees` inside of these attributes. - -### `tags` (default: `[]`) - -Optional, if you are using tagged templates, you should provide the tags in this array. - -### `classRegex` (default: `"^class(Name)?$"`) - -Optional, can be used to support custom attributes diff --git a/docs/rules/enforces-shorthand.md b/docs/rules/enforces-shorthand.md deleted file mode 100644 index 6b694fbe..00000000 --- a/docs/rules/enforces-shorthand.md +++ /dev/null @@ -1,87 +0,0 @@ -# Replaces multiple Tailwind CSS classnames by their shorthand (enforces-shorthand) - -This rule will help you reduce the number of [Tailwind CSS](https://tailwindcss.com/) classnames by using shorthands. - -## Rule Details - -Examples of **incorrect** code for this rule: - -```html -
border shorthand
-``` - -Examples of **correct** code for this rule: - -```html -
border shorthand
-``` - -#### Limitations - -At the moment, the rule will not merge mixed classnames (e.g. using regular values AND arbitrary values). - -```html -
- won't be converted to border-0 shorthand -
-``` - -Also, unless you are using the `classnames-order` rule, the order of your classnames may be affected by the fix. -If indeed, you are using the `classnames-order` rule, then it'll be automatically re-ordered during the next lint process (depending on your autofix preferences) and you won't notice any order issue. - -### Options - -```js -... -"tailwindcss/enforces-shorthand": [, { - "callees": Array, - "config": |, - "skipClassAttribute": , - "tags": Array, -}] -... -``` - -### `callees` (default: `["classnames", "clsx", "ctl", "cva", "tv"]`) - -If you use some utility library like [@netlify/classnames-template-literals](https://github.com/netlify/classnames-template-literals), you can add its name to the list to make sure it gets parsed by this rule. - -For best results, gather the declarative classnames together, avoid mixing conditional classnames in between, move them at the end. - -### `ignoredKeys` (default: `["compoundVariants", "defaultVariants"]`) - -Using libraries like `cva`, some of its object keys are not meant to contain classnames in its value(s). -You can specify which key(s) won't be parsed by the plugin using this setting. -For example, `cva` has `compoundVariants` and `defaultVariants`. -NB: As `compoundVariants` can have classnames inside its `class` property, you can also use a callee to make sure this inner part gets parsed while its parent is ignored. - -### `config` (default: generated by `tailwindcss/lib/lib/load-config`) - -By default the plugin will try to load the file returned by the official `loadConfig()` utility. - -This allows the plugin to use your customized `colors`, `spacing`, `screens`... - -You can provide another path or filename for your Tailwind CSS config file like `"config/tailwind.js"`. - -If the external file cannot be loaded (e.g. incorrect path or deleted file), an empty object `{}` will be used instead. - -It is also possible to directly inject a configuration as plain `object` like `{ prefix: "tw-", theme: { ... } }`. - -Finally, the plugin will [merge the provided configuration](https://tailwindcss.com/docs/configuration#referencing-in-java-script) with [Tailwind CSS's default configuration](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js). - -### `skipClassAttribute` (default: `false`) - -Set `skipClassAttribute` to `true` if you only want to lint the classnames inside one of the `callees`. -While, this will avoid linting the `class` and `className` attributes, it will still lint matching `callees` inside of these attributes. - -### `tags` (default: `[]`) - -Optional, if you are using tagged templates, you should provide the tags in this array. - -### `classRegex` (default: `"^class(Name)?$"`) - -Optional, can be used to support custom attributes - -## Further Reading - -This rule will fix the issue for you. diff --git a/docs/rules/migration-from-tailwind-2.md b/docs/rules/migration-from-tailwind-2.md deleted file mode 100644 index c84cb64e..00000000 --- a/docs/rules/migration-from-tailwind-2.md +++ /dev/null @@ -1,128 +0,0 @@ -# Detect obsolete classnames when upgrading to Tailwind CSS v3 (migration-from-tailwind-2) - -This rule helps you upgrade your codebase from [Tailwind CSS](https://tailwindcss.com/) v2 to v3, you can read more about [upgrading your Tailwind CSS projects from v2 to v3](https://tailwindcss.com/docs/upgrade-guide). - -## Rule Details - -### Obsolete classnames - -Examples of **incorrect** code for this rule: - -```html -
- Automatic transforms and filters -
-``` - -Examples of **correct** code for this rule: - -```html -
- Automatic transforms and filters -
-``` - -The classnames `backdrop-filter`, `filter` & `transform` are [not needed when you are using Tailwind CSS v3](https://tailwindcss.com/docs/upgrade-guide#automatic-transforms-and-filters) because it is always running in JIT mode. - -The rule can fix your code by removing these obsolete classnames. - -### Renamed classnames - -Examples of **incorrect** code for this rule: - -```html -
overflow-clip/ellipsis
-``` - -Examples of **correct** code for this rule: - -```html -
overflow-clip/ellipsis
-``` - -The classnames `overflow-clip` & `overflow-ellipsis` [were renamed in v3](https://tailwindcss.com/docs/upgrade-guide#overflow-clip-ellipsis) to avoid confusion with new CSS properties. As said in the official docs: - -> The old class names will always work but you’re encouraged to update to the new ones. - -This rule can replace the old classnames by the updated classnames, it will work on the following classnames: - -- `overflow-clip` => `text-clip` -- `overflow-ellipsis` => `text-ellipsis` -- `flex-grow` => `grow` -- `flex-shrink` => `shrink` -- `decoration-clone` => `box-decoration-clone` -- `decoration-slice` => `box-decoration-slice` -- `placeholder-color` => `placeholder:text-color` - -### Removed `bg-opacity` - -Examples of **incorrect** code for this rule: - -```html -
bg-opacity
-``` - -Examples of **correct** code for this rule: - -```html -
bg-opacity
-``` - -While still being supported, the `bg-opacity` utility classname was removed from the docs because you should use a suffix modifier on a `bg-color` to provide an alpha value instead. - -This rule will report the issue but **it will not fix it for you**... - -### Options - -```js -... -"tailwindcss/migration-from-tailwind-2": [, { - "callees": Array, - "config": |, - "skipClassAttribute": , - "tags": Array, -}] -... -``` - -### `callees` (default: `["classnames", "clsx", "ctl", "cva", "tv"]`) - -If you use some utility library like [@netlify/classnames-template-literals](https://github.com/netlify/classnames-template-literals), you can add its name to the list to make sure it gets parsed by this rule. - -For best results, gather the declarative classnames together, avoid mixing conditional classnames in between, move them at the end. - -### `ignoredKeys` (default: `["compoundVariants", "defaultVariants"]`) - -Using libraries like `cva`, some of its object keys are not meant to contain classnames in its value(s). -You can specify which key(s) won't be parsed by the plugin using this setting. -For example, `cva` has `compoundVariants` and `defaultVariants`. -NB: As `compoundVariants` can have classnames inside its `class` property, you can also use a callee to make sure this inner part gets parsed while its parent is ignored. - -### `config` (default: generated by `tailwindcss/lib/lib/load-config`) - -By default the plugin will try to load the file returned by the official `loadConfig()` utility. - -This allows the plugin to use your customized `colors`, `spacing`, `screens`... - -You can provide another path or filename for your Tailwind CSS config file like `"config/tailwind.js"`. - -If the external file cannot be loaded (e.g. incorrect path or deleted file), an empty object `{}` will be used instead. - -It is also possible to directly inject a configuration as plain `object` like `{ prefix: "tw-", theme: { ... } }`. - -Finally, the plugin will [merge the provided configuration](https://tailwindcss.com/docs/configuration#referencing-in-java-script) with [Tailwind CSS's default configuration](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js). - -### `skipClassAttribute` (default: `false`) - -Set `skipClassAttribute` to `true` if you only want to lint the classnames inside one of the `callees`. -While, this will avoid linting the `class` and `className` attributes, it will still lint matching `callees` inside of these attributes. - -### `tags` (default: `[]`) - -Optional, if you are using tagged templates, you should provide the tags in this array. - -### `classRegex` (default: `"^class(Name)?$"`) - -Optional, can be used to support custom attributes diff --git a/docs/rules/my-rule.md b/docs/rules/my-rule.md new file mode 100644 index 00000000..1aec9f3c --- /dev/null +++ b/docs/rules/my-rule.md @@ -0,0 +1,29 @@ +# An example ESLint rule + +πŸ’‘ This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). + + + +## Rule details + +Description of the rule would normally go here. + +## Examples + +Examples would normally go here. + +## Options + + + +| Name | Description | Type | Choices | Default | +| :------------------- | :------------------------------------------------------------------- | :------- | :---------------- | :--------------------- | +| `callees` | List of function names to validate classnames | String[] | | [`ctl`] | +| `cssConfigPath` | Path to the Tailwind CSS configuration file (*.css) | String | | `default-path/app.css` | +| `removeDuplicates` | Remove duplicated classnames | Boolean | | `true` | +| `skipClassAttribute` | If you only want to lint the classnames inside one of the `callees`. | Boolean | | `false` | +| `someBool` | someBool description. | Boolean | | `false` | +| `someEnum` | someEnum description. | String | `always`, `never` | `always` | +| `tags` | List of tags to be detected in template literals | String[] | | [`tw`] | + + diff --git a/docs/rules/no-arbitrary-value.md b/docs/rules/no-arbitrary-value.md deleted file mode 100644 index 84f1e861..00000000 --- a/docs/rules/no-arbitrary-value.md +++ /dev/null @@ -1,77 +0,0 @@ -# Forbid using arbitrary values in classnames (no-arbitrary-value) - -Tailwind CSS 3 is Just In Time, all the time. It brings flexibility, great compilation perfs and arbitrary values. -Arbitrary values are great but can be problematic too if you wish to restrict developer to stick with the values defined in the Tailwind CSS config file. - -**By default this rule is turned `off`, if you want to use it set it to `warn` or `error`.** - -## Rule Details - -Examples of **incorrect** code for this rule: - -```html -
border width
-``` - -Examples of **correct** code for this rule: - -```html -
border width
-``` - -### Options - -```js -... -"tailwindcss/no-arbitrary-value": [, { - "callees": Array, - "config": |, - "skipClassAttribute": , - "tags": Array, -}] -... -``` - -### `callees` (default: `["classnames", "clsx", "ctl", "cva", "tv"]`) - -If you use some utility library like [@netlify/classnames-template-literals](https://github.com/netlify/classnames-template-literals), you can add its name to the list to make sure it gets parsed by this rule. - -For best results, gather the declarative classnames together, avoid mixing conditional classnames in between, move them at the end. - -### `ignoredKeys` (default: `["compoundVariants", "defaultVariants"]`) - -Using libraries like `cva`, some of its object keys are not meant to contain classnames in its value(s). -You can specify which key(s) won't be parsed by the plugin using this setting. -For example, `cva` has `compoundVariants` and `defaultVariants`. -NB: As `compoundVariants` can have classnames inside its `class` property, you can also use a callee to make sure this inner part gets parsed while its parent is ignored. - -### `config` (default: generated by `tailwindcss/lib/lib/load-config`) - -By default the plugin will try to load the file returned by the official `loadConfig()` utility. - -This allows the plugin to use your customized `colors`, `spacing`, `screens`... - -You can provide another path or filename for your Tailwind CSS config file like `"config/tailwind.js"`. - -If the external file cannot be loaded (e.g. incorrect path or deleted file), an empty object `{}` will be used instead. - -It is also possible to directly inject a configuration as plain `object` like `{ prefix: "tw-", theme: { ... } }`. - -Finally, the plugin will [merge the provided configuration](https://tailwindcss.com/docs/configuration#referencing-in-java-script) with [Tailwind CSS's default configuration](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js). - -### `skipClassAttribute` (default: `false`) - -Set `skipClassAttribute` to `true` if you only want to lint the classnames inside one of the `callees`. -While, this will avoid linting the `class` and `className` attributes, it will still lint matching `callees` inside of these attributes. - -### `tags` (default: `[]`) - -Optional, if you are using tagged templates, you should provide the tags in this array. - -### `classRegex` (default: `"^class(Name)?$"`) - -Optional, can be used to support custom attributes - -## Further Reading - -This rule will not fix the issue for you because it cannot guess the correct class candidate. diff --git a/docs/rules/no-contradicting-classname.md b/docs/rules/no-contradicting-classname.md deleted file mode 100644 index b96ad32d..00000000 --- a/docs/rules/no-contradicting-classname.md +++ /dev/null @@ -1,77 +0,0 @@ -# Avoid contradicting Tailwind CSS classnames (e.g. "w-3 w-5") (no-contradicting-classname) - -The majority of the Tailwind CSS classes only affect a single CSS property. -Using two or more classnames which affect the same property for the same variant means trouble and confusion. - -## Rule Details - -The rule aims to warn you about contradictions in the classnames you are attaching to an element. - -Examples of **incorrect** code for this rule: - -```html -
which is the correct width ?
-``` - -Examples of **correct** code for this rule: - -```html -
padding is defined once per variant max.
-``` - -### Options - -```js -... -"tailwindcss/no-contradicting-classname": [, { - "callees": Array, - "config": |, - "skipClassAttribute": , - "tags": Array, -}] -... -``` - -### `callees` (default: `["classnames", "clsx", "ctl", "cva", "tv"]`) - -If you use some utility library like [@netlify/classnames-template-literals](https://github.com/netlify/classnames-template-literals), you can add its name to the list to make sure it gets parsed by this rule. - -For best results, gather the declarative classnames together, avoid mixing conditional classnames in between, move them at the end. - -### `ignoredKeys` (default: `["compoundVariants", "defaultVariants"]`) - -Using libraries like `cva`, some of its object keys are not meant to contain classnames in its value(s). -You can specify which key(s) won't be parsed by the plugin using this setting. -For example, `cva` has `compoundVariants` and `defaultVariants`. -NB: As `compoundVariants` can have classnames inside its `class` property, you can also use a callee to make sure this inner part gets parsed while its parent is ignored. - -### `config` (default: generated by `tailwindcss/lib/lib/load-config`) - -By default the plugin will try to load the file returned by the official `loadConfig()` utility. - -This allows the plugin to use your customized `colors`, `spacing`, `screens`... - -You can provide another path or filename for your Tailwind CSS config file like `"config/tailwind.js"`. - -If the external file cannot be loaded (e.g. incorrect path or deleted file), an empty object `{}` will be used instead. - -It is also possible to directly inject a configuration as plain `object` like `{ prefix: "tw-", theme: { ... } }`. - -Finally, the plugin will [merge the provided configuration](https://tailwindcss.com/docs/configuration#referencing-in-java-script) with [Tailwind CSS's default configuration](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js). - -### `skipClassAttribute` (default: `false`) - -Set `skipClassAttribute` to `true` if you only want to lint the classnames inside one of the `callees`. -While, this will avoid linting the `class` and `className` attributes, it will still lint matching `callees` inside of these attributes. - -### `tags` (default: `[]`) - -Optional, if you are using tagged templates, you should provide the tags in this array. - -### `classRegex` (default: `"^class(Name)?$"`) - -Optional, can be used to support custom attributes - -## Further Reading - -This rule will not fix the issue but will let you know about the issue. diff --git a/docs/rules/no-custom-classname.md b/docs/rules/no-custom-classname.md deleted file mode 100644 index ef634322..00000000 --- a/docs/rules/no-custom-classname.md +++ /dev/null @@ -1,118 +0,0 @@ -# Detect classnames which do not belong to Tailwind CSS (no-custom-classname) - -Enable this rule if you do not want to accept using classnames that are not defined in [Tailwind CSS](https://tailwindcss.com/). - -## Rule Details - -Examples of **incorrect** code for this rule: - -```html -
my-custom is not defined in Tailwind CSS!
-``` - -Examples of **correct** code for this rule: - -```html -
- Only Tailwind CSS classnames -
-``` - -### Options - -```js -... -"tailwindcss/no-custom-classname": [, { - "callees": Array, - "config": |, - "cssFiles": Array, - "cssFilesRefreshRate": , - "skipClassAttribute": , - "tags": Array, - "whitelist": Array, -}] -... -``` - -### `callees` (default: `["classnames", "clsx", "ctl", "cva", "tv"]`) - -If you use some utility library like [@netlify/classnames-template-literals](https://github.com/netlify/classnames-template-literals), you can add its name to the list to make sure it gets parsed by this rule. - -For best results, gather the declarative classnames together, avoid mixing conditional classnames in between, move them at the end. - -### `ignoredKeys` (default: `["compoundVariants", "defaultVariants"]`) - -Using libraries like `cva`, some of its object keys are not meant to contain classnames in its value(s). -You can specify which key(s) won't be parsed by the plugin using this setting. -For example, `cva` has `compoundVariants` and `defaultVariants`. -NB: As `compoundVariants` can have classnames inside its `class` property, you can also use a callee to make sure this inner part gets parsed while its parent is ignored. - -### `config` (default: generated by `tailwindcss/lib/lib/load-config`) - -By default the plugin will try to load the file returned by the official `loadConfig()` utility. - -This allows the plugin to use your customized `colors`, `spacing`, `screens`... - -You can provide another path or filename for your Tailwind CSS config file like `"config/tailwind.js"`. - -If the external file cannot be loaded (e.g. incorrect path or deleted file), an empty object `{}` will be used instead. - -It is also possible to directly inject a configuration as plain `object` like `{ prefix: "tw-", theme: { ... } }`. - -Finally, the plugin will [merge the provided configuration](https://tailwindcss.com/docs/configuration#referencing-in-java-script) with [Tailwind CSS's default configuration](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js). - -### `cssFiles` (default: `["**/*.css", "!**/node_modules", "!**/.*", "!**/dist", "!**/build"]`) - -By default the plugin will now look for any `css` files while ignoring files in special folders (`node_modules/`, `dist/`, `build/` folders as well as hidden folders prefixed by a dot e.g. `.git/`). - -Each `css` files will be processed in order to extract the declared classnames in order to accept them. - -> If you are experiencing performance issues with this plugin, make sure to provide this setting and restrict its value to only parse the correct subset of CSS files. Read more about such cases in [PR#92](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/92) and [PR#93](https://github.com/francoismassart/eslint-plugin-tailwindcss/pull/93). - -### `cssFilesRefreshRate` (default: `5_000`) - -The plugin read and parses CSS files which can be a time consuming process depending on your files. - -By default, it runs the process if files were updated for at least 5 seconds (`5_000` ms) but you can increase this setting to enhance performances while reducing the update interval. - -### `skipClassAttribute` (default: `false`) - -Set `skipClassAttribute` to `true` if you only want to lint the classnames inside one of the `callees`. -While, this will avoid linting the `class` and `className` attributes, it will still lint matching `callees` inside of these attributes. - -### `tags` (default: `[]`) - -Optional, if you are using tagged templates, you should provide the tags in this array. - -### `whitelist` (default: `[]`) - -The `whitelist` is empty by default but you can add custom regular expressions to this array to avoid getting warnings or errors while using your custom classes. - -For example, imagine we are using the following custom classnames: `skin-summer`, `skin-xmas`, `custom-1`, `custom-2`, `custom-3`. - -The `whitelist` options should be set to: - -- `['skin\\-(summer|xmas)', 'custom\\-[1-3]']` -- or if you don't like regular expressions (but you should): - `['skin\\-summer', 'skin\\-xmas', 'custom\\-1', 'custom\\-2', 'custom\\-3']` - -### Using negative lookahead expression - -If you want to **allow the usage of custom classname while checking the existence of specific Tailwind CSS classnames**, you can use negative lookahead expression in the whitelisted regex. - -e.g. I want to allow custom classnames while checking the validity of the `text-` and `bg-` classnames: - -```js -[ - // white list any classname which does NOT start with `bg-` and `text-` - "(?!(bg|text)\\-).*", -]; -``` - -### `classRegex` (default: `"^class(Name)?$"`) - -Optional, can be used to support custom attributes - -## Further Reading - -This rule will not fix the issue but will let you know about the issue. diff --git a/docs/rules/no-unnecessary-arbitrary-value.md b/docs/rules/no-unnecessary-arbitrary-value.md deleted file mode 100644 index 953a3a13..00000000 --- a/docs/rules/no-unnecessary-arbitrary-value.md +++ /dev/null @@ -1,110 +0,0 @@ -# Avoid unjustified arbitrary classnames (no-unnecessary-arbitrary-value) - -Arbitrary values are handy but you should stick to regular classnames defined in the Tailwind CSS config file as much as you can. - -## Rule Details - -Given the default configuration in which `h-auto` exists... There is no need to use an arbitrary classname. - -Examples of **incorrect** code for this rule: - -```html -
height
-``` - -Examples of **correct** code for this rule: - -```html -
height
-``` - -### The rule can handle `0` values with or without their units - -Given the default configuration in which `h-0` exists... There is no need to use an arbitrary classname. - -Examples of **incorrect** code with `0` based value: - -```html -
Use `h-0` (`0px`) instead
-``` - -Examples of **correct** code with `0` based value: - -```html - -``` - -### The rule can handle negative & double negative - -Given the default configuration... There is no need to use an arbitrary classname. - -Examples of **incorrect** code for negative arbitrary values: - -```html -
[Double] negative values
-``` - -Examples of **correct** code for negative arbitrary values: - -```html -
[Double] negative values
-``` - -### Options - -```js -... -"tailwindcss/no-unnecessary-arbitrary-value": [, { - "callees": Array, - "config": |, - "skipClassAttribute": , - "tags": Array, -}] -... -``` - -### `callees` (default: `["classnames", "clsx", "ctl", "cva", "tv"]`) - -If you use some utility library like [@netlify/classnames-template-literals](https://github.com/netlify/classnames-template-literals), you can add its name to the list to make sure it gets parsed by this rule. - -For best results, gather the declarative classnames together, avoid mixing conditional classnames in between, move them at the end. - -### `ignoredKeys` (default: `["compoundVariants", "defaultVariants"]`) - -Using libraries like `cva`, some of its object keys are not meant to contain classnames in its value(s). -You can specify which key(s) won't be parsed by the plugin using this setting. -For example, `cva` has `compoundVariants` and `defaultVariants`. -NB: As `compoundVariants` can have classnames inside its `class` property, you can also use a callee to make sure this inner part gets parsed while its parent is ignored. - -### `config` (default: generated by `tailwindcss/lib/lib/load-config`) - -By default the plugin will try to load the file returned by the official `loadConfig()` utility. - -This allows the plugin to use your customized `colors`, `spacing`, `screens`... - -You can provide another path or filename for your Tailwind CSS config file like `"config/tailwind.js"`. - -If the external file cannot be loaded (e.g. incorrect path or deleted file), an empty object `{}` will be used instead. - -It is also possible to directly inject a configuration as plain `object` like `{ prefix: "tw-", theme: { ... } }`. - -Finally, the plugin will [merge the provided configuration](https://tailwindcss.com/docs/configuration#referencing-in-java-script) with [Tailwind CSS's default configuration](https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js). - -### `skipClassAttribute` (default: `false`) - -Set `skipClassAttribute` to `true` if you only want to lint the classnames inside one of the `callees`. -While, this will avoid linting the `class` and `className` attributes, it will still lint matching `callees` inside of these attributes. - -### `tags` (default: `[]`) - -Optional, if you are using tagged templates, you should provide the tags in this array. - -### `classRegex` (default: `"^class(Name)?$"`) - -Optional, can be used to support custom attributes - -## Further Reading - -If there is exactly one equivalent regular classname, this rule will fix the issue for you by replacing the arbitrary classnames by their unique substitutes. - -But if there are several possible substitutes for an arbitrary classname, then you can manually perform the replacement. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..a4d94bef --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,35 @@ +import pluginJs from "@eslint/js"; +import importPlugin from "eslint-plugin-import"; +import simpleImportSort from "eslint-plugin-simple-import-sort"; +import eslintPluginUnicorn from "eslint-plugin-unicorn"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { files: ["**/*.{js,mjs,cjs,ts}"] }, + { ignores: ["lib/**"] }, + { languageOptions: { globals: globals.browser } }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + plugins: { + import: importPlugin, + "simple-import-sort": simpleImportSort, + }, + rules: { + "import/first": "error", + "import/newline-after-import": "error", + "simple-import-sort/imports": "error", + "simple-import-sort/exports": "error", + "@typescript-eslint/array-type": ["error", { default: "generic" }], + }, + }, + eslintPluginUnicorn.configs["flat/recommended"], + { + rules: { + // Already covered + "unicorn/prefer-module": "off", + }, + }, +]; diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..4583b094 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,10 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +// eslint-disable-next-line no-undef +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + testMatch: ["**/*.spec.ts"], + // Jest running with imported vitest utils causes errors like: + // Vitest cannot be imported in a CommonJS module using require(). Please use "import" instead. + modulePathIgnorePatterns: ["/src/utils/tailwindcss-api/worker/"], +}; diff --git a/lib/.prettierrc.json b/lib/.prettierrc.json deleted file mode 100644 index 2a46d49f..00000000 --- a/lib/.prettierrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "printWidth": 120, - "semi": true, - "singleQuote": true, - "trailingComma": "es5" -} diff --git a/lib/config/flat-recommended.js b/lib/config/flat-recommended.js deleted file mode 100644 index d6d103c9..00000000 --- a/lib/config/flat-recommended.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @fileoverview Recommended coniguration for flat style - * @see https://eslint.org/docs/latest/use/configure/configuration-files-new - * @author FranΓ§ois Massart - */ -'use strict'; - -const rules = require('./rules'); - -module.exports = [ - { - name: 'tailwindcss:base', - plugins: { - get tailwindcss() { - return require('../index'); - }, - }, - languageOptions: { - parserOptions: { - ecmaFeatures: { - jsx: true, - }, - }, - }, - }, - { - name: 'tailwindcss:rules', - rules, - }, -]; diff --git a/lib/config/groups.js b/lib/config/groups.js deleted file mode 100644 index 8ab91d53..00000000 --- a/lib/config/groups.js +++ /dev/null @@ -1,1633 +0,0 @@ -/** - * @fileoverview Default groups for Tailwind CSS classnames - * @description The hierarchy of `members` can be useful to detect redundant and/or contradicting classnames - * @version v3.1.3 - * @see https://tailwindcss.com/docs - * @author FranΓ§ois Massart - */ -module.exports.groups = [ - { - type: 'Core Concepts', - members: [ - { - type: 'Hover, Focus, & Other States', - members: [ - { - type: 'group', - members: 'group', - }, - { - type: 'peer', - members: 'peer', - }, - ], - }, - { - type: 'Dark Mode', - members: '${dark}', - }, - { - type: 'Arbitrary properties', - members: '${arbitraryProperties}', - }, - ], - }, - { - type: 'Layout', - members: [ - { - type: 'Aspect Ratio', - members: 'aspect\\-(?${aspectRatio})', - configKey: 'aspectRatio', - }, - { - type: 'Container', - members: 'container', - }, - { - type: 'Columns', - members: 'columns\\-(?${columns})', - configKey: 'columns', - }, - { - type: 'Break After', - members: 'break\\-after\\-(?auto|avoid|all|avoid\\-page|page|left|right|column)', - }, - { - type: 'Break Before', - members: 'break\\-before\\-(?auto|avoid|all|avoid\\-page|page|left|right|column)', - }, - { - type: 'Break Inside', - members: 'break\\-inside\\-(?auto|avoid|avoid\\-page|avoid\\-column)', - }, - { - type: 'Box Decoration Break', - members: 'box\\-decoration\\-(?clone|slice)', - }, - { - type: 'Deprecated Box Decoration Break', - members: 'decoration\\-(?clone|slice)', - deprecated: true, - }, - { - type: 'Box Sizing', - members: 'box\\-(?border|content)', - }, - { - type: 'Display', - members: - 'block|flex|grid|flow\\-root|contents|hidden|inline(\\-(block|flex|table|grid))?|table\\-(column|footer|header|row)\\-group|table(\\-(caption|row|cell|column))?|list\\-item', - }, - { - type: 'Floats', - members: 'float\\-(?right|left|none)', - }, - { - type: 'Clear', - members: 'clear\\-(?left|right|both|none)', - }, - { - type: 'Isolation', - members: '(isolate|isolation\\-auto)', - }, - { - type: 'Object Fit', - members: 'object\\-(?contain|cover|fill|none|scale\\-down)', - }, - { - type: 'Object Position', - members: 'object\\-(?${objectPosition})', - configKey: 'objectPosition', - }, - { - type: 'Overflow', - members: [ - { - type: 'overflow', - members: 'overflow\\-(?auto|hidden|clip|visible|scroll)', - shorthand: 'all', - body: 'overflow', - }, - { - type: 'overflow-x', - members: 'overflow\\-x\\-(?auto|hidden|clip|visible|scroll)', - shorthand: 'x', - body: 'overflow-x', - }, - { - type: 'overflow-y', - members: 'overflow\\-y\\-(?auto|hidden|clip|visible|scroll)', - shorthand: 'y', - body: 'overflow-y', - }, - ], - }, - { - type: 'Overscroll Behavior', - members: [ - { - type: 'overscroll', - members: 'overscroll\\-(?auto|contain|none)', - shorthand: 'all', - body: 'overscroll', - }, - { - type: 'overscroll-x', - members: 'overscroll\\-x\\-(?auto|contain|none)', - shorthand: 'x', - body: 'overscroll-x', - }, - { - type: 'overscroll-y', - members: 'overscroll\\-y\\-(?auto|contain|none)', - shorthand: 'y', - body: 'overscroll-y', - }, - ], - }, - { - type: 'Position', - members: 'static|fixed|absolute|relative|sticky', - }, - { - type: 'Top / Right / Bottom / Left', - members: [ - { - type: 'inset', - members: '(inset\\-(?${inset})|\\-inset\\-(?${-inset}))', - shorthand: 'all', - body: 'inset', - configKey: 'inset', - }, - { - type: 'inset-y', - members: '(inset\\-y\\-(?${inset})|\\-inset\\-y\\-(?${-inset}))', - shorthand: 'y', - body: 'inset-y', - configKey: 'inset', - }, - { - type: 'inset-x', - members: '(inset\\-x\\-(?${inset})|\\-inset\\-x\\-(?${-inset}))', - shorthand: 'x', - body: 'inset-x', - configKey: 'inset', - }, - { - type: 'top', - members: '(top\\-(?${inset})|\\-top\\-(?${-inset}))', - shorthand: 't', - body: 'top', - configKey: 'inset', - }, - { - type: 'right', - members: '(right\\-(?${inset})|\\-right\\-(?${-inset}))', - shorthand: 'r', - body: 'right', - configKey: 'inset', - }, - { - type: 'bottom', - members: '(bottom\\-(?${inset})|\\-bottom\\-(?${-inset}))', - shorthand: 'b', - body: 'bottom', - configKey: 'inset', - }, - { - type: 'left', - members: '(left\\-(?${inset})|\\-left\\-(?${-inset}))', - shorthand: 'l', - body: 'left', - configKey: 'inset', - }, - ], - }, - { - type: 'Visibility', - members: '(in)?visible|collapse', - }, - { - type: 'Z-Index', - members: '(z\\-(?${zIndex})|\\-z\\-(?${-zIndex}))', - configKey: 'zIndex', - }, - ], - }, - { - type: 'Flexbox & Grid', - members: [ - { - type: 'Flex Basis', - members: 'basis\\-(?${flexBasis})', - configKey: 'flexBasis', - }, - { - type: 'Flex Direction', - members: 'flex\\-(row|col)(\\-reverse)?', - }, - { - type: 'Flex Wrap', - members: 'flex\\-(wrap(\\-reverse)?|nowrap)', - }, - { - type: 'Flex', - members: 'flex\\-(?${flex})', - configKey: 'flex', - }, - { - type: 'Flex Grow', - members: 'grow(\\-(?${flexGrow}))?', - configKey: 'flexGrow', - }, - { - type: 'Deprecated Flex Grow', - members: 'flex\\-grow(\\-(?${flexGrow}))?', - deprecated: true, - configKey: 'flexGrow', - }, - { - type: 'Flex Shrink', - members: 'shrink(\\-(?${flexShrink}))?', - configKey: 'flexShrink', - }, - { - type: 'Deprecated Flex Shrink', - members: 'flex\\-shrink(\\-(?${flexShrink}))?', - deprecated: true, - configKey: 'flexShrink', - }, - { - type: 'Order', - members: '(order\\-(?${order})|\\-order\\-(?${-order}))', - configKey: 'order', - }, - { - type: 'Grid Template Columns', - members: 'grid\\-cols\\-(?${gridTemplateColumns})', - configKey: 'gridTemplateColumns', - }, - { - type: 'Grid Column Start / End', - members: [ - { - type: 'grid-column', - members: 'col\\-(?${gridColumn})', - configKey: 'gridColumn', - }, - { - type: 'grid-column-start', - members: 'col\\-start\\-(?${gridColumnStart})', - configKey: 'gridColumnStart', - }, - { - type: 'grid-column-end', - members: 'col\\-end\\-(?${gridColumnEnd})', - configKey: 'gridColumnEnd', - }, - ], - }, - { - type: 'Grid Template Rows', - members: 'grid\\-rows\\-(?${gridTemplateRows})', - configKey: 'gridTemplateRows', - }, - { - type: 'Grid Row Start / End', - members: [ - { - type: 'grid-row', - members: 'row\\-(?${gridRow})', - configKey: 'gridRow', - }, - { - type: 'grid-row-start', - members: 'row\\-start\\-(?${gridRowStart})', - configKey: 'gridRowStart', - }, - { - type: 'grid-row-end', - members: 'row\\-end\\-(?${gridRowEnd})', - configKey: 'gridRowEnd', - }, - ], - }, - { - type: 'Grid Auto Flow', - members: 'grid\\-flow\\-(dense|(row|col)(\\-dense)?)', - }, - { - type: 'Grid Auto Columns', - members: 'auto\\-cols\\-(?${gridAutoColumns})', - configKey: 'gridAutoColumns', - }, - { - type: 'Grid Auto Rows', - members: 'auto\\-rows\\-(?${gridAutoRows})', - configKey: 'gridAutoRows', - }, - { - type: 'Gap', - members: [ - { - type: 'gap', - members: 'gap\\-(?${gap})', - shorthand: 'all', - body: 'gap', - configKey: 'gap', - }, - { - type: 'column-gap', - members: 'gap\\-x\\-(?${gap})', - shorthand: 'x', - body: 'gap-x', - configKey: 'gap', - }, - { - type: 'row-gap', - members: 'gap\\-y\\-(?${gap})', - shorthand: 'y', - body: 'gap-y', - configKey: 'gap', - }, - ], - }, - { - type: 'Justify Content', - members: 'justify\\-(start|end|center|between|around|evenly)', - }, - { - type: 'Justify Items', - members: 'justify\\-items\\-(start|end|center|stretch)', - }, - { - type: 'Justify Self', - members: 'justify\\-self\\-(auto|start|end|center|stretch)', - }, - { - type: 'Align Content', - members: 'content\\-(center|start|end|between|around|evenly|baseline)', - }, - { - type: 'Align Items', - members: 'items\\-(start|end|center|baseline|stretch)', - }, - { - type: 'Align Self', - members: 'self\\-(auto|start|end|center|stretch|baseline)', - }, - { - type: 'Place Content', - members: 'place\\-content\\-(center|start|end|between|around|evenly|stretch|baseline)', - }, - { - type: 'Place Items', - members: 'place\\-items\\-(start|end|center|stretch|baseline)', - }, - { - type: 'Place Self', - members: 'place\\-self\\-(auto|start|end|center|stretch)', - }, - ], - }, - { - type: 'Spacing', - members: [ - { - type: 'Padding', - members: [ - { - type: 'p', - members: 'p\\-(?${padding})', - shorthand: 'all', - body: 'p', - configKey: 'padding', - }, - { - type: 'py', - members: 'py\\-(?${padding})', - shorthand: 'y', - body: 'py', - configKey: 'padding', - }, - { - type: 'px', - members: 'px\\-(?${padding})', - shorthand: 'x', - body: 'px', - configKey: 'padding', - }, - { - type: 'pt', - members: 'pt\\-(?${padding})', - shorthand: 't', - body: 'pt', - configKey: 'padding', - }, - { - type: 'pr', - members: 'pr\\-(?${padding})', - shorthand: 'r', - body: 'pr', - configKey: 'padding', - }, - { - type: 'pb', - members: 'pb\\-(?${padding})', - shorthand: 'b', - body: 'pb', - configKey: 'padding', - }, - { - type: 'pl', - members: 'pl\\-(?${padding})', - shorthand: 'l', - body: 'pl', - configKey: 'padding', - }, - ], - }, - { - type: 'Margin', - members: [ - { - type: 'm', - members: '(m\\-(?${margin})|\\-m\\-(?${-margin}))', - shorthand: 'all', - body: 'm', - configKey: 'margin', - }, - { - type: 'my', - members: '(my\\-(?${margin})|\\-my\\-(?${-margin}))', - shorthand: 'y', - body: 'my', - configKey: 'margin', - }, - { - type: 'mx', - members: '(mx\\-(?${margin})|\\-mx\\-(?${-margin}))', - shorthand: 'x', - body: 'mx', - configKey: 'margin', - }, - { - type: 'mt', - members: '(mt\\-(?${margin})|\\-mt\\-(?${-margin}))', - shorthand: 't', - body: 'mt', - configKey: 'margin', - }, - { - type: 'mr', - members: '(mr\\-(?${margin})|\\-mr\\-(?${-margin}))', - shorthand: 'r', - body: 'mr', - configKey: 'margin', - }, - { - type: 'mb', - members: '(mb\\-(?${margin})|\\-mb\\-(?${-margin}))', - shorthand: 'b', - body: 'mb', - configKey: 'margin', - }, - { - type: 'ml', - members: '(ml\\-(?${margin})|\\-ml\\-(?${-margin}))', - shorthand: 'l', - body: 'ml', - configKey: 'margin', - }, - ], - }, - { - type: 'Space Between', - members: [ - { - type: 'space-y', - members: '(space\\-y\\-(?${space})|\\-space\\-y\\-(?${-space}))', - configKey: 'space', - }, - { - type: 'space-x', - members: '(space\\-x\\-(?${space})|\\-space\\-x\\-(?${-space}))', - configKey: 'space', - }, - { - type: 'space-y-reverse', - members: 'space\\-y\\-reverse', - }, - { - type: 'space-x-reverse', - members: 'space\\-x\\-reverse', - }, - ], - }, - ], - }, - { - type: 'Sizing', - members: [ - { - type: 'Width', - members: 'w\\-(?${width})', - configKey: 'width', - }, - { - type: 'Min-Width', - members: 'min\\-w\\-(?${minWidth})', - configKey: 'minWidth', - }, - { - type: 'Max-Width', - members: 'max\\-w\\-(?${maxWidth})', - configKey: 'maxWidth', - }, - { - type: 'Height', - members: 'h\\-(?${height})', - configKey: 'height', - }, - { - type: 'Min-Height', - members: 'min\\-h\\-(?${minHeight})', - configKey: 'minHeight', - }, - { - type: 'Max-Height', - members: 'max\\-h\\-(?${maxHeight})', - configKey: 'maxHeight', - }, - { - type: 'Size', - members: 'size\\-(?${size})', - configKey: 'size', - }, - ], - }, - { - type: 'Typography', - members: [ - { - type: 'Font Family', - members: 'font\\-(?${fontFamily})', - configKey: 'fontFamily', - }, - { - type: 'Font Size', - members: 'text\\-(?${fontSize})', - configKey: 'fontSize', - }, - { - type: 'Font Smoothing', - members: '(subpixel\\-)?antialiased', - }, - { - type: 'Font Style', - members: '(not\\-)?italic', - }, - { - type: 'Font Weight', - members: 'font\\-(?${fontWeight})', - configKey: 'fontWeight', - }, - { - type: 'Font Variant Numeric', - members: [ - { - type: 'Normal Nums', - members: 'normal\\-nums', - }, - { - type: 'Ordinal', - members: 'ordinal', - }, - { - type: 'Slashed Zero', - members: 'slashed-zero', - }, - { - type: 'Style Nums', - members: '(lining|oldstyle)\\-nums', - }, - { - type: 'Proportinal or Tabular', - members: '(proportional|tabular)\\-nums', - }, - { - type: 'Fractions', - members: '(diagonal|stacked)\\-fractions', - }, - ], - }, - { - type: 'Letter Spacing', - members: '(tracking\\-(?${letterSpacing})|\\-tracking\\-(?${-letterSpacing}))', - configKey: 'letterSpacing', - }, - // { - // type: 'Line Clamp', - // members: 'line\\-clamp\\-(?${lineClamp})', - // configKey: 'lineClamp', - // }, - { - type: 'Line Height', - members: 'leading\\-(?${lineHeight})', - configKey: 'lineHeight', - }, - // { - // type: 'List Style Image', - // members: 'list\\-image\\-(?${listStyleImage})', - // configKey: 'listStyleImage', - // }, - { - type: 'List Style Type', - members: 'list\\-(?${listStyleType})', - configKey: 'listStyleType', - }, - { - type: 'List Style Position', - members: 'list\\-(in|out)side', - }, - { - type: 'Text Alignment', - members: 'text\\-(left|center|right|justify|start|end)', - }, - { - type: 'Text Color', - members: 'text\\-(?${textColor})', - configKey: 'colors', - }, - { - type: 'Text Decoration', - members: '(no\\-)?underline|overline|line\\-through', - }, - { - type: 'Text Decoration Color', - members: 'decoration\\-(?${colors})', - configKey: 'colors', - }, - { - type: 'Text Decoration Style', - members: 'decoration\\-(solid|double|dotted|dashed|wavy)', - }, - { - type: 'Text Decoration Thickness', - members: 'decoration\\-(?${textDecorationThickness})', - configKey: 'textDecorationThickness', - }, - { - type: 'Text Underline Offset', - members: 'underline\\-offset\\-(?${textUnderlineOffset})', - configKey: 'textUnderlineOffset', - }, - { - type: 'Text Transform', - members: '(upper|lower|normal\\-)case|capitalize', - }, - { - type: 'Text Overflow', - members: 'truncate|text\\-(ellipsis|clip)', - }, - { - type: 'Deprecated Text Overflow', - members: 'overflow\\-(ellipsis|clip)', - deprecated: true, - }, - { - type: 'Text Wrap', - members: 'text\\-(wrap|nowrap|balance|pretty)', - }, - { - type: 'Text Indent', - members: '(indent\\-(?${textIndent})|\\-indent\\-(?${-textIndent}))', - configKey: 'textIndent', - }, - { - type: 'Vertical Alignment', - members: 'align\\-(baseline|top|middle|bottom|text\\-(top|bottom)|sub|super)', - }, - { - type: 'Whitespace', - members: 'whitespace\\-(normal|nowrap|pre(\\-(line|wrap))?)', - }, - { - type: 'Word Break', - members: 'break\\-(normal|words|all|keep)', - }, - { - type: 'Content', - members: 'content\\-(?${content})', - configKey: 'content', - }, - ], - }, - { - type: 'Backgrounds', - members: [ - { - type: 'Background Image URL', - members: 'bg\\-\\[(image\\:|url\\()(?${backgroundImageUrl})\\)\\]', - }, - { - type: 'Background Attachment', - members: 'bg\\-(fixed|local|scroll)', - }, - { - type: 'Background Clip', - members: 'bg\\-clip\\-(border|padding|content|text)', - }, - { - type: 'Background Color', - members: 'bg\\-(?${colors})', - configKey: 'colors', - }, - { - type: 'Deprecated Background Opacity', - members: 'bg\\-opacity\\-(?${backgroundOpacity})', - deprecated: true, - }, - { - type: 'Background Origin', - members: 'bg\\-origin\\-(border|padding|content)', - }, - { - type: 'Background Position', - members: 'bg\\-(?${backgroundPosition})', - configKey: 'backgroundPosition', - }, - { - type: 'Background Repeat', - members: 'bg\\-(no\\-repeat|repeat(\\-(x|y|round|space))?)', - }, - { - type: 'Background Size', - members: 'bg\\-(?${backgroundSize})', - configKey: 'backgroundSize', - }, - { - type: 'Background Image', - members: 'bg\\-(?${backgroundImage})', - configKey: 'backgroundImage', - }, - { - type: 'Gradient Color Stops', - members: [ - { - type: 'from', - members: 'from\\-(?${gradientColorStopPositions})', - configKey: 'gradientColorStopPositions', - }, - { - type: 'via', - members: 'via\\-(?${gradientColorStopPositions})', - configKey: 'gradientColorStopPositions', - }, - { - type: 'to', - members: 'to\\-(?${gradientColorStopPositions})', - configKey: 'gradientColorStopPositions', - }, - ], - }, - ], - }, - { - type: 'Borders', - members: [ - { - type: 'Border Radius', - members: [ - { - type: 'border-radius', - members: 'rounded(\\-(?${borderRadius}))?', - shorthand: 'all', - body: 'rounded', - configKey: 'borderRadius', - }, - { - type: 'border-radius-top', - members: 'rounded\\-t(\\-(?${borderRadius}))?', - shorthand: 't', - body: 'rounded-t', - configKey: 'borderRadius', - }, - { - type: 'border-radius-right', - members: 'rounded\\-r(\\-(?${borderRadius}))?', - shorthand: 'r', - body: 'rounded-r', - configKey: 'borderRadius', - }, - { - type: 'border-radius-bottom', - members: 'rounded\\-b(\\-(?${borderRadius}))?', - shorthand: 'b', - body: 'rounded-b', - configKey: 'borderRadius', - }, - { - type: 'border-radius-left', - members: 'rounded\\-l(\\-(?${borderRadius}))?', - shorthand: 'l', - body: 'rounded-l', - configKey: 'borderRadius', - }, - { - type: 'border-radius-top-left', - members: 'rounded\\-tl(\\-(?${borderRadius}))?', - shorthand: 'tl', - body: 'rounded-tl', - configKey: 'borderRadius', - }, - { - type: 'border-radius-top-right', - members: 'rounded\\-tr(\\-(?${borderRadius}))?', - shorthand: 'tr', - body: 'rounded-tr', - configKey: 'borderRadius', - }, - { - type: 'border-radius-bottom-right', - members: 'rounded\\-br(\\-(?${borderRadius}))?', - shorthand: 'br', - body: 'rounded-br', - configKey: 'borderRadius', - }, - { - type: 'border-radius-bottom-left', - members: 'rounded\\-bl(\\-(?${borderRadius}))?', - shorthand: 'bl', - body: 'rounded-bl', - configKey: 'borderRadius', - }, - ], - }, - { - type: 'Border Width', - members: [ - { - type: 'border-width', - members: 'border(\\-(?${borderWidth}))?', - shorthand: 'all', - body: 'border', - configKey: 'borderWidth', - }, - { - type: 'border-y-width', - members: 'border\\-y(\\-(?${borderWidth}))?', - shorthand: 'y', - body: 'border-y', - configKey: 'borderWidth', - }, - { - type: 'border-x-width', - members: 'border\\-x(\\-(?${borderWidth}))?', - shorthand: 'x', - body: 'border-x', - configKey: 'borderWidth', - }, - { - type: 'border-top-width', - members: 'border\\-t(\\-(?${borderWidth}))?', - shorthand: 't', - body: 'border-t', - configKey: 'borderWidth', - }, - { - type: 'border-right-width', - members: 'border\\-r(\\-(?${borderWidth}))?', - shorthand: 'r', - body: 'border-r', - configKey: 'borderWidth', - }, - { - type: 'border-bottom-width', - members: 'border\\-b(\\-(?${borderWidth}))?', - shorthand: 'b', - body: 'border-b', - configKey: 'borderWidth', - }, - { - type: 'border-left-width', - members: 'border\\-l(\\-(?${borderWidth}))?', - shorthand: 'l', - body: 'border-l', - configKey: 'borderWidth', - }, - ], - }, - { - type: 'Border Color', - members: [ - { - type: 'border-color', - members: 'border\\-(?${borderColor})', - shorthand: 'all', - body: 'border', - configKey: 'borderColor', - }, - { - type: 'border-y-color', - members: 'border\\-y\\-(?${borderColor})', - shorthand: 'y', - body: 'border-y', - configKey: 'borderColor', - }, - { - type: 'border-x-color', - members: 'border\\-x\\-(?${borderColor})', - shorthand: 'x', - body: 'border-x', - configKey: 'borderColor', - }, - { - type: 'border-top-color', - members: 'border\\-t\\-(?${borderColor})', - shorthand: 't', - body: 'border-t', - configKey: 'borderColor', - }, - { - type: 'border-right-color', - members: 'border\\-r\\-(?${borderColor})', - shorthand: 'r', - body: 'border-r', - configKey: 'borderColor', - }, - { - type: 'border-bottom-color', - members: 'border\\-b\\-(?${borderColor})', - shorthand: 'b', - body: 'border-b', - configKey: 'borderColor', - }, - { - type: 'border-left-color', - members: 'border\\-l\\-(?${borderColor})', - shorthand: 'l', - body: 'border-l', - configKey: 'borderColor', - }, - ], - }, - { - type: 'Deprecated Border Opacity', - members: 'border\\-opacity\\-(?${borderOpacity})', - deprecated: true, - configKey: 'borderOpacity', - }, - { - type: 'Border Style', - members: 'border\\-(solid|dashed|dotted|double|hidden|none)', - }, - { - type: 'Divide Width', - members: [ - { - type: 'divide-y', - members: 'divide\\-y(\\-(?${divideWidth}))?', - configKey: 'divideWidth', - }, - { - type: 'divide-x', - members: 'divide\\-x(\\-(?${divideWidth}))?', - configKey: 'divideWidth', - }, - { - type: 'divide-y-reverse', - members: 'divide\\-y\\-reverse', - }, - { - type: 'divide-x-reverse', - members: 'divide\\-x\\-reverse', - }, - ], - }, - { - type: 'Divide Color', - members: 'divide\\-(?${divideColor})', - configKey: 'divideColor', - }, - { - type: 'Divide Style', - members: 'divide\\-(solid|dashed|dotted|double|none)', - }, - { - type: 'Outline Width', - members: 'outline\\-(?${outlineWidth})', - configKey: 'outlineWidth', - }, - { - type: 'Outline Color', - members: 'outline\\-(?${outlineColor})', - configKey: 'outlineColor', - }, - { - type: 'Outline Style', - members: 'outline(\\-(none|dashed|dotted|double|hidden))?', - }, - { - type: 'Outline Offset', - members: - '(outline\\-offset\\-(?${outlineOffset})|\\-outline\\-offset\\-(?${-outlineOffset}))', - configKey: 'outlineOffset', - }, - { - type: 'Ring Width', - members: [ - { - type: 'ring', - members: 'ring(\\-(?${ringWidth}))?', - configKey: 'ringWidth', - }, - ], - }, - { - type: 'Ring Inset', - members: [ - { - type: 'ring-inset', - members: 'ring\\-inset', - }, - ], - }, - { - type: 'Ring Color', - members: 'ring\\-(?${colors})', - configKey: 'colors', - }, - { - type: 'Deprecated Ring Opacity', - members: 'ring\\-opacity\\-(?${ringOpacity})', - deprecated: true, - configKey: 'ringOpacity', - }, - { - type: 'Ring Offset Width', - members: 'ring\\-offset\\-(?${ringOffsetWidth})', - configKey: 'ringOffsetWidth', - }, - { - type: 'Ring Offset Color', - members: 'ring\\-offset\\-(?${colors})', - configKey: 'colors', - }, - ], - }, - { - type: 'Effects', - members: [ - { - type: 'Box Shadow', - members: 'shadow(\\-(?${boxShadow}))?', - configKey: 'boxShadow', - }, - { - type: 'Box Shadow Color', - members: 'shadow(\\-(?${boxShadowColor}))?', - configKey: 'boxShadowColor', - }, - { - type: 'Opacity', - members: 'opacity\\-(?${opacity})', - configKey: 'opacity', - }, - { - type: 'Mix Blend Mode', - members: - 'mix\\-blend\\-(normal|multiply|screen|overlay|darken|lighten|color\\-(burn|dodge)|(hard|soft)\\-light|difference|exclusion|hue|saturation|color|luminosity|plus\\-lighter)', - }, - { - type: 'Background Blend Mode', - members: - 'bg\\-blend\\-(normal|multiply|screen|overlay|darken|lighten|color\\-(dodge|burn)|(hard|soft)\\-light|difference|exclusion|hue|saturation|color|luminosity)', - }, - ], - }, - { - type: 'Filters', - members: [ - { - type: 'Deprecated Filter', - members: 'filter', - deprecated: true, - }, - { - type: 'Blur', - members: 'blur(\\-(?${blur}))?', - configKey: 'blur', - }, - { - type: 'Brightness', - members: 'brightness\\-(?${brightness})', - configKey: 'brightness', - }, - { - type: 'Contrast', - members: 'contrast\\-(?${contrast})', - configKey: 'contrast', - }, - { - type: 'Drop Shadow', - members: 'drop\\-shadow(\\-(?${dropShadow}))?', - configKey: 'dropShadow', - }, - { - type: 'Grayscale', - members: 'grayscale(\\-(?${grayscale}))?', - configKey: 'grayscale', - }, - { - type: 'Hue Rotate', - members: 'hue\\-rotate\\-(?${hueRotate})|\\-hue\\-rotate\\-(?${-hueRotate})', - configKey: 'hueRotate', - }, - { - type: 'Invert', - members: 'invert(\\-(?${invert}))?', - configKey: 'invert', - }, - { - type: 'Saturate', - members: 'saturate\\-(?${saturate})', - configKey: 'saturate', - }, - { - type: 'Sepia', - members: 'sepia(\\-(?${sepia}))?', - configKey: 'sepia', - }, - { - type: 'Backdrop Blur', - members: 'backdrop\\-blur(\\-(?${backdropBlur}))?', - configKey: 'backdropBlur', - }, - { - type: 'Backdrop Brightness', - members: 'backdrop\\-brightness\\-(?${backdropBrightness})', - configKey: 'backdropBrightness', - }, - { - type: 'Backdrop Contrast', - members: 'backdrop\\-contrast\\-(?${backdropContrast})', - configKey: 'backdropContrast', - }, - { - type: 'Backdrop Grayscale', - members: 'backdrop\\-grayscale(\\-(?${backdropGrayscale}))?', - configKey: 'backdropGrayscale', - }, - { - type: 'Backdrop Hue Rotate', - members: - 'backdrop\\-hue\\-rotate\\-(?${backdropHueRotate})|\\-backdrop\\-hue\\-rotate\\-(?${-backdropHueRotate})', - configKey: 'backdropHueRotate', - }, - { - type: 'Backdrop Invert', - members: 'backdrop\\-invert(\\-(?${backdropInvert}))?', - configKey: 'backdropInvert', - }, - { - type: 'Backdrop Opacity', - members: 'backdrop\\-opacity\\-(?${backdropOpacity})', - configKey: 'backdropOpacity', - }, - { - type: 'Backdrop Saturate', - members: 'backdrop\\-saturate\\-(?${backdropSaturate})', - configKey: 'backdropSaturate', - }, - { - type: 'Backdrop Sepia', - members: 'backdrop\\-sepia(\\-(?${backdropSepia}))?', - configKey: 'backdropSepia', - }, - ], - }, - { - type: 'Tables', - members: [ - { - type: 'Border Collapse', - members: 'border\\-(collapse|separate)', - }, - { - type: 'Border Spacing', - members: [ - { - type: 'border-spacing', - members: 'border\\-spacing\\-(?${borderSpacing})', - shorthand: 'all', - body: 'border-spacing', - configKey: 'borderSpacing', - }, - { - type: 'border-spacing-x', - members: 'border\\-spacing\\-x\\-(?${borderSpacing})', - shorthand: 'x', - body: 'border-spacing-x', - configKey: 'borderSpacing', - }, - { - type: 'border-spacing-y', - members: 'border\\-spacing\\-y\\-(?${borderSpacing})', - shorthand: 'y', - body: 'border-spacing-y', - configKey: 'borderSpacing', - }, - ], - }, - { - type: 'Table Layout', - members: 'table\\-(auto|fixed)', - }, - ], - }, - { - type: 'Transitions & Animation', - members: [ - { - type: 'Transition Property', - members: 'transition(\\-(?${transitionProperty}))?', - configKey: 'transitionProperty', - }, - { - type: 'Transition Duration', - members: 'duration(\\-(?${transitionDuration}))?', - configKey: 'transitionDuration', - }, - { - type: 'Transition Timing Function', - members: 'ease(\\-(?${transitionTimingFunction}))?', - configKey: 'transitionTimingFunction', - }, - { - type: 'Transition Delay', - members: 'delay\\-(?${transitionDelay})', - configKey: 'transitionDelay', - }, - { - type: 'Animation', - members: 'animate\\-(?${animation})', - configKey: 'animation', - }, - ], - }, - { - type: 'Transforms', - members: [ - { - type: 'Transform GPU', - members: [ - { - type: 'transform-gpu', - members: 'transform\\-gpu', - }, - ], - }, - { - type: 'Transform None', - members: [ - { - type: 'transform-none', - members: 'transform\\-none', - }, - ], - }, - { - type: 'Deprecated Transform', - members: [ - { - type: 'transform', - members: 'transform', - deprecated: true, - }, - ], - }, - { - type: 'Scale', - members: [ - { - type: 'scale', - members: 'scale\\-(?${scale})|\\-scale\\-(?${-scale})', - shorthand: 'all', - body: 'scale', - configKey: 'scale', - }, - { - type: 'scale-y', - members: 'scale\\-y\\-(?${scale})|\\-scale\\-y\\-(?${-scale})', - shorthand: 'y', - body: 'scale-y', - configKey: 'scale', - }, - { - type: 'scale-x', - members: 'scale\\-x\\-(?${scale})|\\-scale\\-x\\-(?${-scale})', - shorthand: 'x', - body: 'scale-x', - configKey: 'scale', - }, - ], - }, - { - type: 'Rotate', - members: '(rotate\\-(?${rotate})|\\-rotate\\-(?${-rotate}))', - configKey: 'rotate', - }, - { - type: 'Translate', - members: [ - { - type: 'translate-x', - members: '(translate\\-x\\-(?${translate})|\\-translate\\-x\\-(?${-translate}))', - configKey: 'translate', - }, - { - type: 'translate-y', - members: '(translate\\-y\\-(?${translate})|\\-translate\\-y\\-(?${-translate}))', - configKey: 'translate', - }, - ], - }, - { - type: 'Skew', - members: [ - { - type: 'skew-x', - members: '(skew\\-x\\-(?${skew})|\\-skew\\-x\\-(?${-skew}))', - configKey: 'skew', - }, - { - type: 'skew-y', - members: '(skew\\-y\\-(?${skew})|\\-skew\\-y\\-(?${-skew}))', - configKey: 'skew', - }, - ], - }, - { - type: 'Transform Origin', - members: 'origin\\-(?${transformOrigin})', - configKey: 'transformOrigin', - }, - ], - }, - { - type: 'Interactivity', - members: [ - { - type: 'Accent Color', - members: 'accent\\-(?${accentColor})', - configKey: 'accentColor', - }, - { - type: 'Appearance', - members: 'appearance\\-none', - }, - { - type: 'Cursor', - members: 'cursor\\-(?${cursor})', - configKey: 'cursor', - }, - { - type: 'Caret Color', - members: 'caret\\-(?${colors})', - configKey: 'colors', - }, - { - type: 'Pointer Events', - members: 'pointer\\-events\\-(none|auto)', - }, - { - type: 'Resize', - members: 'resize(\\-(none|x|y))?', - }, - { - type: 'Scroll Behavior', - members: 'scroll\\-(auto|smooth)', - }, - { - type: 'Scroll Margin', - members: 'scroll\\-(?${scrollMargin})', - configKey: 'scrollMargin', - members: [ - { - type: 'scroll-m', - members: 'scroll-m\\-(?${scrollMargin})|\\-scroll-m\\-(?${-scrollMargin})', - configKey: 'scrollMargin', - }, - { - type: 'scroll-my', - members: 'scroll-my\\-(?${scrollMargin})|\\-scroll-my\\-(?${-scrollMargin})', - configKey: 'scrollMargin', - }, - { - type: 'scroll-mx', - members: 'scroll-mx\\-(?${scrollMargin})|\\-scroll-mx\\-(?${-scrollMargin})', - configKey: 'scrollMargin', - }, - { - type: 'scroll-mt', - members: 'scroll-mt\\-(?${scrollMargin})|\\-scroll-mt\\-(?${-scrollMargin})', - configKey: 'scrollMargin', - }, - { - type: 'scroll-mr', - members: 'scroll-mr\\-(?${scrollMargin})|\\-scroll-mr\\-(?${-scrollMargin})', - configKey: 'scrollMargin', - }, - { - type: 'scroll-mb', - members: 'scroll-mb\\-(?${scrollMargin})|\\-scroll-mb\\-(?${-scrollMargin})', - configKey: 'scrollMargin', - }, - { - type: 'scroll-ml', - members: 'scroll-ml\\-(?${scrollMargin})|\\-scroll-ml\\-(?${-scrollMargin})', - configKey: 'scrollMargin', - }, - ], - }, - { - type: 'Scroll Padding', - members: 'scroll\\-(?${scrollPadding})', - configKey: 'scrollPadding', - members: [ - { - type: 'scroll-p', - members: 'scroll-p\\-(?${scrollPadding})', - configKey: 'scrollPadding', - }, - { - type: 'scroll-py', - members: 'scroll-py\\-(?${scrollPadding})', - configKey: 'scrollPadding', - }, - { - type: 'scroll-px', - members: 'scroll-px\\-(?${scrollPadding})', - configKey: 'scrollPadding', - }, - { - type: 'scroll-pt', - members: 'scroll-pt\\-(?${scrollPadding})', - configKey: 'scrollPadding', - }, - { - type: 'scroll-pr', - members: 'scroll-pr\\-(?${scrollPadding})', - configKey: 'scrollPadding', - }, - { - type: 'scroll-pb', - members: 'scroll-pb\\-(?${scrollPadding})', - configKey: 'scrollPadding', - }, - { - type: 'scroll-pl', - members: 'scroll-pl\\-(?${scrollPadding})', - configKey: 'scrollPadding', - }, - ], - }, - { - type: 'Scroll Snap Align', - members: 'snap\\-(start|end|center|align-none)', - }, - { - type: 'Scroll Snap Stop', - members: 'snap\\-(normal|always)', - }, - { - type: 'Scroll Snap Type', - members: 'snap\\-(none|x|y|both)', - }, - { - type: 'Scroll Snap Type Strictness', - members: 'snap\\-(mandatory|proximity)', - }, - { - type: 'Touch Action', - members: [ - { - type: 'Touch Action Mode', - members: 'touch\\-(auto|none|manipulation)', - }, - { - type: 'Touch Action X', - members: 'touch\\-(pan\\-(x|left|right))', - }, - { - type: 'Touch Action Y', - members: 'touch\\-(pan\\-(y|up|down))', - }, - { - type: 'Touch Action Pinch Zoom', - members: 'touch\\-pinch\\-zoom', - }, - ], - }, - { - type: 'User Select', - members: 'select\\-(none|text|all|auto)', - }, - { - type: 'Will Change', - members: 'will\\-change\\-(?${willChange})', - configKey: 'willChange', - }, - ], - }, - { - type: 'SVG', - members: [ - { - type: 'Fill', - members: 'fill\\-(?${fill})', - configKey: 'fill', - }, - { - type: 'Stroke', - members: 'stroke\\-(?${stroke})', - configKey: 'stroke', - }, - { - type: 'Stroke Width', - members: 'stroke\\-(?${strokeWidth})', - configKey: 'strokeWidth', - }, - ], - }, - { - type: 'Accessibility', - members: [ - { - type: 'Screen Readers', - members: '(not\\-)?sr\\-only', - }, - { - type: 'Forced Color Adjust', - members: 'forced\\-color\\-adjust\\-(auto|none)', - }, - ], - }, - { - type: 'Official Plugins', - members: [ - { - // TODO: - // Support for custom prose classname like on - // https://tailwindcss.com/docs/typography-plugin#changing-the-default-class-name - // Adding custom color themes - // https://tailwindcss.com/docs/typography-plugin#adding-custom-color-themes - type: 'Typography', - members: [ - { - type: 'prose', - members: '(not\\-)?prose', - }, - { - type: 'Prose Gray Scale', - members: 'prose\\-(gray|slate|zinc|neutral|stone)', - }, - { - type: 'Prose Type Scale', - members: 'prose\\-(sm|base|lg|2?xl)', - }, - { - type: 'Prose Dark Mode', - members: 'prose\\-invert', - }, - // These are modifiers and not the last part of the classname - // { - // type: 'Prose Element modifiers', - // members: - // 'prose\\-(headings|lead|h1|h2|h3|h4|p|a|blockquote|figure|figcaption|strong|em|code|pre|ol|ul|li|table|thead|tr|th|td|img|video|hr)', - // }, - ], - }, - // ('Forms' plugin has no related classnames, only selectors like `input[type='password']`) - { - type: 'Aspect Ratio', - members: [ - { - type: 'aspect-w', - members: 'aspect\\-(none|w\\-(?${aspectRatio}))', - }, - { - type: 'aspect-h', - members: 'aspect\\-h\\-(?${aspectRatio})', - }, - ], - }, - { - type: 'Line Clamp', - members: 'line\\-clamp\\-(none|(?${lineClamp}))', - }, - ], - }, -]; diff --git a/lib/config/recommended.js b/lib/config/recommended.js deleted file mode 100644 index be940366..00000000 --- a/lib/config/recommended.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @fileoverview Recommended coniguration for legacy style - * @see https://eslint.org/docs/latest/use/configure/configuration-files - * @author FranΓ§ois Massart - */ -'use strict'; - -const rules = require('./rules'); - -module.exports = { - plugins: ['tailwindcss'], - parserOptions: { - ecmaFeatures: { - jsx: true, - }, - }, - rules, -}; diff --git a/lib/config/rules.js b/lib/config/rules.js deleted file mode 100644 index 2399d016..00000000 --- a/lib/config/rules.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @fileoverview Default rules configuration - * @author FranΓ§ois Massart - */ - -module.exports = { - 'tailwindcss/classnames-order': 'warn', - 'tailwindcss/enforces-negative-arbitrary-values': 'warn', - 'tailwindcss/enforces-shorthand': 'warn', - 'tailwindcss/migration-from-tailwind-2': 'warn', - 'tailwindcss/no-arbitrary-value': 'off', - 'tailwindcss/no-custom-classname': 'warn', - 'tailwindcss/no-contradicting-classname': 'error', - 'tailwindcss/no-unnecessary-arbitrary-value': 'warn', -}; diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index 53824e76..00000000 --- a/lib/index.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @fileoverview Rules enforcing best practices while using Tailwind CSS - * @author FranΓ§ois Massart - */ -'use strict'; - -//------------------------------------------------------------------------------ -// Plugin Definition -//------------------------------------------------------------------------------ - -// import all rules in lib/rules -var base = __dirname + '/rules/'; -module.exports = { - rules: { - 'classnames-order': require(base + 'classnames-order'), - 'enforces-negative-arbitrary-values': require(base + 'enforces-negative-arbitrary-values'), - 'enforces-shorthand': require(base + 'enforces-shorthand'), - 'migration-from-tailwind-2': require(base + 'migration-from-tailwind-2'), - 'no-arbitrary-value': require(base + 'no-arbitrary-value'), - 'no-contradicting-classname': require(base + 'no-contradicting-classname'), - 'no-custom-classname': require(base + 'no-custom-classname'), - 'no-unnecessary-arbitrary-value': require(base + 'no-unnecessary-arbitrary-value'), - }, - configs: { - recommended: require('./config/recommended'), - 'flat/recommended': require('./config/flat-recommended'), - }, -}; diff --git a/lib/rules/classnames-order.js b/lib/rules/classnames-order.js deleted file mode 100644 index e7e35732..00000000 --- a/lib/rules/classnames-order.js +++ /dev/null @@ -1,274 +0,0 @@ -/** - * @fileoverview Use a consistent orders for the Tailwind CSS classnames, based on property then on variants - * @author FranΓ§ois Massart - */ -'use strict'; - -const docsUrl = require('../util/docsUrl'); -const customConfig = require('../util/customConfig'); -const astUtil = require('../util/ast'); -const removeDuplicatesFromClassnamesAndWhitespaces = require('../util/removeDuplicatesFromClassnamesAndWhitespaces'); -const getOption = require('../util/settings'); -const parserUtil = require('../util/parser'); -const order = require('../util/prettier/order'); -const createContextFallback = require('tailwindcss/lib/lib/setupContextUtils').createContext; - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -// Predefine message for use in context.report conditional. -// messageId will still be usable in tests. -const INVALID_CLASSNAMES_ORDER_MSG = 'Invalid Tailwind CSS classnames order'; - -const contextFallbackCache = new WeakMap(); - -module.exports = { - meta: { - docs: { - description: 'Enforce a consistent and logical order of the Tailwind CSS classnames', - category: 'Stylistic Issues', - recommended: false, - url: docsUrl('classnames-order'), - }, - messages: { - invalidOrder: INVALID_CLASSNAMES_ORDER_MSG, - }, - fixable: 'code', - schema: [ - { - type: 'object', - properties: { - callees: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - ignoredKeys: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - config: { - // returned from `loadConfig()` utility - type: ['string', 'object'], - }, - removeDuplicates: { - // default: true, - type: 'boolean', - }, - tags: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - }, - }, - ], - }, - - create: function (context) { - const callees = getOption(context, 'callees'); - const skipClassAttribute = getOption(context, 'skipClassAttribute'); - const tags = getOption(context, 'tags'); - const twConfig = getOption(context, 'config'); - const classRegex = getOption(context, 'classRegex'); - const removeDuplicates = getOption(context, 'removeDuplicates'); - - const mergedConfig = customConfig.resolve(twConfig); - const contextFallback = // Set the created contextFallback in the cache if it does not exist yet. - ( - contextFallbackCache.has(mergedConfig) - ? contextFallbackCache - : contextFallbackCache.set(mergedConfig, createContextFallback(mergedConfig)) - ).get(mergedConfig); - - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- - /** - * Recursive function crawling into child nodes - * @param {ASTNode} node The root node of the current parsing - * @param {ASTNode} arg The child node of node - * @returns {void} - */ - const sortNodeArgumentValue = (node, arg = null) => { - let originalClassNamesValue = null; - let start = null; - let end = null; - let prefix = ''; - let suffix = ''; - if (arg === null) { - originalClassNamesValue = astUtil.extractValueFromNode(node); - const range = astUtil.extractRangeFromNode(node); - if (node.type === 'TextAttribute') { - start = range[0]; - end = range[1]; - } else { - start = range[0] + 1; - end = range[1] - 1; - } - } else { - switch (arg.type) { - case 'Identifier': - return; - case 'TemplateLiteral': - arg.expressions.forEach((exp) => { - sortNodeArgumentValue(node, exp); - }); - arg.quasis.forEach((quasis) => { - sortNodeArgumentValue(node, quasis); - }); - return; - case 'ConditionalExpression': - sortNodeArgumentValue(node, arg.consequent); - sortNodeArgumentValue(node, arg.alternate); - return; - case 'LogicalExpression': - sortNodeArgumentValue(node, arg.right); - return; - case 'ArrayExpression': - arg.elements.forEach((el) => { - sortNodeArgumentValue(node, el); - }); - return; - case 'ObjectExpression': - const isUsedByClassNamesPlugin = node.callee && node.callee.name === 'classnames'; - const isVue = node.key && node.key.type === 'VDirectiveKey'; - arg.properties.forEach((prop) => { - const propVal = isUsedByClassNamesPlugin || isVue ? prop.key : prop.value; - sortNodeArgumentValue(node, propVal); - }); - return; - case 'Property': - sortNodeArgumentValue(node, arg.key); - break; - case 'Literal': - originalClassNamesValue = arg.value; - start = arg.range[0] + 1; - end = arg.range[1] - 1; - break; - case 'TemplateElement': - originalClassNamesValue = arg.value.raw; - if (originalClassNamesValue === '') { - return; - } - start = arg.range[0]; - end = arg.range[1]; - // https://github.com/eslint/eslint/issues/13360 - // The problem is that range computation includes the backticks (`test`) - // but value.raw does not include them, so there is a mismatch. - // start/end does not include the backticks, therefore it matches value.raw. - const txt = context.getSourceCode().getText(arg); - prefix = astUtil.getTemplateElementPrefix(txt, originalClassNamesValue); - suffix = astUtil.getTemplateElementSuffix(txt, originalClassNamesValue); - originalClassNamesValue = astUtil.getTemplateElementBody(txt, prefix, suffix); - break; - } - } - - let { classNames, whitespaces, headSpace, tailSpace } = - astUtil.extractClassnamesFromValue(originalClassNamesValue); - - if (classNames.length <= 1) { - // Don't run sorting for a single or empty className - return; - } - - let orderedClassNames = order(classNames, contextFallback).split(' '); - - if (removeDuplicates) { - removeDuplicatesFromClassnamesAndWhitespaces(orderedClassNames, whitespaces, headSpace, tailSpace); - } - - // Generates the validated/sorted attribute value - let validatedClassNamesValue = ''; - for (let i = 0; i < orderedClassNames.length; i++) { - const w = whitespaces[i] ?? ''; - const cls = orderedClassNames[i]; - validatedClassNamesValue += headSpace ? `${w}${cls}` : `${cls}${w}`; - if (headSpace && tailSpace && i === orderedClassNames.length - 1) { - validatedClassNamesValue += whitespaces[whitespaces.length - 1] ?? ''; - } - } - - if (originalClassNamesValue !== validatedClassNamesValue) { - validatedClassNamesValue = prefix + validatedClassNamesValue + suffix; - context.report({ - node: node, - messageId: 'invalidOrder', - fix: function (fixer) { - return fixer.replaceTextRange([start, end], validatedClassNamesValue); - }, - }); - } - }; - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - const attributeVisitor = function (node) { - if (!astUtil.isClassAttribute(node, classRegex) || skipClassAttribute) { - return; - } - if (astUtil.isLiteralAttributeValue(node)) { - sortNodeArgumentValue(node); - } else if (node.value && node.value.type === 'JSXExpressionContainer') { - sortNodeArgumentValue(node, node.value.expression); - } - }; - - const callExpressionVisitor = function (node) { - const calleeStr = astUtil.calleeToString(node.callee); - if (callees.findIndex((name) => calleeStr === name) === -1) { - return; - } - - node.arguments.forEach((arg) => { - sortNodeArgumentValue(node, arg); - }); - }; - - const scriptVisitor = { - JSXAttribute: attributeVisitor, - TextAttribute: attributeVisitor, - CallExpression: callExpressionVisitor, - TaggedTemplateExpression: function (node) { - if (!tags.includes(node.tag.name ?? node.tag.object?.name ?? node.tag.callee?.name)) { - return; - } - - sortNodeArgumentValue(node, node.quasi); - }, - }; - const templateVisitor = { - CallExpression: callExpressionVisitor, - /* - Tagged templates inside data bindings - https://github.com/vuejs/vue/issues/9721 - */ - VAttribute: function (node) { - switch (true) { - case !astUtil.isValidVueAttribute(node, classRegex): - return; - case astUtil.isVLiteralValue(node): - sortNodeArgumentValue(node, null); - break; - case astUtil.isArrayExpression(node): - node.value.expression.elements.forEach((arg) => { - sortNodeArgumentValue(node, arg); - }); - break; - case astUtil.isObjectExpression(node): - node.value.expression.properties.forEach((prop) => { - sortNodeArgumentValue(node, prop); - }); - break; - } - }, - }; - - return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); - }, -}; diff --git a/lib/rules/enforces-negative-arbitrary-values.js b/lib/rules/enforces-negative-arbitrary-values.js deleted file mode 100644 index 12189935..00000000 --- a/lib/rules/enforces-negative-arbitrary-values.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * @fileoverview Warns about `-` prefixed classnames using arbitrary values - * @author FranΓ§ois Massart - */ -'use strict'; - -const docsUrl = require('../util/docsUrl'); -const customConfig = require('../util/customConfig'); -const astUtil = require('../util/ast'); -const groupUtil = require('../util/groupMethods'); -const getOption = require('../util/settings'); -const parserUtil = require('../util/parser'); - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -// Predefine message for use in context.report conditional. -// messageId will still be usable in tests. -const NEGATIVE_ARBITRARY_VALUE = `Arbitrary value classname '{{classname}}' should not start with a dash (-)`; - -module.exports = { - meta: { - docs: { - description: 'Warns about dash prefixed classnames using arbitrary values', - category: 'Best Practices', - recommended: true, - url: docsUrl('enforces-negative-arbitrary-values'), - }, - messages: { - negativeArbitraryValue: NEGATIVE_ARBITRARY_VALUE, - }, - fixable: null, - schema: [ - { - type: 'object', - properties: { - callees: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - ignoredKeys: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - config: { - // returned from `loadConfig()` utility - type: ['string', 'object'], - }, - tags: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - }, - }, - ], - }, - - create: function (context) { - const callees = getOption(context, 'callees'); - const skipClassAttribute = getOption(context, 'skipClassAttribute'); - const tags = getOption(context, 'tags'); - const twConfig = getOption(context, 'config'); - const classRegex = getOption(context, 'classRegex'); - - const mergedConfig = customConfig.resolve(twConfig); - - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- - - /** - * Recursive function crawling into child nodes - * @param {ASTNode} node The root node of the current parsing - * @param {ASTNode} arg The child node of node - * @returns {void} - */ - const parseForNegativeArbitraryClassNames = (node, arg = null) => { - let originalClassNamesValue = null; - if (arg === null) { - originalClassNamesValue = astUtil.extractValueFromNode(node); - } else { - switch (arg.type) { - case 'Identifier': - return; - case 'TemplateLiteral': - arg.expressions.forEach((exp) => { - parseForNegativeArbitraryClassNames(node, exp); - }); - arg.quasis.forEach((quasis) => { - parseForNegativeArbitraryClassNames(node, quasis); - }); - return; - case 'ConditionalExpression': - parseForNegativeArbitraryClassNames(node, arg.consequent); - parseForNegativeArbitraryClassNames(node, arg.alternate); - return; - case 'LogicalExpression': - parseForNegativeArbitraryClassNames(node, arg.right); - return; - case 'ArrayExpression': - arg.elements.forEach((el) => { - parseForNegativeArbitraryClassNames(node, el); - }); - return; - case 'ObjectExpression': - const isUsedByClassNamesPlugin = node.callee && node.callee.name === 'classnames'; - const isVue = node.key && node.key.type === 'VDirectiveKey'; - arg.properties.forEach((prop) => { - const propVal = isUsedByClassNamesPlugin || isVue ? prop.key : prop.value; - parseForNegativeArbitraryClassNames(node, propVal); - }); - return; - case 'Property': - parseForNegativeArbitraryClassNames(node, arg.key); - return; - case 'Literal': - originalClassNamesValue = arg.value; - break; - case 'TemplateElement': - originalClassNamesValue = arg.value.raw; - if (originalClassNamesValue === '') { - return; - } - break; - } - } - - let { classNames } = astUtil.extractClassnamesFromValue(originalClassNamesValue); - - const detected = classNames.filter((cls) => { - const suffix = groupUtil.getSuffix(cls, mergedConfig.separator); - const negArbitraryValRegEx = - /^\-((inset|scale)(\-(y|x))?|top|right|bottom|left|top|z|order|(scroll\-)?m(y|x|t|r|l|b)?|(skew|space|translate)\-(y|x)|rotate|tracking|indent|(backdrop\-)?hue\-rotate)\-\[.*\]$/i; - return negArbitraryValRegEx.test(suffix); - }); - - detected.forEach((className) => { - context.report({ - node, - messageId: 'negativeArbitraryValue', - data: { - classname: className, - }, - }); - }); - }; - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - const attributeVisitor = function (node) { - if (!astUtil.isClassAttribute(node, classRegex) || skipClassAttribute) { - return; - } - if (astUtil.isLiteralAttributeValue(node)) { - parseForNegativeArbitraryClassNames(node); - } else if (node.value && node.value.type === 'JSXExpressionContainer') { - parseForNegativeArbitraryClassNames(node, node.value.expression); - } - }; - - const callExpressionVisitor = function (node) { - const calleeStr = astUtil.calleeToString(node.callee); - if (callees.findIndex((name) => calleeStr === name) === -1) { - return; - } - node.arguments.forEach((arg) => { - parseForNegativeArbitraryClassNames(node, arg); - }); - }; - - const scriptVisitor = { - JSXAttribute: attributeVisitor, - TextAttribute: attributeVisitor, - CallExpression: callExpressionVisitor, - TaggedTemplateExpression: function (node) { - if (!tags.includes(node.tag.name ?? node.tag.object?.name ?? node.tag.callee?.name)) { - return; - } - parseForNegativeArbitraryClassNames(node, node.quasi); - }, - }; - - const templateVisitor = { - CallExpression: callExpressionVisitor, - /* - Tagged templates inside data bindings - https://github.com/vuejs/vue/issues/9721 - */ - VAttribute: function (node) { - switch (true) { - case !astUtil.isValidVueAttribute(node, classRegex): - return; - case astUtil.isVLiteralValue(node): - parseForNegativeArbitraryClassNames(node); - break; - case astUtil.isArrayExpression(node): - node.value.expression.elements.forEach((arg) => { - parseForNegativeArbitraryClassNames(node, arg); - }); - break; - case astUtil.isObjectExpression(node): - node.value.expression.properties.forEach((prop) => { - parseForNegativeArbitraryClassNames(node, prop); - }); - break; - } - }, - }; - - return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); - }, -}; diff --git a/lib/rules/enforces-shorthand.js b/lib/rules/enforces-shorthand.js deleted file mode 100644 index b147bfa3..00000000 --- a/lib/rules/enforces-shorthand.js +++ /dev/null @@ -1,540 +0,0 @@ -/** - * @fileoverview Avoid using multiple Tailwind CSS classnames when not required (e.g. "mx-3 my-3" could be replaced by "m-3") - * @author FranΓ§ois Massart - */ -'use strict'; - -const docsUrl = require('../util/docsUrl'); -const defaultGroups = require('../config/groups').groups; -const customConfig = require('../util/customConfig'); -const astUtil = require('../util/ast'); -const groupUtil = require('../util/groupMethods'); -const getOption = require('../util/settings'); -const parserUtil = require('../util/parser'); - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -// Predefine message for use in context.report conditional. -// messageId will still be usable in tests. -const SHORTHAND_CANDIDATE_CLASSNAMES_DETECTED_MSG = `Classnames '{{classnames}}' could be replaced by the '{{shorthand}}' shorthand!`; - -module.exports = { - meta: { - docs: { - description: 'Enforces the usage of shorthand Tailwind CSS classnames', - category: 'Best Practices', - recommended: true, - url: docsUrl('enforces-shorthand'), - }, - messages: { - shorthandCandidateDetected: SHORTHAND_CANDIDATE_CLASSNAMES_DETECTED_MSG, - }, - fixable: 'code', - schema: [ - { - type: 'object', - properties: { - callees: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - ignoredKeys: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - config: { - // returned from `loadConfig()` utility - type: ['string', 'object'], - }, - tags: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - }, - }, - ], - }, - - create: function (context) { - const callees = getOption(context, 'callees'); - const skipClassAttribute = getOption(context, 'skipClassAttribute'); - const tags = getOption(context, 'tags'); - const twConfig = getOption(context, 'config'); - const classRegex = getOption(context, 'classRegex'); - - const mergedConfig = customConfig.resolve(twConfig); - - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- - - // These are shorthand candidates that do not share the same parent type - const complexEquivalences = [ - { - needles: ['overflow-hidden', 'text-ellipsis', 'whitespace-nowrap'], - shorthand: 'truncate', - mode: 'exact', - }, - { - needles: ['w-', 'h-'], - shorthand: 'size-', - mode: 'value', - }, - ]; - - // Init assets - const targetProperties = { - Layout: ['Overflow', 'Overscroll Behavior', 'Top / Right / Bottom / Left'], - 'Flexbox & Grid': ['Gap'], - Spacing: ['Padding', 'Margin'], - Sizing: ['Width', 'Height'], - Borders: ['Border Radius', 'Border Width', 'Border Color'], - Tables: ['Border Spacing'], - Transforms: ['Scale'], - Typography: ['Text Overflow', 'Whitespace'], - }; - - // We don't want to affect other rules by object reference - const cloned = JSON.parse(JSON.stringify(defaultGroups)); - const targetGroups = cloned.filter((g) => Object.keys(targetProperties).includes(g.type)); - targetGroups.forEach((g) => { - // Without using the clone, other rules would be affected by this `filter()` - g.members = g.members.filter((sub) => targetProperties[g.type].includes(sub.type)); - }); - - /** - * Retrieve the main part of a classname base on its shorthand scope - * @param {Object} targetGroups A specific subset of the groups - * @param {String} parentType The name of the parent e.g. 'Border Radius' - * @param {String} shorthand The searched shorthand e.g. 'all', 'y', 't', 'tr' - * @returns - */ - const getBodyByShorthand = (targetGroups, parentType, shorthand) => { - const findByMemberType = (obj) => obj.members.find((m) => m.type === parentType); - const mainGroup = targetGroups.find(findByMemberType); - if (!mainGroup) { - return ''; - } - const typeGroup = mainGroup.members.find((m) => m.type === parentType); - // const typeGroup = mainGroup.find(findByMemberType); - if (!typeGroup) { - return ''; - } - const type = typeGroup.members.find((m) => m.shorthand === shorthand); - return !type ? '' : type.body; - }; - - /** - * Parse the classnames and report found shorthand candidates - * @param {ASTNode} node The root node of the current parsing - * @param {ASTNode} arg The child node of node - * @returns {void} - */ - const parseForShorthandCandidates = (node, arg = null) => { - let originalClassNamesValue = null; - let start = null; - let end = null; - let prefix = ''; - let suffix = ''; - const troubles = []; - if (arg === null) { - originalClassNamesValue = astUtil.extractValueFromNode(node); - const range = astUtil.extractRangeFromNode(node); - if (node.type === 'TextAttribute') { - start = range[0]; - end = range[1]; - } else { - start = range[0] + 1; - end = range[1] - 1; - } - } else { - switch (arg.type) { - case 'Identifier': - return; - case 'TemplateLiteral': - arg.expressions.forEach((exp) => { - parseForShorthandCandidates(node, exp); - }); - arg.quasis.forEach((quasis) => { - parseForShorthandCandidates(node, quasis); - }); - return; - case 'ConditionalExpression': - parseForShorthandCandidates(node, arg.consequent); - parseForShorthandCandidates(node, arg.alternate); - return; - case 'LogicalExpression': - parseForShorthandCandidates(node, arg.right); - return; - case 'ArrayExpression': - arg.elements.forEach((el) => { - parseForShorthandCandidates(node, el); - }); - return; - case 'ObjectExpression': - const isUsedByClassNamesPlugin = node.callee && node.callee.name === 'classnames'; - const isVue = node.key && node.key.type === 'VDirectiveKey'; - arg.properties.forEach((prop) => { - const propVal = isUsedByClassNamesPlugin || isVue ? prop.key : prop.value; - parseForShorthandCandidates(node, propVal); - }); - return; - case 'Property': - parseForShorthandCandidates(node, arg.key); - return; - - case 'Literal': - originalClassNamesValue = arg.value; - start = arg.range[0] + 1; - end = arg.range[1] - 1; - break; - case 'TemplateElement': - originalClassNamesValue = arg.value.raw; - if (originalClassNamesValue === '') { - return; - } - start = arg.range[0]; - end = arg.range[1]; - // https://github.com/eslint/eslint/issues/13360 - // The problem is that range computation includes the backticks (`test`) - // but value.raw does not include them, so there is a mismatch. - // start/end does not include the backticks, therefore it matches value.raw. - const txt = context.getSourceCode().getText(arg); - prefix = astUtil.getTemplateElementPrefix(txt, originalClassNamesValue); - suffix = astUtil.getTemplateElementSuffix(txt, originalClassNamesValue); - originalClassNamesValue = astUtil.getTemplateElementBody(txt, prefix, suffix); - break; - } - } - - let { classNames, whitespaces, headSpace, tailSpace } = - astUtil.extractClassnamesFromValue(originalClassNamesValue); - - if (classNames.length <= 1) { - // Don't run sorting for a single or empty className - return; - } - - const parsed = []; - - classNames.forEach((className, index) => { - parsed.push(groupUtil.parseClassname(className, targetGroups, mergedConfig, index)); - }); - - const validated = []; - - // Handle sets of classnames with different parent types - let remaining = parsed; - for (const { needles: inputSet, shorthand: outputClassname, mode } of complexEquivalences) { - if (remaining.length < inputSet.length) { - continue; - } - - // Matching classes - const parsedElementsInInputSet = remaining.filter((remainingClass) => { - if (mode === 'exact') { - // Test if the name contains the target class, eg. 'text-ellipsis' inside 'md:text-ellipsis'... - return inputSet.some((inputClass) => remainingClass.name.includes(inputClass)); - } - // Test if the body of the class matches, eg. 'h-' inside 'h-10' - if (mode === 'value') { - const bodyMatch = inputSet.some((inputClassPattern) => inputClassPattern === remainingClass.body); - if ([undefined, null].includes(mergedConfig.theme.size)) { - return false; - } - // w-screen + h-screen β‰  size-screen (Issue #307) - const sizeKeys = Object.keys(mergedConfig.theme.size); - const isSize = ['w-', 'h-'].includes(remainingClass.body); - const isValidSize = sizeKeys.includes(remainingClass.value); - const wValue = mergedConfig.theme.width[remainingClass.value]; - const hValue = mergedConfig.theme.height[remainingClass.value]; - const sizeValue = mergedConfig.theme.size[remainingClass.value]; - const fullMatch = wValue === hValue && wValue === sizeValue; - return bodyMatch && !(isSize && !isValidSize && !fullMatch); - } - }); - - const variantGroups = new Map(); - parsedElementsInInputSet.forEach((o) => { - const val = mode === 'value' ? o.value : ''; - const v = `${o.variants}${o.important ? '!' : ''}${val}`; - if (!variantGroups.has(v)) { - variantGroups.set( - v, - parsedElementsInInputSet.filter( - (c) => c.variants === o.variants && c.important === o.important && (val === '' || c.value === val) - ) - ); - } - }); - const validKeys = new Set(); - variantGroups.forEach((classes, key) => { - let skip = false; - // Make sure all required classes for the shorthand are present - if (classes.length < inputSet.length) { - skip = true; - } - // Make sure the classes share all the single/shared/same value - if (mode === 'value' && new Set(classes.map((p) => p.value)).size !== 1) { - skip = true; - } - if (!skip) { - validKeys.add(key); - } - }); - validKeys.forEach((k) => { - const candidates = variantGroups.get(k); - const index = candidates[0].index; - const variants = candidates[0].variants; - const important = candidates[0].important ? '!' : ''; - const classValue = mode === 'value' ? candidates[0].value : ''; - - const patchedClassname = `${variants}${important}${mergedConfig.prefix}${outputClassname}${classValue}`; - troubles.push([candidates.map((c) => `${c.name}`), patchedClassname]); - - const validatedClassname = groupUtil.parseClassname(patchedClassname, targetGroups, mergedConfig, index); - validated.push(validatedClassname); - - remaining = remaining.filter((p) => !candidates.includes(p)); - }); - } - - // Handle sets of classnames with the same parent type - // Each group parentType - const checkedGroups = []; - remaining.forEach((classname, idx, arr) => { - // Valid candidate - if (classname.parentType === '') { - validated.push(classname); - } else if (!checkedGroups.includes(classname.parentType)) { - checkedGroups.push(classname.parentType); - const sameType = remaining.filter((cls) => cls.parentType === classname.parentType); - // Comparing same parentType classnames - const checkedVariantsValue = []; - sameType.forEach((cls) => { - const key = cls.variants + (cls.important ? '!' : '') + cls.value; - if (!checkedVariantsValue.includes(key)) { - checkedVariantsValue.push(key); - const sameVariantAndValue = sameType.filter((v) => { - return !(v.variants !== cls.variants || v.value !== cls.value || v.important !== cls.important); - }); - if (sameVariantAndValue.length === 1) { - validated.push(cls); - } else if (sameVariantAndValue.length) { - const supportCorners = ['Border Radius'].includes(classname.parentType); - const hasTL = - supportCorners && sameVariantAndValue.some((c) => ['tl', 't', 'all'].includes(c.shorthand)); - const hasTR = - supportCorners && sameVariantAndValue.some((c) => ['tr', 't', 'all'].includes(c.shorthand)); - const hasBR = - supportCorners && sameVariantAndValue.some((c) => ['br', 'b', 'all'].includes(c.shorthand)); - const hasBL = - supportCorners && sameVariantAndValue.some((c) => ['bl', 'b', 'all'].includes(c.shorthand)); - const hasT = sameVariantAndValue.some((c) => c.shorthand === 't') || (hasTL && hasTR); - const hasR = sameVariantAndValue.some((c) => c.shorthand === 'r') || (hasTR && hasBR); - const hasB = sameVariantAndValue.some((c) => c.shorthand === 'b') || (hasBL && hasBR); - const hasL = sameVariantAndValue.some((c) => c.shorthand === 'l') || (hasTL && hasBL); - const hasX = sameVariantAndValue.some((c) => c.shorthand === 'x') || (hasL && hasR); - const hasY = sameVariantAndValue.some((c) => c.shorthand === 'y') || (hasT && hasB); - const hasAllProp = sameVariantAndValue.some((c) => c.shorthand === 'all'); - const hasAllPropNoCorner = hasY && hasX; - const hasAllPropWithCorners = (hasL && hasR) || (hasT && hasB); - const hasAllEquivalent = !supportCorners ? hasAllPropNoCorner : hasAllPropWithCorners; - const hasAll = hasAllProp || hasAllEquivalent; - const important = cls.important ? '!' : ''; - const isNegative = ('' + cls.value).substring(0, 1) === '-'; - const minus = isNegative ? '-' : ''; - const absoluteVal = isNegative ? ('' + cls.value).substring(1) : cls.value; - - if (hasAll) { - const all = getBodyByShorthand(targetGroups, classname.parentType, 'all'); - const val = absoluteVal.length ? '-' + absoluteVal : ''; - const patchedName = `${cls.variants}${important}${minus}${mergedConfig.prefix}${all}${val}`; - troubles.push([sameVariantAndValue.map((c) => c.name), patchedName]); - cls.name = patchedName; - cls.shorthand = 'all'; - validated.push(cls); - } else if (hasY || hasX) { - const xOrY = hasX ? 'x' : 'y'; - const xOrYType = getBodyByShorthand(targetGroups, classname.parentType, xOrY); - const patchedName = `${cls.variants}${important}${minus}${mergedConfig.prefix}${xOrYType}${absoluteVal.length ? '-' + absoluteVal : '' - }`; - const toBeReplaced = sameVariantAndValue - .filter((c) => { - const candidates = hasX ? ['l', 'r'] : ['t', 'b']; - return candidates.includes(c.shorthand); - }) - .map((c) => c.name); - const toBeKept = sameVariantAndValue.filter((c) => { - const candidates = hasY ? ['l', 'r'] : ['t', 'b']; - return candidates.includes(c.shorthand); - }); - - troubles.push([toBeReplaced, patchedName]); - let replaced = false; - sameVariantAndValue.forEach((ref, i) => { - if (toBeKept.find((k) => k.name === ref.name)) { - validated.push(ref); - } else if (!replaced) { - replaced = true; - const cloned = JSON.parse(JSON.stringify(ref)); - cloned.name = patchedName; - cloned.shorthand = xOrY; - validated.push(cloned); - } - }); - } else if (supportCorners && (hasT || hasR || hasB || hasL)) { - const side = hasT ? 't' : hasR ? 'r' : hasB ? 'b' : 'l'; - const sideBody = getBodyByShorthand(targetGroups, classname.parentType, side); - const val = absoluteVal.length ? '-' + absoluteVal : ''; - const patchedName = `${cls.variants}${important}${minus}${mergedConfig.prefix}${sideBody}${val}`; - const toBeReplaced = sameVariantAndValue - .filter((c) => { - const candidates = hasT ? ['tl', 'tr'] : hasR ? ['tr', 'br'] : hasB ? ['bl', 'br'] : ['tl', 'bl']; - return candidates.includes(c.shorthand); - }) - .map((c) => c.name); - const toBeKept = sameVariantAndValue.filter((c) => { - const candidates = hasT ? ['bl', 'br'] : hasR ? ['tl', 'bl'] : hasB ? ['tl', 'tr'] : ['tr', 'br']; - return candidates.includes(c.shorthand); - }); - - troubles.push([toBeReplaced, patchedName]); - let replaced = false; - sameVariantAndValue.forEach((ref, i) => { - if (toBeKept.find((k) => k.name === ref.name)) { - validated.push(ref); - } else if (!replaced) { - replaced = true; - const cloned = JSON.parse(JSON.stringify(ref)); - cloned.name = patchedName; - cloned.shorthand = side; - validated.push(cloned); - } - }); - } else { - validated.push(...sameVariantAndValue); - } - } - } - }); - } - }); - - // Try to keep the original order - validated.sort((a, b) => (a.index < b.index ? -1 : +1)); - - // Generates the validated attribute value - const union = validated.map((val) => val.leading + val.name + val.trailing); - - let validatedClassNamesValue = ''; - - // Generates the validated attribute value - if (union.length === 1) { - validatedClassNamesValue += headSpace ? whitespaces[0] : ''; - validatedClassNamesValue += union[0]; - validatedClassNamesValue += tailSpace ? whitespaces[whitespaces.length - 1] : ''; - } else { - for (let i = 0; i < union.length; i++) { - const isLast = i === union.length - 1; - const w = whitespaces[i] ?? ''; - const cls = union[i]; - validatedClassNamesValue += headSpace ? `${w}${cls}` : isLast ? `${cls}` : `${cls}${w}`; - if (tailSpace && isLast) { - validatedClassNamesValue += whitespaces[whitespaces.length - 1] ?? ''; - } - } - } - - troubles.forEach((issue) => { - if (originalClassNamesValue !== validatedClassNamesValue) { - validatedClassNamesValue = prefix + validatedClassNamesValue + suffix; - context.report({ - node: node, - messageId: 'shorthandCandidateDetected', - data: { - classnames: issue[0].join(', '), - shorthand: issue[1], - }, - fix: function (fixer) { - return fixer.replaceTextRange([start, end], validatedClassNamesValue); - }, - }); - } - }); - }; - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - const attributeVisitor = function (node) { - if (!astUtil.isClassAttribute(node, classRegex) || skipClassAttribute) { - return; - } - if (astUtil.isLiteralAttributeValue(node)) { - parseForShorthandCandidates(node); - } else if (node.value && node.value.type === 'JSXExpressionContainer') { - parseForShorthandCandidates(node, node.value.expression); - } - }; - - const callExpressionVisitor = function (node) { - const calleeStr = astUtil.calleeToString(node.callee); - if (callees.findIndex((name) => calleeStr === name) === -1) { - return; - } - - node.arguments.forEach((arg) => { - parseForShorthandCandidates(node, arg); - }); - }; - - const scriptVisitor = { - JSXAttribute: attributeVisitor, - TextAttribute: attributeVisitor, - CallExpression: callExpressionVisitor, - TaggedTemplateExpression: function (node) { - if (!tags.includes(node.tag.name ?? node.tag.object?.name ?? node.tag.callee?.name)) { - return; - } - - parseForShorthandCandidates(node, node.quasi); - }, - }; - - const templateVisitor = { - CallExpression: callExpressionVisitor, - /* - Tagged templates inside data bindings - https://github.com/vuejs/vue/issues/9721 - */ - VAttribute: function (node) { - switch (true) { - case !astUtil.isValidVueAttribute(node, classRegex): - return; - case astUtil.isVLiteralValue(node): - parseForShorthandCandidates(node); - break; - case astUtil.isArrayExpression(node): - node.value.expression.elements.forEach((arg) => { - parseForShorthandCandidates(node, arg); - }); - break; - case astUtil.isObjectExpression(node): - node.value.expression.properties.forEach((prop) => { - parseForShorthandCandidates(node, prop); - }); - break; - } - }, - }; - - return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); - }, -}; diff --git a/lib/rules/migration-from-tailwind-2.js b/lib/rules/migration-from-tailwind-2.js deleted file mode 100644 index 5de0f0f7..00000000 --- a/lib/rules/migration-from-tailwind-2.js +++ /dev/null @@ -1,329 +0,0 @@ -/** - * @fileoverview Detect obsolete classnames when upgrading to Tailwind CSS v3 - * @author FranΓ§ois Massart - */ -'use strict'; - -const docsUrl = require('../util/docsUrl'); -const customConfig = require('../util/customConfig'); -const astUtil = require('../util/ast'); -const groupUtil = require('../util/groupMethods'); -const getOption = require('../util/settings'); -const parserUtil = require('../util/parser'); - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -// Predefine message for use in context.report conditional. -// messageId will still be usable in tests. -const CLASSNAME_NOT_NEEDED_MSG = `Classname '{{classnames}}' is not needed in Tailwind CSS v3!`; -const CLASSNAMES_NOT_NEEDED_MSG = `Classnames '{{classnames}}' are not needed in Tailwind CSS v3!`; -const CLASSNAME_CHANGED_MSG = `Classname '{{deprecated}}' should be updated to '{{updated}}' in Tailwind CSS v3!`; -const OPACITY_CLASS_DEPRECATED_MSG = `Classname '{{classname}}' should be replaced by an opacity suffix (eg. '/{{value}}')`; - -module.exports = { - meta: { - docs: { - description: 'Detect obsolete classnames when upgrading to Tailwind CSS v3', - category: 'Possible Errors', - recommended: true, - url: docsUrl('migration-from-tailwind-2'), - }, - messages: { - classnameNotNeeded: CLASSNAME_NOT_NEEDED_MSG, - classnamesNotNeeded: CLASSNAMES_NOT_NEEDED_MSG, - classnameChanged: CLASSNAME_CHANGED_MSG, - classnameOpacityDeprecated: OPACITY_CLASS_DEPRECATED_MSG, - }, - fixable: 'code', - schema: [ - { - type: 'object', - properties: { - callees: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - ignoredKeys: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - config: { - // returned from `loadConfig()` utility - type: ['string', 'object'], - }, - tags: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - }, - }, - ], - }, - - create: function (context) { - const callees = getOption(context, 'callees'); - const skipClassAttribute = getOption(context, 'skipClassAttribute'); - const tags = getOption(context, 'tags'); - const twConfig = getOption(context, 'config'); - const classRegex = getOption(context, 'classRegex'); - - const mergedConfig = customConfig.resolve(twConfig); - - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- - - /** - * Recursive function crawling into child nodes - * @param {ASTNode} node The root node of the current parsing - * @param {ASTNode} arg The child node of node - * @returns {void} - */ - const parseForObsoleteClassNames = (node, arg = null) => { - let originalClassNamesValue = null; - let start = null; - let end = null; - let prefix = ''; - let suffix = ''; - if (arg === null) { - originalClassNamesValue = astUtil.extractValueFromNode(node); - const range = astUtil.extractRangeFromNode(node); - if (node.type === 'TextAttribute') { - start = range[0]; - end = range[1]; - } else { - start = range[0] + 1; - end = range[1] - 1; - } - } else { - switch (arg.type) { - case 'Identifier': - return; - case 'TemplateLiteral': - arg.expressions.forEach((exp) => { - parseForObsoleteClassNames(node, exp); - }); - arg.quasis.forEach((quasis) => { - parseForObsoleteClassNames(node, quasis); - }); - return; - case 'ConditionalExpression': - parseForObsoleteClassNames(node, arg.consequent); - parseForObsoleteClassNames(node, arg.alternate); - return; - case 'LogicalExpression': - parseForObsoleteClassNames(node, arg.right); - return; - case 'ArrayExpression': - arg.elements.forEach((el) => { - parseForObsoleteClassNames(node, el); - }); - return; - case 'ObjectExpression': - arg.properties.forEach((prop) => { - parseForObsoleteClassNames(node, prop.key); - }); - return; - case 'Property': - parseForObsoleteClassNames(node, arg.key); - return; - case 'Literal': - originalClassNamesValue = arg.value; - start = arg.range[0] + 1; - end = arg.range[1] - 1; - break; - case 'TemplateElement': - originalClassNamesValue = arg.value.raw; - if (originalClassNamesValue === '') { - return; - } - start = arg.range[0]; - end = arg.range[1]; - // https://github.com/eslint/eslint/issues/13360 - // The problem is that range computation includes the backticks (`test`) - // but value.raw does not include them, so there is a mismatch. - // start/end does not include the backticks, therefore it matches value.raw. - const txt = context.getSourceCode().getText(arg); - prefix = astUtil.getTemplateElementPrefix(txt, originalClassNamesValue); - suffix = astUtil.getTemplateElementSuffix(txt, originalClassNamesValue); - originalClassNamesValue = astUtil.getTemplateElementBody(txt, prefix, suffix); - break; - } - } - - let { classNames, whitespaces, headSpace, tailSpace } = - astUtil.extractClassnamesFromValue(originalClassNamesValue); - - const notNeeded = []; - const outdated = []; - const deprecatedBgOpacity = []; - const filtered = classNames.filter((cls) => { - const suffix = groupUtil.getSuffix(cls, mergedConfig.separator); - if (/^((backdrop\-)?(filter|transform))$/i.test(suffix)) { - notNeeded.push(cls); - return false; - } - let overflowRes = /^overflow\-(?clip|ellipsis)$/i.exec(suffix); - if (overflowRes && overflowRes.groups && overflowRes.groups.value) { - outdated.push([cls, cls.replace(/overflow\-(clip|ellipsis)$/i, `text-${overflowRes.groups.value}`)]); - } - let growShrinkRes = /flex\-(?grow|shrink)(\-(?${flexVal}))?/i.exec(suffix); - if (growShrinkRes && growShrinkRes.groups && growShrinkRes.groups.prop) { - const prop = growShrinkRes.groups.prop; - const flexVal = growShrinkRes.groups.flexVal; - const optionalVal = flexVal ? `\-${flexVal}` : ''; - const fixRegex = new RegExp(`flex\-${prop}${optionalVal}`); - outdated.push([cls, cls.replace(fixRegex, `${prop}${flexVal ? '-' + flexVal : ''}`)]); - } - let boxRes = /^decoration\-(?clone|slice)$/i.exec(suffix); - if (boxRes && boxRes.groups && boxRes.groups.value) { - const boxVal = boxRes.groups.value; - const fixRegex = new RegExp(`decoration\-${boxVal}`); - outdated.push([cls, cls.replace(fixRegex, `box-decoration\-${boxVal}`)]); - } - let bgOpacityRes = /^(bg|border|ring)\-opacity\-(?\d{1,})$/i.exec(suffix); - if (bgOpacityRes && bgOpacityRes.groups && bgOpacityRes.groups.value) { - const opacityVal = bgOpacityRes.groups.value; - deprecatedBgOpacity.push([cls, opacityVal]); - } - let placeholderRes = /^placeholder\-(?.{1,})$/i.exec(suffix); - if (placeholderRes && placeholderRes.groups && placeholderRes.groups.value) { - const placeholderVal = placeholderRes.groups.value; - const fixPlaceholderRegex = new RegExp(`placeholder\-${placeholderVal}$`); - outdated.push([cls, cls.replace(fixPlaceholderRegex, `placeholder:text\-${placeholderVal}`)]); - } - return true; - }); - - if (notNeeded.length) { - let validatedClassNamesValue = ''; - for (let i = 0; i < filtered.length; i++) { - const isLast = i === filtered.length - 1; - const w = whitespaces[i] ?? ''; - const cls = filtered[i]; - validatedClassNamesValue += headSpace ? `${w}${cls}` : isLast ? `${cls}` : `${cls}${w}`; - if (headSpace && tailSpace && isLast) { - validatedClassNamesValue += whitespaces[whitespaces.length - 1] ?? ''; - } - } - validatedClassNamesValue = prefix + validatedClassNamesValue + suffix; - context.report({ - node, - messageId: notNeeded.length === 1 ? 'classnameNotNeeded' : 'classnamesNotNeeded', - data: { - classnames: notNeeded.join(', '), - }, - fix: function (fixer) { - return fixer.replaceTextRange([start, end], validatedClassNamesValue); - }, - }); - } - - outdated.forEach((outdatedClass) => { - let validatedClassNamesValue = ''; - for (let i = 0; i < filtered.length; i++) { - const w = whitespaces[i] ?? ''; - const cls = filtered[i]; - validatedClassNamesValue += headSpace ? `${w}${cls}` : `${cls}${w}`; - if (headSpace && tailSpace && i === filtered.length - 1) { - validatedClassNamesValue += whitespaces[whitespaces.length - 1] ?? ''; - } - } - validatedClassNamesValue = - prefix + validatedClassNamesValue.replace(outdatedClass[0], outdatedClass[1]) + suffix; - context.report({ - node, - messageId: 'classnameChanged', - data: { - deprecated: outdatedClass[0], - updated: outdatedClass[1], - }, - fix: function (fixer) { - return fixer.replaceTextRange([start, end], validatedClassNamesValue); - }, - }); - }); - deprecatedBgOpacity.forEach((bgClass) => { - context.report({ - node, - messageId: 'classnameOpacityDeprecated', - data: { - classname: bgClass[0], - value: bgClass[1], - }, - }); - }); - }; - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - const attributeVisitor = function (node) { - if (!astUtil.isClassAttribute(node, classRegex) || skipClassAttribute) { - return; - } - if (astUtil.isLiteralAttributeValue(node)) { - parseForObsoleteClassNames(node); - } else if (node.value && node.value.type === 'JSXExpressionContainer') { - parseForObsoleteClassNames(node, node.value.expression); - } - }; - - const callExpressionVisitor = function (node) { - const calleeStr = astUtil.calleeToString(node.callee); - if (callees.findIndex((name) => calleeStr === name) === -1) { - return; - } - node.arguments.forEach((arg) => { - parseForObsoleteClassNames(node, arg); - }); - }; - - const scriptVisitor = { - JSXAttribute: attributeVisitor, - TextAttribute: attributeVisitor, - CallExpression: callExpressionVisitor, - TaggedTemplateExpression: function (node) { - if (!tags.includes(node.tag.name ?? node.tag.object?.name ?? node.tag.callee?.name)) { - return; - } - parseForObsoleteClassNames(node, node.quasi); - }, - }; - - const templateVisitor = { - CallExpression: callExpressionVisitor, - /* - Tagged templates inside data bindings - https://github.com/vuejs/vue/issues/9721 - */ - VAttribute: function (node) { - switch (true) { - case !astUtil.isValidVueAttribute(node, classRegex): - return; - case astUtil.isVLiteralValue(node): - parseForObsoleteClassNames(node); - break; - case astUtil.isArrayExpression(node): - node.value.expression.elements.forEach((arg) => { - parseForObsoleteClassNames(node, arg); - }); - break; - case astUtil.isObjectExpression(node): - node.value.expression.properties.forEach((prop) => { - parseForObsoleteClassNames(node, prop); - }); - break; - } - }, - }; - - return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); - }, -}; diff --git a/lib/rules/no-arbitrary-value.js b/lib/rules/no-arbitrary-value.js deleted file mode 100644 index 71cf4595..00000000 --- a/lib/rules/no-arbitrary-value.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * @fileoverview Forbid using arbitrary values in classnames - * @author FranΓ§ois Massart - */ -'use strict'; - -const docsUrl = require('../util/docsUrl'); -const customConfig = require('../util/customConfig'); -const astUtil = require('../util/ast'); -const groupUtil = require('../util/groupMethods'); -const getOption = require('../util/settings'); -const parserUtil = require('../util/parser'); - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -// Predefine message for use in context.report conditional. -// messageId will still be usable in tests. -const ARBITRARY_VALUE_DETECTED_MSG = `Arbitrary value detected in '{{classname}}'`; - -module.exports = { - meta: { - docs: { - description: 'Forbid using arbitrary values in classnames', - category: 'Best Practices', - recommended: false, - url: docsUrl('no-arbitrary-value'), - }, - messages: { - arbitraryValueDetected: ARBITRARY_VALUE_DETECTED_MSG, - }, - fixable: null, - schema: [ - { - type: 'object', - properties: { - callees: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - ignoredKeys: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - config: { - // returned from `loadConfig()` utility - type: ['string', 'object'], - }, - tags: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - }, - }, - ], - }, - - create: function (context) { - const callees = getOption(context, 'callees'); - const skipClassAttribute = getOption(context, 'skipClassAttribute'); - const tags = getOption(context, 'tags'); - const twConfig = getOption(context, 'config'); - const classRegex = getOption(context, 'classRegex'); - - const mergedConfig = customConfig.resolve(twConfig); - - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- - - /** - * Recursive function crawling into child nodes - * @param {ASTNode} node The root node of the current parsing - * @param {ASTNode} arg The child node of node - * @returns {void} - */ - const parseForArbitraryValues = (node, arg = null) => { - let originalClassNamesValue = null; - if (arg === null) { - originalClassNamesValue = astUtil.extractValueFromNode(node); - } else { - switch (arg.type) { - case 'Identifier': - return; - case 'TemplateLiteral': - arg.expressions.forEach((exp) => { - parseForArbitraryValues(node, exp); - }); - arg.quasis.forEach((quasis) => { - parseForArbitraryValues(node, quasis); - }); - return; - case 'ConditionalExpression': - parseForArbitraryValues(node, arg.consequent); - parseForArbitraryValues(node, arg.alternate); - return; - case 'LogicalExpression': - parseForArbitraryValues(node, arg.right); - return; - case 'ArrayExpression': - arg.elements.forEach((el) => { - parseForArbitraryValues(node, el); - }); - return; - case 'ObjectExpression': - const isUsedByClassNamesPlugin = node.callee && node.callee.name === 'classnames'; - const isVue = node.key && node.key.type === 'VDirectiveKey'; - arg.properties.forEach((prop) => { - const propVal = isUsedByClassNamesPlugin || isVue ? prop.key : prop.value; - parseForArbitraryValues(node, propVal); - }); - return; - case 'Property': - parseForArbitraryValues(node, arg.key); - return; - case 'Literal': - originalClassNamesValue = arg.value; - break; - case 'TemplateElement': - originalClassNamesValue = arg.value.raw; - if (originalClassNamesValue === '') { - return; - } - break; - } - } - - let { classNames } = astUtil.extractClassnamesFromValue(originalClassNamesValue); - const forbidden = []; - classNames.forEach((cls, idx) => { - const parsed = groupUtil.parseClassname(cls, [], mergedConfig, idx); - if (/\[.*\]/i.test(parsed.body)) { - forbidden.push(parsed.name); - } - }); - - forbidden.forEach((forbiddenClass) => { - context.report({ - node, - messageId: 'arbitraryValueDetected', - data: { - classname: forbiddenClass, - }, - }); - }); - }; - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - const attributeVisitor = function (node) { - if (!astUtil.isClassAttribute(node, classRegex) || skipClassAttribute) { - return; - } - if (astUtil.isLiteralAttributeValue(node)) { - parseForArbitraryValues(node); - } else if (node.value && node.value.type === 'JSXExpressionContainer') { - parseForArbitraryValues(node, node.value.expression); - } - }; - - const callExpressionVisitor = function (node) { - const calleeStr = astUtil.calleeToString(node.callee); - if (callees.findIndex((name) => calleeStr === name) === -1) { - return; - } - node.arguments.forEach((arg) => { - parseForArbitraryValues(node, arg); - }); - }; - - const scriptVisitor = { - JSXAttribute: attributeVisitor, - TextAttribute: attributeVisitor, - CallExpression: callExpressionVisitor, - TaggedTemplateExpression: function (node) { - if (!tags.includes(node.tag.name ?? node.tag.object?.name ?? node.tag.callee?.name)) { - return; - } - parseForArbitraryValues(node, node.quasi); - }, - }; - - const templateVisitor = { - CallExpression: callExpressionVisitor, - /* - Tagged templates inside data bindings - https://github.com/vuejs/vue/issues/9721 - */ - VAttribute: function (node) { - switch (true) { - case !astUtil.isValidVueAttribute(node, classRegex): - return; - case astUtil.isVLiteralValue(node): - parseForArbitraryValues(node, null); - break; - case astUtil.isArrayExpression(node): - node.value.expression.elements.forEach((arg) => { - parseForArbitraryValues(node, arg); - }); - break; - case astUtil.isObjectExpression(node): - node.value.expression.properties.forEach((prop) => { - parseForArbitraryValues(node, prop); - }); - break; - } - }, - }; - - return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); - }, -}; diff --git a/lib/rules/no-contradicting-classname.js b/lib/rules/no-contradicting-classname.js deleted file mode 100644 index c7ce96c5..00000000 --- a/lib/rules/no-contradicting-classname.js +++ /dev/null @@ -1,265 +0,0 @@ -/** - * @fileoverview Avoid contradicting Tailwind CSS classnames (e.g. "w-3 w-5") - * @author FranΓ§ois Massart - */ -'use strict'; - -const docsUrl = require('../util/docsUrl'); -const defaultGroups = require('../config/groups').groups; -const customConfig = require('../util/customConfig'); -const astUtil = require('../util/ast'); -const groupUtil = require('../util/groupMethods'); -const getOption = require('../util/settings'); -const parserUtil = require('../util/parser'); - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -// Predefine message for use in context.report conditional. -// messageId will still be usable in tests. -const CONFLICTING_CLASSNAMES_DETECTED_MSG = `Classnames {{classnames}} are conflicting!`; - -module.exports = { - meta: { - docs: { - description: 'Avoid contradicting Tailwind CSS classnames (e.g. "w-3 w-5")', - category: 'Possible Errors', - recommended: true, - url: docsUrl('no-contradicting-classname'), - }, - messages: { - conflictingClassnames: CONFLICTING_CLASSNAMES_DETECTED_MSG, - }, - fixable: null, - schema: [ - { - type: 'object', - properties: { - callees: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - ignoredKeys: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - config: { - // returned from `loadConfig()` utility - type: ['string', 'object'], - }, - tags: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - }, - }, - ], - }, - - create: function (context) { - const callees = getOption(context, 'callees'); - const ignoredKeys = getOption(context, 'ignoredKeys'); - const skipClassAttribute = getOption(context, 'skipClassAttribute'); - const tags = getOption(context, 'tags'); - const twConfig = getOption(context, 'config'); - const classRegex = getOption(context, 'classRegex'); - - const mergedConfig = customConfig.resolve(twConfig); - - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- - - // Init assets before sorting - const groups = groupUtil.getGroups(defaultGroups, mergedConfig); - - /** - * Parse the classnames and report found conflicts - * @param {Array} classNames - * @param {ASTNode} node - */ - const parseForContradictingClassNames = (classNames, node) => { - // Init assets before sorting - const sorted = groupUtil.initGroupSlots(groups); - - // Move each classname inside its dedicated group - classNames.forEach((className) => { - const idx = groupUtil.getGroupIndex(className, groups, mergedConfig.separator); - if (idx > -1) { - sorted[idx].push(className); - } - }); - - // Only multiple classNames - const sortedGroups = sorted.filter((slot) => slot.length > 1); - const arbitraryPropsGroupIndex = sortedGroups.findIndex((slot) => { - const suffix = groupUtil.getSuffix(slot[0], mergedConfig.separator); - return groupUtil.getArbitraryProperty(suffix, mergedConfig.separator) !== ''; - }); - - // Sorts each groups' classnames - const ambiguousArbitraryValuesOrClasses = String.raw`(\[(.*${mergedConfig.separator}))|(^((?!:).)*$)`; - - sortedGroups.forEach((group, groupIndex) => { - const variants = []; - group.forEach((cls) => { - const prefix = groupUtil.getPrefix(cls, mergedConfig.separator); - const name = cls.substr(prefix.length); - if (groupIndex === arbitraryPropsGroupIndex) { - // Arbitrary Props - const arbitraryProp = groupUtil.getArbitraryProperty(name, mergedConfig.separator); - const identifier = prefix + arbitraryProp; - const idx = variants.findIndex((v) => identifier === v.prefix); - if (idx === -1) { - variants.push({ - prefix: identifier, - name: [name], - }); - } else { - variants[idx].name.push(name); - } - } else { - // "Regular classNames" - const rePrefix = prefix === '' ? ambiguousArbitraryValuesOrClasses : '^' + prefix; - const idx = variants.findIndex((v) => v.prefix === rePrefix); - if (idx === -1) { - variants.push({ - prefix: rePrefix, - name: [name], - }); - } else { - variants[idx].name.push(name); - } - } - }); - - // Several classNames with the same prefix - const potentialTroubles = variants.filter((v) => v.name.length > 1); - if (potentialTroubles.length) { - potentialTroubles.forEach((variantGroup) => { - const re = new RegExp(variantGroup.prefix); - const conflicting = group.filter((c) => re.test(c)); - context.report({ - node: node, - messageId: 'conflictingClassnames', - data: { - classnames: conflicting.join(', '), - }, - }); - }); - } - }); - }; - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - const attributeVisitor = function (node) { - if (!astUtil.isClassAttribute(node, classRegex) || skipClassAttribute) { - return; - } - if (astUtil.isLiteralAttributeValue(node)) { - astUtil.parseNodeRecursive(node, null, parseForContradictingClassNames, true, false, ignoredKeys); - } else if (node.value && node.value.type === 'JSXExpressionContainer') { - astUtil.parseNodeRecursive( - node, - node.value.expression, - parseForContradictingClassNames, - true, - false, - ignoredKeys - ); - } - }; - - const callExpressionVisitor = function (node) { - const calleeStr = astUtil.calleeToString(node.callee); - if (callees.findIndex((name) => calleeStr === name) === -1) { - return; - } - const allClassnamesForNode = []; - const pushClasses = (classNames, targetNode) => { - if (targetNode === null) { - // Classnames should be parsed in isolation (e.g. conditional expressions) - parseForContradictingClassNames(classNames, node); - } else { - // Gather the classes prior to validation - allClassnamesForNode.push(...classNames); - } - }; - node.arguments.forEach((arg) => { - astUtil.parseNodeRecursive(node, arg, pushClasses, true, false, ignoredKeys); - }); - parseForContradictingClassNames(allClassnamesForNode, node); - }; - - const scriptVisitor = { - JSXAttribute: attributeVisitor, - TextAttribute: attributeVisitor, - CallExpression: callExpressionVisitor, - TaggedTemplateExpression: function (node) { - if (!tags.includes(node.tag.name ?? node.tag.object?.name ?? node.tag.callee?.name)) { - return; - } - - const allClassnamesForNode = []; - const pushClasses = (classNames, targetNode) => { - if (targetNode === null) { - // Classnames should be parsed in isolation (e.g. conditional expressions) - parseForContradictingClassNames(classNames, node); - } else { - // Gather the classes prior to validation - allClassnamesForNode.push(...classNames); - } - }; - astUtil.parseNodeRecursive(node, node.quasi, pushClasses, true, false, ignoredKeys); - parseForContradictingClassNames(allClassnamesForNode, node); - }, - }; - - const templateVisitor = { - CallExpression: callExpressionVisitor, - /* - Tagged templates inside data bindings - https://github.com/vuejs/vue/issues/9721 - */ - VAttribute: function (node) { - switch (true) { - case !astUtil.isValidVueAttribute(node, classRegex): - return; - case astUtil.isVLiteralValue(node): - astUtil.parseNodeRecursive(node, null, parseForContradictingClassNames, true, false, ignoredKeys); - break; - case astUtil.isArrayExpression(node): - const allClassnamesForNode = []; - const pushClasses = (classNames, targetNode) => { - if (targetNode === null) { - // Classnames should be parsed in isolation (e.g. conditional expressions) - parseForContradictingClassNames(classNames, node); - } else { - // Gather the classes prior to validation - allClassnamesForNode.push(...classNames); - } - }; - node.value.expression.elements.forEach((el) => { - astUtil.parseNodeRecursive(node, el, pushClasses, true, false, ignoredKeys); - }); - parseForContradictingClassNames(allClassnamesForNode, node); - break; - case astUtil.isObjectExpression(node): - node.value.expression.properties.forEach((prop) => { - astUtil.parseNodeRecursive(node, prop, parseForContradictingClassNames, false, false, ignoredKeys); - }); - break; - } - }, - }; - - return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); - }, -}; diff --git a/lib/rules/no-custom-classname.js b/lib/rules/no-custom-classname.js deleted file mode 100644 index 97216be9..00000000 --- a/lib/rules/no-custom-classname.js +++ /dev/null @@ -1,221 +0,0 @@ -/** - * @fileoverview Detect classnames which do not belong to Tailwind CSS - * @author no-custom-classname - */ -'use strict'; - -const docsUrl = require('../util/docsUrl'); -const defaultGroups = require('../config/groups').groups; -const customConfig = require('../util/customConfig'); -const astUtil = require('../util/ast'); -const groupUtil = require('../util/groupMethods'); -const getOption = require('../util/settings'); -const parserUtil = require('../util/parser'); -const getClassnamesFromCSS = require('../util/cssFiles'); -const createContextFallback = require('tailwindcss/lib/lib/setupContextUtils').createContext; -const generated = require('../util/generated'); -const escapeRegex = require('../util/regex').escapeRegex; - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -// Predefine message for use in context.report conditional. -// messageId will still be usable in tests. -const CUSTOM_CLASSNAME_DETECTED_MSG = `Classname '{{classname}}' is not a Tailwind CSS class!`; - -// Group/peer names can be arbitrarily named and are not -// generated by generateRules. Using a custom regexp to -// validate these avoids false reports. -const getGroupNameRegex = (prefix = '') => - new RegExp(`^${escapeRegex(prefix)}(group|peer)\/[\\w\\$\\#\\@\\%\\^\\&\\*\\_\\-]+$`, 'i'); - -const contextFallbackCache = new WeakMap(); - -module.exports = { - meta: { - docs: { - description: 'Detect classnames which do not belong to Tailwind CSS', - category: 'Best Practices', - recommended: false, - url: docsUrl('no-custom-classname'), - }, - messages: { - customClassnameDetected: CUSTOM_CLASSNAME_DETECTED_MSG, - }, - fixable: null, - schema: [ - { - type: 'object', - properties: { - callees: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - ignoredKeys: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - config: { - // returned from `loadConfig()` utility - type: ['string', 'object'], - }, - cssFiles: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - cssFilesRefreshRate: { - type: 'number', - // default: 5_000, - }, - tags: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - whitelist: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - }, - }, - ], - }, - - create: function (context) { - const callees = getOption(context, 'callees'); - const ignoredKeys = getOption(context, 'ignoredKeys'); - const skipClassAttribute = getOption(context, 'skipClassAttribute'); - const tags = getOption(context, 'tags'); - const twConfig = getOption(context, 'config'); - const cssFiles = getOption(context, 'cssFiles'); - const cssFilesRefreshRate = getOption(context, 'cssFilesRefreshRate'); - const whitelist = getOption(context, 'whitelist'); - const classRegex = getOption(context, 'classRegex'); - - const mergedConfig = customConfig.resolve(twConfig); - const contextFallback = // Set the created contextFallback in the cache if it does not exist yet. - ( - contextFallbackCache.has(mergedConfig) - ? contextFallbackCache - : contextFallbackCache.set(mergedConfig, createContextFallback(mergedConfig)) - ).get(mergedConfig); - - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- - - // Init assets before sorting - const groups = groupUtil.getGroups(defaultGroups, mergedConfig); - const classnamesFromFiles = getClassnamesFromCSS(cssFiles, cssFilesRefreshRate); - const groupNameRegex = getGroupNameRegex(mergedConfig.prefix); - - /** - * Parse the classnames and report found conflicts - * @param {Array} classNames - * @param {ASTNode} node - */ - const parseForCustomClassNames = (classNames, node) => { - classNames.forEach((className) => { - const gen = generated(className, contextFallback); - if (gen.length) { - return; // Lazier is faster... processing next className! - } - const idx = groupUtil.getGroupIndex(className, groups, mergedConfig.separator); - if (idx >= 0) { - return; // Lazier is faster... processing next className! - } - const whitelistIdx = groupUtil.getGroupIndex(className, whitelist, mergedConfig.separator); - if (whitelistIdx >= 0) { - return; // Lazier is faster... processing next className! - } - const fromFilesIdx = groupUtil.getGroupIndex(className, classnamesFromFiles, mergedConfig.separator); - if (fromFilesIdx >= 0) { - return; // Lazier is faster... processing next className! - } - if (groupNameRegex.test(className)) { - return; // Lazier is faster... processing next className! - } - - // No match found - context.report({ - node, - messageId: 'customClassnameDetected', - data: { - classname: className, - }, - }); - }); - }; - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - const attributeVisitor = function (node) { - if (!astUtil.isClassAttribute(node, classRegex) || skipClassAttribute) { - return; - } - if (astUtil.isLiteralAttributeValue(node)) { - astUtil.parseNodeRecursive(node, null, parseForCustomClassNames, false, false, ignoredKeys); - } else if (node.value && node.value.type === 'JSXExpressionContainer') { - astUtil.parseNodeRecursive(node, node.value.expression, parseForCustomClassNames, false, false, ignoredKeys); - } - }; - - const callExpressionVisitor = function (node) { - const calleeStr = astUtil.calleeToString(node.callee); - if (callees.findIndex((name) => calleeStr === name) === -1) { - return; - } - node.arguments.forEach((arg) => { - astUtil.parseNodeRecursive(node, arg, parseForCustomClassNames, false, false, ignoredKeys); - }); - }; - - const scriptVisitor = { - JSXAttribute: attributeVisitor, - TextAttribute: attributeVisitor, - CallExpression: callExpressionVisitor, - TaggedTemplateExpression: function (node) { - if (!tags.includes(node.tag.name ?? node.tag.object?.name ?? node.tag.callee?.name)) { - return; - } - astUtil.parseNodeRecursive(node, node.quasi, parseForCustomClassNames, false, false, ignoredKeys); - }, - }; - - const templateVisitor = { - CallExpression: callExpressionVisitor, - /* - Tagged templates inside data bindings - https://github.com/vuejs/vue/issues/9721 - */ - VAttribute: function (node) { - switch (true) { - case !astUtil.isValidVueAttribute(node, classRegex): - return; - case astUtil.isVLiteralValue(node): - astUtil.parseNodeRecursive(node, null, parseForCustomClassNames, false, false, ignoredKeys); - break; - case astUtil.isArrayExpression(node): - node.value.expression.elements.forEach((arg) => { - astUtil.parseNodeRecursive(node, arg, parseForCustomClassNames, false, false, ignoredKeys); - }); - break; - case astUtil.isObjectExpression(node): - node.value.expression.properties.forEach((prop) => { - astUtil.parseNodeRecursive(node, prop, parseForCustomClassNames, false, false, ignoredKeys); - }); - break; - } - }, - }; - - return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); - }, -}; diff --git a/lib/rules/no-unnecessary-arbitrary-value.js b/lib/rules/no-unnecessary-arbitrary-value.js deleted file mode 100644 index 58904f8a..00000000 --- a/lib/rules/no-unnecessary-arbitrary-value.js +++ /dev/null @@ -1,362 +0,0 @@ -/** - * @fileoverview Detect arbitrary classnames which have an existing equivalent preset in the configuration - * @author FranΓ§ois Massart - */ -'use strict'; - -const docsUrl = require('../util/docsUrl'); -const customConfig = require('../util/customConfig'); -const astUtil = require('../util/ast'); -const groupUtil = require('../util/groupMethods'); -const getOption = require('../util/settings'); -const parserUtil = require('../util/parser'); -const { validZeroRegEx } = require('../util/types/length'); -const defaultGroups = require('../config/groups').groups; - -// TODO get the correct value of start and end -// TODO make rule fixable when only 1 match -// TODO propose several fixes when multiple matches + priority to exact match - -//------------------------------------------------------------------------------ -// Rule Definition -//------------------------------------------------------------------------------ - -// Predefine message for use in context.report conditional. -// messageId will still be usable in tests. -const UNNECESSARY_ARBITRARY_VALUE_DETECTED_MSG = `The arbitrary class '{{classname}}' could be replaced by '{{presets}}'`; - -module.exports = { - meta: { - docs: { - description: 'Forbid using arbitrary values in classnames when an equivalent preset exists', - category: 'Best Practices', - recommended: true, - url: docsUrl('no-unnecessary-arbitrary-value'), - }, - messages: { - unnecessaryArbitraryValueDetected: UNNECESSARY_ARBITRARY_VALUE_DETECTED_MSG, - }, - fixable: 'code', - schema: [ - { - type: 'object', - properties: { - callees: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - ignoredKeys: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - config: { - // returned from `loadConfig()` utility - type: ['string', 'object'], - }, - tags: { - type: 'array', - items: { type: 'string', minLength: 0 }, - uniqueItems: true, - }, - }, - }, - ], - }, - - create: function (context) { - const callees = getOption(context, 'callees'); - const skipClassAttribute = getOption(context, 'skipClassAttribute'); - const tags = getOption(context, 'tags'); - const twConfig = getOption(context, 'config'); - const classRegex = getOption(context, 'classRegex'); - - const mergedConfig = customConfig.resolve(twConfig); - const groups = groupUtil.getGroups(defaultGroups, mergedConfig); - const configKeys = groupUtil.getGroupConfigKeys(defaultGroups); - let parentTemplateLiteral = null; - - //---------------------------------------------------------------------- - // Helpers - //---------------------------------------------------------------------- - - /** - * Recursive function crawling into child nodes - * @param {ASTNode} node The root node of the current parsing - * @param {ASTNode} arg The child node of node - * @returns {void} - */ - const parseForArbitraryValues = (node, arg = null) => { - let start = null; - let end = null; - let originalClassNamesValue = null; - if (arg === null) { - originalClassNamesValue = astUtil.extractValueFromNode(node); - const range = astUtil.extractRangeFromNode(node); - if (node.type === 'TextAttribute') { - start = range[0]; - end = range[1]; - } else { - start = range[0] + 1; - end = range[1] - 1; - } - } else { - switch (arg.type) { - case 'Identifier': - return; - case 'TemplateLiteral': - parentTemplateLiteral = arg; - arg.expressions.forEach((exp) => { - parseForArbitraryValues(node, exp); - }); - arg.quasis.forEach((quasis) => { - parseForArbitraryValues(node, quasis); - }); - parentTemplateLiteral = null; - return; - case 'ConditionalExpression': - parseForArbitraryValues(node, arg.consequent); - parseForArbitraryValues(node, arg.alternate); - return; - case 'LogicalExpression': - parseForArbitraryValues(node, arg.right); - return; - case 'ArrayExpression': - arg.elements.forEach((el) => { - parseForArbitraryValues(node, el); - }); - return; - case 'ObjectExpression': - const isUsedByClassNamesPlugin = node.callee && node.callee.name === 'classnames'; - const isVue = node.key && node.key.type === 'VDirectiveKey'; - arg.properties.forEach((prop) => { - const propVal = isUsedByClassNamesPlugin || isVue ? prop.key : prop.value; - parseForArbitraryValues(node, propVal); - }); - return; - case 'Property': - parseForArbitraryValues(node, arg.key); - start = arg.range[0] + 1; - end = arg.range[1] - 1; - return; - case 'Literal': - originalClassNamesValue = arg.value; - start = arg.range[0] + 1; - end = arg.range[1] - 1; - break; - case 'TemplateElement': - originalClassNamesValue = arg.value.raw; - if (originalClassNamesValue === '') { - return; - } - start = arg.range[0]; - end = arg.range[1]; - if (parentTemplateLiteral) { - if (parentTemplateLiteral.range[0] === start) { - start += 1; // Skip opening backtick - } else { - start += 1; // Skip closing } - } - if (parentTemplateLiteral.range[1] === end) { - end -= 1; // Skip closing backtick - } else { - end -= 2; // Skip opening ${ - } - } - break; - } - } - - const arbitraryRegEx = /^(?.*)\[(?.*)\]$/i; - const { classNames } = astUtil.extractClassnamesFromValue(originalClassNamesValue); - const arbitraryClassnames = classNames.filter((c) => arbitraryRegEx.test(c)); - - if (arbitraryClassnames.length === 0) { - return; - } - - const unnecessaryArbitraryClasses = []; - const existingSubstitutes = []; - - arbitraryClassnames.forEach((arbitraryClass, idx) => { - const parsed = groupUtil.parseClassname(arbitraryClass, [], mergedConfig, idx); - const res = arbitraryRegEx.exec(parsed.name); - if (res && res.groups && res.groups.backBone && res.groups.arbitraryValue) { - const backBone = res.groups.backBone; - const arbitraryValue = res.groups.arbitraryValue; - const groupIdx = groupUtil.getGroupIndex(arbitraryClass, groups, mergedConfig.separator); - if ([groups[groupIdx], parsed.body, arbitraryValue].includes(undefined)) { - return false; - } - const canBeNegative = groups[groupIdx].indexOf('?') !== -1; - const isNegativeClass = parsed.body.indexOf('-') === 0; - const isNegativeValue = arbitraryValue.indexOf('-') === 0; - const configurationKey = configKeys[groupIdx]; - const configuration = mergedConfig.theme[configurationKey]; - if ([undefined, null].includes(configuration)) { - return false; - } - const configurationKeys = Object.keys(configuration); - const zeroValueWithOrWithoutUnitsPattern = new RegExp(validZeroRegEx, 'i'); - const isZeroArbitraryValue = zeroValueWithOrWithoutUnitsPattern.test(arbitraryValue); - const negativeSubstitutes = []; - const matchingConfigurationKeys = configurationKeys.filter((key) => { - const configValue = configuration[key]; - if (isZeroArbitraryValue && zeroValueWithOrWithoutUnitsPattern.test(configValue)) { - // Both config and tested values are 0 based (with or without units) - negativeSubstitutes.push(false); - return true; - } - // Negative possibilities - if (canBeNegative) { - const absoluteValue = isNegativeValue ? arbitraryValue.substring(1) : arbitraryValue; - const computedAsNegative = isNegativeClass !== isNegativeValue; - if (`${configValue}` === `${absoluteValue}`) { - negativeSubstitutes.push(computedAsNegative); - return true; - } - return false; - } - // Default - if (`${configValue}` === `${arbitraryValue}`) { - negativeSubstitutes.push(false); - return true; - } - return false; - }); - if (matchingConfigurationKeys.length) { - unnecessaryArbitraryClasses.push(parsed.name); - existingSubstitutes.push( - matchingConfigurationKeys.map((key, idx) => { - let patchedBody = backBone.substring(parsed.variants.length); - patchedBody = patchedBody.charAt(0) === '-' ? patchedBody.substring(1) : patchedBody; - const noneOrMinus = negativeSubstitutes[idx] ? '-' : ''; - if (key === 'DEFAULT') { - return parsed.variants + noneOrMinus + patchedBody.substring(0, patchedBody.length - 1); - } - return parsed.variants + noneOrMinus + patchedBody + key; - }) - ); - } - } - }); - - // TODO Group by range and bundle the fix - const fixables = {}; - unnecessaryArbitraryClasses.forEach((forbiddenClass, idx) => { - if (existingSubstitutes[idx].length === 1) { - const rangeKey = `s${start}e${end}`; - if (!fixables[rangeKey]) { - fixables[rangeKey] = []; - } - const fixer = { - unjustified: forbiddenClass, - substitute: existingSubstitutes[idx][0], - }; - fixables[rangeKey].push(fixer); - } else { - context.report({ - node, - messageId: 'unnecessaryArbitraryValueDetected', - data: { - classname: forbiddenClass, - presets: existingSubstitutes[idx].join("' or '"), - }, - }); - } - }); - Object.keys(fixables).forEach((rangeKey) => { - const batchFixes = fixables[rangeKey]; - let patched = originalClassNamesValue; - const forbiddenClasses = []; - const substitutes = []; - for (let idx = 0; idx < batchFixes.length; idx++) { - // BUG replace could affect same class with distinct variants... eg. h-0 might affect min-h-0 - const unjustified = batchFixes[idx].unjustified; - forbiddenClasses.push(unjustified); - const substitute = batchFixes[idx].substitute; - substitutes.push(substitute); - patched = patched.replace(unjustified, substitute); - } - context.report({ - node, - messageId: 'unnecessaryArbitraryValueDetected', - data: { - classname: forbiddenClasses.join(', '), - presets: substitutes.join(', '), - }, - fix: function (fixer) { - return fixer.replaceTextRange([start, end], patched); - }, - }); - }); - }; - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - const attributeVisitor = function (node) { - if (!astUtil.isClassAttribute(node, classRegex) || skipClassAttribute) { - return; - } - if (astUtil.isLiteralAttributeValue(node)) { - parseForArbitraryValues(node); - } else if (node.value && node.value.type === 'JSXExpressionContainer') { - parseForArbitraryValues(node, node.value.expression); - } - }; - - const callExpressionVisitor = function (node) { - const calleeStr = astUtil.calleeToString(node.callee); - if (callees.findIndex((name) => calleeStr === name) === -1) { - return; - } - node.arguments.forEach((arg) => { - parseForArbitraryValues(node, arg); - }); - }; - - const scriptVisitor = { - JSXAttribute: attributeVisitor, - TextAttribute: attributeVisitor, - CallExpression: callExpressionVisitor, - TaggedTemplateExpression: function (node) { - if (!tags.includes(node.tag.name)) { - return; - } - parseForArbitraryValues(node, node.quasi); - }, - }; - - const templateVisitor = { - CallExpression: callExpressionVisitor, - /* - Tagged templates inside data bindings - https://github.com/vuejs/vue/issues/9721 - */ - VAttribute: function (node) { - switch (true) { - case !astUtil.isValidVueAttribute(node, classRegex): - return; - case astUtil.isVLiteralValue(node): - parseForArbitraryValues(node, null); - break; - case astUtil.isArrayExpression(node): - node.value.expression.elements.forEach((arg) => { - parseForArbitraryValues(node, arg); - }); - break; - case astUtil.isObjectExpression(node): - node.value.expression.properties.forEach((prop) => { - parseForArbitraryValues(node, prop); - }); - break; - } - }, - }; - - return parserUtil.defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor); - }, -}; diff --git a/lib/util/ast.js b/lib/util/ast.js deleted file mode 100644 index ca01cb31..00000000 --- a/lib/util/ast.js +++ /dev/null @@ -1,389 +0,0 @@ -/** - * @fileoverview Utility functions for AST - */ - -'use strict'; - -const { separatorRegEx } = require('./regex'); -// context.parserPath -// /.../eslint-plugin-tailwindcss/node_modules/espree/espree.js -// /.../eslint-plugin-tailwindcss/node_modules/@angular-eslint/template-parser/dist/index.js - -const removeDuplicatesFromArray = require('./removeDuplicatesFromArray'); - -function calleeToString(calleeNode) { - if (calleeNode.type === 'Identifier') { - return calleeNode.name; - } - if (calleeNode.type === 'MemberExpression') { - return `${calleeNode.object.name}.${calleeNode.property.name}`; - } -} - -/** - * Find out if node is `class` or `className` - * - * @param {ASTNode} node The AST node being checked - * @param {String} classRegex Regex to test the attribute that is being checked against - * @returns {Boolean} - */ -function isClassAttribute(node, classRegex) { - if (!node.name) { - return false; - } - let name = ''; - switch (node.type) { - case 'TextAttribute': - name = node.name; - break; - case 'JSXAttribute': - if (node.name.type === 'JSXNamespacedName') { - const ns = node.name.namespace.name || ''; - name = (ns.length ? ns + ':' : '') + node.name.name.name; - } else { - name = node.name.name; - } - break; - default: - name = node.name.name; - } - return new RegExp(classRegex).test(name); -} - -/** - * Find out if node is `class` - * - * @param {ASTNode} node The AST node being checked - * @param {String} classRegex Regex to test the attribute that is being checked against - * @returns {Boolean} - */ -function isVueClassAttribute(node, classRegex) { - const re = new RegExp(classRegex); - let name = ''; - switch (true) { - case node.key && node.key.name && re.test(node.key.name): - // class="vue-classes-as-litteral" - return true; - case node.key && - node.key.name && - node.key.name.name && - node.key.argument && - node.key.argument.name && - /^bind$/.test(node.key.name.name) && - re.test(node.key.argument.name): - // v-bind:class="vue-classes-as-bind" - // :class="vue-classes-as-bind" - return true; - default: - return false; - } -} - -/** - * Find out if node's value attribute is just simple text - * - * @param {ASTNode} node The AST node being checked - * @returns {Boolean} - */ -function isVLiteralValue(node) { - return node.value && node.value.type === 'VLiteral'; -} - -/** - * Find out if node's value attribute is an ArrayExpression - * - * @param {ASTNode} node The AST node being checked - * @returns {Boolean} - */ -function isArrayExpression(node) { - return node.value && node.value.type === 'VExpressionContainer' && node.value.expression.type === 'ArrayExpression'; -} - -/** - * Find out if node's value attribute is an ObjectExpression - * - * @param {ASTNode} node The AST node being checked - * @returns {Boolean} - */ -function isObjectExpression(node) { - return node.value && node.value.type === 'VExpressionContainer' && node.value.expression.type === 'ObjectExpression'; -} - -/** - * Find out if node's value attribute is just simple text - * - * @param {ASTNode} node The AST node being checked - * @returns {Boolean} - */ -function isVueValidAttributeValue(node) { - switch (true) { - case isVLiteralValue(node): // Simple string - case isArrayExpression(node): // ['tw-unknown-class'] - case isObjectExpression(node): // {'tw-unknown-class': true} - return true; - break; - default: - return false; - } -} - -/** - * Find out if node's value attribute is just simple text - * - * @param {ASTNode} node The AST node being checked - * @returns {Boolean} - */ -function isLiteralAttributeValue(node) { - if (node.type === 'TextAttribute' && node.name === 'class' && typeof node.value === 'string') { - return true; - } - if (node.value) { - switch (node.value.type) { - case 'Literal': - // No support for dynamic or conditional... - return !/\{|\?|\}/.test(node.value.value); - case 'JSXExpressionContainer': - // className={"..."} - return node.value.expression.type === 'Literal'; - } - } - return false; -} - -/** - * Find out if the node is a valid candidate for our rules - * - * @param {ASTNode} node The AST node being checked - * @param {String} classRegex Regex to test the attribute that is being checked against - * @returns {Boolean} - */ -function isValidJSXAttribute(node, classRegex) { - if (!isClassAttribute(node, classRegex)) { - // Only run for class[Name] attributes - return false; - } - if (!isLiteralAttributeValue(node)) { - // No support for dynamic or conditional classnames - return false; - } - return true; -} - -/** - * Find out if the node is a valid candidate for our rules - * - * @param {ASTNode} node The AST node being checked - * @param {String} classRegex Regex to test the attribute that is being checked against - * @returns {Boolean} - */ -function isValidVueAttribute(node, classRegex) { - if (!isVueClassAttribute(node, classRegex)) { - // Only run for class attributes - return false; - } - if (!isVueValidAttributeValue(node)) { - // No support for dynamic or conditional classnames - return false; - } - return true; -} - -function extractRangeFromNode(node) { - if (node.type === 'TextAttribute' && node.name === 'class') { - return [node.valueSpan.fullStart.offset, node.valueSpan.end.offset]; - } - if (node.value === undefined) { - return [0, 0]; - } - switch (node.value.type) { - case 'JSXExpressionContainer': - return node.value.expression.range; - default: - return node.value.range; - } -} - -function extractValueFromNode(node) { - if (node.type === 'TextAttribute' && node.name === 'class') { - return node.value; - } - if (node.value === undefined) { - return node.value; - } - - switch (node.value.type) { - case 'JSXExpressionContainer': - return node.value.expression.value; - case 'VExpressionContainer': - switch (node.value.expression.type) { - case 'ArrayExpression': - return node.value.expression.elements; - break; - case 'ObjectExpression': - return node.value.expression.properties; - break; - } - return node.value.expression.value; - default: - return node.value.value; - } -} - -function extractClassnamesFromValue(classStr) { - if (typeof classStr !== 'string') { - return { classNames: [], whitespaces: [], headSpace: false, tailSpace: false }; - } - let parts = classStr.split(separatorRegEx); - if (parts[0] === '') { - parts.shift(); - } - if (parts[parts.length - 1] === '') { - parts.pop(); - } - let headSpace = separatorRegEx.test(parts[0]); - let tailSpace = separatorRegEx.test(parts[parts.length - 1]); - const isClass = (_, i) => (headSpace ? i % 2 !== 0 : i % 2 === 0); - const isNotClass = (_, i) => (headSpace ? i % 2 === 0 : i % 2 !== 0); - let classNames = parts.filter(isClass); - let whitespaces = parts.filter(isNotClass); - return { classNames: classNames, whitespaces: whitespaces, headSpace: headSpace, tailSpace: tailSpace }; -} - -/** - * Inspect and parse an abstract syntax node and run a callback function - * - * @param {ASTNode} rootNode The current root node being parsed by eslint - * @param {ASTNode} childNode The AST node child argument being checked - * @param {Function} cb The callback function - * @param {Boolean} skipConditional Optional, indicate distinct parsing for conditional nodes - * @param {Boolean} isolate Optional, set internally to isolate parsing and validation on conditional children - * @param {Array} ignoredKeys Optional, set object keys which should not be parsed e.g. for `cva` - * @returns {void} - */ -function parseNodeRecursive(rootNode, childNode, cb, skipConditional = false, isolate = false, ignoredKeys = []) { - // TODO allow vue non litteral - let originalClassNamesValue; - let classNames; - if (childNode === null) { - originalClassNamesValue = extractValueFromNode(rootNode); - ({ classNames } = extractClassnamesFromValue(originalClassNamesValue)); - classNames = removeDuplicatesFromArray(classNames); - if (classNames.length === 0) { - // Don't run for empty className - return; - } - cb(classNames, rootNode); - } else if (childNode === undefined) { - // Ignore invalid child candidates (probably inside complex TemplateLiteral) - return; - } else { - const forceIsolation = skipConditional ? true : isolate; - let trim = false; - switch (childNode.type) { - case 'TemplateLiteral': - childNode.expressions.forEach((exp) => { - parseNodeRecursive(rootNode, exp, cb, skipConditional, forceIsolation, ignoredKeys); - }); - childNode.quasis.forEach((quasis) => { - parseNodeRecursive(rootNode, quasis, cb, skipConditional, isolate, ignoredKeys); - }); - return; - case 'ConditionalExpression': - parseNodeRecursive(rootNode, childNode.consequent, cb, skipConditional, forceIsolation, ignoredKeys); - parseNodeRecursive(rootNode, childNode.alternate, cb, skipConditional, forceIsolation, ignoredKeys); - return; - case 'LogicalExpression': - parseNodeRecursive(rootNode, childNode.right, cb, skipConditional, forceIsolation, ignoredKeys); - return; - case 'ArrayExpression': - childNode.elements.forEach((el) => { - parseNodeRecursive(rootNode, el, cb, skipConditional, forceIsolation, ignoredKeys); - }); - return; - case 'ObjectExpression': - childNode.properties.forEach((prop) => { - const isUsedByClassNamesPlugin = rootNode.callee && rootNode.callee.name === 'classnames'; - - if (prop.type === 'SpreadElement') { - // Ignore spread elements - return; - } - - if (prop.key.type === 'Identifier' && ignoredKeys.includes(prop.key.name)) { - // Ignore specific keys defined in settings - return; - } - - parseNodeRecursive( - rootNode, - isUsedByClassNamesPlugin ? prop.key : prop.value, - cb, - skipConditional, - forceIsolation, - ignoredKeys - ); - }); - return; - case 'Property': - parseNodeRecursive(rootNode, childNode.key, cb, skipConditional, forceIsolation, ignoredKeys); - return; - case 'Literal': - trim = true; - originalClassNamesValue = childNode.value; - break; - case 'TemplateElement': - originalClassNamesValue = childNode.value.raw; - break; - } - ({ classNames } = extractClassnamesFromValue(originalClassNamesValue)); - classNames = removeDuplicatesFromArray(classNames); - if (classNames.length === 0) { - // Don't run for empty className - return; - } - const targetNode = isolate ? null : rootNode; - cb(classNames, targetNode); - } -} - -function getTemplateElementPrefix(text, raw) { - const idx = text.indexOf(raw); - if (idx === 0) { - return ''; - } - return text.split(raw).shift(); -} - -function getTemplateElementSuffix(text, raw) { - if (text.indexOf(raw) === -1) { - return ''; - } - return text.split(raw).pop(); -} - -function getTemplateElementBody(text, prefix, suffix) { - let arr = text.split(prefix); - arr.shift(); - let body = arr.join(prefix); - arr = body.split(suffix); - arr.pop(); - return arr.join(suffix); -} - -module.exports = { - calleeToString, - extractRangeFromNode, - extractValueFromNode, - extractClassnamesFromValue, - isClassAttribute, - isLiteralAttributeValue, - isArrayExpression, - isObjectExpression, - isValidJSXAttribute, - isValidVueAttribute, - isVLiteralValue, - parseNodeRecursive, - getTemplateElementPrefix, - getTemplateElementSuffix, - getTemplateElementBody, -}; diff --git a/lib/util/cssFiles.js b/lib/util/cssFiles.js deleted file mode 100644 index 4a49a334..00000000 --- a/lib/util/cssFiles.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -const fg = require('fast-glob'); -const fs = require('fs'); -const postcss = require('postcss'); -const removeDuplicatesFromArray = require('./removeDuplicatesFromArray'); - -let previousGlobsResults = []; -let lastUpdate = null; -let classnamesFromFiles = []; - -/** - * Read CSS files and extract classnames - * @param {Array} patterns Glob patterns to locate files - * @param {Number} refreshRate Interval - * @returns {Array} List of classnames - */ -const generateClassnamesListSync = (patterns, refreshRate = 5_000) => { - const now = new Date().getTime(); - const files = fg.sync(patterns, { suppressErrors: true }); - const newGlobs = previousGlobsResults.flat().join(',') != files.flat().join(','); - const expired = lastUpdate === null || now - lastUpdate > refreshRate; - if (newGlobs || expired) { - previousGlobsResults = files; - lastUpdate = now; - let detectedClassnames = []; - for (const file of files) { - const data = fs.readFileSync(file, 'utf-8'); - const root = postcss.parse(data); - root.walkRules((rule) => { - const regexp = /\.([^\.\,\s\n\:\(\)\[\]\'~\+\>\*\\]*)/gim; - const matches = [...rule.selector.matchAll(regexp)]; - const classnames = matches.map((arr) => arr[1]); - detectedClassnames.push(...classnames); - }); - detectedClassnames = removeDuplicatesFromArray(detectedClassnames); - } - classnamesFromFiles = detectedClassnames; - } - return classnamesFromFiles; -}; - -module.exports = generateClassnamesListSync; diff --git a/lib/util/customConfig.js b/lib/util/customConfig.js deleted file mode 100644 index 9bc6a403..00000000 --- a/lib/util/customConfig.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const resolveConfig = require('tailwindcss/resolveConfig'); -let twLoadConfig; - -try { - twLoadConfig = require('tailwindcss/lib/lib/load-config'); -} catch (err) { - twLoadConfig = null; -} - -const CHECK_REFRESH_RATE = 1_000; -let previousConfig = null; -let lastCheck = null; -let mergedConfig = null; -let lastModifiedDate = null; - -/** - * @see https://stackoverflow.com/questions/9210542/node-js-require-cache-possible-to-invalidate - * @param {string} module The path to the module - * @returns the module's export - */ -function requireUncached(module) { - delete require.cache[require.resolve(module)]; - if (twLoadConfig === null) { - return require(module); - } else { - return twLoadConfig.loadConfig(module); - } -} - -function loadConfig(config) { - let loadedConfig = null; - if (typeof config === 'string') { - const resolvedPath = path.isAbsolute(config) ? config : path.join(path.resolve(), config); - try { - const stats = fs.statSync(resolvedPath); - if (stats === null) { - loadedConfig = {}; - } else if (lastModifiedDate !== stats.mtime) { - lastModifiedDate = stats.mtime; - loadedConfig = requireUncached(resolvedPath); - } else { - loadedConfig = null; - } - } catch (err) { - loadedConfig = {}; - } finally { - return loadedConfig; - } - } else { - if (typeof config === 'object' && config !== null) { - return config; - } - return {}; - } -} - -function convertConfigToString(config) { - switch (typeof config) { - case 'string': - return config; - case 'object': - return JSON.stringify(config); - default: - return config.toString(); - } -} - -function resolve(twConfig) { - const now = new Date().getTime(); - const newConfig = convertConfigToString(twConfig) !== convertConfigToString(previousConfig); - const expired = now - lastCheck > CHECK_REFRESH_RATE; - if (newConfig || expired) { - previousConfig = twConfig; - lastCheck = now; - const userConfig = loadConfig(twConfig); - // userConfig is null when config file was not modified - if (userConfig !== null) { - mergedConfig = resolveConfig(userConfig); - } - } - return mergedConfig; -} - -module.exports = { - resolve, -}; diff --git a/lib/util/docsUrl.js b/lib/util/docsUrl.js deleted file mode 100644 index 496e42cd..00000000 --- a/lib/util/docsUrl.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -// Copied from https://github.com/yannickcr/eslint-plugin-react/blob/master/lib/util/docsUrl.js -function docsUrl(ruleName) { - return `https://github.com/francoismassart/eslint-plugin-tailwindcss/tree/master/docs/rules/${ruleName}.md`; -} - -module.exports = docsUrl; diff --git a/lib/util/generated.js b/lib/util/generated.js deleted file mode 100644 index 708f14e4..00000000 --- a/lib/util/generated.js +++ /dev/null @@ -1,10 +0,0 @@ -var generateRulesFallback = require('tailwindcss/lib/lib/generateRules').generateRules; - -function generate(className, context) { - // const order = generateRulesFallback(new Set([className]), context).sort(([a], [z]) => bigSign(z - a))[0]?.[0] ?? null; - const gen = generateRulesFallback(new Set([className]), context); - // console.debug(gen); - return gen; -} - -module.exports = generate; diff --git a/lib/util/groupMethods.js b/lib/util/groupMethods.js deleted file mode 100644 index ac1bed8e..00000000 --- a/lib/util/groupMethods.js +++ /dev/null @@ -1,613 +0,0 @@ -/** - * @fileoverview Utilities used for grouping classnames - */ - -'use strict'; - -// Ambiguous values -// ================ -// Supported hints: length, color, angle, list -// ------------------------------------------- -// -// border-[color/width] -// text-[color/size] -// ring-[color/width] -// ring-offset-[color/width] -// stroke-[current/width] -// bg-[color/(position/size)] -// -// font-[family/weight] - -const angle = require('./types/angle'); -const color = require('./types/color'); -const length = require('./types/length'); - -/** - * Escape special chars for regular expressions - * - * @param {String} str Regular expression to be escaped - * @returns {String} Escaped version - */ -function escapeSpecialChars(str) { - return str.replace(/\W/g, '\\$&'); -} - -/** - * Generates the opacity suffix based on config - * - * @param {Object} config Tailwind CSS Config - * @returns {String} The suffix or an empty string - */ -function generateOptionalOpacitySuffix(config) { - const opacityKeys = !config.theme['opacity'] ? [] : Object.keys(config.theme['opacity']); - opacityKeys.push('\\[(\\d*\\.?\\d*)%?\\]'); - return `(\\/(${opacityKeys.join('|')}))?`; -} - -/** - * Generate the possible options for the RegEx - * - * @param {String} propName The name of the prop e.g. textColor - * @param {Array} keys Keys to be injected in the options - * @param {Object} config Tailwind CSS Config - * @param {Boolean} isNegative If the value is negative - * @returns {String} Generated part of regex exposing the possible values - */ -function generateOptions(propName, keys, config, isNegative = false) { - const opacitySuffixes = generateOptionalOpacitySuffix(config); - const genericArbitraryOption = '\\[(.*)\\]'; - const defaultKeyIndex = keys.findIndex((v) => v === 'DEFAULT'); - if (defaultKeyIndex > -1) { - keys.splice(defaultKeyIndex, 1); - } - const escapedKeys = keys.map((k) => escapeSpecialChars(k)); - switch (propName) { - case 'dark': - // Optional `dark` class - if (config.darkMode === 'class') { - return 'dark'; - } else if (Array.isArray(config.darkMode) && config.darkMode.length === 2 && config.darkMode[0] === 'class') { - // https://tailwindcss.com/docs/dark-mode#customizing-the-class-name - // For the sake of simplicity we only support a single class name - let value = ''; - const res = /^\.(?[A-Z0-9\:\-\_\[\d\]]*)$/gi.exec(config.darkMode[1]); - if (res && res.groups) { - if (res.groups.classnameValue) { - value = res.groups.classnameValue; - } - } - return value; - } else { - return ''; - } - case 'arbitraryProperties': - escapedKeys.push(genericArbitraryOption); - return '(' + escapedKeys.join('|') + ')'; - case 'colors': - case 'accentColor': - case 'borderColor': - case 'boxShadowColor': - case 'divideColor': - case 'fill': - case 'outlineColor': - case 'textColor': - case 'stroke': - case 'gradientColorStopPositions': - // Colors can use segments like 'indigo' and 'indigo-light' - // https://tailwindcss.com/docs/customizing-colors#color-object-syntax - const options = []; - keys.forEach((k) => { - const color = config.theme[propName][k] || config.theme.colors[k]; - if (typeof color === 'string') { - options.push(escapeSpecialChars(k) + opacitySuffixes); - } else { - const variants = Object.keys(color).map((colorKey) => escapeSpecialChars(colorKey)); - const defaultIndex = variants.findIndex((v) => v === 'DEFAULT'); - const hasDefault = defaultIndex > -1; - if (hasDefault) { - variants.splice(defaultIndex, 1); - } - options.push(k + '(\\-(' + variants.join('|') + '))' + (hasDefault ? '?' : '') + opacitySuffixes); - } - }); - const arbitraryColors = [...color.mergedColorValues]; - switch (propName) { - case 'fill': - // Forbidden prefixes - arbitraryColors.push(`(?!(angle|length|list)\:).{1,}`); - break; - case 'gradientColorStopPositions': - arbitraryColors.push(color.RGBAPercentages); // RGBA % 0.5[%] - arbitraryColors.push(color.optionalColorPrefixedVar); - arbitraryColors.push(color.notHSLAPlusWildcard); - break; - case 'textColor': - arbitraryColors.push(color.RGBAPercentages); // RGBA % 0.5[%] - arbitraryColors.push(color.mandatoryColorPrefixed); - break; - default: - arbitraryColors.push(color.mandatoryColorPrefixed); - } - options.push(`\\[(${arbitraryColors.join('|')})\\]`); - return '(' + options.join('|') + ')'; - case 'borderSpacing': - case 'borderWidth': - case 'divideWidth': - case 'fontSize': - case 'outlineWidth': - case 'outlineOffset': - case 'ringWidth': - case 'ringOffsetWidth': - case 'textUnderlineOffset': - escapedKeys.push(length.selectedUnitsRegEx); - escapedKeys.push(length.anyCalcRegEx); - // Mandatory `length:` prefix + wildcard - escapedKeys.push(`\\[length\\:.{1,}\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'strokeWidth': - escapedKeys.push(length.selectedUnitsRegEx); - escapedKeys.push(length.anyCalcRegEx); - // Mandatory `length:` prefix + calc + wildcard - escapedKeys.push(`\\[length\\:calc\\(.{1,}\\)\\]`); - // Mandatory `length:` prefix + wildcard + optional units - escapedKeys.push(`\\[length\\:(.{1,})(${length.selectedUnits.join('|')})?\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'gap': - case 'height': - case 'lineHeight': - case 'maxHeight': - case 'size': - case 'maxWidth': - case 'minHeight': - case 'minWidth': - case 'padding': - case 'width': - case 'blur': - case 'brightness': - case 'contrast': - case 'grayscale': - case 'invert': - case 'saturate': - case 'sepia': - case 'backdropBlur': - case 'backdropBrightness': - case 'backdropContrast': - case 'backdropGrayscale': - case 'backdropInvert': - case 'backdropOpacity': - case 'backdropSaturate': - case 'backdropSepia': - case 'transitionDuration': - case 'transitionTimingFunction': - case 'transitionDelay': - case 'animation': - case 'transformOrigin': - case 'scale': - case 'cursor': - // All units - escapedKeys.push(length.mergedUnitsRegEx); - // Forbidden prefixes - escapedKeys.push(`\\[(?!(angle|color|length|list)\:).{1,}\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'backdropHueRotate': - case 'hueRotate': - case 'inset': - case 'letterSpacing': - case 'margin': - case 'scrollMargin': - case 'skew': - case 'space': - case 'textIndent': - case 'translate': - // All units - escapedKeys.push(length.mergedUnitsRegEx); - // Forbidden prefixes - escapedKeys.push(`\\[(?!(angle|color|length|list)\:).{1,}\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'backgroundOpacity': - case 'borderOpacity': - case 'opacity': - case 'ringOpacity': - // 0 ... .5 ... 1 - escapedKeys.push(`\\[(0(\\.\\d{1,})?|\\.\\d{1,}|1)\\]`); - escapedKeys.push(length.anyCalcRegEx); - // Unprefixed var() - escapedKeys.push(`\\[var\\(\\-\\-[A-Za-z\\-]{1,}\\)\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'rotate': - escapedKeys.push(`\\[(${angle.mergedAngleValues.join('|')})\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'gridTemplateColumns': - case 'gridColumn': - case 'gridColumnStart': - case 'gridColumnEnd': - case 'gridTemplateRows': - case 'gridRow': - case 'gridRowStart': - case 'gridRowEnd': - case 'gridAutoColumns': - case 'gridAutoRows': - // Forbidden prefixes - escapedKeys.push(`\\[(?!(angle|color|length)\:).{1,}\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'listStyleType': - // Forbidden prefixes - escapedKeys.push(`\\[(?!(angle|color|length|list)\:).{1,}\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'objectPosition': - // Forbidden prefixes - escapedKeys.push(`\\[(?!(angle|color|length)\:).{1,}\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'backgroundPosition': - case 'boxShadow': - case 'dropShadow': - case 'transitionProperty': - // Forbidden prefixes - escapedKeys.push(`\\[(?!((angle|color|length|list)\:)|#|var\\().{1,}\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'backgroundSize': - // Forbidden prefixes - escapedKeys.push(`\\[length\:.{1,}\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'backgroundImageUrl': - // Forbidden prefixes - escapedKeys.push(`.{1,}`); - return '(' + escapedKeys.join('|') + ')'; - case 'backgroundImage': - // Forbidden prefixes - escapedKeys.push(`\\[url\\(.{1,}\\)\\]`); - return '(' + escapedKeys.join('|') + ')'; - case 'order': - case 'zIndex': - escapedKeys.push(genericArbitraryOption); - return '(' + escapedKeys.join('|') + ')'; - case 'fontWeight': - case 'typography': - case 'lineClamp': - // Cannot be arbitrary? - return '(' + escapedKeys.join('|') + ')'; - case 'aspectRatio': - case 'flexGrow': - case 'flexShrink': - case 'fontFamily': - case 'flex': - case 'borderRadius': - default: - escapedKeys.push(genericArbitraryOption); - return '(' + escapedKeys.join('|') + ')'; - } -} - -const cachedRegexes = new WeakMap(); - -/** - * Customize the regex based on config - * - * @param {String} re Regular expression - * @param {Object} config The merged Tailwind CSS config - * @returns {String} Patched version with config values and additional parameters - */ -function patchRegex(re, config) { - if (!cachedRegexes.has(config)) { - cachedRegexes.set(config, {}); - } - const cache = cachedRegexes.get(config); - if (re in cache) { - return cache[re]; - } - let patched = '\\!?'; - // Prefix - if (config.prefix.length) { - patched += escapeSpecialChars(config.prefix); - } - // Props - let replaced = re; - const propsRe = /\$\{(\-?[a-z]*)\}/gi; - const res = replaced.matchAll(propsRe); - const resArray = [...res]; - const props = resArray.map((arr) => arr[1]); - if (props.length === 0) { - return (cache[re] = `${patched}(${replaced})`); - } - // e.g. backgroundColor, letterSpacing, -margin... - props.forEach((prop) => { - const token = new RegExp('\\$\\{' + prop + '\\}'); - const isNegative = prop.substr(0, 1) === '-'; - const absoluteProp = isNegative ? prop.substr(1) : prop; - if (prop === 'dark') { - // Special case, not a default property from the theme - replaced = replaced.replace(token, generateOptions(absoluteProp, [], config, isNegative)); - return `${patched}(${replaced})`; - } else if (prop === 'arbitraryProperties') { - // Special case - replaced = replaced.replace( - new RegExp('\\$\\{' + absoluteProp + '\\}'), - generateOptions(absoluteProp, [], config, isNegative) - ); - return `${patched}(${replaced})`; - } else if (prop === 'backgroundImageUrl') { - // Special case - replaced = replaced.replace(new RegExp('\\$\\{' + prop + '\\}'), generateOptions(prop, [], config, false)); - return `${patched}(${replaced})`; - } else if (!config.theme || !config.theme[absoluteProp]) { - // prop not found in config - return; - } - // Normal scenario - const keys = Object.keys(config.theme[absoluteProp]) - .filter((key) => { - if (isNegative) { - // Negative prop cannot support NaN values and inherits positive values - const val = config.theme[absoluteProp][key]; - const isCalc = typeof val === 'string' && val.indexOf('calc') === 0; - const num = parseFloat(val); - if (isCalc) { - return true; - } - if (isNaN(num)) { - return false; - } - } else if (key[0] === '-') { - // Positive prop cannot use key starting with '-' - return false; - } - return true; - }) - .map((key) => { - if (isNegative && key[0] === '-') { - return key.substring(1); - } - return key; - }); - if (keys.length === 0 || replaced.match(token) === null) { - // empty array - return; - } - const opts = generateOptions(absoluteProp, keys, config, isNegative); - replaced = replaced.replace(token, opts); - }); - return (cache[re] = `${patched}(${replaced})`); -} - -/** - * Generates a flatten array from the groups config - * - * @param {Array} groupsConfig The array of objects containing the regex - * @param {Object} twConfig The merged config of Tailwind CSS - * @returns {Array} Flatten array - */ -function getGroups(groupsConfig, twConfig = null) { - const groups = []; - groupsConfig.forEach((group) => { - // e.g. SIZING or SPACING - group.members.forEach((prop) => { - // e.g. Width or Padding - if (typeof prop.members === 'string') { - // Unique property, like `width` limited to one value - groups.push(prop.members); - } else { - // Multiple properties, like `padding`, `padding-top`... - prop.members.forEach((subprop) => { - groups.push(subprop.members); - }); - } - }); - }); - if (twConfig === null) { - return groups; - } - return groups.map((re) => patchRegex(re, twConfig)); -} - -/** - * Generates an array of empty arrays prior to grouping - * - * @param {Array} groups The array of objects containing the regex - * @returns {Array} Array of empty arrays - */ -function initGroupSlots(groups) { - const slots = []; - groups.forEach((g) => slots.push([])); - return slots; -} - -/** - * Searches for a match between classname and Tailwind CSS group - * - * @param {Array} name The target classname - * @param {Array} arr The flatten array containing the regex - * @param {String} separator The delimiter to be used between variants - * @returns {Array} Array of empty arrays - */ -function getGroupIndex(name, arr, separator = ':') { - const classSuffix = getSuffix(name, separator); - let idx = arr.findIndex((pattern) => { - const classRe = new RegExp(`^(${pattern})$`); - return classRe.test(classSuffix); - }, classSuffix); - return idx; -} - -/** - * Generates a flatten array from the groups configKeys - * - * @param {Array} groupsConfig The array of objects containing the regex - * @param {Object} twConfig The merged config of Tailwind CSS - * @returns {Array} Flatten array - */ -function getGroupConfigKeys(groupsConfig) { - const groups = []; - groupsConfig.forEach((group) => { - // e.g. SIZING or SPACING - group.members.forEach((prop) => { - // e.g. Width or Padding - if (typeof prop.members === 'string') { - // Unique property, like `width` limited to one value - groups.push(prop.configKey ? prop.configKey : null); - } else { - // Multiple properties, like `padding`, `padding-top`... - prop.members.forEach((subprop) => { - groups.push(subprop.configKey ? subprop.configKey : null); - }); - } - }); - }); - return groups; -} - -/** - * Returns the prefix (variants) of a className including the separator or an empty string if none - * - * @param {String} name Classname to be parsed - * @param {String} separator The separator character as in config - * @returns {String} The prefix - */ -function getPrefix(name, separator) { - const rootSeparator = String.raw`(? "mask-type" - * - * @see https://tailwindcss.com/docs/adding-custom-styles#arbitrary-properties - * @param {String} name Classname suffix (without it variants) to be parsed - * @param {String} separator The separator character as in config - * @returns {String} The arbitrary property - */ -function getArbitraryProperty(name, separator) { - const arbitraryPropPattern = String.raw`^\[([a-z\-]*)${separator}\.*`; - const arbitraryPropRegExp = new RegExp(arbitraryPropPattern); - const results = arbitraryPropRegExp.exec(name); - return results === null ? '' : results[1]; -} - -/** - * Get the last part of the full classname - * e.g. "lg:w-[100px]" => "w-[100px]" - * - * @param {String} className The target classname - * @param {String} separator The delimiter to be used between variants - * @returns {String} The classname without its variants - */ -function getSuffix(className, separator = ':') { - const prefix = getPrefix(className, separator); - return className.substring(prefix.length); -} - -/** - * Find the group of a classname - * - * @param {String} name Classname to be find using patterns (without modifiers) - * @param {Array} group The group being tested - * @param {Object} config Tailwind CSS config - * @param {String} parentType The name of the parent group - * @returns {Object} The infos - */ -function findInGroup(name, group, config, parentType = null) { - if (typeof group.members === 'string') { - const pattern = patchRegex(group.members, config); - const classRe = new RegExp(`^(${pattern})$`); - if (classRe.test(name)) { - const res = classRe.exec(name); - let value = ''; - if (res && res.groups) { - if (res.groups.value) { - value = res.groups.value; - } - if (res.groups.negativeValue) { - value = '-' + res.groups.negativeValue; - } - } - return { - group: parentType, - ...group, - value: value, - }; - } else { - return null; - } - } else { - const innerGroup = group.members.find((v) => findInGroup(name, v, config, group.type)); - if (!innerGroup) { - return null; - } else { - return findInGroup(name, innerGroup, config, group.type); - } - } -} - -/** - * Returns an object with parsed properties - * - * @param {String} name Classname to be parsed - * @param {Array} arr The flatten array containing the regex - * @param {Object} config The Tailwind CSS config - * @param {Number} index The index - * @returns {Object} Parsed infos - */ -function parseClassname(name, arr, config, index = null) { - const leadingRe = new RegExp('^(?\\s*)'); - const trailingRe = new RegExp('(?\\s*)$'); - let leading = ''; - let core = ''; - let trailing = ''; - const leadingRes = leadingRe.exec(name); - if (leadingRes && leadingRes.groups) { - leading = leadingRes.groups.leading || ''; - } - const trailingRes = trailingRe.exec(name); - if (trailingRes && trailingRes.groups) { - trailing = trailingRes.groups.trailing || ''; - } - core = name.substring(leading.length, name.length - trailing.length); - const variants = getPrefix(core, config.separator); - const classSuffix = getSuffix(core, config.separator); - let slot = null; - arr.forEach((group) => { - if (slot === null) { - const found = findInGroup(classSuffix, group, config); - if (found) { - slot = found; - } - } - }); - const value = slot ? slot.value : ''; - const isNegative = value[0] === '-'; - const off = isNegative ? 1 : 0; - const body = core.substr(0, core.length - value.length + off).substr(variants.length + off); - return { - index: index, - name: core, - variants: variants, - parentType: slot ? slot.group : '', - body: body, - value: value, - shorthand: slot && slot.shorthand ? slot.shorthand : '', - leading: leading, - trailing: trailing, - important: body.substr(0, 1) === '!', - }; -} - -module.exports = { - initGroupSlots, - getArbitraryProperty, - getGroups, - getGroupIndex, - getGroupConfigKeys, - getPrefix, - getSuffix, - parseClassname, -}; diff --git a/lib/util/parser.js b/lib/util/parser.js deleted file mode 100644 index 82d13dfc..00000000 --- a/lib/util/parser.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @see parserServices https://eslint.org/docs/developer-guide/working-with-rules#the-context-object - * @param {Object} context - * @param {Function} templateBodyVisitor - * @param {Function} scriptVisitor - * @returns - */ -function defineTemplateBodyVisitor(context, templateBodyVisitor, scriptVisitor) { - const parserServices = getParserServices(context); - if (parserServices == null || parserServices.defineTemplateBodyVisitor == null) { - // Default parser - return scriptVisitor; - } - - // Using "vue-eslint-parser" requires this setup - // @see https://eslint.org/docs/developer-guide/working-with-rules#the-context-object - return parserServices.defineTemplateBodyVisitor(templateBodyVisitor, scriptVisitor); -} - -/** - * This function is API compatible with eslint v8.x and eslint v9 or later. - * @see https://eslint.org/blog/2023/09/preparing-custom-rules-eslint-v9/#from-context-to-sourcecode - */ -function getParserServices(context) { - return context.sourceCode ? context.sourceCode.parserServices : context.parserServices; -} - -module.exports = { - defineTemplateBodyVisitor, -}; diff --git a/lib/util/prettier/order.js b/lib/util/prettier/order.js deleted file mode 100644 index 04d76a7c..00000000 --- a/lib/util/prettier/order.js +++ /dev/null @@ -1,101 +0,0 @@ -const { separatorRegEx } = require('../regex'); - -function bigSign(bigIntValue) { - return (bigIntValue > 0n) - (bigIntValue < 0n); -} - -function prefixCandidate(context, selector) { - let prefix = context.tailwindConfig.prefix; - return typeof prefix === 'function' ? prefix(selector) : prefix + selector; -} - -// Polyfill for older Tailwind CSS versions -function getClassOrderPolyfill(classes, { env }) { - // A list of utilities that are used by certain Tailwind CSS utilities but - // that don't exist on their own. This will result in them "not existing" and - // sorting could be weird since you still require them in order to make the - // host utitlies work properly. (Thanks Biology) - let parasiteUtilities = new Set([prefixCandidate(env.context, 'group'), prefixCandidate(env.context, 'peer')]); - - let classNamesWithOrder = []; - - for (let className of classes) { - let order = env.generateRules(new Set([className]), env.context).sort(([a], [z]) => bigSign(z - a))[0]?.[0] ?? null; - - if (order === null && parasiteUtilities.has(className)) { - // This will make sure that it is at the very beginning of the - // `components` layer which technically means 'before any - // components'. - order = env.context.layerOrder.components; - } - - classNamesWithOrder.push([className, order]); - } - - return classNamesWithOrder; -} - -function sortClasses(classStr, { env, ignoreFirst = false, ignoreLast = false }) { - if (typeof classStr !== 'string' || classStr === '') { - return classStr; - } - - // Ignore class attributes containing `{{`, to match Prettier behaviour: - // https://github.com/prettier/prettier/blob/main/src/language-html/embed.js#L83-L88 - if (classStr.includes('{{')) { - return classStr; - } - - let result = ''; - let parts = classStr.split(separatorRegEx); - let classes = parts.filter((_, i) => i % 2 === 0); - let whitespace = parts.filter((_, i) => i % 2 !== 0); - - if (classes[classes.length - 1] === '') { - classes.pop(); - } - - let prefix = ''; - if (ignoreFirst) { - prefix = `${classes.shift() ?? ''}${whitespace.shift() ?? ''}`; - } - - let suffix = ''; - if (ignoreLast) { - suffix = `${whitespace.pop() ?? ''}${classes.pop() ?? ''}`; - } - - let classNamesWithOrder = env.context.getClassOrder - ? env.context.getClassOrder(classes) - : getClassOrderPolyfill(classes, { env }); - - classes = classNamesWithOrder - .sort(([, a], [, z]) => { - if (a === z) return 0; - // if (a === null) return options.unknownClassPosition === 'start' ? -1 : 1 - // if (z === null) return options.unknownClassPosition === 'start' ? 1 : -1 - if (a === null) return -1; - if (z === null) return 1; - return bigSign(a - z); - }) - .map(([className]) => className); - - for (let i = 0; i < classes.length; i++) { - result += `${classes[i]}${whitespace[i] ?? ''}`; - } - - return prefix + result + suffix; -} - -/** - * - * @param {Array} unordered the unordered classnames - * @param context - * @returns {Array} the ordered classnames - */ -function order(unordered, context) { - const sorted = sortClasses(unordered.join(' '), { env: { context: context } }); - return sorted; -} - -module.exports = order; diff --git a/lib/util/regex.js b/lib/util/regex.js deleted file mode 100644 index 78189ace..00000000 --- a/lib/util/regex.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Escapes a string to be used in a regular expression - * Copied from https://stackoverflow.com/a/3561711. - * @param {string} input - * @returns {string} - */ -function escapeRegex(input) { - return input.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&'); -} - -const separatorRegEx = /([\t\n\f\r ]+)/; - -module.exports = { - escapeRegex, - separatorRegEx, -}; diff --git a/lib/util/removeDuplicatesFromArray.js b/lib/util/removeDuplicatesFromArray.js deleted file mode 100644 index 6301fe4a..00000000 --- a/lib/util/removeDuplicatesFromArray.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -function removeDuplicatesFromArray(arr) { - return [...new Set(arr)]; -} - -module.exports = removeDuplicatesFromArray; diff --git a/lib/util/removeDuplicatesFromClassnamesAndWhitespaces.js b/lib/util/removeDuplicatesFromClassnamesAndWhitespaces.js deleted file mode 100644 index f660273c..00000000 --- a/lib/util/removeDuplicatesFromClassnamesAndWhitespaces.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -function removeDuplicatesFromClassnamesAndWhitespaces(orderedClassNames, whitespaces, headSpace, tailSpace) { - let previous = orderedClassNames[0]; - const offset = (!headSpace && !tailSpace) || tailSpace ? -1 : 0; - for (let i = 1; i < orderedClassNames.length; i++) { - const cls = orderedClassNames[i]; - // This function assumes that the list of classNames is ordered, so just comparing to the previous className is enough - if (cls === previous) { - orderedClassNames.splice(i, 1); - whitespaces.splice(i + offset, 1); - i--; - } - previous = cls; - } -} - -module.exports = removeDuplicatesFromClassnamesAndWhitespaces; diff --git a/lib/util/settings.js b/lib/util/settings.js deleted file mode 100644 index 9c24567f..00000000 --- a/lib/util/settings.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; -let resolveDefaultConfigPathAlias; - -try { - const { resolveDefaultConfigPath } = require('tailwindcss/lib/util/resolveConfigPath'); - resolveDefaultConfigPathAlias = resolveDefaultConfigPath; -} catch (err) { - resolveDefaultConfigPathAlias = null; -} - -function getOption(context, name) { - // Options (defined at rule level) - const options = context.options[0] || {}; - if (options[name] != undefined) { - return options[name]; - } - // Settings (defined at plugin level, shared accross rules) - if (context.settings && context.settings.tailwindcss && context.settings.tailwindcss[name] != undefined) { - return context.settings.tailwindcss[name]; - } - // Fallback to defaults - switch (name) { - case 'callees': - return ['classnames', 'clsx', 'ctl', 'cva', 'tv']; - case 'ignoredKeys': - return ['compoundVariants', 'defaultVariants']; - case 'classRegex': - return '^class(Name)?$'; - case 'config': - if (resolveDefaultConfigPathAlias === null) { - return 'tailwind.config.js'; - } else { - return resolveDefaultConfigPathAlias(); - } - case 'cssFiles': - return ['**/*.css', '!**/node_modules', '!**/.*', '!**/dist', '!**/build']; - case 'cssFilesRefreshRate': - return 5_000; - case 'removeDuplicates': - return true; - case 'skipClassAttribute': - return false; - case 'tags': - return []; - case 'whitelist': - return []; - } -} - -module.exports = getOption; diff --git a/lib/util/types/angle.js b/lib/util/types/angle.js deleted file mode 100644 index 3073b834..00000000 --- a/lib/util/types/angle.js +++ /dev/null @@ -1,11 +0,0 @@ -const units = ['deg', 'grad', 'rad', 'turn']; - -const mergedAngleValues = [ - `\\-?(\\d{1,}(\\.\\d{1,})?|\\.\\d{1,})(${units.join('|')})`, - `calc\\(.{1,}\\)`, - `var\\(\\-\\-[A-Za-z\\-]{1,}\\)`, -]; - -module.exports = { - mergedAngleValues, -}; diff --git a/lib/util/types/color.js b/lib/util/types/color.js deleted file mode 100644 index a6e1452a..00000000 --- a/lib/util/types/color.js +++ /dev/null @@ -1,191 +0,0 @@ -const cssNamedColors = [ - 'indianred', - 'lightcoral', - 'salmon', - 'darksalmon', - 'lightsalmon', - 'crimson', - 'red', - 'firebrick', - 'darkred', - 'pink', - 'lightpink', - 'hotpink', - 'deeppink', - 'mediumvioletred', - 'palevioletred', - 'coral', - 'tomato', - 'orangered', - 'darkorange', - 'orange', - 'gold', - 'yellow', - 'lightyellow', - 'lemonchiffon', - 'lightgoldenrodyellow', - 'papayawhip', - 'moccasin', - 'peachpuff', - 'palegoldenrod', - 'khaki', - 'darkkhaki', - 'lavender', - 'thistle', - 'plum', - 'violet', - 'orchid', - 'fuchsia', - 'magenta', - 'mediumorchid', - 'mediumpurple', - 'blueviolet', - 'darkviolet', - 'darkorchid', - 'darkmagenta', - 'purple', - 'rebeccapurple', - 'indigo', - 'mediumslateblue', - 'slateblue', - 'darkslateblue', - 'greenyellow', - 'chartreuse', - 'lawngreen', - 'lime', - 'limegreen', - 'palegreen', - 'lightgreen', - 'mediumspringgreen', - 'springgreen', - 'mediumseagreen', - 'seagreen', - 'forestgreen', - 'green', - 'darkgreen', - 'yellowgreen', - 'olivedrab', - 'olive', - 'darkolivegreen', - 'mediumaquamarine', - 'darkseagreen', - 'lightseagreen', - 'darkcyan', - 'teal', - 'aqua', - 'cyan', - 'lightcyan', - 'paleturquoise', - 'aquamarine', - 'turquoise', - 'mediumturquoise', - 'darkturquoise', - 'cadetblue', - 'steelblue', - 'lightsteelblue', - 'powderblue', - 'lightblue', - 'skyblue', - 'lightskyblue', - 'deepskyblue', - 'dodgerblue', - 'cornflowerblue', - 'royalblue', - 'blue', - 'mediumblue', - 'darkblue', - 'navy', - 'midnightblue', - 'cornsilk', - 'blanchedalmond', - 'bisque', - 'navajowhite', - 'wheat', - 'burlywood', - 'tan', - 'rosybrown', - 'sandybrown', - 'goldenrod', - 'darkgoldenrod', - 'peru', - 'chocolate', - 'saddlebrown', - 'sienna', - 'brown', - 'maroon', - 'white', - 'snow', - 'honeydew', - 'mintcream', - 'azure', - 'aliceblue', - 'ghostwhite', - 'whitesmoke', - 'seashell', - 'beige', - 'oldlace', - 'floralwhite', - 'ivory', - 'antiquewhite', - 'linen', - 'lavenderblush', - 'mistyrose', - 'gainsboro', - 'lightgray', - 'lightgrey', - 'silver', - 'darkgray', - 'darkgrey', - 'gray', - 'grey', - 'dimgray', - 'dimgrey', - 'lightslategray', - 'lightslategrey', - 'slategray', - 'slategrey', - 'darkslategray', - 'darkslategrey', - 'black', - 'transparent', - 'currentColor', -]; - -// RGB[A] hexa: #123456AA, #B4DA55, #000A, #123 -const hexRGBA = '\\#(([0-9A-Fa-f]{8})|([0-9A-Fa-f]{6})|([0-9A-Fa-f]{4})|([0-9A-Fa-f]{3}))'; - -// RGB 0-255: rgb(10,20,30) -const RGBIntegers = 'rgb\\(\\d{1,3}\\,\\d{1,3}\\,\\d{1,3}\\)'; - -// RGB %: rgb(25%,50%,75%) -const RGBPercentages = 'rgb\\(\\d{1,3}%\\,\\d{1,3}%\\,\\d{1,3}%\\)'; - -// RGBA: rgba(50,100,255,.5), rgba(50,100,255,50%) -const supportedRGBA = 'rgba\\(\\d{1,3}\\,\\d{1,3}\\,\\d{1,3}\\,\\d*(\\.\\d*)?%?\\)'; - -const RGBAPercentages = 'rgba\\(\\d{1,3}%\\,\\d{1,3}%\\,\\d{1,3}%\\,\\d*(\\.\\d*)?%?\\)'; - -const optionalColorPrefixedVar = '(color\\:)?var\\(\\-\\-[A-Za-z\\-]{1,}\\)'; - -const mandatoryColorPrefixed = 'color\\:(?!(hsla\\()).{1,}'; - -const notHSLAPlusWildcard = '(?!(hsla\\()).{1,}'; - -// HSL -const supportedHSL = 'hsl\\(\\d{1,3}%?\\,\\d{1,3}%?\\,\\d{1,3}%?\\)'; - -// 'hsla\\(\\d{1,3}%?\\,\\d{1,3}%?\\,\\d{1,3}%?\\,\\d*(\\.\\d*)?%?\\)', - -const colorValues = [hexRGBA, RGBIntegers, RGBPercentages, supportedRGBA, supportedHSL]; - -const mergedColorValues = [...cssNamedColors, ...colorValues]; - -module.exports = { - cssNamedColors, - colorValues, - mergedColorValues, - RGBAPercentages, - optionalColorPrefixedVar, - mandatoryColorPrefixed, - notHSLAPlusWildcard, -}; diff --git a/lib/util/types/length.js b/lib/util/types/length.js deleted file mode 100644 index f71511e6..00000000 --- a/lib/util/types/length.js +++ /dev/null @@ -1,46 +0,0 @@ -const removeDuplicatesFromArray = require('../removeDuplicatesFromArray'); - -// Units -const fontUnits = ['cap', 'ch', 'em', 'ex', 'ic', 'lh', 'rem', 'rlh']; -const viewportUnits = ['vb', 'vh', 'vi', 'vw', 'vmin', 'vmax']; -const absoluteUnits = ['px', 'mm', 'cm', 'in', 'pt', 'pc']; -const perInchUnits = ['lin', 'pt', 'mm']; -const otherUnits = ['%']; -const mergedUnits = removeDuplicatesFromArray([ - ...fontUnits, - ...viewportUnits, - ...absoluteUnits, - ...perInchUnits, - ...otherUnits, -]); -const selectedUnits = mergedUnits.filter((el) => { - // All units minus this blacklist - return !['cap', 'ic', 'vb', 'vi'].includes(el); -}); - -const absoluteValues = ['0', 'xx\\-small', 'x\\-small', 'small', 'medium', 'large', 'x\\-large', 'xx\\-large']; -const relativeValues = ['larger', 'smaller']; -const globalValues = ['inherit', 'initial', 'unset']; -const mergedValues = [...absoluteValues, ...relativeValues, ...globalValues]; - -const mergedLengthValues = [`\\-?\\d*\\.?\\d*(${mergedUnits.join('|')})`, ...mergedValues]; -mergedLengthValues.push('length\\:var\\(\\-\\-[a-z\\-]{1,}\\)'); - -const mergedUnitsRegEx = `\\[(\\d{1,}(\\.\\d{1,})?|(\\.\\d{1,})?)(${mergedUnits.join('|')})\\]`; - -const selectedUnitsRegEx = `\\[(\\d{1,}(\\.\\d{1,})?|(\\.\\d{1,})?)(${selectedUnits.join('|')})\\]`; - -const anyCalcRegEx = `\\[calc\\(.{1,}\\)\\]`; - -const validZeroRegEx = `^(0(\\.0{1,})?|\\.0{1,})(${mergedUnits.join('|')})?$`; - -module.exports = { - mergedUnits, - selectedUnits, - mergedUnitsRegEx, - selectedUnitsRegEx, - anyCalcRegEx, - mergedValues, - mergedLengthValues, - validZeroRegEx, -}; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index f04c866e..00000000 --- a/package-lock.json +++ /dev/null @@ -1,4866 +0,0 @@ -{ - "name": "eslint-plugin-tailwindcss", - "version": "3.17.2", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "eslint-plugin-tailwindcss", - "version": "3.17.2", - "license": "MIT", - "dependencies": { - "fast-glob": "^3.2.5", - "postcss": "^8.4.4" - }, - "devDependencies": { - "@angular-eslint/template-parser": "^15.2.0", - "@tailwindcss/aspect-ratio": "^0.4.2", - "@tailwindcss/forms": "^0.5.3", - "@tailwindcss/line-clamp": "^0.4.2", - "@tailwindcss/typography": "^0.5.8", - "@typescript-eslint/parser": "^5.50.0", - "autoprefixer": "^10.4.0", - "daisyui": "^2.6.4", - "eslint": "^8.57.0", - "mocha": "^10.2.0", - "semver": "^7.6.0", - "tailwindcss": "^3.4.0", - "typescript": "4.3.5", - "vue-eslint-parser": "^9.4.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "tailwindcss": "^3.4.0" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-15.2.0.tgz", - "integrity": "sha512-a0bfXxYyGoWJHrVQ4QER0HdRgselcTtJeyqiFPAxID2ZxF0IBGKLNTtugUTXekEmiLev8yGLX9TqAtthN57fEg==", - "dev": true - }, - "node_modules/@angular-eslint/template-parser": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-15.2.0.tgz", - "integrity": "sha512-xnnxPfV/G0Ll3B0HGrF1ucsc/DHmNE6UhhmWxYPTERq0McbZGRiATa66hCoOZ/Rdylun4ogBfsRKAG8XxEvlvw==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "15.2.0", - "eslint-scope": "^7.0.0" - }, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@tailwindcss/aspect-ratio": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz", - "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==", - "dev": true, - "peerDependencies": { - "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" - } - }, - "node_modules/@tailwindcss/forms": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz", - "integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==", - "dev": true, - "dependencies": { - "mini-svg-data-uri": "^1.2.3" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" - } - }, - "node_modules/@tailwindcss/line-clamp": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", - "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", - "dev": true, - "peerDependencies": { - "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" - } - }, - "node_modules/@tailwindcss/typography": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.8.tgz", - "integrity": "sha512-xGQEp8KXN8Sd8m6R4xYmwxghmswrd0cPnNI2Lc6fmrC3OojysTBJJGSIVwPV56q4t6THFUK3HJ0EaWwpglSxWw==", - "dev": true, - "dependencies": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "postcss-selector-parser": "6.0.10" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.50.0.tgz", - "integrity": "sha512-KCcSyNaogUDftK2G9RXfQyOCt51uB5yqC6pkUYqhYh8Kgt+DwR5M0EwEAxGPy/+DH6hnmKeGsNhiZRQxjH71uQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.50.0.tgz", - "integrity": "sha512-rt03kaX+iZrhssaT974BCmoUikYtZI24Vp/kwTSy841XhiYShlqoshRFDvN1FKKvU2S3gK+kcBW1EA7kNUrogg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.50.0.tgz", - "integrity": "sha512-atruOuJpir4OtyNdKahiHZobPKFvZnBnfDiyEaBf6d9vy9visE7gDjlmhl+y29uxZ2ZDgvXijcungGFjGGex7w==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.50.0.tgz", - "integrity": "sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.50.0.tgz", - "integrity": "sha512-cdMeD9HGu6EXIeGOh2yVW6oGf9wq8asBgZx7nsR/D36gTfQ0odE5kcRYe5M81vjEFAcPeugXrHg78Imu55F6gg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.50.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz", - "integrity": "sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA==", - "dev": true, - "dependencies": { - "browserslist": "^4.17.5", - "caniuse-lite": "^1.0.30001272", - "fraction.js": "^4.1.1", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.1.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz", - "integrity": "sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001280", - "electron-to-chromium": "^1.3.896", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001286", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001286.tgz", - "integrity": "sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.1.tgz", - "integrity": "sha512-MFJr0uY4RvTQUKvPq7dh9grVOTYSFeXja2mBXioCGjnjJoXrAp9jJ1NQTDR73c9nwBSAQiNKloKl5zq9WB9UPw==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-string": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", - "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", - "dev": true, - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/color/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-selector-tokenizer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", - "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "fastparse": "^1.1.2" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/daisyui": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-2.6.4.tgz", - "integrity": "sha512-3l7WHgpOTdyUBVu2TD6uZH4+IbwaBnPXdoWjjvmzT6hxR5+WUHMl4vvPP+7/VB+CcoxSB296qaYWXQcoWcbISw==", - "dev": true, - "dependencies": { - "color": "^4.2", - "css-selector-tokenizer": "^0.8.0", - "postcss-js": "^4.0.0", - "tailwindcss": "^3.0" - }, - "peerDependencies": { - "autoprefixer": "^10.0.2", - "postcss": "^8.1.6" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.15.tgz", - "integrity": "sha512-WDw2IUL3k4QpbzInV3JZK+Zd1NjWJPDZ28oUSchWb/kf6AVj7/niaAlgcJlvojFa1d7pJSyQ/KSZsEtq5W7aGQ==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", - "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "node_modules/fraction.js": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", - "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=", - "dev": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mini-svg-data-uri": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.3.tgz", - "integrity": "sha512-gSfqpMRC8IxghvMcxzzmMnWpXAChSA+vy4cia33RgerMS8Fex95akUyQZPbxJJmeBGiGmK7n/1OpUX8ksRjIdA==", - "dev": true, - "bin": { - "mini-svg-data-uri": "cli.js" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss": { - "version": "8.4.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", - "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - }, - "engines": { - "node": ">= 14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.11" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-nested/node_modules/postcss-selector-parser": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz", - "integrity": "sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dev": true, - "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sucrase": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", - "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwindcss": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.0.tgz", - "integrity": "sha512-VigzymniH77knD1dryXbyxR+ePHihHociZbXnLZHUyzf2MMs2ZVqlUrZ3FvpXP8pno9JzmILt1sZPD19M3IxtA==", - "dev": true, - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.19.1", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/tailwindcss/node_modules/postcss-selector-parser": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz", - "integrity": "sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/vue-eslint-parser": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz", - "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", - "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true - }, - "@angular-eslint/bundled-angular-compiler": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-15.2.0.tgz", - "integrity": "sha512-a0bfXxYyGoWJHrVQ4QER0HdRgselcTtJeyqiFPAxID2ZxF0IBGKLNTtugUTXekEmiLev8yGLX9TqAtthN57fEg==", - "dev": true - }, - "@angular-eslint/template-parser": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-15.2.0.tgz", - "integrity": "sha512-xnnxPfV/G0Ll3B0HGrF1ucsc/DHmNE6UhhmWxYPTERq0McbZGRiATa66hCoOZ/Rdylun4ogBfsRKAG8XxEvlvw==", - "dev": true, - "requires": { - "@angular-eslint/bundled-angular-compiler": "15.2.0", - "eslint-scope": "^7.0.0" - } - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@tailwindcss/aspect-ratio": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz", - "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==", - "dev": true, - "requires": {} - }, - "@tailwindcss/forms": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz", - "integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==", - "dev": true, - "requires": { - "mini-svg-data-uri": "^1.2.3" - } - }, - "@tailwindcss/line-clamp": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", - "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", - "dev": true, - "requires": {} - }, - "@tailwindcss/typography": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.8.tgz", - "integrity": "sha512-xGQEp8KXN8Sd8m6R4xYmwxghmswrd0cPnNI2Lc6fmrC3OojysTBJJGSIVwPV56q4t6THFUK3HJ0EaWwpglSxWw==", - "dev": true, - "requires": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "postcss-selector-parser": "6.0.10" - } - }, - "@typescript-eslint/parser": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.50.0.tgz", - "integrity": "sha512-KCcSyNaogUDftK2G9RXfQyOCt51uB5yqC6pkUYqhYh8Kgt+DwR5M0EwEAxGPy/+DH6hnmKeGsNhiZRQxjH71uQ==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.50.0", - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/typescript-estree": "5.50.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.50.0.tgz", - "integrity": "sha512-rt03kaX+iZrhssaT974BCmoUikYtZI24Vp/kwTSy841XhiYShlqoshRFDvN1FKKvU2S3gK+kcBW1EA7kNUrogg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0" - } - }, - "@typescript-eslint/types": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.50.0.tgz", - "integrity": "sha512-atruOuJpir4OtyNdKahiHZobPKFvZnBnfDiyEaBf6d9vy9visE7gDjlmhl+y29uxZ2ZDgvXijcungGFjGGex7w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.50.0.tgz", - "integrity": "sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.50.0", - "@typescript-eslint/visitor-keys": "5.50.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.50.0.tgz", - "integrity": "sha512-cdMeD9HGu6EXIeGOh2yVW6oGf9wq8asBgZx7nsR/D36gTfQ0odE5kcRYe5M81vjEFAcPeugXrHg78Imu55F6gg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.50.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz", - "integrity": "sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA==", - "dev": true, - "requires": { - "browserslist": "^4.17.5", - "caniuse-lite": "^1.0.30001272", - "fraction.js": "^4.1.1", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.1.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz", - "integrity": "sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001280", - "electron-to-chromium": "^1.3.896", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001286", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001286.tgz", - "integrity": "sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ==", - "dev": true - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.1.tgz", - "integrity": "sha512-MFJr0uY4RvTQUKvPq7dh9grVOTYSFeXja2mBXioCGjnjJoXrAp9jJ1NQTDR73c9nwBSAQiNKloKl5zq9WB9UPw==", - "dev": true, - "requires": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "dependencies": { - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-string": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", - "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-selector-tokenizer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", - "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "fastparse": "^1.1.2" - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "daisyui": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-2.6.4.tgz", - "integrity": "sha512-3l7WHgpOTdyUBVu2TD6uZH4+IbwaBnPXdoWjjvmzT6hxR5+WUHMl4vvPP+7/VB+CcoxSB296qaYWXQcoWcbISw==", - "dev": true, - "requires": { - "color": "^4.2", - "css-selector-tokenizer": "^0.8.0", - "postcss-js": "^4.0.0", - "tailwindcss": "^3.0" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "electron-to-chromium": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.15.tgz", - "integrity": "sha512-WDw2IUL3k4QpbzInV3JZK+Zd1NjWJPDZ28oUSchWb/kf6AVj7/niaAlgcJlvojFa1d7pJSyQ/KSZsEtq5W7aGQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - } - } - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", - "dev": true - }, - "fastq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", - "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "fraction.js": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", - "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mini-svg-data-uri": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.3.tgz", - "integrity": "sha512-gSfqpMRC8IxghvMcxzzmMnWpXAChSA+vy4cia33RgerMS8Fex95akUyQZPbxJJmeBGiGmK7n/1OpUX8ksRjIdA==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "postcss": { - "version": "8.4.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", - "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", - "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "requires": { - "camelcase-css": "^2.0.1" - } - }, - "postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dev": true, - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - } - }, - "postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.11" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz", - "integrity": "sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - } - } - }, - "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "requires": { - "pify": "^2.3.0" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dev": true, - "requires": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - } - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "sucrase": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", - "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "tailwindcss": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.0.tgz", - "integrity": "sha512-VigzymniH77knD1dryXbyxR+ePHihHociZbXnLZHUyzf2MMs2ZVqlUrZ3FvpXP8pno9JzmILt1sZPD19M3IxtA==", - "dev": true, - "requires": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.19.1", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "postcss-selector-parser": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz", - "integrity": "sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "vue-eslint-parser": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz", - "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==", - "dev": true, - "requires": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yaml": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", - "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json index 77b7308f..a5569d91 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "eslint-plugin-tailwindcss", - "version": "3.17.2", + "version": "4.0.0-alpha.1", "description": "Rules enforcing best practices while using Tailwind CSS", "keywords": [ "eslint", "eslintplugin", "eslint-plugin", "tailwind", - "tailwindcss" + "tailwindcss", + "typescript" ], "author": "FranΓ§ois Massart", "repository": { @@ -17,40 +18,62 @@ "homepage": "https://github.com/francoismassart/eslint-plugin-tailwindcss", "bugs": "https://github.com/francoismassart/eslint-plugin-tailwindcss/issues", "main": "lib/index.js", - "scripts": { - "test": "npm run test:base && npm run test:integration", - "test:base": "mocha \"tests/lib/**/*.js\"", - "test:integration": "mocha \"tests/integrations/*.js\" --timeout 60000" - }, "files": [ - "lib" + "docs/", + "lib/" ], "peerDependencies": { - "tailwindcss": "^3.4.0" + "tailwindcss": "^4.0.0" + }, + "type": "commonjs", + "exports": { + ".": { + "default": "./lib/index.js" + }, + "./package.json": "./package.json" + }, + "scripts": { + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "build": "tsc --build", + "build:diagnostics": "tsc --build --diagnostics", + "watch": "tsc --watch", + "tsup": "tsup ./src/index.ts --outDir lib/", + "tsup:watch": "tsup ./src/index.ts --watch --outDir lib/", + "docs:init": "pnpm build && eslint-doc-generator --init-rule-docs", + "docs:update": "pnpm build && eslint-doc-generator", + "test:jest": "jest", + "test": "vitest" }, "dependencies": { - "fast-glob": "^3.2.5", - "postcss": "^8.4.4" + "@typescript-eslint/utils": "^8.37.0", + "postcss": "^8.4.4", + "synckit": "^0.11.11", + "tailwind-api-utils": "^1.0.3" }, "devDependencies": { - "@angular-eslint/template-parser": "^15.2.0", - "@tailwindcss/aspect-ratio": "^0.4.2", - "@tailwindcss/forms": "^0.5.3", - "@tailwindcss/line-clamp": "^0.4.2", - "@tailwindcss/typography": "^0.5.8", - "@typescript-eslint/parser": "^5.50.0", - "autoprefixer": "^10.4.0", - "daisyui": "^2.6.4", - "eslint": "^8.57.0", - "mocha": "^10.2.0", - "semver": "^7.6.0", - "tailwindcss": "^3.4.0", - "typescript": "4.3.5", - "vue-eslint-parser": "^9.4.2" + "@eslint/js": "^9.16.0", + "@types/eslint": "^8.56.10", + "@types/jest": "^29.5.12", + "@typescript-eslint/parser": "^8.37.0", + "@typescript-eslint/rule-tester": "^8.37.0", + "eslint": "^9.31.0", + "eslint-doc-generator": "^2.2.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-simple-import-sort": "^12.1.1", + "eslint-plugin-unicorn": "^56.0.1", + "globals": "^15.13.0", + "jest": "^29.7.0", + "tailwindcss": "^4.0.0", + "ts-jest": "^29.1.4", + "tsup": "^8.1.0", + "typescript": "^5.4.5", + "typescript-eslint": "^8.18.0", + "vitest": "^1.6.0" }, - "packageManager": "npm@10.2.5+sha256.8002e3e7305d2abd4016e1368af48d49b066c269079eeb10a56e7d6598acfdaa", "engines": { - "node": ">=18.12.0" + "node": ">=20.10.0" }, + "packageManager": "pnpm@8.15.5", "license": "MIT" -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..7cf55ca5 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,5760 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@typescript-eslint/utils': + specifier: ^8.37.0 + version: 8.37.0(eslint@9.31.0)(typescript@5.8.3) + postcss: + specifier: ^8.4.4 + version: 8.5.6 + synckit: + specifier: ^0.11.11 + version: 0.11.11 + tailwind-api-utils: + specifier: ^1.0.3 + version: 1.0.3(tailwindcss@4.1.11) + +devDependencies: + '@eslint/js': + specifier: ^9.16.0 + version: 9.31.0 + '@types/eslint': + specifier: ^8.56.10 + version: 8.56.12 + '@types/jest': + specifier: ^29.5.12 + version: 29.5.14 + '@typescript-eslint/parser': + specifier: ^8.37.0 + version: 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/rule-tester': + specifier: ^8.37.0 + version: 8.37.0(eslint@9.31.0)(typescript@5.8.3) + eslint: + specifier: ^9.31.0 + version: 9.31.0 + eslint-doc-generator: + specifier: ^2.2.2 + version: 2.2.2(eslint@9.31.0)(typescript@5.8.3) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.37.0)(eslint@9.31.0) + eslint-plugin-simple-import-sort: + specifier: ^12.1.1 + version: 12.1.1(eslint@9.31.0) + eslint-plugin-unicorn: + specifier: ^56.0.1 + version: 56.0.1(eslint@9.31.0) + globals: + specifier: ^15.13.0 + version: 15.15.0 + jest: + specifier: ^29.7.0 + version: 29.7.0 + tailwindcss: + specifier: ^4.0.0 + version: 4.1.11 + ts-jest: + specifier: ^29.1.4 + version: 29.4.0(@babel/core@7.28.0)(esbuild@0.25.6)(jest@29.7.0)(typescript@5.8.3) + tsup: + specifier: ^8.1.0 + version: 8.5.0(postcss@8.5.6)(typescript@5.8.3) + typescript: + specifier: ^5.4.5 + version: 5.8.3 + typescript-eslint: + specifier: ^8.18.0 + version: 8.37.0(eslint@9.31.0)(typescript@5.8.3) + vitest: + specifier: ^1.6.0 + version: 1.6.1 + +packages: + + /@ampproject/remapping@2.3.0: + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + dev: true + + /@babel/code-frame@7.27.1: + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + dev: true + + /@babel/compat-data@7.28.0: + resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.28.0: + resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/helpers': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + convert-source-map: 2.0.0 + debug: 4.4.1 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.28.0: + resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + dev: true + + /@babel/helper-compilation-targets@7.27.2: + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.28.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.25.1 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-globals@7.28.0: + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-module-imports@7.27.1: + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0): + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-plugin-utils@7.27.1: + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-string-parser@7.27.1: + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.27.1: + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.27.1: + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers@7.27.6: + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.1 + dev: true + + /@babel/parser@7.28.0: + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.28.1 + dev: true + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.0): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.0): + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.0): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.0): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0): + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.0): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.0): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0): + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.0): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.0): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.0): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.0): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.0): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.0): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.0): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.0): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0): + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/template@7.27.2: + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + dev: true + + /@babel/traverse@7.28.0: + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.1 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.28.1: + resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + dev: true + + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@esbuild/aix-ppc64@0.21.5: + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/aix-ppc64@0.25.6: + resolution: {integrity: sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.21.5: + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.25.6: + resolution: {integrity: sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.21.5: + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.25.6: + resolution: {integrity: sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.21.5: + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.25.6: + resolution: {integrity: sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.21.5: + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.25.6: + resolution: {integrity: sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.21.5: + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.25.6: + resolution: {integrity: sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.21.5: + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.25.6: + resolution: {integrity: sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.21.5: + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.25.6: + resolution: {integrity: sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.21.5: + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.25.6: + resolution: {integrity: sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.21.5: + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.25.6: + resolution: {integrity: sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.21.5: + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.25.6: + resolution: {integrity: sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.21.5: + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.25.6: + resolution: {integrity: sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.21.5: + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.25.6: + resolution: {integrity: sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.21.5: + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.25.6: + resolution: {integrity: sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.21.5: + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.25.6: + resolution: {integrity: sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.21.5: + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.25.6: + resolution: {integrity: sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.21.5: + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.25.6: + resolution: {integrity: sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-arm64@0.25.6: + resolution: {integrity: sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.21.5: + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.25.6: + resolution: {integrity: sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-arm64@0.25.6: + resolution: {integrity: sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.21.5: + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.25.6: + resolution: {integrity: sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openharmony-arm64@0.25.6: + resolution: {integrity: sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.21.5: + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.25.6: + resolution: {integrity: sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.21.5: + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.25.6: + resolution: {integrity: sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.21.5: + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.25.6: + resolution: {integrity: sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.21.5: + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.25.6: + resolution: {integrity: sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.7.0(eslint@9.31.0): + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 9.31.0 + eslint-visitor-keys: 3.4.3 + + /@eslint-community/regexpp@4.12.1: + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + /@eslint/config-array@0.21.0: + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + /@eslint/config-helpers@0.3.0: + resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + /@eslint/core@0.15.1: + resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@types/json-schema': 7.0.15 + + /@eslint/eslintrc@3.3.1: + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + ajv: 6.12.6 + debug: 4.4.1 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + /@eslint/js@9.31.0: + resolution: {integrity: sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + /@eslint/object-schema@2.1.6: + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + /@eslint/plugin-kit@0.3.3: + resolution: {integrity: sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@eslint/core': 0.15.1 + levn: 0.4.1 + + /@humanfs/core@0.19.1: + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + /@humanfs/node@0.16.6: + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + /@humanwhocodes/retry@0.3.1: + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + /@humanwhocodes/retry@0.4.3: + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true + + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/console@29.7.0: + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + dev: true + + /@jest/core@29.7.0: + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@24.0.14) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /@jest/environment@29.7.0: + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + jest-mock: 29.7.0 + dev: true + + /@jest/expect-utils@29.7.0: + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 + dev: true + + /@jest/expect@29.7.0: + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/fake-timers@29.7.0: + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 24.0.14 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + dev: true + + /@jest/globals@29.7.0: + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/reporters@29.7.0: + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.29 + '@types/node': 24.0.14 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jest/source-map@29.6.3: + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.29 + callsites: 3.1.0 + graceful-fs: 4.2.11 + dev: true + + /@jest/test-result@29.7.0: + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + dev: true + + /@jest/test-sequencer@29.7.0: + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + dev: true + + /@jest/transform@29.7.0: + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.28.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.29 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/types@29.6.3: + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 24.0.14 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + dev: true + + /@jridgewell/gen-mapping@0.3.12: + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 + dev: true + + /@jridgewell/resolve-uri@3.1.2: + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.5.4: + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} + dev: true + + /@jridgewell/trace-mapping@0.3.29: + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + /@one-ini/wasm@0.2.0: + resolution: {integrity: sha512-n+L/BvrwKUn7q5O3wHGo+CJZAqfewh38+37sk+eBzv/39lM9pPgPRd4sOZRvSRzo0ukLxzyXso4WlGj2oKZ5hA==} + dev: true + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + + /@pkgr/core@0.2.9: + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dev: false + + /@rollup/rollup-android-arm-eabi@4.45.1: + resolution: {integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.45.1: + resolution: {integrity: sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.45.1: + resolution: {integrity: sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.45.1: + resolution: {integrity: sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-freebsd-arm64@4.45.1: + resolution: {integrity: sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-freebsd-x64@4.45.1: + resolution: {integrity: sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.45.1: + resolution: {integrity: sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-musleabihf@4.45.1: + resolution: {integrity: sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.45.1: + resolution: {integrity: sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.45.1: + resolution: {integrity: sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-loongarch64-gnu@4.45.1: + resolution: {integrity: sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-powerpc64le-gnu@4.45.1: + resolution: {integrity: sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.45.1: + resolution: {integrity: sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-musl@4.45.1: + resolution: {integrity: sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-s390x-gnu@4.45.1: + resolution: {integrity: sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.45.1: + resolution: {integrity: sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.45.1: + resolution: {integrity: sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.45.1: + resolution: {integrity: sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.45.1: + resolution: {integrity: sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.45.1: + resolution: {integrity: sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rtsao/scc@1.1.0: + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + dev: true + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sinonjs/commons@3.0.1: + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers@10.3.0: + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + dependencies: + '@sinonjs/commons': 3.0.1 + dev: true + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.7 + dev: true + + /@types/babel__generator@7.27.0: + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + dependencies: + '@babel/types': 7.28.1 + dev: true + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + dev: true + + /@types/babel__traverse@7.20.7: + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + dependencies: + '@babel/types': 7.28.1 + dev: true + + /@types/eslint@8.56.12: + resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} + dependencies: + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + dev: true + + /@types/estree@1.0.8: + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + /@types/graceful-fs@4.1.9: + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + dependencies: + '@types/node': 24.0.14 + dev: true + + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + + /@types/istanbul-lib-report@3.0.3: + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + dev: true + + /@types/istanbul-reports@3.0.4: + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + dependencies: + '@types/istanbul-lib-report': 3.0.3 + dev: true + + /@types/jest@29.5.14: + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/node@24.0.14: + resolution: {integrity: sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw==} + dependencies: + undici-types: 7.8.0 + dev: true + + /@types/normalize-package-data@2.4.4: + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + dev: true + + /@types/stack-utils@2.0.3: + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + dev: true + + /@types/yargs-parser@21.0.3: + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + dev: true + + /@types/yargs@17.0.33: + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + dependencies: + '@types/yargs-parser': 21.0.3 + dev: true + + /@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0)(eslint@9.31.0)(typescript@5.8.3): + resolution: {integrity: sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.37.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.37.0 + '@typescript-eslint/type-utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.37.0 + eslint: 9.31.0 + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3): + resolution: {integrity: sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + dependencies: + '@typescript-eslint/scope-manager': 8.37.0 + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.37.0 + debug: 4.4.1 + eslint: 9.31.0 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/project-service@8.37.0(typescript@5.8.3): + resolution: {integrity: sha512-BIUXYsbkl5A1aJDdYJCBAo8rCEbAvdquQ8AnLb6z5Lp1u3x5PNgSSx9A/zqYc++Xnr/0DVpls8iQ2cJs/izTXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + dependencies: + '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.8.3) + '@typescript-eslint/types': 8.37.0 + debug: 4.4.1 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + /@typescript-eslint/rule-tester@8.37.0(eslint@9.31.0)(typescript@5.8.3): + resolution: {integrity: sha512-jOdNuyQO6XROMk9yRB6uqA6R/kqwQXM77zgfC4tfDNaPnen5pvqEj5vuouFXoiJs77ZQsGsebJhcPMJeDFuWCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + dependencies: + '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + ajv: 6.12.6 + eslint: 9.31.0 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/scope-manager@8.37.0: + resolution: {integrity: sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/visitor-keys': 8.37.0 + + /@typescript-eslint/tsconfig-utils@8.37.0(typescript@5.8.3): + resolution: {integrity: sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + dependencies: + typescript: 5.8.3 + + /@typescript-eslint/type-utils@8.37.0(eslint@9.31.0)(typescript@5.8.3): + resolution: {integrity: sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + dependencies: + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + debug: 4.4.1 + eslint: 9.31.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@8.37.0: + resolution: {integrity: sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + /@typescript-eslint/typescript-estree@8.37.0(typescript@5.8.3): + resolution: {integrity: sha512-zuWDMDuzMRbQOM+bHyU4/slw27bAUEcKSKKs3hcv2aNnc/tvE/h7w60dwVw8vnal2Pub6RT1T7BI8tFZ1fE+yg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + dependencies: + '@typescript-eslint/project-service': 8.37.0(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.8.3) + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/visitor-keys': 8.37.0 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + /@typescript-eslint/utils@8.37.0(eslint@9.31.0)(typescript@5.8.3): + resolution: {integrity: sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + '@typescript-eslint/scope-manager': 8.37.0 + '@typescript-eslint/types': 8.37.0 + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + eslint: 9.31.0 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + /@typescript-eslint/visitor-keys@8.37.0: + resolution: {integrity: sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@typescript-eslint/types': 8.37.0 + eslint-visitor-keys: 4.2.1 + + /@vitest/expect@1.6.1: + resolution: {integrity: sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==} + dependencies: + '@vitest/spy': 1.6.1 + '@vitest/utils': 1.6.1 + chai: 4.5.0 + dev: true + + /@vitest/runner@1.6.1: + resolution: {integrity: sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==} + dependencies: + '@vitest/utils': 1.6.1 + p-limit: 5.0.0 + pathe: 1.1.2 + dev: true + + /@vitest/snapshot@1.6.1: + resolution: {integrity: sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==} + dependencies: + magic-string: 0.30.17 + pathe: 1.1.2 + pretty-format: 29.7.0 + dev: true + + /@vitest/spy@1.6.1: + resolution: {integrity: sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==} + dependencies: + tinyspy: 2.2.1 + dev: true + + /@vitest/utils@1.6.1: + resolution: {integrity: sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==} + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + + /acorn-jsx@5.3.2(acorn@8.15.0): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.15.0 + + /acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + dependencies: + acorn: 8.15.0 + dev: true + + /acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + /ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + /array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + dev: true + + /array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + dev: true + + /array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + dev: true + + /array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-shim-unscopables: 1.1.0 + dev: true + + /array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-shim-unscopables: 1.1.0 + dev: true + + /arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + dev: true + + /assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + dev: true + + /async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + dev: true + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.1.0 + dev: true + + /babel-jest@29.7.0(@babel/core@7.28.0): + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.28.0 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.28.0) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.27.1 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.1 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.7 + dev: true + + /babel-preset-current-node-syntax@1.1.0(@babel/core@7.28.0): + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.28.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.0) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.0) + dev: true + + /babel-preset-jest@29.6.3(@babel/core@7.28.0): + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.28.0 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.0) + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + /brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + dependencies: + balanced-match: 1.0.2 + + /braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.1.1 + + /browserslist@4.25.1: + resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001727 + electron-to-chromium: 1.5.187 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.25.1) + dev: true + + /bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + dependencies: + fast-json-stable-stringify: 2.1.0 + dev: true + + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /bundle-require@5.1.0(esbuild@0.25.6): + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + dependencies: + esbuild: 0.25.6 + load-tsconfig: 0.2.5 + dev: true + + /cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + dev: true + + /call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + dev: true + + /call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + dev: true + + /call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite@1.0.30001727: + resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} + dev: true + + /chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.4 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.1.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /change-case@5.4.4: + resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} + dev: true + + /char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: true + + /check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + dependencies: + readdirp: 4.1.2 + dev: true + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: true + + /ci-info@4.3.0: + resolution: {integrity: sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==} + engines: {node: '>=8'} + dev: true + + /cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + dev: true + + /clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + dev: true + + /commander@14.0.0: + resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} + engines: {node: '>=20'} + dev: true + + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + /confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + /confbox@0.2.2: + resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} + dev: false + + /consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /core-js-compat@3.44.0: + resolution: {integrity: sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==} + dependencies: + browserslist: 4.25.1 + dev: true + + /cosmiconfig@9.0.0(typescript@5.8.3): + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + typescript: 5.8.3 + dev: true + + /create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@24.0.14) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + /data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + dev: true + + /data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + dev: true + + /data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + + /dedent@1.6.0: + resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + dev: true + + /deep-eql@4.1.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.1.0 + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + dev: true + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: true + + /detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: true + + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dot-prop@9.0.0: + resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} + engines: {node: '>=18'} + dependencies: + type-fest: 4.41.0 + dev: true + + /dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /editorconfig@2.0.1: + resolution: {integrity: sha512-jMVc7LbF/M13cSpBiVWGut+qhIyOddIhSXPAntMSboEigGFGaQmBow9ZrVog0VT2K89qm0cyGHa7FRhcOqP8hA==} + engines: {node: '>=18'} + hasBin: true + dependencies: + '@one-ini/wasm': 0.2.0 + commander: 13.1.0 + minimatch: 10.0.1 + semver: 7.7.2 + dev: true + + /ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.9.2 + dev: true + + /electron-to-chromium@1.5.187: + resolution: {integrity: sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA==} + dev: true + + /emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /enhanced-resolve@5.18.2: + resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.2 + dev: false + + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + dev: true + + /es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + dev: true + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: true + + /es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + dev: true + + /es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + dev: true + + /es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + dependencies: + hasown: 2.0.2 + dev: true + + /es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + dev: true + + /esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + dev: true + + /esbuild@0.25.6: + resolution: {integrity: sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.6 + '@esbuild/android-arm': 0.25.6 + '@esbuild/android-arm64': 0.25.6 + '@esbuild/android-x64': 0.25.6 + '@esbuild/darwin-arm64': 0.25.6 + '@esbuild/darwin-x64': 0.25.6 + '@esbuild/freebsd-arm64': 0.25.6 + '@esbuild/freebsd-x64': 0.25.6 + '@esbuild/linux-arm': 0.25.6 + '@esbuild/linux-arm64': 0.25.6 + '@esbuild/linux-ia32': 0.25.6 + '@esbuild/linux-loong64': 0.25.6 + '@esbuild/linux-mips64el': 0.25.6 + '@esbuild/linux-ppc64': 0.25.6 + '@esbuild/linux-riscv64': 0.25.6 + '@esbuild/linux-s390x': 0.25.6 + '@esbuild/linux-x64': 0.25.6 + '@esbuild/netbsd-arm64': 0.25.6 + '@esbuild/netbsd-x64': 0.25.6 + '@esbuild/openbsd-arm64': 0.25.6 + '@esbuild/openbsd-x64': 0.25.6 + '@esbuild/openharmony-arm64': 0.25.6 + '@esbuild/sunos-x64': 0.25.6 + '@esbuild/win32-arm64': 0.25.6 + '@esbuild/win32-ia32': 0.25.6 + '@esbuild/win32-x64': 0.25.6 + dev: true + + /escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + /eslint-doc-generator@2.2.2(eslint@9.31.0)(typescript@5.8.3): + resolution: {integrity: sha512-LBr0Nz1AZnkifkOMyE0sfx+IvS/V+TK1Sp8fCYDdk4Eb5gZCpEcK4t/ImT23oJAwso26rkHzBCRMrd/bc7bddQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=22.0.0} + hasBin: true + peerDependencies: + eslint: '>= 8.57.1' + dependencies: + '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + ajv: 8.17.1 + change-case: 5.4.4 + commander: 14.0.0 + cosmiconfig: 9.0.0(typescript@5.8.3) + deepmerge: 4.3.1 + dot-prop: 9.0.0 + editorconfig: 2.0.1 + eslint: 9.31.0 + jest-diff: 29.7.0 + json-schema: 0.4.0 + json-schema-traverse: 1.0.0 + markdown-table: 3.0.4 + type-fest: 4.41.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils@2.12.1(@typescript-eslint/parser@8.37.0)(eslint-import-resolver-node@0.3.9)(eslint@9.31.0): + resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + debug: 3.2.7 + eslint: 9.31.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.37.0)(eslint@9.31.0): + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@rtsao/scc': 1.1.0 + '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.31.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.37.0)(eslint-import-resolver-node@0.3.9)(eslint@9.31.0) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-simple-import-sort@12.1.1(eslint@9.31.0): + resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} + peerDependencies: + eslint: '>=5.0.0' + dependencies: + eslint: 9.31.0 + dev: true + + /eslint-plugin-unicorn@56.0.1(eslint@9.31.0): + resolution: {integrity: sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==} + engines: {node: '>=18.18'} + peerDependencies: + eslint: '>=8.56.0' + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + ci-info: 4.3.0 + clean-regexp: 1.0.0 + core-js-compat: 3.44.0 + eslint: 9.31.0 + esquery: 1.6.0 + globals: 15.15.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.1.0 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.7.2 + strip-indent: 3.0.0 + dev: true + + /eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + /eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + /eslint@9.31.0: + resolution: {integrity: sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.0 + '@eslint/core': 0.15.1 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.31.0 + '@eslint/plugin-kit': 0.3.3 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + /espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.8 + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + + /exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + dev: true + + /exsolve@1.0.7: + resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} + dev: false + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + /fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + /fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + dev: true + + /fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + dependencies: + reusify: 1.1.0 + + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: true + + /fdir@6.4.6(picomatch@4.0.3): + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + dependencies: + picomatch: 4.0.3 + dev: true + + /file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + dependencies: + flat-cache: 4.0.1 + + /filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + dependencies: + minimatch: 5.1.6 + dev: true + + /fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + /fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} + dependencies: + magic-string: 0.30.17 + mlly: 1.7.4 + rollup: 4.45.1 + dev: true + + /flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + /flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + /for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + dev: true + + /foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + dev: true + + /get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + dev: true + + /get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + + /glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + /globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + dev: true + + /globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + dev: true + + /gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.1 + dev: true + + /has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + dependencies: + dunder-proto: 1.0.1 + dev: true + + /has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.1.0 + dev: true + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + + /ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + /ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + /import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + dev: true + + /is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + dev: true + + /is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + dependencies: + has-bigints: 1.1.0 + dev: true + + /is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + dev: true + + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + dependencies: + hasown: 2.0.2 + dev: true + + /is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + dev: true + + /is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + /is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + + /is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + + /is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + dev: true + + /is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + /is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + dev: true + + /is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + dev: true + + /is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + dev: true + + /is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + dev: true + + /is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.19 + dev: true + + /is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + dev: true + + /is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + dev: true + + /is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.28.0 + '@babel/parser': 7.28.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + dependencies: + '@babel/core': 7.28.0 + '@babel/parser': 7.28.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.4.1 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + + /jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true + + /jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + dev: true + + /jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + dev: true + + /jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.6.0 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true + + /jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0 + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@24.0.14) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /jest-config@29.7.0(@types/node@24.0.14): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.28.0 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + babel-jest: 29.7.0(@babel/core@7.28.0) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true + + /jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true + + /jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + detect-newline: 3.1.0 + dev: true + + /jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + dev: true + + /jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + jest-mock: 29.7.0 + jest-util: 29.7.0 + dev: true + + /jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 24.0.14 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true + + /jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true + + /jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/code-frame': 7.27.1 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + dev: true + + /jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + jest-util: 29.7.0 + dev: true + + /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 29.7.0 + dev: true + + /jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.10 + resolve.exports: 2.0.3 + slash: 3.0.0 + dev: true + + /jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + chalk: 4.1.2 + cjs-module-lexer: 1.4.3 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.28.0 + '@babel/generator': 7.28.0 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/types': 7.28.1 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.0) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + dev: true + + /jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + dev: true + + /jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 24.0.14 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + dev: true + + /jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 24.0.14 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + dev: false + + /joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + dev: true + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + + /jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + + /leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + /lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + dependencies: + mlly: 1.7.4 + pkg-types: 1.3.1 + dev: true + + /local-pkg@1.1.1: + resolution: {integrity: sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==} + engines: {node: '>=14'} + dependencies: + mlly: 1.7.4 + pkg-types: 2.2.0 + quansync: 0.2.10 + dev: false + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + + /lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + /lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + dev: true + + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + dev: true + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.7.2 + dev: true + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + + /markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + dev: true + + /math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + /micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + dependencies: + brace-expansion: 2.0.2 + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.12 + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.2 + dev: true + + /minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.2 + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + + /mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + dependencies: + acorn: 8.15.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.1 + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: true + + /nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + + /node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + dev: true + + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.10 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + dev: true + + /object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + dev: true + + /object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + dev: true + + /object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + /own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + + /p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + dependencies: + yocto-queue: 1.2.1 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + dev: true + + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + dev: true + + /pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + /pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + + /picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + /picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + dev: true + + /pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + dev: true + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.3 + + /pkg-types@2.2.0: + resolution: {integrity: sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==} + dependencies: + confbox: 0.2.2 + exsolve: 1.0.7 + pathe: 2.0.3 + dev: false + + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + + /possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + dev: true + + /postcss-load-config@6.0.1(postcss@8.5.6): + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + dependencies: + lilconfig: 3.1.3 + postcss: 8.5.6 + dev: true + + /postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + dev: true + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + /pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + dev: true + + /quansync@0.2.10: + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} + dev: false + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + /react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + dev: true + + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + dev: true + + /reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + dev: true + + /regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + dev: true + + /regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + dev: true + + /regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} + dev: true + + /resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + /rollup@4.45.1: + resolution: {integrity: sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.45.1 + '@rollup/rollup-android-arm64': 4.45.1 + '@rollup/rollup-darwin-arm64': 4.45.1 + '@rollup/rollup-darwin-x64': 4.45.1 + '@rollup/rollup-freebsd-arm64': 4.45.1 + '@rollup/rollup-freebsd-x64': 4.45.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.45.1 + '@rollup/rollup-linux-arm-musleabihf': 4.45.1 + '@rollup/rollup-linux-arm64-gnu': 4.45.1 + '@rollup/rollup-linux-arm64-musl': 4.45.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.45.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.45.1 + '@rollup/rollup-linux-riscv64-gnu': 4.45.1 + '@rollup/rollup-linux-riscv64-musl': 4.45.1 + '@rollup/rollup-linux-s390x-gnu': 4.45.1 + '@rollup/rollup-linux-x64-gnu': 4.45.1 + '@rollup/rollup-linux-x64-musl': 4.45.1 + '@rollup/rollup-win32-arm64-msvc': 4.45.1 + '@rollup/rollup-win32-ia32-msvc': 4.45.1 + '@rollup/rollup-win32-x64-msvc': 4.45.1 + fsevents: 2.3.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + + /safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + dev: true + + /safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + dev: true + + /safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + dev: true + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + dev: true + + /set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + dev: true + + /set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + /side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + dev: true + + /side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + dev: true + + /side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + dev: true + + /side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + dev: true + + /siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + /source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + dependencies: + whatwg-url: 7.1.0 + dev: true + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.21 + dev: true + + /spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 + dev: true + + /spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + + /stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + dev: true + + /std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + dev: true + + /stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + dev: true + + /string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + dev: true + + /string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + dev: true + + /string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.1.0 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + /strip-literal@2.1.1: + resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==} + dependencies: + js-tokens: 9.0.1 + dev: true + + /sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + ts-interface-checker: 0.1.13 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /synckit@0.11.11: + resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.2.9 + dev: false + + /tailwind-api-utils@1.0.3(tailwindcss@4.1.11): + resolution: {integrity: sha512-KpzUHkH1ug1sq4394SLJX38ZtpeTiqQ1RVyFTTSY2XuHsNSTWUkRo108KmyyrMWdDbQrLYkSHaNKj/a3bmA4sQ==} + peerDependencies: + tailwindcss: ^3.3.0 || ^4.0.0 || ^4.0.0-beta + dependencies: + enhanced-resolve: 5.18.2 + jiti: 2.4.2 + local-pkg: 1.1.1 + tailwindcss: 4.1.11 + dev: false + + /tailwindcss@4.1.11: + resolution: {integrity: sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==} + + /tapable@2.2.2: + resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==} + engines: {node: '>=6'} + dev: false + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: true + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: true + + /tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + dev: true + + /tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + dev: true + + /tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + dependencies: + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + dev: true + + /tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + dev: true + + /tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + + /tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + dependencies: + punycode: 2.3.1 + dev: true + + /tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + + /ts-api-utils@2.1.0(typescript@5.8.3): + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + dependencies: + typescript: 5.8.3 + + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: true + + /ts-jest@29.4.0(@babel/core@7.28.0)(esbuild@0.25.6)(jest@29.7.0)(typescript@5.8.3): + resolution: {integrity: sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 || ^30.0.0 + '@jest/types': ^29.0.0 || ^30.0.0 + babel-jest: ^29.0.0 || ^30.0.0 + esbuild: '*' + jest: ^29.0.0 || ^30.0.0 + jest-util: ^29.0.0 || ^30.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/transform': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + jest-util: + optional: true + dependencies: + '@babel/core': 7.28.0 + bs-logger: 0.2.6 + ejs: 3.1.10 + esbuild: 0.25.6 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.7.2 + type-fest: 4.41.0 + typescript: 5.8.3 + yargs-parser: 21.1.1 + dev: true + + /tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tsup@8.5.0(postcss@8.5.6)(typescript@5.8.3): + resolution: {integrity: sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + dependencies: + bundle-require: 5.1.0(esbuild@0.25.6) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.2 + debug: 4.4.1 + esbuild: 0.25.6 + fix-dts-default-cjs-exports: 1.0.1 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-load-config: 6.0.1(postcss@8.5.6) + resolve-from: 5.0.0 + rollup: 4.45.1 + source-map: 0.8.0-beta.0 + sucrase: 3.35.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tree-kill: 1.2.2 + typescript: 5.8.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + dev: true + + /typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + dev: true + + /typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + dev: true + + /typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + dev: true + + /typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + dev: true + + /typescript-eslint@8.37.0(eslint@9.31.0)(typescript@5.8.3): + resolution: {integrity: sha512-TnbEjzkE9EmcO0Q2zM+GE8NQLItNAJpMmED1BdgoBMYNdqMhzlbqfdSwiRlAzEK2pA9UzVW0gzaaIzXWg2BjfA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + dependencies: + '@typescript-eslint/eslint-plugin': 8.37.0(@typescript-eslint/parser@8.37.0)(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + eslint: 9.31.0 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + dev: true + + /typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + /ufo@1.6.1: + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + + /unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + dev: true + + /undici-types@7.8.0: + resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + dev: true + + /update-browserslist-db@1.1.3(browserslist@4.25.1): + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.25.1 + escalade: 3.2.0 + picocolors: 1.1.1 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + + /v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.29 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /vite-node@1.6.1: + resolution: {integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.4.1 + pathe: 1.1.2 + picocolors: 1.1.1 + vite: 5.4.19 + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vite@5.4.19: + resolution: {integrity: sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.21.5 + postcss: 8.5.6 + rollup: 4.45.1 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vitest@1.6.1: + resolution: {integrity: sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.6.1 + '@vitest/ui': 1.6.1 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@vitest/expect': 1.6.1 + '@vitest/runner': 1.6.1 + '@vitest/snapshot': 1.6.1 + '@vitest/spy': 1.6.1 + '@vitest/utils': 1.6.1 + acorn-walk: 8.3.4 + chai: 4.5.0 + debug: 4.4.1 + execa: 8.0.1 + local-pkg: 0.5.1 + magic-string: 0.30.17 + pathe: 1.1.2 + picocolors: 1.1.1 + std-env: 3.9.0 + strip-literal: 2.1.1 + tinybench: 2.9.0 + tinypool: 0.8.4 + vite: 5.4.19 + vite-node: 1.6.1 + why-is-node-running: 2.3.0 + transitivePeerDependencies: + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + dev: true + + /walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + + /webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + dev: true + + /whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + dev: true + + /which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + dev: true + + /which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + dev: true + + /which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + dev: true + + /which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + + /why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + dev: true + + /word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + /yocto-queue@1.2.1: + resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} + engines: {node: '>=12.20'} + dev: true diff --git a/setup-vitest.js b/setup-vitest.js new file mode 100644 index 00000000..24e3ffdc --- /dev/null +++ b/setup-vitest.js @@ -0,0 +1,9 @@ +import { RuleTester } from "@typescript-eslint/rule-tester"; +import * as vitest from "vitest"; + +RuleTester.afterAll = vitest.afterAll; + +// If you are not using vitest with globals: true (https://vitest.dev/config/#globals): +RuleTester.it = vitest.it; +RuleTester.itOnly = vitest.it.only; +RuleTester.describe = vitest.describe; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..7d36fc01 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,38 @@ +import * as parserBase from "@typescript-eslint/parser"; +import { TSESLint } from "@typescript-eslint/utils"; +import { Linter } from "@typescript-eslint/utils/ts-eslint"; + +import { rules } from "./rules"; + +export const parser: TSESLint.FlatConfig.Parser = { + meta: parserBase.meta, + parseForESLint: parserBase.parseForESLint, +}; + +const { name, version } = + // `import`ing here would bypass the TSConfig's `"rootDir": "src"` + // Also an import statement will make TSC copy the package.json to the dist folder + // eslint-disable-next-line @typescript-eslint/no-require-imports + require("../package.json") as { + name: string; + version: string; + }; + +/** + * TODO: Add configs (recommended, etc.) + * @see https://github.com/typescript-eslint/examples/blob/main/packages/eslint-plugin-example-typed-linting/src/index.ts + */ + +// Plugin not fully initialized yet. +// See https://eslint.org/docs/latest/extend/plugins#configs-in-plugins +const plugin = { + // `configs`, assigned later + configs: {}, + rules, + meta: { + name, + version, + }, +} satisfies Linter.Plugin; + +export default plugin; diff --git a/src/rules/index.ts b/src/rules/index.ts new file mode 100644 index 00000000..030be60c --- /dev/null +++ b/src/rules/index.ts @@ -0,0 +1,5 @@ +import { myRule, RULE_NAME as MY_RULE } from "./my-rule"; + +export const rules = { + [MY_RULE]: myRule, +}; diff --git a/src/rules/my-rule.spec.ts b/src/rules/my-rule.spec.ts new file mode 100644 index 00000000..3a40ac8e --- /dev/null +++ b/src/rules/my-rule.spec.ts @@ -0,0 +1,85 @@ +import * as Parser from "@typescript-eslint/parser"; +import { RuleTester } from "@typescript-eslint/rule-tester"; + +import { myRule, RULE_NAME } from "./my-rule"; + +const ruleTester = new RuleTester({ + languageOptions: { + parser: Parser, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, +}); + +ruleTester.run(RULE_NAME, myRule, { + valid: [ + { + // a code snippet that should pass the linter + code: `const x = 5;`, + options: [ + { + callees: ["ctl2"], + someBool: true, + someEnum: "always", + }, + ], + }, + { + code: `let y = 'abc123';`, + }, + { + code: ``, + }, + { + // a code snippet that should pass the linter + code: `var x = 5;`, + options: [ + { + someBool: true, + someEnum: "always", + }, + ], + }, + ], + invalid: [ + { + code: `var z = 'foo'`, + errors: [ + { + messageId: "issue:var", + suggestions: [ + { + messageId: "fix:let", + output: `let z = 'foo'`, + }, + { + messageId: "fix:const", + output: `const z = 'foo'`, + }, + ], + }, + ], + }, + { + code: ``, + errors: [ + { + messageId: "issue:var", + suggestions: [ + { + messageId: "fix:let", + output: ``, + }, + { + messageId: "fix:const", + output: ``, + }, + ], + }, + ], + }, + ], +}); diff --git a/src/rules/my-rule.ts b/src/rules/my-rule.ts new file mode 100644 index 00000000..498f36b4 --- /dev/null +++ b/src/rules/my-rule.ts @@ -0,0 +1,142 @@ +import { RuleCreator } from "@typescript-eslint/utils/eslint-utils"; + +import { PluginSharedSettings } from "../types"; +import urlCreator from "../url-creator"; +import { + DEFAULTS, + parsePluginSettings, + type PluginSettings, + sharedSettingsSchema, +} from "../utils/parse-plugin-settings"; + +export { ESLintUtils } from "@typescript-eslint/utils"; + +export const RULE_NAME = "my-rule"; + +// Message IDs don't need to be prefixed, I just find it easier to keep track of them this way +type MessageIds = "issue:var" | "fix:let" | "fix:const"; + +/** + * The extra options that the rule can accept. + * These options get merged with the shared settings. + * The typing is not used by `eslint-doc-generator` which uses the `schema` property in the rule's metadata. + * Yet, it is useful for the IDE to provide autocompletion and type checking. + */ +type RuleOptions = { + someBool: boolean; + someEnum: string; +}; + +export type MergedOptions = RuleOptions & PluginSettings; + +const RULE_DEFAULT: RuleOptions = { + someBool: false, + someEnum: "always", +}; + +// TODO which one ? +// - type Options = [RuleOptions]; +// - type Options = [MergedOptions]; +type Options = [MergedOptions]; + +// The Rule creator returns a function that is used to create a well-typed ESLint rule +// The parameter passed into RuleCreator is a URL generator function. +export const createRule = RuleCreator(urlCreator); + +export const myRule = createRule({ + name: RULE_NAME, + meta: { + docs: { + description: "An example ESLint rule", + }, + hasSuggestions: true, + messages: { + "issue:var": "Prefer using `let` or `const`", + "fix:let": "Replace this `var` declaration with `let`", + "fix:const": "Replace this `var` declaration with `const`", + }, + // Schema is also parsed by `eslint-doc-generator` + schema: [ + { + type: "object", + properties: { + ...sharedSettingsSchema, + someBool: { + description: "someBool description.", + type: "boolean", + default: RULE_DEFAULT.someBool, + }, + someEnum: { + description: "someEnum description.", + type: "string", + enum: ["always", "never"], + default: RULE_DEFAULT.someEnum, + }, + }, + additionalProperties: false, + }, + ], + type: "suggestion", + }, + /** + * About `defaultOptions`: + * - `defaultOptions` is not used in the generated documentation + * - `defaultOptions` is used when options are not provided in the rules configuration + * - If some configuration is provided as the second argument, it is ignored, not merged + * - In other words, the `defaultOptions` is only used when the rule is used without configuration + */ + defaultOptions: [ + { + ...DEFAULTS, + someBool: false, + someEnum: "always", + }, + ], + create: (context, options) => { + // Reading inline configuration + console.log("\n", new Date(), "\n", "Options (rule):", "\n", options[0]); + + // Shared settings + const sharedSettings = (context.settings?.tailwindcss || + DEFAULTS) as PluginSharedSettings; + console.log("\n", "sharedSettings (rule):", "\n", sharedSettings); + + // Merged settings + // const merged = parsePluginSettings(options[0]) as RuleOptions; + const merged = parsePluginSettings({ + tailwindcss: options[0], + }) as RuleOptions; + console.log("\n", "merged (rule):", "\n", merged); + + return { + VariableDeclaration: (node) => { + console.log("\n", "merged.someBool:", "\n", merged.someBool); + if (merged.someBool === true) { + console.log("someBool is true, processing VariableDeclaration"); + return; + } + if (node.kind === "var") { + const rangeStart = node.range[0]; + const range: readonly [number, number] = [ + rangeStart, + rangeStart + 3 /* 'var'.length */, + ]; + context.report({ + node, + messageId: "issue:var", // Prints the message with this ID when a problem is found + suggest: [ + { + messageId: "fix:let", + fix: (fixer) => fixer.replaceTextRange(range, "let"), + }, + { + messageId: "fix:const", + fix: (fixer) => fixer.replaceTextRange(range, "const"), + }, + ], + }); + } + }, + }; + }, +}); diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..a15580a6 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,37 @@ +export interface PluginSharedSettings { + /** + * @description Path to the CSS stylesheet in your Tailwind project (v4+) + * @example "src/styles/tailwind.css" + */ + stylesheet?: string; + /** + * @description Path to Tailwind configuration file + * @example "tailwind.config.js" + */ + config?: string; + /** + * @description List of attributes/props that contain sortable Tailwind classes + * @default [] + * @example ["className"] + */ + attributes?: Array; + /** + * @description List of functions and tagged templates that contain sortable Tailwind classes + * @default [] + * @example ["clsx", "tw", "ctl"] + */ + functions?: Array; + /** + * @description Preserve whitespace around Tailwind classes when sorting + * @default false + */ + preserveWhitespace?: boolean; + /** + * @description Preserve duplicate classes inside a class list when sorting + * @default false + */ + preserveDuplicates?: boolean; +} +export interface SharedConfigurationSettings { + tailwindcss?: PluginSharedSettings; +} diff --git a/src/url-creator.ts b/src/url-creator.ts new file mode 100644 index 00000000..a31ef8e3 --- /dev/null +++ b/src/url-creator.ts @@ -0,0 +1,4 @@ +export default function urlCreator(name: string) { + // return `https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/HEAD/docs/rules/${name}.md`; + return `https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/alpha/v4-basic-files/docs/rules/${name}.md`; +} diff --git a/src/utils/parse-plugin-settings.ts b/src/utils/parse-plugin-settings.ts new file mode 100644 index 00000000..c3528152 --- /dev/null +++ b/src/utils/parse-plugin-settings.ts @@ -0,0 +1,82 @@ +// Inspired by https://github.com/vitest-dev/eslint-plugin-vitest/blob/7fb864c28f91a92891c7a4fa025ca9d2a9780d49/src/utils/parse-plugin-settings.ts + +import { JSONSchema4 } from "@typescript-eslint/utils/json-schema"; +import type { SharedConfigurationSettings } from "@typescript-eslint/utils/ts-eslint"; + +/** + * Typing of the shared settings of the eslint-plugin-tailwindcss. + */ +export type PluginSettings = { + callees?: Array; // TODO can we use a {Set} instead ? + cssConfigPath?: string; + removeDuplicates?: boolean; + skipClassAttribute?: boolean; + tags?: Array; // TODO can we use a {Set} instead ? +}; + +/** + * The default values for the shared settings. + */ +export const DEFAULTS: PluginSettings = { + callees: ["ctl"], + cssConfigPath: "default-path/app.css", + removeDuplicates: true, + skipClassAttribute: false, + tags: ["tw"], +}; + +/** + * The JSON schema for the shared settings to be reused in many of the rule's configuration. + */ +export const sharedSettingsSchema: Record = { + callees: { + description: "List of function names to validate classnames", + type: "array", + items: { type: "string", minLength: 0 }, + uniqueItems: true, + default: DEFAULTS.callees, + }, + cssConfigPath: { + description: "Path to the Tailwind CSS configuration file (*.css)", + type: "string", + default: DEFAULTS.cssConfigPath, + }, + removeDuplicates: { + description: "Remove duplicated classnames", + type: "boolean", + default: DEFAULTS.removeDuplicates, + }, + skipClassAttribute: { + description: + "If you only want to lint the classnames inside one of the `callees`.", + type: "boolean", + default: DEFAULTS.skipClassAttribute, + }, + tags: { + description: "List of tags to be detected in template literals", + type: "array", + items: { type: "string", minLength: 0 }, + uniqueItems: true, + default: DEFAULTS.tags, + }, +}; + +/** + * @description Parses the global eslint settings and merge. + * @param settings The shared settings from the ESLint configuration. + * @returns The parsed plugin settings. + */ +export function parsePluginSettings( + settings: SharedConfigurationSettings +): PluginSettings & RuleOptions { + const tailwindcssSettings = ( + typeof settings.tailwindcss !== "object" || settings.tailwindcss === null + ? {} + : settings.tailwindcss + ) as PluginSettings & RuleOptions; + + return { + ...DEFAULTS, + ...tailwindcssSettings, + }; +} diff --git a/src/utils/tailwindcss-api/index.ts b/src/utils/tailwindcss-api/index.ts new file mode 100644 index 00000000..3cc636be --- /dev/null +++ b/src/utils/tailwindcss-api/index.ts @@ -0,0 +1,21 @@ +import { createSyncFn } from "synckit"; + +import { type Theme } from "./types"; + +export const loadThemeWorker: (cssConfigPath: string) => Theme = createSyncFn( + require.resolve("./worker/load-theme.mjs") +); + +export const getSortedClassNamesWorker: ( + cssConfigPath: string, + unorderedClassNames: Array +) => Array = createSyncFn( + require.resolve("./worker/get-sorted-class-names.mjs") +); + +export const isValidClassNameWorker: ( + cssConfigPath: string, + className: string +) => boolean = createSyncFn( + require.resolve("./worker/is-valid-class-name.mjs") +); diff --git a/src/utils/tailwindcss-api/types.d.ts b/src/utils/tailwindcss-api/types.d.ts new file mode 100644 index 00000000..1e6947ef --- /dev/null +++ b/src/utils/tailwindcss-api/types.d.ts @@ -0,0 +1,27 @@ +export type TailwindConfig = { + separator?: string; + prefix?: string; + content?: { + files?: Array; + }; +}; + +export interface DesignSystem { + getClassOrder: (classes: Array) => Array<[string, bigint | null]>; + candidatesToCss: (classes: Array) => Array; + tailwindConfig?: TailwindConfig; +} + +type ThemeValue = { + value: string; + options: number; + src: string | undefined; +}; + +export type Theme = { + prefix: string; + values: Map; + // @ts-expect-error Unexpected any. Specify a different type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + keyframes: Set; +}; diff --git a/src/utils/tailwindcss-api/worker/get-sorted-class-names.mjs b/src/utils/tailwindcss-api/worker/get-sorted-class-names.mjs new file mode 100644 index 00000000..1d1ef218 --- /dev/null +++ b/src/utils/tailwindcss-api/worker/get-sorted-class-names.mjs @@ -0,0 +1,40 @@ +/** + * ⚠️ This is a worker script which is ran in node's `worker_threads`. + * πŸ€“ This means that it is not executed in the main thread, but in a separate thread. + * πŸ˜… Because of this, expect some disturbances, like: + * - `console.log` won't work `vitest`... (seems to work with `jest`). + * - You cannot pass complex objects as arguments, only serializable ones. + * - You cannot retun complex objects, only serializable ones. + * - e.g. You cannot return the `utils.context` directly, but you can return some of its properties... + * + * ℹ️ It uses the `*.mjs` extension to indicate that it is an ES module. + * βœ… We still check the syntax with TypeScript, but it is not a TypeScript file. + */ + +// @ts-check + +import { runAsWorker } from "synckit"; +import { TailwindUtils } from "tailwind-api-utils"; + +runAsWorker( + async ( + /** + * @type {string} The path to the Tailwind CSS config file + */ + cssConfigPath, + /** + * @type {Array} List of class names to sort + */ + unorderedClassNames + ) => { + const utils = new TailwindUtils(); + await utils.loadConfigV4(cssConfigPath); + if (!utils.context) { + throw new Error( + `Failed to load the Tailwind CSS theme using: "${cssConfigPath}"` + ); + } + const sorted = await utils.getSortedClassNames(unorderedClassNames); + return sorted; + } +); diff --git a/src/utils/tailwindcss-api/worker/get-sorted-class-names.spec.ts b/src/utils/tailwindcss-api/worker/get-sorted-class-names.spec.ts new file mode 100644 index 00000000..ee7ce348 --- /dev/null +++ b/src/utils/tailwindcss-api/worker/get-sorted-class-names.spec.ts @@ -0,0 +1,45 @@ +import { expect, test } from "vitest"; + +import { getSortedClassNamesWorker } from ".."; + +test(`Sort classnames based on "normal.css"`, () => { + const path = require.resolve("../../../../tests/stubs/css/normal.css"); + const unorderdClassNames = [ + "lg:flex", + "block", + "top-0", + "unknown", + "text-red-100", + ]; + const sorted = getSortedClassNamesWorker(path, unorderdClassNames); + // Unknown classnames should be first + expect(sorted[0]).toBe("unknown"); + // The rest should be sorted as well + expect(sorted).toStrictEqual([ + "unknown", + "top-0", + "block", + "text-red-100", + "lg:flex", + ]); +}); + +test(`Sort "tw:" prefixed classnames based on "tiny-prefixed.css"`, () => { + const path = require.resolve("../../../../tests/stubs/css/tiny-prefixed.css"); + const unorderdClassNames = [ + "tw:flex", + "tw:unknown", + "tw:hover:text-tiny", + "tw:top-0", + ]; + const sorted = getSortedClassNamesWorker(path, unorderdClassNames); + // Unknown classnames should be first + expect(sorted[0]).toBe("tw:unknown"); + // The rest should be sorted as well + expect(sorted).toStrictEqual([ + "tw:unknown", + "tw:top-0", + "tw:flex", + "tw:hover:text-tiny", + ]); +}); diff --git a/src/utils/tailwindcss-api/worker/is-valid-class-name.mjs b/src/utils/tailwindcss-api/worker/is-valid-class-name.mjs new file mode 100644 index 00000000..dacee2d9 --- /dev/null +++ b/src/utils/tailwindcss-api/worker/is-valid-class-name.mjs @@ -0,0 +1,40 @@ +/** + * ⚠️ This is a worker script which is ran in node's `worker_threads`. + * πŸ€“ This means that it is not executed in the main thread, but in a separate thread. + * πŸ˜… Because of this, expect some disturbances, like: + * - `console.log` won't work `vitest`... (seems to work with `jest`). + * - You cannot pass complex objects as arguments, only serializable ones. + * - You cannot retun complex objects, only serializable ones. + * - e.g. You cannot return the `utils.context` directly, but you can return some of its properties... + * + * ℹ️ It uses the `*.mjs` extension to indicate that it is an ES module. + * βœ… We still check the syntax with TypeScript, but it is not a TypeScript file. + */ + +// @ts-check + +import { runAsWorker } from "synckit"; +import { TailwindUtils } from "tailwind-api-utils"; + +runAsWorker( + async ( + /** + * @type {string} The path to the Tailwind CSS config file + */ + cssConfigPath, + /** + * @type {string} Class name to validate + */ + className + ) => { + const utils = new TailwindUtils(); + await utils.loadConfigV4(cssConfigPath); + if (!utils.context) { + throw new Error( + `Failed to load the Tailwind CSS theme using: "${cssConfigPath}"` + ); + } + const sorted = await utils.isValidClassName(className); + return sorted; + } +); diff --git a/src/utils/tailwindcss-api/worker/is-valid-class-name.spec.ts b/src/utils/tailwindcss-api/worker/is-valid-class-name.spec.ts new file mode 100644 index 00000000..0ca5cfd1 --- /dev/null +++ b/src/utils/tailwindcss-api/worker/is-valid-class-name.spec.ts @@ -0,0 +1,22 @@ +import { expect, test } from "vitest"; + +import { isValidClassNameWorker } from ".."; + +test(`Validate classnames based on "normal.css"`, () => { + const path = require.resolve("../../../../tests/stubs/css/normal.css"); + // Unknown classnames should be invalid + expect(isValidClassNameWorker(path, "unknown")).toBe(false); + // Known classnames should be valid + expect(isValidClassNameWorker(path, "flex")).toBe(true); +}); + +test(`Validate "tw:" prefixed classnames based on "tiny-prefixed.css"`, () => { + const path = require.resolve("../../../../tests/stubs/css/tiny-prefixed.css"); + // Unknown classnames should be invalid + expect(isValidClassNameWorker(path, "tw:unknown")).toBe(false); + // Known classnames should be valid + expect(isValidClassNameWorker(path, "tw:flex")).toBe(true); + expect(isValidClassNameWorker(path, "tw:border-tiny")).toBe(true); + // Unprefixed classnames should be invalid + expect(isValidClassNameWorker(path, "flex")).toBe(false); +}); diff --git a/src/utils/tailwindcss-api/worker/load-theme.mjs b/src/utils/tailwindcss-api/worker/load-theme.mjs new file mode 100644 index 00000000..1d309306 --- /dev/null +++ b/src/utils/tailwindcss-api/worker/load-theme.mjs @@ -0,0 +1,36 @@ +/** + * ⚠️ This is a worker script which is ran in node's `worker_threads`. + * πŸ€“ This means that it is not executed in the main thread, but in a separate thread. + * πŸ˜… Because of this, expect some disturbances, like: + * - `console.log` won't work `vitest`... (seems to work with `jest`). + * - You cannot pass complex objects as arguments, only serializable ones. + * - You cannot retun complex objects, only serializable ones. + * - e.g. You cannot return the `utils.context` directly, but you can return some of its properties... + * + * ℹ️ It uses the `*.mjs` extension to indicate that it is an ES module. + * βœ… We still check the syntax with TypeScript, but it is not a TypeScript file. + */ + +// @ts-check + +import { runAsWorker } from "synckit"; +import { TailwindUtils } from "tailwind-api-utils"; + +runAsWorker( + async ( + /** + * @type {string} The path to the Tailwind CSS config file + */ + cssConfigPath + ) => { + const utils = new TailwindUtils(); + await utils.loadConfigV4(cssConfigPath); + if (!utils.context) { + throw new Error( + `Failed to load the Tailwind CSS theme using: "${cssConfigPath}"` + ); + } + // @ts-expect-error Property 'theme' does not exist on type 'DesignSystem'.ts(2339) + return utils.context?.theme; + } +); diff --git a/src/utils/tailwindcss-api/worker/load-theme.spec.ts b/src/utils/tailwindcss-api/worker/load-theme.spec.ts new file mode 100644 index 00000000..8054eb24 --- /dev/null +++ b/src/utils/tailwindcss-api/worker/load-theme.spec.ts @@ -0,0 +1,14 @@ +import { expect, test } from "vitest"; + +import { loadThemeWorker } from ".."; + +test(`load theme from "tiny-prefixed.css"`, () => { + const path = require.resolve("../../../../tests/stubs/css/tiny-prefixed.css"); + const theme = loadThemeWorker(path); + expect(theme.prefix).toBe("tw"); + expect(theme.keyframes.size).toBe( + ["spin", "ping", "pulse", "bounce"].length * 2 + ); + console.log("Theme values:", theme.values); + expect(theme.values.size).toBe(3); +}); diff --git a/tests/.prettierrc.json b/tests/.prettierrc.json deleted file mode 100644 index c2ba36ec..00000000 --- a/tests/.prettierrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "printWidth": 120, - "semi": true, - "singleQuote": false, - "trailingComma": "es5" -} diff --git a/tests/integrations/flat-config.js b/tests/integrations/flat-config.js deleted file mode 100644 index 391c69ff..00000000 --- a/tests/integrations/flat-config.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; - -const { strict: assert } = require("assert"); -const cp = require("child_process"); -const path = require("path"); -const semver = require("semver"); - -const ESLINT = `.${path.sep}node_modules${path.sep}.bin${path.sep}eslint`; - -describe("Integration with flat config", () => { - let originalCwd; - - before(() => { - originalCwd = process.cwd(); - process.chdir(path.join(__dirname, "flat-config")); - cp.execSync("npm i -f", { stdio: "inherit" }); - }); - after(() => { - process.chdir(originalCwd); - }); - - it("should work with flat config", () => { - if ( - !semver.satisfies( - process.version, - require(path.join(__dirname, "flat-config/node_modules/eslint/package.json")).engines.node - ) - ) { - return; - } - - const result = JSON.parse( - cp.execSync(`${ESLINT} a.vue --format=json`, { - encoding: "utf8", - }) - ); - assert.strictEqual(result.length, 1); - assert.deepStrictEqual(result[0].messages[0].messageId, "invalidOrder"); - }); -}); diff --git a/tests/integrations/flat-config/.npmrc b/tests/integrations/flat-config/.npmrc deleted file mode 100644 index 43c97e71..00000000 --- a/tests/integrations/flat-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/tests/integrations/flat-config/a.vue b/tests/integrations/flat-config/a.vue deleted file mode 100644 index 4a4fb2aa..00000000 --- a/tests/integrations/flat-config/a.vue +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/tests/integrations/flat-config/eslint.config.js b/tests/integrations/flat-config/eslint.config.js deleted file mode 100644 index effca20b..00000000 --- a/tests/integrations/flat-config/eslint.config.js +++ /dev/null @@ -1,13 +0,0 @@ -import vue from "eslint-plugin-vue"; -import tailwind from "eslint-plugin-tailwindcss"; - -export default [ - ...vue.configs["flat/recommended"], - ...tailwind.configs["flat/recommended"], - { - rules: { - "vue/multi-word-component-names": "off", - "tailwindcss/classnames-order": "warn", - }, - }, -]; diff --git a/tests/integrations/flat-config/package.json b/tests/integrations/flat-config/package.json deleted file mode 100644 index 39fbfc6e..00000000 --- a/tests/integrations/flat-config/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "private": true, - "name": "integration-test-for-flat-config", - "version": "1.0.0", - "type": "module", - "description": "Integration test for flat config", - "dependencies": { - "eslint": "^8.57.0", - "eslint-plugin-vue": "^9.24.0", - "eslint-plugin-tailwindcss": "file:../../..", - "vue-eslint-parser": "^9.4.2" - } -} diff --git a/tests/integrations/legacy-config.js b/tests/integrations/legacy-config.js deleted file mode 100644 index 243b10dc..00000000 --- a/tests/integrations/legacy-config.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; - -const { strict: assert } = require("assert"); -const cp = require("child_process"); -const path = require("path"); -const semver = require("semver"); - -const ESLINT = `.${path.sep}node_modules${path.sep}.bin${path.sep}eslint`; - -describe("Integration with legacy config", () => { - let originalCwd; - - before(() => { - originalCwd = process.cwd(); - process.chdir(path.join(__dirname, "legacy-config")); - cp.execSync("npm i -f", { stdio: "inherit" }); - }); - after(() => { - process.chdir(originalCwd); - }); - - it("should work with legacy config", () => { - if ( - !semver.satisfies( - process.version, - require(path.join(__dirname, "legacy-config/node_modules/eslint/package.json")).engines.node - ) - ) { - return; - } - - const result = JSON.parse( - cp.execSync(`${ESLINT} a.vue --format=json`, { - encoding: "utf8", - }) - ); - assert.strictEqual(result.length, 1); - assert.deepStrictEqual(result[0].messages[0].messageId, "invalidOrder"); - }); -}); diff --git a/tests/integrations/legacy-config/.eslintrc b/tests/integrations/legacy-config/.eslintrc deleted file mode 100644 index 7595199e..00000000 --- a/tests/integrations/legacy-config/.eslintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "root": true, - "parser": "vue-eslint-parser", - "parserOptions": { - "sourceType": "module" - }, - "extends": ["plugin:vue/vue3-recommended", "plugin:tailwindcss/recommended"], - "rules": { - "vue/multi-word-component-names": "off", - "tailwindcss/classnames-order": "warn" - } -} diff --git a/tests/integrations/legacy-config/.npmrc b/tests/integrations/legacy-config/.npmrc deleted file mode 100644 index 43c97e71..00000000 --- a/tests/integrations/legacy-config/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/tests/integrations/legacy-config/a.vue b/tests/integrations/legacy-config/a.vue deleted file mode 100644 index 4a4fb2aa..00000000 --- a/tests/integrations/legacy-config/a.vue +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/tests/integrations/legacy-config/package.json b/tests/integrations/legacy-config/package.json deleted file mode 100644 index 39fbfc6e..00000000 --- a/tests/integrations/legacy-config/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "private": true, - "name": "integration-test-for-flat-config", - "version": "1.0.0", - "type": "module", - "description": "Integration test for flat config", - "dependencies": { - "eslint": "^8.57.0", - "eslint-plugin-vue": "^9.24.0", - "eslint-plugin-tailwindcss": "file:../../..", - "vue-eslint-parser": "^9.4.2" - } -} diff --git a/tests/lib/index.js b/tests/lib/index.js deleted file mode 100644 index 605c2375..00000000 --- a/tests/lib/index.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @fileoverview Use a consistent orders for the Tailwind CSS classnames, based on property then on variants - * @author FranΓ§ois Massart - */ -"use strict"; - -var plugin = require("../../lib/index"); - -var assert = require("assert"); -var fs = require("fs"); -var path = require("path"); - -var rules = fs.readdirSync(path.resolve(__dirname, "../../lib/rules/")).map(function (f) { - return path.basename(f, ".js"); -}); - -describe("all rule files should be exported by the plugin", function () { - rules.forEach(function (ruleName) { - it(`should export ${ruleName}`, function () { - assert.equal(plugin.rules[ruleName], require(path.join("../../lib/rules", ruleName))); - }); - }); -}); - -describe("configurations", function () { - it(`should export a "recommended" configuration`, function () { - assert(plugin.configs.recommended); - }); - - it(`should export a "flat/recommended" configuration`, function () { - assert(plugin.configs["flat/recommended"]); - }); -}); diff --git a/tests/lib/rules/another.css b/tests/lib/rules/another.css deleted file mode 100644 index b51d1f7c..00000000 --- a/tests/lib/rules/another.css +++ /dev/null @@ -1,45 +0,0 @@ -/* override input always getting focus styling from package "focus-visible" */ -.focus-outline[data-focus-visible-added].focus-visible.focus, -.focus-outline[data-focus-visible-added].focus-visible.focus:focus, -input[type="text"].focus\:outline-none[data-focus-visible-added]:focus, -input[type="email"].focus\:outline-none[data-focus-visible-added]:focus { - box-shadow: none; - outline-width: 0; -} -/* .custom-carousel li:first-child { - padding-left: 20vw; -} */ - -:global(.slide:not(.selected)) { - opacity: 0.2; -} - -.gallery-snackbar { - @apply w-full; -} - -.custom-slide { - height: 70vh; -} - -@media (min-width: 768px) { - .custom-carousel li:not(:first-child) { - @apply pl-16; - } - - .custom-carousel li:not(:last-child) { - @apply pr-16; - } - - .custom-carousel :global(.carousel-root) { - padding: 0 calc(10vw + 16px); - } - - .gallery-snackbar { - width: calc(80vw - 32px); - } - - .indicator { - margin-left: calc(10vw + 16px); - } -} diff --git a/tests/lib/rules/arbitrary-values.js b/tests/lib/rules/arbitrary-values.js deleted file mode 100644 index 24163176..00000000 --- a/tests/lib/rules/arbitrary-values.js +++ /dev/null @@ -1,690 +0,0 @@ -/** - * @fileoverview Detect ambiguous / invalid arbitrary values - * @description By valid we mean accepted by the JIT compiler even if the injected value is invalid on its CSS usage - * @author FranΓ§ois Massart - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var rule = require("../../../lib/rules/no-custom-classname"); -var RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -var parserOptions = { - ecmaVersion: 2019, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, -}; - -var config = [ - { - config: { - darkMode: "class", - }, - }, -]; - -var generateErrors = (classnames) => { - const errors = []; - classnames.split(" ").map((classname) => { - errors.push({ - messageId: "customClassnameDetected", - data: { - classname: classname, - }, - }); - }); - return errors; -}; - -var ruleTester = new RuleTester({ parserOptions }); - -ruleTester.run("arbitrary-values", rule, { - valid: [ - { - code: ` -
- - Tailwind CSS V3: dark is valid when - config.darkMode === 'class' - -
- `, - options: config, - }, - { - code: ` -
- Aspect Ratio accepts arbitrary values -
- `, - }, - { - code: ` -
- Valid object-position -
- `, - options: config, - }, - { - code: ` -
- Should accept the arbitrary values -
`, - }, - { - code: ` -
- Arbitrary values for zIndex -
- `, - options: config, - }, - { - code: ` -
- Arbitrary values for flex -
- `, - options: config, - }, - { - code: ` -
- Arbitrary values for positive integers -
- `, - options: config, - }, - { - code: ` -
- Arbitrary values for order -
- `, - options: config, - }, - { - code: ` -
- placeholderColor using #RGB -
- `, - options: config, - }, - { - code: ` -
- placeholderColor using rgb[a]() -
- `, - options: config, - }, - { - code: ` -
- placeholderColor using hsl -
- `, - options: config, - }, - { - code: ` -
- Battle testing valid textColor -
- `, - options: config, - }, - { - code: ` -
- Color opacity shorthands -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for border-width -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for divide-x-width divide-y-width -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for fontSize -
- `, - options: config, - }, - { - code: ` -
-
1
-
2
-
3
-
4
-
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for height -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for line-height -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for max-height -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for max-width -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for min-height -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for min-width -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for padding -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for ringWidth -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for width -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for inset -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for letterSpacing -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for margin -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for space -
- `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for opacity -
- `, - options: config, - }, - { - code: ` -
rotate
- `, - options: config, - }, - { - code: ` -
- Invalid grids, cols -
- `, - options: config, - }, - { - code: ` -
    -
  • one
  • -
  • two
  • -
  • three
  • -
- `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` -
- Arbitrary values for border-radius -
- `, - }, - { - code: ` -
- Testing arbitrary values for: opacity, order, zIndex -
`, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` -
origin
- `, - options: config, - }, - { - code: ` -
scale
- `, - options: config, - }, - { - code: ` -
scale
- `, - options: config, - }, - { - code: ` -
translate
- `, - options: config, - }, - { - code: ` -
skew
- `, - options: config, - }, - { - code: ` -
Cursor
- `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` - - `, - options: config, - }, - { - code: ` -
- Valid arbitrary values for stroke-width -
- `, - options: config, - }, - { - code: ` -
- support named group/peer syntax -
- `, - options: config, - }, - ], - - invalid: [ - { - code: ` -
- - Tailwind CSS V3: dark is not valid unless - config.darkMode === 'class' - -
- `, - errors: generateErrors("dark"), - }, - { - code: ` -
- Aspect Ratio -
- `, - errors: generateErrors("aspect-ko"), - }, - { - code: ` -
- Invalid object-position -
- `, - options: config, - errors: generateErrors("object-[angle:0%,10%]"), - }, - { - code: ` -
- Unsupported placeholderColor using hsla -
- `, - options: config, - errors: generateErrors("placeholder:text-[hsla(240,100%,50%,0.7]"), - }, - { - code: ` -
- Invalid arbitrary values for rotate -
- `, - options: config, - errors: generateErrors("rotate-[angle:5deg]"), - }, - { - code: ` -
    -
  • invalid
  • -
  • nope
  • -
  • no
  • -
- `, - options: config, - errors: generateErrors("list-[angle:var(--some)] list-[list:var(--some)]"), - }, - { - code: ` - - `, - options: config, - errors: generateErrors("ease-[list:1px]"), - }, - { - code: ` - - `, - options: config, - errors: generateErrors("delay-[list:var(--some)]"), - }, - { - code: ` - - `, - options: config, - errors: generateErrors("animate-[list:1s]"), - }, - { - code: ` -
origin
- `, - options: config, - errors: generateErrors("origin-[list:top,right] origin-[list:10%]"), - }, - { - code: ` -
translate
- `, - options: config, - errors: generateErrors("translate-y-[list:-10px]"), - }, - { - code: ` -
skew
- `, - options: config, - errors: generateErrors("skew-y-[list:-10px]"), - }, - { - code: ` -
Cursor
- `, - options: config, - errors: generateErrors("cursor-[list:'yolo','ftw']"), - }, - { - code: ` - - `, - options: config, - errors: generateErrors("outline-[list:2px,solid,red] outline-[list:var(--some)]"), - }, - { - code: ` - - `, - options: config, - errors: generateErrors("outline-[list:2px,solid,red] outline-[list:var(--some)]"), - }, - { - code: ` - - `, - options: config, - errors: generateErrors("fill-[list:var(--some)] fill-[angle:var(--some)]"), - }, - { - code: ` - - `, - options: config, - errors: generateErrors("stroke-[angle:var(--some)]"), - }, - ...(['myTag', 'myTag.subTag', 'myTag(SomeComponent)'].map(tag => ({ - code: `${tag}\`stroke-[var(--some)] stroke-['yolo'] stroke-[angle:var(--some)]\``, - errors: generateErrors("stroke-[angle:var(--some)]"), - options: [ - { - tags: ["myTag"], - }, - ], - }))), - ], -}); diff --git a/tests/lib/rules/classnames-order.js b/tests/lib/rules/classnames-order.js deleted file mode 100644 index 032c1f46..00000000 --- a/tests/lib/rules/classnames-order.js +++ /dev/null @@ -1,958 +0,0 @@ -/** - * @fileoverview Use a consistent orders for the Tailwind CSS classnames, based on property then on variants - * @author FranΓ§ois Massart - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var rule = require("../../../lib/rules/classnames-order"); -var RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -var parserOptions = { - ecmaVersion: 2019, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, -}; - -var ruleTester = new RuleTester({ parserOptions }); - -const generateErrors = (count) => { - const errors = []; - - for (let i = 0; i < count; i++) { - errors.push({ - messageId: "invalidOrder", - }); - } - - return errors; -}; - -const errors = generateErrors(1); - -const sharedOptions = [ - { - config: { - theme: { - extend: { - fontSize: { large: "20rem" }, - colors: { - "deque-blue": "#243c5a", - }, - }, - }, - plugins: [ - require("@tailwindcss/typography"), - require("@tailwindcss/forms"), - require("@tailwindcss/aspect-ratio"), - require("@tailwindcss/line-clamp"), - ], - }, - }, -]; - -const skipClassAttributeOptions = [ - { - skipClassAttribute: true, - config: { - theme: {}, - plugins: [], - }, - }, -]; - -ruleTester.run("classnames-order", rule, { - valid: [ - { - code: `
Simple, basic
`, - }, - { - code: `
Simple, using 'tw' prop
`, - options: [ - { - classRegex: "^tw$", - }, - ], - }, - { - code: "
ctl + exp
", - }, - { - code: "
ctl + var
", - }, - { - code: "
Space trim issue
", - }, - { - code: ` - ctl(\` - flex items-center justify-center - \${variant === SpinnerVariant.OVERLAY && \`z-60 rounded border-2 bg-gray-400 px-4 \${widthClass} \${heightClass}\`} - \${ - variant === SpinnerVariant.FULLSCREEN && - \`z-60 fixed bottom-0 left-0 right-0 top-0 bg-white bg-opacity-60 px-4 dark:bg-purple-900 dark:bg-opacity-60\` - } - \`)`, - }, - { - code: `
Simple quotes
`, - }, - { - code: `
Extra space at the end
`, - }, - { - code: `
Extra space at the end, but with 'tw' prop
`, - options: [ - { - classRegex: "^tw$", - }, - ], - }, - { - code: `
'p', then 'py' then 'px'
`, - }, - { - code: ``, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ``, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ``, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: `ctl(\` - container - flex - w-12 - sm:w-6 - lg:w-4 - \`)`, - }, - { - code: `
Custom prefix and separator
`, - options: [ - { - config: { prefix: "lorem-", separator: "_" }, - }, - ], - }, - { - code: `
Allowed arbitrary value
`, - }, - { - code: `
Stackable variants
`, - }, - { - code: `
clsx
`, - options: [ - { - callees: ["clsx"], - }, - ], - }, - { - code: `
Options override shared settings
`, - options: [ - { - config: { prefix: "opts-" }, - }, - ], - settings: { - tailwindcss: { - config: { prefix: "sttgs-" }, - }, - }, - }, - { - code: `
Use settings
`, - settings: { - tailwindcss: { - config: { prefix: "sttgs-", separator: "_" }, - }, - }, - }, - ...(['myTag', 'myTag.subTag', 'myTag(SomeComponent)'].map(tag => ({ - code: `${tag}\` - container - flex - w-12 - sm:w-6 - lg:w-4 - \``, - options: [ - { - tags: ["myTag"], - }, - ], - }))), - { - code: `
Number values
`, - settings: { - tailwindcss: { - config: { theme: { zIndex: { dialog: 10000 } } }, - }, - }, - }, - { - code: `
Extra spaces
`, - }, - { - code: `
Valid using mode official
`, - }, - { - code: `
Valid using mode official
`, - options: [ - { - config: { prefix: "lorem-", separator: "_" }, - }, - ], - }, - { - // No plugin - code: ` - - `, - }, - { - code: ` -
https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/109#issuecomment-1044625260 no config, so bg-deque-blue text-large goes at first position because custom
- `, - }, - { - code: ` -
https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/109#issuecomment-1044625260
- `, - options: sharedOptions, - }, - { - // Kitchensink - code: ` - - `, - options: sharedOptions, - }, - { - code: ` -
Issue #131
- `, - }, - { - code: ` -
-

Issue #142

-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
- `, - }, - { - code: `
No errors while typing
`, - }, - { - code: ` -
skipClassAttribute
- `, - options: skipClassAttributeOptions, - }, - { - code: `
Do not treat full width space as class separator
`, - }, - { - code: ` - const func = () => ({ a: 12 }); -
Spread of a function return inside clsx
- `, - }, - ], - invalid: [ - { - code: ` - export interface FakePropsInterface { - readonly name?: string; - } - function Fake({ - name = 'yolo' - }: FakeProps) { - return ( - <> -

Welcome {name}

-

Bye {name}

- - ); - } - export default Fake; - `, - output: ` - export interface FakePropsInterface { - readonly name?: string; - } - function Fake({ - name = 'yolo' - }: FakeProps) { - return ( - <> -

Welcome {name}

-

Bye {name}

- - ); - } - export default Fake; - `, - parser: require.resolve("@typescript-eslint/parser"), - errors: errors, - }, - { - code: `
Classnames will be ordered
`, - output: `
Classnames will be ordered
`, - errors: errors, - }, - { - code: `
Enhancing readability
`, - output: `
Enhancing readability
`, - errors: errors, - }, - { - code: `
Enhancing readability with 'tw' prop
`, - output: `
Enhancing readability with 'tw' prop
`, - options: [ - { - classRegex: "^tw$", - }, - ], - errors: errors, - }, - { - code: `
:)...
`, - output: `
:)...
`, - errors: errors, - }, - { - code: ``, - output: ``, - errors: errors, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ``, - output: ``, - errors: errors, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ``, - output: ``, - errors: errors, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: "ctl(`p-10 w-full ${some}`)", - output: "ctl(`w-full p-10 ${some}`)", - errors: errors, - }, - { - code: "
Space trim issue with fix
", - output: "
Space trim issue with fix
", - errors: errors, - }, - { - code: `
`, - output: `
`, - options: [ - { - config: { - plugins: [require("@tailwindcss/typography")], - }, - }, - ], - errors: errors, - }, - { - code: `
`, - output: `
`, - options: [ - { - config: { - plugins: [require("@tailwindcss/line-clamp")], - }, - }, - ], - errors: errors, - }, - { - code: `
Simple quotes
`, - output: `
Simple quotes
`, - errors: errors, - }, - { - options: [ - { - removeDuplicates: false, - }, - ], - code: `
removeDuplicates: false
`, - output: `
removeDuplicates: false
`, - errors: errors, - }, - { - code: `
Single line dups + no head/tail spaces
`, - output: `
Single line dups + no head/tail spaces
`, - errors: errors, - }, - { - code: `
Single dups line + head spaces
`, - output: `
Single dups line + head spaces
`, - errors: errors, - }, - { - code: `
Single line dups + tail spaces
`, - output: `
Single line dups + tail spaces
`, - errors: errors, - }, - { - // Multiline + both head/tail spaces - code: ` - ctl(\` - invalid - sm:w-6 - container - invalid - flex - container - w-12 - flex - container - lg:w-4 - lg:w-4 - \`);`, - output: ` - ctl(\` - invalid - container - flex - w-12 - sm:w-6 - lg:w-4 - \`);`, - errors: errors, - }, - { - code: ` - ctl(\` - invalid - sm:w-6 - container - w-12 - flex - lg:w-4 - \`);`, - output: ` - ctl(\` - invalid - container - flex - w-12 - sm:w-6 - lg:w-4 - \`);`, - errors: errors, - }, - { - code: ` - const buttonClasses = ctl(\` - \${fullWidth ? "w-12" : "w-6"} - container - \${fullWidth ? "sm:w-8" : "sm:w-4"} - lg:w-9 - flex - \${hasError && "bg-red"} - \`);`, - output: ` - const buttonClasses = ctl(\` - \${fullWidth ? "w-12" : "w-6"} - container - \${fullWidth ? "sm:w-8" : "sm:w-4"} - flex - lg:w-9 - \${hasError && "bg-red"} - \`);`, - errors: errors, - }, - { - code: ` - const buttonClasses = ctl(\` - \${fullWidth ? "w-12" : "w-6"} - flex - container - \${fullWidth ? "sm:w-7" : "sm:w-4"} - lg:py-4 - sm:py-6 - \${hasError && "bg-red"} - \`);`, - output: ` - const buttonClasses = ctl(\` - \${fullWidth ? "w-12" : "w-6"} - container - flex - \${fullWidth ? "sm:w-7" : "sm:w-4"} - sm:py-6 - lg:py-4 - \${hasError && "bg-red"} - \`);`, - errors: generateErrors(2), - }, - { - code: `
Allowed arbitrary value but incorrect order
`, - output: `
Allowed arbitrary value but incorrect order
`, - errors: errors, - }, - { - code: `clsx(\`absolute bottom-0 w-full h-[70px] flex flex-col\`);`, - output: `clsx(\`absolute bottom-0 flex h-[70px] w-full flex-col\`);`, - options: [ - { - callees: ["clsx"], - }, - ], - errors: errors, - }, - { - code: `cva({ - primary: ["absolute bottom-0 w-full h-[70px] flex flex-col"], - })`, - output: `cva({ - primary: ["absolute bottom-0 flex h-[70px] w-full flex-col"], - })`, - options: [ - { - callees: ["cva"], - }, - ], - errors: errors, - }, - { - code: `
clsx
`, - output: `
clsx
`, - options: [ - { - callees: ["clsx"], - }, - ], - errors: errors, - }, - { - code: ` - ctl(\` - px-2 - flex - \${ - !isDisabled && - \` - top-0 - flex - border-0 - \` - } - \${ - isDisabled && - \` - border-0 - mx-0 - \` - } - \`) - `, - output: ` - ctl(\` - flex - px-2 - \${ - !isDisabled && - \` - top-0 - flex - border-0 - \` - } - \${ - isDisabled && - \` - mx-0 - border-0 - \` - } - \`) - `, - errors: generateErrors(2), - }, - { - code: `
...
`, - output: `
...
`, - errors: errors, - }, - { - code: `ctl(\`\${enabled && "px-2 flex"}\`)`, - output: `ctl(\`\${enabled && "flex px-2"}\`)`, - errors: errors, - }, - { - code: `ctl(\`px-2 flex\`)`, - output: `ctl(\`flex px-2\`)`, - errors: errors, - }, - { - code: ` - ctl(\` - px-2 - flex - \`) - `, - output: ` - ctl(\` - flex - px-2 - \`) - `, - errors: errors, - }, - { - code: ` -
- #19 -
- `, - output: ` -
- #19 -
- `, - errors: errors, - }, - { - code: ` -
- `, - output: ` -
- `, - errors: generateErrors(2), - }, - ...(['myTag', 'myTag.subTag', 'myTag(SomeComponent)'].flatMap(tag => ([ - { - code: ` - ${tag}\` - invalid - sm:w-6 - container - w-12 - flex - lg:w-4 - \`;`, - output: ` - ${tag}\` - invalid - container - flex - w-12 - sm:w-6 - lg:w-4 - \`;`, - options: [ - { - tags: ["myTag"], - }, - ], - errors: errors, - }, - { - code: ` - const buttonClasses = ${tag}\` - \${fullWidth ? "w-12" : "w-6"} - container - \${fullWidth ? "sm:w-8" : "sm:w-4"} - lg:w-9 - flex - \${hasError && "bg-red"} - \`;`, - output: ` - const buttonClasses = ${tag}\` - \${fullWidth ? "w-12" : "w-6"} - container - \${fullWidth ? "sm:w-8" : "sm:w-4"} - flex - lg:w-9 - \${hasError && "bg-red"} - \`;`, - options: [ - { - tags: ["myTag"], - }, - ], - errors: errors, - }, - { - code: ` - const buttonClasses = ${tag}\` - \${fullWidth ? "w-12" : "w-6"} - flex - container - \${fullWidth ? "sm:w-7" : "sm:w-4"} - lg:py-4 - sm:py-6 - \${hasError && "bg-red"} - \`;`, - output: ` - const buttonClasses = ${tag}\` - \${fullWidth ? "w-12" : "w-6"} - container - flex - \${fullWidth ? "sm:w-7" : "sm:w-4"} - sm:py-6 - lg:py-4 - \${hasError && "bg-red"} - \`;`, - options: [ - { - tags: ["myTag"], - }, - ], - errors: generateErrors(2), - }, - ]))), - { - code: ` - classnames([ - 'invalid lg:w-4 sm:w-6', - ['w-12 flex'], - ])`, - output: ` - classnames([ - 'invalid sm:w-6 lg:w-4', - ['flex w-12'], - ])`, - errors: generateErrors(2), - }, - { - code: ` - classnames({ - invalid, - flex: myFlag, - 'lg:w-4 sm:w-6': resize - })`, - output: ` - classnames({ - invalid, - flex: myFlag, - 'sm:w-6 lg:w-4': resize - })`, - errors: errors, - }, - { - code: ` -
-
`, - output: ` -
-
`, - errors: [...errors, ...errors], - parser: require.resolve("@angular-eslint/template-parser"), - }, - { - code: `
:)
`, - output: `
:)
`, - errors: errors, - parser: require.resolve("@angular-eslint/template-parser"), - }, - { - code: ` -
- :) -
`, - output: ` -
- :) -
`, - errors: errors, - parser: require.resolve("@angular-eslint/template-parser"), - }, - { - code: `
Using official sorting
`, - output: `
Using official sorting
`, - errors: errors, - }, - { - code: `ctl(\`\${some} container animate-spin first:flex \${bool ? "flex-col flex" : ""}\`)`, - output: `ctl(\`\${some} container animate-spin first:flex \${bool ? "flex flex-col" : ""}\`)`, - errors: errors, - }, - { - code: `ctl(\`p-3 border-gray-300 m-4 h-24 lg:p-4 flex border-2 lg:m-4\`)`, - output: `ctl(\`m-4 flex h-24 border-2 border-gray-300 p-3 lg:m-4 lg:p-4\`)`, - errors: errors, - }, - { - // https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/131 - code: "", - output: "", - errors: errors, - }, - { - // https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/131 - code: "", - output: "", - errors: errors, - }, - { - // https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/131 - code: ``, - output: ``, - errors: errors, - }, - { - // https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/131 - code: ``, - output: ``, - errors: errors, - }, - { - code: ` -
skipClassAttribute
- `, - output: ` -
skipClassAttribute
- `, - options: skipClassAttributeOptions, - errors: errors, - }, - { - code: ``, - output: ``, - errors: errors, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ``, - output: ``, - errors: errors, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ``, - output: ``, - errors: errors, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ``, - output: ``, - errors: errors, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - `, - output: ` - `, - errors: errors, - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: `
support named group/peer syntax
`, - output: `
support named group/peer syntax
`, - errors: errors, - }, - ], -}); diff --git a/tests/lib/rules/dummy.css b/tests/lib/rules/dummy.css deleted file mode 100644 index 68c1587a..00000000 --- a/tests/lib/rules/dummy.css +++ /dev/null @@ -1,45 +0,0 @@ -/* Only used for running tests */ -.some { - color: black; -} -.white-listed { - color: yellow; -} -.classnames { - color: red; -} -.one, -.two { - color: red; -} - -@media screen and (min-width: 480px) { - body { - background-color: lightgreen; - } -} - -#main { - border: 1px solid black; -} -@layer base { - ul li { - padding: 5px; - } - .base { - display: block; - } -} - -@tailwind utilities; - -.btn { - @apply border-red; -} - -.parent { - .child, - .btn { - background: none; - } -} diff --git a/tests/lib/rules/enforces-negative-arbitrary-values.js b/tests/lib/rules/enforces-negative-arbitrary-values.js deleted file mode 100644 index 1fd9df27..00000000 --- a/tests/lib/rules/enforces-negative-arbitrary-values.js +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @fileoverview Warns about `-` prefixed classnames using arbitrary values - * @author FranΓ§ois Massart - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var rule = require("../../../lib/rules/enforces-negative-arbitrary-values"); -var RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -var parserOptions = { - ecmaVersion: 2019, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, -}; - -const skipClassAttributeOptions = [ - { - skipClassAttribute: true, - config: { - theme: {}, - plugins: [], - }, - }, -]; - -var generateErrors = (classes) => { - const errors = []; - classes.split(" ").forEach((cls) => - errors.push({ - messageId: "negativeArbitraryValue", - data: { - classname: cls, - }, - }) - ); - return errors; -}; - -var ruleTester = new RuleTester({ parserOptions }); - -ruleTester.run("enforces-negative-arbitrary-values", rule, { - valid: [ - { - code: `
top-[-50px]
`, - }, - { - code: `
top-[-50px]
`, - }, - { - code: `
top-[-50px]
`, - }, - { - code: `
No errors while typing
`, - }, - { - code: ` -
skipClassAttribute
- `, - options: skipClassAttributeOptions, - }, - ], - invalid: [ - { - code: `
all
`, - errors: generateErrors( - "-inset-[1px] -inset-y-[1px] -inset-x-[1px] -top-[1px] -right-[1px] -bottom-[1px] -left-[1px] -top-[1px] -z-[2] -order-[2] -m-[1px] -my-[1px] -mx-[1px] -mt-[1px] -mr-[1px] -mb-[1px] -ml-[1px] -mt-[1px] -space-y-[1px] -space-x-[1px] -tracking-[1px] -indent-[1px] -hue-rotate-[50%] -backdrop-hue-rotate-[50%] -scale-[50%] -scale-y-[50%] -scale-x-[50%] -rotate-[45deg] -translate-x-[1px] -translate-y-[1px] -skew-x-[45deg] -skew-y-[45deg] -scroll-m-[1px] -scroll-my-[1px] -scroll-mx-[1px] -scroll-mt-[1px] -scroll-mr-[1px] -scroll-mb-[1px] -scroll-ml-[1px] -scroll-mt-[1px]" - ), - }, - { - code: ` -
skipClassAttribute
- `, - options: skipClassAttributeOptions, - errors: generateErrors("-inset-y-[1px]"), - }, - { - code: `cva({ - primary: ["-inset-[1px] -inset-y-[1px] -inset-x-[1px] -top-[1px] -right-[1px] -bottom-[1px] -left-[1px] -top-[1px] -z-[2] -order-[2] -m-[1px] -my-[1px] -mx-[1px] -mt-[1px] -mr-[1px] -mb-[1px] -ml-[1px] -mt-[1px] -space-y-[1px] -space-x-[1px] -tracking-[1px] -indent-[1px] -hue-rotate-[50%] -backdrop-hue-rotate-[50%] -scale-[50%] -scale-y-[50%] -scale-x-[50%] -rotate-[45deg] -translate-x-[1px] -translate-y-[1px] -skew-x-[45deg] -skew-y-[45deg] -scroll-m-[1px] -scroll-my-[1px] -scroll-mx-[1px] -scroll-mt-[1px] -scroll-mr-[1px] -scroll-mb-[1px] -scroll-ml-[1px] -scroll-mt-[1px]"] - });`, - options: [ - { - callees: ["cva"], - }, - ], - errors: generateErrors( - "-inset-[1px] -inset-y-[1px] -inset-x-[1px] -top-[1px] -right-[1px] -bottom-[1px] -left-[1px] -top-[1px] -z-[2] -order-[2] -m-[1px] -my-[1px] -mx-[1px] -mt-[1px] -mr-[1px] -mb-[1px] -ml-[1px] -mt-[1px] -space-y-[1px] -space-x-[1px] -tracking-[1px] -indent-[1px] -hue-rotate-[50%] -backdrop-hue-rotate-[50%] -scale-[50%] -scale-y-[50%] -scale-x-[50%] -rotate-[45deg] -translate-x-[1px] -translate-y-[1px] -skew-x-[45deg] -skew-y-[45deg] -scroll-m-[1px] -scroll-my-[1px] -scroll-mx-[1px] -scroll-mt-[1px] -scroll-mr-[1px] -scroll-mb-[1px] -scroll-ml-[1px] -scroll-mt-[1px]" - ), - }, - { - code: ` - - `, - errors: generateErrors("-inset-[1px] -inset-y-[1px]"), - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - errors: generateErrors("-top-[1px] -bottom-[1px]"), - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - errors: generateErrors("-left-[1px] -top-[1px]"), - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - errors: generateErrors("-my-[1px] -mx-[1px]"), - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: `
support named group/peer syntax
`, - errors: generateErrors("group/edit:-inset-[1px]"), - }, - ...(['myTag', 'myTag.subTag', 'myTag(SomeComponent)'].map(tag => ({ - code: `${tag}\`-my-[1px] -mx-[1px]\``, - errors: generateErrors("-my-[1px] -mx-[1px]"), - options: [ - { - tags: ["myTag"], - }, - ], - }))), - ], -}); diff --git a/tests/lib/rules/enforces-shorthand.js b/tests/lib/rules/enforces-shorthand.js deleted file mode 100644 index 30ecb43f..00000000 --- a/tests/lib/rules/enforces-shorthand.js +++ /dev/null @@ -1,814 +0,0 @@ -/** - * @fileoverview Detect classname candidates for shorthand replacement - * @description E.g. `mx-4 my-4` can be replaced by `m-4` - * @author FranΓ§ois Massart - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var rule = require("../../../lib/rules/enforces-shorthand"); -var RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -var parserOptions = { - ecmaVersion: 2019, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, -}; - -const skipClassAttributeOptions = [ - { - skipClassAttribute: true, - config: { - theme: {}, - plugins: [], - }, - }, -]; - -const incompleteCustomWidthHeightOptions = [ - { - config: { - theme: { - extend: { - width: { custom: "100px" }, - height: { custom: "100px" }, - }, - }, - plugins: [], - }, - }, -]; - -const customSpacingOnlyOptions = [ - { - config: { - theme: { - extend: { - spacing: { custom: "100px" }, - }, - }, - plugins: [], - }, - }, -]; - -const customSizeOnlyOptions = [ - { - config: { - theme: { - extend: { - size: { size: "100px" }, - }, - }, - plugins: [], - }, - }, -]; - -const ambiguousOptions = [ - { - config: { - theme: { - extend: { - width: { ambiguous: "75px" }, - height: { ambiguous: "120px" }, - size: { ambiguous: "100px" }, - }, - }, - plugins: [], - }, - }, -]; - -var generateError = (classnames, shorthand) => { - return { - messageId: "shorthandCandidateDetected", - data: { - classnames: classnames.join(", "), - shorthand: shorthand, - }, - }; -}; - -var ruleTester = new RuleTester({ parserOptions }); - -ruleTester.run("shorthands", rule, { - valid: [ - { - code: ` -
- No shorthand possible for overflow -
- `, - }, - { - code: ` -
- No shorthand possible for overscroll -
- `, - }, - { - code: ` -
- No shorthand possible for margin -
- `, - }, - { - code: ` -
- No shorthand possible for inset -
`, - }, - { - code: ` -
- Cannot merge mixed values (arbitrary + regular) -
`, - }, - { - code: ` -
- No shorthand possible for gap -
`, - }, - { - code: ``, - }, - { - code: `
`, - }, - { - code: `
issue #91
`, - }, - { - code: `
No errors while typing
`, - }, - { - code: ` -
skipClassAttribute
- `, - options: skipClassAttributeOptions, - }, - { - code: ` -
- support named group/peer syntax -
- `, - }, - { - code: ` -
- Possible shorthand available for truncate, but some of the classes have modifiers -
- `, - }, - { - code: ` -
- Possible shorthand available for truncate, but some of the classes have important -
- `, - }, - { - code: "
issue #312
", - }, - { - code: "
issue #307
", - }, - { - code: `
Incomplete config should not use size-*
`, - options: incompleteCustomWidthHeightOptions, - }, - { - code: `
Ambiguous cannot size-*
`, - options: ambiguousOptions, - }, - { - code: `
h-custom & w-custom don't exist... no size-*
`, - options: customSizeOnlyOptions, - }, - ], - - invalid: [ - { - code: ` -
- Possible shorthand for overflow -
- `, - output: ` -
- Possible shorthand for overflow -
- `, - errors: [generateError(["overflow-x-auto", "overflow-y-auto"], "overflow-auto")], - }, - { - code: ` -
- Possible shorthand for overscroll -
- `, - output: ` -
- Possible shorthand for overscroll -
- `, - errors: [generateError(["overscroll-x-contain", "overscroll-y-contain"], "overscroll-contain")], - }, - { - code: ` -
- Possible shorthand for margin -
- `, - output: ` -
- Possible shorthand for margin -
- `, - errors: [generateError(["mt-0", "mb-0"], "my-0")], - }, - { - code: ` -
- Possible shorthand for negative margin -
- `, - output: ` -
- Possible shorthand for negative margin -
- `, - errors: [generateError(["-mt-1", "-mb-1"], "-my-1")], - }, - { - code: ` -
- Possible shorthand for margin -
- `, - output: ` -
- Possible shorthand for margin -
- `, - errors: [ - generateError(["mt-0", "mb-0"], "my-0"), - generateError(["md:mx-2", "md:my-2"], "md:m-2"), - generateError(["py-0", "px-0"], "p-0"), - ], - }, - { - code: ` -
- Possible shorthand for border-radius -
- `, - output: ` -
- Possible shorthand for border-radius -
- `, - errors: [ - generateError(["rounded-tl-sm", "rounded-tr-sm"], "rounded-t-sm"), - generateError(["md:rounded-t-md", "md:rounded-b-md"], "md:rounded-md"), - ], - }, - { - code: ` -
- Possible shorthand for border-radius -
- `, - output: ` -
- Possible shorthand for border-radius -
- `, - errors: [generateError(["rounded-tl", "rounded-tr", "rounded-b"], "rounded")], - }, - { - code: ` -
- Possible shorthand for border-radius -
- `, - output: ` -
- Possible shorthand for border-radius -
- `, - errors: [generateError(["rounded-tl-sm", "rounded-tr-sm", "rounded-b-sm"], "rounded-sm")], - }, - { - code: ` -
- Possible shorthand for border-radius -
- `, - output: ` -
- Possible shorthand for border-radius -
- `, - errors: [generateError(["rounded-tl-sm", "rounded-tr-sm"], "rounded-t-sm")], - }, - { - code: ` -
- Possible shorthand for border-radius -
- `, - output: ` -
- Possible shorthand for border-radius -
- `, - errors: [ - generateError(["rounded-tl-sm", "rounded-tr-sm"], "rounded-t-sm"), - generateError(["md:rounded-t-md", "md:rounded-b-md"], "md:rounded-md"), - ], - }, - { - code: ` -
- Possible shorthand for border-width -
- `, - output: ` -
- Possible shorthand for border-width -
- `, - errors: [ - generateError(["border-t-4", "border-b-4"], "border-y-4"), - generateError(["md:border-t-0", "md:border-b-0"], "md:border-y-0"), - generateError(["lg:border-y", "lg:border-l", "lg:border-r"], "lg:border"), - ], - }, - { - code: ` -
- Possible shorthand for border-width -
- `, - output: ` -
- Possible shorthand for border-width -
- `, - errors: [generateError(["border-t-4", "border-b-4"], "border-y-4")], - }, - { - code: ` -
- No shorthand possible -
`, - output: ` -
- No shorthand possible -
`, - errors: [ - generateError(["top-[0]", "bottom-[0]"], "inset-y-[0]"), - generateError(["right-[var(--some-value)]", "left-[var(--some-value)]"], "inset-x-[var(--some-value)]"), - ], - }, - { - code: ` -
- Randomized classnames order -
- `, - output: ` -
- Randomized classnames order -
- `, - errors: [ - generateError(["rounded-tr-sm", "rounded-tl-sm"], "rounded-t-sm"), - generateError(["md:rounded-b-md", "md:rounded-t-md"], "md:rounded-md"), - generateError(["border-t-4", "border-b-4"], "border-y-4"), - ], - }, - { - code: ` -
- Possible shorthand for gap -
`, - output: ` -
- Possible shorthand for gap -
`, - errors: [generateError(["gap-x-4", "gap-y-4"], "gap-4")], - }, - { - code: ` -
- Possible shorthand for border-color -
`, - output: ` -
- Possible shorthand for border-color -
`, - errors: [ - generateError( - ["border-t-indigo-200/50", "border-x-indigo-200/50", "border-b-indigo-200/50"], - "border-indigo-200/50" - ), - ], - }, - { - code: ``, - output: ``, - errors: [generateError(["scale-x-75", "scale-y-75"], "scale-75")], - }, - { - code: ``, - output: ``, - errors: [generateError(["scale-x-75", "scale-y-75"], "scale-75")], - }, - { - code: ``, - output: ``, - errors: [generateError(["-scale-x-50", "-scale-y-50"], "-scale-50")], - }, - { - code: ` -
- Multilines -
`, - output: ` -
- Multilines -
`, - errors: [generateError(["w-48", "h-48"], "size-48"), generateError(["py-8", "px-8"], "p-8")], - }, - { - code: `classnames(['py-8 px-8 w-48 h-48 text-white'])`, - output: `classnames(['p-8 size-48 text-white'])`, - errors: [generateError(["w-48", "h-48"], "size-48"), generateError(["py-8", "px-8"], "p-8")], - }, - { - code: `classnames({'py-8 px-8 text-white': true})`, - output: `classnames({'p-8 text-white': true})`, - errors: [generateError(["py-8", "px-8"], "p-8")], - }, - { - code: `classnames({'!py-8 !px-8 text-white': true})`, - output: `classnames({'!p-8 text-white': true})`, - errors: [generateError(["!py-8", "!px-8"], "!p-8")], - }, - { - code: `classnames({'!pt-8 !pb-8 pr-8 !pl-8': true})`, - output: `classnames({'!py-8 pr-8 !pl-8': true})`, - errors: [generateError(["!pt-8", "!pb-8"], "!py-8")], - }, - { - code: `classnames({'!pt-8 !pb-8 !pr-8 !pl-8': true})`, - output: `classnames({'!p-8': true})`, - errors: [generateError(["!pt-8", "!pb-8", "!pr-8", "!pl-8"], "!p-8")], - }, - { - code: `classnames({'!pt-8 pb-8 pr-8 pl-8': true})`, - output: `classnames({'!pt-8 pb-8 px-8': true})`, - errors: [generateError(["pr-8", "pl-8"], "px-8")], - }, - { - code: `classnames({'md:!rounded-tr block md:rounded-tl md:rounded-br md:rounded-bl': true})`, - output: `classnames({'md:!rounded-tr block md:rounded-tl md:rounded-b': true})`, - errors: [generateError(["md:rounded-br", "md:rounded-bl"], "md:rounded-b")], - }, - { - code: ` -
- Issue #120 -
- `, - output: ` -
- Issue #120 -
- `, - errors: [generateError(["rounded-r-full", "rounded-l-full"], "rounded-full")], - }, - { - code: `classnames('sfc-border-l-0 sfc-border-r-0')`, - output: `classnames('sfc-border-x-0')`, - options: [ - { - config: { prefix: "sfc-" }, - }, - ], - errors: [generateError(["sfc-border-l-0", "sfc-border-r-0"], "sfc-border-x-0")], - }, - { - code: `classnames('md_sfc-border-l-0 md_sfc-border-r-0')`, - output: `classnames('md_sfc-border-x-0')`, - options: [ - { - config: { prefix: "sfc-", separator: "_" }, - }, - ], - errors: [generateError(["md_sfc-border-l-0", "md_sfc-border-r-0"], "md_sfc-border-x-0")], - }, - { - code: ` -
- Issue #148 -
- `, - output: ` -
- Issue #148 -
- `, - errors: [generateError(["border-spacing-x-px", "border-spacing-y-px"], "border-spacing-px")], - }, - { - code: ` -
skipClassAttribute
- `, - output: ` -
skipClassAttribute
- `, - options: skipClassAttributeOptions, - errors: [generateError(["mt-0", "mb-0"], "my-0")], - }, - { - code: ` -
- Issue #182 -
- `, - output: ` -
- Issue #182 -
- `, - errors: [generateError(["p-2", "pl-2", "pr-2"], "p-2")], - }, - { - code: `cva({ - primary: ["border-l-0 border-r-0"], - });`, - output: `cva({ - primary: ["border-x-0"], - });`, - options: [ - { - callees: ["cva"], - }, - ], - errors: [generateError(["border-l-0", "border-r-0"], "border-x-0")], - }, - { - code: ` - - `, - output: ` - - `, - errors: [generateError(["overflow-x-auto", "overflow-y-auto"], "overflow-auto")], - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - output: ` - - `, - errors: [generateError(["overscroll-x-contain", "overscroll-y-contain"], "overscroll-contain")], - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - output: ` - - `, - errors: [generateError(["mt-0", "mb-0"], "my-0")], - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - output: ` - - `, - errors: [generateError(["-mt-1", "-mb-1"], "-my-1")], - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` -
- support named group/peer syntax -
- `, - output: ` -
- support named group/peer syntax -
- `, - errors: [generateError(["group/name:rounded-r-full", "group/name:rounded-l-full"], "group/name:rounded-full")], - }, - { - code: ` -
- Possible shorthand when using truncate -
- `, - output: ` -
- Possible shorthand when using truncate -
- `, - errors: [generateError(["overflow-hidden", "text-ellipsis", "whitespace-nowrap"], "truncate")], - }, - { - code: ` -
- Possible shorthand when using truncate with breakpoint -
- `, - output: ` -
- Possible shorthand when using truncate with breakpoint -
- `, - errors: [generateError(["md:overflow-hidden", "md:text-ellipsis", "md:whitespace-nowrap"], "md:truncate")], - }, - { - code: ` -
- Possible shorthand when using truncate with hover -
- `, - output: ` -
- Possible shorthand when using truncate with hover -
- `, - errors: [ - generateError(["hover:overflow-hidden", "hover:text-ellipsis", "hover:whitespace-nowrap"], "hover:truncate"), - ], - }, - { - code: ` -
- Possible shorthand when using truncate with hover, breakpoint, important and prefix -
- `, - output: ` -
- Possible shorthand when using truncate with hover, breakpoint, important and prefix -
- `, - errors: [ - generateError( - ["hover:sm:!tw-overflow-hidden", "hover:sm:!tw-text-ellipsis", "hover:sm:!tw-whitespace-nowrap"], - "hover:sm:!tw-truncate" - ), - ], - options: [ - { - config: { prefix: "tw-" }, - }, - ], - }, - { - code: ` -
- Possible shorthand when using truncate, tested with additional classnames -
- `, - output: ` -
- Possible shorthand when using truncate, tested with additional classnames -
- `, - errors: [generateError(["overflow-hidden", "text-ellipsis", "whitespace-nowrap"], "truncate")], - }, - { - code: "
Leading space trim issue with fix
", - output: "
Leading space trim issue with fix
", - errors: [generateError(["px-10", "py-10"], "p-10")], - }, - { - code: "
Leading space trim issue with fix (2)
", - output: "
Leading space trim issue with fix (2)
", - errors: [generateError(["px-10", "py-10"], "p-10")], - }, - { - code: "
Trailing space trim issue with fix
", - output: "
Trailing space trim issue with fix
", - errors: [generateError(["px-10", "py-10"], "p-10")], - }, - { - code: "
Trailing space trim issue with fix (2)
", - output: "
Trailing space trim issue with fix (2)
", - errors: [generateError(["px-10", "py-10"], "p-10")], - }, - { - code: `
New size-* utilities
`, - output: `
New size-* utilities
`, - errors: [generateError(["h-10", "w-10"], "size-10")], - }, - { - code: `
New size-* utilities
`, - output: `
New size-* utilities
`, - errors: [generateError(["md:h-5", "md:w-5"], "md:size-5")], - }, - { - code: `
size-*
`, - output: `
size-*
`, - errors: [generateError(["h-custom", "w-custom"], "size-custom")], - options: customSpacingOnlyOptions, - }, - ...["myTag", "myTag.subTag", "myTag(SomeComponent)"].map((tag) => ({ - code: `${tag}\`overflow-hidden text-ellipsis whitespace-nowrap text-white text-xl\``, - output: `${tag}\`truncate text-white text-xl\``, - errors: [generateError(["overflow-hidden", "text-ellipsis", "whitespace-nowrap"], "truncate")], - options: [ - { - tags: ["myTag"], - }, - ], - })), - ], -}); diff --git a/tests/lib/rules/migration-from-tailwind-2.js b/tests/lib/rules/migration-from-tailwind-2.js deleted file mode 100644 index 0ada3e76..00000000 --- a/tests/lib/rules/migration-from-tailwind-2.js +++ /dev/null @@ -1,404 +0,0 @@ -/** - * @fileoverview Detect obsolete classnames when upgrading to Tailwind CSS v3 - * @author FranΓ§ois Massart - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var rule = require("../../../lib/rules/migration-from-tailwind-2"); -var RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -var parserOptions = { - ecmaVersion: 2019, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, -}; - -const skipClassAttributeOptions = [ - { - skipClassAttribute: true, - config: { - theme: {}, - plugins: [], - }, - }, -]; - -var ruleTester = new RuleTester({ parserOptions }); - -ruleTester.run("migration-from-tailwind-2", rule, { - valid: [ - { - code: `
Automatic transforms and filters
`, - }, - { - code: `
transition-transform
`, - }, - { - code: `
transition-[var(--transform)]
`, - }, - { - code: `
No errors while typing
`, - }, - ], - invalid: [ - { - code: `
Automatic transform
`, - output: `
Automatic transform
`, - errors: [ - { - messageId: "classnameNotNeeded", - data: { - classnames: "transform", - }, - }, - ], - }, - { - code: `
Automatic transform
`, - output: `
Automatic transform
`, - errors: [ - { - messageId: "classnameNotNeeded", - data: { - classnames: "backdrop-filter", - }, - }, - ], - }, - { - code: `
Automatic transforms and filters
`, - output: `
Automatic transforms and filters
`, - errors: [ - { - messageId: "classnamesNotNeeded", - data: { - classnames: "transform, filter, backdrop-filter", - }, - }, - ], - }, - { - code: `
overflow-clip/ellipsis
`, - output: `
overflow-clip/ellipsis
`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "overflow-clip", - updated: "text-clip", - }, - }, - ], - }, - { - code: `
overflow-clip/ellipsis
`, - output: `
overflow-clip/ellipsis
`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "overflow-ellipsis", - updated: "text-ellipsis", - }, - }, - ], - }, - { - code: `
support named group/peer syntax
`, - output: `
support named group/peer syntax
`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "group/name:overflow-ellipsis", - updated: "group/name:text-ellipsis", - }, - }, - ], - }, - { - code: `
flex-grow/shrink
`, - output: `
flex-grow/shrink
`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "flex-grow-0", - updated: "grow-0", - }, - }, - ], - }, - { - code: `
flex-grow/shrink
`, - output: `
flex-grow/shrink
`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "flex-shrink", - updated: "shrink", - }, - }, - ], - }, - { - code: `
decoration-clone/slice
`, - output: `
decoration-clone/slice
`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "decoration-clone", - updated: "box-decoration-clone", - }, - }, - ], - }, - { - code: `
decoration-clone/slice
`, - output: `
decoration-clone/slice
`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "decoration-slice", - updated: "box-decoration-slice", - }, - }, - ], - }, - { - code: `
bg-opacity
`, - errors: [ - { - messageId: "classnameOpacityDeprecated", - data: { - classname: "bg-opacity-50", - value: "50", - }, - }, - ], - }, - { - code: `
ring-opacity
`, - errors: [ - { - messageId: "classnameOpacityDeprecated", - data: { - classname: "ring-opacity-50", - value: "50", - }, - }, - { - messageId: "classnameOpacityDeprecated", - data: { - classname: "border-opacity-50", - value: "50", - }, - }, - ], - }, - { - code: `
`, - output: `
`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "placeholder-red-900", - updated: "placeholder:text-red-900", - }, - }, - ], - }, - { - code: `classnames(["placeholder-red-900"])`, - output: `classnames(["placeholder:text-red-900"])`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "placeholder-red-900", - updated: "placeholder:text-red-900", - }, - }, - ], - }, - { - code: `classnames({"placeholder-red-900": true})`, - output: `classnames({"placeholder:text-red-900": true})`, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "placeholder-red-900", - updated: "placeholder:text-red-900", - }, - }, - ], - }, - { - code: ` - @if (session()->has('status')) -

- {{ session('status') }} -

- @endif`, - output: ` - @if (session()->has('status')) -

- {{ session('status') }} -

- @endif`, - parser: require.resolve("@angular-eslint/template-parser"), - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "flex-shrink", - updated: "shrink", - }, - }, - ], - }, - { - code: `
`, - output: `
`, - options: skipClassAttributeOptions, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "placeholder-red-900", - updated: "placeholder:text-red-900", - }, - }, - ], - }, - { - code: ` - - `, - output: ` - - `, - options: skipClassAttributeOptions, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "placeholder-red-900", - updated: "placeholder:text-red-900", - }, - }, - ], - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - output: ` - - `, - options: skipClassAttributeOptions, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "flex-shrink", - updated: "shrink", - }, - }, - ], - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - output: ` - - `, - options: skipClassAttributeOptions, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "decoration-slice", - updated: "box-decoration-slice", - }, - }, - ], - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - { - code: ` - - `, - output: ` - - `, - options: skipClassAttributeOptions, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "flex-grow-0", - updated: "grow-0", - }, - }, - ], - filename: "test.vue", - parser: require.resolve("vue-eslint-parser"), - }, - ...(['myTag', 'myTag.subTag', 'myTag(SomeComponent)'].map(tag => ({ - code: `${tag}\`flex-grow-0\``, - output: `${tag}\`grow-0\``, - errors: [ - { - messageId: "classnameChanged", - data: { - deprecated: "flex-grow-0", - updated: "grow-0", - }, - }, - ], - options: [ - { - tags: ["myTag"], - }, - ], - }))), - ], -}); diff --git a/tests/lib/rules/no-arbitrary-value.js b/tests/lib/rules/no-arbitrary-value.js deleted file mode 100644 index 0a438e0d..00000000 --- a/tests/lib/rules/no-arbitrary-value.js +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @fileoverview Forbid using arbitrary values in classnames - * @author FranΓ§ois Massart - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var rule = require("../../../lib/rules/no-arbitrary-value"); -var RuleTester = require("eslint").RuleTester; - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -var parserOptions = { - ecmaVersion: 2019, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, -}; - -const skipClassAttributeOptions = [ - { - skipClassAttribute: true, - config: { - theme: {}, - plugins: [], - }, - }, -]; - -var generateErrors = (classnames) => { - const errors = []; - if (typeof classnames === "string") { - classnames = classnames.split(" "); - } - classnames.map((classname) => { - errors.push({ - messageId: "arbitraryValueDetected", - data: { - classname: classname, - }, - }); - }); - return errors; -}; - -var ruleTester = new RuleTester({ parserOptions }); - -ruleTester.run("no-arbitrary-value", rule, { - valid: [ - { - code: `
No arbitrary value
`, - }, - { - code: `
No errors while typing
`, - }, - { - code: `
Skip class attribute
`, - options: skipClassAttributeOptions, - }, - { - code: `
Issue #318
`, - }, - ], - - invalid: [ - { - code: `
Arbitrary width!
`, - errors: generateErrors("w-[10px]"), - }, - { - code: `
Arbitrary width in named group!
`, - errors: generateErrors("group/name:w-[10px]"), - }, - { - code: `
Arbitrary width!
`, - errors: generateErrors("w-[10px]"), - }, - { - code: `
Arbitrary values!
`, - errors: generateErrors("bg-[rgba(10,20,30,0.5)] [mask-type:luminance]"), - }, - { - code: `ctl(\` - [mask-type:luminance] - container - flex - bg-[rgba(10,20,30,0.5)] - w-12 - sm:w-6 - lg:w-4 - \`)`, - errors: generateErrors("[mask-type:luminance] bg-[rgba(10,20,30,0.5)]"), - }, - { - code: ` -