diff --git a/.github/workflows/auto_test.yml b/.github/workflows/auto_test.yml index c39fa9b..d169c09 100644 --- a/.github/workflows/auto_test.yml +++ b/.github/workflows/auto_test.yml @@ -4,9 +4,9 @@ name: Tests on: # Triggers the workflow on push or pull request events but only for the "main" branch push: - branches: [ "main" ] + branches: ["main"] pull_request: - branches: [ "main" ] + branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -21,7 +21,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Install dependencie using the runners shell - name: Install dependencies @@ -30,4 +30,3 @@ jobs: # Runs test using the runners shell - name: Test run: npm run test - \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..8a4725e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,48 @@ +name: Release + +on: + push: + branches: + - main + - beta + pull_request: + branches: + - main + - beta + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write # to be able to publish a GitHub release + issues: write # to be able to comment on released issues + pull-requests: write # to be able to comment on released pull requests + id-token: write # to enable use of OIDC for npm provenance + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: npm install + + - name: Build NPM package + run: npm run build + + - name: Edit First Release Version + run: sed -i 's/\( FIRST_RELEASE\) = "1.0.0"/\1 = "3.0.0"/' node_modules/semantic-release/lib/definitions/constants.js + + - name: Edit First Prerelease Version + run: sed -i 's/\( FIRSTPRERELEASE\) = "1"/\1 = "3"/' node_modules/semantic-release/lib/definitions/constants.js + + - name: Create Release + if: github.event_name == 'push' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npm run semantic-release + + - name: Dry Run Release + if: github.event_name == 'pull_request' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npm run semantic-release --dry-run diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 7605e7f..0000000 --- a/.prettierignore +++ /dev/null @@ -1,5 +0,0 @@ -build -coverage -dist -node_modules -*.test.* \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index cf7c9eb..0000000 --- a/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "semi": true, - "trailingComma": "all", - "singleQuote": false, - "printWidth": 100, - "tabWidth": 2 -} diff --git a/README.md b/README.md index 138fe9a..32beb60 100644 --- a/README.md +++ b/README.md @@ -8,49 +8,61 @@ Project starts on 30-10-2023 [![npm version](https://img.shields.io/npm/v/next-css-obfuscator?color=red&style=flat)](https://www.npmjs.com/package/next-css-obfuscator) [![npm downloads](https://img.shields.io/npm/dt/next-css-obfuscator?color=blue&style=flat)](https://www.npmjs.com/package/next-css-obfuscator) -> [!CAUTION]\ -> This package has no support for TailwindCSS 4 yet, but is under development, and hopefully will be able to release within 1-2 months. - --- Visit the [GitHub Page](https://github.com/soranoo/next-css-obfuscator/) for better reading experience and latest docs. 😎 ---- +--- + +### πŸŽ‰ Version 3 has NOW been released πŸŽ‰ (πŸ’₯ Breaking Changes) +>[!IMPORTANT]\ +> This version is a major update and has breaking changes. Please read the [migration guide](docs/upgrade-to-v3.md) carefully before upgrading. -### πŸŽ‰ Version 2.1.0 has NOW been released πŸŽ‰ - Shout out to [hoangnhan2ka3](https://github.com/hoangnhan2ka3) for providing a πŸ’ͺwonderful [issue](https://github.com/soranoo/next-css-obfuscator/issues/6) report and a demo site. +>[!TIP]\ +> Don't upgrade to this version unless you are using TailwindCSS 4.0.0 or above. "If it works, don't touch it." :) - #### πŸ“Œ Changes - - Much Much Much better quality of CSS selector obfuscation - - Delete original CSS automatically after obfuscation (only apply at full obfuscation) - - Support TailwindCSS Universal Selector (eg. `*:pt-4`) - - More tests +#### πŸ“Œ Feature Changes + +- Support TailwindCSS 4. +- Support nested CSS. +- Support CSS idents obfuscation. - #### πŸ“Œ Configuration Changes - - Removed `customTailwindDarkModeSelector` option, the dark mode selector will be automatically obfuscated at full obfuscation. - - Merged `includeAnyMatchRegexes` and `excludeAnyMatchRegexes` options into `whiteListedFolderPaths` and `blackListedFolderPaths` options. (Directly move the regexes to the `whiteListedFolderPaths` and `blackListedFolderPaths` options) - - Added `removeOriginalCss` option, default to `false`. Set to `true` to delete original CSS from CSS files if it has a obfuscated version. - - `classIgnore` option now supports Regex. +#### πŸ“Œ Configuration Changes + +- `enableJsAst` option is now enabled by default. +- Default `generatorSeed` not longer fixed to `-1`, but a random string. +- `simplify-seedable` mode is not longer supported. Use `random` mode instead. +- Removed `includeAnyMatchRegexes` and `excludeAnyMatchRegexes` options, the `whiteListedFolderPaths` and `blackListedFolderPaths` options will be used instead. +- Deprecated `classLength` option, not longer supported. +- Added `ignorePatterns` option to ignore the class names and idents that match the regexes or strings. +- Not longer preserve TailwindCSS dark mode class names (ie `.dark`). Add the dark mode class name to the `ignorePatterns.selectors` option to preserve it. +- Merge `classIgnore` into `ignorePatterns.selectors` option. +- Renamed `classPrefix` and `classSuffix` to `prefix` and `suffix`. ### πŸ’₯ Version 2 (Major Update) + This version is deeply inspired by [PostCSS-Obfuscator](https://github.com/n4j1Br4ch1D/postcss-obfuscator). Shout out to [n4j1Br4ch1D](https://github.com/n4j1Br4ch1D) for creating such a great package and thank you [tremor](https://github.com/tremorlabs) for sponsoring this project. - #### πŸ“Œ Changes - - Support basic partial obfuscation - - Support TailwindCSS Dark Mode - - New configuration file `next-css-obfuscator.config.cjs` - - More configuration options - - Now become a independent solution (no need to patch `PostCSS-Obfuscator` anymore) - - More tests - - Better CSS parsing +#### πŸ“Œ Changes + +- Support basic partial obfuscation +- Support TailwindCSS Dark Mode +- New configuration file `next-css-obfuscator.config.cjs` +- More configuration options +- Now become a independent solution (no need to patch `PostCSS-Obfuscator` anymore) +- More tests +- Better CSS parsing ### πŸ“š Migration Guides -- [Migrate from version 1.x to 2.x](docs/upgrade-to-v2.md) +- [Migrate from version 1.x to 2.x](docs/upgrade-to-v2.md) +- [Migrate from version 2.x to 3.x](docs/upgrade-to-v3.md) [version 1.x README](https://github.com/soranoo/next-css-obfuscator/tree/v.1.1.0) +[version 2.x README](https://github.com/soranoo/next-css-obfuscator/tree/v.2.2.19) + Give me a ⭐ if you like it. ## πŸ“– Table of Contents @@ -152,21 +164,29 @@ Visit the [npm](https://www.npmjs.com/package/next-css-obfuscator) page. 1. Create and add the following code to `next-css-obfuscator.config.cjs` or `next-css-obfuscator.config.ts`: - ##### Obfuscate all files + ##### Obfuscate all files + ```javascript + /** @type {import("next-css-obfuscator").Options} */ module.exports = { enable: true, - mode: "random", // random | simplify | simplify-seedable + mode: "random", // random | simplify refreshClassConversionJson: false, // recommended set to true if not in production allowExtensions: [".jsx", ".tsx", ".js", ".ts", ".html", ".rsc"], }; ``` - ##### Partially obfuscate + + ##### Partially obfuscate + +> [!CAUTION]\ +> Partially obfuscate can be EXTREMELY buggy. Be cautious when using this feature. + ```javascript + /** @type {import("next-css-obfuscator").Options} */ module.exports = { enable: true, - mode: "random", // random | simplify | simplify-seedable + mode: "random", // random | simplify refreshClassConversionJson: false, // recommended set to true if not in production allowExtensions: [".jsx", ".tsx", ".js", ".ts", ".html", ".rsc"], @@ -175,21 +195,10 @@ Visit the [npm](https://www.npmjs.com/package/next-css-obfuscator) page. ``` - ##### TypeScript - ```ts - import { Options } from "next-css-obfuscator"; - - module.exports = { - // other options ... - } as Options; - ``` - - - Feel free to checkout [πŸ“– Config Options Reference](#-config-options-reference) for more options and details. - > [!NOTE]\ - > The obfuscation will never work as expected, tweak the options with your own needs. +> [!TIP]\ +> The obfuscation will never work as expected, tweak the options with your own needs. 2. Add the following code to `package.json`: @@ -232,6 +241,7 @@ to make sure the build is always obfuscated and no need to run `obfuscate-build` > It is a good idea to add the `/css-obfuscator` folder to `.gitignore` to prevent the conversion table from being uploaded to the repository. #### Partially obfuscate + To partially obfuscate your project, you have to add the obfuscate marker class to the components you want to obfuscate. ```diff @@ -260,14 +270,15 @@ See [Next 14 App Router Partially Obfuscated Demo](https://github.com/soranoo/ne ## πŸ”§ My Setting -If you are interested in my setting (from my production site), here it is +If you are interested in my setting, here it is ```javascript // next-css-obfuscator.config.cjs +/** @type {import("next-css-obfuscator").Options} */ module.exports = { enable: true, - mode: "random", // random | simplify | simplify-seedable + mode: "random", // random | simplify refreshClassConversionJson: false, // recommended set to true if not in production allowExtensions: [".jsx", ".tsx", ".js", ".ts", ".html", ".rsc"], @@ -280,6 +291,7 @@ module.exports = { ], }; ``` + [*1] See this [comment](https://github.com/soranoo/next-css-obfuscator/issues/6#issuecomment-1919495298) It may not be the best setting but it works for me. :) @@ -289,29 +301,31 @@ It may not be the best setting but it works for me. :) | Option | Type | Default | Description | | ---------------------------- | ----------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | | enable | boolean | true | Enable or disable the obfuscation. | -|mode| "random" \| "simplify" \| "simplify-seedable" | "random" | Obfuscate mode,

**random**: Fixed size random class name

**simplify**: Alphabetic class name, like [medium](https://medium.com/)

**simplify-seedable**: Random dynamic size class name| +| mode | "random" \| "simplify" | "random" | Obfuscate mode,

**random**: Fixed size random class name

**simplify**: Alphabetic class name, like [medium](https://medium.com/)| |buildFolderPath|string|"./.next"|The folder path to store the build files built by Next.js.| |classConversionJsonFolderPath|string|"./css-obfuscator"|The folder path to store the before obfuscate and after obfuscated classes conversion table.| |refreshClassConversionJson|boolean|false|Refresh the class conversion JSON file(s) at every obfuscation. Good for setting tweaking but not recommended for production.| -|classLength|number|5|The length of the obfuscated class name if in random mode.

It is not recommended to set the length to less than 4. -|classPrefix|string|""|The prefix of the obfuscated class name.| -|classSuffix|string|""|The suffix of the obfuscated class name.| -|classIgnore|(string \| Regex)[ ]|[ ]|The class names to be ignored during obfuscation.| +|prefix.selectors|string|""|The prefix of the obfuscated classname.| +|prefix.idents|string|""|The prefix of the obfuscated ident name.| +|suffix.selectors|string|""|The suffix of the obfuscated classname.| +|suffix.idents|string|""|The suffix of the obfuscated ident name.| +|ignorePatterns|{selectors: [], idents: []}|{selectors: [], idents: []}|The patterns to be ignored during obfuscation.| |allowExtensions|string[ ]|[".jsx", ".tsx", ".js", ".ts", ".html", ".rsc"]|The file extensions to be processed.| |contentIgnoreRegexes|RegExp[ ]|[/\.jsxs\)\("\w+"/g]|The regexes to match the content to be ignored during obfuscation.| -|whiteListedFolderPaths|(string \| Regex)[ ]|[ ]|The folder paths/Regex to be processed. Empty array means all folders will be processed.| -|blackListedFolderPaths|(string \| Regex)[ ]|[ ]|The folder paths/Regex to be ignored.| +|whiteListedFolderPaths|[string \| Regex]( )|[ ]|The folder paths/Regex to be processed. Empty array means all folders will be processed.| +|blackListedFolderPaths|[string \| Regex]( )|[ ]|The folder paths/Regex to be ignored.| |enableMarkers|boolean|false|Enable or disable the obfuscation markers.| |markers|string[ ]|[ ]|Classes that indicate component(s) need to obfuscate.| |removeMarkersAfterObfuscated|boolean|true|Remove the obfuscation markers from HTML elements after obfuscation.| |removeOriginalCss|boolean|false|Delete original CSS from CSS files if it has a obfuscated version. (*NOT recommended* using in partial obfuscation) -|generatorSeed|string|"-1"|The seed for the random class name generator. "-1" means use random seed.

For "random" and "simplify-seedable" mode only. | +|generatorSeed|string \| undefined|{random string}|The seed for the random class name generator. "undefined" means use random seed.

For "random" mode only. | |logLevel|"debug" \| "info" \| "warn" \| "error" \| "success"| "info"|The log level.| ### Experimental Features Options 🚧 + | Option| Type| Default| Description| Stage | | - | - | - | - | - | -|enableJsAst|boolean|false|Whether to obfuscate JS files using abstract syntax tree parser.

`contentIgnoreRegexes` option will be ignored if this option is enabled.|Alpha| +|enableJsAst|boolean|true|Whether to obfuscate JS files using abstract syntax tree parser.

`contentIgnoreRegexes` option will be ignored if this option is enabled.|Alpha| > [!NOTE]\ > The above options are still at the early stages of development and may not work as expected. @@ -320,26 +334,57 @@ It may not be the best setting but it works for me. :) > [!NOTE]\ > **Stages** - +> > 1. **PoC**: Proof of Concept. The feature is still in the concept stage and is not recommended in production. > 2. **Alpha**: The feature is still in the early stage of development and may not work as expected. > 3. **Beta**: The feature is almost completed and should work as expected but may have some issues. (if no issue is reported in a period, it will be considered stable.) > 4. **Stable**: The feature is in the final stage of development and should work as expected. ### All options in one place πŸ“¦ + ```js // next-css-obfuscator.config.cjs module.exports = { enable: true, // Enable or disable the plugin. - mode: "random", // Obfuscate mode, "random", "simplify" or "simplify-seedable" + mode: "random", // Obfuscate mode, "random", "simplify" or "simplify-seedable". buildFolderPath: ".next", // Build folder of your project. classConversionJsonFolderPath: "./css-obfuscator", // The folder path to store the before obfuscate and after obfuscated classes conversion table. refreshClassConversionJson: false, // Refresh the class conversion JSON file. + /** + * @deprecated Not longer used from v3.0.0 and will be removed in the next major version. + */ classLength: 5, // Length of the obfuscated class name. + + /** + * @deprecated Merged into `prefix` from v3.0.0 and will be removed in the next major version. + */ classPrefix: "", // Prefix of the obfuscated class name. + + /** + * @deprecated Merged into `suffix` from v3.0.0 and will be removed in the next major version. + */ classSuffix: "", // Suffix of the obfuscated class name. + + prefix: { + selectors: "", // Prefix of the obfuscated classname. + idents: "", // Prefix of the obfuscated ident name. + }, + suffix: { + selectors: "", // Suffix of the obfuscated classname. + idents: "", // Suffix of the obfuscated ident name. + }, + + /** + * @deprecated Merged into `ignorePatterns.selectors` from v3.0.0 and will be removed in the next major version. + */ classIgnore: [], // The class names to be ignored during obfuscation. + ignorePatterns: { // The patterns to be ignored during obfuscation. + selectors: [], // The selectors to be ignored during obfuscation. + idents: [], // The idents to be ignored during obfuscation. + }, + allowExtensions: [".jsx", ".tsx", ".js", ".ts", ".html", ".rsc"], // The file extensions to be processed. contentIgnoreRegexes: [ /\.jsxs\)\("\w+"/g, // avoid accidentally obfuscate the HTML tag @@ -351,10 +396,12 @@ module.exports = { markers: ["next-css-obfuscation"], // Classes that indicate component(s) need to obfuscate. removeMarkersAfterObfuscated: true, // Remove the obfuscation markers from HTML elements after obfuscation. removeOriginalCss: false, // Delete original CSS from CSS files if it has a obfuscated version. - generatorSeed: "-1", // The seed for the random generator. "-1" means use random seed. + generatorSeed: undefined, // The seed for the random generator. "undefined" means use random seed. - //! Experimental feature - enableJsAst: false, // Whether to obfuscate JS files using abstract syntax tree parser (Experimental feature) + /** + * Experimental feature + */ + enableJsAst: true, // Whether to obfuscate JS files using abstract syntax tree parser. (Experimental feature) logLevel: "info", // Log level }; @@ -385,6 +432,7 @@ Your conversion table may be messed up. Try to delete the `classConversionJsonFo In a normal situation, the package will only remove the original CSS that is related to the obfuscation and you should not see any CSS sharing the same declaration block. You are not expected to see this: + ```css /* example.css */ @@ -396,18 +444,20 @@ You are not expected to see this: /* obfuscated form */ .d8964 { - --tw-text-opacity: 1; - color: rgb(214 211 209 / var(--tw-text-opacity)); + --d89645: 1; + color: rgb(214 211 209 / var(--d89645)); } ``` + But this: + ```css /* example.css */ /* obfuscated form */ .d8964 { - --tw-text-opacity: 1; - color: rgb(214 211 209 / var(--tw-text-opacity)); + --d89645: 1; + color: rgb(214 211 209 / var(--d89645)); } ``` @@ -463,6 +513,7 @@ If you are going to obfuscate the whole site, you will get a way more accurate o Thank you to all the sponsors who support this project. #### Organizations (1) +
@@ -475,6 +526,7 @@ Thank you to all the sponsors who support this project.
#### Individuals (1) +
@@ -487,6 +539,7 @@ Thank you to all the sponsors who support this project.
## 🦾 Special Thanks +
@@ -505,9 +558,11 @@ Contributions are welcome! If you find a bug or have a feature request, please o ## πŸ›οΈ Commercial Usage #### IndividualπŸ•Ί + Are you using this package for a personal project? That's great! You can support us by starring this repo on Github ⭐🌟⭐. #### Organization πŸ‘―β€β™‚οΈ + Are you using this package within your organization and generating revenue from it? Fantastic! We depend on your support to continue developing and maintaining the package under an MIT License. You might consider showing your support through [Github Sponsors](https://github.com/sponsors/soranoo). ## πŸ“ License diff --git a/bin/cli.mjs b/bin/cli.mjs index 90ba1c3..40ac88e 100644 --- a/bin/cli.mjs +++ b/bin/cli.mjs @@ -2,4 +2,4 @@ import { obfuscateCli } from "../dist/index.js"; -obfuscateCli(); \ No newline at end of file +obfuscateCli(); diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..923f464 --- /dev/null +++ b/biome.json @@ -0,0 +1,73 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "ignore": [ + "node_modules", + ".next", + "packages/tsconfig", + "demos", + "coverage", + "dist" + ] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "lineWidth": 80, + "indentWidth": 2, + "lineEnding": "lf" + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + + "complexity": { + "noUselessTypeConstraint": "error", + "useLiteralKeys": "error", + "useOptionalChain": "error", + "noForEach": "off" + }, + "correctness": { + "noUnusedVariables": "info", + "useArrayLiterals": "error" + }, + "style": { + "noInferrableTypes": "error", + "noNamespace": "error", + "useAsConstAssertion": "error", + "useBlockStatements": "error", + "useConsistentArrayType": "error", + "useForOf": "error", + "useShorthandFunctionType": "error", + "useImportType": "error" + }, + "suspicious": { + "noDebugger": "info", + "noEmptyBlockStatements": "error", + "noExplicitAny": "error", + "noExtraNonNullAssertion": "error", + "noMisleadingInstantiator": "error", + "noUnsafeDeclarationMerging": "error", + "useAwait": "warn", + "useNamespaceKeyword": "error" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double", + "semicolons": "always", + "trailingCommas": "all" + } + } +} diff --git a/demos/next14-app-router/next-css-obfuscator.config.cjs b/demos/next14-app-router/next-css-obfuscator.config.cjs index 6267c92..14b4b20 100644 --- a/demos/next14-app-router/next-css-obfuscator.config.cjs +++ b/demos/next14-app-router/next-css-obfuscator.config.cjs @@ -1,3 +1,4 @@ +/** @type {import("next-css-obfuscator").Options} */ module.exports = { enable: true, mode: "random", // random | simplify diff --git a/demos/next14-app-router/package-lock.json b/demos/next14-app-router/package-lock.json index 329af0e..5e5ec3b 100644 --- a/demos/next14-app-router/package-lock.json +++ b/demos/next14-app-router/package-lock.json @@ -25,7 +25,7 @@ "cross-env": "^7.0.3", "eslint": "^8.54.0", "eslint-config-next": "^14.0.4", - "next-css-obfuscator": "^2.1.0-beta2", + "next-css-obfuscator": "^3.0.0-beta.5", "postcss": "^8.4.32", "postcss-cli": "^11.0.0", "prettier": "^3.1.0", @@ -55,6 +55,69 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", + "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.27.3", + "@babel/types": "^7.27.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz", + "integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.27.3" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/runtime": { "version": "7.23.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz", @@ -67,6 +130,100 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", + "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@deno/shim-deno": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@deno/shim-deno/-/shim-deno-0.18.2.tgz", + "integrity": "sha512-oQ0CVmOio63wlhwQF75zA4ioolPvOwAoK0yuzcS5bDC1JUvH3y1GS8xPh8EOpcoDQRU4FTG8OQfxhpR+c6DrzA==", + "dev": true, + "dependencies": { + "@deno/shim-deno-test": "^0.5.0", + "which": "^4.0.0" + } + }, + "node_modules/@deno/shim-deno-test": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@deno/shim-deno-test/-/shim-deno-test-0.5.0.tgz", + "integrity": "sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w==", + "dev": true + }, + "node_modules/@deno/shim-deno/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@deno/shim-deno/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, "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", @@ -245,47 +402,47 @@ } }, "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==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "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==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "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==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1078,18 +1235,6 @@ "has-symbols": "^1.0.3" } }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, "node_modules/autoprefixer": { "version": "10.4.16", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", @@ -1465,25 +1610,18 @@ "node": ">= 8" } }, - "node_modules/css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - } - }, - "node_modules/css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==", + "node_modules/css-seasoning": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/css-seasoning/-/css-seasoning-1.9.0.tgz", + "integrity": "sha512-pj0G5jzID0VZrb1Dk+ZljDxjrGmEN2iSM3AEJ1g6pIktFmwjyUkxbxQFEmHi3/cgWOwFNfzSyGTLy85h4g9KiQ==", "dev": true, "dependencies": { - "css": "^2.0.0" + "@deno/shim-deno": "~0.18.0", + "lightningcss-wasm": "^1.29.1", + "xxhash-wasm": "^1.1.0" + }, + "bin": { + "css-seasoning": "bin/cli.mjs" } }, "node_modules/cssesc": { @@ -1527,15 +1665,6 @@ } } }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1627,6 +1756,73 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -1658,6 +1854,18 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", + "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -2788,6 +2996,31 @@ "node": ">= 0.4" } }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.1", + "entities": "^6.0.0" + } + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -3257,6 +3490,18 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3354,6 +3599,31 @@ "node": ">= 0.8.0" } }, + "node_modules/lightningcss-wasm": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-wasm/-/lightningcss-wasm-1.30.1.tgz", + "integrity": "sha512-KJTnKEn0REV6DoJzxG0m5EKVEFA1CVE1isDYpXjsuqWXwLKFPJtA9Z9BSzPZJwAZFN2KaUzy+IWGP59p5bm2sA==", + "bundleDependencies": [ + "napi-wasm" + ], + "dev": true, + "dependencies": { + "napi-wasm": "^1.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-wasm/node_modules/napi-wasm": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -3559,12 +3829,18 @@ } }, "node_modules/next-css-obfuscator": { - "version": "2.1.0-beta2", - "resolved": "https://registry.npmjs.org/next-css-obfuscator/-/next-css-obfuscator-2.1.0-beta2.tgz", - "integrity": "sha512-w9+nNi/9dGCubqgCDOBOTNPZEKGpjl+xYnc3zjTm0ho91vTiIhFO3pvnPwAoJ0HhAsIJ+3N1nSCudctlaVo/kQ==", - "dev": true, - "dependencies": { - "css-parse": "^2.0.0", + "version": "3.0.0-beta.5", + "resolved": "https://registry.npmjs.org/next-css-obfuscator/-/next-css-obfuscator-3.0.0-beta.5.tgz", + "integrity": "sha512-HrmPrwj//A60u6r+7Nlg6WB2JdtU+z4DImiK31jtPwFatbyqRySyBCEGlUngTDeY8mEocUTobuaM+/amPM8iJw==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.23.6", + "@babel/parser": "^7.23.9", + "@babel/traverse": "^7.23.9", + "css-seasoning": "^1.8.0", + "html-escaper": "^3.0.3", + "htmlparser2": "^10.0.0", + "lightningcss-wasm": "^1.29.3", "yargs": "^17.7.2" }, "bin": { @@ -3885,9 +4161,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -4481,13 +4757,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4676,15 +4945,6 @@ "node": ">=8" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -4693,27 +4953,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated", - "dev": true - }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -5299,13 +5538,6 @@ "punycode": "^2.1.0" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5503,6 +5735,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", + "dev": true + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/demos/next14-app-router/package.json b/demos/next14-app-router/package.json index e4e671a..4c77b12 100644 --- a/demos/next14-app-router/package.json +++ b/demos/next14-app-router/package.json @@ -28,7 +28,7 @@ "cross-env": "^7.0.3", "eslint": "^8.54.0", "eslint-config-next": "^14.0.4", - "next-css-obfuscator": "^2.1.0-beta2", + "next-css-obfuscator": "^3.0.0-beta.5", "postcss": "^8.4.32", "postcss-cli": "^11.0.0", "prettier": "^3.1.0", diff --git a/docs/upgrade-to-v3.md b/docs/upgrade-to-v3.md new file mode 100644 index 0000000..7dad9ba --- /dev/null +++ b/docs/upgrade-to-v3.md @@ -0,0 +1,22 @@ +# Toward to version 3 + +Version 3 introduces several breaking changes, primarily focused on supporting TailwindCSS 4, nested CSS, and CSS ident obfuscation. Please review the configuration changes below carefully before upgrading. + +## Configuration + +The following table outlines the changes to the configuration options from version 2.x to 3.x: + +| Old configuration (v2.x) | New configuration (v3.x) | Notes | +| ------------------------------ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| `generatorSeed` (default: -1) | `generatorSeed` (default: {random}) | Default seed is now a random string. Provide a fixed string if you need consistent output across builds (e.g., for CDN caching). | +| `mode: "simplify-seedable"` | β›” (Removed) | Use `mode: "random"` with a fixed `generatorSeed` instead. | +| `classLength` | β›” (Deprecated) | No longer supported. Will be removed in the next major version. | +| `classPrefix` | `prefix.selectors` | Renamed for clarity, now applies to both selectors and idents. `classPrefix` will be removed in the next major version. | +| ➑️ | `prefix.idents` | New option to add specific prefix idents| +| `classSuffix` | `suffix.selectors` | Renamed for clarity, now applies to both selectors and idents. `classSuffix` will be removed in the next major version. | +| ➑️ | `suffix.idents` | New option to add specific suffix idents| +| `classIgnore` | `ignorePatterns.selectors` | Merged into the new `ignorePatterns` object. `classIgnore` will be removed in the next major version. | +| ➑️ | `ignorePatterns.idents` | New option to ignore specific CSS idents| +| `includeAnyMatchRegexes` | β›” (Removed) | Use `whiteListedFolderPaths` instead. | +| `excludeAnyMatchRegexes` | β›” (Removed) | Use `blackListedFolderPaths` instead. | +| (Implicit `.dark` preservation)| (No implicit preservation) | TailwindCSS `.dark` class is no longer preserved by default. Add `.dark` or relevant selectors to `ignorePatterns.selectors`. | diff --git a/package-lock.json b/package-lock.json index 7f52229..6e90343 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,27 +1,31 @@ { "name": "next-css-obfuscator", - "version": "2.2.19", + "version": "3.0.0-beta.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "next-css-obfuscator", - "version": "2.2.19", + "version": "3.0.0-beta.4", "license": "MIT", "dependencies": { "@babel/generator": "^7.23.6", "@babel/parser": "^7.23.9", "@babel/traverse": "^7.23.9", - "css-parse": "^2.0.0", + "css-seasoning": "^1.9.0", "html-escaper": "^3.0.3", "htmlparser2": "^10.0.0", - "recoverable-random": "^1.0.5", + "lightningcss-wasm": "^1.29.3", "yargs": "^17.7.2" }, "bin": { "next-css-obfuscator": "bin/cli.mjs" }, "devDependencies": { + "@biomejs/biome": "1.9.4", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^11.0.1", + "@semantic-release/npm": "^12.0.1", "@types/babel__generator": "^7.6.8", "@types/babel__traverse": "^7.20.5", "@types/html-escaper": "^3.0.4", @@ -29,7 +33,7 @@ "@types/react": "^18.2.31", "@types/yargs": "^17.0.32", "@vitest/coverage-v8": "^3.0.5", - "prettier": "^3.2.4", + "semantic-release": "^24.2.3", "tslib": "^2.6.2", "typescript": "^5.0.2", "vitest": "^3.0.5" @@ -49,81 +53,18 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/generator": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", @@ -196,83 +137,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { "version": "7.26.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", @@ -341,6 +205,207 @@ "node": ">=18" } }, + "node_modules/@biomejs/biome": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", + "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "dev": true, + "hasInstallScript": true, + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", + "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", + "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", + "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", + "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", + "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", + "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", + "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", + "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@deno/shim-deno": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@deno/shim-deno/-/shim-deno-0.18.2.tgz", + "integrity": "sha512-oQ0CVmOio63wlhwQF75zA4ioolPvOwAoK0yuzcS5bDC1JUvH3y1GS8xPh8EOpcoDQRU4FTG8OQfxhpR+c6DrzA==", + "dependencies": { + "@deno/shim-deno-test": "^0.5.0", + "which": "^4.0.0" + } + }, + "node_modules/@deno/shim-deno-test": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@deno/shim-deno-test/-/shim-deno-test-0.5.0.tgz", + "integrity": "sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w==" + }, + "node_modules/@deno/shim-deno/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@deno/shim-deno/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", @@ -914,26 +979,277 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "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==", "dev": true, - "optional": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, "engines": { - "node": ">=14" + "node": ">= 8" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.2.tgz", - "integrity": "sha512-6Fyg9yQbwJR+ykVdT9sid1oc2ewejS6h4wzQltmJfSW53N60G/ah9pngXGANdy9/aaE/TcUFpWosdm7JXS1WTQ==", - "cpu": [ - "arm" - ], + "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==", "dev": true, - "optional": true, - "os": [ + "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==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@octokit/auth-token": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", + "dev": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.5.tgz", + "integrity": "sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.2.2", + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", + "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", + "dev": true, + "dependencies": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", + "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", + "dev": true, + "dependencies": { + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.0.0.tgz", + "integrity": "sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", + "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.10.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.2.1.tgz", + "integrity": "sha512-wUc3gv0D6vNHpGxSaR3FlqJpTXGWgqmk607N9L3LvPL4QjaxDgX/1nY2mGpT37Khn+nlIXdljczkRnNdTTV3/A==", + "dev": true, + "dependencies": { + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.6.1.tgz", + "integrity": "sha512-bt3EBUkeKUzDQXRCcFrR9SWVqlLFRRqcCrr6uAorWt6NXTyjMKqcGrFmXqJy9NCbnKgiIZ2OXWq04theFc76Jg==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.7.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^6.1.3" + } + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/request": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.3.tgz", + "integrity": "sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", + "dev": true, + "dependencies": { + "@octokit/types": "^14.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.0.0.tgz", + "integrity": "sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^25.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", + "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", + "dev": true, + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.2.tgz", + "integrity": "sha512-6Fyg9yQbwJR+ykVdT9sid1oc2ewejS6h4wzQltmJfSW53N60G/ah9pngXGANdy9/aaE/TcUFpWosdm7JXS1WTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ "android" ] }, @@ -1171,134 +1487,460 @@ "win32" ] }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true + }, + "node_modules/@semantic-release/commit-analyzer": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-13.0.1.tgz", + "integrity": "sha512-wdnBPHKkr9HhNhXOhZD5a2LNl91+hs8CC2vsAVYxtZH3y0dV3wKn+uZSN61rdJQZ8EGxzWB3inWocBHV9+u/CQ==", "dev": true, "dependencies": { - "@babel/types": "^7.0.0" + "conventional-changelog-angular": "^8.0.0", + "conventional-changelog-writer": "^8.0.0", + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.0.0", + "debug": "^4.0.0", + "import-from-esm": "^2.0.0", + "lodash-es": "^4.17.21", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=20.8.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" + "engines": { + "node": ">=18" } }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@types/html-escaper": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/html-escaper/-/html-escaper-3.0.4.tgz", - "integrity": "sha512-UKSaMPMXXKnq1jDj74seVikfdq5pWvoXcIgOUbwYzHuAEGiv8/juom1i/MsWBF8boFSI0uHQCSZauzr5OYnnJA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.8.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", - "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "node_modules/@semantic-release/git": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz", + "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.0", + "p-reduce": "^2.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" } }, - "node_modules/@types/prop-types": { - "version": "15.7.9", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", - "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.2.33", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", - "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", + "node_modules/@semantic-release/git/node_modules/@semantic-release/error": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", + "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" + "engines": { + "node": ">=14.17" } }, - "node_modules/@types/scheduler": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", - "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "node_modules/@semantic-release/git/node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "dependencies": { - "@types/yargs-parser": "*" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true - }, - "node_modules/@vitest/coverage-v8": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz", - "integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==", + "node_modules/@semantic-release/git/node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^1.0.2", - "debug": "^4.4.0", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.6", - "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.17", - "magicast": "^0.3.5", - "std-env": "^3.8.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/browser": "3.0.5", - "vitest": "3.0.5" - }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } + "engines": { + "node": ">=6" } }, - "node_modules/@vitest/expect": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", - "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", + "node_modules/@semantic-release/git/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "@vitest/spy": "3.0.5", - "@vitest/utils": "3.0.5", - "chai": "^5.1.2", - "tinyrainbow": "^2.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@vitest/mocker": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", - "integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", + "node_modules/@semantic-release/git/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/@semantic-release/git/node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/git/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/git/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@semantic-release/git/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/git/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/git/node_modules/p-reduce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", + "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/git/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/@semantic-release/git/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@semantic-release/github": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.1.tgz", + "integrity": "sha512-Z9cr0LgU/zgucbT9cksH0/pX9zmVda9hkDPcgIE0uvjMQ8w/mElDivGjx1w1pEQ+MuQJ5CBq3VCF16S6G4VH3A==", + "dev": true, + "dependencies": { + "@octokit/core": "^6.0.0", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-retry": "^7.0.0", + "@octokit/plugin-throttling": "^9.0.0", + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^5.0.0", + "debug": "^4.3.4", + "dir-glob": "^3.0.1", + "globby": "^14.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "issue-parser": "^7.0.0", + "lodash-es": "^4.17.21", + "mime": "^4.0.0", + "p-filter": "^4.0.0", + "url-join": "^5.0.0" + }, + "engines": { + "node": ">=20.8.1" + }, + "peerDependencies": { + "semantic-release": ">=24.1.0" + } + }, + "node_modules/@semantic-release/npm": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-12.0.1.tgz", + "integrity": "sha512-/6nntGSUGK2aTOI0rHPwY3ZjgY9FkXmEHbW9Kr+62NVOsyqpKKeP0lrCH+tphv+EsNdJNmqqwijTEnVWUMQ2Nw==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^5.0.0", + "execa": "^9.0.0", + "fs-extra": "^11.0.0", + "lodash-es": "^4.17.21", + "nerf-dart": "^1.0.0", + "normalize-url": "^8.0.0", + "npm": "^10.5.0", + "rc": "^1.2.8", + "read-pkg": "^9.0.0", + "registry-auth-token": "^5.0.0", + "semver": "^7.1.2", + "tempy": "^3.0.0" + }, + "engines": { + "node": ">=20.8.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/release-notes-generator": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-14.0.3.tgz", + "integrity": "sha512-XxAZRPWGwO5JwJtS83bRdoIhCiYIx8Vhr+u231pQAsdFIAbm19rSVJLdnBN+Avvk7CKvNQE/nJ4y7uqKH6WTiw==", + "dev": true, + "dependencies": { + "conventional-changelog-angular": "^8.0.0", + "conventional-changelog-writer": "^8.0.0", + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.0.0", + "debug": "^4.0.0", + "get-stream": "^7.0.0", + "import-from-esm": "^2.0.0", + "into-stream": "^7.0.0", + "lodash-es": "^4.17.21", + "read-package-up": "^11.0.0" + }, + "engines": { + "node": ">=20.8.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/get-stream": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", + "integrity": "sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/html-escaper": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/html-escaper/-/html-escaper-3.0.4.tgz", + "integrity": "sha512-UKSaMPMXXKnq1jDj74seVikfdq5pWvoXcIgOUbwYzHuAEGiv8/juom1i/MsWBF8boFSI0uHQCSZauzr5OYnnJA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.8.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", + "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.9", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", + "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.2.33", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", + "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", + "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@vitest/coverage-v8": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz", + "integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^1.0.2", + "debug": "^4.4.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.17", + "magicast": "^0.3.5", + "std-env": "^3.8.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "3.0.5", + "vitest": "3.0.5" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", + "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", + "dev": true, + "dependencies": { + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", + "chai": "^5.1.2", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", + "integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", "dev": true, "dependencies": { "@vitest/spy": "3.0.5", @@ -1386,46 +2028,99 @@ "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "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==", + "node_modules/aggregate-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", + "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", + "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "clean-stack": "^5.2.0", + "indent-string": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=12" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "bin": { - "atob": "bin/atob.js" + "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==", + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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/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/argv-formatter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", + "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", + "dev": true + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, "engines": { - "node": ">= 4.5.0" + "node": ">=12" } }, "node_modules/balanced-match": { @@ -1434,6 +2129,18 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "dev": true + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1443,6 +2150,18 @@ "balanced-match": "^1.0.0" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -1452,6 +2171,15 @@ "node": ">=8" } }, + "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/chai": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", @@ -1468,6 +2196,27 @@ "node": ">=12" } }, + "node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", @@ -1477,6 +2226,111 @@ "node": ">= 16" } }, + "node_modules/clean-stack": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", + "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/cli-highlight/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/cli-highlight/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/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -1506,6 +2360,124 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.0.0.tgz", + "integrity": "sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.0.1.tgz", + "integrity": "sha512-hlqcy3xHred2gyYg/zXSMXraY2mjAYYo0msUCpK+BGyaVJMFCKWVXPIHiaacGO2GGp13kvHWXFhYmxT4QQqW3Q==", + "dev": true, + "dependencies": { + "conventional-commits-filter": "^5.0.0", + "handlebars": "^4.7.7", + "meow": "^13.0.0", + "semver": "^7.5.2" + }, + "bin": { + "conventional-changelog-writer": "dist/cli/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-commits-filter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-5.0.0.tgz", + "integrity": "sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-commits-parser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.1.0.tgz", + "integrity": "sha512-5nxDo7TwKB5InYBl4ZC//1g9GRwB/F3TXOGR9hgUjMGfvSP4Vu5NkpNro2+1+TIEy1vwxApl5ircECr2ri5JIw==", + "dev": true, + "dependencies": { + "meow": "^13.0.0" + }, + "bin": { + "conventional-commits-parser": "dist/cli/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/convert-hrtime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/convert-hrtime/-/convert-hrtime-5.0.0.tgz", + "integrity": "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1520,23 +2492,44 @@ "node": ">= 8" } }, - "node_modules/css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, "dependencies": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==", + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-seasoning": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/css-seasoning/-/css-seasoning-1.9.0.tgz", + "integrity": "sha512-pj0G5jzID0VZrb1Dk+ZljDxjrGmEN2iSM3AEJ1g6pIktFmwjyUkxbxQFEmHi3/cgWOwFNfzSyGTLy85h4g9KiQ==", "dependencies": { - "css": "^2.0.0" + "@deno/shim-deno": "~0.18.0", + "lightningcss-wasm": "^1.29.1", + "xxhash-wasm": "^1.1.0" + }, + "bin": { + "css-seasoning": "bin/cli.mjs" } }, "node_modules/csstype": { @@ -1561,14 +2554,6 @@ } } }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", @@ -1578,6 +2563,27 @@ "node": ">=6" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "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/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -1640,6 +2646,27 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -1651,6 +2678,12 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "dev": true + }, "node_modules/entities": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", @@ -1662,16 +2695,154 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", + "node_modules/env-ci": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.1.0.tgz", + "integrity": "sha512-Z8dnwSDbV1XYM9SBF2J0GcNVvmfmfh3a49qddGIROhBoVro6MZVTji15z/sJbQ2ko2ei8n988EU1wzoLU/tF+g==", + "dev": true, + "dependencies": { + "execa": "^8.0.0", + "java-properties": "^1.0.2" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + } + }, + "node_modules/env-ci/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/env-ci/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/env-ci/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-module-lexer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", + "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1717,6 +2888,18 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -1726,6 +2909,48 @@ "@types/estree": "^1.0.0" } }, + "node_modules/execa": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", + "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.3", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.0", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/expect-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", @@ -1735,6 +2960,114 @@ "node": ">=12.0.0" } }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "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.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-versions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-6.0.0.tgz", + "integrity": "sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==", + "dev": true, + "dependencies": { + "semver-regex": "^4.0.5", + "super-regex": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -1751,6 +3084,30 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1765,6 +3122,18 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-timeout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/function-timeout/-/function-timeout-1.0.2.tgz", + "integrity": "sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1773,6 +3142,32 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-log-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.1.tgz", + "integrity": "sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==", + "dev": true, + "dependencies": { + "argv-formatter": "~1.0.0", + "spawn-error-forwarder": "~1.0.0", + "split2": "~1.0.0", + "stream-combiner2": "~1.1.1", + "through2": "~2.0.0", + "traverse": "0.6.8" + } + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -1793,6 +3188,18 @@ "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==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -1801,30 +3208,140 @@ "node": ">=4" } }, - "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==", + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/html-escaper": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", - "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==" + "node_modules/globby/node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/htmlparser2": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", - "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } + "node_modules/globby/node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "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/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/hook-std": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", + "integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "dev": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==" + }, + "node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } ], "dependencies": { "domelementtype": "^2.3.0", @@ -1833,10 +3350,164 @@ "entities": "^6.0.0" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/ignore": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", + "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "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/import-fresh/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/import-from-esm": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-2.0.0.tgz", + "integrity": "sha512-YVt14UZCgsX1vZQ3gKjkWVdBdHQ6eu3MPU1TBgL1H5orXe2+jWD006WCPPtOuwlQm10NuzOW5WawiF1Q9veW8g==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "import-meta-resolve": "^4.0.0" + }, + "engines": { + "node": ">=18.20" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/index-to-position": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz", + "integrity": "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/into-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-7.0.0.tgz", + "integrity": "sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==", + "dev": true, + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", @@ -1846,12 +3517,100 @@ "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==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/issue-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-7.0.1.tgz", + "integrity": "sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==", + "dev": true, + "dependencies": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -1923,11 +3682,32 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/java-properties": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", + "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "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/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -1939,37 +3719,173 @@ "node": ">=4" } }, - "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "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==", + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "universalify": "^2.0.0" }, - "engines": { - "node": ">=10" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, + "node_modules/lightningcss-wasm": { + "version": "1.29.3", + "resolved": "https://registry.npmjs.org/lightningcss-wasm/-/lightningcss-wasm-1.29.3.tgz", + "integrity": "sha512-j02QNSRVBKxsSBinpSCgx3x8XwwOoO50ekDO1O5rBf+dS0j46qSojv+3BDzMNCaGFJ18EjcnXGDkG3ImIbU/PQ==", + "bundleDependencies": [ + "napi-wasm" + ], "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "napi-wasm": "^1.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/magicast": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", - "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "node_modules/lightningcss-wasm/node_modules/napi-wasm": { + "version": "1.1.3", + "inBundle": true, + "license": "MIT" + }, + "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/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true + }, + "node_modules/loupe": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "dev": true + }, + "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/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, "dependencies": { "@babel/parser": "^7.25.4", @@ -1992,6 +3908,118 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/marked": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/marked-terminal": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.3.0.tgz", + "integrity": "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^7.0.0", + "ansi-regex": "^6.1.0", + "chalk": "^5.4.1", + "cli-highlight": "^2.1.11", + "cli-table3": "^0.6.5", + "node-emoji": "^2.2.0", + "supports-hyperlinks": "^3.1.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "marked": ">=1 <16" + } + }, + "node_modules/marked-terminal/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.7.tgz", + "integrity": "sha512-2OfDPL+e03E0LrXaGYOtTFIYhiuzep94NSsuhrNULq+stylcJedcHdzHtz0atMUuGwJfFYs0YL5xeC/Ca2x0eQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -2007,6 +4035,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -2021,6 +4058,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "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.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -2040,12 +4088,3053 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", + "dev": true + }, + "node_modules/node-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.2.tgz", + "integrity": "sha512-iriPEPIkoMYUy3F6f3wwSZAU93E0Eg6cHwIR6jzzOXWSy+SD/rOODEs74cVONHKSx2obXtuUoyidVEhISrisgQ==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/redact", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "normalize-package-data", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dev": true, + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^8.0.0", + "@npmcli/config": "^9.0.0", + "@npmcli/fs": "^4.0.0", + "@npmcli/map-workspaces": "^4.0.2", + "@npmcli/package-json": "^6.1.0", + "@npmcli/promise-spawn": "^8.0.2", + "@npmcli/redact": "^3.0.0", + "@npmcli/run-script": "^9.0.1", + "@sigstore/tuf": "^3.0.0", + "abbrev": "^3.0.0", + "archy": "~1.0.0", + "cacache": "^19.0.1", + "chalk": "^5.3.0", + "ci-info": "^4.1.0", + "cli-columns": "^4.0.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.4.5", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^8.0.2", + "ini": "^5.0.0", + "init-package-json": "^7.0.2", + "is-cidr": "^5.1.0", + "json-parse-even-better-errors": "^4.0.0", + "libnpmaccess": "^9.0.0", + "libnpmdiff": "^7.0.0", + "libnpmexec": "^9.0.0", + "libnpmfund": "^6.0.0", + "libnpmhook": "^11.0.0", + "libnpmorg": "^7.0.0", + "libnpmpack": "^8.0.0", + "libnpmpublish": "^10.0.1", + "libnpmsearch": "^8.0.0", + "libnpmteam": "^7.0.0", + "libnpmversion": "^7.0.0", + "make-fetch-happen": "^14.0.3", + "minimatch": "^9.0.5", + "minipass": "^7.1.1", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^11.0.0", + "nopt": "^8.0.0", + "normalize-package-data": "^7.0.0", + "npm-audit-report": "^6.0.0", + "npm-install-checks": "^7.1.1", + "npm-package-arg": "^12.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-profile": "^11.0.1", + "npm-registry-fetch": "^18.0.2", + "npm-user-validate": "^3.0.0", + "p-map": "^4.0.0", + "pacote": "^19.0.1", + "parse-conflict-json": "^4.0.0", + "proc-log": "^5.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^4.0.0", + "semver": "^7.6.3", + "spdx-expression-parse": "^4.0.0", + "ssri": "^12.0.0", + "supports-color": "^9.4.0", + "tar": "^6.2.1", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^6.0.0", + "which": "^5.0.0", + "write-file-atomic": "^6.0.0" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/agent": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^4.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/map-workspaces": "^4.0.1", + "@npmcli/metavuln-calculator": "^8.0.0", + "@npmcli/name-from-folder": "^3.0.0", + "@npmcli/node-gyp": "^4.0.0", + "@npmcli/package-json": "^6.0.1", + "@npmcli/query": "^4.0.0", + "@npmcli/redact": "^3.0.0", + "@npmcli/run-script": "^9.0.1", + "bin-links": "^5.0.0", + "cacache": "^19.0.1", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^8.0.0", + "json-parse-even-better-errors": "^4.0.0", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^10.2.2", + "minimatch": "^9.0.4", + "nopt": "^8.0.0", + "npm-install-checks": "^7.1.0", + "npm-package-arg": "^12.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.1", + "pacote": "^19.0.0", + "parse-conflict-json": "^4.0.0", + "proc-log": "^5.0.0", + "proggy": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^4.0.0", + "semver": "^7.3.7", + "ssri": "^12.0.0", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/config": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^4.0.1", + "@npmcli/package-json": "^6.0.1", + "ci-info": "^4.0.0", + "ini": "^5.0.0", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^8.0.0", + "ini": "^5.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^10.0.0", + "proc-log": "^5.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "8.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cacache": "^19.0.0", + "json-parse-even-better-errors": "^4.0.0", + "pacote": "^20.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { + "version": "20.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "6.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^8.0.0", + "json-parse-even-better-errors": "^4.0.0", + "normalize-package-data": "^7.0.0", + "proc-log": "^5.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/query": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^6.1.2" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/redact": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "9.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^4.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "node-gyp": "^11.0.0", + "proc-log": "^5.0.0", + "which": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.3.2", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2", + "tuf-js": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "7.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^7.0.0", + "npm-normalize-package-bin": "^4.0.0", + "proc-log": "^5.0.0", + "read-cmd-shim": "^5.0.0", + "write-file-atomic": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "19.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/chownr": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/minizlib": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/mkdirp": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/p-map": { + "version": "7.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/tar": { + "version": "7.4.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/yallist": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "5.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ci-info": { + "version": "4.1.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "4.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^5.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.6", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/debug": { + "version": "4.3.7", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/diff": { + "version": "5.2.0", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/npm/node_modules/foreground-child": { + "version": "3.3.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "10.4.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "7.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "7.0.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ini": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "7.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/package-json": "^6.0.0", + "npm-package-arg": "^12.0.0", + "promzard": "^2.0.0", + "read": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/ip-address": { + "version": "9.0.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "5.1.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "^4.1.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/jackspeak": { + "version": "3.4.3", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/npm/node_modules/jsbn": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^12.0.0", + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^8.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "binary-extensions": "^2.3.0", + "diff": "^5.1.0", + "minimatch": "^9.0.4", + "npm-package-arg": "^12.0.0", + "pacote": "^19.0.0", + "tar": "^6.2.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^8.0.0", + "@npmcli/run-script": "^9.0.1", + "ci-info": "^4.0.0", + "npm-package-arg": "^12.0.0", + "pacote": "^19.0.0", + "proc-log": "^5.0.0", + "read": "^4.0.0", + "read-package-json-fast": "^4.0.0", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^8.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "11.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^8.0.0", + "@npmcli/run-script": "^9.0.1", + "npm-package-arg": "^12.0.0", + "pacote": "^19.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "10.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "ci-info": "^4.0.0", + "normalize-package-data": "^7.0.0", + "npm-package-arg": "^12.0.0", + "npm-registry-fetch": "^18.0.1", + "proc-log": "^5.0.0", + "semver": "^7.3.7", + "sigstore": "^3.0.0", + "ssri": "^12.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.1", + "@npmcli/run-script": "^9.0.1", + "json-parse-even-better-errors": "^4.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "10.4.3", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "14.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "ssri": "^12.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "7.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-fetch/node_modules/minizlib": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "11.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "tar": "^7.4.3", + "which": "^5.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/minizlib": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/mkdirp": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/tar": { + "version": "7.4.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/nopt/node_modules/abbrev": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^8.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "7.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "12.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^7.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "10.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^7.1.0", + "npm-normalize-package-bin": "^4.0.0", + "npm-package-arg": "^12.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "11.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "18.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/redact": "^3.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^14.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^12.0.0", + "proc-log": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch/node_modules/minizlib": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/package-json-from-dist": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/npm/node_modules/pacote": { + "version": "19.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/proggy": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-inflight": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "read": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "^2.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/rimraf": { + "version": "5.0.10", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.6.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/sigstore": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/sign": "^3.0.0", + "@sigstore/tuf": "^3.0.0", + "@sigstore/verify": "^2.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/bundle": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/core": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/sign": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "make-fetch-happen": "^14.0.1", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/verify": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.8.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "8.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.5.0", + "dev": true, + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.20", + "dev": true, + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/sprintf-js": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/npm/node_modules/ssri": { + "version": "12.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.2.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/models": "3.0.1", + "debug": "^4.3.6", + "make-fetch-happen": "^14.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/tuf-js/node_modules/@tufjs/models": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/which": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/which/node_modules/isexe": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "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/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "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/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-each-series": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", + "integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-4.1.0.tgz", + "integrity": "sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==", + "dev": true, + "dependencies": { + "p-map": "^7.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-reduce": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", + "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "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/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "dev": true + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -2077,6 +7166,15 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "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/pathe": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", @@ -2096,9 +7194,42 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", + "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", @@ -2128,25 +7259,159 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "node_modules/pretty-ms": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", + "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", + "dev": true, + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "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==", + "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/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, "bin": { - "prettier": "bin/prettier.cjs" + "rc": "cli.js" + } + }, + "node_modules/read-package-up": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", + "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", + "dev": true, + "dependencies": { + "find-up-simple": "^1.0.0", + "read-pkg": "^9.0.0", + "type-fest": "^4.6.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/recoverable-random": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/recoverable-random/-/recoverable-random-1.0.5.tgz", - "integrity": "sha512-/8pSRgo2b96TZPK7UshniNn0A/q3ePARXsDL8z0Yvhhk7+PESziarQ0e8mn4YNM7qB6bX0mPcEfMtda4RY/ahA==" + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/registry-auth-token": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.0.tgz", + "integrity": "sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==", + "dev": true, + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } }, "node_modules/require-directory": { "version": "2.1.1", @@ -2156,11 +7421,24 @@ "node": ">=0.10.0" } }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } }, "node_modules/rollup": { "version": "4.34.2", @@ -2200,6 +7478,78 @@ "fsevents": "~2.3.2" } }, + "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==", + "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" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semantic-release": { + "version": "24.2.3", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.3.tgz", + "integrity": "sha512-KRhQG9cUazPavJiJEFIJ3XAMjgfd0fcK3B+T26qOl8L0UG5aZUjeRfREO0KM5InGtYwxqiiytkJrbcYoLDEv0A==", + "dev": true, + "dependencies": { + "@semantic-release/commit-analyzer": "^13.0.0-beta.1", + "@semantic-release/error": "^4.0.0", + "@semantic-release/github": "^11.0.0", + "@semantic-release/npm": "^12.0.0", + "@semantic-release/release-notes-generator": "^14.0.0-beta.1", + "aggregate-error": "^5.0.0", + "cosmiconfig": "^9.0.0", + "debug": "^4.0.0", + "env-ci": "^11.0.0", + "execa": "^9.0.0", + "figures": "^6.0.0", + "find-versions": "^6.0.0", + "get-stream": "^6.0.0", + "git-log-parser": "^1.2.0", + "hook-std": "^3.0.0", + "hosted-git-info": "^8.0.0", + "import-from-esm": "^2.0.0", + "lodash-es": "^4.17.21", + "marked": "^12.0.0", + "marked-terminal": "^7.0.0", + "micromatch": "^4.0.2", + "p-each-series": "^3.0.0", + "p-reduce": "^3.0.0", + "read-package-up": "^11.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.3.2", + "semver-diff": "^4.0.0", + "signale": "^1.2.1", + "yargs": "^17.5.1" + }, + "bin": { + "semantic-release": "bin/semantic-release.js" + }, + "engines": { + "node": ">=20.8.1" + } + }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -2212,52 +7562,201 @@ "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver-regex": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/signale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", + "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", + "dev": true, + "dependencies": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/signale/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/signale/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/signale/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" } }, - "node_modules/shebang-command": { + "node_modules/signale/node_modules/figures": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/shebang-regex": { + "node_modules/signale/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/siginfo": { + "node_modules/signale/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/skin-tone": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "dev": true, + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "engines": { - "node": ">=14" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2271,24 +7770,52 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "node_modules/spawn-error-forwarder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", + "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated" + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", + "dev": true + }, + "node_modules/split2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", + "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", + "dev": true, + "dependencies": { + "through2": "~2.0.0" + } }, "node_modules/stackback": { "version": "0.0.2", @@ -2302,6 +7829,25 @@ "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", "dev": true }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -2354,6 +7900,52 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/super-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/super-regex/-/super-regex-1.0.0.tgz", + "integrity": "sha512-CY8u7DtbvucKuquCmOFEKhr9Besln7n9uN8eFbwcoGYWXOMW07u2o8njWaiXt11ylS3qoGF55pILjRmPlbodyg==", + "dev": true, + "dependencies": { + "function-timeout": "^1.0.1", + "time-span": "^5.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2366,6 +7958,73 @@ "node": ">=8" } }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/test-exclude": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", @@ -2380,6 +8039,52 @@ "node": ">=18" } }, + "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/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/time-span": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/time-span/-/time-span-5.1.0.tgz", + "integrity": "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==", + "dev": true, + "dependencies": { + "convert-hrtime": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -2419,12 +8124,48 @@ "node": ">=14.0.0" } }, + "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==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/traverse": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", + "integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, + "node_modules/type-fest": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.0.tgz", + "integrity": "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", @@ -2438,17 +8179,100 @@ "node": ">=14.17" } }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/url-join": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.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/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } }, "node_modules/vite": { "version": "6.2.6", @@ -2644,6 +8468,12 @@ "node": ">=8" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -2678,6 +8508,20 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -2716,6 +8560,18 @@ "engines": { "node": ">=12" } + }, + "node_modules/yoctocolors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", + "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 07ca11f..3982586 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next-css-obfuscator", - "version": "2.2.19", + "version": "3.0.0-beta.5", "description": "A package deeply inspired by PostCSS-Obfuscator but for Next.js.", "main": "dist/index.js", "type": "commonjs", @@ -10,7 +10,9 @@ "build": "npm run test && tsc", "dev": "tsc -w", "pub": "npm run build && npm publish", - "pub@beta": "npm run build && npm publish --tag beta" + "pub@beta": "npm run build && npm publish --tag beta", + "semantic-release": "semantic-release", + "lint": "biome check ." }, "repository": { "type": "git", @@ -26,13 +28,17 @@ "@babel/generator": "^7.23.6", "@babel/parser": "^7.23.9", "@babel/traverse": "^7.23.9", - "css-parse": "^2.0.0", + "css-seasoning": "^1.9.0", "html-escaper": "^3.0.3", "htmlparser2": "^10.0.0", - "recoverable-random": "^1.0.5", + "lightningcss-wasm": "^1.29.3", "yargs": "^17.7.2" }, "devDependencies": { + "@biomejs/biome": "1.9.4", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^11.0.1", + "@semantic-release/npm": "^12.0.1", "@types/babel__generator": "^7.6.8", "@types/babel__traverse": "^7.20.5", "@types/html-escaper": "^3.0.4", @@ -40,7 +46,7 @@ "@types/react": "^18.2.31", "@types/yargs": "^17.0.32", "@vitest/coverage-v8": "^3.0.5", - "prettier": "^3.2.4", + "semantic-release": "^24.2.3", "tslib": "^2.6.2", "typescript": "^5.0.2", "vitest": "^3.0.5" diff --git a/release.config.cjs b/release.config.cjs new file mode 100644 index 0000000..0dc9519 --- /dev/null +++ b/release.config.cjs @@ -0,0 +1,17 @@ +module.exports = { + branches: [{ name: "main" }, { name: "beta", prerelease: true }], + plugins: [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/npm", + [ + "@semantic-release/git", + { + message: + "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}", + assets: ["package.json", "CHANGELOG.md"], + }, + ], + // "@semantic-release/github", + ], +}; diff --git a/src/__tests__/html.test.ts b/src/__tests__/html.test.ts new file mode 100644 index 0000000..242fce5 --- /dev/null +++ b/src/__tests__/html.test.ts @@ -0,0 +1,254 @@ +import type { SelectorConversion } from "../types"; + +import { describe, expect, it } from "vitest"; + +import { obfuscateHtmlClassNames } from "../handlers/html"; + +//! ================================ +//! obfuscateHtmlClassNames +//! ================================ + +describe("obfuscateHtmlClassNames", () => { + it("should obfuscate class names correctly", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { "\\.foo": "\\.a" }; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual(`
`); + expect(result.usedKeys).to.deep.equal(["\\.foo"]); + }); + + it("should handle nested tags with obfuscate class", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { "\\.foo": "\\.a" }; + const keyClass = "key"; + + // Act + const result = obfuscateHtmlClassNames({ + html, + selectorConversion, + obfuscateMarkerClass: keyClass, + }); + + // Assert + expect(result.obfuscatedContent).toEqual( + `
`, + ); + expect(result.usedKeys).to.deep.equal(["\\.foo"]); + }); + + it("should not obfuscate class names outside of obfuscate class scope", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { + "\\.foo": "\\.a", + "\\.bar": "\\.b", + }; + const keyClass = "key"; + + // Act + const result = obfuscateHtmlClassNames({ + html, + selectorConversion, + obfuscateMarkerClass: keyClass, + }); + + // Assert + expect(result.obfuscatedContent).toEqual( + `
`, + ); + expect(result.usedKeys).to.deep.equal([]); + }); + + it("should handle script tags", () => { + // Arrange + const html = ``; + const selectorConversion: SelectorConversion = { + "\\.fol": "\\.a", + "\\.foo": "\\.b", + }; + + // Act + const result = obfuscateHtmlClassNames({ + html, + selectorConversion, + obfuscateMarkerClass: "", + }); + + // Assert + expect(result.obfuscatedContent).toEqual( + ``, + ); + expect(result.usedKeys).to.deep.equal(["\\.fol", "\\.foo"]); + }); + + it("should handle void tags", () => { + // Arrange + const html = ``; + const selectorConversion: SelectorConversion = { "\\.foo": "\\.a" }; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual(``); + expect(result.usedKeys).to.deep.equal(["\\.foo"]); + }); + + it("should handle comments", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { "\\.foo": "\\.a" }; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual( + `
`, + ); + expect(result.usedKeys).to.deep.equal(["\\.foo"]); + }); + + it("should handle HTML without classes", () => { + // Arrange + const html = "
"; + const selectorConversion: SelectorConversion = {}; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual("
"); + expect(result.usedKeys).to.deep.equal([]); + }); + + it("should handle empty HTML", () => { + // Arrange + const html = ""; + const selectorConversion: SelectorConversion = { "\\.foo": "\\.a" }; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual(""); + expect(result.usedKeys).to.deep.equal([]); + }); + + it("should handle HTML with multiple classes in one element", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { + "\\.foo": "\\.a", + "\\.bar": "\\.b", + "\\.baz": "\\.c", + }; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual(`
`); + expect(result.usedKeys).to.deep.equal(["\\.foo", "\\.bar", "\\.baz"]); + }); + + it("should handle HTML with nested structures and multiple classes", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { + "\\.foo": "\\.a", + "\\.bar": "\\.b", + "\\.baz": "\\.c", + }; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual( + `
`, + ); + expect(result.usedKeys).to.deep.equal(["\\.foo", "\\.bar", "\\.baz"]); + }); + + it("should handle HTML with obfuscate marker class", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { "\\.foo": "\\.a" }; + const obfuscateMarkerClass = "key"; + + // Act + const result = obfuscateHtmlClassNames({ + html, + selectorConversion, + obfuscateMarkerClass, + }); + + // Assert + expect(result.obfuscatedContent).toEqual( + `
`, + ); + expect(result.usedKeys).to.deep.equal(["\\.foo"]); + }); + + it("should handle HTML with multiple classes and obfuscate marker class", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { + "\\.foo": "\\.a", + "\\.bar": "\\.b", + "\\.baz": "\\.c", + }; + const obfuscateMarkerClass = "key"; + + // Act + const result = obfuscateHtmlClassNames({ + html, + selectorConversion, + obfuscateMarkerClass, + }); + + // Assert + expect(result.obfuscatedContent).toEqual(`
`); + expect(result.usedKeys).to.deep.equal(["\\.foo", "\\.bar", "\\.baz"]); + }); + + it("should handle HTML instruction", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { "\\.foo": "\\.a" }; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual( + `
`, + ); + expect(result.usedKeys).to.deep.equal(["\\.foo"]); + }); + + /** + * @see https://github.com/soranoo/next-css-obfuscator/issues/57 + */ + it("should handle double quot inside double quot", () => { + // Arrange + const html = `
`; + const selectorConversion: SelectorConversion = { "\\.foo": "\\.a" }; + + // Act + const result = obfuscateHtmlClassNames({ html, selectorConversion }); + + // Assert + expect(result.obfuscatedContent).toEqual( + `
`, + ); + expect(result.usedKeys).to.deep.equal(["\\.foo"]); + }); +}); diff --git a/src/handlers/js-ast.test.ts b/src/__tests__/js-ast.test.ts similarity index 85% rename from src/handlers/js-ast.test.ts rename to src/__tests__/js-ast.test.ts index 38449ea..2465d53 100644 --- a/src/handlers/js-ast.test.ts +++ b/src/__tests__/js-ast.test.ts @@ -1,31 +1,30 @@ -import { describe, it, expect } from "vitest"; -import traverse, { NodePath } from "@babel/traverse"; -import * as t from "@babel/types"; -import * as parser from "@babel/parser"; import generator from "@babel/generator"; -import { searchStringLiterals, obfuscateJsWithAst } from "./js-ast"; +import * as parser from "@babel/parser"; +import traverse, { type NodePath } from "@babel/traverse"; +import type * as t from "@babel/types"; +import { describe, expect, it } from "vitest"; +import { obfuscateJsWithAst, searchStringLiterals } from "../handlers/js-ast"; -function stripCode(code: string) { +const stripCode = (code: string) => { return code.replace(/\s/g, ""); -} - +}; //! ================================ //! searchStringLiterals //! ================================ describe("searchStringLiterals", () => { - function findStartPointNode(ast: t.File) { + const findStartPointNode = (ast: t.File) => { let startPointNode: NodePath | undefined; traverse(ast, { FunctionDeclaration(path) { if (path.node.id?.name === "startPoint") { - startPointNode = path.get('body'); + startPointNode = path.get("body"); } }, }); return startPointNode; - } + }; //? ******************************* //? Basic @@ -38,26 +37,28 @@ describe("searchStringLiterals", () => { function startPoint() { return "function"; } - ` + `; const expectedCode = ` const a = "test"; function startPoint() { return "{{found}}"; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["function"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should not handle string literals in comments", () => { @@ -67,25 +68,27 @@ describe("searchStringLiterals", () => { function startPoint() { return "function"; } - ` + `; const expectedCode = ` // const a = "test"; function startPoint() { return "{{found}}"; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["function"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -104,7 +107,7 @@ describe("searchStringLiterals", () => { var f = "test6"; return a + b + c + d + e + f; } - ` + `; const expectedCode = ` const a = "{{found}}"; let b = "{{found}}"; @@ -116,18 +119,20 @@ describe("searchStringLiterals", () => { var f = "{{found}}"; return a + b + c + d + e + f; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["test", "test2", "test3", "test4", "test5", "test6"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle variable declarations with multiple variables correctly", () => { @@ -137,25 +142,27 @@ describe("searchStringLiterals", () => { function startPoint() { return a + b; } - ` + `; const expectedCode = ` const a = "{{found}}", b = "{{found}}"; function startPoint() { return a + b; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["test", "test2"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -170,7 +177,7 @@ describe("searchStringLiterals", () => { const localVar = "world"; return "hello" + localVar; } - ` + `; const expectedCode = ` const globalVar = "out"; @@ -178,19 +185,21 @@ describe("searchStringLiterals", () => { const localVar = "{{found}}"; return "{{found}}" + localVar; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "world"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle global variables correctly", () => { @@ -201,7 +210,7 @@ describe("searchStringLiterals", () => { const localVar = "local"; return "hello" + globalVar; } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -209,19 +218,21 @@ describe("searchStringLiterals", () => { const localVar = "local"; return "{{found}}" + globalVar; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "world"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -237,7 +248,7 @@ describe("searchStringLiterals", () => { const localVar = "again"; return "hello" + (localBool ? globalVar : localVar); } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -246,19 +257,21 @@ describe("searchStringLiterals", () => { const localVar = "{{found}}"; return "{{found}}" + (localBool ? globalVar : localVar); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "world", "again"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle if statements correctly", () => { @@ -273,7 +286,7 @@ describe("searchStringLiterals", () => { } return "hello" + localVar; } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -285,19 +298,21 @@ describe("searchStringLiterals", () => { } return "{{found}}" + localVar; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "world", "hello", "again"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -315,7 +330,7 @@ describe("searchStringLiterals", () => { function startPoint() { return "hello" + globalVar + call(); } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -326,19 +341,21 @@ describe("searchStringLiterals", () => { function startPoint() { return "{{found}}" + globalVar + call(); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "global", "world"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle function calls with arguments correctly", () => { @@ -352,7 +369,7 @@ describe("searchStringLiterals", () => { function startPoint() { return "hello" + globalVar + call("world"); } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -363,19 +380,21 @@ describe("searchStringLiterals", () => { function startPoint() { return "{{found}}" + globalVar + call("{{found}}"); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "global", "world"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle function calls with multiple arguments correctly", () => { @@ -389,7 +408,7 @@ describe("searchStringLiterals", () => { function startPoint() { return "hello" + globalVar + call("world", "again"); } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -400,19 +419,21 @@ describe("searchStringLiterals", () => { function startPoint() { return "{{found}}" + globalVar + call("{{found}}", "{{found}}"); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "global", "world", "again"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle function calls with nested function calls correctly", () => { @@ -430,7 +451,7 @@ describe("searchStringLiterals", () => { function startPoint() { return "hello" + globalVar + call(call2("world"), "again"); } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -445,19 +466,21 @@ describe("searchStringLiterals", () => { function startPoint() { return "{{found}}" + globalVar + call(call2("{{found}}"), "{{found}}"); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "global", "world", "again"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle function calls with boolean expressions correctly", () => { @@ -476,7 +499,7 @@ describe("searchStringLiterals", () => { const bool = true; return "hello" + globalVar + call(bool ? "world1" : call2("world2"), "again"); } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -492,19 +515,21 @@ describe("searchStringLiterals", () => { const bool = true; return "{{found}}" + globalVar + call(bool ? "{{found}}" : call2("{{found}}"), "{{found}}"); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "global", "world1", "world2", "again"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle arrow function calls correctly", () => { @@ -518,7 +543,7 @@ describe("searchStringLiterals", () => { function startPoint() { return "hello" + globalVar + call("world", "again"); } - ` + `; const expectedCode = ` const globalVar = "{{found}}"; @@ -529,19 +554,21 @@ describe("searchStringLiterals", () => { function startPoint() { return "{{found}}" + globalVar + call("{{found}}", "{{found}}"); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["hello", "global", "world", "again"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -553,24 +580,26 @@ describe("searchStringLiterals", () => { function startPoint() { return document.getElementById("element"); } - ` + `; const expectedCode = ` function startPoint() { return document.getElementById("{{found}}"); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle document.{method} with variables correctly", () => { @@ -579,25 +608,27 @@ describe("searchStringLiterals", () => { const id = "element"; return document.getElementById(id); } - ` + `; const expectedCode = ` function startPoint() { const id = "{{found}}"; return document.getElementById(id); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -612,7 +643,7 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const expectedCode = ` function startPoint() { const obj = { @@ -620,19 +651,21 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["value"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle object expressions' operations correctly", () => { @@ -645,7 +678,7 @@ describe("searchStringLiterals", () => { obj["key2"] = "another2"; return obj.key; } - ` + `; const expectedCode = ` function startPoint() { const obj = { @@ -655,19 +688,21 @@ describe("searchStringLiterals", () => { obj["key2"] = "{{found}}"; return obj.key; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["another", "another2", "value"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle object expressions with variables correctly", () => { @@ -679,7 +714,7 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const expectedCode = ` function startPoint() { const value = "{{found}}"; @@ -688,19 +723,21 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["value"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle object expressions with function calls correctly", () => { @@ -715,7 +752,7 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const expectedCode = ` function call() { return "{{found}}"; @@ -727,19 +764,21 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["call"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle object expressions with function calls with arguments correctly", () => { @@ -754,7 +793,7 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const expectedCode = ` function call(arg) { return arg; @@ -766,19 +805,21 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["call"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle object expressions with function calls with boolean expressions correctly", () => { @@ -795,7 +836,7 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const expectedCode = ` function call(arg) { return arg; @@ -809,19 +850,21 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["value", "another"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle object expressions with a variable key correctly", () => { @@ -838,7 +881,7 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const expectedCode = ` function call(arg) { return arg; @@ -852,19 +895,21 @@ describe("searchStringLiterals", () => { }; return obj.key; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["value", "another", "{{found}}"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -877,25 +922,27 @@ describe("searchStringLiterals", () => { const arr = ["element_1", "element_2"]; return arr[0]; } - ` + `; const expectedCode = ` function startPoint() { const arr = ["{{found}}", "{{found}}"]; return arr[0]; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle array concatenation correctly and no duplicates node should be scaned", () => { @@ -907,7 +954,7 @@ describe("searchStringLiterals", () => { const arr4 = [...arr, ...arr3]; return arr4; } - ` + `; const expectedCode = ` function startPoint() { const arr = ["{{found}}"]; @@ -916,19 +963,21 @@ describe("searchStringLiterals", () => { const arr4 = [...arr, ...arr3]; return arr4; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle array expressions with variables correctly", () => { @@ -939,7 +988,7 @@ describe("searchStringLiterals", () => { const arr = [element1, element2]; return arr[0]; } - ` + `; const expectedCode = ` function startPoint() { const element1 = "{{found}}"; @@ -947,19 +996,21 @@ describe("searchStringLiterals", () => { const arr = [element1, element2]; return arr[0]; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle array expressions with function calls correctly", () => { @@ -972,7 +1023,7 @@ describe("searchStringLiterals", () => { const arr = [call(), "element_2"]; return arr[0]; } - ` + `; const expectedCode = ` function call() { return "{{found}}"; @@ -982,19 +1033,21 @@ describe("searchStringLiterals", () => { const arr = [call(), "{{found}}"]; return arr[0]; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle array expressions with function calls with arguments correctly", () => { @@ -1007,7 +1060,7 @@ describe("searchStringLiterals", () => { const arr = [call("element_1"), "element_2"]; return arr[0]; } - ` + `; const expectedCode = ` function call(arg) { return arg; @@ -1017,19 +1070,21 @@ describe("searchStringLiterals", () => { const arr = [call("{{found}}"), "{{found}}"]; return arr[0]; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle array expressions with function calls with boolean expressions correctly", () => { @@ -1044,7 +1099,7 @@ describe("searchStringLiterals", () => { const arr = [call(bool ? key : "another"), "element_2"]; return arr[0]; } - ` + `; const expectedCode = ` function call(arg) { return arg; @@ -1056,19 +1111,21 @@ describe("searchStringLiterals", () => { const arr = [call(bool ? key : "{{found}}"), "{{found}}"]; return arr[0]; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["value", "another", "element_2"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -1092,7 +1149,7 @@ describe("searchStringLiterals", () => { return "default"; } } - ` + `; const expectedCode = ` function startPoint() { const key = "value"; @@ -1109,19 +1166,21 @@ describe("searchStringLiterals", () => { return "{{found}}"; } } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["another", "default"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -1140,7 +1199,7 @@ describe("searchStringLiterals", () => { } return result; } - ` + `; const expectedCode = ` function startPoint() { const arr = ["{{found}}", "{{found}}"]; @@ -1152,19 +1211,21 @@ describe("searchStringLiterals", () => { } return result; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2", "result"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle foreach statements correctly", () => { @@ -1178,7 +1239,7 @@ describe("searchStringLiterals", () => { }); return result; } - ` + `; const expectedCode = ` function startPoint() { const arr = ["{{found}}", "{{found}}"]; @@ -1189,19 +1250,21 @@ describe("searchStringLiterals", () => { }); return result; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2", "result"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle map statements correctly", () => { @@ -1214,7 +1277,7 @@ describe("searchStringLiterals", () => { }); return result; } - ` + `; const expectedCode = ` function startPoint() { const arr = ["{{found}}", "{{found}}"]; @@ -1224,19 +1287,21 @@ describe("searchStringLiterals", () => { }); return result; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); it("should handle while statements correctly", () => { @@ -1253,7 +1318,7 @@ describe("searchStringLiterals", () => { } return result; } - ` + `; const expectedCode = ` function startPoint() { const arr = ["{{found}}", "{{found}}"]; @@ -1267,19 +1332,21 @@ describe("searchStringLiterals", () => { } return result; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); const expected = ["element_1", "element_2", "result"]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -1301,7 +1368,7 @@ describe("searchStringLiterals", () => { } return result; } - ` + `; const expectedCode = ` function startPoint() { const arr = ["{{found}}", "{{found}}"]; @@ -1316,19 +1383,27 @@ describe("searchStringLiterals", () => { } return result; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); - const expected = ["element_1", "element_2", "element_3", "element_4", "result"]; + const expected = [ + "element_1", + "element_2", + "element_3", + "element_4", + "result", + ]; expect(result).toEqual(expected); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -1340,22 +1415,24 @@ describe("searchStringLiterals", () => { function startPoint() { "className_A".replace("className_A", "className_B"); } - ` + `; const expectedCode = ` function startPoint() { "{{found}}".replace("{{found}}", "{{found}}"); } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" + return "{{found}}"; }); expect(result).toEqual(["className_A", "className_A", "className_B"]); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); //? ******************************* @@ -1368,25 +1445,30 @@ describe("searchStringLiterals", () => { const value = "value"; return \`hello \${value}\`; } - ` + `; const expectedCode = ` function startPoint() { const value = "{{found}}"; return \`{{found}} \${value}\`; } - ` + `; const ast = parser.parse(code); - let result: string[] = []; + const result: string[] = []; searchStringLiterals(findStartPointNode(ast)!, (str) => { result.push(str); - return "{{found}}" - }) + return "{{found}}"; + }); - expect(result).toEqual(["hello "/* Raw */, "hello " /* Cooked */, "value"]); - expect(stripCode(generator(ast, {}, code).code)).toEqual(stripCode(expectedCode)); + expect(result).toEqual([ + "hello " /* Raw */, + "hello " /* Cooked */, + "value", + ]); + expect(stripCode(generator(ast, {}, code).code)).toEqual( + stripCode(expectedCode), + ); }); - }); //! ================================ @@ -1394,14 +1476,13 @@ describe("searchStringLiterals", () => { //! ================================ describe("obfuscateJsWithAst", () => { - //? ******************************* //? Real World Example //? ******************************* it("should handle basic real world example 1", () => { - const code = `(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6773:function(e,t,n){Promise.resolve().then(n.bind(n,1845)),Promise.resolve().then(n.bind(n,7388)),Promise.resolve().then(n.bind(n,6016)),Promise.resolve().then(n.bind(n,1120)),Promise.resolve().then(n.bind(n,1255)),Promise.resolve().then(n.t.bind(n,5935,23)),Promise.resolve().then(n.t.bind(n,3710,23)),Promise.resolve().then(n.t.bind(n,3385,23)),Promise.resolve().then(n.bind(n,6212)),Promise.resolve().then(n.bind(n,1267)),Promise.resolve().then(n.bind(n,5322)),Promise.resolve().then(n.bind(n,9149))},6212:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return d}});var r=n(3827),i=n(703),l=n(8792),a={src:"/_next/static/media/some.svg",height:42,width:42,blurWidth:0,blurHeight:0},s=n(4090),o=n(7907);function d(){(0,o.usePathname)();let[e,t]=(0,s.useState)(!1),n=(0,s.useCallback)((e,t)=>{if(e.id===t)return!0;for(let r=0;r{t(n(document.body,"NotFoundPage"))},[n]),e?null:(0,r.jsx)(r.Fragment,{children:(0,r.jsx)("header",{className:"h-[4.4dvw] size-full bg-transparent px-[1.41dvw] flex items-center",children:(0,r.jsx)(l.default,{href:"/",className:"flex items-center flex-shrink-0",children:(0,r.jsx)(i.default,{className:"w-auto h-[1.88dvw]",src:a,alt:"Logo"})})})})}},1267:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return o}});var r=n(3827),i=n(8792),l=n(7907),a=n(4090),s=n(6314);function o(){let e=(0,l.usePathname)(),[t,n]=(0,a.useState)(!1),o=(0,a.useCallback)((e,t)=>{if(e.id===t)return!0;for(let n=0;n{n(o(document.body,"NotFoundPage"))},[o]);let d=[{href:"/",label:"Home"},{href:"/tag1",label:"tag1"},{href:"/tag2",label:"tag2"},{href:"/tag3",label:"tag3"},{href:"/tag4",label:"tag4"},],[u,c]=(0,a.useState)(()=>{let t=d.find(t=>t.href===e);return t?t.label:"label"}),[h,f]=(0,a.useState)(()=>{if(e.startsWith("/tag1"))return"tag1";{let t=d.find(t=>t.href===e);return t?t.label:"label"}});return(0,a.useEffect)(()=>{e.startsWith("/tag1")&&f("tag1")},[e]),(0,a.useEffect)(()=>{e.startsWith("/tag1/")&&(f("tag1"),c("tag1"))},[e]),t?null:(0,r.jsx)(r.Fragment,{children:(0,r.jsx)("div",{className:"z-0 w-[11dvw] h-dvh [&_.side-box]:absolute [&_.side-box]:left-[0.94dvw] [&_.side-box]:top-0 [&_.side-box]:-z-10 [&_.side-box]:h-full [&_.side-box]:w-[calc(100%-0.94dvw)] [&_.side-box]:rounded-tl-[0.94dvw] [&_.side-box]:rounded-bl-[0.94dvw] [&_.side-box]:bg-gradient-to-r [&_.side-box]:from-[#2858ff] [&_.side-box]:to-85%",children:(0,r.jsx)("div",{className:" flex flex-col items-start size-full *:relative *:w-full *:font-bold [&_a]:flex [&_a]:items-center [&_a]:w-full [&_a]:pe-[2.82dvw] [&_a]:h-[2.82dvw] [&_a]:transition-[padding_color] [&_a]:ease-bounce [&_a]:duration-300 [&_#side-box-line]:absolute [&_#side-box-line]:left-0 [&_#side-box-line]:top-0 [&_#side-box-line]:-z-10 [&_#side-box-line]:h-full [&_#side-box-line]:w-[0.235dvw] [&_#side-box-line]:transition-opacity [&_#side-box-line]:duration-0 [&_#side-box-line]:rounded-tr-full [&_#side-box-line]:rounded-br-full [&_#side-box-line]:bg-[#2858ff] ",children:d.map(t=>(0,r.jsx)(s.E.div,{onHoverStart:()=>c(t.label),onHoverEnd:()=>c(h),onClick:()=>f(t.label),children:(0,r.jsxs)(i.default,{href:t.href,className:t.href===e||e.startsWith("/tag1")&&"/tag1"===t.href?"text-white ps-[2.115dvw]":"text-white/50 ps-[1.41dvw]",children:[t.href===e||e.startsWith("/tag1/")&&"/tag1"===t.href?(0,r.jsx)(s.E.div,{transition:{type:"spring",duration:.65,mass:.5},layoutId:"sideBox",className:"side-box"}):null,t.label,t.label===u||e.startsWith("/tag1/")&&"/tag1/"===t.href?(0,r.jsx)(s.E.div,{transition:{type:"spring",duration:.8},layoutId:"sideBoxLine",id:"side-box-line"}):null,]})},t.href))})})})}},9149:function(e,t,n){"use strict";n.r(t);var r=n(4404),i=n(4090),l=n(7717);let a=e=>{let{color:t,height:n,crawl:r,crawlSpeed:a,initialPosition:s,easing:o,speed:d,shadow:u,template:c,zIndex:h=99999999,delay:f}=e,$=null!=t?t:"#29d";return(u||void 0===u)&&(u||"box-shadow:0 0 10px ".concat($,",0 0 5px ").concat($)),i.useEffect(()=>{let e;function t(){clearTimeout(e),e=setTimeout(l.start,null!=f?f:200)}function n(){clearTimeout(e),l.done()}l.configure({trickle:null==r||r,trickleSpeed:null!=a?a:200,minimum:null!=s?s:.55+.2*Math.random(),easing:null!=o?o:"ease-out",speed:null!=d?d:180,template:null!=c?c:'
'});var i=document.querySelectorAll("html");function u(e){try{let r=e.target,l=function(e){for(;e&&"a"!==e.tagName.toLowerCase();)e=e.parentElement;return e}(r),a=null==l?void 0:l.href;if(a){var s;let o=window.location.href,d="_blank"===l.target,u=a.startsWith("blob:"),c=function(e,t){let n=new URL(e),r=new URL(t);if(n.hostname===r.hostname&&n.pathname===r.pathname&&n.search===r.search){let i=n.hash,l=r.hash;return i!==l&&n.href.replace(i,"")===r.href.replace(l,"")}return!1}(o,a),h;a===o||c||d||u||e.ctrlKey?(t(),n(),[].forEach.call(i,function(e){e.classList.remove("nprogress-busy")})):(t(),h=(s=window.history).pushState,s.pushState=function(){return n(),[].forEach.call(i,function(e){e.classList.remove("nprogress-busy")}),h.apply(s,arguments)})}}catch(f){t(),n()}}return document.addEventListener("click",u),()=>{document.removeEventListener("click",u)}},[r,a,f,o,s,d,c]),null};t.default=a,a.propTypes={color:r.string,height:r.number,crawl:r.bool,crawlSpeed:r.number,initialPosition:r.number,easing:r.string,speed:r.number,delay:r.number,template:r.string,shadow:r.oneOfType([r.string,r.bool]),zIndex:r.number}},5322:function(e,t,n){"use strict";n.r(t);var r=n(3827),i=n(4090);t.default=()=>{let e=(0,i.useRef)(null);return(0,i.useEffect)(()=>{let t=e.current,n=null==t?void 0:t.getContext("2d"),r={x:.5*window.innerWidth,y:.5*window.innerHeight},i={pointsNumber:8,widthFactor:4,spring:.35,friction:.48},l=Array(i.pointsNumber);for(let a=0;a{r.x=e,r.y=t},o=()=>{e.current&&(e.current.width=window.innerWidth,e.current.height=window.innerHeight)},d=e=>{if(n&&(n.strokeStyle="#e2ecfc"),t&&(null==n||n.clearRect(0,0,t.width,t.height)),l.forEach((e,t)=>{let n=0===t?r:l[t-1],a=0===t?.4*i.spring:i.spring;e.dx+=(n.x-e.x)*a,e.dy+=(n.y-e.y)*a,e.dx*=i.friction,e.dy*=i.friction,e.x+=e.dx,e.y+=e.dy}),n){n.lineCap="round",n.beginPath(),n.moveTo(l[0].x,l[0].y);for(let a=1;a{o()},c=e=>{s(e.pageX,e.pageY)},h=e=>{s(e.pageX,e.pageY)},f=e=>{s(e.targetTouches[0].pageX,e.targetTouches[0].pageY)};return window.addEventListener("click",c),window.addEventListener("mousemove",h),window.addEventListener("touchmove",f),window.addEventListener("resize",u),o(),d(0),()=>{window.removeEventListener("click",c),window.removeEventListener("mousemove",h),window.removeEventListener("touchmove",f),window.removeEventListener("resize",u)}},[]),(0,r.jsx)("canvas",{ref:e})}},3385:function(){}},function(e){e.O(0,[314,250,134,336,971,69,744],function(){return e(e.s=6773)}),_N_E=e.O()},]);` - const expectedCode = `(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6773:function(e,t,n){Promise.resolve().then(n.bind(n,1845)),Promise.resolve().then(n.bind(n,7388)),Promise.resolve().then(n.bind(n,6016)),Promise.resolve().then(n.bind(n,1120)),Promise.resolve().then(n.bind(n,1255)),Promise.resolve().then(n.t.bind(n,5935,23)),Promise.resolve().then(n.t.bind(n,3710,23)),Promise.resolve().then(n.t.bind(n,3385,23)),Promise.resolve().then(n.bind(n,6212)),Promise.resolve().then(n.bind(n,1267)),Promise.resolve().then(n.bind(n,5322)),Promise.resolve().then(n.bind(n,9149))},6212:function(e,t,n){\"usestrict\";n.r(t),n.d(t,{default:function(){returnd}});varr=n(3827),i=n(703),l=n(8792),a={src:\"/_next/static/media/some.svg\",height:42,width:42,blurWidth:0,blurHeight:0},s=n(4090),o=n(7907);functiond(){(0,o.usePathname)();let[e,t]=(0,s.useState)(!1),n=(0,s.useCallback)((e,t)=>{if(e.id===t)return!0;for(letr=0;r{t(n(document.body,\"NotFoundPage\"))},[n]),e?null:(0,r.jsx)(r.Fragment,{children:(0,r.jsx)(\"header\",{className:\"{{obfuscated}}\",children:(0,r.jsx)(l.default,{href:\"/\",className:\"{{obfuscated}}\",children:(0,r.jsx)(i.default,{className:\"{{obfuscated}}\",src:a,alt:\"Logo\"})})})})}},1267:function(e,t,n){\"usestrict\";n.r(t),n.d(t,{default:function(){returno}});varr=n(3827),i=n(8792),l=n(7907),a=n(4090),s=n(6314);functiono(){lete=(0,l.usePathname)(),[t,n]=(0,a.useState)(!1),o=(0,a.useCallback)((e,t)=>{if(e.id===t)return!0;for(letn=0;n{n(o(document.body,\"NotFoundPage\"))},[o]);letd=[{href:\"/\",label:\"Home\"},{href:\"/tag1\",label:\"tag1\"},{href:\"/tag2\",label:\"tag2\"},{href:\"/tag3\",label:\"tag3\"},{href:\"/tag4\",label:\"tag4\"}],[u,c]=(0,a.useState)(()=>{lett=d.find(t=>t.href===e);returnt?t.label:\"label\"}),[h,f]=(0,a.useState)(()=>{if(e.startsWith(\"/tag1\"))return\"tag1\";{lett=d.find(t=>t.href===e);returnt?t.label:\"label\"}});return(0,a.useEffect)(()=>{e.startsWith(\"/tag1\")&&f(\"tag1\")},[e]),(0,a.useEffect)(()=>{e.startsWith(\"/tag1/\")&&(f(\"tag1\"),c(\"tag1\"))},[e]),t?null:(0,r.jsx)(r.Fragment,{children:(0,r.jsx)(\"div\",{className:\"{{obfuscated}}\",children:(0,r.jsx)(\"div\",{className:\"{{obfuscated}}\",children:d.map(t=>(0,r.jsx)(s.E.div,{onHoverStart:()=>c(t.label),onHoverEnd:()=>c(h),onClick:()=>f(t.label),children:(0,r.jsxs)(i.default,{href:t.href,className:t.href===e||e.startsWith(\"/tag1\")&&\"/tag1\"===t.href?\"{{obfuscated}}\":\"{{obfuscated}}\",children:[t.href===e||e.startsWith(\"/tag1/\")&&\"/tag1\"===t.href?(0,r.jsx)(s.E.div,{transition:{type:\"spring\",duration:.65,mass:.5},layoutId:\"sideBox\",className:\"{{obfuscated}}\"}):null,t.label,t.label===u||e.startsWith(\"/tag1/\")&&\"/tag1/\"===t.href?(0,r.jsx)(s.E.div,{transition:{type:\"spring\",duration:.8},layoutId:\"sideBoxLine\",id:\"side-box-line\"}):null]})},t.href))})})})}},9149:function(e,t,n){\"usestrict\";n.r(t);varr=n(4404),i=n(4090),l=n(7717);leta=e=>{let{color:t,height:n,crawl:r,crawlSpeed:a,initialPosition:s,easing:o,speed:d,shadow:u,template:c,zIndex:h=99999999,delay:f}=e,$=null!=t?t:\"#29d\";return(u||void0===u)&&(u||\"box-shadow:0010px\".concat($,\",005px\").concat($)),i.useEffect(()=>{lete;functiont(){clearTimeout(e),e=setTimeout(l.start,null!=f?f:200)}functionn(){clearTimeout(e),l.done()}l.configure({trickle:null==r||r,trickleSpeed:null!=a?a:200,minimum:null!=s?s:.55+.2*Math.random(),easing:null!=o?o:\"ease-out\",speed:null!=d?d:180,template:null!=c?c:\"\"});vari=document.querySelectorAll(\"html\");functionu(e){try{letr=e.target,l=function(e){for(;e&&\"a\"!==e.tagName.toLowerCase();)e=e.parentElement;returne}(r),a=null==l?void0:l.href;if(a){vars;leto=window.location.href,d=\"_blank\"===l.target,u=a.startsWith(\"blob:\"),c=function(e,t){letn=newURL(e),r=newURL(t);if(n.hostname===r.hostname&&n.pathname===r.pathname&&n.search===r.search){leti=n.hash,l=r.hash;returni!==l&&n.href.replace(i,\"\")===r.href.replace(l,\"\")}return!1}(o,a),h;a===o||c||d||u||e.ctrlKey?(t(),n(),[].forEach.call(i,function(e){e.classList.remove(\"nprogress-busy\")})):(t(),h=(s=window.history).pushState,s.pushState=function(){returnn(),[].forEach.call(i,function(e){e.classList.remove(\"nprogress-busy\")}),h.apply(s,arguments)})}}catch(f){t(),n()}}returndocument.addEventListener(\"click\",u),()=>{document.removeEventListener(\"click\",u)}},[r,a,f,o,s,d,c]),null};t.default=a,a.propTypes={color:r.string,height:r.number,crawl:r.bool,crawlSpeed:r.number,initialPosition:r.number,easing:r.string,speed:r.number,delay:r.number,template:r.string,shadow:r.oneOfType([r.string,r.bool]),zIndex:r.number}},5322:function(e,t,n){\"usestrict\";n.r(t);varr=n(3827),i=n(4090);t.default=()=>{lete=(0,i.useRef)(null);return(0,i.useEffect)(()=>{lett=e.current,n=null==t?void0:t.getContext(\"2d\"),r={x:.5*window.innerWidth,y:.5*window.innerHeight},i={pointsNumber:8,widthFactor:4,spring:.35,friction:.48},l=Array(i.pointsNumber);for(leta=0;a{r.x=e,r.y=t},o=()=>{e.current&&(e.current.width=window.innerWidth,e.current.height=window.innerHeight)},d=e=>{if(n&&(n.strokeStyle=\"#e2ecfc\"),t&&(null==n||n.clearRect(0,0,t.width,t.height)),l.forEach((e,t)=>{letn=0===t?r:l[t-1],a=0===t?.4*i.spring:i.spring;e.dx+=(n.x-e.x)*a,e.dy+=(n.y-e.y)*a,e.dx*=i.friction,e.dy*=i.friction,e.x+=e.dx,e.y+=e.dy}),n){n.lineCap=\"round\",n.beginPath(),n.moveTo(l[0].x,l[0].y);for(leta=1;a{o()},c=e=>{s(e.pageX,e.pageY)},h=e=>{s(e.pageX,e.pageY)},f=e=>{s(e.targetTouches[0].pageX,e.targetTouches[0].pageY)};returnwindow.addEventListener(\"click\",c),window.addEventListener(\"mousemove\",h),window.addEventListener(\"touchmove\",f),window.addEventListener(\"resize\",u),o(),d(0),()=>{window.removeEventListener(\"click\",c),window.removeEventListener(\"mousemove\",h),window.removeEventListener(\"touchmove\",f),window.removeEventListener(\"resize\",u)}},[]),(0,r.jsx)(\"canvas\",{ref:e})}},3385:function(){}},function(e){e.O(0,[314,250,134,336,971,69,744],function(){returne(e.s=6773)}),_N_E=e.O()}]);` + const code = `(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6773:function(e,t,n){Promise.resolve().then(n.bind(n,1845)),Promise.resolve().then(n.bind(n,7388)),Promise.resolve().then(n.bind(n,6016)),Promise.resolve().then(n.bind(n,1120)),Promise.resolve().then(n.bind(n,1255)),Promise.resolve().then(n.t.bind(n,5935,23)),Promise.resolve().then(n.t.bind(n,3710,23)),Promise.resolve().then(n.t.bind(n,3385,23)),Promise.resolve().then(n.bind(n,6212)),Promise.resolve().then(n.bind(n,1267)),Promise.resolve().then(n.bind(n,5322)),Promise.resolve().then(n.bind(n,9149))},6212:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return d}});var r=n(3827),i=n(703),l=n(8792),a={src:"/_next/static/media/some.svg",height:42,width:42,blurWidth:0,blurHeight:0},s=n(4090),o=n(7907);function d(){(0,o.usePathname)();let[e,t]=(0,s.useState)(!1),n=(0,s.useCallback)((e,t)=>{if(e.id===t)return!0;for(let r=0;r{t(n(document.body,"NotFoundPage"))},[n]),e?null:(0,r.jsx)(r.Fragment,{children:(0,r.jsx)("header",{className:"h-[4.4dvw] size-full bg-transparent px-[1.41dvw] flex items-center",children:(0,r.jsx)(l.default,{href:"/",className:"flex items-center flex-shrink-0",children:(0,r.jsx)(i.default,{className:"w-auto h-[1.88dvw]",src:a,alt:"Logo"})})})})}},1267:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return o}});var r=n(3827),i=n(8792),l=n(7907),a=n(4090),s=n(6314);function o(){let e=(0,l.usePathname)(),[t,n]=(0,a.useState)(!1),o=(0,a.useCallback)((e,t)=>{if(e.id===t)return!0;for(let n=0;n{n(o(document.body,"NotFoundPage"))},[o]);let d=[{href:"/",label:"Home"},{href:"/tag1",label:"tag1"},{href:"/tag2",label:"tag2"},{href:"/tag3",label:"tag3"},{href:"/tag4",label:"tag4"},],[u,c]=(0,a.useState)(()=>{let t=d.find(t=>t.href===e);return t?t.label:"label"}),[h,f]=(0,a.useState)(()=>{if(e.startsWith("/tag1"))return"tag1";{let t=d.find(t=>t.href===e);return t?t.label:"label"}});return(0,a.useEffect)(()=>{e.startsWith("/tag1")&&f("tag1")},[e]),(0,a.useEffect)(()=>{e.startsWith("/tag1/")&&(f("tag1"),c("tag1"))},[e]),t?null:(0,r.jsx)(r.Fragment,{children:(0,r.jsx)("div",{className:"z-0 w-[11dvw] h-dvh [&_.side-box]:absolute [&_.side-box]:left-[0.94dvw] [&_.side-box]:top-0 [&_.side-box]:-z-10 [&_.side-box]:h-full [&_.side-box]:w-[calc(100%-0.94dvw)] [&_.side-box]:rounded-tl-[0.94dvw] [&_.side-box]:rounded-bl-[0.94dvw] [&_.side-box]:bg-gradient-to-r [&_.side-box]:from-[#2858ff] [&_.side-box]:to-85%",children:(0,r.jsx)("div",{className:" flex flex-col items-start size-full *:relative *:w-full *:font-bold [&_a]:flex [&_a]:items-center [&_a]:w-full [&_a]:pe-[2.82dvw] [&_a]:h-[2.82dvw] [&_a]:transition-[padding_color] [&_a]:ease-bounce [&_a]:duration-300 [&_#side-box-line]:absolute [&_#side-box-line]:left-0 [&_#side-box-line]:top-0 [&_#side-box-line]:-z-10 [&_#side-box-line]:h-full [&_#side-box-line]:w-[0.235dvw] [&_#side-box-line]:transition-opacity [&_#side-box-line]:duration-0 [&_#side-box-line]:rounded-tr-full [&_#side-box-line]:rounded-br-full [&_#side-box-line]:bg-[#2858ff] ",children:d.map(t=>(0,r.jsx)(s.E.div,{onHoverStart:()=>c(t.label),onHoverEnd:()=>c(h),onClick:()=>f(t.label),children:(0,r.jsxs)(i.default,{href:t.href,className:t.href===e||e.startsWith("/tag1")&&"/tag1"===t.href?"text-white ps-[2.115dvw]":"text-white/50 ps-[1.41dvw]",children:[t.href===e||e.startsWith("/tag1/")&&"/tag1"===t.href?(0,r.jsx)(s.E.div,{transition:{type:"spring",duration:.65,mass:.5},layoutId:"sideBox",className:"side-box"}):null,t.label,t.label===u||e.startsWith("/tag1/")&&"/tag1/"===t.href?(0,r.jsx)(s.E.div,{transition:{type:"spring",duration:.8},layoutId:"sideBoxLine",id:"side-box-line"}):null,]})},t.href))})})})}},9149:function(e,t,n){"use strict";n.r(t);var r=n(4404),i=n(4090),l=n(7717);let a=e=>{let{color:t,height:n,crawl:r,crawlSpeed:a,initialPosition:s,easing:o,speed:d,shadow:u,template:c,zIndex:h=99999999,delay:f}=e,$=null!=t?t:"#29d";return(u||void 0===u)&&(u||"box-shadow:0 0 10px ".concat($,",0 0 5px ").concat($)),i.useEffect(()=>{let e;function t(){clearTimeout(e),e=setTimeout(l.start,null!=f?f:200)}function n(){clearTimeout(e),l.done()}l.configure({trickle:null==r||r,trickleSpeed:null!=a?a:200,minimum:null!=s?s:.55+.2*Math.random(),easing:null!=o?o:"ease-out",speed:null!=d?d:180,template:null!=c?c:'
'});var i=document.querySelectorAll("html");function u(e){try{let r=e.target,l=function(e){for(;e&&"a"!==e.tagName.toLowerCase();)e=e.parentElement;return e}(r),a=null==l?void 0:l.href;if(a){var s;let o=window.location.href,d="_blank"===l.target,u=a.startsWith("blob:"),c=function(e,t){let n=new URL(e),r=new URL(t);if(n.hostname===r.hostname&&n.pathname===r.pathname&&n.search===r.search){let i=n.hash,l=r.hash;return i!==l&&n.href.replace(i,"")===r.href.replace(l,"")}return!1}(o,a),h;a===o||c||d||u||e.ctrlKey?(t(),n(),[].forEach.call(i,function(e){e.classList.remove("nprogress-busy")})):(t(),h=(s=window.history).pushState,s.pushState=function(){return n(),[].forEach.call(i,function(e){e.classList.remove("nprogress-busy")}),h.apply(s,arguments)})}}catch(f){t(),n()}}return document.addEventListener("click",u),()=>{document.removeEventListener("click",u)}},[r,a,f,o,s,d,c]),null};t.default=a,a.propTypes={color:r.string,height:r.number,crawl:r.bool,crawlSpeed:r.number,initialPosition:r.number,easing:r.string,speed:r.number,delay:r.number,template:r.string,shadow:r.oneOfType([r.string,r.bool]),zIndex:r.number}},5322:function(e,t,n){"use strict";n.r(t);var r=n(3827),i=n(4090);t.default=()=>{let e=(0,i.useRef)(null);return(0,i.useEffect)(()=>{let t=e.current,n=null==t?void 0:t.getContext("2d"),r={x:.5*window.innerWidth,y:.5*window.innerHeight},i={pointsNumber:8,widthFactor:4,spring:.35,friction:.48},l=Array(i.pointsNumber);for(let a=0;a{r.x=e,r.y=t},o=()=>{e.current&&(e.current.width=window.innerWidth,e.current.height=window.innerHeight)},d=e=>{if(n&&(n.strokeStyle="#e2ecfc"),t&&(null==n||n.clearRect(0,0,t.width,t.height)),l.forEach((e,t)=>{let n=0===t?r:l[t-1],a=0===t?.4*i.spring:i.spring;e.dx+=(n.x-e.x)*a,e.dy+=(n.y-e.y)*a,e.dx*=i.friction,e.dy*=i.friction,e.x+=e.dx,e.y+=e.dy}),n){n.lineCap="round",n.beginPath(),n.moveTo(l[0].x,l[0].y);for(let a=1;a{o()},c=e=>{s(e.pageX,e.pageY)},h=e=>{s(e.pageX,e.pageY)},f=e=>{s(e.targetTouches[0].pageX,e.targetTouches[0].pageY)};return window.addEventListener("click",c),window.addEventListener("mousemove",h),window.addEventListener("touchmove",f),window.addEventListener("resize",u),o(),d(0),()=>{window.removeEventListener("click",c),window.removeEventListener("mousemove",h),window.removeEventListener("touchmove",f),window.removeEventListener("resize",u)}},[]),(0,r.jsx)("canvas",{ref:e})}},3385:function(){}},function(e){e.O(0,[314,250,134,336,971,69,744],function(){return e(e.s=6773)}),_N_E=e.O()},]);`; + const expectedCode = `(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6773:function(e,t,n){Promise.resolve().then(n.bind(n,1845)),Promise.resolve().then(n.bind(n,7388)),Promise.resolve().then(n.bind(n,6016)),Promise.resolve().then(n.bind(n,1120)),Promise.resolve().then(n.bind(n,1255)),Promise.resolve().then(n.t.bind(n,5935,23)),Promise.resolve().then(n.t.bind(n,3710,23)),Promise.resolve().then(n.t.bind(n,3385,23)),Promise.resolve().then(n.bind(n,6212)),Promise.resolve().then(n.bind(n,1267)),Promise.resolve().then(n.bind(n,5322)),Promise.resolve().then(n.bind(n,9149))},6212:function(e,t,n){\"usestrict\";n.r(t),n.d(t,{default:function(){returnd}});varr=n(3827),i=n(703),l=n(8792),a={src:\"/_next/static/media/some.svg\",height:42,width:42,blurWidth:0,blurHeight:0},s=n(4090),o=n(7907);functiond(){(0,o.usePathname)();let[e,t]=(0,s.useState)(!1),n=(0,s.useCallback)((e,t)=>{if(e.id===t)return!0;for(letr=0;r{t(n(document.body,\"NotFoundPage\"))},[n]),e?null:(0,r.jsx)(r.Fragment,{children:(0,r.jsx)(\"header\",{className:\"{{obfuscated}}\",children:(0,r.jsx)(l.default,{href:\"/\",className:\"{{obfuscated}}\",children:(0,r.jsx)(i.default,{className:\"{{obfuscated}}\",src:a,alt:\"Logo\"})})})})}},1267:function(e,t,n){\"usestrict\";n.r(t),n.d(t,{default:function(){returno}});varr=n(3827),i=n(8792),l=n(7907),a=n(4090),s=n(6314);functiono(){lete=(0,l.usePathname)(),[t,n]=(0,a.useState)(!1),o=(0,a.useCallback)((e,t)=>{if(e.id===t)return!0;for(letn=0;n{n(o(document.body,\"NotFoundPage\"))},[o]);letd=[{href:\"/\",label:\"Home\"},{href:\"/tag1\",label:\"tag1\"},{href:\"/tag2\",label:\"tag2\"},{href:\"/tag3\",label:\"tag3\"},{href:\"/tag4\",label:\"tag4\"}],[u,c]=(0,a.useState)(()=>{lett=d.find(t=>t.href===e);returnt?t.label:\"label\"}),[h,f]=(0,a.useState)(()=>{if(e.startsWith(\"/tag1\"))return\"tag1\";{lett=d.find(t=>t.href===e);returnt?t.label:\"label\"}});return(0,a.useEffect)(()=>{e.startsWith(\"/tag1\")&&f(\"tag1\")},[e]),(0,a.useEffect)(()=>{e.startsWith(\"/tag1/\")&&(f(\"tag1\"),c(\"tag1\"))},[e]),t?null:(0,r.jsx)(r.Fragment,{children:(0,r.jsx)(\"div\",{className:\"{{obfuscated}}\",children:(0,r.jsx)(\"div\",{className:\"{{obfuscated}}\",children:d.map(t=>(0,r.jsx)(s.E.div,{onHoverStart:()=>c(t.label),onHoverEnd:()=>c(h),onClick:()=>f(t.label),children:(0,r.jsxs)(i.default,{href:t.href,className:t.href===e||e.startsWith(\"/tag1\")&&\"/tag1\"===t.href?\"{{obfuscated}}\":\"{{obfuscated}}\",children:[t.href===e||e.startsWith(\"/tag1/\")&&\"/tag1\"===t.href?(0,r.jsx)(s.E.div,{transition:{type:\"spring\",duration:.65,mass:.5},layoutId:\"sideBox\",className:\"{{obfuscated}}\"}):null,t.label,t.label===u||e.startsWith(\"/tag1/\")&&\"/tag1/\"===t.href?(0,r.jsx)(s.E.div,{transition:{type:\"spring\",duration:.8},layoutId:\"sideBoxLine\",id:\"side-box-line\"}):null]})},t.href))})})})}},9149:function(e,t,n){\"usestrict\";n.r(t);varr=n(4404),i=n(4090),l=n(7717);leta=e=>{let{color:t,height:n,crawl:r,crawlSpeed:a,initialPosition:s,easing:o,speed:d,shadow:u,template:c,zIndex:h=99999999,delay:f}=e,$=null!=t?t:\"#29d\";return(u||void0===u)&&(u||\"box-shadow:0010px\".concat($,\",005px\").concat($)),i.useEffect(()=>{lete;functiont(){clearTimeout(e),e=setTimeout(l.start,null!=f?f:200)}functionn(){clearTimeout(e),l.done()}l.configure({trickle:null==r||r,trickleSpeed:null!=a?a:200,minimum:null!=s?s:.55+.2*Math.random(),easing:null!=o?o:\"ease-out\",speed:null!=d?d:180,template:null!=c?c:\"\"});vari=document.querySelectorAll(\"html\");functionu(e){try{letr=e.target,l=function(e){for(;e&&\"a\"!==e.tagName.toLowerCase();)e=e.parentElement;returne}(r),a=null==l?void0:l.href;if(a){vars;leto=window.location.href,d=\"_blank\"===l.target,u=a.startsWith(\"blob:\"),c=function(e,t){letn=newURL(e),r=newURL(t);if(n.hostname===r.hostname&&n.pathname===r.pathname&&n.search===r.search){leti=n.hash,l=r.hash;returni!==l&&n.href.replace(i,\"\")===r.href.replace(l,\"\")}return!1}(o,a),h;a===o||c||d||u||e.ctrlKey?(t(),n(),[].forEach.call(i,function(e){e.classList.remove(\"nprogress-busy\")})):(t(),h=(s=window.history).pushState,s.pushState=function(){returnn(),[].forEach.call(i,function(e){e.classList.remove(\"nprogress-busy\")}),h.apply(s,arguments)})}}catch(f){t(),n()}}returndocument.addEventListener(\"click\",u),()=>{document.removeEventListener(\"click\",u)}},[r,a,f,o,s,d,c]),null};t.default=a,a.propTypes={color:r.string,height:r.number,crawl:r.bool,crawlSpeed:r.number,initialPosition:r.number,easing:r.string,speed:r.number,delay:r.number,template:r.string,shadow:r.oneOfType([r.string,r.bool]),zIndex:r.number}},5322:function(e,t,n){\"usestrict\";n.r(t);varr=n(3827),i=n(4090);t.default=()=>{lete=(0,i.useRef)(null);return(0,i.useEffect)(()=>{lett=e.current,n=null==t?void0:t.getContext(\"2d\"),r={x:.5*window.innerWidth,y:.5*window.innerHeight},i={pointsNumber:8,widthFactor:4,spring:.35,friction:.48},l=Array(i.pointsNumber);for(leta=0;a{r.x=e,r.y=t},o=()=>{e.current&&(e.current.width=window.innerWidth,e.current.height=window.innerHeight)},d=e=>{if(n&&(n.strokeStyle=\"#e2ecfc\"),t&&(null==n||n.clearRect(0,0,t.width,t.height)),l.forEach((e,t)=>{letn=0===t?r:l[t-1],a=0===t?.4*i.spring:i.spring;e.dx+=(n.x-e.x)*a,e.dy+=(n.y-e.y)*a,e.dx*=i.friction,e.dy*=i.friction,e.x+=e.dx,e.y+=e.dy}),n){n.lineCap=\"round\",n.beginPath(),n.moveTo(l[0].x,l[0].y);for(leta=1;a{o()},c=e=>{s(e.pageX,e.pageY)},h=e=>{s(e.pageX,e.pageY)},f=e=>{s(e.targetTouches[0].pageX,e.targetTouches[0].pageY)};returnwindow.addEventListener(\"click\",c),window.addEventListener(\"mousemove\",h),window.addEventListener(\"touchmove\",f),window.addEventListener(\"resize\",u),o(),d(0),()=>{window.removeEventListener(\"click\",c),window.removeEventListener(\"mousemove\",h),window.removeEventListener(\"touchmove\",f),window.removeEventListener(\"resize\",u)}},[]),(0,r.jsx)(\"canvas\",{ref:e})}},3385:function(){}},function(e){e.O(0,[314,250,134,336,971,69,744],function(){returne(e.s=6773)}),_N_E=e.O()}]);`; const { obfuscatedCode } = obfuscateJsWithAst(code, undefined); expect(stripCode(obfuscatedCode)).toEqual(stripCode(expectedCode)); diff --git a/src/__tests__/js.test.ts b/src/__tests__/js.test.ts new file mode 100644 index 0000000..6789c63 --- /dev/null +++ b/src/__tests__/js.test.ts @@ -0,0 +1,128 @@ +import { describe, expect, test } from "vitest"; +import { searchForwardComponent } from "../handlers/js"; + +//! ================================ +//! searchForwardComponent +//! ================================ + +describe("searchForwardComponent", () => { + test("should return component name when jsx format is correct", () => { + // Arrange + const content = `const element = o.jsx(ComponentName, {data: dataValue, index: "date"});`; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual(["ComponentName"]); + }); + + test("should return multiple component names for multiple matches", () => { + // Arrange + const content = + "o.jsx(FirstComponent, props); o.jsx(SecondComponent, otherProps);"; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual(["FirstComponent", "SecondComponent"]); + }); + + test("should return an empty array when no component name is found", () => { + // Arrange + const content = `o.jsx("h1", {data: dataValue, index: "date"});`; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual([]); + }); + + test("should return an empty array when content is empty", () => { + // Arrange + const content = ""; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual([]); + }); + + test("should return an empty array when jsx is not used", () => { + // Arrange + const content = `const element = React.createElement("div", null, "Hello World");`; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual([]); + }); + + test("should handle special characters in component names", () => { + // Arrange + const content = "o.jsx($Comp_1, props); o.jsx(_Comp$2, otherProps);"; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual(["$Comp_1", "_Comp$2"]); + }); + + test("should not return component names when they are quoted", () => { + // Arrange + const content = `o.jsx("ComponentName", props); o.jsx('AnotherComponent', otherProps);`; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual([]); + }); + + test("should return component names when they are followed by a brace", () => { + // Arrange + const content = "o.jsx(ComponentName, {props: true});"; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual(["ComponentName"]); + }); + + test("should handle content with line breaks and multiple jsx calls", () => { + // Arrange + const content = ` + o.jsx(FirstComponent, {data: dataValue}); + o.jsx(SecondComponent, {index: "date"}); + o.jsx(ThirdComponent, {flag: true}); + `; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual([ + "FirstComponent", + "SecondComponent", + "ThirdComponent", + ]); + }); + + test("should handle content with nested jsx calls", () => { + // Arrange + const content = + "o.jsx(ParentComponent, {children: o.jsx(ChildComponent, {})})"; + + // Act + const result = searchForwardComponent(content); + + // Assert + expect(result).toEqual(["ParentComponent", "ChildComponent"]); + }); +}); diff --git a/src/__tests__/utils.test.ts b/src/__tests__/utils.test.ts new file mode 100644 index 0000000..02dfb93 --- /dev/null +++ b/src/__tests__/utils.test.ts @@ -0,0 +1,221 @@ +import { beforeEach, describe, expect, it, test } from "vitest"; +import { + duplicationCheck, + findContentBetweenMarker, + getFilenameFromPath, +} from "../utils"; + +//! ================================ +//! findContentBetweenMarker +//! ================================ + +describe("findContentBetweenMarker", () => { + it("should return the correct content between markers", () => { + const content = "123{{4}5{67}8}901{2345678}9"; + const targetStr = "5"; + const openSymbol = "{"; + const closeSymbol = "}"; + + const expectedOutput = ["{4}5{67}8", "2345678"]; + + const result = findContentBetweenMarker( + content, + targetStr, + openSymbol, + closeSymbol, + ); + expect(result).toEqual(expectedOutput); + }); + + // it('should return the correct content between (if marker length > 1)', () => { + // const content = '[Hello_0 [[Hello_1]]! Hello_2 [[Hello_3]]!]'; + // const targetStr = 'He'; + // const openSymbol = '[['; + // const closeSymbol = ']]'; + + // const expectedOutput = ['Hello_1', 'Hello_3']; + + // const result = findContentBetweenMarker(content, targetStr, openSymbol, closeSymbol); + // expect(result).toEqual(expectedOutput); + // }); +}); + +//! ================================ +//! getFilenameFromPath +//! ================================ + +describe("getFilenameFromPath", () => { + test("should extract filename from a Unix-like path", () => { + // Act + const result = getFilenameFromPath("/home/user/documents/report.pdf"); + + // Assert + expect(result).toBe("report.pdf"); + }); + + test("should extract filename from a Windows-like path", () => { + // Act + const result = getFilenameFromPath("C:\\Users\\hokin\\report.pdf"); + + // Assert + expect(result).toBe("report.pdf"); + }); + + test("should handle filenames without an extension", () => { + // Act + const result = getFilenameFromPath("/home/user/documents/notes"); + + // Assert + expect(result).toBe("notes"); + }); + + test("should handle paths with multiple periods", () => { + // Act + const result = getFilenameFromPath("/home/user/documents/report.v1.0.pdf"); + + // Assert + expect(result).toBe("report.v1.0.pdf"); + }); + + test("should handle paths with no directory", () => { + // Act + const result = getFilenameFromPath("report.pdf"); + + // Assert + expect(result).toBe("report.pdf"); + }); + + test("should handle empty strings", () => { + // Act + const result = getFilenameFromPath(""); + + // Assert + expect(result).toBe(""); + }); + + test("should handle paths with only directories and no filename", () => { + // Act + const result = getFilenameFromPath("/home/user/documents/"); + + // Assert + expect(result).toBe(""); + }); + + test("should handle paths with special characters in the filename", () => { + // Act + const result = getFilenameFromPath("/home/user/documents/~$!%20report.pdf"); + + // Assert + expect(result).toBe("~$!%20report.pdf"); + }); + + test("should handle paths with a dot at the start", () => { + // Act + const result = getFilenameFromPath("/home/user/documents/.env"); + + // Assert + expect(result).toBe(".env"); + }); + + test("should handle paths with a space in the filename", () => { + // Act + const result = getFilenameFromPath("/home/user/documents/my report.pdf"); + + // Assert + expect(result).toBe("my report.pdf"); + }); +}); + +//! ================================ +//! duplicationCheck +//! ================================ + +describe("duplicationCheck", () => { + test("should return false for an array with no duplicates", () => { + // Arrange + const input = ["apple", "banana", "cherry"]; + + // Act + const result = duplicationCheck(input); + + // Assert + expect(result).toBe(false); + }); + + test("should return true for an array with duplicates", () => { + // Arrange + const input = ["apple", "banana", "apple"]; + + // Act + const result = duplicationCheck(input); + + // Assert + expect(result).toBe(true); + }); + + test("should return false for an empty array", () => { + // Arrange + const input: string[] = []; + + // Act + const result = duplicationCheck(input); + + // Assert + expect(result).toBe(false); + }); + + test("should return false for an array with one element", () => { + // Arrange + const input = ["apple"]; + + // Act + const result = duplicationCheck(input); + + // Assert + expect(result).toBe(false); + }); + + test("should return true for an array with all elements being the same", () => { + // Arrange + const input = ["apple", "apple", "apple"]; + + // Act + const result = duplicationCheck(input); + + // Assert + expect(result).toBe(true); + }); + + test("should handle case sensitivity properly", () => { + // Arrange + const input = ["apple", "Apple"]; + + // Act + const result = duplicationCheck(input); + + // Assert + expect(result).toBe(false); + }); + + test("should return true for an array with duplicates that are not adjacent", () => { + // Arrange + const input = ["apple", "banana", "cherry", "apple", "date"]; + + // Act + const result = duplicationCheck(input); + + // Assert + expect(result).toBe(true); + }); + + test("should return false for an array with similar but unique strings", () => { + // Arrange + const input = ["a", "ab", "abc", "abcd"]; + + // Act + const result = duplicationCheck(input); + + // Assert + expect(result).toBe(false); + }); +}); diff --git a/src/config.ts b/src/config.ts index 0f7f17e..c6e7208 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,54 +1,84 @@ -import type { Options, OptionalOptions } from "./types"; - -const defaultOptions: Options = { - enable: true, // Enable or disable the plugin. - mode: "random", // Obfuscate mode, "random", "simplify" or "simplify-seedable". - buildFolderPath: ".next", // Build folder of your project. - classConversionJsonFolderPath: "./css-obfuscator", // The folder path to store the before obfuscate and after obfuscated classes conversion table. - refreshClassConversionJson: false, // Refresh the class conversion JSON file. - - classLength: 5, // Length of the obfuscated class name. - classPrefix: "", // Prefix of the obfuscated class name. - classSuffix: "", // Suffix of the obfuscated class name. - classIgnore: [], // The class names to be ignored during obfuscation. - allowExtensions: [".jsx", ".tsx", ".js", ".ts", ".html", ".rsc"], // The file extensions to be processed. - contentIgnoreRegexes: [ - /\.jsxs\)\("\w+"/g, // avoid accidentally obfuscate the HTML tag - ], // The regexes to match the file content to be ignored during obfuscation. - - whiteListedFolderPaths: [], // Only obfuscate files in these folders - blackListedFolderPaths: ["./.next/cache"], // Don't obfuscate files in these folders - enableMarkers: false, // Enable or disable the obfuscate marker classes. - markers: ["next-css-obfuscation"], // Classes that indicate component(s) need to obfuscate. - removeMarkersAfterObfuscated: true, // Remove the obfuscation markers from HTML elements after obfuscation. - removeOriginalCss: false, // Delete original CSS from CSS files if it has a obfuscated version. - generatorSeed: "-1", // The seed for the random generator. "-1" means use random seed. - - /** - * Experimental feature - */ - enableJsAst: false, // Whether to obfuscate JS files using abstract syntax tree parser. (Experimental feature) - - logLevel: "info", // Log level +import type { OptionalOptions, Options } from "./types"; + +export const defaultOptions: Options = { + enable: true, // Enable or disable the plugin. + mode: "random", // Obfuscate mode, "random", "simplify" or "simplify-seedable". + buildFolderPath: ".next", // Build folder of your project. + classConversionJsonFolderPath: "./css-obfuscator", // The folder path to store the before obfuscate and after obfuscated classes conversion table. + refreshClassConversionJson: false, // Refresh the class conversion JSON file. + + /** + * @deprecated Not longer used from v3.0.0 and will be removed in the next major version. + */ + classLength: 5, // Length of the obfuscated class name. + + /** + * @deprecated Merged into `prefix` from v3.0.0 and will be removed in the next major version. + */ + classPrefix: "", // Prefix of the obfuscated class name. + + /** + * @deprecated Merged into `suffix` from v3.0.0 and will be removed in the next major version. + */ + classSuffix: "", // Suffix of the obfuscated class name. + + prefix: { + selectors: "", // Prefix of the obfuscated classname. + idents: "", // Prefix of the obfuscated ident name. + }, + suffix: { + selectors: "", // Suffix of the obfuscated classname. + idents: "", // Suffix of the obfuscated ident name. + }, + + /** + * @deprecated Merged into `ignorePatterns.selectors` from v3.0.0 and will be removed in the next major version. + */ + classIgnore: [], // The class names to be ignored during obfuscation. + ignorePatterns: { + // The patterns to be ignored during obfuscation. + selectors: [], // The selectors to be ignored during obfuscation. + idents: [], // The idents to be ignored during obfuscation. + }, + + allowExtensions: [".jsx", ".tsx", ".js", ".ts", ".html", ".rsc"], // The file extensions to be processed. + contentIgnoreRegexes: [ + /\.jsxs\)\("\w+"/g, // avoid accidentally obfuscate the HTML tag + ], // The regexes to match the file content to be ignored during obfuscation. + + whiteListedFolderPaths: [], // Only obfuscate files in these folders + blackListedFolderPaths: ["./.next/cache"], // Don't obfuscate files in these folders + enableMarkers: false, // Enable or disable the obfuscate marker classes. + markers: ["next-css-obfuscation"], // Classes that indicate component(s) need to obfuscate. + removeMarkersAfterObfuscated: true, // Remove the obfuscation markers from HTML elements after obfuscation. + removeOriginalCss: false, // Delete original CSS from CSS files if it has a obfuscated version. + generatorSeed: undefined, // The seed for the random generator. "undefined" means use random seed. + + /** + * Experimental feature + */ + enableJsAst: true, // Whether to obfuscate JS files using abstract syntax tree parser. (Experimental feature) + + logLevel: "info", // Log level }; -class Config { - private options: Options; - - constructor(options?: OptionalOptions) { - if (!options) { - this.options = defaultOptions; - return; - } - this.options = { - ...defaultOptions, - ...options, - }; - } +export class Config { + private options: Options; - public get(): Options { - return this.options; + constructor(options?: OptionalOptions) { + if (!options) { + this.options = defaultOptions; + return; } + this.options = { + ...defaultOptions, + ...options, + }; + } + + public get(): Options { + return this.options; + } } -export default Config; \ No newline at end of file +export default Config; diff --git a/src/handlers/css.test.ts b/src/handlers/css.test.ts deleted file mode 100644 index 0d908b0..0000000 --- a/src/handlers/css.test.ts +++ /dev/null @@ -1,529 +0,0 @@ -import { describe, it, expect, test } from "vitest"; - -// @ts-ignore -import css from "css"; - -import { - copyCssData, - renameCssSelector, - extractClassFromSelector, -} from "./css"; - -const testCss = ` -.s0-1 { - background: #181810; - color: #181811; -} - -@media (min-width: 640px) -{ - .s1-1 - { - background: #181812; - color: #181813; - } - - @media (min-width: 768px) - { - .s2-1, .s2-1-1 { - background: #181814; - color: #181815; - }, - .s2-1, .s2-1-1 { - background: #181814; - color: #181815; - }, - .s2-2, .s2-2-2 { - background: #181816; - color: #181817; - }, - .s2-3 { - background: #181818; - color: #181819; - } - } - - .s1-2 - { - background: #181820; - color: #181821; - } -} - -.s0-2 { - background: #181822; - color: #181823; -} -` - -// function getCssRulesIncludedSelector(selector: string, cssObj: any): any[] { -// function recursive(rules: any[]) { -// for (const item of rules) { -// if (item.rules) { -// const result: any = recursive(item.rules); -// if (result !== null) { -// return [{ ...item, rules: result }]; -// } -// } else if (item.selectors.includes(selector)) { -// // remove empty selectors -// item.selectors = item.selectors.filter((selector: any) => selector !== ""); - -// return [{ ...item, selectors: [selector] }]; -// } -// } -// return null; -// } -// return recursive(cssObj.stylesheet.rules) || []; -// } - -// describe("getCssRulesIncludedSelector", () => { -// it("should return the correct CSS rules (single selector, no nested rule)", () => { -// const cssObj = css.parse(testCss); - -// const selector = ".s0-1"; -// const expectedOutput = [{ "type": "rule", "selectors": [".s0-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181810", "position": { "start": { "line": 3, "column": 5 }, "end": { "line": 3, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181811", "position": { "start": { "line": 4, "column": 5 }, "end": { "line": 4, "column": 19 } } }], "position": { "start": { "line": 2, "column": 1 }, "end": { "line": 5, "column": 2 } } }]; - -// const result = getCssRulesIncludedSelector(selector, cssObj); -// expect(result).toEqual(expectedOutput); -// }); - -// it("should return the correct CSS rules (multiple nested rules)", () => { -// const cssObj = css.parse(testCss); - -// const selector = ".s2-3"; -// const expectedOutput = [{ "type": "media", "media": "(min-width: 640px)", "rules": [{ "type": "media", "media": "(min-width: 768px)", "rules": [{ "type": "rule", "selectors": [".s2-3"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181818", "position": { "start": { "line": 26, "column": 13 }, "end": { "line": 26, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181819", "position": { "start": { "line": 27, "column": 13 }, "end": { "line": 27, "column": 27 } } }], "position": { "start": { "line": 24, "column": 10 }, "end": { "line": 28, "column": 10 } } }], "position": { "start": { "line": 15, "column": 5 }, "end": { "line": 29, "column": 6 } } }], "position": { "start": { "line": 7, "column": 1 }, "end": { "line": 36, "column": 2 } } }]; - -// const result = getCssRulesIncludedSelector(selector, cssObj); -// expect(result).toEqual(expectedOutput); -// }); - -// it("should return the correct CSS rules (multiple selector in same rule)", () => { -// const cssObj = css.parse(testCss); - -// const selector = ".s2-2-2"; -// const expectedOutput = [{ "type": "media", "media": "(min-width: 640px)", "rules": [{ "type": "media", "media": "(min-width: 768px)", "rules": [{ "type": "rule", "selectors": [".s2-2-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181816", "position": { "start": { "line": 22, "column": 13 }, "end": { "line": 22, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181817", "position": { "start": { "line": 23, "column": 13 }, "end": { "line": 23, "column": 27 } } }], "position": { "start": { "line": 20, "column": 10 }, "end": { "line": 24, "column": 10 } } }], "position": { "start": { "line": 15, "column": 5 }, "end": { "line": 29, "column": 6 } } }], "position": { "start": { "line": 7, "column": 1 }, "end": { "line": 36, "column": 2 } } }]; - -// const result = getCssRulesIncludedSelector(selector, cssObj); -// expect(result).toEqual(expectedOutput); -// }); - -// it("should return the empty array", () => { -// const cssObj = css.parse(testCss); - -// const selector = ".s2-2-3"; -// const expectedOutput: [] = []; - -// const result = getCssRulesIncludedSelector(selector, cssObj); -// expect(result).toEqual(expectedOutput); -// }); -// }); - - -//! ================================ -//! renameCssSelector -//! ================================ - -describe("renameCssSelector", () => { - it("should rename the CSS selector (single selector, no nested rule)", () => { - const cssObj = css.parse(testCss); - - const oldSelector = ".s1-1"; - const newSelector = ".s1-1-new"; - const expectedOutput = [{ "type": "rule", "selectors": [".s0-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181810", "position": { "start": { "line": 3, "column": 5 }, "end": { "line": 3, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181811", "position": { "start": { "line": 4, "column": 5 }, "end": { "line": 4, "column": 19 } } }], "position": { "start": { "line": 2, "column": 1 }, "end": { "line": 5, "column": 2 } } }, { "type": "media", "media": "(min-width: 640px)", "rules": [{ "type": "rule", "selectors": [".s1-1-new"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181812", "position": { "start": { "line": 11, "column": 9 }, "end": { "line": 11, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181813", "position": { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": 23 } } }], "position": { "start": { "line": 9, "column": 5 }, "end": { "line": 13, "column": 6 } } }, { "type": "media", "media": "(min-width: 768px)", "rules": [{ "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 18, "column": 13 }, "end": { "line": 18, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 19, "column": 13 }, "end": { "line": 19, "column": 27 } } }], "position": { "start": { "line": 17, "column": 9 }, "end": { "line": 20, "column": 10 } } }, { "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 22, "column": 13 }, "end": { "line": 22, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 23, "column": 13 }, "end": { "line": 23, "column": 27 } } }], "position": { "start": { "line": 20, "column": 10 }, "end": { "line": 24, "column": 10 } } }, { "type": "rule", "selectors": [".s2-2", ".s2-2-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181816", "position": { "start": { "line": 26, "column": 13 }, "end": { "line": 26, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181817", "position": { "start": { "line": 27, "column": 13 }, "end": { "line": 27, "column": 27 } } }], "position": { "start": { "line": 24, "column": 10 }, "end": { "line": 28, "column": 10 } } }, { "type": "rule", "selectors": [".s2-3"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181818", "position": { "start": { "line": 30, "column": 13 }, "end": { "line": 30, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181819", "position": { "start": { "line": 31, "column": 13 }, "end": { "line": 31, "column": 27 } } }], "position": { "start": { "line": 28, "column": 10 }, "end": { "line": 32, "column": 10 } } }], "position": { "start": { "line": 15, "column": 5 }, "end": { "line": 33, "column": 6 } } }, { "type": "rule", "selectors": [".s1-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181820", "position": { "start": { "line": 37, "column": 9 }, "end": { "line": 37, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181821", "position": { "start": { "line": 38, "column": 9 }, "end": { "line": 38, "column": 23 } } }], "position": { "start": { "line": 35, "column": 5 }, "end": { "line": 39, "column": 6 } } }], "position": { "start": { "line": 7, "column": 1 }, "end": { "line": 40, "column": 2 } } }, { "type": "rule", "selectors": [".s0-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181822", "position": { "start": { "line": 43, "column": 5 }, "end": { "line": 43, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181823", "position": { "start": { "line": 44, "column": 5 }, "end": { "line": 44, "column": 19 } } }], "position": { "start": { "line": 42, "column": 1 }, "end": { "line": 45, "column": 2 } } }]; - - const result = renameCssSelector(oldSelector, newSelector, cssObj); - expect(result.stylesheet.rules).toEqual(expectedOutput); - }); - - it("should rename the CSS selector (multiple nested media queries)", () => { - const cssObj = css.parse(testCss); - - const oldSelector = ".s2-2"; - const newSelector = ".s2-2-new"; - const expectedOutput = [{ "type": "rule", "selectors": [".s0-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181810", "position": { "start": { "line": 3, "column": 5 }, "end": { "line": 3, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181811", "position": { "start": { "line": 4, "column": 5 }, "end": { "line": 4, "column": 19 } } }], "position": { "start": { "line": 2, "column": 1 }, "end": { "line": 5, "column": 2 } } }, { "type": "media", "media": "(min-width: 640px)", "rules": [{ "type": "rule", "selectors": [".s1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181812", "position": { "start": { "line": 11, "column": 9 }, "end": { "line": 11, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181813", "position": { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": 23 } } }], "position": { "start": { "line": 9, "column": 5 }, "end": { "line": 13, "column": 6 } } }, { "type": "media", "media": "(min-width: 768px)", "rules": [{ "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 18, "column": 13 }, "end": { "line": 18, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 19, "column": 13 }, "end": { "line": 19, "column": 27 } } }], "position": { "start": { "line": 17, "column": 9 }, "end": { "line": 20, "column": 10 } } }, { "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 22, "column": 13 }, "end": { "line": 22, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 23, "column": 13 }, "end": { "line": 23, "column": 27 } } }], "position": { "start": { "line": 20, "column": 10 }, "end": { "line": 24, "column": 10 } } }, { "type": "rule", "selectors": [".s2-2-new", ".s2-2-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181816", "position": { "start": { "line": 26, "column": 13 }, "end": { "line": 26, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181817", "position": { "start": { "line": 27, "column": 13 }, "end": { "line": 27, "column": 27 } } }], "position": { "start": { "line": 24, "column": 10 }, "end": { "line": 28, "column": 10 } } }, { "type": "rule", "selectors": [".s2-3"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181818", "position": { "start": { "line": 30, "column": 13 }, "end": { "line": 30, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181819", "position": { "start": { "line": 31, "column": 13 }, "end": { "line": 31, "column": 27 } } }], "position": { "start": { "line": 28, "column": 10 }, "end": { "line": 32, "column": 10 } } }], "position": { "start": { "line": 15, "column": 5 }, "end": { "line": 33, "column": 6 } } }, { "type": "rule", "selectors": [".s1-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181820", "position": { "start": { "line": 37, "column": 9 }, "end": { "line": 37, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181821", "position": { "start": { "line": 38, "column": 9 }, "end": { "line": 38, "column": 23 } } }], "position": { "start": { "line": 35, "column": 5 }, "end": { "line": 39, "column": 6 } } }], "position": { "start": { "line": 7, "column": 1 }, "end": { "line": 40, "column": 2 } } }, { "type": "rule", "selectors": [".s0-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181822", "position": { "start": { "line": 43, "column": 5 }, "end": { "line": 43, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181823", "position": { "start": { "line": 44, "column": 5 }, "end": { "line": 44, "column": 19 } } }], "position": { "start": { "line": 42, "column": 1 }, "end": { "line": 45, "column": 2 } } }]; - - const result = renameCssSelector(oldSelector, newSelector, cssObj); - expect(result.stylesheet.rules).toEqual(expectedOutput); - }); -}); - -//! ================================ -//! copyCssData -//! ================================ - -describe("copyCssData", () => { - it("should copy the CSS data (single selector, no nested rule)", () => { - const cssObj = css.parse(testCss); - - const targetSelector = ".s0-2"; - const newSelectorName = ".s0-2-new"; - const expectedOutput = [{ "type": "rule", "selectors": [".s0-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181810", "position": { "start": { "line": 3, "column": 5 }, "end": { "line": 3, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181811", "position": { "start": { "line": 4, "column": 5 }, "end": { "line": 4, "column": 19 } } }], "position": { "start": { "line": 2, "column": 1 }, "end": { "line": 5, "column": 2 } } }, { "type": "media", "media": "(min-width: 640px)", "rules": [{ "type": "rule", "selectors": [".s1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181812", "position": { "start": { "line": 11, "column": 9 }, "end": { "line": 11, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181813", "position": { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": 23 } } }], "position": { "start": { "line": 9, "column": 5 }, "end": { "line": 13, "column": 6 } } }, { "type": "media", "media": "(min-width: 768px)", "rules": [{ "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 18, "column": 13 }, "end": { "line": 18, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 19, "column": 13 }, "end": { "line": 19, "column": 27 } } }], "position": { "start": { "line": 17, "column": 9 }, "end": { "line": 20, "column": 10 } } }, { "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 22, "column": 13 }, "end": { "line": 22, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 23, "column": 13 }, "end": { "line": 23, "column": 27 } } }], "position": { "start": { "line": 20, "column": 10 }, "end": { "line": 24, "column": 10 } } }, { "type": "rule", "selectors": [".s2-2", ".s2-2-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181816", "position": { "start": { "line": 26, "column": 13 }, "end": { "line": 26, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181817", "position": { "start": { "line": 27, "column": 13 }, "end": { "line": 27, "column": 27 } } }], "position": { "start": { "line": 24, "column": 10 }, "end": { "line": 28, "column": 10 } } }, { "type": "rule", "selectors": [".s2-3"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181818", "position": { "start": { "line": 30, "column": 13 }, "end": { "line": 30, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181819", "position": { "start": { "line": 31, "column": 13 }, "end": { "line": 31, "column": 27 } } }], "position": { "start": { "line": 28, "column": 10 }, "end": { "line": 32, "column": 10 } } }], "position": { "start": { "line": 15, "column": 5 }, "end": { "line": 33, "column": 6 } } }, { "type": "rule", "selectors": [".s1-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181820", "position": { "start": { "line": 37, "column": 9 }, "end": { "line": 37, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181821", "position": { "start": { "line": 38, "column": 9 }, "end": { "line": 38, "column": 23 } } }], "position": { "start": { "line": 35, "column": 5 }, "end": { "line": 39, "column": 6 } } }], "position": { "start": { "line": 7, "column": 1 }, "end": { "line": 40, "column": 2 } } }, { "type": "rule", "selectors": [".s0-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181822", "position": { "start": { "line": 43, "column": 5 }, "end": { "line": 43, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181823", "position": { "start": { "line": 44, "column": 5 }, "end": { "line": 44, "column": 19 } } }], "position": { "start": { "line": 42, "column": 1 }, "end": { "line": 45, "column": 2 } } }, { "type": "rule", "selectors": [".s0-2-new"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181822", "position": { "start": { "line": 43, "column": 5 }, "end": { "line": 43, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181823", "position": { "start": { "line": 44, "column": 5 }, "end": { "line": 44, "column": 19 } } }], "position": { "start": { "line": 42, "column": 1 }, "end": { "line": 45, "column": 2 } } }]; - - const result = copyCssData(targetSelector, newSelectorName, cssObj); - expect(result.stylesheet.rules).toEqual(expectedOutput); - }); - - it("should copy the CSS data (multiple nested rules)", () => { - const cssObj = css.parse(testCss); - - const targetSelector = ".s2-3"; - const newSelectorName = ".s2-3-new"; - const expectedOutput = [{ "type": "rule", "selectors": [".s0-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181810", "position": { "start": { "line": 3, "column": 5 }, "end": { "line": 3, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181811", "position": { "start": { "line": 4, "column": 5 }, "end": { "line": 4, "column": 19 } } }], "position": { "start": { "line": 2, "column": 1 }, "end": { "line": 5, "column": 2 } } }, { "type": "media", "media": "(min-width: 640px)", "rules": [{ "type": "rule", "selectors": [".s1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181812", "position": { "start": { "line": 11, "column": 9 }, "end": { "line": 11, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181813", "position": { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": 23 } } }], "position": { "start": { "line": 9, "column": 5 }, "end": { "line": 13, "column": 6 } } }, { "type": "media", "media": "(min-width: 768px)", "rules": [{ "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 18, "column": 13 }, "end": { "line": 18, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 19, "column": 13 }, "end": { "line": 19, "column": 27 } } }], "position": { "start": { "line": 17, "column": 9 }, "end": { "line": 20, "column": 10 } } }, { "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 22, "column": 13 }, "end": { "line": 22, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 23, "column": 13 }, "end": { "line": 23, "column": 27 } } }], "position": { "start": { "line": 20, "column": 10 }, "end": { "line": 24, "column": 10 } } }, { "type": "rule", "selectors": [".s2-2", ".s2-2-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181816", "position": { "start": { "line": 26, "column": 13 }, "end": { "line": 26, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181817", "position": { "start": { "line": 27, "column": 13 }, "end": { "line": 27, "column": 27 } } }], "position": { "start": { "line": 24, "column": 10 }, "end": { "line": 28, "column": 10 } } }, { "type": "rule", "selectors": [".s2-3"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181818", "position": { "start": { "line": 30, "column": 13 }, "end": { "line": 30, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181819", "position": { "start": { "line": 31, "column": 13 }, "end": { "line": 31, "column": 27 } } }], "position": { "start": { "line": 28, "column": 10 }, "end": { "line": 32, "column": 10 } } }, { "type": "rule", "selectors": [".s2-3-new"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181818", "position": { "start": { "line": 30, "column": 13 }, "end": { "line": 30, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181819", "position": { "start": { "line": 31, "column": 13 }, "end": { "line": 31, "column": 27 } } }], "position": { "start": { "line": 28, "column": 10 }, "end": { "line": 32, "column": 10 } } }], "position": { "start": { "line": 15, "column": 5 }, "end": { "line": 33, "column": 6 } } }, { "type": "rule", "selectors": [".s1-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181820", "position": { "start": { "line": 37, "column": 9 }, "end": { "line": 37, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181821", "position": { "start": { "line": 38, "column": 9 }, "end": { "line": 38, "column": 23 } } }], "position": { "start": { "line": 35, "column": 5 }, "end": { "line": 39, "column": 6 } } }], "position": { "start": { "line": 7, "column": 1 }, "end": { "line": 40, "column": 2 } } }, { "type": "rule", "selectors": [".s0-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181822", "position": { "start": { "line": 43, "column": 5 }, "end": { "line": 43, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181823", "position": { "start": { "line": 44, "column": 5 }, "end": { "line": 44, "column": 19 } } }], "position": { "start": { "line": 42, "column": 1 }, "end": { "line": 45, "column": 2 } } }]; - - const result = copyCssData(targetSelector, newSelectorName, cssObj); - expect(result.stylesheet.rules).toEqual(expectedOutput); - }); - - it("should copy the CSS data (multiple selector in same rule)", () => { - const cssObj = css.parse(testCss); - - const targetSelector = ".s2-2-2"; - const newSelectorName = ".s2-2-2-new"; - const expectedOutput = [{ "type": "rule", "selectors": [".s0-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181810", "position": { "start": { "line": 3, "column": 5 }, "end": { "line": 3, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181811", "position": { "start": { "line": 4, "column": 5 }, "end": { "line": 4, "column": 19 } } }], "position": { "start": { "line": 2, "column": 1 }, "end": { "line": 5, "column": 2 } } }, { "type": "media", "media": "(min-width: 640px)", "rules": [{ "type": "rule", "selectors": [".s1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181812", "position": { "start": { "line": 11, "column": 9 }, "end": { "line": 11, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181813", "position": { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": 23 } } }], "position": { "start": { "line": 9, "column": 5 }, "end": { "line": 13, "column": 6 } } }, { "type": "media", "media": "(min-width: 768px)", "rules": [{ "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 18, "column": 13 }, "end": { "line": 18, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 19, "column": 13 }, "end": { "line": 19, "column": 27 } } }], "position": { "start": { "line": 17, "column": 9 }, "end": { "line": 20, "column": 10 } } }, { "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 22, "column": 13 }, "end": { "line": 22, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 23, "column": 13 }, "end": { "line": 23, "column": 27 } } }], "position": { "start": { "line": 20, "column": 10 }, "end": { "line": 24, "column": 10 } } }, { "type": "rule", "selectors": [".s2-2", ".s2-2-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181816", "position": { "start": { "line": 26, "column": 13 }, "end": { "line": 26, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181817", "position": { "start": { "line": 27, "column": 13 }, "end": { "line": 27, "column": 27 } } }], "position": { "start": { "line": 24, "column": 10 }, "end": { "line": 28, "column": 10 } } }, { "type": "rule", "selectors": [".s2-2-2-new"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181816", "position": { "start": { "line": 26, "column": 13 }, "end": { "line": 26, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181817", "position": { "start": { "line": 27, "column": 13 }, "end": { "line": 27, "column": 27 } } }], "position": { "start": { "line": 24, "column": 10 }, "end": { "line": 28, "column": 10 } } }, { "type": "rule", "selectors": [".s2-3"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181818", "position": { "start": { "line": 30, "column": 13 }, "end": { "line": 30, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181819", "position": { "start": { "line": 31, "column": 13 }, "end": { "line": 31, "column": 27 } } }], "position": { "start": { "line": 28, "column": 10 }, "end": { "line": 32, "column": 10 } } }], "position": { "start": { "line": 15, "column": 5 }, "end": { "line": 33, "column": 6 } } }, { "type": "rule", "selectors": [".s1-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181820", "position": { "start": { "line": 37, "column": 9 }, "end": { "line": 37, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181821", "position": { "start": { "line": 38, "column": 9 }, "end": { "line": 38, "column": 23 } } }], "position": { "start": { "line": 35, "column": 5 }, "end": { "line": 39, "column": 6 } } }], "position": { "start": { "line": 7, "column": 1 }, "end": { "line": 40, "column": 2 } } }, { "type": "rule", "selectors": [".s0-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181822", "position": { "start": { "line": 43, "column": 5 }, "end": { "line": 43, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181823", "position": { "start": { "line": 44, "column": 5 }, "end": { "line": 44, "column": 19 } } }], "position": { "start": { "line": 42, "column": 1 }, "end": { "line": 45, "column": 2 } } }]; - - const result = copyCssData(targetSelector, newSelectorName, cssObj); - expect(result.stylesheet.rules).toEqual(expectedOutput); - }); - - it("should copy the CSS data (same selector with different declarations)", () => { - const cssObj = css.parse(testCss); - - const targetSelector = ".s2-1"; - const newSelectorName = ".s2-1-new"; - const expectedOutput = [{ "type": "rule", "selectors": [".s0-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181810", "position": { "start": { "line": 3, "column": 5 }, "end": { "line": 3, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181811", "position": { "start": { "line": 4, "column": 5 }, "end": { "line": 4, "column": 19 } } }], "position": { "start": { "line": 2, "column": 1 }, "end": { "line": 5, "column": 2 } } }, { "type": "media", "media": "(min-width: 640px)", "rules": [{ "type": "rule", "selectors": [".s1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181812", "position": { "start": { "line": 11, "column": 9 }, "end": { "line": 11, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181813", "position": { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": 23 } } }], "position": { "start": { "line": 9, "column": 5 }, "end": { "line": 13, "column": 6 } } }, { "type": "media", "media": "(min-width: 768px)", "rules": [{ "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 18, "column": 13 }, "end": { "line": 18, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 19, "column": 13 }, "end": { "line": 19, "column": 27 } } }], "position": { "start": { "line": 17, "column": 9 }, "end": { "line": 20, "column": 10 } } }, { "type": "rule", "selectors": [".s2-1-new"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 18, "column": 13 }, "end": { "line": 18, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 19, "column": 13 }, "end": { "line": 19, "column": 27 } } }], "position": { "start": { "line": 17, "column": 9 }, "end": { "line": 20, "column": 10 } } }, { "type": "rule", "selectors": [".s2-1", ".s2-1-1"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 22, "column": 13 }, "end": { "line": 22, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 23, "column": 13 }, "end": { "line": 23, "column": 27 } } }], "position": { "start": { "line": 20, "column": 10 }, "end": { "line": 24, "column": 10 } } }, { "type": "rule", "selectors": [".s2-1-new"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181814", "position": { "start": { "line": 22, "column": 13 }, "end": { "line": 22, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181815", "position": { "start": { "line": 23, "column": 13 }, "end": { "line": 23, "column": 27 } } }], "position": { "start": { "line": 20, "column": 10 }, "end": { "line": 24, "column": 10 } } }, { "type": "rule", "selectors": [".s2-2", ".s2-2-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181816", "position": { "start": { "line": 26, "column": 13 }, "end": { "line": 26, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181817", "position": { "start": { "line": 27, "column": 13 }, "end": { "line": 27, "column": 27 } } }], "position": { "start": { "line": 24, "column": 10 }, "end": { "line": 28, "column": 10 } } }, { "type": "rule", "selectors": [".s2-3"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181818", "position": { "start": { "line": 30, "column": 13 }, "end": { "line": 30, "column": 32 } } }, { "type": "declaration", "property": "color", "value": "#181819", "position": { "start": { "line": 31, "column": 13 }, "end": { "line": 31, "column": 27 } } }], "position": { "start": { "line": 28, "column": 10 }, "end": { "line": 32, "column": 10 } } }], "position": { "start": { "line": 15, "column": 5 }, "end": { "line": 33, "column": 6 } } }, { "type": "rule", "selectors": [".s1-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181820", "position": { "start": { "line": 37, "column": 9 }, "end": { "line": 37, "column": 28 } } }, { "type": "declaration", "property": "color", "value": "#181821", "position": { "start": { "line": 38, "column": 9 }, "end": { "line": 38, "column": 23 } } }], "position": { "start": { "line": 35, "column": 5 }, "end": { "line": 39, "column": 6 } } }], "position": { "start": { "line": 7, "column": 1 }, "end": { "line": 40, "column": 2 } } }, { "type": "rule", "selectors": [".s0-2"], "declarations": [{ "type": "declaration", "property": "background", "value": "#181822", "position": { "start": { "line": 43, "column": 5 }, "end": { "line": 43, "column": 24 } } }, { "type": "declaration", "property": "color", "value": "#181823", "position": { "start": { "line": 44, "column": 5 }, "end": { "line": 44, "column": 19 } } }], "position": { "start": { "line": 42, "column": 1 }, "end": { "line": 45, "column": 2 } } }]; - - const result = copyCssData(targetSelector, newSelectorName, cssObj); - expect(result.stylesheet.rules).toEqual(expectedOutput); - }); -}); - -//! ================================ -//! extractClassFromSelector -//! ================================ - -describe("extractClassFromSelector", () => { - - it("should extract single class from simple selector", () => { - const sample = ".example htmlTag"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["example"] - }); - }); - - test("should extract multiple classes from complex selector", () => { - const sample = ":is(.some-class .some-class\\:bg-dark::-moz-placeholder)[data-active=\'true\']"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["some-class", "some-class\\:bg-dark"] - }); - }); - - test("should handle selector with no classes", () => { - const sample = "div"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: [] - }); - }); - - test("should handle selector with action pseudo-classes and not extract them", () => { - const sample = ".btn:hover .btn-active::after"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["btn", "btn-active"] - }); - }); - - test("should handle selector with vendor pseudo-classes and not extract them", () => { - const sample = ".btn-moz:-moz-focusring .btn-ms::-ms-placeholder .btn-webkit::-webkit-placeholder .btn-o::-o-placeholder"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["btn-moz", "btn-ms", "btn-webkit", "btn-o"] - }); - }); - - test("should handle selector with escaped characters", () => { - const sample = ".escaped\\:class:action"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["escaped\\:class"] - }); - }); - - test("should handle selector with multiple classes separated by spaces", () => { - const sample = ".class1 .class2 .class3"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1", "class2", "class3"] - }); - }); - - test("should handle selector with multiple classes separated by commas", () => { - const sample = ".class1, .class2, .class3"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1", "class2", "class3"] - }); - }); - - test("should handle selector with a combination of classes and ids", () => { - const sample = ".class1 #id .class2"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1", "class2"] - }); - }); - - test("should handle [attribute] selector", () => { - const sample = ".class1[data-attr=\"value\"] .class2[data-attr='value']"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1", "class2"] - }); - }); - - test("should handle action pseudo-class selector correctly", () => { - const sample = ".class1\\:hover\\:class2:after .class3\\:hover\\:class4:after:hover :is(.class5 .class6\\:hover\\:class7:hover:after) :is(.hover\\:class8\\:class9):after>:last-child"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1\\:hover\\:class2", "class3\\:hover\\:class4", "class5", "class6\\:hover\\:class7", "hover\\:class8\\:class9"] - }); - }); - - test("should ignore [attribute] selector that not in the same scope as class", () => { - const sample = ":is(.class1 .class2\\:class3\\:\\!class4)[aria-selected=\"true\"]"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1", "class2\\:class3\\:\\!class4"] - }); - }); - - test("should return null for invalid input types", () => { - // Act & Assert - // @ts-ignore - expect(() => extractClassFromSelector(null)).toThrow(TypeError); - // @ts-ignore - expect(() => extractClassFromSelector(undefined)).toThrow(TypeError); - expect(() => extractClassFromSelector(123 as any)).toThrow(TypeError); - }); - - - //? ********************* - //? Tailwind CSS - //? ********************* - test("should handle Tailwind CSS important selector '!'", () => { - const sample = ".\\!my-0 .some-class\\:\\!bg-white"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["\\!my-0", "some-class\\:\\!bg-white"] - }) - }); - - test("should handle Tailwind CSS selector with start with '-'", () => { - const sample = ".-class-1"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["-class-1"] - }) - }); - - test("should handle Tailwind CSS selector with '.' at the number", () => { - const sample = ".class-0\\.5 .class-1\\.125"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class-0\\.5", "class-1\\.125"] - }) - }); - - test("should handle Tailwind CSS selector with '/' at the number", () => { - const sample = ".class-1\\/2"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class-1\\/2"] - }) - }); - - test("should handle Tailwind CSS selector with '%' at the number", () => { - const sample = ".\\[\\.class1\\]\\:to-85\\%"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["\\[\\.class1\\]\\:to-85\\%"] - }) - }); - - test("should handle Tailwind CSS universal selector", () => { - const sample = ".\\*\\:class1 .class2\\*\\:class3 .class4\\*:.class5"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["\\*\\:class1", "class2\\*\\:class3", "class4\\*", "class5"] - }) - }); - - test("should handle Tailwind CSS [custom parameter] selector", () => { - const sample = ".class1\\[100\\] .class2-\\[200\\]"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1\\[100\\]", "class2-\\[200\\]"] - }) - }); - - test("should handle Tailwind CSS [custom parameter] selector with escaped characters", () => { - const sample = ".class1\\[1em\\] .class2-\\[2em\\] .class3\\[3\\%\\] .class4-\\[4\\%\\]"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1\\[1em\\]", "class2-\\[2em\\]", "class3\\[3\\%\\]", "class4-\\[4\\%\\]"] - }) - }); - - test("should handle complex Tailwind CSS [custom parameter] selector", () => { - const sample = ".w-\\[calc\\(10\\%\\+5px\\)\\]"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["w-\\[calc\\(10\\%\\+5px\\)\\]"] - }) - }); - - test("should ignore Tailwind CSS [custom parameter] selector that not in the same scope as class", () => { - const sample = ":is(.class1)[100]"; - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: ["class1"] - }) - }); - - test("should handle Tailwind CSS [custom selector] child elements selector", () => { - const sample = ` - .\\[\\&\\>\\class1\\]:after - .\\[\\&_class2\\]:hover - .\\[\\&_\\.class3\\]\\:class4 - .\\[\\&_\\#id1\\]::moz-placeholder - .\\[\\&_\\#id2\\]\\:class5.\\[\\&_\\#id\\]\\:class6 - `; - - // .\[\&_a\[class\]\]:hover <= will not work, (?:\\\[(?:[^\[\]\s]*|(?R))*\\\]))+) , javascript regex does not support recursive regex - - // Act - const result = extractClassFromSelector(sample); - - // Assert - expect(result).toEqual({ - selector: sample, - extractedClasses: [ - "\\[\\&\\>\\class1\\]", "\\[\\&_class2\\]", - "\\[\\&_\\.class3\\]\\:class4", "\\[\\&_\\#id1\\]", - "\\[\\&_\\#id2\\]\\:class5", "\\[\\&_\\#id\\]\\:class6" - ] - }) - }); -}); diff --git a/src/handlers/css.ts b/src/handlers/css.ts index 0758d08..b9f06b3 100644 --- a/src/handlers/css.ts +++ b/src/handlers/css.ts @@ -1,429 +1,220 @@ -import path from "path"; -import fs from "fs"; -// @ts-ignore -import css from 'css'; -import NumberGenerator from "recoverable-random"; +import type { + ConversionTables, + PrefixSuffixOptions, + TransformProps, +} from "css-seasoning"; +import type { obfuscateMode } from "../types"; + +import fs from "node:fs"; +import path from "node:path"; +import { initTransform, transform } from "css-seasoning"; +import lightningcssInit, { + transform as lightningcssTransform, +} from "lightningcss-wasm"; + +// TODO: html failed with . import { - log, - getRandomString, - seedableSimplifyString, - simplifyString, - loadAndMergeJsonFiles, - findAllFilesWithExt, - usedKeyRegistery, - getFilenameFromPath, - duplicationCheck, - createKey, - decodeKey, + findAllFilesWithExt, + getFilenameFromPath, + loadConversionTables, + log, + stringToNumber, } from "../utils"; -import { obfuscateMode, SelectorConversion } from "../types"; -let randomStringGeneraterStateCode: string | undefined = undefined; -let currentAlphabetPoistion = 1; -function createNewClassName( - mode: obfuscateMode, - className: string, - classPrefix: string = "", - classSuffix: string = "", - classNameLength: number = 5, - seed: string = Math.random().toString() -) { - let newClassName = className; - - let { rngStateCode, randomString }: { rngStateCode: string, randomString: string } = { rngStateCode: "", randomString: "" }; - - //? Based on the mechanism behind `recoverable-random` library - //? `stateCode` is directly equivalent to the `seed` - //? so recover the stateCode is the same as setting the seed - //? so the seed input `seedableSimplifyString` - //? in the following usage is meaningless - //? :) - - switch (mode) { - case "random": - ({ rngStateCode, randomString } = getRandomString(classNameLength, seed, undefined, className)); - break; - case "simplify-seedable": - ({ rngStateCode, randomString } = seedableSimplifyString(className, seed, seed + NumberGenerator.stringToSeed(className).toString())); - break; - case "simplify": - randomString = simplifyString(currentAlphabetPoistion); - currentAlphabetPoistion++; - break; - default: - break; +const obfuscateCss = ({ + cssPath, + removeOriginalCss, + isFullObfuscation, + outCssPath, + conversionTables, + + mode = "random", + prefix, + suffix, + ignorePatterns, + generatorSeed = Math.random().toString().slice(2, 10), // take 8 digits from the random number +}: { + cssPath: string; + removeOriginalCss?: boolean; + isFullObfuscation?: boolean; + outCssPath?: string; + conversionTables?: ConversionTables; + + mode?: obfuscateMode; + prefix?: PrefixSuffixOptions; + suffix?: PrefixSuffixOptions; + ignorePatterns?: TransformProps["ignorePatterns"]; + generatorSeed?: string; +}) => { + if (!outCssPath) { + // If no output path is provided, use the input path + outCssPath = cssPath; + } else if (!fs.existsSync(path.dirname(outCssPath))) { + // Create the output directory if it doesn't exist + fs.mkdirSync(path.dirname(outCssPath)); + } + + const cssContent = fs.readFileSync(cssPath, "utf-8"); + + let transformerMode: TransformProps["mode"] = + mode === "simplify" ? "minimal" : "hash"; + if (!transformerMode) { + // @ts-expect-error - "simplify-seedable" is deprecated but for backward compatibility + if (mode === "simplify-seedable") { + log( + "warn", + "CSS obfuscation", + "The 'simplify-seedable' mode is deprecated, please use 'random' or 'simplify' instead. Now will fall back to 'random' mode.", + ); + transformerMode = "hash"; } + log("error", "CSS obfuscation", `Invalid mode: ${mode}`); + throw new Error(`Invalid mode: ${mode}`); + } + + let finCss = ""; + const { css: obfuscatedCss, conversionTables: newConversionTables } = + transform({ + css: cssContent, + conversionTables: conversionTables, + mode: transformerMode, + prefix: prefix, + suffix: suffix, + seed: stringToNumber(generatorSeed), + ignorePatterns: ignorePatterns, + }); - newClassName = randomString; - randomStringGeneraterStateCode = rngStateCode; - - if (classPrefix) { - newClassName = `${classPrefix}${newClassName}`; - } - if (classSuffix) { - newClassName = `${newClassName}${classSuffix}`; - } - - return newClassName; -} - -//? CSS action selectors always at the end of the selector -//? and they can be stacked, eg. "class:hover:active" -//? action selectors can start with ":" or "::" -const findActionSelectorsRegex = /(?)/g; + if (removeOriginalCss) { + finCss = obfuscatedCss; + } else { + // if keep original selector, we need to merge the original css with the obfuscated css + // then minify the css in order to marge the css + const mixedCss = cssContent + obfuscatedCss; + const { code } = lightningcssTransform({ + filename: "style.css", + code: new TextEncoder().encode(mixedCss), + minify: true, + }); + finCss = new TextDecoder().decode(code); + } + + const totalConversion = + Object.keys(newConversionTables.selectors).length + + Object.keys(newConversionTables.idents).length; + if (removeOriginalCss) { + log( + "info", + "CSS rules:", + `Modified ${totalConversion} CSS rules to ${getFilenameFromPath(cssPath)}`, + ); + } else { + const oldTotalConversion = conversionTables + ? Object.keys(conversionTables.selectors).length + + Object.keys(conversionTables.idents).length + : 0; + log( + "info", + "CSS rules:", + `Added ${totalConversion - oldTotalConversion} new CSS rules to ${getFilenameFromPath(cssPath)}`, + ); + } + + // Save the obfuscated CSS to the output path + const sizeBefore = Buffer.byteLength(cssContent, "utf8"); + fs.writeFileSync(outCssPath, finCss); + const sizeAfter = Buffer.byteLength(finCss, "utf8"); + const percentChange = Math.round((sizeAfter / sizeBefore) * 100); + log( + "success", + "CSS obfuscated:", + `Size from ${sizeBefore} to ${sizeAfter} bytes (${percentChange}%) in ${getFilenameFromPath(cssPath)}`, + ); + + return { + conversionTables: newConversionTables, + }; +}; /** - * Extracts classes from a CSS selector. - * - * @param selector - The CSS selector to extract classes from. - * @param replacementClassNames - The replacement class names. - * The position of the class name in the array should match the - * position of the class in the selector that you want to replece. - * @returns An array of extracted classes. - * - * @example - * // Returns: ["some-class", "some-class", "bg-white", "some-class", "bg-dark"] - * extractClassFromSelector(":is(.some-class .some-class\\:!bg-white .some-class\\:bg-dark::-moz-placeholder)[data-active=\'true\']"); - * - * @example - * // Returns: [] - * extractClassFromSelector("div"); + * */ -function extractClassFromSelector(selector: string, replacementClassNames?: (string | undefined)[]) { - //? "\\[\w\%\:\.\!\*\<\>\/]" handle escaped characters - //? "(?:\\\[(?:[^\[\]\s])*\\\]))+)" handle [attribute / Tailwind CSS custom parameter] selector - const extractClassRegex = /(?<=[.:!]|(?\/]|(?:\\\[(?:[^\[\]\s])*\\\]))+)(?![\w\-]*\()/g; - - const vendorPseudoClassRegexes = [ - /::?-moz-[\w-]+/g, // Firefox - /::?-ms-[\w-]+/g, // Internet Explorer, Edge - /::?-webkit-[\w-]+/g, // Safari, Chrome, and Opera - /::?-o-[\w-]+/g, // Opera (old ver) - ] - - // temporary remove action selectors - selector = selector.replace(findActionSelectorsRegex, (match) => { - return createKey(match); - }); - - // temporary remove vendor pseudo classes - vendorPseudoClassRegexes.forEach((regex, i) => { - selector = selector.replace(regex, (match) => { - return createKey(match); - }); +export const obfuscateCssFiles = async ({ + selectorConversionJsonFolderPath, + buildFolderPath, + whiteListedFolderPaths = [], + blackListedFolderPaths = [], + mode = "random", + prefix, + suffix, + ignorePatterns, + generatorSeed = new Date().getTime().toString(), + removeOriginalCss = false, +}: { + selectorConversionJsonFolderPath: string; + buildFolderPath: string; + whiteListedFolderPaths: (string | RegExp)[]; + blackListedFolderPaths: (string | RegExp)[]; + mode?: obfuscateMode; + prefix?: PrefixSuffixOptions; + suffix?: PrefixSuffixOptions; + ignorePatterns?: TransformProps["ignorePatterns"]; + generatorSeed?: string; + removeOriginalCss?: boolean; +}) => { + // Initialize nessesary modules + await Promise.all([initTransform(), lightningcssInit()]); + + // Create the selector conversion JSON folder if it doesn't exist + if (!fs.existsSync(selectorConversionJsonFolderPath)) { + fs.mkdirSync(selectorConversionJsonFolderPath); + } + + // Load and merge all JSON files in the selector conversion folder + const conversionTables = loadConversionTables( + selectorConversionJsonFolderPath, + ); + + // Get all CSS files using the unified path filtering function + const cssPaths = findAllFilesWithExt(".css", buildFolderPath, { + whiteListedFolderPaths, + blackListedFolderPaths, + }); + + const tables: ConversionTables = { + selectors: {}, + idents: {}, + }; + + cssPaths.forEach(async (cssPath) => { + const { conversionTables: newConversionTables } = await obfuscateCss({ + cssPath: cssPath, + conversionTables: conversionTables, + + prefix, + suffix, + mode, + ignorePatterns, + generatorSeed, + removeOriginalCss, }); - // extract classes - let classes = selector.match(extractClassRegex) as string[] | undefined; - - // replace classes with replacementClassNames - if (replacementClassNames !== undefined) { - selector = selector.replace(extractClassRegex, (originalClassName) => { - return replacementClassNames.shift() || originalClassName; - }); - } - - // place back the pseudo classes - selector = decodeKey(selector); - - return { - selector: selector, - extractedClasses: classes || [] - }; -} - -function getAllSelector(cssObj: any): any[] { - const selectors: string[] = []; - function recursive(rules: any[]) { - for (const item of rules) { - if (item.rules) { - recursive(item.rules); - } else if (item.selectors) { - // remove empty selectors - item.selectors = item.selectors.filter((selector: any) => selector !== ""); - - selectors.push(...item.selectors); - } - } - return null; - } - recursive(cssObj.stylesheet.rules); - return selectors; -} - -function createSelectorConversionJson( - { - selectorConversionJsonFolderPath, - buildFolderPath, - - mode = "random", - classNameLength = 5, - classPrefix = "", - classSuffix = "", - classIgnore = [], - - enableObfuscateMarkerClasses = false, - generatorSeed = Math.random().toString().slice(2, 10), // take 8 digits from the random number - }: { - selectorConversionJsonFolderPath: string, - buildFolderPath: string, - - mode?: obfuscateMode, - classNameLength?: number, - classPrefix?: string, - classSuffix?: string, - classIgnore?: (string | RegExp)[], - - enableObfuscateMarkerClasses?: boolean, - generatorSeed?: string, - }) { - if (!fs.existsSync(selectorConversionJsonFolderPath)) { - fs.mkdirSync(selectorConversionJsonFolderPath); - } - - const selectorConversion: SelectorConversion = loadAndMergeJsonFiles(selectorConversionJsonFolderPath); - - // pre-defined ".dark", mainly for tailwindcss dark mode - if (enableObfuscateMarkerClasses) { - selectorConversion[".dark"] = ".dark"; - } - - // get all css selectors - const cssPaths = findAllFilesWithExt(".css", buildFolderPath); - const selectors: string[] = []; - cssPaths.forEach((cssPath) => { - const cssContent = fs.readFileSync(cssPath, "utf-8"); - const cssObj = css.parse(cssContent); - selectors.push(...getAllSelector(cssObj)); + // Merge the conversion tables + Object.entries(newConversionTables.selectors).forEach(([key, value]) => { + if (!tables.selectors[key]) { + // If it doesn't exist, create a new entry + tables.selectors[key] = value; + } }); - - // remove duplicated selectors - const uniqueSelectors = [...new Set(selectors)]; - - const allowClassStartWith = [".", "#", ":is(", ":where(", ":not(" - , ":matches(", ":nth-child(", ":nth-last-child(" - , ":nth-of-type(", ":nth-last-of-type(", ":first-child(" - , ":last-child(", ":first-of-type(", ":last-of-type(" - , ":only-child(", ":only-of-type(", ":empty(", ":link(" - , ":visited(", ":active(", ":hover(", ":focus(", ":target(" - , ":lang(", ":enabled(", ":disabled(", ":checked(", ":default(" - , ":indeterminate(", ":root(", ":before(" - , ":after(", ":first-letter(", ":first-line(", ":selection(" - , ":read-only(", ":read-write(", ":fullscreen(", ":optional(" - , ":required(", ":valid(", ":invalid(", ":in-range(", ":out-of-range(" - , ":placeholder-shown(" - ]; - - const selectorClassPair: { [key: string]: string[] } = {}; - - for (let i = 0; i < uniqueSelectors.length; i++) { - const originalSelector = uniqueSelectors[i]; - const { extractedClasses } = extractClassFromSelector(originalSelector) || []; - selectorClassPair[originalSelector] = extractedClasses; - } - - //? since a multi part selector normally grouped by multiple basic selectors - //? so we need to obfuscate the basic selector first - //? eg. ":is(.class1 .class2)" grouped by ".class1" and ".class2" - // sort the selectorClassPair by the number of classes in the selector (from least to most) - // and remove the selector with no class - const sortedSelectorClassPair = Object.entries(selectorClassPair) - .sort((a, b) => a[1].length - b[1].length) - .filter((pair) => pair[1].length > 0); - - for (let i = 0; i < sortedSelectorClassPair.length; i++) { - const [originalSelector, selectorClasses] = sortedSelectorClassPair[i]; - if (selectorClasses.length == 0) { - continue; - } - - let selector = originalSelector; - let classes = selectorClasses; - - if (classes && allowClassStartWith.some((start) => selector.startsWith(start))) { - classes = classes.map((className) => { - - // apply ignore list - if (classIgnore.some(regex => { - if (typeof regex === "string") { - return className === regex; - } - return new RegExp(regex).test(className) - })) { - return className; - } - - // try to get the obfuscated selector from the selectorConversion - // if not found, create a new one - let obfuscatedSelector = selectorConversion[`.${className}`]; - if (!obfuscatedSelector) { - const obfuscatedClass = createNewClassName(mode, className, classPrefix, classSuffix, classNameLength, generatorSeed); - obfuscatedSelector = `.${obfuscatedClass}`; - selectorConversion[`.${className}`] = obfuscatedSelector; - } - - // return the obfuscated class - return obfuscatedSelector.slice(1) - }); - - // obfuscate the selector - const { selector: obfuscatedSelector } = extractClassFromSelector(originalSelector, classes); - - selectorConversion[originalSelector] = obfuscatedSelector; - } - } - - const jsonPath = path.join(process.cwd(), selectorConversionJsonFolderPath, "conversion.json"); - fs.writeFileSync(jsonPath, JSON.stringify(selectorConversion, null, 2)); - if (duplicationCheck(Object.keys(selectorConversion))) { - if (mode == "random") { - log("error", "Obfuscation", "Duplicated class names found in the conversion JSON, try to increase the class name length / open an issue on GitHub https://github.com/soranoo/next-css-obfuscator/issues"); - } else { - log("error", "Obfuscation", "Duplicated class names found in the conversion JSON, please open an issue on GitHub https://github.com/soranoo/next-css-obfuscator/issues"); - } - } -} - -function copyCssData(targetSelector: string, newSelectorName: string, cssObj: any) { - function recursive(rules: any[]): any[] { - return rules.map((item: any) => { - if (item.rules) { - let newRules = recursive(item.rules); - if (Array.isArray(newRules)) { - newRules = newRules.flat(); - } - return { ...item, rules: newRules }; - } else if (item.selectors) { - // remove empty selectors - item.selectors = item.selectors.filter((selector: any) => selector !== ""); - - // check if the selector is the target selector - if (item.selectors.includes(targetSelector)) { - const newRule = JSON.parse(JSON.stringify(item)); - newRule.selectors = [newSelectorName]; - - return [item, newRule]; - } else { - return item; - } - } else { - return item; - } - }); - } - cssObj.stylesheet.rules = recursive(cssObj.stylesheet.rules).flat(); - return cssObj; -} - -function renameCssSelector(oldSelector: string, newSelector: string, cssObj: any) { - function recursive(rules: any[]): any[] { - return rules.map((item: any) => { - if (item.rules) { - return { ...item, rules: recursive(item.rules) }; - } else if (item.selectors) { - // remove empty selectors - item.selectors = item.selectors.filter((selector: any) => selector !== ""); - - let updatedSelectors = item.selectors.map((selector: any) => - selector === oldSelector ? newSelector : selector - ); - - return { ...item, selectors: updatedSelectors }; - } else { - return item; - } - }); - } - - cssObj.stylesheet.rules = recursive(cssObj.stylesheet.rules); - return cssObj; -} - -function obfuscateCss( - selectorConversion: SelectorConversion, - cssPath: string, - replaceOriginalSelector: boolean = false, - isFullObfuscation: boolean = false, - outCssPath?: string, -) { - if (!outCssPath) { - outCssPath = cssPath; - } else if (!fs.existsSync(path.dirname(outCssPath))) { - fs.mkdirSync(path.dirname(outCssPath)); - } - - let cssContent = fs.readFileSync(cssPath, "utf-8"); - - let cssObj = css.parse(cssContent); - const cssRulesCount = cssObj.stylesheet.rules.length; - - if (isFullObfuscation) { - Object.keys(selectorConversion).forEach((key) => { - usedKeyRegistery.add(key); - }); - } else { - // join all selectors start with ":" (eg. ":is") - Object.keys(selectorConversion).forEach((key) => { - if (key.startsWith(":")) { - usedKeyRegistery.add(key); - } - }); - - // join all selectors with action selectors - const actionSelectors = getAllSelector(cssObj).filter((selector) => selector.match(findActionSelectorsRegex)); - actionSelectors.forEach((actionSelector) => { - usedKeyRegistery.add(actionSelector); - }); - - // join all Tailwind CSS [child] selectors (eg. ".\[\&_\.side-box\]\:absolute .side-box") - const tailwindCssChildSelectors = getAllSelector(cssObj).filter((selector) => selector.startsWith(".\\[")); - tailwindCssChildSelectors.forEach((tailwindCssChildSelector) => { - usedKeyRegistery.add(tailwindCssChildSelector); - }); - - // join all child selectors (eg. ">*") - const universalSelectors = getAllSelector(cssObj).filter((selector) => selector.includes(">")); - universalSelectors.forEach((universalSelector) => { - usedKeyRegistery.add(universalSelector); - }); - } - - // modify css rules - usedKeyRegistery.forEach((key) => { - const originalSelectorName = key; - const obfuscatedSelectorName = selectorConversion[key]; - if (obfuscatedSelectorName) { - if (replaceOriginalSelector) { - cssObj = renameCssSelector(originalSelectorName, selectorConversion[key], cssObj); - } else { - cssObj = copyCssData(originalSelectorName, selectorConversion[key], cssObj); - } - } + Object.entries(newConversionTables.idents).forEach(([key, value]) => { + if (!tables.idents[key]) { + // If it doesn't exist, create a new entry + tables.idents[key] = value; + } }); + }); - if (replaceOriginalSelector) { - log("info", "CSS rules:", `Modified ${usedKeyRegistery.size} CSS rules to ${getFilenameFromPath(cssPath)}`); - } else { - log("info", "CSS rules:", `Added ${cssObj.stylesheet.rules.length - cssRulesCount} new CSS rules to ${getFilenameFromPath(cssPath)}`); - } - - const cssOptions = { - compress: true, - }; - const cssObfuscatedContent = css.stringify(cssObj, cssOptions); - - const sizeBefore = Buffer.byteLength(cssContent, "utf8"); - fs.writeFileSync(outCssPath, cssObfuscatedContent); - const sizeAfter = Buffer.byteLength(cssObfuscatedContent, "utf8"); - const percentChange = Math.round(((sizeAfter) / sizeBefore) * 100); - log("success", "CSS obfuscated:", `Size from ${sizeBefore} to ${sizeAfter} bytes (${percentChange}%) in ${getFilenameFromPath(cssPath)}`); -} - -export { - copyCssData, - renameCssSelector, - createSelectorConversionJson, - obfuscateCss, - extractClassFromSelector, -} \ No newline at end of file + return { + conversionTables: tables, + }; +}; diff --git a/src/handlers/html.test.ts b/src/handlers/html.test.ts deleted file mode 100644 index 58982b4..0000000 --- a/src/handlers/html.test.ts +++ /dev/null @@ -1,235 +0,0 @@ -import type { SelectorConversion } from '../types'; - -import { describe, it, expect } from "vitest"; - -import { - findHtmlTagContentsByClass, - obfuscateHtmlClassNames, -} from "./html"; - - -//! ================================ -//! findHtmlTagContentsByClass -//! ================================ - -/** - * @deprecated - */ -describe("findHtmlTagContentsByClass", () => { - const content = `
12345678
901234
56789
0123456
`; - - it("should return the correct content within the tag that with a given class", () => { - const targetClass = "test1"; - - const expectedOutput = ['
12345678
901234
56789
']; - - const result = findHtmlTagContentsByClass(content, targetClass); - expect(result).toEqual(expectedOutput); - }); - - it("should return empty array if no content found", () => { - const targetClass = "test5"; - - const expectedOutput: unknown[] = []; - - const result = findHtmlTagContentsByClass(content, targetClass); - expect(result).toEqual(expectedOutput); - }); -}); - -//! ================================ -//! obfuscateHtmlClassNames -//! ================================ - -describe("obfuscateHtmlClassNames", () => { - - it("should obfuscate class names correctly", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo"]); - }); - - it("should handle nested tags with obfuscate class", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a" }; - const keyClass = "key"; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion, obfuscateMarkerClass: keyClass }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo"]); - }); - - it("should not obfuscate class names outside of obfuscate class scope", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a", ".bar": ".b" }; - const keyClass = "key"; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion, obfuscateMarkerClass: keyClass }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([]); - }); - - it("should handle script tags", () => { - // Arrange - const html = ``; - const selectorConversion: SelectorConversion = { ".fol": ".a", ".foo": ".b" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion, obfuscateMarkerClass: "" }); - - // Assert - expect(result.obfuscatedContent).toEqual(``); - expect(result.usedKeys).to.deep.equal([".fol", ".foo"]); - }); - - it("should handle void tags", () => { - // Arrange - const html = ``; - const selectorConversion: SelectorConversion = { ".foo": ".a" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual(``); - expect(result.usedKeys).to.deep.equal([".foo"]); - }); - - - it("should handle comments", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo"]); - }); - - it("should handle HTML without classes", () => { - // Arrange - const html = "
"; - const selectorConversion: SelectorConversion = {}; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual("
"); - expect(result.usedKeys).to.deep.equal([]); - }); - - it("should handle empty HTML", () => { - // Arrange - const html = ""; - const selectorConversion: SelectorConversion = { ".foo": ".a" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual(""); - expect(result.usedKeys).to.deep.equal([]); - }); - - it("should handle HTML with multiple classes in one element", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a", ".bar": ".b", ".baz": ".c" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo", ".bar", ".baz"]); - }); - - it("should handle HTML with nested structures and multiple classes", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a", ".bar": ".b", ".baz": ".c" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo", ".bar", ".baz"]); - }); - - it("should handle HTML with obfuscate marker class", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a" }; - const obfuscateMarkerClass = "key"; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion, obfuscateMarkerClass }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo"]); - }); - - it("should handle HTML with multiple classes and obfuscate marker class", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a", ".bar": ".b", ".baz": ".c" }; - const obfuscateMarkerClass = "key"; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion, obfuscateMarkerClass }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo", ".bar", ".baz"]); - }); - - it("should handle HTML instruction", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo"]); - }); - - /** - * @see https://github.com/soranoo/next-css-obfuscator/issues/57 - */ - it("should handle double quot inside double quot", () => { - // Arrange - const html = `
`; - const selectorConversion: SelectorConversion = { ".foo": ".a" }; - - // Act - const result = obfuscateHtmlClassNames({ html, selectorConversion }); - - // Assert - expect(result.obfuscatedContent).toEqual(`
`); - expect(result.usedKeys).to.deep.equal([".foo"]); - }); -}); diff --git a/src/handlers/html.ts b/src/handlers/html.ts index 3b32b82..91b5665 100644 --- a/src/handlers/html.ts +++ b/src/handlers/html.ts @@ -1,302 +1,154 @@ import type { SelectorConversion } from "../types"; -import * as htmlparser2 from "htmlparser2"; +import { cssUnescape } from "css-seasoning"; import { escape as htmlEscape } from "html-escaper"; -import { log, obfuscateKeys } from "../utils"; +import * as htmlparser2 from "htmlparser2"; +import { obfuscateKeys } from "../utils"; import { obfuscateJs } from "./js"; -/** - * @deprecated - */ -function findHtmlTagContentsRecursive( - content: string, - targetTag: string, - targetClass: string | null = null, - foundTagContents: string[] = [], - deep = 0, - maxDeep = -1, -) { - let contentAfterTag = content; - const startTagWithClassRegexStr = targetClass - ? // ref: https://stackoverflow.com/a/16559544 - `(<\\w+?\\s+?class\\s*=\\s*['\"][^'\"]*?\\b${targetClass}\\b)` - : ""; - const startTagRegexStr = `(<${targetTag}[\\s|>])`; - const endTagRegexStr = `(<\/${targetTag}>)`; - - // clear content before the start tag - const clearContentBeforeStartTagRegex = new RegExp( - `${startTagWithClassRegexStr ? startTagWithClassRegexStr + ".*|" + startTagRegexStr : startTagRegexStr + ".*"}`, - "i", - ); - const contentAfterStartTagMatch = contentAfterTag.match( - clearContentBeforeStartTagRegex, - ); - if (contentAfterStartTagMatch) { - contentAfterTag = contentAfterStartTagMatch[0]; - } - - let endTagCont = 0; - - const endTagContRegex = new RegExp(endTagRegexStr, "gi"); - const endTagContMatch = contentAfterTag.match(endTagContRegex); - if (endTagContMatch) { - endTagCont = endTagContMatch.length; - } - - let closeTagPoition = 0; - - const tagPatternRegex = new RegExp( - `${startTagWithClassRegexStr ? startTagWithClassRegexStr + "|" + startTagRegexStr : startTagRegexStr}|${endTagRegexStr}`, - "gi", - ); - const tagPatternMatch = contentAfterTag.match(tagPatternRegex); - if (tagPatternMatch) { - let tagCount = 0; - let markedPosition = false; - for (let i = 0; i < tagPatternMatch.length; i++) { - if (tagPatternMatch[i].startsWith(")`, "i"); - const remainingHtmlTagMatch = remainingHtml.match(remainingHtmlTagRegex); - if (remainingHtmlTagMatch) { - if (maxDeep === -1 || deep < maxDeep) { - return findHtmlTagContentsRecursive( - remainingHtml, - targetTag, - targetClass, - foundTagContents, - deep + 1, - maxDeep, - ); - } - log("warn", "HTML search:", "Max deep reached, recursive break"); - return foundTagContents; - } - } - - return foundTagContents; -} - -/** - * @deprecated - */ -function findHtmlTagContents( - content: string, - targetTag: string, - targetClass: string | null = null, -) { - return findHtmlTagContentsRecursive(content, targetTag, targetClass); -} - -/** - * @deprecated - */ -function findHtmlTagContentsByClass(content: string, targetClass: string) { - const regex = new RegExp( - `(<(\\w+)\\s+class\\s*=\\s*['\"][^'\"]*?\\b${targetClass}\\b)`, - "i", - ); - const match = content.match(regex); - if (match) { - const tag = match[2]; - return findHtmlTagContents(content, tag, targetClass); - } - return []; -} - -function obfuscateHtmlClassNames({ - html, - selectorConversion, - obfuscateMarkerClass = "", - contentIgnoreRegexes = [], +export const obfuscateHtmlClassNames = ({ + html, + selectorConversion, + obfuscateMarkerClass = "", + contentIgnoreRegexes = [], }: { - html: string; - selectorConversion: SelectorConversion; - obfuscateMarkerClass?: string; - contentIgnoreRegexes?: RegExp[]; -}) { - const voidTags = [ - "area", - "base", - "br", - "col", - "command", - "embed", - "hr", - "img", - "input", - "keygen", - "link", - "meta", - "param", - "source", - "track", - "wbr", - ]; - - let modifiedHtml = ""; - let insideObsClassScope = false; - let ObsClassScopeTagCount = 0; // Count of the obfuscate class scope tag (for nested tags with the same class name) - let ObsClassScopeTag = ""; - - let scriptContent = ""; - let isScriptTag = false; - - const usedKeys: string[] = []; - - const parser = new htmlparser2.Parser( - { - onprocessinginstruction(name, data) { - modifiedHtml += `<${data}>`; - }, - onopentag(tagName, attribs) { - if (tagName === "script") { - isScriptTag = true; - scriptContent = ""; // reset script content for a new script tag - } - - if (attribs.class) { - // Check if the current tag is within the scope of the obfuscate class - if ( - !insideObsClassScope && - obfuscateMarkerClass && - attribs.class.includes(obfuscateMarkerClass) - ) { - insideObsClassScope = true; - ObsClassScopeTag = tagName; - } - - if (insideObsClassScope || !obfuscateMarkerClass) { - const { obfuscatedContent, usedKeys: _usedKeys } = obfuscateKeys( - selectorConversion, - attribs.class, - [], - true, - ); - usedKeys.push(..._usedKeys); - // Update the class to the modified class names - attribs.class = obfuscatedContent; - } - } - - if (insideObsClassScope && tagName === ObsClassScopeTag) { - ObsClassScopeTagCount++; - } - - // Reconstruct the tag with the modified class names - modifiedHtml += `<${tagName}`; - for (const key in attribs) { - // modifiedHtml += ` ${key}="${attribs[key]}"`; + html: string; + selectorConversion: SelectorConversion; + obfuscateMarkerClass?: string; + contentIgnoreRegexes?: RegExp[]; +}) => { + const voidTags = [ + "area", + "base", + "br", + "col", + "command", + "embed", + "hr", + "img", + "input", + "keygen", + "link", + "meta", + "param", + "source", + "track", + "wbr", + ]; + + let modifiedHtml = ""; + let insideObsClassScope = false; + let ObsClassScopeTagCount = 0; // Count of the obfuscate class scope tag (for nested tags with the same class name) + let ObsClassScopeTag = ""; + + let scriptContent = ""; + let isScriptTag = false; + + const usedKeys: string[] = []; + + const parser = new htmlparser2.Parser( + { + onprocessinginstruction(_, data) { + modifiedHtml += `<${data}>`; + }, + onopentag(tagName, attribs) { + if (tagName === "script") { + isScriptTag = true; + scriptContent = ""; // reset script content for a new script tag + } + + if (attribs.class) { + // Check if the current tag is within the scope of the obfuscate class + if ( + !insideObsClassScope && + obfuscateMarkerClass && + attribs.class.includes(obfuscateMarkerClass) + ) { + insideObsClassScope = true; + ObsClassScopeTag = tagName; + } + + if (insideObsClassScope || !obfuscateMarkerClass) { + const { obfuscatedContent, usedKeys: _usedKeys } = obfuscateKeys( + selectorConversion, + attribs.class, + [], + ); + usedKeys.push(..._usedKeys); + // Update the class to the modified class names + attribs.class = obfuscatedContent; + } + } + + if (insideObsClassScope && tagName === ObsClassScopeTag) { + ObsClassScopeTagCount++; + } + + // Reconstruct the tag with the modified class names + modifiedHtml += `<${tagName}`; + for (const key in attribs) { + // modifiedHtml += ` ${key}="${attribs[key]}"`; modifiedHtml += ` ${key}="${htmlEscape(attribs[key])}"`; - } - if (voidTags.includes(tagName)) { - modifiedHtml += " />"; - } else { - modifiedHtml += ">"; - } - }, - oncomment(comment) { - modifiedHtml += ``; - }, - ontext(text) { - if (isScriptTag) { - scriptContent += text; - } else { - modifiedHtml += text; - } - }, - onclosetag(tagname) { - if (voidTags.includes(tagname)) { - return; - } - - if (tagname === "script" && isScriptTag) { - isScriptTag = false; - let obfuscatedScriptContent = scriptContent; - Object.keys(selectorConversion).forEach((key) => { - const className = key.slice(1); - const obfuscatedJs = obfuscateJs( - obfuscatedScriptContent, - className, - { [key]: selectorConversion[key] }, - "{a HTML file path}", - contentIgnoreRegexes, - ); - if (obfuscatedJs !== obfuscatedScriptContent) { - obfuscatedScriptContent = obfuscatedJs; - usedKeys.push(key); - } - }); - modifiedHtml += `${obfuscatedScriptContent}`; - } - modifiedHtml += ``; - - if (insideObsClassScope && tagname === ObsClassScopeTag) { - ObsClassScopeTagCount--; - } - - if (ObsClassScopeTagCount === 0) { - insideObsClassScope = false; - } - }, - }, - { decodeEntities: true }, - ); - - parser.write(html); - parser.end(); - - return { - obfuscatedContent: modifiedHtml, - usedKeys: Array.from(new Set(usedKeys)), - }; -} - -export { - findHtmlTagContents, - findHtmlTagContentsByClass, - obfuscateHtmlClassNames, + } + if (voidTags.includes(tagName)) { + modifiedHtml += " />"; + } else { + modifiedHtml += ">"; + } + }, + oncomment(comment) { + modifiedHtml += ``; + }, + ontext(text) { + if (isScriptTag) { + scriptContent += text; + } else { + modifiedHtml += text; + } + }, + onclosetag(tagname) { + if (voidTags.includes(tagname)) { + return; + } + + if (tagname === "script" && isScriptTag) { + isScriptTag = false; + let obfuscatedScriptContent = scriptContent; + Object.keys(selectorConversion).forEach((key) => { + const className = cssUnescape(key).slice(1); + const obfuscatedJs = obfuscateJs( + obfuscatedScriptContent, + className, + { [key]: selectorConversion[key] }, + "{a HTML file path}", + contentIgnoreRegexes, + ); + if (obfuscatedJs !== obfuscatedScriptContent) { + obfuscatedScriptContent = obfuscatedJs; + usedKeys.push(key); + } + }); + modifiedHtml += `${obfuscatedScriptContent}`; + } + modifiedHtml += ``; + + if (insideObsClassScope && tagname === ObsClassScopeTag) { + ObsClassScopeTagCount--; + } + + if (ObsClassScopeTagCount === 0) { + insideObsClassScope = false; + } + }, + }, + { decodeEntities: true }, + ); + + parser.write(html); + parser.end(); + + return { + obfuscatedContent: modifiedHtml, + usedKeys: Array.from(new Set(usedKeys)), + }; }; diff --git a/src/handlers/js-ast.ts b/src/handlers/js-ast.ts index 44907e8..b533429 100644 --- a/src/handlers/js-ast.ts +++ b/src/handlers/js-ast.ts @@ -1,10 +1,10 @@ +import generator from "@babel/generator"; import * as parser from "@babel/parser"; -import traverse, { NodePath } from "@babel/traverse"; +import traverse, { type NodePath } from "@babel/traverse"; import * as t from "@babel/types"; -import generator from "@babel/generator"; +import type { SelectorConversion } from "../types"; import { obfuscateKeys } from "../utils"; -import { type SelectorConversion } from "../types"; /** * Obfuscate the JavaScript code using AST(Abstract Syntax Tree) @@ -14,12 +14,12 @@ import { type SelectorConversion } from "../types"; * @param stripUnnecessarySpace - whether to strip unnecessary space in the className, e.g. " a b c " => "a b c" * @returns - the obfuscated code and the used keys */ -function obfuscateJsWithAst( +export const obfuscateJsWithAst = ( code: string, selectorConversion: SelectorConversion | undefined, startingKeys: string[] = [], - stripUnnecessarySpace: boolean = true -) { + stripUnnecessarySpace = true, +) => { const ast = parser.parse(code, { sourceType: "module", plugins: ["jsx"] }); const usedKeys: Set = new Set(); @@ -38,12 +38,17 @@ function obfuscateJsWithAst( } // strip unnecessary space, e.g. " a b c " => "a b c " - str = stripUnnecessarySpace ? str.replace(/\s+/g, " ").trimStart() //? avoid trimming the end to keep the space between classes + const newStr = stripUnnecessarySpace + ? str + .replace(/\s+/g, " ") + .trimStart() //? avoid trimming the end to keep the space between classes : str; - const { obfuscatedContent, usedKeys: obfuscateUsedKeys } = obfuscateKeys(selectorConversion, str); - if (obfuscatedContent !== str) { - obfuscateUsedKeys.forEach(key => usedKeys.add(key)); + const { obfuscatedContent, usedKeys: obfuscateUsedKeys } = + obfuscateKeys(selectorConversion, newStr); + + if (obfuscatedContent !== newStr) { + obfuscateUsedKeys.forEach((key) => usedKeys.add(key)); return obfuscatedContent; } }); @@ -61,10 +66,9 @@ function obfuscateJsWithAst( const obfuscatedCode = generator(ast, options, code); return { obfuscatedCode: obfuscatedCode.code, - usedKeys: usedKeys + usedKeys: usedKeys, }; -} - +}; /** * Search for string literals in the AST and replace them with the result of the callback function @@ -73,12 +77,13 @@ function obfuscateJsWithAst( * @param scannedNodes - (for recursion) keep track of scanned nodes to avoid infinite loop * @returns - the modified AST node */ -function searchStringLiterals(path: NodePath, - callback: (str: string) => void | string, +export const searchStringLiterals = ( + path: NodePath, + callback: (str: string) => undefined | string, //? keep track of scanned nodes to avoid infinite loop - scannedNodes: Set = new Set() -) { + scannedNodes: Set = new Set(), +) => { /* Skip this node if it has already been scanned */ if (path.node && scannedNodes.has(path.node)) { return; @@ -89,7 +94,7 @@ function searchStringLiterals(path: NodePath, if (t.isBlockStatement(path.node)) { const body = path.get("body"); if (Array.isArray(body)) { - body.forEach(nodePath => { + body.forEach((nodePath) => { switch (nodePath.node.type) { //? only care about statements that return statements maybe inside //? to avoid scanning all string literals in that block @@ -107,22 +112,20 @@ function searchStringLiterals(path: NodePath, } else { searchStringLiterals(body, callback, scannedNodes); } - } - /* function return statement */ - else if (t.isReturnStatement(path.node)) { + } else if (t.isReturnStatement(path.node)) { + /* function return statement */ const argument = path.get("argument"); if (argument) { if (!Array.isArray(argument)) { searchStringLiterals(argument, callback, scannedNodes); } else { - argument.forEach(arg => { + argument.forEach((arg) => { searchStringLiterals(arg, callback, scannedNodes); }); } } - } - /* binary expression (e.g. const a = "hello" + "world") */ - else if (t.isBinaryExpression(path.node)) { + } else if (t.isBinaryExpression(path.node)) { + /* binary expression (e.g. const a = "hello" + "world") */ const left = path.get("left"); const right = path.get("right"); if (left && !Array.isArray(left)) { @@ -131,15 +134,13 @@ function searchStringLiterals(path: NodePath, if (right && !Array.isArray(right)) { searchStringLiterals(right, callback, scannedNodes); } - } - /* string literal (e.g. "hello"), the string within the quotes */ - else if (t.isStringLiteral(path.node)) { + } else if (t.isStringLiteral(path.node)) { + /* string literal (e.g. "hello"), the string within the quotes */ const replacement = callback(path.node.value); if (replacement) { path.replaceWith(t.stringLiteral(replacement)); } - } - else if (t.isIdentifier(path.node)) { + } else if (t.isIdentifier(path.node)) { const variableName = path.node.name; const binding = path.scope.getBinding(variableName); if (binding && t.isVariableDeclarator(binding.path.node)) { @@ -153,16 +154,15 @@ function searchStringLiterals(path: NodePath, searchStringLiterals(body, callback, scannedNodes); } } - } - /* call expression (e.g. const a = call()) */ - else if (t.isCallExpression(path.node)) { + } else if (t.isCallExpression(path.node)) { + /* call expression (e.g. const a = call()) */ const callee = path.get("callee"); if (callee && !Array.isArray(callee)) { searchStringLiterals(callee, callback, scannedNodes); } const args = path.get("arguments"); if (Array.isArray(args)) { - args.forEach(arg => { + args.forEach((arg) => { if (t.isStringLiteral(arg.node)) { const replacement = callback(arg.node.value); if (replacement) { @@ -173,9 +173,8 @@ function searchStringLiterals(path: NodePath, } }); } - } - /* conditional expression (e.g. const a = true ? "hello" : "world") */ - else if (t.isConditionalExpression(path.node)) { + } else if (t.isConditionalExpression(path.node)) { + /* conditional expression (e.g. const a = true ? "hello" : "world") */ const test = path.get("test"); const consequent = path.get("consequent"); const alternate = path.get("alternate"); @@ -188,9 +187,8 @@ function searchStringLiterals(path: NodePath, if (alternate && !Array.isArray(alternate)) { searchStringLiterals(alternate, callback, scannedNodes); } - } - /* if statement (e.g. if (true) { "hello" } else { "world" }) */ - else if (t.isIfStatement(path.node)) { + } else if (t.isIfStatement(path.node)) { + /* if statement (e.g. if (true) { "hello" } else { "world" }) */ const test = path.get("test"); const consequent = path.get("consequent"); const alternate = path.get("alternate"); @@ -203,47 +201,43 @@ function searchStringLiterals(path: NodePath, if (alternate && !Array.isArray(alternate)) { searchStringLiterals(alternate, callback, scannedNodes); } - } - /* object expression (e.g. const a = { key: "value" }) */ - else if (t.isObjectExpression(path.node)) { + } else if (t.isObjectExpression(path.node)) { + /* object expression (e.g. const a = { key: "value" }) */ const properties = path.get("properties"); if (Array.isArray(properties)) { - properties.forEach(prop => { + properties.forEach((prop) => { searchStringLiterals(prop, callback, scannedNodes); }); } - } - /* object property (key and value of an object expression) */ - else if (t.isObjectProperty(path.node)) { + } else if (t.isObjectProperty(path.node)) { + /* object property (key and value of an object expression) */ const value = path.get("value"); if (value && !Array.isArray(value)) { searchStringLiterals(value, callback, scannedNodes); } - } - /* array expression (e.g. const a = ["element_1", "element_2"]) */ - else if (t.isArrayExpression(path.node)) { + } else if (t.isArrayExpression(path.node)) { + /* array expression (e.g. const a = ["element_1", "element_2"]) */ const elements = path.get("elements"); if (Array.isArray(elements)) { - elements.forEach(element => { + elements.forEach((element) => { searchStringLiterals(element, callback, scannedNodes); }); } - } - /* switch statement (e.g. switch (value) { case "1": return "one"; case "2": return "two"; default: return "default"; }) */ - else if (t.isSwitchStatement(path.node)) { + } else if (t.isSwitchStatement(path.node)) { + /* switch statement (e.g. switch (value) { case "1": return "one"; case "2": return "two"; default: return "default"; }) */ const cases = path.get("cases"); if (Array.isArray(cases)) { - cases.forEach(c => { + cases.forEach((c) => { searchStringLiterals(c, callback, scannedNodes); }); } - } - /* switch case (e.g. case "1": return "one") */ - else if (t.isSwitchCase(path.node)) { + } else if (t.isSwitchCase(path.node)) { + /* switch case (e.g. case "1": return "one") */ const consequent = path.get("consequent"); if (Array.isArray(consequent)) { - consequent.forEach(c => { - if (t.isReturnStatement(c.node)) { // only care about return statements, if any variable declarations are present, they will be handled in the next iteration + consequent.forEach((c) => { + if (t.isReturnStatement(c.node)) { + // only care about return statements, if any variable declarations are present, they will be handled in the next iteration searchStringLiterals(c, callback, scannedNodes); } }); @@ -295,9 +289,8 @@ function searchStringLiterals(path: NodePath, searchStringLiterals(handlerBody, callback, scannedNodes); } } - } - /* member expression (e.g. "scroll-top".replace("-", "_")); "scroll-top ".concat("visible"); */ - else if (t.isMemberExpression(path.node)) { + } else if (t.isMemberExpression(path.node)) { + /* member expression (e.g. "scroll-top".replace("-", "_")); "scroll-top ".concat("visible"); */ const object = path.get("object"); const property = path.get("property"); const argument = path.get("argument"); @@ -310,28 +303,26 @@ function searchStringLiterals(path: NodePath, if (argument && !Array.isArray(argument)) { searchStringLiterals(argument, callback, scannedNodes); } else if (Array.isArray(argument)) { - argument.forEach(arg => { + argument.forEach((arg) => { searchStringLiterals(arg, callback, scannedNodes); }); } - } - /* template literal (e.g. `hello ${name}`) */ - else if (t.isTemplateLiteral(path.node)) { + } else if (t.isTemplateLiteral(path.node)) { + /* template literal (e.g. `hello ${name}`) */ const quasis = path.get("quasis"); const expressions = path.get("expressions"); if (Array.isArray(quasis)) { - quasis.forEach(quasi => { + quasis.forEach((quasi) => { searchStringLiterals(quasi, callback, scannedNodes); }); } if (Array.isArray(expressions)) { - expressions.forEach(expression => { + expressions.forEach((expression) => { searchStringLiterals(expression, callback, scannedNodes); }); } - } - /* template element (e.g. `hello ${name}`) */ - else if (t.isTemplateElement(path.node)) { + } else if (t.isTemplateElement(path.node)) { + /* template element (e.g. `hello ${name}`) */ const node = path.node as t.TemplateElement; if (node.value) { @@ -353,8 +344,7 @@ function searchStringLiterals(path: NodePath, } } } - } - else { + } else { path.traverse({ Identifier(innerPath) { searchStringLiterals(innerPath, callback, scannedNodes); @@ -365,9 +355,4 @@ function searchStringLiterals(path: NodePath, }); } return path; -} - -export { - searchStringLiterals, - obfuscateJsWithAst, -} +}; diff --git a/src/handlers/js.test.ts b/src/handlers/js.test.ts deleted file mode 100644 index 6e33ffc..0000000 --- a/src/handlers/js.test.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { describe, it, expect, test } from "vitest"; -import { - searchForwardComponent, -} from "./js"; - -//! ================================ -//! searchForwardComponent -//! ================================ - -describe("searchForwardComponent", () => { - - test("should return component name when jsx format is correct", () => { - // Arrange - const content = `const element = o.jsx(ComponentName, {data: dataValue, index: "date"});`; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual(["ComponentName"]); - }); - - test("should return multiple component names for multiple matches", () => { - // Arrange - const content = `o.jsx(FirstComponent, props); o.jsx(SecondComponent, otherProps);`; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual(["FirstComponent", "SecondComponent"]); - }); - - test("should return an empty array when no component name is found", () => { - // Arrange - const content = `o.jsx("h1", {data: dataValue, index: "date"});`; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual([]); - }); - - test("should return an empty array when content is empty", () => { - // Arrange - const content = ""; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual([]); - }); - - test("should return an empty array when jsx is not used", () => { - // Arrange - const content = `const element = React.createElement("div", null, "Hello World");`; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual([]); - }); - - test("should handle special characters in component names", () => { - // Arrange - const content = `o.jsx($Comp_1, props); o.jsx(_Comp$2, otherProps);`; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual(["$Comp_1", "_Comp$2"]); - }); - - test("should not return component names when they are quoted", () => { - // Arrange - const content = `o.jsx("ComponentName", props); o.jsx('AnotherComponent', otherProps);`; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual([]); - }); - - test("should return component names when they are followed by a brace", () => { - // Arrange - const content = `o.jsx(ComponentName, {props: true});`; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual(["ComponentName"]); - }); - - test("should handle content with line breaks and multiple jsx calls", () => { - // Arrange - const content = ` - o.jsx(FirstComponent, {data: dataValue}); - o.jsx(SecondComponent, {index: "date"}); - o.jsx(ThirdComponent, {flag: true}); - `; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual(["FirstComponent", "SecondComponent", "ThirdComponent"]); - }); - - test("should handle content with nested jsx calls", () => { - // Arrange - const content = `o.jsx(ParentComponent, {children: o.jsx(ChildComponent, {})})`; - - // Act - const result = searchForwardComponent(content); - - // Assert - expect(result).toEqual(["ParentComponent", "ChildComponent"]); - }); - -}); diff --git a/src/handlers/js.ts b/src/handlers/js.ts index 343c98e..ba5d839 100644 --- a/src/handlers/js.ts +++ b/src/handlers/js.ts @@ -1,18 +1,16 @@ +import type { SelectorConversion } from "../types"; import { - log, + addKeysToRegistery, + findClosestSymbolPosition, findContentBetweenMarker, - replaceFirstMatch, + log, normalizePath, obfuscateKeys, - addKeysToRegistery, - findClosestSymbolPosition + replaceFirstMatch, } from "../utils"; - -import { SelectorConversion } from "../types"; import { obfuscateJsWithAst } from "./js-ast"; - -function searchForwardComponent(content: string) { +export const searchForwardComponent = (content: string) => { const componentSearchRegex = /(?<=\.jsx\()[^,|"|']+/g; //eg. o.jsx(yt,{data:yc,index:"date // then return yt @@ -24,10 +22,13 @@ function searchForwardComponent(content: string) { return match; } return []; -} +}; -function searchComponent(content: string, componentName: string) { - const componentSearchRegex = new RegExp(`\\b(?:const|let|var)\\s+(${componentName})\\s*=\\s*.*?(\\{)`, "g"); +const searchComponent = (content: string, componentName: string) => { + const componentSearchRegex = new RegExp( + `\\b(?:const|let|var)\\s+(${componentName})\\s*=\\s*.*?(\\{)`, + "g", + ); // eg, let yt=l().forwardRef((e,t)=>{let const match = content.match(componentSearchRegex); let openSymbolPos = -1; @@ -35,81 +36,138 @@ function searchComponent(content: string, componentName: string) { openSymbolPos = content.indexOf(match[0]) + match[0].length; } - const closeMarkerPos = findClosestSymbolPosition(content, "{", "}", openSymbolPos, "forward"); + const closeMarkerPos = findClosestSymbolPosition( + content, + "{", + "}", + openSymbolPos, + "forward", + ); const componentContent = content.slice(openSymbolPos, closeMarkerPos); return componentContent; -} - -function obfuscateForwardComponentJs(searchContent: string, wholeContent: string, selectorConversion: SelectorConversion) { - const componentNames = searchForwardComponent(searchContent).filter((componentName) => { - return !componentName.includes("."); - }); - - const componentsCode = componentNames.map(componentName => { +}; + +export const obfuscateForwardComponentJs = ( + searchContent: string, + wholeContent: string, + selectorConversion: SelectorConversion, +) => { + const componentNames = searchForwardComponent(searchContent).filter( + (componentName) => { + return !componentName.includes("."); + }, + ); + + const componentsCode = componentNames.map((componentName) => { const componentContent = searchComponent(wholeContent, componentName); return { name: componentName, - code: componentContent - } + code: componentContent, + }; }); const componentsObfuscatedCode = componentsCode.map((componentContent) => { - const classNameBlocks = findContentBetweenMarker(componentContent.code, "className:", "{", "}"); - const obfuscatedClassNameBlocks = classNameBlocks.map(block => { - const { obfuscatedContent, usedKeys } = obfuscateKeys(selectorConversion, block); + const classNameBlocks = findContentBetweenMarker( + componentContent.code, + "className:", + "{", + "}", + ); + const obfuscatedClassNameBlocks = classNameBlocks.map((block) => { + const { obfuscatedContent, usedKeys } = obfuscateKeys( + selectorConversion, + block, + ); addKeysToRegistery(usedKeys); return obfuscatedContent; }); if (classNameBlocks.length !== obfuscatedClassNameBlocks.length) { - log("error", `Component obfuscation:`, `classNameBlocks.length !== obfuscatedClassNameBlocks.length`); + log( + "error", + "Component obfuscation:", + "classNameBlocks.length !== obfuscatedClassNameBlocks.length", + ); return componentContent; } let obscuredCode = componentContent.code; for (let i = 0; i < classNameBlocks.length; i++) { - obscuredCode = replaceFirstMatch(obscuredCode, classNameBlocks[i], obfuscatedClassNameBlocks[i]); + obscuredCode = replaceFirstMatch( + obscuredCode, + classNameBlocks[i], + obfuscatedClassNameBlocks[i], + ); } - log("debug", `Obscured keys in component:`, componentContent.name); + log("debug", "Obscured keys in component:", componentContent.name); return { name: componentContent.name, - code: obscuredCode - } + code: obscuredCode, + }; }); - const componentObfuscatedcomponentCodePairs: { name: string, componentCode: string, componentObfuscatedCode: string }[] = []; + const componentObfuscatedcomponentCodePairs: { + name: string; + componentCode: string; + componentObfuscatedCode: string; + }[] = []; for (let i = 0; i < componentsCode.length; i++) { if (componentsCode[i] !== componentsObfuscatedCode[i]) { componentObfuscatedcomponentCodePairs.push({ name: componentsCode[i].name, componentCode: componentsCode[i].code, - componentObfuscatedCode: componentsObfuscatedCode[i].code + componentObfuscatedCode: componentsObfuscatedCode[i].code, }); } } - for (let i = 0; i < componentsCode.length; i++) { - const childComponentObfuscatedcomponentCodePairs = obfuscateForwardComponentJs(componentsCode[i].code, wholeContent, selectorConversion); - componentObfuscatedcomponentCodePairs.push(...childComponentObfuscatedcomponentCodePairs); + for (const component of componentsCode) { + const childComponentObfuscatedcomponentCodePairs = + obfuscateForwardComponentJs( + component.code, + wholeContent, + selectorConversion, + ); + componentObfuscatedcomponentCodePairs.push( + ...childComponentObfuscatedcomponentCodePairs, + ); } return componentObfuscatedcomponentCodePairs; -} - -function obfuscateJs(content: string, key: string, selectorCoversion: SelectorConversion - , filePath: string, contentIgnoreRegexes: RegExp[] = [], useAst: boolean = false) { - +}; + +export const obfuscateJs = ( + content: string, + key: string, + selectorCoversion: SelectorConversion, + filePath: string, + contentIgnoreRegexes: RegExp[] = [], + useAst = false, +) => { if (useAst) { try { - const { obfuscatedCode, usedKeys } = obfuscateJsWithAst(content, selectorCoversion, key ? [key] : [], true); + const { obfuscatedCode, usedKeys } = obfuscateJsWithAst( + content, + selectorCoversion, + key ? [key] : [], + true, + ); addKeysToRegistery(usedKeys); if (content !== obfuscatedCode) { - log("debug", `Obscured keys with AST and marker "${key}":`, `${normalizePath(filePath)}`); + log( + "debug", + `Obscured keys with AST and marker "${key}":`, + `${normalizePath(filePath)}`, + ); } return obfuscatedCode; } catch (error) { if (error instanceof SyntaxError) { log("warn", "Syntax error ignored:", error); - log("warn", "Obfuscation with AST failed:", "Falling back to regex obfuscation"); + log( + "warn", + "Obfuscation with AST failed:", + "Falling back to regex obfuscation", + ); } else { throw error; // re-throw non-syntax errors } @@ -117,19 +175,22 @@ function obfuscateJs(content: string, key: string, selectorCoversion: SelectorCo } const truncatedContents = findContentBetweenMarker(content, key, "{", "}"); + let newContent = content; truncatedContents.forEach((truncatedContent) => { - const { obfuscatedContent, usedKeys } = obfuscateKeys(selectorCoversion, truncatedContent, contentIgnoreRegexes); + const { obfuscatedContent, usedKeys } = obfuscateKeys( + selectorCoversion, + truncatedContent, + contentIgnoreRegexes, + ); addKeysToRegistery(usedKeys); if (truncatedContent !== obfuscatedContent) { - content = content.replace(truncatedContent, obfuscatedContent); - log("debug", `Obscured keys with marker "${key}":`, `${normalizePath(filePath)}`); + newContent = newContent.replace(truncatedContent, obfuscatedContent); + log( + "debug", + `Obscured keys with marker "${key}":`, + `${normalizePath(filePath)}`, + ); } }); - return content; -} - -export { - obfuscateForwardComponentJs, - obfuscateJs, - searchForwardComponent, -} \ No newline at end of file + return newContent; +}; diff --git a/src/index.ts b/src/index.ts index c76898b..d6b9528 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,19 +1,19 @@ -import fs from "fs"; -import path from "path"; +import type { OptionalOptions, Options } from "./types"; + +import fs from "node:fs"; +import path from "node:path"; import yargs from "yargs"; +import Config from "./config"; +import { obfuscateCssFiles } from "./handlers/css"; import { + findAllFilesWithExt, + getFilenameFromPath, log, replaceJsonKeysInFiles, setLogLevel, - findAllFilesWithExt, } from "./utils"; -import { createSelectorConversionJson } from "./handlers/css"; - -import Config from "./config"; -import { Options, OptionalOptions } from "./types"; - -function obfuscate(options: Options) { +const obfuscate = async (options: Options) => { setLogLevel(options.logLevel); if (!options.enable) { @@ -21,8 +21,14 @@ function obfuscate(options: Options) { return; } - const classConversionJsonPaths = findAllFilesWithExt(".json", options.classConversionJsonFolderPath); - if (options.refreshClassConversionJson && classConversionJsonPaths.length > 0) { + const classConversionJsonPaths = findAllFilesWithExt( + ".json", + options.classConversionJsonFolderPath, + ); + if ( + options.refreshClassConversionJson && + classConversionJsonPaths.length > 0 + ) { log("info", "Obfuscation", "Refreshing class conversion JSON"); for (const jsonPath of classConversionJsonPaths) { fs.unlinkSync(jsonPath); @@ -31,52 +37,78 @@ function obfuscate(options: Options) { } log("info", "Obfuscation", "Creating/Updating class conversion JSON"); - createSelectorConversionJson({ + + // Reconstruct ignore patterns for backward compatibility + // TODO: Remove in the next major version + let ignorePatterns = options.ignorePatterns; + if (options.classIgnore) { + if (ignorePatterns && !Array.isArray(ignorePatterns)) { + ignorePatterns.selectors?.push(...options.classIgnore); + } else { + ignorePatterns = { + selectors: [...(ignorePatterns || []), ...options.classIgnore], + idents: [...(ignorePatterns || [])], + }; + } + } + + // Create conversion tables and obfuscate CSS files + const { conversionTables } = await obfuscateCssFiles({ selectorConversionJsonFolderPath: options.classConversionJsonFolderPath, buildFolderPath: options.buildFolderPath, + whiteListedFolderPaths: options.whiteListedFolderPaths, + blackListedFolderPaths: options.blackListedFolderPaths, mode: options.mode, - classNameLength: options.classLength, - classPrefix: options.classPrefix, - classSuffix: options.classSuffix, - classIgnore: options.classIgnore, + prefix: options.prefix || { selectors: options.classPrefix }, + suffix: options.suffix || { selectors: options.classSuffix }, + ignorePatterns: ignorePatterns, - enableObfuscateMarkerClasses: options.enableMarkers, - generatorSeed: options.generatorSeed === "-1" ? undefined : options.generatorSeed, + generatorSeed: options.generatorSeed, + removeOriginalCss: options.removeOriginalCss, }); - log("success", "Obfuscation", "Class conversion JSON created/updated"); - - if ((options.includeAnyMatchRegexes && options.includeAnyMatchRegexes.length > 0) - || (options.excludeAnyMatchRegexes && options.excludeAnyMatchRegexes.length > 0)) { - log("warn", "Obfuscation", "'includeAnyMatchRegexes' and 'excludeAnyMatchRegexes' are deprecated, please use whiteListedFolderPaths and blackListedFolderPaths instead"); - } + // Save the conversion table to a JSON file + const jsonPath = path.join( + process.cwd(), + options.classConversionJsonFolderPath, + "conversion.json", + ); + console.log({ jsonPath }); + fs.writeFileSync(jsonPath, JSON.stringify(conversionTables, null, 2)); + log( + "success", + "CSS obfuscation:", + `Saved conversion table to ${getFilenameFromPath(jsonPath)}`, + ); + + // Use the same unified paths for replacing JSON keys in files replaceJsonKeysInFiles({ + conversionTables: conversionTables, targetFolder: options.buildFolderPath, allowExtensions: options.allowExtensions, - selectorConversionJsonFolderPath: options.classConversionJsonFolderPath, contentIgnoreRegexes: options.contentIgnoreRegexes, - whiteListedFolderPaths: [...options.whiteListedFolderPaths, ...(options.includeAnyMatchRegexes || [])], - blackListedFolderPaths: [...options.blackListedFolderPaths, ...(options.excludeAnyMatchRegexes || [])], + whiteListedFolderPaths: options.whiteListedFolderPaths, + blackListedFolderPaths: options.blackListedFolderPaths, enableObfuscateMarkerClasses: options.enableMarkers, obfuscateMarkerClasses: options.markers, - removeObfuscateMarkerClassesAfterObfuscated: options.removeMarkersAfterObfuscated, - removeOriginalCss: options.removeOriginalCss, + removeObfuscateMarkerClassesAfterObfuscated: + options.removeMarkersAfterObfuscated, enableJsAst: options.enableJsAst, }); -} +}; -function obfuscateCli() { +export const obfuscateCli = async () => { const argv = yargs.option("config", { alias: "c", type: "string", - description: "Path to the config file" + description: "Path to the config file", }).argv; - let configPath; + let configPath: string | undefined = undefined; // @ts-ignore if (argv.config) { @@ -100,8 +132,8 @@ function obfuscateCli() { } const config = new Config(configPath ? require(configPath) : undefined).get(); - obfuscate(config); + await obfuscate(config); log("success", "Obfuscation", "Completed~"); -} +}; -export { obfuscateCli, type OptionalOptions as Options }; +export type { OptionalOptions as Options }; diff --git a/src/types.ts b/src/types.ts index a45bdf6..6a58238 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,85 +1,86 @@ -type LogLevel = "debug" | "info" | "warn" | "error" | "success"; -type obfuscateMode = "random" | "simplify" | "simplify-seedable"; -type SelectorConversion = { [key: string]: string }; - -type Options = { - enable: boolean; - mode: obfuscateMode; - buildFolderPath: string; - classConversionJsonFolderPath: string; - refreshClassConversionJson: boolean; - - classLength: number; - classPrefix: string; - classSuffix: string; - classIgnore: (string | RegExp)[]; - allowExtensions: string[]; - contentIgnoreRegexes: RegExp[]; - - whiteListedFolderPaths: (string | RegExp)[]; - blackListedFolderPaths: (string | RegExp)[]; - /** - * @deprecated - */ - includeAnyMatchRegexes?: RegExp[]; - /** - * @deprecated - */ - excludeAnyMatchRegexes?: RegExp[]; - enableMarkers: boolean; - markers: string[]; - removeMarkersAfterObfuscated: boolean; - removeOriginalCss: boolean; - generatorSeed: string; - - enableJsAst: boolean; - - logLevel: LogLevel; -} -type OptionalOptions = { - enable?: boolean; - mode?: obfuscateMode; - buildFolderPath?: string; - classConversionJsonFolderPath?: string; - refreshClassConversionJson?: boolean; - - classLength?: number; - classPrefix?: string; - classSuffix?: string; - classIgnore?: string[]; - allowExtensions?: string[]; - contentIgnoreRegexes: RegExp[]; - - whiteListedFolderPaths?: (string | RegExp)[]; - blackListedFolderPaths?: (string | RegExp)[]; - /** - * @deprecated - */ - includeAnyMatchRegexes?: RegExp[]; - /** - * @deprecated - */ - excludeAnyMatchRegexes?: RegExp[]; - enableMarkers?: boolean; - markers?: string[]; - removeMarkersAfterObfuscated?: boolean; - removeOriginalCss?: boolean; - generatorSeed?: string; - - enableJsAst?: boolean; - - logLevel?: LogLevel; -} +import type { + ConversionTables, + PrefixSuffixOptions, + TransformProps, +} from "css-seasoning"; + +export type LogLevel = "debug" | "info" | "warn" | "error" | "success"; +export type obfuscateMode = "random" | "simplify"; +export type SelectorConversion = ConversionTables["selectors"]; + +export type Options = { + enable: boolean; + mode: obfuscateMode; + buildFolderPath: string; + classConversionJsonFolderPath: string; + refreshClassConversionJson: boolean; + + /** + * @deprecated Not longer used from v3.0.0 and will be removed in the next major version. + */ + classLength: number; + + /** + * @deprecated Merged into `prefix` from v3.0.0 and will be removed in the next major version. + */ + classPrefix: string; + /** + * @deprecated Merged into `suffix` from v3.0.0 and will be removed in the next major version. + */ + classSuffix: string; + + prefix: PrefixSuffixOptions; + suffix: PrefixSuffixOptions; + + /** + * @deprecated Merged into `ignorePatterns.selectors` from v3.0.0 and will be removed in the next major version. + */ + classIgnore: (string | RegExp)[]; + ignorePatterns: TransformProps["ignorePatterns"]; + + allowExtensions: string[]; + contentIgnoreRegexes: RegExp[]; -interface HtmlCharacterEntityConversion { - [key: string]: string; - } - -export { - type LogLevel, - type obfuscateMode, - type SelectorConversion, - type Options, - type OptionalOptions, - type HtmlCharacterEntityConversion -} \ No newline at end of file + whiteListedFolderPaths: (string | RegExp)[]; + blackListedFolderPaths: (string | RegExp)[]; + enableMarkers: boolean; + markers: string[]; + removeMarkersAfterObfuscated: boolean; + removeOriginalCss: boolean; + generatorSeed: string | undefined; + + enableJsAst: boolean; + + logLevel: LogLevel; +}; + +export type OptionalOptions = { + enable?: boolean; + mode?: obfuscateMode; + buildFolderPath?: string; + classConversionJsonFolderPath?: string; + refreshClassConversionJson?: boolean; + + classLength?: number; + classPrefix?: string; + classSuffix?: string; + classIgnore?: string[]; + allowExtensions?: string[]; + contentIgnoreRegexes: RegExp[]; + + whiteListedFolderPaths?: (string | RegExp)[]; + blackListedFolderPaths?: (string | RegExp)[]; + enableMarkers?: boolean; + markers?: string[]; + removeMarkersAfterObfuscated?: boolean; + removeOriginalCss?: boolean; + generatorSeed?: string; + + enableJsAst?: boolean; + + logLevel?: LogLevel; +}; + +export interface HtmlCharacterEntityConversion { + [key: string]: string; +} diff --git a/src/utils.test.ts b/src/utils.test.ts deleted file mode 100644 index 54505ee..0000000 --- a/src/utils.test.ts +++ /dev/null @@ -1,418 +0,0 @@ -import { describe, it, expect, test, beforeEach } from "vitest"; -import { - findContentBetweenMarker, - getFilenameFromPath, - getRandomString, - seedableSimplifyString, - duplicationCheck, - simplifyString, -} from "./utils"; -import NumberGenerator from "recoverable-random"; - - -//! ================================ -//! findContentBetweenMarker -//! ================================ - -describe("findContentBetweenMarker", () => { - - it("should return the correct content between markers", () => { - const content = `123{{4}5{67}8}901{2345678}9`; - const targetStr = '5'; - const openSymbol = '{'; - const closeSymbol = '}'; - - const expectedOutput = ["{4}5{67}8", "2345678"]; - - const result = findContentBetweenMarker(content, targetStr, openSymbol, closeSymbol); - expect(result).toEqual(expectedOutput); - }); - - // it('should return the correct content between (if marker length > 1)', () => { - // const content = '[Hello_0 [[Hello_1]]! Hello_2 [[Hello_3]]!]'; - // const targetStr = 'He'; - // const openSymbol = '[['; - // const closeSymbol = ']]'; - - // const expectedOutput = ['Hello_1', 'Hello_3']; - - // const result = findContentBetweenMarker(content, targetStr, openSymbol, closeSymbol); - // expect(result).toEqual(expectedOutput); - // }); -}); - - - -//! ================================ -//! getFilenameFromPath -//! ================================ - -describe("getFilenameFromPath", () => { - - test("should extract filename from a Unix-like path", () => { - // Act - const result = getFilenameFromPath("/home/user/documents/report.pdf"); - - // Assert - expect(result).toBe("report.pdf"); - }); - - test("should extract filename from a Windows-like path", () => { - // Act - const result = getFilenameFromPath("C:\\Users\\hokin\\report.pdf"); - - // Assert - expect(result).toBe("report.pdf"); - }); - - test("should handle filenames without an extension", () => { - // Act - const result = getFilenameFromPath("/home/user/documents/notes"); - - // Assert - expect(result).toBe("notes"); - }); - - test("should handle paths with multiple periods", () => { - // Act - const result = getFilenameFromPath("/home/user/documents/report.v1.0.pdf"); - - // Assert - expect(result).toBe("report.v1.0.pdf"); - }); - - test("should handle paths with no directory", () => { - // Act - const result = getFilenameFromPath("report.pdf"); - - // Assert - expect(result).toBe("report.pdf"); - }); - - test("should handle empty strings", () => { - // Act - const result = getFilenameFromPath(""); - - // Assert - expect(result).toBe(""); - }); - - test("should handle paths with only directories and no filename", () => { - // Act - const result = getFilenameFromPath("/home/user/documents/"); - - // Assert - expect(result).toBe(""); - }); - - test("should handle paths with special characters in the filename", () => { - // Act - const result = getFilenameFromPath("/home/user/documents/~$!%20report.pdf"); - - // Assert - expect(result).toBe("~$!%20report.pdf"); - }); - - test("should handle paths with a dot at the start", () => { - // Act - const result = getFilenameFromPath("/home/user/documents/.env"); - - // Assert - expect(result).toBe(".env"); - }); - - test("should handle paths with a space in the filename", () => { - // Act - const result = getFilenameFromPath("/home/user/documents/my report.pdf"); - - // Assert - expect(result).toBe("my report.pdf"); - }); - - test("should throw an error for non-string inputs", () => { - // Arrange - const input: any = null; - - // Act and Assert - expect(() => getFilenameFromPath(input)).toThrow(TypeError); - }); - -}); - -//! ================================ -//! getRandomString -//! ================================ - -describe("getRandomString", () => { - let rng: NumberGenerator; - - beforeEach(() => { - rng = new NumberGenerator(); - }); - - test("should generate a random string of a given length", () => { - // Arrange - const length = 10; - const seed = "testSeed"; - rng = new NumberGenerator(seed); // Mocked RNG for consistent results - - // Act - const result = getRandomString(length, seed); - - // Assert - expect(result.randomString).toHaveLength(length); - expect(result.randomString).toMatch(/^[a-z][a-z0-9-_]+$/); - }); - - test("should recover RNG state if state code is provided", () => { - // Arrange - const length = 10; - const seed = "testSeed"; - const stateCode = "someStateCode"; - rng = new NumberGenerator(seed); // Mocked RNG for consistent results - const initialStateCode = rng.getStateCode(); - - // Act - const result = getRandomString(length, seed, stateCode); - - // Assert - expect(result.rngStateCode).not.toBe(initialStateCode); - }); - - test("should throw an error if length is not a positive integer", () => { - // Arrange - const invalidLengths = [0, -1, 1.5, NaN, Infinity]; - - // Act & Assert - invalidLengths.forEach(length => { - expect(() => getRandomString(length as any)).toThrow(); - }); - }); - - test("should handle edge case where length is 1", () => { - // Arrange - const length = 1; - - // Act - const result = getRandomString(length); - - // Assert - expect(result.randomString).toHaveLength(length); - expect(result.randomString).toMatch(/^[a-z]$/); - }); - - test("should return a valid rngStateCode", () => { - // Arrange - const length = 10; - - // Act - const result = getRandomString(length); - - // Assert - expect(result.rngStateCode).toBeDefined(); - expect(typeof parseInt(result.rngStateCode)).toBe("number"); - }); -}); - -//! ================================ -//! seedableSimplifyString -//! ================================ - -describe("seedableSimplifyString", () => { - let rng: NumberGenerator; - - beforeEach(() => { - rng = new NumberGenerator("default-seed"); - }); - - test("should throw an error for empty string", () => { - // Act & Assert - expect(() => seedableSimplifyString("")).toThrow("String can not be empty"); - }); - - test("should return a simplified string and rng state code", () => { - // Arrange - const input = "a1e2i3o4u5w6_-"; - - // Act - const result = seedableSimplifyString(input, "seed"); - - // Assert - expect(result.randomString.length).toBeLessThan(input.length); - expect(typeof parseInt(result.rngStateCode)).toBe("number"); - }); - - test("should recover RNG state from state code", () => { - // Arrange - const stateCode = "some-state-code"; - const input = "test"; - rng.recoverState(stateCode); - const expectedStateCode = rng.getStateCode(); - - // Act - const result = seedableSimplifyString(input, undefined, stateCode); - - // Assert - expect(result.rngStateCode).toBe(expectedStateCode); - }); - - test("should handle strings without vowels or numbers", () => { - // Arrange - const input = "bcdfghjklmnpqrstvxyz"; - const expectedOutput = input; // No vowels or numbers to remove - - // Act - const result = seedableSimplifyString(input, "seed"); - - // Assert - expect(result.randomString).toBe(expectedOutput); - }); - - test("should handle strings with only vowels and numbers", () => { - // Arrange - const input = "aeiou12345"; - const expectedOutput = ""; // All characters should be removed - - // Act - const result = seedableSimplifyString(input, "seed"); - - // Assert - expect(result.randomString).toHaveLength(1); // Should contain one random character - }); -}); - - -//! ================================ -//! duplicationCheck -//! ================================ - -describe("duplicationCheck", () => { - - test("should return false for an array with no duplicates", () => { - // Arrange - const input = ["apple", "banana", "cherry"]; - - // Act - const result = duplicationCheck(input); - - // Assert - expect(result).toBe(false); - }); - - test("should return true for an array with duplicates", () => { - // Arrange - const input = ["apple", "banana", "apple"]; - - // Act - const result = duplicationCheck(input); - - // Assert - expect(result).toBe(true); - }); - - test("should return false for an empty array", () => { - // Arrange - const input: string[] = []; - - // Act - const result = duplicationCheck(input); - - // Assert - expect(result).toBe(false); - }); - - test("should return false for an array with one element", () => { - // Arrange - const input = ["apple"]; - - // Act - const result = duplicationCheck(input); - - // Assert - expect(result).toBe(false); - }); - - test("should return true for an array with all elements being the same", () => { - // Arrange - const input = ["apple", "apple", "apple"]; - - // Act - const result = duplicationCheck(input); - - // Assert - expect(result).toBe(true); - }); - - test("should handle case sensitivity properly", () => { - // Arrange - const input = ["apple", "Apple"]; - - // Act - const result = duplicationCheck(input); - - // Assert - expect(result).toBe(false); - }); - - test("should return true for an array with duplicates that are not adjacent", () => { - // Arrange - const input = ["apple", "banana", "cherry", "apple", "date"]; - - // Act - const result = duplicationCheck(input); - - // Assert - expect(result).toBe(true); - }); - - test("should return false for an array with similar but unique strings", () => { - // Arrange - const input = ["a", "ab", "abc", "abcd"]; - - // Act - const result = duplicationCheck(input); - - // Assert - expect(result).toBe(false); - }); -}); - - -//! ================================ -//! simplifyString -//! ================================ - -describe("simplifyString", () => { - - test.each([ - { position: 1, expected: "a" }, - { position: 26, expected: "z" }, - { position: 27, expected: "aa" }, - { position: 52, expected: "az" }, - { position: 53, expected: "ba" }, - { position: 702, expected: "zz" }, - { position: 703, expected: "aaa" }, - ])("returns correct string for position $position", ({ position, expected }) => { - // Act - const result = simplifyString(position); - - // Assert - expect(result).toBe(expected); - }); - - test("throws error for negative position", () => { - // Arrange - const input = -1; - - // Act & Assert - expect(() => simplifyString(input)).toThrow("Position must be a positive integer"); - }); - - test("throws error for non-integer position", () => { - // Arrange - const input = 27.5; - - // Act & Assert - expect(() => simplifyString(input)).toThrow("Position must be a positive integer"); - }); -}); \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index 510218a..84e6bfd 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,15 +1,50 @@ import fs from "node:fs"; import path from "node:path"; -import NumberGenerator from "recoverable-random"; -import type { - LogLevel, - SelectorConversion, - HtmlCharacterEntityConversion -} from "./types"; - -import { obfuscateCss } from "./handlers/css"; +import { type ConversionTables, cssEscape, cssUnescape } from "css-seasoning"; import { obfuscateHtmlClassNames } from "./handlers/html"; import { obfuscateJs } from "./handlers/js"; +import type { LogLevel, SelectorConversion } from "./types"; + +// Add a new function for path filtering +/** + * Checks if a path should be included based on whitelist and blacklist rules + * + * @param filePath - The file path to check + * @param whiteListedFolderPaths - Paths to include + * @param blackListedFolderPaths - Paths to exclude (higher priority than whitelist) + * @returns - True if the path should be included, false otherwise + */ +const shouldIncludePath = ( + filePath: string, + whiteListedFolderPaths: (string | RegExp)[] = [], + blackListedFolderPaths: (string | RegExp)[] = [], +): boolean => { + const normalizedPath = normalizePath(filePath); + + // Check if the path is blacklisted (higher priority) + const isBlacklisted = blackListedFolderPaths.some((excludePath) => { + if (typeof excludePath === "string") { + return normalizedPath.includes(excludePath); + } + return excludePath.test(normalizedPath); + }); + + if (isBlacklisted) { + return false; // Skip this file/directory + } + + // Check if the path is whitelisted (if whitelist is not empty) + const isWhitelisted = + whiteListedFolderPaths.length === 0 || + whiteListedFolderPaths.some((includePath) => { + if (typeof includePath === "string") { + return normalizedPath.includes(includePath); + } + return includePath.test(normalizedPath); + }); + + return isWhitelisted; +}; //! ==================== //! Log @@ -19,7 +54,7 @@ const issuer = "[next-css-obfuscator]"; let logLevel: LogLevel = "info"; const levels: LogLevel[] = ["debug", "info", "warn", "error", "success"]; -function log(type: LogLevel, task: string, data: any) { +export const log = (type: LogLevel, task: string, data: unknown) => { //ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js if (levels.indexOf(type) < levels.indexOf(logLevel)) { return; @@ -29,7 +64,14 @@ function log(type: LogLevel, task: string, data: any) { switch (type) { case "debug": - console.debug(mainColor, issuer, "[Debug] \x1b[37m", task, data, "\x1b[0m"); + console.debug( + mainColor, + issuer, + "[Debug] \x1b[37m", + task, + data, + "\x1b[0m", + ); break; case "info": console.info(mainColor, issuer, "πŸ—―οΈ \x1b[36m", task, data, "\x1b[0m"); @@ -47,11 +89,11 @@ function log(type: LogLevel, task: string, data: any) { console.log("'\x1b[0m'", issuer, task, data, "\x1b[0m"); break; } -} +}; -function setLogLevel(level: LogLevel) { +export const setLogLevel = (level: LogLevel) => { logLevel = level; -} +}; //! ==================== //! Constants @@ -69,52 +111,45 @@ function setLogLevel(level: LogLevel) { // }; //! ==================== -//! +//! //! ==================== -const usedKeyRegistery = new Set(); - +export const usedKeyRegistery = new Set(); +export const replaceJsonKeysInFiles = ({ + conversionTables, + targetFolder, + allowExtensions, -function replaceJsonKeysInFiles( - { - targetFolder, - allowExtensions, - selectorConversionJsonFolderPath, + contentIgnoreRegexes, - contentIgnoreRegexes, + whiteListedFolderPaths, + blackListedFolderPaths, + enableObfuscateMarkerClasses, + obfuscateMarkerClasses, + removeObfuscateMarkerClassesAfterObfuscated, - whiteListedFolderPaths, - blackListedFolderPaths, - enableObfuscateMarkerClasses, - obfuscateMarkerClasses, - removeObfuscateMarkerClassesAfterObfuscated, - removeOriginalCss, + enableJsAst, +}: { + conversionTables: ConversionTables; + targetFolder: string; + allowExtensions: string[]; - enableJsAst, - }: { - targetFolder: string, - allowExtensions: string[], - selectorConversionJsonFolderPath: string, + contentIgnoreRegexes: RegExp[]; - contentIgnoreRegexes: RegExp[], + whiteListedFolderPaths: (string | RegExp)[]; + blackListedFolderPaths: (string | RegExp)[]; + enableObfuscateMarkerClasses: boolean; + obfuscateMarkerClasses: string[]; + removeObfuscateMarkerClassesAfterObfuscated: boolean; - whiteListedFolderPaths: (string | RegExp)[], - blackListedFolderPaths: (string | RegExp)[], - enableObfuscateMarkerClasses: boolean, - obfuscateMarkerClasses: string[], - removeObfuscateMarkerClassesAfterObfuscated: boolean, - removeOriginalCss: boolean, - - enableJsAst: boolean, - }) { + enableJsAst: boolean; +}) => { //ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js - const classConversion: SelectorConversion = loadAndMergeJsonFiles(selectorConversionJsonFolderPath); - if (removeObfuscateMarkerClassesAfterObfuscated) { - obfuscateMarkerClasses.forEach(obfuscateMarkerClass => { - classConversion[`.${obfuscateMarkerClass}`] = ""; + obfuscateMarkerClasses.forEach((obfuscateMarkerClass) => { + conversionTables.selectors[cssEscape(`.${obfuscateMarkerClass}`)] = ""; }); } @@ -128,33 +163,15 @@ function replaceJsonKeysInFiles( fs.readdirSync(filePath).forEach((subFilePath) => { replaceJsonKeysInFile(path.join(filePath, subFilePath)); }); - } else if ( - allowExtensions.includes(fileExt) - ) { - - let isTargetFile = true; - if (whiteListedFolderPaths.length > 0) { - isTargetFile = whiteListedFolderPaths.some((incloudPath) => { - if (typeof incloudPath === "string") { - return normalizePath(filePath).includes(incloudPath); - } - const regex = new RegExp(incloudPath); - return regex.test(normalizePath(filePath)); - }); - } - if (blackListedFolderPaths.length > 0) { - const res = !blackListedFolderPaths.some((incloudPath) => { - if (typeof incloudPath === "string") { - return normalizePath(filePath).includes(incloudPath); - } - const regex = new RegExp(incloudPath); - return regex.test(normalizePath(filePath)); - }); - if (!res) { - isTargetFile = false; - } - } - if (!isTargetFile) { + } else if (allowExtensions.includes(fileExt)) { + // Use the unified path filtering function + if ( + !shouldIncludePath( + filePath, + whiteListedFolderPaths, + blackListedFolderPaths, + ) + ) { return; } @@ -163,76 +180,51 @@ function replaceJsonKeysInFiles( const fileContentOriginal = fileContent; if (enableObfuscateMarkerClasses) { - obfuscateMarkerClasses.forEach(obfuscateMarkerClass => { + obfuscateMarkerClasses.forEach((obfuscateMarkerClass) => { const isHtml = [".html"].includes(fileExt); if (isHtml) { // filter all html // ref: https://stackoverflow.com/a/56102604 - const htmlRegex = new RegExp(`(<(.*)>(.*)<\/([^br][A-Za-z0-9]+)>)`, 'g'); + // biome-ignore lint/complexity/useRegexLiterals: using regex literals herer will cause typing issues + const htmlRegex = new RegExp( + "(<(.*)>(.*))", + "g", + ); const htmlMatch = fileContent.match(htmlRegex); if (htmlMatch) { const htmlOriginal = htmlMatch[0]; - // let html = htmlOriginal; - - //! rollback - // const tagContents = findHtmlTagContentsByClass(html, obfuscateMarkerClass); - // tagContents.forEach(tagContent => { - // const { obfuscatedContent, usedKeys } = obfuscateKeys(classConversion, tagContent, contentIgnoreRegexes); - // addKeysToRegistery(usedKeys); - // if (tagContent !== obfuscatedContent) { - // html = html.replace(tagContent, obfuscatedContent); - // log("debug", `Obscured keys under HTML tag in file:`, normalizePath(filePath)); - // } - // }); - - //! rollback - // const scriptTagContents = findHtmlTagContents(html, "script"); - // scriptTagContents.forEach(scriptTagContent => { - // const obfuscateScriptContent = obfuscateJs( - // scriptTagContent, - // obfuscateMarkerClass, - // classConversion, - // filePath, - // contentIgnoreRegexes, - // enableJsAst - // ); - // if (scriptTagContent !== obfuscateScriptContent) { - // html = html.replace(scriptTagContent, obfuscateScriptContent); - // log("debug", `Obscured keys under HTML script tag in file:`, normalizePath(filePath)); - // } - // }); - - //! rollback - // if (htmlOriginal !== html) { - // fileContent = fileContent.replace(htmlOriginal, html); - // } - - //! NEW const { obfuscatedContent, usedKeys } = obfuscateHtmlClassNames({ html: htmlOriginal, - selectorConversion: classConversion, + selectorConversion: conversionTables.selectors, obfuscateMarkerClass: obfuscateMarkerClass, contentIgnoreRegexes: contentIgnoreRegexes, }); addKeysToRegistery(usedKeys); if (htmlOriginal !== obfuscatedContent) { - fileContent = fileContent.replace(htmlOriginal, obfuscatedContent); + fileContent = fileContent.replace( + htmlOriginal, + obfuscatedContent, + ); } } } else { - const obfuscateScriptContent = obfuscateJs(fileContent, + const obfuscateScriptContent = obfuscateJs( + fileContent, obfuscateMarkerClass, - classConversion, + conversionTables.selectors, filePath, contentIgnoreRegexes, - enableJsAst + enableJsAst, ); if (fileContent !== obfuscateScriptContent) { fileContent = obfuscateScriptContent; - log("debug", `Obscured keys in JS like content file:`, normalizePath(filePath)); + log( + "debug", + "Obscured keys in JS like content file:", + normalizePath(filePath), + ); } } - }); } else { /* Handle Full Obfuscation */ @@ -241,20 +233,24 @@ function replaceJsonKeysInFiles( const obfuscateScriptContent = obfuscateJs( fileContent, enableJsAst ? "" : "jsx", - classConversion, + conversionTables.selectors, filePath, contentIgnoreRegexes, - enableJsAst + enableJsAst, ); if (fileContent !== obfuscateScriptContent) { fileContent = obfuscateScriptContent; - log("debug", `Obscured keys in JSX related file:`, normalizePath(filePath)); + log( + "debug", + "Obscured keys in JSX related file:", + normalizePath(filePath), + ); } } else if ([".html"].includes(fileExt)) { //! NEW const { obfuscatedContent, usedKeys } = obfuscateHtmlClassNames({ html: fileContent, - selectorConversion: classConversion, + selectorConversion: conversionTables.selectors, contentIgnoreRegexes: contentIgnoreRegexes, }); @@ -262,12 +258,11 @@ function replaceJsonKeysInFiles( addKeysToRegistery(usedKeys); } else { const { obfuscatedContent, usedKeys } = obfuscateKeys( - classConversion, + conversionTables.selectors, fileContent, - contentIgnoreRegexes + contentIgnoreRegexes, ); - fileContent = obfuscatedContent; addKeysToRegistery(usedKeys); } @@ -277,54 +272,50 @@ function replaceJsonKeysInFiles( log("success", "Data obfuscated:", normalizePath(filePath)); fs.writeFileSync(filePath, fileContent); } - } else if (fileExt === ".css") { cssPaths.push(filePath); } - } + }; // Process all files in the directory excluding .css files replaceJsonKeysInFile(targetFolder); // Obfuscate CSS files - cssPaths.forEach((cssPath) => { - obfuscateCss(classConversion, cssPath, removeOriginalCss, !enableObfuscateMarkerClasses); - }); - -} + // cssPaths.forEach(async (cssPath) => { + // await obfuscateCss(classConversion, cssPath, removeOriginalCss, !enableObfuscateMarkerClasses); + // }); +}; -function obfuscateKeys( +export const obfuscateKeys = ( selectorConversion: SelectorConversion, fileContent: string, contentIgnoreRegexes: RegExp[] = [], - useHtmlEntity: boolean = false -) { +) => { //ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js const usedKeys = new Set(); Object.keys(selectorConversion).forEach((key) => { const fileContentOriginal = fileContent; // let keyUse = escapeRegExp(key.slice(1).replace(/\\/g, "")); - let keyUse = key.slice(1); + let keyUse = cssUnescape(key).slice(1); - //! deprecated - // if (useHtmlEntity) { - // const regex = new RegExp(`(${Object.keys(HTML_CHARACTER_ENTITY_CONVERSION).join("|")})`, "g"); - // keyUse = keyUse.replace(regex, (m: string) => { - // return HTML_CHARACTER_ENTITY_CONVERSION[m] - // }); - // } - keyUse = escapeRegExp(keyUse.replace(/\\/g, "")); + keyUse = escapeRegExp(keyUse.replace(/\\/g, "")); // escape the key //? sample: "text-sm w-full\n text-right\n p-2 flex gap-2 hover:bg-gray-100 dark:hover:bg-red-700 text-right" - let exactMatchRegex = new RegExp(`([\\s"'\\\`]|^)(${keyUse})(?=$|[\\s"'\\\`]|\\\\n|\\\\",|\\\\"})`, 'g'); // match exact wording & avoid ` ' "" + const exactMatchRegex = new RegExp( + `([\\s"'\\\`]|^)(${keyUse})(?=$|[\\s"'\\\`]|\\\\n|\\\\",|\\\\"})`, + "g", + ); // match exact wording & avoid ` ' "" // exactMatchRegex = new RegExp(`([\\s"'\\\`]|^)(${keyUse})(?=$|[\\s"'\\\`])`, 'g'); // match exact wording & avoid ` ' "" - const replacement = `$1` + selectorConversion[key].slice(1).replace(/\\/g, ""); + const replacement = `$1${selectorConversion[key].slice(1).replace(/\\/g, "").slice(1)}`; const matches = fileContent.match(exactMatchRegex); const originalObscuredContentPairs = matches?.map((match) => { - return { originalContent: match, obscuredContent: match.replace(exactMatchRegex, replacement) }; + return { + originalContent: match, + obscuredContent: match.replace(exactMatchRegex, replacement), + }; }); fileContent = fileContent.replace(exactMatchRegex, replacement); // capture preceding space @@ -334,87 +325,98 @@ function obfuscateKeys( originalContentFragments?.map((originalContentFragment) => { originalObscuredContentPairs?.map((pair) => { - if (originalContentFragments?.some((fragment) => fragment.includes(pair.originalContent))) { - log("debug", "Obscured keys:", `Ignored ${pair.originalContent} at ${originalContentFragment}`); - fileContent = fileContent.replace(originalContentFragment.replace(pair.originalContent, pair.obscuredContent), originalContentFragment); + if ( + originalContentFragments?.some((fragment) => + fragment.includes(pair.originalContent), + ) + ) { + log( + "debug", + "Obscured keys:", + `Ignored ${pair.originalContent} at ${originalContentFragment}`, + ); + fileContent = fileContent.replace( + originalContentFragment.replace( + pair.originalContent, + pair.obscuredContent, + ), + originalContentFragment, + ); } }); }); }); } - if (fileContentOriginal !== fileContent && !usedKeys.has(key)) { usedKeys.add(key); } }); return { obfuscatedContent: fileContent, usedKeys: usedKeys }; -} +}; -function escapeRegExp(str: string) { +const escapeRegExp = (str: string) => { //ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js - return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string -} + return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string +}; /** * Get the filename from a file path * @param filePath - The path to the file * @returns The filename of the file */ -function getFilenameFromPath(filePath: string) { +export const getFilenameFromPath = (filePath: string) => { //ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js - return filePath.replace(/^.*[\\/]/, ''); -} + return filePath.replace(/^.*[\\/]/, ""); +}; /** * Normalizes a file path by replacing backslashes with forward slashes. - * + * * @param filePath - The file path to normalize. * @returns The normalized file path. - * + * * @example * // Returns: 'c:/Users/next-css-obfuscator/src/utils.ts' * normalizePath('c:\\Users\\next-css-obfuscator\\src\\utils.ts'); - * + * * @example * // Returns: 'path/to/file' * normalizePath('path\\to\\file'); */ -function normalizePath(filePath: string) { +export const normalizePath = (filePath: string) => { return filePath.replace(/\\/g, "/"); -} - -function loadAndMergeJsonFiles(jsonFolderPath: string) { - //ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js - const jsonFiles: { [key: string]: any } = {}; - - fs.readdirSync(jsonFolderPath).forEach((file: string) => { - const filePath = path.join(jsonFolderPath, file); - const fileData = JSON.parse(fs.readFileSync(filePath, "utf-8")); - Object.assign(jsonFiles, fileData); - }); - - return jsonFiles; -} +}; /** - * - * @param content - * @param openMarker - * @param closeMarker - * @param startPosition + * + * @param content + * @param openMarker + * @param closeMarker + * @param startPosition * @param direction - if "forward", the function will search the closest closeMarker after the startPosition, if "backward", the function will search the closest openMarker before the startPosition - * @returns + * @returns */ -function findClosestSymbolPosition(content: string, openMarker: string, closeMarker: string, startPosition: number = 0, direction: "forward" | "backward" = "backward") { +export const findClosestSymbolPosition = ( + content: string, + openMarker: string, + closeMarker: string, + startPosition = 0, + direction: "forward" | "backward" = "backward", +) => { let level = 0; let currentPos = startPosition; if (direction === "backward") { while (currentPos >= 0 && level >= 0) { - if (content.slice(currentPos, currentPos + openMarker.length) === openMarker) { + if ( + content.slice(currentPos, currentPos + openMarker.length) === openMarker + ) { level--; - } else if (content.slice(currentPos, currentPos + closeMarker.length) === closeMarker) { + } else if ( + content.slice(currentPos, currentPos + closeMarker.length) === + closeMarker + ) { level++; } currentPos--; @@ -425,9 +427,14 @@ function findClosestSymbolPosition(content: string, openMarker: string, closeMar } } else { while (currentPos < content.length && level >= 0) { - if (content.slice(currentPos, currentPos + openMarker.length) === openMarker) { + if ( + content.slice(currentPos, currentPos + openMarker.length) === openMarker + ) { level++; - } else if (content.slice(currentPos, currentPos + closeMarker.length) === closeMarker) { + } else if ( + content.slice(currentPos, currentPos + closeMarker.length) === + closeMarker + ) { level--; } currentPos++; @@ -439,9 +446,14 @@ function findClosestSymbolPosition(content: string, openMarker: string, closeMar } return currentPos; -} +}; -function findContentBetweenMarker(content: string, targetStr: string, openMarker: string, closeMarker: string) { +export const findContentBetweenMarker = ( + content: string, + targetStr: string, + openMarker: string, + closeMarker: string, +) => { if (openMarker === closeMarker) { throw new Error("openMarker and closeMarker can not be the same"); } @@ -449,8 +461,20 @@ function findContentBetweenMarker(content: string, targetStr: string, openMarker let targetStrPosition = content.indexOf(targetStr); const truncatedContents: string[] = []; while (targetStrPosition !== -1 && targetStrPosition < content.length) { - const openPos = findClosestSymbolPosition(content, openMarker, closeMarker, targetStrPosition, "backward"); - const closePos = findClosestSymbolPosition(content, openMarker, closeMarker, targetStrPosition, "forward"); + const openPos = findClosestSymbolPosition( + content, + openMarker, + closeMarker, + targetStrPosition, + "backward", + ); + const closePos = findClosestSymbolPosition( + content, + openMarker, + closeMarker, + targetStrPosition, + "forward", + ); if (openPos === -1 && closePos === -1) { break; @@ -466,36 +490,53 @@ function findContentBetweenMarker(content: string, targetStr: string, openMarker } return truncatedContents; -} +}; -function addKeysToRegistery(usedKeys: Set | string[]) { +export const addKeysToRegistery = (usedKeys: Set | string[]) => { usedKeys.forEach((key) => { usedKeyRegistery.add(key); }); -} +}; /** - * Find all files with the specified extension in the build folder - * @param ext - the extension of the files to find (e.g. .css) "." is required - * @param targetFolderPath - the path to the folder to start searching from - * @returns - an array of file relative paths + * Find all files with the specified extension in the build folder. + * + * @param ext - the extension of the files to find (e.g. .css) "." is required. + * @param targetFolderPath - the path to the folder to start searching from. + * @param options - optional parameters. + * @param options.whiteListedFolderPaths - an array of folder paths to include in the search. + * @param options.blackListedFolderPaths - an array of folder paths to exclude from the search. Higher priority than whiteListedFolderPaths. + * @returns - an array of file relative paths. */ -function findAllFilesWithExt(ext: string, targetFolderPath: string): string[] { +export const findAllFilesWithExt = ( + ext: string, + targetFolderPath: string, + options?: { + whiteListedFolderPaths?: (string | RegExp)[]; + blackListedFolderPaths?: (string | RegExp)[]; + }, +): string[] => { if (!fs.existsSync(targetFolderPath)) { return []; } const targetExtFiles: string[] = []; + const whiteList = options?.whiteListedFolderPaths || []; + const blackList = options?.blackListedFolderPaths || []; - function findCssFiles(dir: string) { + const findFiles = (dir: string) => { const files = fs.readdirSync(dir); files.forEach((file) => { - const filePath = normalizePath(path.join(dir, file)); + const filePath = path.join(dir, file); + + if (!shouldIncludePath(filePath, whiteList, blackList)) { + return; // Skip this file/directory + } if (fs.statSync(filePath).isDirectory()) { - // if it's a directory, recursively search for CSS files - findCssFiles(filePath); + // if it's a directory, recursively search for files + findFiles(filePath); } else { // check if the file has the specified extension if (file.endsWith(ext)) { @@ -503,144 +544,80 @@ function findAllFilesWithExt(ext: string, targetFolderPath: string): string[] { } } }); - } - - // start searching for CSS files from the specified directory - findCssFiles(targetFolderPath); - - return targetExtFiles; -} - -let rng: NumberGenerator | undefined = undefined; - -function getRandomString(length: number, seed?: string, rngStateCode?: string, str?: string) { - if (length <= 0 || !Number.isInteger(length)) { - throw new Error("Length must be a positive integer"); - } - - if (!rng) { - rng = new NumberGenerator(seed); - } - if (rngStateCode) { - rng.recoverState(rngStateCode); - } - - let rn = rng.random(0, 1, true); - if (str && seed) { - // can create a more collision resistant "random number" but in fact it's not random number - rn = Number.parseFloat(`0.${NumberGenerator.stringToSeed(str) + NumberGenerator.stringToSeed(seed)}`); - } - - //ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js - // Generate a random string of characters with the specified length - const randomString = rn.toString(36).substring(2, length - 1 + 2); - // Combine the random string with a prefix to make it a valid class name (starts with a letter, contains only letters, digits, hyphens, and underscores) - const randomLetter = String.fromCharCode(Math.floor(rng.random(0, 1, true) * 26) + 97); // 97 is the ASCII code for lowercase 'a' - return { - rngStateCode: rng.getStateCode(), - randomString: `${randomLetter}${randomString}`, }; -} - -/** - * - * @param str - * @param seed - * @param rngStateCode - * @returns - */ -function seedableSimplifyString(str: string, seed?: string, rngStateCode?: string) { - if (!str) { - throw new Error("String can not be empty"); - } - if (!rng) { - rng = new NumberGenerator(seed); - } - if (rngStateCode) { - rng.recoverState(rngStateCode); - } - - //ref: https://github.com/n4j1Br4ch1D/postcss-obfuscator/blob/main/utils.js - const tempStr = str.replace(/[aeiouw\d_-]/gi, ""); - - return { - rngStateCode: rng.getStateCode(), - randomString: tempStr.length < 1 - ? String.fromCharCode(Math.floor(rng.random(0, 1, true) * 26) + 97) + tempStr - : tempStr, - }; -} - -/** - * Get a simplified string from a number - * @param alphabetPoistion (starting from 1) - * @returns alphabet string - * - * @example - * simplifyString(1) // returns "a" - * simplifyString(26) // returns "z" - * simplifyString(27) // returns "aa" - * simplifyString(52) // returns "az" - * simplifyString(53) // returns "ba" - */ -function simplifyString(alphabetPoistion: number) { - if (alphabetPoistion <= 0 || !Number.isInteger(alphabetPoistion)) { - throw new Error("Position must be a positive integer"); - } - let dividend = alphabetPoistion; - let columnName = ""; - let modulo = 0; + // start searching for files from the specified directory + findFiles(targetFolderPath); - while (dividend > 0) { - modulo = (dividend - 1) % 26; - columnName = String.fromCharCode(97 + modulo) + columnName; - dividend = Math.floor((dividend - modulo) / 26); - } - - return columnName; -} + return targetExtFiles; +}; -function replaceFirstMatch(source: string, find: string, replace: string): string { +export const replaceFirstMatch = ( + source: string, + find: string, + replace: string, +): string => { const index = source.indexOf(find); if (index !== -1) { return source.slice(0, index) + replace + source.slice(index + find.length); } return source; -} +}; /** * Check if there are any duplicates in an array of strings * @param arr - an array of strings * @returns - true if there are any duplicates, false otherwise */ -function duplicationCheck(arr: string[]) { +export const duplicationCheck = (arr: string[]) => { const set = new Set(arr); return arr.length !== set.size; -} - - -function createKey(str: string) { - const b64 = Buffer.from(str).toString("base64").replace(/=/g, ""); - return `{{{{{{${b64}}}}}}}`; -} - -function decodeKey(str: string) { - const regex = /{{{{{{([\w\+\/]+)}}}}}}/g; - str = str.replace(regex, (match, p1) => { - // Calculate the number of '=' needed - const padding = p1.length % 4 === 0 ? 0 : 4 - (p1.length % 4); - // Add back the '=' - const b64 = p1 + "=".repeat(padding); - return Buffer.from(b64, "base64").toString("ascii"); +}; + +/** + * Convert a string to a number by summing the char codes of each character + * + * @param str - The string to convert + * @returns The sum of the char codes of each character in the string + * + * @example + * stringToNumber("abc") // returns 294 (97 + 98 + 99) + * stringToNumber("hello") // returns 532 (104 + 101 + 108 + 108 + 111) + */ +export const stringToNumber = (str: string) => { + return str.split("").reduce((acc, char) => { + return acc + char.charCodeAt(0); + }, 0); +}; + +/** + * Loads and merges all JSON files (Conversion Tables) in the specified folder. + * + * @param folderPath - The folder path to load the conversion tables from. + * @returns ConversionTables - The merged conversion tables. + */ +export const loadConversionTables = (folderPath: string): ConversionTables => { + const tables: ConversionTables = { + idents: {}, + selectors: {}, + }; + + fs.readdirSync(folderPath).forEach((file: string) => { + const filePath = path.join(folderPath, file); + const fileData = JSON.parse(fs.readFileSync(filePath, "utf-8")); + + if ( + Object.keys(fileData).includes("idents") && + Object.keys(fileData).includes("selectors") + ) { + Object.assign(tables.idents, fileData.idents); + Object.assign(tables.selectors, fileData.selectors); + } else { + // if the file doesn't have ident, it should be selector + //? For backward compatibility + Object.assign(tables.selectors, fileData); + } }); - return str; -} - -export { - getFilenameFromPath, log, normalizePath, loadAndMergeJsonFiles - , replaceJsonKeysInFiles, setLogLevel, findContentBetweenMarker, replaceFirstMatch - , findAllFilesWithExt, getRandomString, seedableSimplifyString, usedKeyRegistery - , obfuscateKeys, findClosestSymbolPosition, addKeysToRegistery, duplicationCheck - , createKey, decodeKey, simplifyString + + return tables; }; diff --git a/tsconfig.json b/tsconfig.json index 132c89a..a719f75 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,7 @@ "esModuleInterop": true, "skipLibCheck": true, "moduleResolution": "node", - "newLine": "LF", + "newLine": "LF" }, "exclude": [ "node_modules", @@ -23,6 +23,7 @@ "bin", "patched-postcss-obfuscator", "demos", - "src/*.test.*" + "src/*.test.*", + "release.config.cjs" ] -} \ No newline at end of file +}