├── .github ├── renovate.json5 └── workflows │ ├── release.yml │ └── test.yml ├── .gitignore ├── .npmrc ├── .vscode ├── extensions.json └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── biome.json ├── package.json ├── playground ├── package.json ├── rsbuild.config.ts └── src │ ├── index.css │ └── index.js ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── rslib.config.ts ├── src ├── Set.prototype.isSubsetOf.ts ├── TailwindCSSRspackPlugin.ts └── index.ts ├── test ├── basic │ ├── index.test.ts │ └── src │ │ └── index.js ├── cjs │ ├── config │ │ ├── package.json │ │ └── tailwind.config.js │ ├── index.test.ts │ └── src │ │ └── index.js ├── config │ ├── config │ │ └── tailwind.config.js │ ├── index.test.ts │ └── src │ │ └── index.js ├── exclude-include │ ├── index.test.ts │ └── src │ │ ├── exclude.js │ │ ├── include.jsx │ │ ├── index.js │ │ ├── not-exclude.js │ │ └── not-include.ts ├── exclude │ ├── index.test.ts │ └── src │ │ ├── exclude.js │ │ ├── index.js │ │ └── not-exclude.js ├── helper.ts ├── include │ ├── index.test.ts │ └── src │ │ ├── include.jsx │ │ ├── index.js │ │ └── not-include.ts ├── isSubsetOf.test.ts ├── multi-entries │ ├── a.js │ ├── b.js │ ├── c.js │ ├── d.js │ ├── e.js │ └── index.test.ts ├── postcss-config │ ├── flex-to-grid.js │ ├── index.test.ts │ ├── postcss.config.js │ └── src │ │ └── index.js ├── tools-postcss │ ├── flex-to-grid.js │ ├── index.test.ts │ └── src │ │ └── index.js └── with-resource-query │ ├── index.test.ts │ └── src │ └── index.js └── tsconfig.json /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | $schema: 'https://docs.renovatebot.com/renovate-schema.json', 3 | extends: [ 4 | 'config:recommended', 5 | 'schedule:monthly', 6 | 'group:allNonMajor', 7 | ], 8 | rangeStrategy: 'bump', 9 | packageRules: [ 10 | { 11 | matchDepTypes: [ 12 | 'peerDependencies', 13 | ], 14 | enabled: false, 15 | }, 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This action will publish the package to npm and create a GitHub release. 2 | name: Release 3 | 4 | on: 5 | # Run `npm run bump` to bump the version and create a git tag. 6 | push: 7 | tags: 8 | - "v*" 9 | 10 | workflow_dispatch: 11 | 12 | permissions: 13 | contents: write 14 | id-token: write 15 | 16 | jobs: 17 | publish: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | 23 | - name: Install Pnpm 24 | run: npm i -g corepack@latest --force && corepack enable 25 | 26 | - name: Setup Node.js 27 | uses: actions/setup-node@v4 28 | with: 29 | node-version: 22 30 | cache: "pnpm" 31 | 32 | - name: Install Dependencies 33 | run: pnpm install 34 | 35 | - name: Publish 36 | uses: JS-DevTools/npm-publish@v3 37 | with: 38 | token: ${{ secrets.NPM_TOKEN }} 39 | 40 | - name: Create GitHub Release 41 | uses: ncipollo/release-action@v1 42 | with: 43 | generateReleaseNotes: "true" 44 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | # Controls when the action will run. 4 | on: 5 | # Triggers the workflow on pull request events but only for the main branch 6 | pull_request: 7 | branches: [main] 8 | push: 9 | branches: [main] 10 | # Allows you to run this workflow manually from the Actions tab 11 | workflow_dispatch: 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | test: 16 | runs-on: ${{ matrix.os }} 17 | name: Test tailwindcss@${{ matrix.tailwindcss }} on ${{ matrix.os }} 18 | strategy: 19 | matrix: 20 | os: [ubuntu-latest, windows-latest] 21 | tailwindcss: 22 | - "^3" 23 | - "3.1.0" # The fist version that support `options.config`. 24 | 25 | # Steps represent a sequence of tasks that will be executed as part of the job 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v4 29 | 30 | - name: Install Pnpm 31 | run: npm i -g corepack@latest --force && corepack enable 32 | 33 | - name: Setup Node.js 34 | uses: actions/setup-node@v4 35 | with: 36 | node-version: 22 37 | cache: "pnpm" 38 | 39 | - name: Install Dependencies 40 | run: pnpm install && npx playwright install chromium 41 | 42 | - name: Install tailwindcss@${{ matrix.tailwindcss }} 43 | if: ${{ matrix.tailwindcss }} != "latest" 44 | # Tailwind CSS <= v3.4.0 does not have correct TypeScript definition, which will make `rslib build` fail. 45 | continue-on-error: true 46 | run: pnpm add -D -w tailwindcss@${{ matrix.tailwindcss }} 47 | 48 | - name: Run Test 49 | run: pnpm run test 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local 2 | .DS_Store 3 | *.local 4 | *.log* 5 | 6 | # Dist 7 | node_modules 8 | dist/ 9 | test-results 10 | 11 | # IDE 12 | .vscode/* 13 | !.vscode/settings.json 14 | !.vscode/extensions.json 15 | .idea 16 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # Disable the default public-hoist-pattern(*-eslint-*, *-prettier-*) 2 | public-hoist-pattern= 3 | hoist-workspace-packages=true 4 | strict-peer-dependencies=true 5 | engine-strict=true 6 | registry=https://registry.npmjs.org/ 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["biomejs.biome"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.useIgnoreFiles": true, 3 | "[json]": { 4 | "editor.defaultFormatter": "biomejs.biome" 5 | }, 6 | "[typescript]": { 7 | "editor.defaultFormatter": "biomejs.biome" 8 | }, 9 | "[javascript]": { 10 | "editor.defaultFormatter": "biomejs.biome" 11 | }, 12 | "[javascriptreact]": { 13 | "editor.defaultFormatter": "biomejs.biome" 14 | }, 15 | "[css]": { 16 | "editor.defaultFormatter": "biomejs.biome" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 0.2.0 4 | 5 | - Fixed bug that other postcss plugins should not run before tailwindcss. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Rspack Contrib 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rsbuild-plugin-tailwindcss 2 | 3 | An Rsbuild plugin to integrate with [Tailwind CSS](https://tailwindcss.com/) V3. 4 | 5 |

6 | 7 | npm version 8 | 9 | license 10 | downloads 11 |

12 | 13 | ## Why? 14 | 15 | Tailwind CSS is able to remove unused CSS classes through [Content Configuration](https://tailwindcss.com/docs/content-configuration). However, its accuracy may be insufficient when: 16 | 17 | - Using multiple entries 18 | - Using a Tailwind CSS-based component library 19 | 20 | This plugin uses the Rspack module graph to override the `content` configuration with imported modules, generating Tailwind CSS output _**based on usage**_. 21 | 22 | ## Usage 23 | 24 | Install: 25 | 26 | ```bash 27 | npm add tailwindcss@3 rsbuild-plugin-tailwindcss -D 28 | ``` 29 | 30 | Add plugin to your `rsbuild.config.ts`: 31 | 32 | ```ts 33 | // rsbuild.config.ts 34 | import { pluginTailwindCSS } from "rsbuild-plugin-tailwindcss"; 35 | 36 | export default { 37 | plugins: [pluginTailwindCSS()], 38 | }; 39 | ``` 40 | 41 | ### Custom Tailwind CSS Configuration 42 | 43 | Create a `tailwind.config.js` file at the root of the project: 44 | 45 | ```js 46 | /** @type {import('tailwindcss').Config} */ 47 | export default { 48 | theme: { 49 | colors: { 50 | blue: "#1fb6ff", 51 | purple: "#7e5bef", 52 | pink: "#ff49db", 53 | orange: "#ff7849", 54 | green: "#13ce66", 55 | yellow: "#ffc82c", 56 | "gray-dark": "#273444", 57 | gray: "#8492a6", 58 | "gray-light": "#d3dce6", 59 | }, 60 | }, 61 | }; 62 | ``` 63 | 64 | This will be auto-loaded by Rsbuild and applied by `rsbuild-plugin-tailwindcss`. 65 | 66 | > [!NOTE] 67 | > 68 | > You don't need to add `content` in the `tailwind.config.js`. `rsbuild-plugin-tailwindcss` will add the imported modules for you. 69 | 70 | ### Custom PostCSS Options 71 | 72 | Create a `postcss.config.js` file at the root of the project: 73 | 74 | ```js 75 | export default { 76 | plugins: { 77 | cssnano: process.env["NODE_ENV"] === "production" ? {} : false, 78 | }, 79 | }; 80 | ``` 81 | 82 | > [!NOTE] 83 | > 84 | > You don't need to add `tailwindcss` in the `postcss.config.js`. `rsbuild-plugin-tailwindcss` will add the plugin for you. 85 | 86 | Or use the [`tools.postcss`](https://rsbuild.dev/config/tools/postcss) option in `rsbuild.config.ts`. 87 | 88 | ## Options 89 | 90 | ### `config` 91 | 92 | - Type: `string | undefined` 93 | - Default: `tailwind.config.js` 94 | 95 | The path to custom Tailwind CSS configuration. Could be a relative path from the root of the project or an absolute path. 96 | 97 | - Example: 98 | 99 | ```js 100 | // rsbuild.config.ts 101 | import { pluginTailwindCSS } from "rsbuild-plugin-tailwindcss"; 102 | 103 | export default { 104 | plugins: [ 105 | pluginTailwindCSS({ 106 | config: "./config/tailwind.config.js", 107 | }), 108 | ], 109 | }; 110 | ``` 111 | 112 | ### `exclude` / `include` 113 | 114 | - Type: `ReadonlyArray | string | RegExp | null | undefined` 115 | - Default: `undefined` 116 | 117 | These two options are used to filter which module to be processed by Tailwind CSS using [`picomatch`](https://github.com/micromatch/picomatch#globbing-features) pattern. 118 | 119 | If `include` is omitted or empty, all modules that do not match any of the `exclude` patterns will be included. 120 | Otherwise, only modules that match one or more of the `include` patterns and do not match any of the `exclude` patterns will be included. 121 | 122 | - Example: 123 | 124 | Include all `.js`, `.jsx`, `.ts`, `.tsx` files but exclude files in `./src/store` and `node_modules`: 125 | 126 | ```js 127 | // rsbuild.config.ts 128 | import { pluginTailwindCSS } from "@byted-lynx/plugin-tailwindcss"; 129 | 130 | export default { 131 | plugins: [ 132 | pluginTailwindCSS({ 133 | include: /\.[jt]sx?/, 134 | exclude: ["./src/store/**", /[\\/]node_modules[\\/]/], 135 | }), 136 | ], 137 | }; 138 | ``` 139 | 140 | Note that `picomatch` patterns are very similar to [`minimatch`](https://github.com/isaacs/minimatch#readme) patterns, and in most use cases, they are interchangeable. If you have more specific pattern matching needs, you can view [this comparison table](https://github.com/micromatch/picomatch#library-comparisons) to learn more about where the libraries differ. 141 | 142 | ## Debugging 143 | 144 | Use `DEBUG='rsbuild'` to enable debugging mode for the plugin. When debugging is enabled, the plugin will: 145 | 146 | 1. Save the generated Tailwind CSS configuration files in the `.rsbuild/` directory inside your project's output path. 147 | 2. Generate readable configuration files that include all modules being processed by Tailwind CSS. 148 | 149 | This is helpful for: 150 | 151 | - Inspecting which modules are included in the Tailwind CSS content scanning 152 | - Troubleshooting issues with CSS purging 153 | - Understanding how the plugin is generating configurations for each entry point 154 | 155 | Example: 156 | 157 | ```bash 158 | # For macOS/Linux 159 | DEBUG=rsbuild npm run build 160 | 161 | # For Windows (cmd) 162 | set DEBUG=rsbuild && npm run build 163 | 164 | # For Windows (PowerShell) 165 | $env:DEBUG="rsbuild"; npm run build 166 | ``` 167 | 168 | You can also use more specific debug patterns: 169 | 170 | - `DEBUG=rsbuild:tailwind` - Debug only the Tailwind CSS plugin 171 | - `DEBUG=rsbuild:*` - Debug all Rsbuild plugins 172 | - `DEBUG=*` - Debug everything 173 | 174 | ## Credits 175 | 176 | Thanks to: 177 | 178 | - [Tailwind CSS V4](https://tailwindcss.com/blog/tailwindcss-v4-alpha) for the idea of purge CSS by module graph. 179 | - The [purge-tailwind-plugin](https://github.com/hardfist/purge-tailwind-plugin) created by [@hardfist](https://github.com/hardfist) for the implementation of the Rspack plugin. 180 | - The [Rollup](https://github.com/rollup/) project created by [Rich Harris](https://github.com/Rich-Harris) and maintained by [Lukas Taegert-Atkinson](https://github.com/lukastaegert) for the implementaion of `exclude` and `include`. 181 | 182 | ## License 183 | 184 | [MIT](./LICENSE). 185 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", 3 | "organizeImports": { 4 | "enabled": true 5 | }, 6 | "vcs": { 7 | "enabled": true, 8 | "defaultBranch": "main", 9 | "clientKind": "git", 10 | "useIgnoreFile": true 11 | }, 12 | "formatter": { 13 | "indentStyle": "space" 14 | }, 15 | "javascript": { 16 | "formatter": { 17 | "quoteStyle": "single" 18 | } 19 | }, 20 | "css": { 21 | "formatter": { 22 | "enabled": true 23 | } 24 | }, 25 | "linter": { 26 | "enabled": true, 27 | "rules": { 28 | "recommended": true 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rsbuild-plugin-tailwindcss", 3 | "version": "0.2.1", 4 | "repository": "https://github.com/rspack-contrib/rsbuild-plugin-tailwindcss", 5 | "license": "MIT", 6 | "type": "module", 7 | "exports": { 8 | ".": { 9 | "types": "./dist/index.d.ts", 10 | "import": "./dist/index.js", 11 | "require": "./dist/index.cjs" 12 | } 13 | }, 14 | "main": "./dist/index.js", 15 | "module": "./dist/index.mjs", 16 | "types": "./dist/index.d.ts", 17 | "files": ["dist"], 18 | "scripts": { 19 | "build": "rslib build", 20 | "bump": "npx bumpp", 21 | "dev": "rslib build --watch", 22 | "lint": "biome check .", 23 | "lint:write": "biome check . --write", 24 | "prepare": "simple-git-hooks && npm run build", 25 | "test": "playwright test" 26 | }, 27 | "simple-git-hooks": { 28 | "pre-commit": "npm run lint:write" 29 | }, 30 | "devDependencies": { 31 | "@biomejs/biome": "^1.9.4", 32 | "@playwright/test": "^1.52.0", 33 | "@rollup/pluginutils": "^5.1.4", 34 | "@rsbuild/core": "^1.4.0-beta.1", 35 | "@rslib/core": "^0.9.1", 36 | "@rsbuild/webpack": "^1.3.2", 37 | "@types/node": "^22.15.29", 38 | "@types/semver": "^7.7.0", 39 | "playwright": "^1.52.0", 40 | "postcss": "^8.5.4", 41 | "semver": "^7.7.2", 42 | "simple-git-hooks": "^2.13.0", 43 | "tailwindcss": "^3.4.17", 44 | "typescript": "^5.8.3" 45 | }, 46 | "peerDependencies": { 47 | "@rsbuild/core": "^1.1.0", 48 | "tailwindcss": "^3.1.0" 49 | }, 50 | "peerDependenciesMeta": { 51 | "@rsbuild/core": { 52 | "optional": true 53 | } 54 | }, 55 | "packageManager": "pnpm@10.11.1", 56 | "publishConfig": { 57 | "access": "public", 58 | "provenance": true, 59 | "registry": "https://registry.npmjs.org/" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playground", 3 | "private": true, 4 | "version": "0.0.0", 5 | "devDependencies": { 6 | "rsbuild-plugin-tailwindcss": "workspace:*" 7 | }, 8 | "scripts": { 9 | "dev": "npx rsbuild dev", 10 | "build": "npx rsbuild build" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /playground/rsbuild.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@rsbuild/core'; 2 | import { pluginTailwindCSS } from 'rsbuild-plugin-tailwindcss'; 3 | 4 | export default defineConfig({ 5 | plugins: [pluginTailwindCSS()], 6 | }); 7 | -------------------------------------------------------------------------------- /playground/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind utilities; 2 | -------------------------------------------------------------------------------- /playground/src/index.js: -------------------------------------------------------------------------------- 1 | import './index.css'; 2 | 3 | document.querySelector('#root').innerHTML = ` 4 |
5 |

Vanilla Rsbuild

6 |

Start building amazing things with Rsbuild.

7 |
8 | `; 9 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | devDependencies: 11 | '@biomejs/biome': 12 | specifier: ^1.9.4 13 | version: 1.9.4 14 | '@playwright/test': 15 | specifier: ^1.52.0 16 | version: 1.52.0 17 | '@rollup/pluginutils': 18 | specifier: ^5.1.4 19 | version: 5.1.4 20 | '@rsbuild/core': 21 | specifier: ^1.4.0-beta.1 22 | version: 1.4.0-beta.1 23 | '@rsbuild/webpack': 24 | specifier: ^1.3.2 25 | version: 1.3.2(@rsbuild/core@1.4.0-beta.1)(@rspack/core@1.3.13(@swc/helpers@0.5.17)) 26 | '@rslib/core': 27 | specifier: ^0.9.1 28 | version: 0.9.1(typescript@5.8.3) 29 | '@types/node': 30 | specifier: ^22.15.29 31 | version: 22.15.29 32 | '@types/semver': 33 | specifier: ^7.7.0 34 | version: 7.7.0 35 | playwright: 36 | specifier: ^1.52.0 37 | version: 1.52.0 38 | postcss: 39 | specifier: ^8.5.4 40 | version: 8.5.4 41 | semver: 42 | specifier: ^7.7.2 43 | version: 7.7.2 44 | simple-git-hooks: 45 | specifier: ^2.13.0 46 | version: 2.13.0 47 | tailwindcss: 48 | specifier: ^3.4.17 49 | version: 3.4.17 50 | typescript: 51 | specifier: ^5.8.3 52 | version: 5.8.3 53 | 54 | playground: 55 | devDependencies: 56 | rsbuild-plugin-tailwindcss: 57 | specifier: workspace:* 58 | version: link:.. 59 | 60 | packages: 61 | 62 | '@alloc/quick-lru@5.2.0': 63 | resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} 64 | engines: {node: '>=10'} 65 | 66 | '@ast-grep/napi-darwin-arm64@0.37.0': 67 | resolution: {integrity: sha512-QAiIiaAbLvMEg/yBbyKn+p1gX2/FuaC0SMf7D7capm/oG4xGMzdeaQIcSosF4TCxxV+hIH4Bz9e4/u7w6Bnk3Q==} 68 | engines: {node: '>= 10'} 69 | cpu: [arm64] 70 | os: [darwin] 71 | 72 | '@ast-grep/napi-darwin-x64@0.37.0': 73 | resolution: {integrity: sha512-zvcvdgekd4ySV3zUbUp8HF5nk5zqwiMXTuVzTUdl/w08O7JjM6XPOIVT+d2o/MqwM9rsXdzdergY5oY2RdhSPA==} 74 | engines: {node: '>= 10'} 75 | cpu: [x64] 76 | os: [darwin] 77 | 78 | '@ast-grep/napi-linux-arm64-gnu@0.37.0': 79 | resolution: {integrity: sha512-L7Sj0lXy8X+BqSMgr1LB8cCoWk0rericdeu+dC8/c8zpsav5Oo2IQKY1PmiZ7H8IHoFBbURLf8iklY9wsD+cyA==} 80 | engines: {node: '>= 10'} 81 | cpu: [arm64] 82 | os: [linux] 83 | 84 | '@ast-grep/napi-linux-arm64-musl@0.37.0': 85 | resolution: {integrity: sha512-LF9sAvYy6es/OdyJDO3RwkX3I82Vkfsng1sqUBcoWC1jVb1wX5YVzHtpQox9JrEhGl+bNp7FYxB4Qba9OdA5GA==} 86 | engines: {node: '>= 10'} 87 | cpu: [arm64] 88 | os: [linux] 89 | 90 | '@ast-grep/napi-linux-x64-gnu@0.37.0': 91 | resolution: {integrity: sha512-TViz5/klqre6aSmJzswEIjApnGjJzstG/SE8VDWsrftMBMYt2PTu3MeluZVwzSqDao8doT/P+6U11dU05UOgxw==} 92 | engines: {node: '>= 10'} 93 | cpu: [x64] 94 | os: [linux] 95 | 96 | '@ast-grep/napi-linux-x64-musl@0.37.0': 97 | resolution: {integrity: sha512-/BcCH33S9E3ovOAEoxYngUNXgb+JLg991sdyiNP2bSoYd30a9RHrG7CYwW6fMgua3ijQ474eV6cq9yZO1bCpXg==} 98 | engines: {node: '>= 10'} 99 | cpu: [x64] 100 | os: [linux] 101 | 102 | '@ast-grep/napi-win32-arm64-msvc@0.37.0': 103 | resolution: {integrity: sha512-TjQA4cFoIEW2bgjLkaL9yqT4XWuuLa5MCNd0VCDhGRDMNQ9+rhwi9eLOWRaap3xzT7g+nlbcEHL3AkVCD2+b3A==} 104 | engines: {node: '>= 10'} 105 | cpu: [arm64] 106 | os: [win32] 107 | 108 | '@ast-grep/napi-win32-ia32-msvc@0.37.0': 109 | resolution: {integrity: sha512-uNmVka8fJCdYsyOlF9aZqQMLTatEYBynjChVTzUfFMDfmZ0bihs/YTqJVbkSm8TZM7CUX82apvn50z/dX5iWRA==} 110 | engines: {node: '>= 10'} 111 | cpu: [ia32] 112 | os: [win32] 113 | 114 | '@ast-grep/napi-win32-x64-msvc@0.37.0': 115 | resolution: {integrity: sha512-vCiFOT3hSCQuHHfZ933GAwnPzmL0G04JxQEsBRfqONywyT8bSdDc/ECpAfr3S9VcS4JZ9/F6tkePKW/Om2Dq2g==} 116 | engines: {node: '>= 10'} 117 | cpu: [x64] 118 | os: [win32] 119 | 120 | '@ast-grep/napi@0.37.0': 121 | resolution: {integrity: sha512-Hb4o6h1Pf6yRUAX07DR4JVY7dmQw+RVQMW5/m55GoiAT/VRoKCWBtIUPPOnqDVhbx1Cjfil9b6EDrgJsUAujEQ==} 122 | engines: {node: '>= 10'} 123 | 124 | '@biomejs/biome@1.9.4': 125 | resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} 126 | engines: {node: '>=14.21.3'} 127 | hasBin: true 128 | 129 | '@biomejs/cli-darwin-arm64@1.9.4': 130 | resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} 131 | engines: {node: '>=14.21.3'} 132 | cpu: [arm64] 133 | os: [darwin] 134 | 135 | '@biomejs/cli-darwin-x64@1.9.4': 136 | resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} 137 | engines: {node: '>=14.21.3'} 138 | cpu: [x64] 139 | os: [darwin] 140 | 141 | '@biomejs/cli-linux-arm64-musl@1.9.4': 142 | resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} 143 | engines: {node: '>=14.21.3'} 144 | cpu: [arm64] 145 | os: [linux] 146 | 147 | '@biomejs/cli-linux-arm64@1.9.4': 148 | resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} 149 | engines: {node: '>=14.21.3'} 150 | cpu: [arm64] 151 | os: [linux] 152 | 153 | '@biomejs/cli-linux-x64-musl@1.9.4': 154 | resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} 155 | engines: {node: '>=14.21.3'} 156 | cpu: [x64] 157 | os: [linux] 158 | 159 | '@biomejs/cli-linux-x64@1.9.4': 160 | resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} 161 | engines: {node: '>=14.21.3'} 162 | cpu: [x64] 163 | os: [linux] 164 | 165 | '@biomejs/cli-win32-arm64@1.9.4': 166 | resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} 167 | engines: {node: '>=14.21.3'} 168 | cpu: [arm64] 169 | os: [win32] 170 | 171 | '@biomejs/cli-win32-x64@1.9.4': 172 | resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} 173 | engines: {node: '>=14.21.3'} 174 | cpu: [x64] 175 | os: [win32] 176 | 177 | '@isaacs/cliui@8.0.2': 178 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 179 | engines: {node: '>=12'} 180 | 181 | '@jridgewell/gen-mapping@0.3.5': 182 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} 183 | engines: {node: '>=6.0.0'} 184 | 185 | '@jridgewell/resolve-uri@3.1.2': 186 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 187 | engines: {node: '>=6.0.0'} 188 | 189 | '@jridgewell/set-array@1.2.1': 190 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 191 | engines: {node: '>=6.0.0'} 192 | 193 | '@jridgewell/source-map@0.3.6': 194 | resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} 195 | 196 | '@jridgewell/sourcemap-codec@1.5.0': 197 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 198 | 199 | '@jridgewell/trace-mapping@0.3.25': 200 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 201 | 202 | '@module-federation/error-codes@0.14.0': 203 | resolution: {integrity: sha512-GGk+EoeSACJikZZyShnLshtq9E2eCrDWbRiB4QAFXCX4oYmGgFfzXlx59vMNwqTKPJWxkEGnPYacJMcr2YYjag==} 204 | 205 | '@module-federation/error-codes@0.14.3': 206 | resolution: {integrity: sha512-sBJ3XKU9g5Up31jFeXPFsD8AgORV7TLO/cCSMuRewSfgYbG/3vSKLJmfHrO6+PvjZSb9VyV2UaF02ojktW65vw==} 207 | 208 | '@module-federation/runtime-core@0.14.0': 209 | resolution: {integrity: sha512-fGE1Ro55zIFDp/CxQuRhKQ1pJvG7P0qvRm2N+4i8z++2bgDjcxnCKUqDJ8lLD+JfJQvUJf0tuSsJPgevzueD4g==} 210 | 211 | '@module-federation/runtime-core@0.14.3': 212 | resolution: {integrity: sha512-xMFQXflLVW/AJTWb4soAFP+LB4XuhE7ryiLIX8oTyUoBBgV6U2OPghnFljPjeXbud72O08NYlQ1qsHw1kN/V8Q==} 213 | 214 | '@module-federation/runtime-tools@0.14.0': 215 | resolution: {integrity: sha512-y/YN0c2DKsLETE+4EEbmYWjqF9G6ZwgZoDIPkaQ9p0pQu0V4YxzWfQagFFxR0RigYGuhJKmSU/rtNoHq+qF8jg==} 216 | 217 | '@module-federation/runtime-tools@0.14.3': 218 | resolution: {integrity: sha512-QBETX7iMYXdSa3JtqFlYU+YkpymxETZqyIIRiqg0gW+XGpH3jgU68yjrme2NBJp7URQi/CFZG8KWtfClk0Pjgw==} 219 | 220 | '@module-federation/runtime@0.14.0': 221 | resolution: {integrity: sha512-kR3cyHw/Y64SEa7mh4CHXOEQYY32LKLK75kJOmBroLNLO7/W01hMNAvGBYTedS7hWpVuefPk1aFZioy3q2VLdQ==} 222 | 223 | '@module-federation/runtime@0.14.3': 224 | resolution: {integrity: sha512-7ZHpa3teUDVhraYdxQGkfGHzPbjna4LtwbpudgzAxSLLFxLDNanaxCuSeIgSM9c+8sVUNC9kvzUgJEZB0krPJw==} 225 | 226 | '@module-federation/sdk@0.14.0': 227 | resolution: {integrity: sha512-lg/OWRsh18hsyTCamOOhEX546vbDiA2O4OggTxxH2wTGr156N6DdELGQlYIKfRdU/0StgtQS81Goc0BgDZlx9A==} 228 | 229 | '@module-federation/sdk@0.14.3': 230 | resolution: {integrity: sha512-THJZMfbXpqjQOLblCQ8jjcBFFXsGRJwUWE9l/Q4SmuCSKMgAwie7yLT0qSGrHmyBYrsUjAuy+xNB4nfKP0pnGw==} 231 | 232 | '@module-federation/webpack-bundler-runtime@0.14.0': 233 | resolution: {integrity: sha512-POWS6cKBicAAQ3DNY5X7XEUSfOfUsRaBNxbuwEfSGlrkTE9UcWheO06QP2ndHi8tHQuUKcIHi2navhPkJ+k5xg==} 234 | 235 | '@module-federation/webpack-bundler-runtime@0.14.3': 236 | resolution: {integrity: sha512-hIyJFu34P7bY2NeMIUHAS/mYUHEY71VTAsN0A0AqEJFSVPszheopu9VdXq0VDLrP9KQfuXT8SDxeYeJXyj0mgA==} 237 | 238 | '@nodelib/fs.scandir@2.1.5': 239 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 240 | engines: {node: '>= 8'} 241 | 242 | '@nodelib/fs.stat@2.0.5': 243 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 244 | engines: {node: '>= 8'} 245 | 246 | '@nodelib/fs.walk@1.2.8': 247 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 248 | engines: {node: '>= 8'} 249 | 250 | '@pkgjs/parseargs@0.11.0': 251 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 252 | engines: {node: '>=14'} 253 | 254 | '@playwright/test@1.52.0': 255 | resolution: {integrity: sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==} 256 | engines: {node: '>=18'} 257 | hasBin: true 258 | 259 | '@rollup/pluginutils@5.1.4': 260 | resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} 261 | engines: {node: '>=14.0.0'} 262 | peerDependencies: 263 | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 264 | peerDependenciesMeta: 265 | rollup: 266 | optional: true 267 | 268 | '@rsbuild/core@1.3.22': 269 | resolution: {integrity: sha512-FGB7m8Tn/uiOhvqk0lw+NRMyD+VYJ+eBqVfpn0X11spkJDiPWn8UkMRvfzCX4XFcNZwRKYuuKJaZK1DNU8UG+w==} 270 | engines: {node: '>=16.10.0'} 271 | hasBin: true 272 | 273 | '@rsbuild/core@1.4.0-beta.1': 274 | resolution: {integrity: sha512-kE78UEmnxtIn/oy8Y37VKF33cqVhEmns+jvZ+42rGjqfCfNC38+B/jU6g2D/WumE6OzyCUfgxqyuN3/HZVzLoA==} 275 | engines: {node: '>=16.10.0'} 276 | hasBin: true 277 | 278 | '@rsbuild/webpack@1.3.2': 279 | resolution: {integrity: sha512-ecpZDyKLunUkEM5Yg6UVCONJFHD4+qY5Vtci8t2BRZneQgwZiYrENz+RKYN7NBir6+7nHy3pYMVPU5WJAkGPSA==} 280 | peerDependencies: 281 | '@rsbuild/core': ^1.3.21 282 | 283 | '@rslib/core@0.9.1': 284 | resolution: {integrity: sha512-aa/LXYxr49lCNm/b0B4CQoTB5286MPglGsE5/YFoY0VwIcKJdMz0zBJ4DsPwh27/fcfDQvmN1+J9tzjt9TxQtQ==} 285 | engines: {node: '>=16.7.0'} 286 | hasBin: true 287 | peerDependencies: 288 | '@microsoft/api-extractor': ^7 289 | typescript: ^5 290 | peerDependenciesMeta: 291 | '@microsoft/api-extractor': 292 | optional: true 293 | typescript: 294 | optional: true 295 | 296 | '@rspack/binding-darwin-arm64@1.3.12': 297 | resolution: {integrity: sha512-8hKjVTBeWPqkMzFPNWIh72oU9O3vFy3e88wRjMPImDCXBiEYrKqGTTLd/J0SO+efdL3SBD1rX1IvdJpxCv6Yrw==} 298 | cpu: [arm64] 299 | os: [darwin] 300 | 301 | '@rspack/binding-darwin-arm64@1.3.13': 302 | resolution: {integrity: sha512-1c+KC+TFaKRWu+SO4cJZ5oHKOFuDhTIitbSIG9boJpDRoZmJxHDmFyTTxVI2r2QUjxJaDdUlSFepybhhJ3UiPg==} 303 | cpu: [arm64] 304 | os: [darwin] 305 | 306 | '@rspack/binding-darwin-x64@1.3.12': 307 | resolution: {integrity: sha512-Sj4m+mCUxL7oCpdu7OmWT7fpBM7hywk5CM9RDc3D7StaBZbvNtNftafCrTZzTYKuZrKmemTh5SFzT5Tz7tf6GA==} 308 | cpu: [x64] 309 | os: [darwin] 310 | 311 | '@rspack/binding-darwin-x64@1.3.13': 312 | resolution: {integrity: sha512-YBF+XjoGSjhJ5o/xOaCBd39BntMudMeup11j2Dz+rrTH+wG6TvH017HYIgDMT3UBVv66eNsQpzA0ZW5raJ0lbA==} 313 | cpu: [x64] 314 | os: [darwin] 315 | 316 | '@rspack/binding-linux-arm64-gnu@1.3.12': 317 | resolution: {integrity: sha512-7MuOxf3/Mhv4mgFdLTvgnt/J+VouNR65DEhorth+RZm3LEWojgoFEphSAMAvpvAOpYSS68Sw4SqsOZi719ia2w==} 318 | cpu: [arm64] 319 | os: [linux] 320 | 321 | '@rspack/binding-linux-arm64-gnu@1.3.13': 322 | resolution: {integrity: sha512-II71Ez7Z0/5ZpcK+kCgvXFKK0AysS9La8LNQbqf2wmzxDJi5H8eVUiwkM5BabICxzOWYtTGJLZ89QbCYaFbqCg==} 323 | cpu: [arm64] 324 | os: [linux] 325 | 326 | '@rspack/binding-linux-arm64-musl@1.3.12': 327 | resolution: {integrity: sha512-s6KKj20T9Z1bA8caIjU6EzJbwyDo1URNFgBAlafCT2UC6yX7flstDJJ38CxZacA9A2P24RuQK2/jPSZpWrTUFA==} 328 | cpu: [arm64] 329 | os: [linux] 330 | 331 | '@rspack/binding-linux-arm64-musl@1.3.13': 332 | resolution: {integrity: sha512-JFFhqglKVjlWcmmVwdS80Kw6v35yY9xlQJup09mL8gMtiiFiT36wTyTujz15Iv+2+S/Dv0Z+UeUJ99KRbQxgcQ==} 333 | cpu: [arm64] 334 | os: [linux] 335 | 336 | '@rspack/binding-linux-x64-gnu@1.3.12': 337 | resolution: {integrity: sha512-0w/sRREYbRgHgWvs2uMEJSLfvzbZkPHUg6CMcYQGNVK6axYRot6jPyKetyFYA9pR5fB5rsXegpnFaZaVrRIK2g==} 338 | cpu: [x64] 339 | os: [linux] 340 | 341 | '@rspack/binding-linux-x64-gnu@1.3.13': 342 | resolution: {integrity: sha512-ogm4rt+PMQHkMg/0mA9VTjfGE3c+YaHZQT8KrFgTsoj2YCW9WO2J/RjdMc6STG4Y10BWO9Ar2azLxxHrKb+8UQ==} 343 | cpu: [x64] 344 | os: [linux] 345 | 346 | '@rspack/binding-linux-x64-musl@1.3.12': 347 | resolution: {integrity: sha512-jEdxkPymkRxbijDRsBGdhopcbGXiXDg59lXqIRkVklqbDmZ/O6DHm7gImmlx5q9FoWbz0gqJuOKBz4JqWxjWVA==} 348 | cpu: [x64] 349 | os: [linux] 350 | 351 | '@rspack/binding-linux-x64-musl@1.3.13': 352 | resolution: {integrity: sha512-8icDyXhg1iMKhQ3X2FTgAGQTQqnli9FyqHCuRIBauxy1V4W478Mp9Y+V+ErVUY1YxbZEUrkt3a59hssjGeDEeg==} 353 | cpu: [x64] 354 | os: [linux] 355 | 356 | '@rspack/binding-win32-arm64-msvc@1.3.12': 357 | resolution: {integrity: sha512-ZRvUCb3TDLClAqcTsl/o9UdJf0B5CgzAxgdbnYJbldyuyMeTUB4jp20OfG55M3C2Nute2SNhu2bOOp9Se5Ongw==} 358 | cpu: [arm64] 359 | os: [win32] 360 | 361 | '@rspack/binding-win32-arm64-msvc@1.3.13': 362 | resolution: {integrity: sha512-y5XxwxDW4DrPKy+8P6t7I7IbA7B/iXjLoaS0jP/EwjSHWf/EnZzq9MgWqdop1km8Mwx6s1zcj+0qs73jL2N98w==} 363 | cpu: [arm64] 364 | os: [win32] 365 | 366 | '@rspack/binding-win32-ia32-msvc@1.3.12': 367 | resolution: {integrity: sha512-1TKPjuXStPJr14f3ZHuv40Xc/87jUXx10pzVtrPnw+f3hckECHrbYU/fvbVzZyuXbsXtkXpYca6ygCDRJAoNeQ==} 368 | cpu: [ia32] 369 | os: [win32] 370 | 371 | '@rspack/binding-win32-ia32-msvc@1.3.13': 372 | resolution: {integrity: sha512-n24sznsZe3lC8ok6MgsT1nG4lVx3SQ/lZ0g23i2BGMRN8/p+kaC2eoPaHe/4m9Liz/W4Z5LhZCCvg4DQMEzeLA==} 373 | cpu: [ia32] 374 | os: [win32] 375 | 376 | '@rspack/binding-win32-x64-msvc@1.3.12': 377 | resolution: {integrity: sha512-lCR0JfnYKpV+a6r2A2FdxyUKUS4tajePgpPJN5uXDgMGwrDtRqvx+d0BHhwjFudQVJq9VVbRaL89s2MQ6u+xYw==} 378 | cpu: [x64] 379 | os: [win32] 380 | 381 | '@rspack/binding-win32-x64-msvc@1.3.13': 382 | resolution: {integrity: sha512-CLyTNo0OrOD7xFKusFciKKG+8CXPowjPz+tcdkkrKYqGzAPzOcszblikITJhMbc7DLMzdTRSZUTkKLRydYH9sw==} 383 | cpu: [x64] 384 | os: [win32] 385 | 386 | '@rspack/binding@1.3.12': 387 | resolution: {integrity: sha512-4Ic8lV0+LCBfTlH5aIOujIRWZOtgmG223zC4L3o8WY/+ESAgpdnK6lSSMfcYgRanYLAy3HOmFIp20jwskMpbAg==} 388 | 389 | '@rspack/binding@1.3.13': 390 | resolution: {integrity: sha512-BdM6tfLCP7/0H5uGc+okG6AYsU9JEnR5bRHq4YuGaS4tb+N5ct0czm0LprGMZ7zRAnIql/zoLn/bHlheNxZw3g==} 391 | 392 | '@rspack/core@1.3.12': 393 | resolution: {integrity: sha512-mAPmV4LPPRgxpouUrGmAE4kpF1NEWJGyM5coebsjK/zaCMSjw3mkdxiU2b5cO44oIi0Ifv5iGkvwbdrZOvMyFA==} 394 | engines: {node: '>=16.0.0'} 395 | peerDependencies: 396 | '@swc/helpers': '>=0.5.1' 397 | peerDependenciesMeta: 398 | '@swc/helpers': 399 | optional: true 400 | 401 | '@rspack/core@1.3.13': 402 | resolution: {integrity: sha512-j9jsNzKeEN14yraqX4jAFrM/nMfX5YEPgEMPlp4g5NAu3siaBa8gDF5brbdNq6TDXnTHK1MwwjaMdKA+3YeBKQ==} 403 | engines: {node: '>=16.0.0'} 404 | peerDependencies: 405 | '@swc/helpers': '>=0.5.1' 406 | peerDependenciesMeta: 407 | '@swc/helpers': 408 | optional: true 409 | 410 | '@rspack/lite-tapable@1.0.1': 411 | resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} 412 | engines: {node: '>=16.0.0'} 413 | 414 | '@swc/helpers@0.5.17': 415 | resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} 416 | 417 | '@types/eslint-scope@3.7.7': 418 | resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} 419 | 420 | '@types/eslint@9.6.1': 421 | resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} 422 | 423 | '@types/estree@1.0.6': 424 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 425 | 426 | '@types/html-minifier-terser@6.1.0': 427 | resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} 428 | 429 | '@types/json-schema@7.0.15': 430 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 431 | 432 | '@types/node@22.15.29': 433 | resolution: {integrity: sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==} 434 | 435 | '@types/semver@7.7.0': 436 | resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} 437 | 438 | '@webassemblyjs/ast@1.14.1': 439 | resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} 440 | 441 | '@webassemblyjs/floating-point-hex-parser@1.13.2': 442 | resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} 443 | 444 | '@webassemblyjs/helper-api-error@1.13.2': 445 | resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} 446 | 447 | '@webassemblyjs/helper-buffer@1.14.1': 448 | resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} 449 | 450 | '@webassemblyjs/helper-numbers@1.13.2': 451 | resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} 452 | 453 | '@webassemblyjs/helper-wasm-bytecode@1.13.2': 454 | resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} 455 | 456 | '@webassemblyjs/helper-wasm-section@1.14.1': 457 | resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} 458 | 459 | '@webassemblyjs/ieee754@1.13.2': 460 | resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} 461 | 462 | '@webassemblyjs/leb128@1.13.2': 463 | resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} 464 | 465 | '@webassemblyjs/utf8@1.13.2': 466 | resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} 467 | 468 | '@webassemblyjs/wasm-edit@1.14.1': 469 | resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} 470 | 471 | '@webassemblyjs/wasm-gen@1.14.1': 472 | resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} 473 | 474 | '@webassemblyjs/wasm-opt@1.14.1': 475 | resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} 476 | 477 | '@webassemblyjs/wasm-parser@1.14.1': 478 | resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} 479 | 480 | '@webassemblyjs/wast-printer@1.14.1': 481 | resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} 482 | 483 | '@xtuc/ieee754@1.2.0': 484 | resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} 485 | 486 | '@xtuc/long@4.2.2': 487 | resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} 488 | 489 | acorn@8.14.0: 490 | resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} 491 | engines: {node: '>=0.4.0'} 492 | hasBin: true 493 | 494 | ajv-formats@2.1.1: 495 | resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} 496 | peerDependencies: 497 | ajv: ^8.0.0 498 | peerDependenciesMeta: 499 | ajv: 500 | optional: true 501 | 502 | ajv-keywords@5.1.0: 503 | resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} 504 | peerDependencies: 505 | ajv: ^8.8.2 506 | 507 | ajv@8.17.1: 508 | resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} 509 | 510 | ansi-regex@5.0.1: 511 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 512 | engines: {node: '>=8'} 513 | 514 | ansi-regex@6.1.0: 515 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 516 | engines: {node: '>=12'} 517 | 518 | ansi-styles@4.3.0: 519 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 520 | engines: {node: '>=8'} 521 | 522 | ansi-styles@6.2.1: 523 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 524 | engines: {node: '>=12'} 525 | 526 | any-promise@1.3.0: 527 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 528 | 529 | anymatch@3.1.3: 530 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 531 | engines: {node: '>= 8'} 532 | 533 | arg@5.0.2: 534 | resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} 535 | 536 | balanced-match@1.0.2: 537 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 538 | 539 | binary-extensions@2.3.0: 540 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 541 | engines: {node: '>=8'} 542 | 543 | boolbase@1.0.0: 544 | resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} 545 | 546 | brace-expansion@2.0.1: 547 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 548 | 549 | braces@3.0.3: 550 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 551 | engines: {node: '>=8'} 552 | 553 | browserslist@4.24.2: 554 | resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} 555 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 556 | hasBin: true 557 | 558 | buffer-from@1.1.2: 559 | resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} 560 | 561 | camel-case@4.1.2: 562 | resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} 563 | 564 | camelcase-css@2.0.1: 565 | resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} 566 | engines: {node: '>= 6'} 567 | 568 | caniuse-lite@1.0.30001716: 569 | resolution: {integrity: sha512-49/c1+x3Kwz7ZIWt+4DvK3aMJy9oYXXG6/97JKsnjdCk/6n9vVyWL8NAwVt95Lwt9eigI10Hl782kDfZUUlRXw==} 570 | 571 | caniuse-lite@1.0.30001721: 572 | resolution: {integrity: sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==} 573 | 574 | chalk@4.1.2: 575 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 576 | engines: {node: '>=10'} 577 | 578 | chokidar@3.6.0: 579 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 580 | engines: {node: '>= 8.10.0'} 581 | 582 | chrome-trace-event@1.0.4: 583 | resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} 584 | engines: {node: '>=6.0'} 585 | 586 | clean-css@5.3.3: 587 | resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} 588 | engines: {node: '>= 10.0'} 589 | 590 | color-convert@2.0.1: 591 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 592 | engines: {node: '>=7.0.0'} 593 | 594 | color-name@1.1.4: 595 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 596 | 597 | commander@2.20.3: 598 | resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} 599 | 600 | commander@4.1.1: 601 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 602 | engines: {node: '>= 6'} 603 | 604 | commander@8.3.0: 605 | resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} 606 | engines: {node: '>= 12'} 607 | 608 | copy-webpack-plugin@11.0.0: 609 | resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} 610 | engines: {node: '>= 14.15.0'} 611 | peerDependencies: 612 | webpack: ^5.1.0 613 | 614 | core-js@3.42.0: 615 | resolution: {integrity: sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==} 616 | 617 | cross-spawn@7.0.6: 618 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 619 | engines: {node: '>= 8'} 620 | 621 | css-select@4.3.0: 622 | resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} 623 | 624 | css-what@6.1.0: 625 | resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} 626 | engines: {node: '>= 6'} 627 | 628 | cssesc@3.0.0: 629 | resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} 630 | engines: {node: '>=4'} 631 | hasBin: true 632 | 633 | didyoumean@1.2.2: 634 | resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} 635 | 636 | dir-glob@3.0.1: 637 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 638 | engines: {node: '>=8'} 639 | 640 | dlv@1.1.3: 641 | resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} 642 | 643 | dom-converter@0.2.0: 644 | resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} 645 | 646 | dom-serializer@1.4.1: 647 | resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} 648 | 649 | domelementtype@2.3.0: 650 | resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} 651 | 652 | domhandler@4.3.1: 653 | resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} 654 | engines: {node: '>= 4'} 655 | 656 | domutils@2.8.0: 657 | resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} 658 | 659 | dot-case@3.0.4: 660 | resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} 661 | 662 | eastasianwidth@0.2.0: 663 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 664 | 665 | electron-to-chromium@1.5.67: 666 | resolution: {integrity: sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ==} 667 | 668 | emoji-regex@8.0.0: 669 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 670 | 671 | emoji-regex@9.2.2: 672 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 673 | 674 | enhanced-resolve@5.17.1: 675 | resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} 676 | engines: {node: '>=10.13.0'} 677 | 678 | entities@2.2.0: 679 | resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} 680 | 681 | es-module-lexer@1.5.4: 682 | resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} 683 | 684 | escalade@3.2.0: 685 | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 686 | engines: {node: '>=6'} 687 | 688 | eslint-scope@5.1.1: 689 | resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} 690 | engines: {node: '>=8.0.0'} 691 | 692 | esrecurse@4.3.0: 693 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 694 | engines: {node: '>=4.0'} 695 | 696 | estraverse@4.3.0: 697 | resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} 698 | engines: {node: '>=4.0'} 699 | 700 | estraverse@5.3.0: 701 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 702 | engines: {node: '>=4.0'} 703 | 704 | estree-walker@2.0.2: 705 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 706 | 707 | events@3.3.0: 708 | resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} 709 | engines: {node: '>=0.8.x'} 710 | 711 | fast-deep-equal@3.1.3: 712 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 713 | 714 | fast-glob@3.3.2: 715 | resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} 716 | engines: {node: '>=8.6.0'} 717 | 718 | fast-uri@3.0.3: 719 | resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} 720 | 721 | fastq@1.17.1: 722 | resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 723 | 724 | fdir@6.4.4: 725 | resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} 726 | peerDependencies: 727 | picomatch: ^3 || ^4 728 | peerDependenciesMeta: 729 | picomatch: 730 | optional: true 731 | 732 | fill-range@7.1.1: 733 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 734 | engines: {node: '>=8'} 735 | 736 | foreground-child@3.3.0: 737 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} 738 | engines: {node: '>=14'} 739 | 740 | fsevents@2.3.2: 741 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 742 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 743 | os: [darwin] 744 | 745 | fsevents@2.3.3: 746 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 747 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 748 | os: [darwin] 749 | 750 | function-bind@1.1.2: 751 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 752 | 753 | glob-parent@5.1.2: 754 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 755 | engines: {node: '>= 6'} 756 | 757 | glob-parent@6.0.2: 758 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 759 | engines: {node: '>=10.13.0'} 760 | 761 | glob-to-regexp@0.4.1: 762 | resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} 763 | 764 | glob@10.4.5: 765 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 766 | hasBin: true 767 | 768 | globby@13.2.2: 769 | resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} 770 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 771 | 772 | graceful-fs@4.2.11: 773 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 774 | 775 | has-flag@4.0.0: 776 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 777 | engines: {node: '>=8'} 778 | 779 | hasown@2.0.2: 780 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 781 | engines: {node: '>= 0.4'} 782 | 783 | he@1.2.0: 784 | resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} 785 | hasBin: true 786 | 787 | html-minifier-terser@6.1.0: 788 | resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} 789 | engines: {node: '>=12'} 790 | hasBin: true 791 | 792 | html-webpack-plugin@5.6.3: 793 | resolution: {integrity: sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==} 794 | engines: {node: '>=10.13.0'} 795 | peerDependencies: 796 | '@rspack/core': 0.x || 1.x 797 | webpack: ^5.20.0 798 | peerDependenciesMeta: 799 | '@rspack/core': 800 | optional: true 801 | webpack: 802 | optional: true 803 | 804 | htmlparser2@6.1.0: 805 | resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} 806 | 807 | ignore@5.3.2: 808 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 809 | engines: {node: '>= 4'} 810 | 811 | is-binary-path@2.1.0: 812 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 813 | engines: {node: '>=8'} 814 | 815 | is-core-module@2.15.1: 816 | resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} 817 | engines: {node: '>= 0.4'} 818 | 819 | is-extglob@2.1.1: 820 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 821 | engines: {node: '>=0.10.0'} 822 | 823 | is-fullwidth-code-point@3.0.0: 824 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 825 | engines: {node: '>=8'} 826 | 827 | is-glob@4.0.3: 828 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 829 | engines: {node: '>=0.10.0'} 830 | 831 | is-number@7.0.0: 832 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 833 | engines: {node: '>=0.12.0'} 834 | 835 | isexe@2.0.0: 836 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 837 | 838 | jackspeak@3.4.3: 839 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 840 | 841 | jest-worker@27.5.1: 842 | resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} 843 | engines: {node: '>= 10.13.0'} 844 | 845 | jiti@1.21.6: 846 | resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} 847 | hasBin: true 848 | 849 | jiti@2.4.2: 850 | resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} 851 | hasBin: true 852 | 853 | json-parse-even-better-errors@2.3.1: 854 | resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} 855 | 856 | json-schema-traverse@1.0.0: 857 | resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} 858 | 859 | json5@2.2.3: 860 | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 861 | engines: {node: '>=6'} 862 | hasBin: true 863 | 864 | lilconfig@3.1.3: 865 | resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} 866 | engines: {node: '>=14'} 867 | 868 | lines-and-columns@1.2.4: 869 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 870 | 871 | loader-runner@4.3.0: 872 | resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} 873 | engines: {node: '>=6.11.5'} 874 | 875 | lodash@4.17.21: 876 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 877 | 878 | lower-case@2.0.2: 879 | resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} 880 | 881 | lru-cache@10.4.3: 882 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 883 | 884 | magic-string@0.30.17: 885 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} 886 | 887 | merge-stream@2.0.0: 888 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 889 | 890 | merge2@1.4.1: 891 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 892 | engines: {node: '>= 8'} 893 | 894 | micromatch@4.0.8: 895 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 896 | engines: {node: '>=8.6'} 897 | 898 | mime-db@1.52.0: 899 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 900 | engines: {node: '>= 0.6'} 901 | 902 | mime-types@2.1.35: 903 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 904 | engines: {node: '>= 0.6'} 905 | 906 | mini-css-extract-plugin@2.9.2: 907 | resolution: {integrity: sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==} 908 | engines: {node: '>= 12.13.0'} 909 | peerDependencies: 910 | webpack: ^5.0.0 911 | 912 | minimatch@9.0.5: 913 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 914 | engines: {node: '>=16 || 14 >=14.17'} 915 | 916 | minimist@1.2.8: 917 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 918 | 919 | minipass@7.1.2: 920 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 921 | engines: {node: '>=16 || 14 >=14.17'} 922 | 923 | mz@2.7.0: 924 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 925 | 926 | nanoid@3.3.11: 927 | resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 928 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 929 | hasBin: true 930 | 931 | neo-async@2.6.2: 932 | resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} 933 | 934 | no-case@3.0.4: 935 | resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} 936 | 937 | node-releases@2.0.18: 938 | resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} 939 | 940 | normalize-path@3.0.0: 941 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 942 | engines: {node: '>=0.10.0'} 943 | 944 | nth-check@2.1.1: 945 | resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} 946 | 947 | object-assign@4.1.1: 948 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 949 | engines: {node: '>=0.10.0'} 950 | 951 | object-hash@3.0.0: 952 | resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} 953 | engines: {node: '>= 6'} 954 | 955 | package-json-from-dist@1.0.1: 956 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 957 | 958 | param-case@3.0.4: 959 | resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} 960 | 961 | pascal-case@3.1.2: 962 | resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} 963 | 964 | path-key@3.1.1: 965 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 966 | engines: {node: '>=8'} 967 | 968 | path-parse@1.0.7: 969 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 970 | 971 | path-scurry@1.11.1: 972 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 973 | engines: {node: '>=16 || 14 >=14.18'} 974 | 975 | path-type@4.0.0: 976 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 977 | engines: {node: '>=8'} 978 | 979 | picocolors@1.1.1: 980 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 981 | 982 | picomatch@2.3.1: 983 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 984 | engines: {node: '>=8.6'} 985 | 986 | picomatch@4.0.2: 987 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 988 | engines: {node: '>=12'} 989 | 990 | pify@2.3.0: 991 | resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} 992 | engines: {node: '>=0.10.0'} 993 | 994 | pirates@4.0.6: 995 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} 996 | engines: {node: '>= 6'} 997 | 998 | playwright-core@1.52.0: 999 | resolution: {integrity: sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==} 1000 | engines: {node: '>=18'} 1001 | hasBin: true 1002 | 1003 | playwright@1.52.0: 1004 | resolution: {integrity: sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==} 1005 | engines: {node: '>=18'} 1006 | hasBin: true 1007 | 1008 | postcss-import@15.1.0: 1009 | resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} 1010 | engines: {node: '>=14.0.0'} 1011 | peerDependencies: 1012 | postcss: ^8.0.0 1013 | 1014 | postcss-js@4.0.1: 1015 | resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} 1016 | engines: {node: ^12 || ^14 || >= 16} 1017 | peerDependencies: 1018 | postcss: ^8.4.21 1019 | 1020 | postcss-load-config@4.0.2: 1021 | resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} 1022 | engines: {node: '>= 14'} 1023 | peerDependencies: 1024 | postcss: '>=8.0.9' 1025 | ts-node: '>=9.0.0' 1026 | peerDependenciesMeta: 1027 | postcss: 1028 | optional: true 1029 | ts-node: 1030 | optional: true 1031 | 1032 | postcss-nested@6.2.0: 1033 | resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} 1034 | engines: {node: '>=12.0'} 1035 | peerDependencies: 1036 | postcss: ^8.2.14 1037 | 1038 | postcss-selector-parser@6.1.2: 1039 | resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} 1040 | engines: {node: '>=4'} 1041 | 1042 | postcss-value-parser@4.2.0: 1043 | resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 1044 | 1045 | postcss@8.5.4: 1046 | resolution: {integrity: sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==} 1047 | engines: {node: ^10 || ^12 || >=14} 1048 | 1049 | pretty-error@4.0.0: 1050 | resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} 1051 | 1052 | queue-microtask@1.2.3: 1053 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1054 | 1055 | randombytes@2.1.0: 1056 | resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} 1057 | 1058 | read-cache@1.0.0: 1059 | resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} 1060 | 1061 | readdirp@3.6.0: 1062 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1063 | engines: {node: '>=8.10.0'} 1064 | 1065 | reduce-configs@1.1.0: 1066 | resolution: {integrity: sha512-DQxy6liNadHfrLahZR7lMdc227NYVaQZhY5FMsxLEjX8X0SCuH+ESHSLCoz2yDZFq1/CLMDOAHdsEHwOEXKtvg==} 1067 | 1068 | relateurl@0.2.7: 1069 | resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} 1070 | engines: {node: '>= 0.10'} 1071 | 1072 | renderkid@3.0.0: 1073 | resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} 1074 | 1075 | require-from-string@2.0.2: 1076 | resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} 1077 | engines: {node: '>=0.10.0'} 1078 | 1079 | resolve@1.22.8: 1080 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} 1081 | hasBin: true 1082 | 1083 | reusify@1.0.4: 1084 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1085 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1086 | 1087 | rsbuild-plugin-dts@0.9.1: 1088 | resolution: {integrity: sha512-04pkKrebuajsCpC8Vj2z4n6NFFxUYAdUdqSQRFGkGhdmururoDFYW0k9+ZQq9XrSQTlB01F/HFv5mAc0dwG/Qg==} 1089 | engines: {node: '>=16.7.0'} 1090 | peerDependencies: 1091 | '@microsoft/api-extractor': ^7 1092 | '@rsbuild/core': 1.x 1093 | typescript: ^5 1094 | peerDependenciesMeta: 1095 | '@microsoft/api-extractor': 1096 | optional: true 1097 | typescript: 1098 | optional: true 1099 | 1100 | run-parallel@1.2.0: 1101 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1102 | 1103 | safe-buffer@5.2.1: 1104 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1105 | 1106 | schema-utils@4.3.0: 1107 | resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} 1108 | engines: {node: '>= 10.13.0'} 1109 | 1110 | schema-utils@4.3.2: 1111 | resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} 1112 | engines: {node: '>= 10.13.0'} 1113 | 1114 | semver@7.7.2: 1115 | resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} 1116 | engines: {node: '>=10'} 1117 | hasBin: true 1118 | 1119 | serialize-javascript@6.0.2: 1120 | resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} 1121 | 1122 | shebang-command@2.0.0: 1123 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1124 | engines: {node: '>=8'} 1125 | 1126 | shebang-regex@3.0.0: 1127 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1128 | engines: {node: '>=8'} 1129 | 1130 | signal-exit@4.1.0: 1131 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1132 | engines: {node: '>=14'} 1133 | 1134 | simple-git-hooks@2.13.0: 1135 | resolution: {integrity: sha512-N+goiLxlkHJlyaYEglFypzVNMaNplPAk5syu0+OPp/Bk6dwVoXF6FfOw2vO0Dp+JHsBaI+w6cm8TnFl2Hw6tDA==} 1136 | hasBin: true 1137 | 1138 | slash@4.0.0: 1139 | resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} 1140 | engines: {node: '>=12'} 1141 | 1142 | source-map-js@1.2.1: 1143 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1144 | engines: {node: '>=0.10.0'} 1145 | 1146 | source-map-support@0.5.21: 1147 | resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} 1148 | 1149 | source-map@0.6.1: 1150 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1151 | engines: {node: '>=0.10.0'} 1152 | 1153 | string-width@4.2.3: 1154 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1155 | engines: {node: '>=8'} 1156 | 1157 | string-width@5.1.2: 1158 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1159 | engines: {node: '>=12'} 1160 | 1161 | strip-ansi@6.0.1: 1162 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1163 | engines: {node: '>=8'} 1164 | 1165 | strip-ansi@7.1.0: 1166 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1167 | engines: {node: '>=12'} 1168 | 1169 | strip-bom@3.0.0: 1170 | resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 1171 | engines: {node: '>=4'} 1172 | 1173 | sucrase@3.35.0: 1174 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} 1175 | engines: {node: '>=16 || 14 >=14.17'} 1176 | hasBin: true 1177 | 1178 | supports-color@7.2.0: 1179 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1180 | engines: {node: '>=8'} 1181 | 1182 | supports-color@8.1.1: 1183 | resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} 1184 | engines: {node: '>=10'} 1185 | 1186 | supports-preserve-symlinks-flag@1.0.0: 1187 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1188 | engines: {node: '>= 0.4'} 1189 | 1190 | tailwindcss@3.4.17: 1191 | resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} 1192 | engines: {node: '>=14.0.0'} 1193 | hasBin: true 1194 | 1195 | tapable@2.2.1: 1196 | resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} 1197 | engines: {node: '>=6'} 1198 | 1199 | terser-webpack-plugin@5.3.12: 1200 | resolution: {integrity: sha512-jDLYqo7oF8tJIttjXO6jBY5Hk8p3A8W4ttih7cCEq64fQFWmgJ4VqAQjKr7WwIDlmXKEc6QeoRb5ecjZ+2afcg==} 1201 | engines: {node: '>= 10.13.0'} 1202 | peerDependencies: 1203 | '@swc/core': '*' 1204 | esbuild: '*' 1205 | uglify-js: '*' 1206 | webpack: ^5.1.0 1207 | peerDependenciesMeta: 1208 | '@swc/core': 1209 | optional: true 1210 | esbuild: 1211 | optional: true 1212 | uglify-js: 1213 | optional: true 1214 | 1215 | terser@5.36.0: 1216 | resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==} 1217 | engines: {node: '>=10'} 1218 | hasBin: true 1219 | 1220 | thenify-all@1.6.0: 1221 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1222 | engines: {node: '>=0.8'} 1223 | 1224 | thenify@3.3.1: 1225 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1226 | 1227 | tinyglobby@0.2.14: 1228 | resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} 1229 | engines: {node: '>=12.0.0'} 1230 | 1231 | to-regex-range@5.0.1: 1232 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1233 | engines: {node: '>=8.0'} 1234 | 1235 | ts-interface-checker@0.1.13: 1236 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} 1237 | 1238 | tsconfig-paths-webpack-plugin@4.2.0: 1239 | resolution: {integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==} 1240 | engines: {node: '>=10.13.0'} 1241 | 1242 | tsconfig-paths@4.2.0: 1243 | resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} 1244 | engines: {node: '>=6'} 1245 | 1246 | tslib@2.8.1: 1247 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1248 | 1249 | typescript@5.8.3: 1250 | resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} 1251 | engines: {node: '>=14.17'} 1252 | hasBin: true 1253 | 1254 | undici-types@6.21.0: 1255 | resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 1256 | 1257 | update-browserslist-db@1.1.1: 1258 | resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} 1259 | hasBin: true 1260 | peerDependencies: 1261 | browserslist: '>= 4.21.0' 1262 | 1263 | util-deprecate@1.0.2: 1264 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1265 | 1266 | utila@0.4.0: 1267 | resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} 1268 | 1269 | watchpack@2.4.2: 1270 | resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} 1271 | engines: {node: '>=10.13.0'} 1272 | 1273 | webpack-sources@3.2.3: 1274 | resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} 1275 | engines: {node: '>=10.13.0'} 1276 | 1277 | webpack@5.99.9: 1278 | resolution: {integrity: sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==} 1279 | engines: {node: '>=10.13.0'} 1280 | hasBin: true 1281 | peerDependencies: 1282 | webpack-cli: '*' 1283 | peerDependenciesMeta: 1284 | webpack-cli: 1285 | optional: true 1286 | 1287 | which@2.0.2: 1288 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1289 | engines: {node: '>= 8'} 1290 | hasBin: true 1291 | 1292 | wrap-ansi@7.0.0: 1293 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1294 | engines: {node: '>=10'} 1295 | 1296 | wrap-ansi@8.1.0: 1297 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1298 | engines: {node: '>=12'} 1299 | 1300 | yaml@2.6.1: 1301 | resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} 1302 | engines: {node: '>= 14'} 1303 | hasBin: true 1304 | 1305 | snapshots: 1306 | 1307 | '@alloc/quick-lru@5.2.0': {} 1308 | 1309 | '@ast-grep/napi-darwin-arm64@0.37.0': 1310 | optional: true 1311 | 1312 | '@ast-grep/napi-darwin-x64@0.37.0': 1313 | optional: true 1314 | 1315 | '@ast-grep/napi-linux-arm64-gnu@0.37.0': 1316 | optional: true 1317 | 1318 | '@ast-grep/napi-linux-arm64-musl@0.37.0': 1319 | optional: true 1320 | 1321 | '@ast-grep/napi-linux-x64-gnu@0.37.0': 1322 | optional: true 1323 | 1324 | '@ast-grep/napi-linux-x64-musl@0.37.0': 1325 | optional: true 1326 | 1327 | '@ast-grep/napi-win32-arm64-msvc@0.37.0': 1328 | optional: true 1329 | 1330 | '@ast-grep/napi-win32-ia32-msvc@0.37.0': 1331 | optional: true 1332 | 1333 | '@ast-grep/napi-win32-x64-msvc@0.37.0': 1334 | optional: true 1335 | 1336 | '@ast-grep/napi@0.37.0': 1337 | optionalDependencies: 1338 | '@ast-grep/napi-darwin-arm64': 0.37.0 1339 | '@ast-grep/napi-darwin-x64': 0.37.0 1340 | '@ast-grep/napi-linux-arm64-gnu': 0.37.0 1341 | '@ast-grep/napi-linux-arm64-musl': 0.37.0 1342 | '@ast-grep/napi-linux-x64-gnu': 0.37.0 1343 | '@ast-grep/napi-linux-x64-musl': 0.37.0 1344 | '@ast-grep/napi-win32-arm64-msvc': 0.37.0 1345 | '@ast-grep/napi-win32-ia32-msvc': 0.37.0 1346 | '@ast-grep/napi-win32-x64-msvc': 0.37.0 1347 | 1348 | '@biomejs/biome@1.9.4': 1349 | optionalDependencies: 1350 | '@biomejs/cli-darwin-arm64': 1.9.4 1351 | '@biomejs/cli-darwin-x64': 1.9.4 1352 | '@biomejs/cli-linux-arm64': 1.9.4 1353 | '@biomejs/cli-linux-arm64-musl': 1.9.4 1354 | '@biomejs/cli-linux-x64': 1.9.4 1355 | '@biomejs/cli-linux-x64-musl': 1.9.4 1356 | '@biomejs/cli-win32-arm64': 1.9.4 1357 | '@biomejs/cli-win32-x64': 1.9.4 1358 | 1359 | '@biomejs/cli-darwin-arm64@1.9.4': 1360 | optional: true 1361 | 1362 | '@biomejs/cli-darwin-x64@1.9.4': 1363 | optional: true 1364 | 1365 | '@biomejs/cli-linux-arm64-musl@1.9.4': 1366 | optional: true 1367 | 1368 | '@biomejs/cli-linux-arm64@1.9.4': 1369 | optional: true 1370 | 1371 | '@biomejs/cli-linux-x64-musl@1.9.4': 1372 | optional: true 1373 | 1374 | '@biomejs/cli-linux-x64@1.9.4': 1375 | optional: true 1376 | 1377 | '@biomejs/cli-win32-arm64@1.9.4': 1378 | optional: true 1379 | 1380 | '@biomejs/cli-win32-x64@1.9.4': 1381 | optional: true 1382 | 1383 | '@isaacs/cliui@8.0.2': 1384 | dependencies: 1385 | string-width: 5.1.2 1386 | string-width-cjs: string-width@4.2.3 1387 | strip-ansi: 7.1.0 1388 | strip-ansi-cjs: strip-ansi@6.0.1 1389 | wrap-ansi: 8.1.0 1390 | wrap-ansi-cjs: wrap-ansi@7.0.0 1391 | 1392 | '@jridgewell/gen-mapping@0.3.5': 1393 | dependencies: 1394 | '@jridgewell/set-array': 1.2.1 1395 | '@jridgewell/sourcemap-codec': 1.5.0 1396 | '@jridgewell/trace-mapping': 0.3.25 1397 | 1398 | '@jridgewell/resolve-uri@3.1.2': {} 1399 | 1400 | '@jridgewell/set-array@1.2.1': {} 1401 | 1402 | '@jridgewell/source-map@0.3.6': 1403 | dependencies: 1404 | '@jridgewell/gen-mapping': 0.3.5 1405 | '@jridgewell/trace-mapping': 0.3.25 1406 | 1407 | '@jridgewell/sourcemap-codec@1.5.0': {} 1408 | 1409 | '@jridgewell/trace-mapping@0.3.25': 1410 | dependencies: 1411 | '@jridgewell/resolve-uri': 3.1.2 1412 | '@jridgewell/sourcemap-codec': 1.5.0 1413 | 1414 | '@module-federation/error-codes@0.14.0': {} 1415 | 1416 | '@module-federation/error-codes@0.14.3': {} 1417 | 1418 | '@module-federation/runtime-core@0.14.0': 1419 | dependencies: 1420 | '@module-federation/error-codes': 0.14.0 1421 | '@module-federation/sdk': 0.14.0 1422 | 1423 | '@module-federation/runtime-core@0.14.3': 1424 | dependencies: 1425 | '@module-federation/error-codes': 0.14.3 1426 | '@module-federation/sdk': 0.14.3 1427 | 1428 | '@module-federation/runtime-tools@0.14.0': 1429 | dependencies: 1430 | '@module-federation/runtime': 0.14.0 1431 | '@module-federation/webpack-bundler-runtime': 0.14.0 1432 | 1433 | '@module-federation/runtime-tools@0.14.3': 1434 | dependencies: 1435 | '@module-federation/runtime': 0.14.3 1436 | '@module-federation/webpack-bundler-runtime': 0.14.3 1437 | 1438 | '@module-federation/runtime@0.14.0': 1439 | dependencies: 1440 | '@module-federation/error-codes': 0.14.0 1441 | '@module-federation/runtime-core': 0.14.0 1442 | '@module-federation/sdk': 0.14.0 1443 | 1444 | '@module-federation/runtime@0.14.3': 1445 | dependencies: 1446 | '@module-federation/error-codes': 0.14.3 1447 | '@module-federation/runtime-core': 0.14.3 1448 | '@module-federation/sdk': 0.14.3 1449 | 1450 | '@module-federation/sdk@0.14.0': {} 1451 | 1452 | '@module-federation/sdk@0.14.3': {} 1453 | 1454 | '@module-federation/webpack-bundler-runtime@0.14.0': 1455 | dependencies: 1456 | '@module-federation/runtime': 0.14.0 1457 | '@module-federation/sdk': 0.14.0 1458 | 1459 | '@module-federation/webpack-bundler-runtime@0.14.3': 1460 | dependencies: 1461 | '@module-federation/runtime': 0.14.3 1462 | '@module-federation/sdk': 0.14.3 1463 | 1464 | '@nodelib/fs.scandir@2.1.5': 1465 | dependencies: 1466 | '@nodelib/fs.stat': 2.0.5 1467 | run-parallel: 1.2.0 1468 | 1469 | '@nodelib/fs.stat@2.0.5': {} 1470 | 1471 | '@nodelib/fs.walk@1.2.8': 1472 | dependencies: 1473 | '@nodelib/fs.scandir': 2.1.5 1474 | fastq: 1.17.1 1475 | 1476 | '@pkgjs/parseargs@0.11.0': 1477 | optional: true 1478 | 1479 | '@playwright/test@1.52.0': 1480 | dependencies: 1481 | playwright: 1.52.0 1482 | 1483 | '@rollup/pluginutils@5.1.4': 1484 | dependencies: 1485 | '@types/estree': 1.0.6 1486 | estree-walker: 2.0.2 1487 | picomatch: 4.0.2 1488 | 1489 | '@rsbuild/core@1.3.22': 1490 | dependencies: 1491 | '@rspack/core': 1.3.12(@swc/helpers@0.5.17) 1492 | '@rspack/lite-tapable': 1.0.1 1493 | '@swc/helpers': 0.5.17 1494 | core-js: 3.42.0 1495 | jiti: 2.4.2 1496 | 1497 | '@rsbuild/core@1.4.0-beta.1': 1498 | dependencies: 1499 | '@rspack/core': 1.3.13(@swc/helpers@0.5.17) 1500 | '@rspack/lite-tapable': 1.0.1 1501 | '@swc/helpers': 0.5.17 1502 | core-js: 3.42.0 1503 | jiti: 2.4.2 1504 | 1505 | '@rsbuild/webpack@1.3.2(@rsbuild/core@1.4.0-beta.1)(@rspack/core@1.3.13(@swc/helpers@0.5.17))': 1506 | dependencies: 1507 | '@rsbuild/core': 1.4.0-beta.1 1508 | copy-webpack-plugin: 11.0.0(webpack@5.99.9) 1509 | html-webpack-plugin: 5.6.3(@rspack/core@1.3.13(@swc/helpers@0.5.17))(webpack@5.99.9) 1510 | mini-css-extract-plugin: 2.9.2(webpack@5.99.9) 1511 | picocolors: 1.1.1 1512 | reduce-configs: 1.1.0 1513 | tsconfig-paths-webpack-plugin: 4.2.0 1514 | webpack: 5.99.9 1515 | transitivePeerDependencies: 1516 | - '@rspack/core' 1517 | - '@swc/core' 1518 | - esbuild 1519 | - uglify-js 1520 | - webpack-cli 1521 | 1522 | '@rslib/core@0.9.1(typescript@5.8.3)': 1523 | dependencies: 1524 | '@rsbuild/core': 1.3.22 1525 | rsbuild-plugin-dts: 0.9.1(@rsbuild/core@1.3.22)(typescript@5.8.3) 1526 | tinyglobby: 0.2.14 1527 | optionalDependencies: 1528 | typescript: 5.8.3 1529 | 1530 | '@rspack/binding-darwin-arm64@1.3.12': 1531 | optional: true 1532 | 1533 | '@rspack/binding-darwin-arm64@1.3.13': 1534 | optional: true 1535 | 1536 | '@rspack/binding-darwin-x64@1.3.12': 1537 | optional: true 1538 | 1539 | '@rspack/binding-darwin-x64@1.3.13': 1540 | optional: true 1541 | 1542 | '@rspack/binding-linux-arm64-gnu@1.3.12': 1543 | optional: true 1544 | 1545 | '@rspack/binding-linux-arm64-gnu@1.3.13': 1546 | optional: true 1547 | 1548 | '@rspack/binding-linux-arm64-musl@1.3.12': 1549 | optional: true 1550 | 1551 | '@rspack/binding-linux-arm64-musl@1.3.13': 1552 | optional: true 1553 | 1554 | '@rspack/binding-linux-x64-gnu@1.3.12': 1555 | optional: true 1556 | 1557 | '@rspack/binding-linux-x64-gnu@1.3.13': 1558 | optional: true 1559 | 1560 | '@rspack/binding-linux-x64-musl@1.3.12': 1561 | optional: true 1562 | 1563 | '@rspack/binding-linux-x64-musl@1.3.13': 1564 | optional: true 1565 | 1566 | '@rspack/binding-win32-arm64-msvc@1.3.12': 1567 | optional: true 1568 | 1569 | '@rspack/binding-win32-arm64-msvc@1.3.13': 1570 | optional: true 1571 | 1572 | '@rspack/binding-win32-ia32-msvc@1.3.12': 1573 | optional: true 1574 | 1575 | '@rspack/binding-win32-ia32-msvc@1.3.13': 1576 | optional: true 1577 | 1578 | '@rspack/binding-win32-x64-msvc@1.3.12': 1579 | optional: true 1580 | 1581 | '@rspack/binding-win32-x64-msvc@1.3.13': 1582 | optional: true 1583 | 1584 | '@rspack/binding@1.3.12': 1585 | optionalDependencies: 1586 | '@rspack/binding-darwin-arm64': 1.3.12 1587 | '@rspack/binding-darwin-x64': 1.3.12 1588 | '@rspack/binding-linux-arm64-gnu': 1.3.12 1589 | '@rspack/binding-linux-arm64-musl': 1.3.12 1590 | '@rspack/binding-linux-x64-gnu': 1.3.12 1591 | '@rspack/binding-linux-x64-musl': 1.3.12 1592 | '@rspack/binding-win32-arm64-msvc': 1.3.12 1593 | '@rspack/binding-win32-ia32-msvc': 1.3.12 1594 | '@rspack/binding-win32-x64-msvc': 1.3.12 1595 | 1596 | '@rspack/binding@1.3.13': 1597 | optionalDependencies: 1598 | '@rspack/binding-darwin-arm64': 1.3.13 1599 | '@rspack/binding-darwin-x64': 1.3.13 1600 | '@rspack/binding-linux-arm64-gnu': 1.3.13 1601 | '@rspack/binding-linux-arm64-musl': 1.3.13 1602 | '@rspack/binding-linux-x64-gnu': 1.3.13 1603 | '@rspack/binding-linux-x64-musl': 1.3.13 1604 | '@rspack/binding-win32-arm64-msvc': 1.3.13 1605 | '@rspack/binding-win32-ia32-msvc': 1.3.13 1606 | '@rspack/binding-win32-x64-msvc': 1.3.13 1607 | 1608 | '@rspack/core@1.3.12(@swc/helpers@0.5.17)': 1609 | dependencies: 1610 | '@module-federation/runtime-tools': 0.14.0 1611 | '@rspack/binding': 1.3.12 1612 | '@rspack/lite-tapable': 1.0.1 1613 | caniuse-lite: 1.0.30001721 1614 | optionalDependencies: 1615 | '@swc/helpers': 0.5.17 1616 | 1617 | '@rspack/core@1.3.13(@swc/helpers@0.5.17)': 1618 | dependencies: 1619 | '@module-federation/runtime-tools': 0.14.3 1620 | '@rspack/binding': 1.3.13 1621 | '@rspack/lite-tapable': 1.0.1 1622 | optionalDependencies: 1623 | '@swc/helpers': 0.5.17 1624 | 1625 | '@rspack/lite-tapable@1.0.1': {} 1626 | 1627 | '@swc/helpers@0.5.17': 1628 | dependencies: 1629 | tslib: 2.8.1 1630 | 1631 | '@types/eslint-scope@3.7.7': 1632 | dependencies: 1633 | '@types/eslint': 9.6.1 1634 | '@types/estree': 1.0.6 1635 | 1636 | '@types/eslint@9.6.1': 1637 | dependencies: 1638 | '@types/estree': 1.0.6 1639 | '@types/json-schema': 7.0.15 1640 | 1641 | '@types/estree@1.0.6': {} 1642 | 1643 | '@types/html-minifier-terser@6.1.0': {} 1644 | 1645 | '@types/json-schema@7.0.15': {} 1646 | 1647 | '@types/node@22.15.29': 1648 | dependencies: 1649 | undici-types: 6.21.0 1650 | 1651 | '@types/semver@7.7.0': {} 1652 | 1653 | '@webassemblyjs/ast@1.14.1': 1654 | dependencies: 1655 | '@webassemblyjs/helper-numbers': 1.13.2 1656 | '@webassemblyjs/helper-wasm-bytecode': 1.13.2 1657 | 1658 | '@webassemblyjs/floating-point-hex-parser@1.13.2': {} 1659 | 1660 | '@webassemblyjs/helper-api-error@1.13.2': {} 1661 | 1662 | '@webassemblyjs/helper-buffer@1.14.1': {} 1663 | 1664 | '@webassemblyjs/helper-numbers@1.13.2': 1665 | dependencies: 1666 | '@webassemblyjs/floating-point-hex-parser': 1.13.2 1667 | '@webassemblyjs/helper-api-error': 1.13.2 1668 | '@xtuc/long': 4.2.2 1669 | 1670 | '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} 1671 | 1672 | '@webassemblyjs/helper-wasm-section@1.14.1': 1673 | dependencies: 1674 | '@webassemblyjs/ast': 1.14.1 1675 | '@webassemblyjs/helper-buffer': 1.14.1 1676 | '@webassemblyjs/helper-wasm-bytecode': 1.13.2 1677 | '@webassemblyjs/wasm-gen': 1.14.1 1678 | 1679 | '@webassemblyjs/ieee754@1.13.2': 1680 | dependencies: 1681 | '@xtuc/ieee754': 1.2.0 1682 | 1683 | '@webassemblyjs/leb128@1.13.2': 1684 | dependencies: 1685 | '@xtuc/long': 4.2.2 1686 | 1687 | '@webassemblyjs/utf8@1.13.2': {} 1688 | 1689 | '@webassemblyjs/wasm-edit@1.14.1': 1690 | dependencies: 1691 | '@webassemblyjs/ast': 1.14.1 1692 | '@webassemblyjs/helper-buffer': 1.14.1 1693 | '@webassemblyjs/helper-wasm-bytecode': 1.13.2 1694 | '@webassemblyjs/helper-wasm-section': 1.14.1 1695 | '@webassemblyjs/wasm-gen': 1.14.1 1696 | '@webassemblyjs/wasm-opt': 1.14.1 1697 | '@webassemblyjs/wasm-parser': 1.14.1 1698 | '@webassemblyjs/wast-printer': 1.14.1 1699 | 1700 | '@webassemblyjs/wasm-gen@1.14.1': 1701 | dependencies: 1702 | '@webassemblyjs/ast': 1.14.1 1703 | '@webassemblyjs/helper-wasm-bytecode': 1.13.2 1704 | '@webassemblyjs/ieee754': 1.13.2 1705 | '@webassemblyjs/leb128': 1.13.2 1706 | '@webassemblyjs/utf8': 1.13.2 1707 | 1708 | '@webassemblyjs/wasm-opt@1.14.1': 1709 | dependencies: 1710 | '@webassemblyjs/ast': 1.14.1 1711 | '@webassemblyjs/helper-buffer': 1.14.1 1712 | '@webassemblyjs/wasm-gen': 1.14.1 1713 | '@webassemblyjs/wasm-parser': 1.14.1 1714 | 1715 | '@webassemblyjs/wasm-parser@1.14.1': 1716 | dependencies: 1717 | '@webassemblyjs/ast': 1.14.1 1718 | '@webassemblyjs/helper-api-error': 1.13.2 1719 | '@webassemblyjs/helper-wasm-bytecode': 1.13.2 1720 | '@webassemblyjs/ieee754': 1.13.2 1721 | '@webassemblyjs/leb128': 1.13.2 1722 | '@webassemblyjs/utf8': 1.13.2 1723 | 1724 | '@webassemblyjs/wast-printer@1.14.1': 1725 | dependencies: 1726 | '@webassemblyjs/ast': 1.14.1 1727 | '@xtuc/long': 4.2.2 1728 | 1729 | '@xtuc/ieee754@1.2.0': {} 1730 | 1731 | '@xtuc/long@4.2.2': {} 1732 | 1733 | acorn@8.14.0: {} 1734 | 1735 | ajv-formats@2.1.1(ajv@8.17.1): 1736 | optionalDependencies: 1737 | ajv: 8.17.1 1738 | 1739 | ajv-keywords@5.1.0(ajv@8.17.1): 1740 | dependencies: 1741 | ajv: 8.17.1 1742 | fast-deep-equal: 3.1.3 1743 | 1744 | ajv@8.17.1: 1745 | dependencies: 1746 | fast-deep-equal: 3.1.3 1747 | fast-uri: 3.0.3 1748 | json-schema-traverse: 1.0.0 1749 | require-from-string: 2.0.2 1750 | 1751 | ansi-regex@5.0.1: {} 1752 | 1753 | ansi-regex@6.1.0: {} 1754 | 1755 | ansi-styles@4.3.0: 1756 | dependencies: 1757 | color-convert: 2.0.1 1758 | 1759 | ansi-styles@6.2.1: {} 1760 | 1761 | any-promise@1.3.0: {} 1762 | 1763 | anymatch@3.1.3: 1764 | dependencies: 1765 | normalize-path: 3.0.0 1766 | picomatch: 2.3.1 1767 | 1768 | arg@5.0.2: {} 1769 | 1770 | balanced-match@1.0.2: {} 1771 | 1772 | binary-extensions@2.3.0: {} 1773 | 1774 | boolbase@1.0.0: {} 1775 | 1776 | brace-expansion@2.0.1: 1777 | dependencies: 1778 | balanced-match: 1.0.2 1779 | 1780 | braces@3.0.3: 1781 | dependencies: 1782 | fill-range: 7.1.1 1783 | 1784 | browserslist@4.24.2: 1785 | dependencies: 1786 | caniuse-lite: 1.0.30001716 1787 | electron-to-chromium: 1.5.67 1788 | node-releases: 2.0.18 1789 | update-browserslist-db: 1.1.1(browserslist@4.24.2) 1790 | 1791 | buffer-from@1.1.2: {} 1792 | 1793 | camel-case@4.1.2: 1794 | dependencies: 1795 | pascal-case: 3.1.2 1796 | tslib: 2.8.1 1797 | 1798 | camelcase-css@2.0.1: {} 1799 | 1800 | caniuse-lite@1.0.30001716: {} 1801 | 1802 | caniuse-lite@1.0.30001721: {} 1803 | 1804 | chalk@4.1.2: 1805 | dependencies: 1806 | ansi-styles: 4.3.0 1807 | supports-color: 7.2.0 1808 | 1809 | chokidar@3.6.0: 1810 | dependencies: 1811 | anymatch: 3.1.3 1812 | braces: 3.0.3 1813 | glob-parent: 5.1.2 1814 | is-binary-path: 2.1.0 1815 | is-glob: 4.0.3 1816 | normalize-path: 3.0.0 1817 | readdirp: 3.6.0 1818 | optionalDependencies: 1819 | fsevents: 2.3.3 1820 | 1821 | chrome-trace-event@1.0.4: {} 1822 | 1823 | clean-css@5.3.3: 1824 | dependencies: 1825 | source-map: 0.6.1 1826 | 1827 | color-convert@2.0.1: 1828 | dependencies: 1829 | color-name: 1.1.4 1830 | 1831 | color-name@1.1.4: {} 1832 | 1833 | commander@2.20.3: {} 1834 | 1835 | commander@4.1.1: {} 1836 | 1837 | commander@8.3.0: {} 1838 | 1839 | copy-webpack-plugin@11.0.0(webpack@5.99.9): 1840 | dependencies: 1841 | fast-glob: 3.3.2 1842 | glob-parent: 6.0.2 1843 | globby: 13.2.2 1844 | normalize-path: 3.0.0 1845 | schema-utils: 4.3.0 1846 | serialize-javascript: 6.0.2 1847 | webpack: 5.99.9 1848 | 1849 | core-js@3.42.0: {} 1850 | 1851 | cross-spawn@7.0.6: 1852 | dependencies: 1853 | path-key: 3.1.1 1854 | shebang-command: 2.0.0 1855 | which: 2.0.2 1856 | 1857 | css-select@4.3.0: 1858 | dependencies: 1859 | boolbase: 1.0.0 1860 | css-what: 6.1.0 1861 | domhandler: 4.3.1 1862 | domutils: 2.8.0 1863 | nth-check: 2.1.1 1864 | 1865 | css-what@6.1.0: {} 1866 | 1867 | cssesc@3.0.0: {} 1868 | 1869 | didyoumean@1.2.2: {} 1870 | 1871 | dir-glob@3.0.1: 1872 | dependencies: 1873 | path-type: 4.0.0 1874 | 1875 | dlv@1.1.3: {} 1876 | 1877 | dom-converter@0.2.0: 1878 | dependencies: 1879 | utila: 0.4.0 1880 | 1881 | dom-serializer@1.4.1: 1882 | dependencies: 1883 | domelementtype: 2.3.0 1884 | domhandler: 4.3.1 1885 | entities: 2.2.0 1886 | 1887 | domelementtype@2.3.0: {} 1888 | 1889 | domhandler@4.3.1: 1890 | dependencies: 1891 | domelementtype: 2.3.0 1892 | 1893 | domutils@2.8.0: 1894 | dependencies: 1895 | dom-serializer: 1.4.1 1896 | domelementtype: 2.3.0 1897 | domhandler: 4.3.1 1898 | 1899 | dot-case@3.0.4: 1900 | dependencies: 1901 | no-case: 3.0.4 1902 | tslib: 2.8.1 1903 | 1904 | eastasianwidth@0.2.0: {} 1905 | 1906 | electron-to-chromium@1.5.67: {} 1907 | 1908 | emoji-regex@8.0.0: {} 1909 | 1910 | emoji-regex@9.2.2: {} 1911 | 1912 | enhanced-resolve@5.17.1: 1913 | dependencies: 1914 | graceful-fs: 4.2.11 1915 | tapable: 2.2.1 1916 | 1917 | entities@2.2.0: {} 1918 | 1919 | es-module-lexer@1.5.4: {} 1920 | 1921 | escalade@3.2.0: {} 1922 | 1923 | eslint-scope@5.1.1: 1924 | dependencies: 1925 | esrecurse: 4.3.0 1926 | estraverse: 4.3.0 1927 | 1928 | esrecurse@4.3.0: 1929 | dependencies: 1930 | estraverse: 5.3.0 1931 | 1932 | estraverse@4.3.0: {} 1933 | 1934 | estraverse@5.3.0: {} 1935 | 1936 | estree-walker@2.0.2: {} 1937 | 1938 | events@3.3.0: {} 1939 | 1940 | fast-deep-equal@3.1.3: {} 1941 | 1942 | fast-glob@3.3.2: 1943 | dependencies: 1944 | '@nodelib/fs.stat': 2.0.5 1945 | '@nodelib/fs.walk': 1.2.8 1946 | glob-parent: 5.1.2 1947 | merge2: 1.4.1 1948 | micromatch: 4.0.8 1949 | 1950 | fast-uri@3.0.3: {} 1951 | 1952 | fastq@1.17.1: 1953 | dependencies: 1954 | reusify: 1.0.4 1955 | 1956 | fdir@6.4.4(picomatch@4.0.2): 1957 | optionalDependencies: 1958 | picomatch: 4.0.2 1959 | 1960 | fill-range@7.1.1: 1961 | dependencies: 1962 | to-regex-range: 5.0.1 1963 | 1964 | foreground-child@3.3.0: 1965 | dependencies: 1966 | cross-spawn: 7.0.6 1967 | signal-exit: 4.1.0 1968 | 1969 | fsevents@2.3.2: 1970 | optional: true 1971 | 1972 | fsevents@2.3.3: 1973 | optional: true 1974 | 1975 | function-bind@1.1.2: {} 1976 | 1977 | glob-parent@5.1.2: 1978 | dependencies: 1979 | is-glob: 4.0.3 1980 | 1981 | glob-parent@6.0.2: 1982 | dependencies: 1983 | is-glob: 4.0.3 1984 | 1985 | glob-to-regexp@0.4.1: {} 1986 | 1987 | glob@10.4.5: 1988 | dependencies: 1989 | foreground-child: 3.3.0 1990 | jackspeak: 3.4.3 1991 | minimatch: 9.0.5 1992 | minipass: 7.1.2 1993 | package-json-from-dist: 1.0.1 1994 | path-scurry: 1.11.1 1995 | 1996 | globby@13.2.2: 1997 | dependencies: 1998 | dir-glob: 3.0.1 1999 | fast-glob: 3.3.2 2000 | ignore: 5.3.2 2001 | merge2: 1.4.1 2002 | slash: 4.0.0 2003 | 2004 | graceful-fs@4.2.11: {} 2005 | 2006 | has-flag@4.0.0: {} 2007 | 2008 | hasown@2.0.2: 2009 | dependencies: 2010 | function-bind: 1.1.2 2011 | 2012 | he@1.2.0: {} 2013 | 2014 | html-minifier-terser@6.1.0: 2015 | dependencies: 2016 | camel-case: 4.1.2 2017 | clean-css: 5.3.3 2018 | commander: 8.3.0 2019 | he: 1.2.0 2020 | param-case: 3.0.4 2021 | relateurl: 0.2.7 2022 | terser: 5.36.0 2023 | 2024 | html-webpack-plugin@5.6.3(@rspack/core@1.3.13(@swc/helpers@0.5.17))(webpack@5.99.9): 2025 | dependencies: 2026 | '@types/html-minifier-terser': 6.1.0 2027 | html-minifier-terser: 6.1.0 2028 | lodash: 4.17.21 2029 | pretty-error: 4.0.0 2030 | tapable: 2.2.1 2031 | optionalDependencies: 2032 | '@rspack/core': 1.3.13(@swc/helpers@0.5.17) 2033 | webpack: 5.99.9 2034 | 2035 | htmlparser2@6.1.0: 2036 | dependencies: 2037 | domelementtype: 2.3.0 2038 | domhandler: 4.3.1 2039 | domutils: 2.8.0 2040 | entities: 2.2.0 2041 | 2042 | ignore@5.3.2: {} 2043 | 2044 | is-binary-path@2.1.0: 2045 | dependencies: 2046 | binary-extensions: 2.3.0 2047 | 2048 | is-core-module@2.15.1: 2049 | dependencies: 2050 | hasown: 2.0.2 2051 | 2052 | is-extglob@2.1.1: {} 2053 | 2054 | is-fullwidth-code-point@3.0.0: {} 2055 | 2056 | is-glob@4.0.3: 2057 | dependencies: 2058 | is-extglob: 2.1.1 2059 | 2060 | is-number@7.0.0: {} 2061 | 2062 | isexe@2.0.0: {} 2063 | 2064 | jackspeak@3.4.3: 2065 | dependencies: 2066 | '@isaacs/cliui': 8.0.2 2067 | optionalDependencies: 2068 | '@pkgjs/parseargs': 0.11.0 2069 | 2070 | jest-worker@27.5.1: 2071 | dependencies: 2072 | '@types/node': 22.15.29 2073 | merge-stream: 2.0.0 2074 | supports-color: 8.1.1 2075 | 2076 | jiti@1.21.6: {} 2077 | 2078 | jiti@2.4.2: {} 2079 | 2080 | json-parse-even-better-errors@2.3.1: {} 2081 | 2082 | json-schema-traverse@1.0.0: {} 2083 | 2084 | json5@2.2.3: {} 2085 | 2086 | lilconfig@3.1.3: {} 2087 | 2088 | lines-and-columns@1.2.4: {} 2089 | 2090 | loader-runner@4.3.0: {} 2091 | 2092 | lodash@4.17.21: {} 2093 | 2094 | lower-case@2.0.2: 2095 | dependencies: 2096 | tslib: 2.8.1 2097 | 2098 | lru-cache@10.4.3: {} 2099 | 2100 | magic-string@0.30.17: 2101 | dependencies: 2102 | '@jridgewell/sourcemap-codec': 1.5.0 2103 | 2104 | merge-stream@2.0.0: {} 2105 | 2106 | merge2@1.4.1: {} 2107 | 2108 | micromatch@4.0.8: 2109 | dependencies: 2110 | braces: 3.0.3 2111 | picomatch: 2.3.1 2112 | 2113 | mime-db@1.52.0: {} 2114 | 2115 | mime-types@2.1.35: 2116 | dependencies: 2117 | mime-db: 1.52.0 2118 | 2119 | mini-css-extract-plugin@2.9.2(webpack@5.99.9): 2120 | dependencies: 2121 | schema-utils: 4.3.0 2122 | tapable: 2.2.1 2123 | webpack: 5.99.9 2124 | 2125 | minimatch@9.0.5: 2126 | dependencies: 2127 | brace-expansion: 2.0.1 2128 | 2129 | minimist@1.2.8: {} 2130 | 2131 | minipass@7.1.2: {} 2132 | 2133 | mz@2.7.0: 2134 | dependencies: 2135 | any-promise: 1.3.0 2136 | object-assign: 4.1.1 2137 | thenify-all: 1.6.0 2138 | 2139 | nanoid@3.3.11: {} 2140 | 2141 | neo-async@2.6.2: {} 2142 | 2143 | no-case@3.0.4: 2144 | dependencies: 2145 | lower-case: 2.0.2 2146 | tslib: 2.8.1 2147 | 2148 | node-releases@2.0.18: {} 2149 | 2150 | normalize-path@3.0.0: {} 2151 | 2152 | nth-check@2.1.1: 2153 | dependencies: 2154 | boolbase: 1.0.0 2155 | 2156 | object-assign@4.1.1: {} 2157 | 2158 | object-hash@3.0.0: {} 2159 | 2160 | package-json-from-dist@1.0.1: {} 2161 | 2162 | param-case@3.0.4: 2163 | dependencies: 2164 | dot-case: 3.0.4 2165 | tslib: 2.8.1 2166 | 2167 | pascal-case@3.1.2: 2168 | dependencies: 2169 | no-case: 3.0.4 2170 | tslib: 2.8.1 2171 | 2172 | path-key@3.1.1: {} 2173 | 2174 | path-parse@1.0.7: {} 2175 | 2176 | path-scurry@1.11.1: 2177 | dependencies: 2178 | lru-cache: 10.4.3 2179 | minipass: 7.1.2 2180 | 2181 | path-type@4.0.0: {} 2182 | 2183 | picocolors@1.1.1: {} 2184 | 2185 | picomatch@2.3.1: {} 2186 | 2187 | picomatch@4.0.2: {} 2188 | 2189 | pify@2.3.0: {} 2190 | 2191 | pirates@4.0.6: {} 2192 | 2193 | playwright-core@1.52.0: {} 2194 | 2195 | playwright@1.52.0: 2196 | dependencies: 2197 | playwright-core: 1.52.0 2198 | optionalDependencies: 2199 | fsevents: 2.3.2 2200 | 2201 | postcss-import@15.1.0(postcss@8.5.4): 2202 | dependencies: 2203 | postcss: 8.5.4 2204 | postcss-value-parser: 4.2.0 2205 | read-cache: 1.0.0 2206 | resolve: 1.22.8 2207 | 2208 | postcss-js@4.0.1(postcss@8.5.4): 2209 | dependencies: 2210 | camelcase-css: 2.0.1 2211 | postcss: 8.5.4 2212 | 2213 | postcss-load-config@4.0.2(postcss@8.5.4): 2214 | dependencies: 2215 | lilconfig: 3.1.3 2216 | yaml: 2.6.1 2217 | optionalDependencies: 2218 | postcss: 8.5.4 2219 | 2220 | postcss-nested@6.2.0(postcss@8.5.4): 2221 | dependencies: 2222 | postcss: 8.5.4 2223 | postcss-selector-parser: 6.1.2 2224 | 2225 | postcss-selector-parser@6.1.2: 2226 | dependencies: 2227 | cssesc: 3.0.0 2228 | util-deprecate: 1.0.2 2229 | 2230 | postcss-value-parser@4.2.0: {} 2231 | 2232 | postcss@8.5.4: 2233 | dependencies: 2234 | nanoid: 3.3.11 2235 | picocolors: 1.1.1 2236 | source-map-js: 1.2.1 2237 | 2238 | pretty-error@4.0.0: 2239 | dependencies: 2240 | lodash: 4.17.21 2241 | renderkid: 3.0.0 2242 | 2243 | queue-microtask@1.2.3: {} 2244 | 2245 | randombytes@2.1.0: 2246 | dependencies: 2247 | safe-buffer: 5.2.1 2248 | 2249 | read-cache@1.0.0: 2250 | dependencies: 2251 | pify: 2.3.0 2252 | 2253 | readdirp@3.6.0: 2254 | dependencies: 2255 | picomatch: 2.3.1 2256 | 2257 | reduce-configs@1.1.0: {} 2258 | 2259 | relateurl@0.2.7: {} 2260 | 2261 | renderkid@3.0.0: 2262 | dependencies: 2263 | css-select: 4.3.0 2264 | dom-converter: 0.2.0 2265 | htmlparser2: 6.1.0 2266 | lodash: 4.17.21 2267 | strip-ansi: 6.0.1 2268 | 2269 | require-from-string@2.0.2: {} 2270 | 2271 | resolve@1.22.8: 2272 | dependencies: 2273 | is-core-module: 2.15.1 2274 | path-parse: 1.0.7 2275 | supports-preserve-symlinks-flag: 1.0.0 2276 | 2277 | reusify@1.0.4: {} 2278 | 2279 | rsbuild-plugin-dts@0.9.1(@rsbuild/core@1.3.22)(typescript@5.8.3): 2280 | dependencies: 2281 | '@ast-grep/napi': 0.37.0 2282 | '@rsbuild/core': 1.3.22 2283 | magic-string: 0.30.17 2284 | picocolors: 1.1.1 2285 | tinyglobby: 0.2.14 2286 | tsconfig-paths: 4.2.0 2287 | optionalDependencies: 2288 | typescript: 5.8.3 2289 | 2290 | run-parallel@1.2.0: 2291 | dependencies: 2292 | queue-microtask: 1.2.3 2293 | 2294 | safe-buffer@5.2.1: {} 2295 | 2296 | schema-utils@4.3.0: 2297 | dependencies: 2298 | '@types/json-schema': 7.0.15 2299 | ajv: 8.17.1 2300 | ajv-formats: 2.1.1(ajv@8.17.1) 2301 | ajv-keywords: 5.1.0(ajv@8.17.1) 2302 | 2303 | schema-utils@4.3.2: 2304 | dependencies: 2305 | '@types/json-schema': 7.0.15 2306 | ajv: 8.17.1 2307 | ajv-formats: 2.1.1(ajv@8.17.1) 2308 | ajv-keywords: 5.1.0(ajv@8.17.1) 2309 | 2310 | semver@7.7.2: {} 2311 | 2312 | serialize-javascript@6.0.2: 2313 | dependencies: 2314 | randombytes: 2.1.0 2315 | 2316 | shebang-command@2.0.0: 2317 | dependencies: 2318 | shebang-regex: 3.0.0 2319 | 2320 | shebang-regex@3.0.0: {} 2321 | 2322 | signal-exit@4.1.0: {} 2323 | 2324 | simple-git-hooks@2.13.0: {} 2325 | 2326 | slash@4.0.0: {} 2327 | 2328 | source-map-js@1.2.1: {} 2329 | 2330 | source-map-support@0.5.21: 2331 | dependencies: 2332 | buffer-from: 1.1.2 2333 | source-map: 0.6.1 2334 | 2335 | source-map@0.6.1: {} 2336 | 2337 | string-width@4.2.3: 2338 | dependencies: 2339 | emoji-regex: 8.0.0 2340 | is-fullwidth-code-point: 3.0.0 2341 | strip-ansi: 6.0.1 2342 | 2343 | string-width@5.1.2: 2344 | dependencies: 2345 | eastasianwidth: 0.2.0 2346 | emoji-regex: 9.2.2 2347 | strip-ansi: 7.1.0 2348 | 2349 | strip-ansi@6.0.1: 2350 | dependencies: 2351 | ansi-regex: 5.0.1 2352 | 2353 | strip-ansi@7.1.0: 2354 | dependencies: 2355 | ansi-regex: 6.1.0 2356 | 2357 | strip-bom@3.0.0: {} 2358 | 2359 | sucrase@3.35.0: 2360 | dependencies: 2361 | '@jridgewell/gen-mapping': 0.3.5 2362 | commander: 4.1.1 2363 | glob: 10.4.5 2364 | lines-and-columns: 1.2.4 2365 | mz: 2.7.0 2366 | pirates: 4.0.6 2367 | ts-interface-checker: 0.1.13 2368 | 2369 | supports-color@7.2.0: 2370 | dependencies: 2371 | has-flag: 4.0.0 2372 | 2373 | supports-color@8.1.1: 2374 | dependencies: 2375 | has-flag: 4.0.0 2376 | 2377 | supports-preserve-symlinks-flag@1.0.0: {} 2378 | 2379 | tailwindcss@3.4.17: 2380 | dependencies: 2381 | '@alloc/quick-lru': 5.2.0 2382 | arg: 5.0.2 2383 | chokidar: 3.6.0 2384 | didyoumean: 1.2.2 2385 | dlv: 1.1.3 2386 | fast-glob: 3.3.2 2387 | glob-parent: 6.0.2 2388 | is-glob: 4.0.3 2389 | jiti: 1.21.6 2390 | lilconfig: 3.1.3 2391 | micromatch: 4.0.8 2392 | normalize-path: 3.0.0 2393 | object-hash: 3.0.0 2394 | picocolors: 1.1.1 2395 | postcss: 8.5.4 2396 | postcss-import: 15.1.0(postcss@8.5.4) 2397 | postcss-js: 4.0.1(postcss@8.5.4) 2398 | postcss-load-config: 4.0.2(postcss@8.5.4) 2399 | postcss-nested: 6.2.0(postcss@8.5.4) 2400 | postcss-selector-parser: 6.1.2 2401 | resolve: 1.22.8 2402 | sucrase: 3.35.0 2403 | transitivePeerDependencies: 2404 | - ts-node 2405 | 2406 | tapable@2.2.1: {} 2407 | 2408 | terser-webpack-plugin@5.3.12(webpack@5.99.9): 2409 | dependencies: 2410 | '@jridgewell/trace-mapping': 0.3.25 2411 | jest-worker: 27.5.1 2412 | schema-utils: 4.3.2 2413 | serialize-javascript: 6.0.2 2414 | terser: 5.36.0 2415 | webpack: 5.99.9 2416 | 2417 | terser@5.36.0: 2418 | dependencies: 2419 | '@jridgewell/source-map': 0.3.6 2420 | acorn: 8.14.0 2421 | commander: 2.20.3 2422 | source-map-support: 0.5.21 2423 | 2424 | thenify-all@1.6.0: 2425 | dependencies: 2426 | thenify: 3.3.1 2427 | 2428 | thenify@3.3.1: 2429 | dependencies: 2430 | any-promise: 1.3.0 2431 | 2432 | tinyglobby@0.2.14: 2433 | dependencies: 2434 | fdir: 6.4.4(picomatch@4.0.2) 2435 | picomatch: 4.0.2 2436 | 2437 | to-regex-range@5.0.1: 2438 | dependencies: 2439 | is-number: 7.0.0 2440 | 2441 | ts-interface-checker@0.1.13: {} 2442 | 2443 | tsconfig-paths-webpack-plugin@4.2.0: 2444 | dependencies: 2445 | chalk: 4.1.2 2446 | enhanced-resolve: 5.17.1 2447 | tapable: 2.2.1 2448 | tsconfig-paths: 4.2.0 2449 | 2450 | tsconfig-paths@4.2.0: 2451 | dependencies: 2452 | json5: 2.2.3 2453 | minimist: 1.2.8 2454 | strip-bom: 3.0.0 2455 | 2456 | tslib@2.8.1: {} 2457 | 2458 | typescript@5.8.3: {} 2459 | 2460 | undici-types@6.21.0: {} 2461 | 2462 | update-browserslist-db@1.1.1(browserslist@4.24.2): 2463 | dependencies: 2464 | browserslist: 4.24.2 2465 | escalade: 3.2.0 2466 | picocolors: 1.1.1 2467 | 2468 | util-deprecate@1.0.2: {} 2469 | 2470 | utila@0.4.0: {} 2471 | 2472 | watchpack@2.4.2: 2473 | dependencies: 2474 | glob-to-regexp: 0.4.1 2475 | graceful-fs: 4.2.11 2476 | 2477 | webpack-sources@3.2.3: {} 2478 | 2479 | webpack@5.99.9: 2480 | dependencies: 2481 | '@types/eslint-scope': 3.7.7 2482 | '@types/estree': 1.0.6 2483 | '@types/json-schema': 7.0.15 2484 | '@webassemblyjs/ast': 1.14.1 2485 | '@webassemblyjs/wasm-edit': 1.14.1 2486 | '@webassemblyjs/wasm-parser': 1.14.1 2487 | acorn: 8.14.0 2488 | browserslist: 4.24.2 2489 | chrome-trace-event: 1.0.4 2490 | enhanced-resolve: 5.17.1 2491 | es-module-lexer: 1.5.4 2492 | eslint-scope: 5.1.1 2493 | events: 3.3.0 2494 | glob-to-regexp: 0.4.1 2495 | graceful-fs: 4.2.11 2496 | json-parse-even-better-errors: 2.3.1 2497 | loader-runner: 4.3.0 2498 | mime-types: 2.1.35 2499 | neo-async: 2.6.2 2500 | schema-utils: 4.3.2 2501 | tapable: 2.2.1 2502 | terser-webpack-plugin: 5.3.12(webpack@5.99.9) 2503 | watchpack: 2.4.2 2504 | webpack-sources: 3.2.3 2505 | transitivePeerDependencies: 2506 | - '@swc/core' 2507 | - esbuild 2508 | - uglify-js 2509 | 2510 | which@2.0.2: 2511 | dependencies: 2512 | isexe: 2.0.0 2513 | 2514 | wrap-ansi@7.0.0: 2515 | dependencies: 2516 | ansi-styles: 4.3.0 2517 | string-width: 4.2.3 2518 | strip-ansi: 6.0.1 2519 | 2520 | wrap-ansi@8.1.0: 2521 | dependencies: 2522 | ansi-styles: 6.2.1 2523 | string-width: 5.1.2 2524 | strip-ansi: 7.1.0 2525 | 2526 | yaml@2.6.1: {} 2527 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'playground' 3 | -------------------------------------------------------------------------------- /rslib.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@rslib/core'; 2 | 3 | export default defineConfig({ 4 | lib: [ 5 | { format: 'esm', syntax: 'es2021', dts: true }, 6 | { format: 'cjs', syntax: 'es2021' }, 7 | ], 8 | }); 9 | -------------------------------------------------------------------------------- /src/Set.prototype.isSubsetOf.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * See: {@link https://github.com/tc39/proposal-set-methods | Set Methods for JavaScript} 3 | */ 4 | export function isSubsetOf(a: ReadonlySet, b: ReadonlySet): boolean { 5 | // Node.js v22 will have native implementation. 6 | if (typeof a.isSubsetOf === 'function') { 7 | return a.isSubsetOf(b); 8 | } 9 | 10 | if (a.size > b.size) { 11 | return false; 12 | } 13 | 14 | for (const item of a) { 15 | if (!b.has(item)) { 16 | return false; 17 | } 18 | } 19 | return true; 20 | } 21 | -------------------------------------------------------------------------------- /src/TailwindCSSRspackPlugin.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'node:fs'; 2 | import { mkdir, mkdtemp, readFile, writeFile } from 'node:fs/promises'; 3 | import { createRequire } from 'node:module'; 4 | import { tmpdir } from 'node:os'; 5 | import path from 'node:path'; 6 | import { pathToFileURL } from 'node:url'; 7 | 8 | import { createFilter } from '@rollup/pluginutils'; 9 | import type { PostCSSLoaderOptions, Rspack } from '@rsbuild/core'; 10 | import type { Processor } from 'postcss'; 11 | 12 | import { isSubsetOf } from './Set.prototype.isSubsetOf.js'; 13 | 14 | /** 15 | * The options for {@link TailwindRspackPlugin}. 16 | * 17 | * @public 18 | */ 19 | interface TailwindRspackPluginOptions { 20 | /** 21 | * The path to the configuration of Tailwind CSS. 22 | * 23 | * @example 24 | * 25 | * Use absolute path: 26 | * 27 | * ```js 28 | * // rspack.config.js 29 | * import path from 'node:path' 30 | * import { fileURLToPath } from 'node:url' 31 | * 32 | * import { TailwindRspackPlugin } from 'rsbuild-plugin-tailwindcss' 33 | * 34 | * const __dirname = path.dirname(fileURLToPath(import.meta.url)) 35 | * 36 | * export default { 37 | * plugins: [ 38 | * new TailwindRspackPlugin({ 39 | * config: path.resolve(__dirname, './config/tailwind.config.js'), 40 | * }), 41 | * ], 42 | * } 43 | * ``` 44 | * 45 | * @example 46 | * 47 | * Use relative path: 48 | * 49 | * ```js 50 | * // rspack.config.js 51 | * import { TailwindRspackPlugin } from 'rsbuild-plugin-tailwindcss' 52 | * 53 | * export default { 54 | * plugins: [ 55 | * new TailwindRspackPlugin({ 56 | * config: './config/tailwind.config.js', 57 | * }), 58 | * ], 59 | * } 60 | * ``` 61 | */ 62 | config: string; 63 | 64 | /** 65 | * The modules to be excluded. 66 | * 67 | * If {@link include} is omitted or empty, 68 | * all modules that do not match any of the {@link exclude} patterns will be included. 69 | * Otherwise, only modules that match one or more of the {@link include} patterns 70 | * and do not match any of the {@link exclude} patterns will be included. 71 | * 72 | * @example 73 | * 74 | * ```js 75 | * // rspack.config.js 76 | * import { TailwindRspackPlugin } from 'rsbuild-plugin-tailwindcss' 77 | * 78 | * export default { 79 | * plugins: [ 80 | * new TailwindRspackPlugin({ 81 | * exclude: [ 82 | * './src/store/**', 83 | * /[\\/]node_modules[\\/]/, 84 | * ], 85 | * }), 86 | * ], 87 | * } 88 | * ``` 89 | */ 90 | exclude?: FilterPattern | undefined; 91 | 92 | /** 93 | * The modules to be included using `picomatch` patterns. 94 | * 95 | * If {@link include} is omitted or empty, 96 | * all modules that do not match any of the {@link exclude} patterns will be included. 97 | * Otherwise, only modules that match one or more of the {@link include} patterns 98 | * and do not match any of the {@link exclude} patterns will be included. 99 | * 100 | * @example 101 | * 102 | * ```js 103 | * // rspack.config.js 104 | * import { TailwindRspackPlugin } from 'rsbuild-plugin-tailwindcss' 105 | * 106 | * export default { 107 | * plugins: [ 108 | * new TailwindRspackPlugin({ 109 | * include: [ 110 | * /\.[jt]sx?/, 111 | * ], 112 | * }), 113 | * ], 114 | * } 115 | * ``` 116 | */ 117 | include?: FilterPattern | undefined; 118 | 119 | /** 120 | * The postcss options to be applied. 121 | * 122 | * @example 123 | * 124 | * Use `cssnano`: 125 | * 126 | * ```js 127 | * // rspack.config.js 128 | * import { TailwindRspackPlugin } from 'rsbuild-plugin-tailwindcss' 129 | * 130 | * export default { 131 | * plugins: [ 132 | * new TailwindRspackPlugin({ 133 | * postcssOptions: { 134 | * plugins: { 135 | * cssnano: process.env['NODE_ENV'] === 'production' ? {} : false, 136 | * }, 137 | * }, 138 | * }), 139 | * ], 140 | * } 141 | * ``` 142 | */ 143 | postcssOptions: Exclude< 144 | PostCSSLoaderOptions['postcssOptions'], 145 | (loaderContext: Rspack.LoaderContext) => void 146 | >; 147 | } 148 | 149 | // From `@rollup/pluginutils` 150 | /** 151 | * A valid `picomatch` glob pattern, or array of patterns. 152 | */ 153 | export type FilterPattern = 154 | | ReadonlyArray 155 | | string 156 | | RegExp 157 | | null; 158 | 159 | /** 160 | * The Rspack plugin for Tailwind integration. 161 | * 162 | * @public 163 | */ 164 | class TailwindRspackPlugin { 165 | constructor(private readonly options: TailwindRspackPluginOptions) {} 166 | 167 | /** 168 | * The entry point of a Rspack plugin. 169 | * @param compiler - the Rspack compiler 170 | */ 171 | apply(compiler: Rspack.Compiler): void { 172 | new TailwindRspackPluginImpl(compiler, this.options); 173 | } 174 | } 175 | 176 | export { TailwindRspackPlugin }; 177 | export type { TailwindRspackPluginOptions }; 178 | 179 | class TailwindRspackPluginImpl { 180 | name = 'TailwindRspackPlugin'; 181 | 182 | postcssProcessorCache = new Map< 183 | /** entryName */ string, 184 | [entryModules: ReadonlySet, Processor] 185 | >(); 186 | 187 | constructor( 188 | private compiler: Rspack.Compiler, 189 | private options: TailwindRspackPluginOptions, 190 | ) { 191 | const filter = createFilter(options.include, options.exclude, { 192 | // biome-ignore lint/style/noNonNullAssertion: context should exist 193 | resolve: compiler.options.context!, 194 | }); 195 | 196 | compiler.hooks.thisCompilation.tap(this.name, (compilation) => { 197 | compilation.hooks.processAssets.tapPromise(this.name, async () => { 198 | await Promise.all( 199 | [...compilation.entrypoints.entries()].map( 200 | async ([entryName, entrypoint]) => { 201 | const cssFiles = entrypoint 202 | .getFiles() 203 | .filter((file) => file.endsWith('.css')) 204 | .map((file) => compilation.getAsset(file)) 205 | .filter((file) => !!file); 206 | 207 | if (cssFiles.length === 0) { 208 | // Ignore entrypoint without CSS files. 209 | return; 210 | } 211 | 212 | const cache = this.postcssProcessorCache.get(entryName); 213 | if (compiler.modifiedFiles?.size && cache) { 214 | const [cachedEntryModules, cachedPostcssProcessor] = cache; 215 | if (isSubsetOf(compiler.modifiedFiles, cachedEntryModules)) { 216 | await this.#transformCSSAssets( 217 | compilation, 218 | cachedPostcssProcessor, 219 | cssFiles, 220 | ); 221 | return; 222 | } 223 | } 224 | 225 | // collect all the modules corresponding to specific entry 226 | const entryModules = new Set(); 227 | 228 | for (const chunk of entrypoint.chunks) { 229 | const modules = 230 | compilation.chunkGraph.getChunkModulesIterable(chunk); 231 | for (const module of modules) { 232 | collectModules(module, entryModules); 233 | } 234 | } 235 | 236 | if (compiler.modifiedFiles && cache) { 237 | const [cachedEntryModules, cachedPostcssProcessor] = cache; 238 | if (isSubsetOf(entryModules, cachedEntryModules)) { 239 | await this.#transformCSSAssets( 240 | compilation, 241 | cachedPostcssProcessor, 242 | cssFiles, 243 | ); 244 | return; 245 | } 246 | } 247 | 248 | const [ 249 | { default: postcss }, 250 | { default: tailwindcss }, 251 | configPath, 252 | ] = await Promise.all([ 253 | import('postcss'), 254 | import('tailwindcss'), 255 | this.#prepareTailwindConfig( 256 | entryName, 257 | Array.from(entryModules).filter(filter), 258 | ), 259 | ]); 260 | 261 | const processor = postcss([ 262 | // We use a config path to avoid performance issue of TailwindCSS 263 | // See: https://github.com/tailwindlabs/tailwindcss/issues/14229 264 | tailwindcss({ 265 | config: configPath, 266 | }), 267 | ...(options.postcssOptions?.plugins ?? []), 268 | ]); 269 | 270 | this.postcssProcessorCache.set(entryName, [ 271 | entryModules, 272 | processor, 273 | ]); 274 | 275 | await this.#transformCSSAssets(compilation, processor, cssFiles); 276 | }, 277 | ), 278 | ); 279 | }); 280 | }); 281 | } 282 | 283 | async #transformCSSAssets( 284 | compilation: Rspack.Compilation, 285 | postcssProcessor: Processor, 286 | cssFiles: Array, 287 | ) { 288 | const { RawSource } = this.compiler.webpack.sources; 289 | 290 | // iterate all css asset in entry and inject entry modules into tailwind content 291 | await Promise.all( 292 | cssFiles.map(async (asset) => { 293 | const content = asset.source.source(); 294 | // transform .css which contains tailwind mixin 295 | // FIXME: add custom postcss config 296 | const transformResult = await postcssProcessor.process(content, { 297 | from: asset.name, 298 | ...this.options.postcssOptions, 299 | }); 300 | // FIXME: avoid `updateAsset` when no change is found. 301 | // FIXME: add sourcemap support 302 | compilation.updateAsset(asset.name, new RawSource(transformResult.css)); 303 | }), 304 | ); 305 | } 306 | 307 | async ensureTempDir(entryName: string): Promise { 308 | const prefix = path.join(tmpdir(), entryName); 309 | await mkdir(path.dirname(prefix), { recursive: true }); 310 | return await mkdtemp(prefix); 311 | } 312 | 313 | async #prepareTailwindConfig( 314 | entryName: string, 315 | entryModules: Array, 316 | ): Promise { 317 | const userConfig = path.isAbsolute(this.options.config) 318 | ? this.options.config 319 | : // biome-ignore lint/style/noNonNullAssertion: should have context 320 | path.resolve(this.compiler.options.context!, this.options.config); 321 | 322 | const outputDir = DEBUG 323 | ? path.resolve( 324 | // biome-ignore lint/style/noNonNullAssertion: should have `output.path` 325 | this.compiler.options.output.path!, 326 | '.rsbuild', 327 | entryName, 328 | ) 329 | : await this.ensureTempDir(entryName); 330 | 331 | if (DEBUG) { 332 | await mkdir(outputDir, { recursive: true }); 333 | } 334 | 335 | const [configName, configContent] = await this.#generateTailwindConfig( 336 | userConfig, 337 | entryModules, 338 | ); 339 | const configPath = path.resolve(outputDir, configName); 340 | 341 | await writeFile(configPath, configContent); 342 | 343 | return configPath; 344 | } 345 | 346 | async #resolveTailwindCSSVersion(): Promise { 347 | const require = createRequire(import.meta.url); 348 | const pkgPath = require.resolve('tailwindcss/package.json', { 349 | paths: [this.compiler.context], 350 | }); 351 | 352 | const content = await readFile(pkgPath, 'utf-8'); 353 | 354 | const { version } = JSON.parse(content) as { version: string }; 355 | 356 | return version; 357 | } 358 | 359 | async #generateTailwindConfig( 360 | userConfig: string, 361 | entryModules: string[], 362 | ): Promise<['tailwind.config.mjs' | 'tailwind.config.cjs', string]> { 363 | const version = await this.#resolveTailwindCSSVersion(); 364 | 365 | const { default: satisfies } = await import( 366 | 'semver/functions/satisfies.js' 367 | ); 368 | 369 | const content = JSON.stringify(entryModules); 370 | if (satisfies(version, '^3.3.0')) { 371 | // Tailwind CSS support using ESM configuration in v3.3.0 372 | // See: 373 | // - https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.0 374 | // - https://github.com/tailwindlabs/tailwindcss/pull/10785 375 | // - https://github.com/rspack-contrib/rsbuild-plugin-tailwindcss/issues/18 376 | // 377 | // In this case, we provide an ESM configuration to support both ESM and CJS. 378 | return [ 379 | 'tailwind.config.mjs', 380 | existsSync(userConfig) 381 | ? `\ 382 | import config from '${pathToFileURL(userConfig)}' 383 | export default { 384 | ...config, 385 | content: ${content} 386 | }` 387 | : `\ 388 | export default { 389 | content: ${content} 390 | }`, 391 | ]; 392 | } 393 | 394 | // Otherwise, we provide an CJS configuration since TailwindCSS would always use `require`. 395 | return [ 396 | 'tailwind.config.cjs', 397 | existsSync(userConfig) 398 | ? `\ 399 | const config = require(${JSON.stringify(userConfig)}) 400 | module.exports = { 401 | ...config, 402 | content: ${content} 403 | }` 404 | : `\ 405 | module.exports = { 406 | content: ${content} 407 | }`, 408 | ]; 409 | } 410 | } 411 | 412 | function collectModules( 413 | module: Rspack.Module | Rspack.ConcatenatedModule | Rspack.NormalModule, 414 | entryModules: Set, 415 | ): void { 416 | if ('modules' in module && module.modules) { 417 | for (const innerModule of module.modules) { 418 | collectModules(innerModule, entryModules); 419 | } 420 | } else if ('resource' in module && module.resource) { 421 | // The value of `module.resource` maybe one of them: 422 | // 1. /w/a.js 423 | // 2. /w/a.js?component 424 | 425 | const resource: string = 426 | // rspack doesn't have the property `module.resourceResolveData.path` now. 427 | module.resource.split('?')[0]; 428 | entryModules.add(resource); 429 | } 430 | } 431 | 432 | const DEBUG = (function isDebug() { 433 | if (!process.env.DEBUG) { 434 | return false; 435 | } 436 | 437 | const values = process.env.DEBUG.toLocaleLowerCase().split(','); 438 | return ['rsbuild', 'rsbuild:tailwind', 'rsbuild:*', '*'].some((key) => 439 | values.includes(key), 440 | ); 441 | })(); 442 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | PostCSSLoaderOptions, 3 | RsbuildPlugin, 4 | Rspack, 5 | } from '@rsbuild/core'; 6 | 7 | import { TailwindRspackPlugin } from './TailwindCSSRspackPlugin.js'; 8 | import type { FilterPattern } from './TailwindCSSRspackPlugin.js'; 9 | 10 | export type { FilterPattern }; 11 | 12 | export interface PluginTailwindCSSOptions { 13 | /** 14 | * The path to the configuration of Tailwind CSS. 15 | * 16 | * @remarks 17 | * 18 | * The default value is `tailwind.config.js`. 19 | * 20 | * @example 21 | * 22 | * Use relative path: 23 | * 24 | * ```js 25 | * // rsbuild.config.ts 26 | * import { pluginTailwindCSS } from '@byted-lynx/plugin-tailwindcss' 27 | * 28 | * export default { 29 | * plugins: [ 30 | * pluginTailwindCSS({ 31 | * config: './config/tailwind.config.js', 32 | * }), 33 | * ], 34 | * } 35 | * ``` 36 | * 37 | * @example 38 | * 39 | * Use absolute path: 40 | * 41 | * ```js 42 | * // rsbuild.config.ts 43 | * import path from 'node:path' 44 | * import { fileURLToPath } from 'node:url' 45 | * 46 | * import { pluginTailwindCSS } from 'rsbuild-plugin-tailwindcss' 47 | * 48 | * const __dirname = path.dirname(fileURLToPath(import.meta.url)) 49 | * 50 | * export default { 51 | * plugins: [ 52 | * pluginTailwindCSS({ 53 | * config: path.resolve(__dirname, './config/tailwind.config.js'), 54 | * }), 55 | * ], 56 | * } 57 | * ``` 58 | */ 59 | config?: string; 60 | 61 | /** 62 | * The modules to be excluded using `picomatch` patterns. 63 | * 64 | * If {@link include} is omitted or empty, 65 | * all modules that do not match any of the {@link exclude} patterns will be included. 66 | * Otherwise, only modules that match one or more of the {@link include} patterns 67 | * and do not match any of the {@link exclude} patterns will be included. 68 | * 69 | * @example 70 | * 71 | * ```js 72 | * // rsbuild.config.ts 73 | * import { pluginTailwindCSS } from '@byted-lynx/plugin-tailwindcss' 74 | * 75 | * export default { 76 | * plugins: [ 77 | * pluginTailwindCSS({ 78 | * exclude: [ 79 | * './src/store/**', 80 | * /[\\/]node_modules[\\/]/, 81 | * ], 82 | * }), 83 | * ], 84 | * } 85 | * ``` 86 | */ 87 | exclude?: FilterPattern | undefined; 88 | 89 | /** 90 | * The modules to be included using `picomatch` patterns. 91 | * 92 | * If {@link include} is omitted or empty, 93 | * all modules that do not match any of the {@link exclude} patterns will be included. 94 | * Otherwise, only modules that match one or more of the {@link include} patterns 95 | * and do not match any of the {@link exclude} patterns will be included. 96 | * 97 | * @example 98 | * 99 | * ```js 100 | * // rsbuild.config.ts 101 | * import { pluginTailwindCSS } from '@byted-lynx/plugin-tailwindcss' 102 | * 103 | * export default { 104 | * plugins: [ 105 | * pluginTailwindCSS({ 106 | * include: [ 107 | * /\.[jt]sx?/, 108 | * ], 109 | * }), 110 | * ], 111 | * } 112 | * ``` 113 | */ 114 | include?: FilterPattern | undefined; 115 | } 116 | 117 | export const pluginTailwindCSS = ( 118 | options: PluginTailwindCSSOptions = {}, 119 | ): RsbuildPlugin => ({ 120 | name: 'rsbuild:tailwindcss', 121 | 122 | setup(api) { 123 | let postcssOptions: Exclude< 124 | PostCSSLoaderOptions['postcssOptions'], 125 | (loaderContext: Rspack.LoaderContext) => void 126 | >; 127 | 128 | api.modifyRsbuildConfig({ 129 | order: 'post', 130 | handler(config, { mergeRsbuildConfig }) { 131 | return mergeRsbuildConfig(config, { 132 | tools: { 133 | postcss(config) { 134 | if (typeof config.postcssOptions === 'function') { 135 | throw new Error( 136 | 'pluginTailwindCSS does not support using `tools.postcss` as function', 137 | ); 138 | } 139 | if (config.postcssOptions) { 140 | // Remove `tailwindcss` from `postcssOptions` 141 | // to avoid `@tailwind` being transformed by `postcss-loader`. 142 | config.postcssOptions.plugins = 143 | config.postcssOptions.plugins?.filter( 144 | (p) => 145 | 'postcssPlugin' in p && p.postcssPlugin !== 'tailwindcss', 146 | ) ?? []; 147 | postcssOptions = config.postcssOptions; 148 | } 149 | }, 150 | }, 151 | }); 152 | }, 153 | }); 154 | 155 | api.modifyBundlerChain({ 156 | order: 'post', 157 | handler(chain) { 158 | chain.plugin('tailwindcss').use(TailwindRspackPlugin, [ 159 | { 160 | config: options.config ?? 'tailwind.config.js', 161 | include: options.include, 162 | exclude: options.exclude, 163 | postcssOptions, 164 | }, 165 | ]); 166 | }, 167 | }); 168 | }, 169 | }); 170 | 171 | export { TailwindRspackPlugin } from './TailwindCSSRspackPlugin.js'; 172 | -------------------------------------------------------------------------------- /test/basic/index.test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'node:fs'; 2 | import { dirname, resolve } from 'node:path'; 3 | import { fileURLToPath } from 'node:url'; 4 | import { expect, test } from '@playwright/test'; 5 | import { createRsbuild } from '@rsbuild/core'; 6 | import { pluginTailwindCSS } from '../../src'; 7 | import { getRandomPort } from '../helper'; 8 | 9 | const __dirname = dirname(fileURLToPath(import.meta.url)); 10 | 11 | test('should dev with tailwind utilities', async ({ page }) => { 12 | const rsbuild = await createRsbuild({ 13 | cwd: __dirname, 14 | rsbuildConfig: { 15 | plugins: [pluginTailwindCSS()], 16 | server: { 17 | port: getRandomPort(), 18 | }, 19 | }, 20 | }); 21 | 22 | const { server, urls } = await rsbuild.startDevServer(); 23 | 24 | await page.goto(urls[0]); 25 | 26 | const display = await page.evaluate(() => { 27 | const el = document.getElementById('test'); 28 | 29 | if (!el) { 30 | throw new Error('#test not found'); 31 | } 32 | 33 | return window.getComputedStyle(el).getPropertyValue('display'); 34 | }); 35 | 36 | expect(display).toBe('flex'); 37 | 38 | await server.close(); 39 | }); 40 | 41 | test('should build with tailwind utilities', async ({ page }) => { 42 | const rsbuild = await createRsbuild({ 43 | cwd: __dirname, 44 | rsbuildConfig: { 45 | plugins: [pluginTailwindCSS()], 46 | server: { 47 | port: getRandomPort(), 48 | }, 49 | }, 50 | }); 51 | 52 | await rsbuild.build(); 53 | const { server, urls } = await rsbuild.preview(); 54 | 55 | await page.goto(urls[0]); 56 | 57 | const display = await page.evaluate(() => { 58 | const el = document.getElementById('test'); 59 | 60 | if (!el) { 61 | throw new Error('#test not found'); 62 | } 63 | 64 | return window.getComputedStyle(el).getPropertyValue('display'); 65 | }); 66 | 67 | expect(display).toBe('flex'); 68 | 69 | await server.close(); 70 | }); 71 | 72 | test('should not generate tailwind.config.js in dist/', async () => { 73 | const rsbuild = await createRsbuild({ 74 | cwd: __dirname, 75 | rsbuildConfig: { 76 | plugins: [pluginTailwindCSS()], 77 | }, 78 | }); 79 | 80 | await rsbuild.build(); 81 | 82 | expect(existsSync(resolve(__dirname, './dist/.rsbuild'))).toBeFalsy(); 83 | }); 84 | 85 | test('should dev with nested entry', async ({ page }) => { 86 | const rsbuild = await createRsbuild({ 87 | cwd: __dirname, 88 | rsbuildConfig: { 89 | source: { 90 | entry: { 91 | 'nested/output/folder/bundle': resolve(__dirname, './src/index.js'), 92 | }, 93 | }, 94 | plugins: [pluginTailwindCSS()], 95 | server: { 96 | port: getRandomPort(), 97 | }, 98 | }, 99 | }); 100 | 101 | const { server, urls } = await rsbuild.startDevServer(); 102 | 103 | await page.goto(`${urls[0]}/nested/output/folder/bundle`); 104 | 105 | const display = await page.evaluate(() => { 106 | const el = document.getElementById('test'); 107 | if (!el) { 108 | throw new Error('#test not found'); 109 | } 110 | 111 | return window.getComputedStyle(el).getPropertyValue('display'); 112 | }); 113 | 114 | expect(display).toBe('flex'); 115 | 116 | await server.close(); 117 | }); 118 | -------------------------------------------------------------------------------- /test/basic/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'flex'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/cjs/config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "commonjs" 3 | } 4 | -------------------------------------------------------------------------------- /test/cjs/config/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = {}; 3 | -------------------------------------------------------------------------------- /test/cjs/index.test.ts: -------------------------------------------------------------------------------- 1 | import { dirname, resolve } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { expect, test } from '@playwright/test'; 4 | import { createRsbuild } from '@rsbuild/core'; 5 | import { pluginTailwindCSS } from '../../src'; 6 | import { getRandomPort } from '../helper'; 7 | 8 | const __dirname = dirname(fileURLToPath(import.meta.url)); 9 | 10 | test('should build with relative config', async ({ page }) => { 11 | const rsbuild = await createRsbuild({ 12 | cwd: __dirname, 13 | rsbuildConfig: { 14 | plugins: [ 15 | pluginTailwindCSS({ 16 | config: './config/tailwind.config.js', 17 | }), 18 | ], 19 | server: { 20 | port: getRandomPort(), 21 | }, 22 | }, 23 | }); 24 | 25 | await rsbuild.build(); 26 | const { server, urls } = await rsbuild.preview(); 27 | 28 | await page.goto(urls[0]); 29 | 30 | const display = await page.evaluate(() => { 31 | const el = document.getElementById('test'); 32 | 33 | if (!el) { 34 | throw new Error('#test not found'); 35 | } 36 | 37 | return window.getComputedStyle(el).getPropertyValue('display'); 38 | }); 39 | 40 | expect(display).toBe('flex'); 41 | 42 | await server.close(); 43 | }); 44 | 45 | test('should build with absolute config', async ({ page }) => { 46 | const rsbuild = await createRsbuild({ 47 | cwd: __dirname, 48 | rsbuildConfig: { 49 | plugins: [ 50 | pluginTailwindCSS({ 51 | config: resolve(__dirname, './config/tailwind.config.js'), 52 | }), 53 | ], 54 | server: { 55 | port: getRandomPort(), 56 | }, 57 | }, 58 | }); 59 | 60 | await rsbuild.build(); 61 | const { server, urls } = await rsbuild.preview(); 62 | 63 | await page.goto(urls[0]); 64 | 65 | const display = await page.evaluate(() => { 66 | const el = document.getElementById('test'); 67 | 68 | if (!el) { 69 | throw new Error('#test not found'); 70 | } 71 | 72 | return window.getComputedStyle(el).getPropertyValue('display'); 73 | }); 74 | 75 | expect(display).toBe('flex'); 76 | 77 | await server.close(); 78 | }); 79 | 80 | test('should build without tailwind.config.js', async ({ page }) => { 81 | const rsbuild = await createRsbuild({ 82 | cwd: __dirname, 83 | rsbuildConfig: { 84 | server: { 85 | port: getRandomPort(), 86 | }, 87 | plugins: [pluginTailwindCSS()], 88 | }, 89 | }); 90 | 91 | await rsbuild.build(); 92 | const { server, urls } = await rsbuild.preview(); 93 | 94 | await page.goto(urls[0]); 95 | 96 | const display = await page.evaluate(() => { 97 | const el = document.getElementById('test'); 98 | 99 | if (!el) { 100 | throw new Error('#test not found'); 101 | } 102 | 103 | return window.getComputedStyle(el).getPropertyValue('display'); 104 | }); 105 | 106 | expect(display).toBe('flex'); 107 | 108 | await server.close(); 109 | }); 110 | -------------------------------------------------------------------------------- /test/cjs/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'flex'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/config/config/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default {}; 3 | -------------------------------------------------------------------------------- /test/config/index.test.ts: -------------------------------------------------------------------------------- 1 | import { dirname, resolve } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { expect, test } from '@playwright/test'; 4 | import { createRsbuild } from '@rsbuild/core'; 5 | import { pluginTailwindCSS } from '../../src'; 6 | import { supportESM, getRandomPort } from '../helper'; 7 | 8 | const __dirname = dirname(fileURLToPath(import.meta.url)); 9 | 10 | test('should build with relative config', async ({ page }) => { 11 | test.skip( 12 | !supportESM(), 13 | 'Skip since the tailwindcss version does not support ESM configuration', 14 | ); 15 | 16 | const rsbuild = await createRsbuild({ 17 | cwd: __dirname, 18 | rsbuildConfig: { 19 | plugins: [ 20 | pluginTailwindCSS({ 21 | config: './config/tailwind.config.js', 22 | }), 23 | ], 24 | server: { 25 | port: getRandomPort(), 26 | }, 27 | }, 28 | }); 29 | 30 | await rsbuild.build(); 31 | const { server, urls } = await rsbuild.preview(); 32 | 33 | await page.goto(urls[0]); 34 | 35 | const display = await page.evaluate(() => { 36 | const el = document.getElementById('test'); 37 | 38 | if (!el) { 39 | throw new Error('#test not found'); 40 | } 41 | 42 | return window.getComputedStyle(el).getPropertyValue('display'); 43 | }); 44 | 45 | expect(display).toBe('flex'); 46 | 47 | await server.close(); 48 | }); 49 | 50 | test('should build with absolute config', async ({ page }) => { 51 | test.skip( 52 | !supportESM(), 53 | 'Skip since the tailwindcss version does not support ESM configuration', 54 | ); 55 | 56 | const rsbuild = await createRsbuild({ 57 | cwd: __dirname, 58 | rsbuildConfig: { 59 | plugins: [ 60 | pluginTailwindCSS({ 61 | config: resolve(__dirname, './config/tailwind.config.js'), 62 | }), 63 | ], 64 | server: { 65 | port: getRandomPort(), 66 | }, 67 | }, 68 | }); 69 | 70 | await rsbuild.build(); 71 | const { server, urls } = await rsbuild.preview(); 72 | 73 | await page.goto(urls[0]); 74 | 75 | const display = await page.evaluate(() => { 76 | const el = document.getElementById('test'); 77 | 78 | if (!el) { 79 | throw new Error('#test not found'); 80 | } 81 | 82 | return window.getComputedStyle(el).getPropertyValue('display'); 83 | }); 84 | 85 | expect(display).toBe('flex'); 86 | 87 | await server.close(); 88 | }); 89 | 90 | test('should build without tailwind.config.js', async ({ page }) => { 91 | const rsbuild = await createRsbuild({ 92 | cwd: __dirname, 93 | rsbuildConfig: { 94 | plugins: [pluginTailwindCSS()], 95 | server: { 96 | port: getRandomPort(), 97 | }, 98 | }, 99 | }); 100 | 101 | await rsbuild.build(); 102 | const { server, urls } = await rsbuild.preview(); 103 | 104 | await page.goto(urls[0]); 105 | 106 | const display = await page.evaluate(() => { 107 | const el = document.getElementById('test'); 108 | 109 | if (!el) { 110 | throw new Error('#test not found'); 111 | } 112 | 113 | return window.getComputedStyle(el).getPropertyValue('display'); 114 | }); 115 | 116 | expect(display).toBe('flex'); 117 | 118 | await server.close(); 119 | }); 120 | -------------------------------------------------------------------------------- /test/config/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'flex'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/exclude-include/index.test.ts: -------------------------------------------------------------------------------- 1 | import { dirname } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { expect, test } from '@playwright/test'; 4 | import { createRsbuild } from '@rsbuild/core'; 5 | 6 | import { getRandomPort } from '../helper'; 7 | 8 | const __dirname = dirname(fileURLToPath(import.meta.url)); 9 | 10 | test('should build with included and excluded modules', async ({ page }) => { 11 | const { pluginTailwindCSS } = await import('../../src'); 12 | const rsbuild = await createRsbuild({ 13 | cwd: __dirname, 14 | rsbuildConfig: { 15 | plugins: [ 16 | pluginTailwindCSS({ 17 | include: './src/*.{js,jsx}', 18 | exclude: './src/exclude.js', 19 | }), 20 | ], 21 | server: { 22 | port: getRandomPort(), 23 | }, 24 | }, 25 | }); 26 | 27 | await rsbuild.build(); 28 | const { server, urls } = await rsbuild.preview(); 29 | 30 | await page.goto(urls[0]); 31 | 32 | const display = await page.evaluate(() => { 33 | const el = document.getElementById('test'); 34 | 35 | if (!el) { 36 | throw new Error('#test not found'); 37 | } 38 | 39 | return window.getComputedStyle(el).getPropertyValue('display'); 40 | }); 41 | 42 | expect(display).toBe('flex'); 43 | 44 | // Exclude 45 | { 46 | const textAlign = await page.evaluate(() => { 47 | const el = document.getElementById('exclude'); 48 | 49 | if (!el) { 50 | throw new Error('#exclude not found'); 51 | } 52 | 53 | return window.getComputedStyle(el).getPropertyValue('text-align'); 54 | }); 55 | 56 | expect(textAlign).not.toBe('center'); 57 | 58 | // The `not-exclude.js` imported by `exclude.js` should not be excluded. 59 | const paddingTop = await page.evaluate(() => { 60 | const el = document.getElementById('not-exclude'); 61 | 62 | if (!el) { 63 | throw new Error('#not-exclude not found'); 64 | } 65 | 66 | return window.getComputedStyle(el).getPropertyValue('padding-top'); 67 | }); 68 | 69 | expect(paddingTop).toBe('16px'); 70 | } 71 | 72 | // Include 73 | { 74 | const textAlign = await page.evaluate(() => { 75 | const el = document.getElementById('not-include'); 76 | 77 | if (!el) { 78 | throw new Error('#not-include not found'); 79 | } 80 | 81 | return window.getComputedStyle(el).getPropertyValue('text-align'); 82 | }); 83 | 84 | expect(textAlign).not.toBe('center'); 85 | 86 | // The `include.js` imported by `not-include.ts` should be included. 87 | const paddingTop = await page.evaluate(() => { 88 | const el = document.getElementById('include'); 89 | 90 | if (!el) { 91 | throw new Error('#include not found'); 92 | } 93 | 94 | return window.getComputedStyle(el).getPropertyValue('padding-top'); 95 | }); 96 | 97 | expect(paddingTop).toBe('16px'); 98 | } 99 | await server.close(); 100 | }); 101 | -------------------------------------------------------------------------------- /test/exclude-include/src/exclude.js: -------------------------------------------------------------------------------- 1 | // The `not-exclude.js` imported by `exclude.js` should not be excluded. 2 | import './not-exclude.js'; 3 | 4 | function className() { 5 | return 'text-center'; 6 | } 7 | 8 | const root = document.getElementById('root'); 9 | const element = document.createElement('div'); 10 | element.id = 'exclude'; 11 | element.className = className(); 12 | root.appendChild(element); 13 | -------------------------------------------------------------------------------- /test/exclude-include/src/include.jsx: -------------------------------------------------------------------------------- 1 | function className() { 2 | return 'pt-4'; 3 | } 4 | 5 | const root = document.getElementById('root'); 6 | const element = document.createElement('div'); 7 | element.id = 'include'; 8 | element.className = className(); 9 | root.appendChild(element); 10 | -------------------------------------------------------------------------------- /test/exclude-include/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | import './exclude.js'; 4 | import './not-include.ts'; 5 | 6 | function className() { 7 | return 'flex'; 8 | } 9 | 10 | const root = document.getElementById('root'); 11 | const element = document.createElement('div'); 12 | element.id = 'test'; 13 | element.className = className(); 14 | root.appendChild(element); 15 | -------------------------------------------------------------------------------- /test/exclude-include/src/not-exclude.js: -------------------------------------------------------------------------------- 1 | function className() { 2 | return 'pt-4'; 3 | } 4 | 5 | const root = document.getElementById('root'); 6 | const element = document.createElement('div'); 7 | element.id = 'not-exclude'; 8 | element.className = className(); 9 | root.appendChild(element); 10 | -------------------------------------------------------------------------------- /test/exclude-include/src/not-include.ts: -------------------------------------------------------------------------------- 1 | // The `include.jsx` imported by `not-include.ts` should not be excluded. 2 | import './include.jsx'; 3 | 4 | function className() { 5 | return 'text-center'; 6 | } 7 | 8 | const root = document.getElementById('root'); 9 | const element = document.createElement('div'); 10 | element.id = 'not-include'; 11 | element.className = className(); 12 | root?.appendChild(element); 13 | -------------------------------------------------------------------------------- /test/exclude/index.test.ts: -------------------------------------------------------------------------------- 1 | import { dirname } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { expect, test } from '@playwright/test'; 4 | import { createRsbuild } from '@rsbuild/core'; 5 | 6 | import { getRandomPort } from '../helper'; 7 | 8 | const __dirname = dirname(fileURLToPath(import.meta.url)); 9 | 10 | test('should build with excluded modules', async ({ page }) => { 11 | const { pluginTailwindCSS } = await import('../../src'); 12 | const rsbuild = await createRsbuild({ 13 | cwd: __dirname, 14 | rsbuildConfig: { 15 | plugins: [ 16 | pluginTailwindCSS({ 17 | exclude: ['./src/exclude.js'], 18 | }), 19 | ], 20 | server: { 21 | port: getRandomPort(), 22 | }, 23 | }, 24 | }); 25 | 26 | await rsbuild.build(); 27 | const { server, urls } = await rsbuild.preview(); 28 | 29 | await page.goto(urls[0]); 30 | 31 | const display = await page.evaluate(() => { 32 | const el = document.getElementById('test'); 33 | 34 | if (!el) { 35 | throw new Error('#test not found'); 36 | } 37 | 38 | return window.getComputedStyle(el).getPropertyValue('display'); 39 | }); 40 | 41 | expect(display).toBe('flex'); 42 | 43 | const textAlign = await page.evaluate(() => { 44 | const el = document.getElementById('exclude'); 45 | 46 | if (!el) { 47 | throw new Error('#exclude not found'); 48 | } 49 | 50 | return window.getComputedStyle(el).getPropertyValue('text-align'); 51 | }); 52 | 53 | expect(textAlign).not.toBe('center'); 54 | 55 | // The `not-exclude.js` imported by `exclude.js` should not be excluded. 56 | const paddingTop = await page.evaluate(() => { 57 | const el = document.getElementById('not-exclude'); 58 | 59 | if (!el) { 60 | throw new Error('#not-exclude not found'); 61 | } 62 | 63 | return window.getComputedStyle(el).getPropertyValue('padding-top'); 64 | }); 65 | 66 | expect(paddingTop).toBe('16px'); 67 | 68 | await server.close(); 69 | }); 70 | -------------------------------------------------------------------------------- /test/exclude/src/exclude.js: -------------------------------------------------------------------------------- 1 | // The `not-exclude.js` imported by `exclude.js` should not be excluded. 2 | import './not-exclude.js'; 3 | 4 | function className() { 5 | return 'text-center'; 6 | } 7 | 8 | const root = document.getElementById('root'); 9 | const element = document.createElement('div'); 10 | element.id = 'exclude'; 11 | element.className = className(); 12 | root.appendChild(element); 13 | -------------------------------------------------------------------------------- /test/exclude/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | import './exclude.js'; 4 | 5 | function className() { 6 | return 'flex'; 7 | } 8 | 9 | const root = document.getElementById('root'); 10 | const element = document.createElement('div'); 11 | element.id = 'test'; 12 | element.className = className(); 13 | root.appendChild(element); 14 | -------------------------------------------------------------------------------- /test/exclude/src/not-exclude.js: -------------------------------------------------------------------------------- 1 | function className() { 2 | return 'pt-4'; 3 | } 4 | 5 | const root = document.getElementById('root'); 6 | const element = document.createElement('div'); 7 | element.id = 'not-exclude'; 8 | element.className = className(); 9 | root.appendChild(element); 10 | -------------------------------------------------------------------------------- /test/helper.ts: -------------------------------------------------------------------------------- 1 | import satisfies from 'semver/functions/satisfies.js'; 2 | import pkg from 'tailwindcss/package.json' with { type: 'json' }; 3 | 4 | const portMap = new Map(); 5 | 6 | export function getRandomPort( 7 | defaultPort = Math.ceil(Math.random() * 30000) + 15000, 8 | ) { 9 | let port = defaultPort; 10 | while (true) { 11 | if (!portMap.get(port)) { 12 | portMap.set(port, 1); 13 | return port; 14 | } 15 | port++; 16 | } 17 | } 18 | 19 | export function supportESM(): boolean { 20 | // Tailwind CSS support using ESM configuration in v3.3.0 21 | // See: 22 | // - https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.0 23 | // - https://github.com/tailwindlabs/tailwindcss/pull/10785 24 | // - https://github.com/rspack-contrib/rsbuild-plugin-tailwindcss/issues/18 25 | return satisfies(pkg.version, '^3.3.0'); 26 | } 27 | -------------------------------------------------------------------------------- /test/include/index.test.ts: -------------------------------------------------------------------------------- 1 | import { dirname } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { expect, test } from '@playwright/test'; 4 | import { createRsbuild } from '@rsbuild/core'; 5 | 6 | import { getRandomPort } from '../helper'; 7 | 8 | const __dirname = dirname(fileURLToPath(import.meta.url)); 9 | 10 | test('should build with included modules', async ({ page }) => { 11 | const { pluginTailwindCSS } = await import('../../src'); 12 | const rsbuild = await createRsbuild({ 13 | cwd: __dirname, 14 | rsbuildConfig: { 15 | plugins: [ 16 | pluginTailwindCSS({ 17 | include: './src/*.{js,jsx}', 18 | }), 19 | ], 20 | server: { 21 | port: getRandomPort(), 22 | }, 23 | }, 24 | }); 25 | 26 | await rsbuild.build(); 27 | const { server, urls } = await rsbuild.preview(); 28 | 29 | await page.goto(urls[0]); 30 | 31 | const display = await page.evaluate(() => { 32 | const el = document.getElementById('test'); 33 | 34 | if (!el) { 35 | throw new Error('#test not found'); 36 | } 37 | 38 | return window.getComputedStyle(el).getPropertyValue('display'); 39 | }); 40 | 41 | expect(display).toBe('flex'); 42 | 43 | const textAlign = await page.evaluate(() => { 44 | const el = document.getElementById('not-include'); 45 | 46 | if (!el) { 47 | throw new Error('#not-include not found'); 48 | } 49 | 50 | return window.getComputedStyle(el).getPropertyValue('text-align'); 51 | }); 52 | 53 | expect(textAlign).not.toBe('center'); 54 | 55 | // The `include.js` imported by `not-include.ts` should be included. 56 | const paddingTop = await page.evaluate(() => { 57 | const el = document.getElementById('include'); 58 | 59 | if (!el) { 60 | throw new Error('#include not found'); 61 | } 62 | 63 | return window.getComputedStyle(el).getPropertyValue('padding-top'); 64 | }); 65 | 66 | expect(paddingTop).toBe('16px'); 67 | 68 | await server.close(); 69 | }); 70 | -------------------------------------------------------------------------------- /test/include/src/include.jsx: -------------------------------------------------------------------------------- 1 | function className() { 2 | return 'pt-4'; 3 | } 4 | 5 | const root = document.getElementById('root'); 6 | const element = document.createElement('div'); 7 | element.id = 'include'; 8 | element.className = className(); 9 | root.appendChild(element); 10 | -------------------------------------------------------------------------------- /test/include/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | import './not-include.ts'; 4 | 5 | function className() { 6 | return 'flex'; 7 | } 8 | 9 | const root = document.getElementById('root'); 10 | const element = document.createElement('div'); 11 | element.id = 'test'; 12 | element.className = className(); 13 | root.appendChild(element); 14 | -------------------------------------------------------------------------------- /test/include/src/not-include.ts: -------------------------------------------------------------------------------- 1 | // The `include.jsx` imported by `not-include.ts` should not be excluded. 2 | import './include.jsx'; 3 | 4 | function className() { 5 | return 'text-center'; 6 | } 7 | 8 | const root = document.getElementById('root'); 9 | const element = document.createElement('div'); 10 | element.id = 'not-include'; 11 | element.className = className(); 12 | root?.appendChild(element); 13 | -------------------------------------------------------------------------------- /test/isSubsetOf.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from '@playwright/test'; 2 | 3 | import { isSubsetOf } from '../src/Set.prototype.isSubsetOf'; 4 | 5 | test.describe('Set.prototype.isSubsetOf', () => { 6 | test('subsets', () => { 7 | const set1 = new Set([1, 2, 3]); 8 | const set2 = new Set([4, 5, 6]); 9 | const set3 = new Set([1, 2, 3, 4, 5, 6]); 10 | 11 | expect(isSubsetOf(set1, set2)).toBe(false); 12 | expect(isSubsetOf(set2, set1)).toBe(false); 13 | expect(isSubsetOf(set1, set3)).toBe(true); 14 | expect(isSubsetOf(set2, set3)).toBe(true); 15 | }); 16 | 17 | test('empty sets', () => { 18 | const s1 = new Set([]); 19 | const s2 = new Set([1, 2]); 20 | 21 | expect(isSubsetOf(s1, s2)).toBe(true); 22 | 23 | const s3 = new Set([1, 2]); 24 | const s4 = new Set([]); 25 | 26 | expect(isSubsetOf(s3, s4)).toBe(false); 27 | 28 | const s5 = new Set([]); 29 | const s6 = new Set([]); 30 | 31 | expect(isSubsetOf(s5, s6)).toBe(true); 32 | }); 33 | 34 | test('self', () => { 35 | const s1 = new Set([1, 2]); 36 | 37 | expect(isSubsetOf(s1, s1)).toBe(true); 38 | }); 39 | 40 | test('same', () => { 41 | const s1 = new Set([1, 2]); 42 | const s2 = new Set([1, 2]); 43 | 44 | expect(isSubsetOf(s1, s2)).toBe(true); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /test/multi-entries/a.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'flex'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/multi-entries/b.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'w-8'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/multi-entries/c.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'px-4'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/multi-entries/d.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'z-20'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/multi-entries/e.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'justify-end'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/multi-entries/index.test.ts: -------------------------------------------------------------------------------- 1 | import { dirname } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | 4 | import test, { expect } from '@playwright/test'; 5 | import { createRsbuild } from '@rsbuild/core'; 6 | 7 | import { pluginTailwindCSS } from '../../src'; 8 | import { getRandomPort } from '../helper'; 9 | 10 | const __dirname = dirname(fileURLToPath(import.meta.url)); 11 | 12 | test('should dev with tailwind utilities in multiple entries', async ({ 13 | page, 14 | }) => { 15 | const rsbuild = await createRsbuild({ 16 | cwd: __dirname, 17 | rsbuildConfig: { 18 | dev: { 19 | writeToDisk: true, 20 | }, 21 | source: { 22 | entry: { 23 | a: './a.js', 24 | b: './b.js', 25 | c: './c.js', 26 | d: './d.js', 27 | e: './e.js', 28 | }, 29 | }, 30 | plugins: [pluginTailwindCSS()], 31 | server: { 32 | port: getRandomPort(), 33 | }, 34 | }, 35 | }); 36 | 37 | const { server, urls } = await rsbuild.startDevServer(); 38 | 39 | await page.goto(`${urls[0]}/a`); 40 | let style = await getStyle(); 41 | expect(style.display).toBe('flex'); // flex 42 | expect(style.width).not.toBe('32px'); // w-8 43 | expect(style.paddingLeft).not.toBe('0'); // px-4 44 | expect(style.paddingRight).not.toBe('0'); // px-4 45 | expect(style.zIndex).not.toBe('20'); // z-20 46 | expect(style.justifyContent).not.toBe('flex-end'); // justify-end 47 | 48 | await page.goto(`${urls[0]}/b`); 49 | style = await getStyle(); 50 | expect(style.display).not.toBe('flex'); // flex 51 | expect(style.width).toBe('32px'); // w-8 52 | expect(style.paddingLeft).not.toBe('0'); // px-4 53 | expect(style.paddingRight).not.toBe('0'); // px-4 54 | expect(style.zIndex).not.toBe('20'); // z-20 55 | expect(style.justifyContent).not.toBe('flex-end'); // justify-end 56 | 57 | await page.goto(`${urls[0]}/c`); 58 | style = await getStyle(); 59 | expect(style.display).not.toBe('flex'); // flex 60 | expect(style.width).not.toBe('32px'); // w-8 61 | expect(style.paddingLeft).toBe('16px'); // px-4 62 | expect(style.paddingRight).toBe('16px'); // px-4 63 | expect(style.zIndex).not.toBe('20'); // z-20 64 | expect(style.justifyContent).not.toBe('flex-end'); // justify-end 65 | 66 | await page.goto(`${urls[0]}/d`); 67 | style = await getStyle(); 68 | expect(style.display).not.toBe('flex'); // flex 69 | expect(style.width).not.toBe('32px'); // w-8 70 | expect(style.paddingLeft).not.toBe('0'); // px-4 71 | expect(style.paddingRight).not.toBe('0'); // px-4 72 | expect(style.zIndex).toBe('20'); // z-20 73 | expect(style.justifyContent).not.toBe('flex-end'); // justify-end 74 | 75 | await page.goto(`${urls[0]}/e`); 76 | style = await getStyle(); 77 | expect(style.display).not.toBe('flex'); // flex 78 | expect(style.width).not.toBe('32px'); // w-8 79 | expect(style.paddingLeft).not.toBe('0'); // px-4 80 | expect(style.paddingRight).not.toBe('0'); // px-4 81 | expect(style.zIndex).not.toBe('20'); // z-20 82 | expect(style.justifyContent).toBe('flex-end'); // justify-end 83 | 84 | await server.close(); 85 | 86 | async function getStyle() { 87 | return await page.evaluate(() => { 88 | const el = document.getElementById('test'); 89 | 90 | if (!el) { 91 | throw new Error('#test not found'); 92 | } 93 | 94 | return window.getComputedStyle(el); 95 | }); 96 | } 97 | }); 98 | 99 | test('should build with tailwind utilities in multiple entries', async ({ 100 | page, 101 | }) => { 102 | const rsbuild = await createRsbuild({ 103 | cwd: __dirname, 104 | rsbuildConfig: { 105 | source: { 106 | entry: { 107 | a: './a.js', 108 | b: './b.js', 109 | c: './c.js', 110 | d: './d.js', 111 | e: './e.js', 112 | }, 113 | }, 114 | plugins: [pluginTailwindCSS()], 115 | server: { 116 | port: getRandomPort(), 117 | }, 118 | }, 119 | }); 120 | 121 | await rsbuild.build(); 122 | const { server, urls } = await rsbuild.preview(); 123 | 124 | await page.goto(`${urls[0]}/a`); 125 | let style = await getStyle(); 126 | expect(style.display).toBe('flex'); // flex 127 | expect(style.width).not.toBe('32px'); // w-8 128 | expect(style.paddingLeft).not.toBe('0'); // px-4 129 | expect(style.paddingRight).not.toBe('0'); // px-4 130 | expect(style.zIndex).not.toBe('20'); // z-20 131 | expect(style.justifyContent).not.toBe('flex-end'); // justify-end 132 | 133 | await page.goto(`${urls[0]}/b`); 134 | style = await getStyle(); 135 | expect(style.display).not.toBe('flex'); // flex 136 | expect(style.width).toBe('32px'); // w-8 137 | expect(style.paddingLeft).not.toBe('0'); // px-4 138 | expect(style.paddingRight).not.toBe('0'); // px-4 139 | expect(style.zIndex).not.toBe('20'); // z-20 140 | expect(style.justifyContent).not.toBe('flex-end'); // justify-end 141 | 142 | await page.goto(`${urls[0]}/c`); 143 | style = await getStyle(); 144 | expect(style.display).not.toBe('flex'); // flex 145 | expect(style.width).not.toBe('32px'); // w-8 146 | expect(style.paddingLeft).toBe('16px'); // px-4 147 | expect(style.paddingRight).toBe('16px'); // px-4 148 | expect(style.zIndex).not.toBe('20'); // z-20 149 | expect(style.justifyContent).not.toBe('flex-end'); // justify-end 150 | 151 | await page.goto(`${urls[0]}/d`); 152 | style = await getStyle(); 153 | expect(style.display).not.toBe('flex'); // flex 154 | expect(style.width).not.toBe('32px'); // w-8 155 | expect(style.paddingLeft).not.toBe('0'); // px-4 156 | expect(style.paddingRight).not.toBe('0'); // px-4 157 | expect(style.zIndex).toBe('20'); // z-20 158 | expect(style.justifyContent).not.toBe('flex-end'); // justify-end 159 | 160 | await page.goto(`${urls[0]}/e`); 161 | style = await getStyle(); 162 | expect(style.display).not.toBe('flex'); // flex 163 | expect(style.width).not.toBe('32px'); // w-8 164 | expect(style.paddingLeft).not.toBe('0'); // px-4 165 | expect(style.paddingRight).not.toBe('0'); // px-4 166 | expect(style.zIndex).not.toBe('20'); // z-20 167 | expect(style.justifyContent).toBe('flex-end'); // justify-end 168 | 169 | await server.close(); 170 | 171 | async function getStyle() { 172 | return await page.evaluate(() => { 173 | const el = document.getElementById('test'); 174 | 175 | if (!el) { 176 | throw new Error('#test not found'); 177 | } 178 | 179 | return window.getComputedStyle(el); 180 | }); 181 | } 182 | }); 183 | -------------------------------------------------------------------------------- /test/postcss-config/flex-to-grid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @returns {import('postcss').AcceptedPlugin} 3 | */ 4 | export default function () { 5 | return { 6 | postcssPlugin: 'flex-to-grid', 7 | Declaration: { 8 | display(decl) { 9 | if (decl.value === 'flex') { 10 | decl.value = 'grid'; 11 | } 12 | }, 13 | }, 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /test/postcss-config/index.test.ts: -------------------------------------------------------------------------------- 1 | import { dirname } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { expect, test } from '@playwright/test'; 4 | import { createRsbuild } from '@rsbuild/core'; 5 | import { pluginTailwindCSS } from '../../src'; 6 | import { getRandomPort } from '../helper'; 7 | 8 | const __dirname = dirname(fileURLToPath(import.meta.url)); 9 | 10 | test('should build with postcss.config.js', async ({ page }) => { 11 | const rsbuild = await createRsbuild({ 12 | cwd: __dirname, 13 | rsbuildConfig: { 14 | plugins: [pluginTailwindCSS()], 15 | server: { 16 | port: getRandomPort(), 17 | }, 18 | }, 19 | }); 20 | 21 | await rsbuild.build(); 22 | const { server, urls } = await rsbuild.preview(); 23 | 24 | await page.goto(urls[0]); 25 | 26 | const display = await page.evaluate(() => { 27 | const el = document.getElementById('test'); 28 | 29 | if (!el) { 30 | throw new Error('#test not found'); 31 | } 32 | 33 | return window.getComputedStyle(el).getPropertyValue('display'); 34 | }); 35 | 36 | expect(display).toBe('grid'); 37 | 38 | await server.close(); 39 | }); 40 | -------------------------------------------------------------------------------- /test/postcss-config/postcss.config.js: -------------------------------------------------------------------------------- 1 | import tailwindcss from 'tailwindcss'; 2 | import flexToGrid from './flex-to-grid'; 3 | 4 | export default { 5 | plugins: [tailwindcss(), flexToGrid()], 6 | }; 7 | -------------------------------------------------------------------------------- /test/postcss-config/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'flex'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/tools-postcss/flex-to-grid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @returns {import('postcss').AcceptedPlugin} 3 | */ 4 | export default function () { 5 | return { 6 | postcssPlugin: 'flex-to-grid', 7 | Declaration: { 8 | display(decl) { 9 | if (decl.value === 'flex') { 10 | decl.value = 'grid'; 11 | } 12 | }, 13 | }, 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /test/tools-postcss/index.test.ts: -------------------------------------------------------------------------------- 1 | import { dirname } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { expect, test } from '@playwright/test'; 4 | import { createRsbuild } from '@rsbuild/core'; 5 | import { pluginTailwindCSS } from '../../src'; 6 | import { getRandomPort } from '../helper'; 7 | 8 | const __dirname = dirname(fileURLToPath(import.meta.url)); 9 | 10 | test('should build with tools.postcss with tailwindcss', async ({ page }) => { 11 | const { default: tailwindcss } = await import('tailwindcss'); 12 | const rsbuild = await createRsbuild({ 13 | cwd: __dirname, 14 | rsbuildConfig: { 15 | plugins: [pluginTailwindCSS()], 16 | tools: { 17 | postcss: { 18 | postcssOptions: { 19 | plugins: [tailwindcss()], 20 | }, 21 | }, 22 | }, 23 | server: { 24 | port: getRandomPort(), 25 | }, 26 | }, 27 | }); 28 | 29 | await rsbuild.build(); 30 | const { server, urls } = await rsbuild.preview(); 31 | 32 | await page.goto(urls[0]); 33 | 34 | const display = await page.evaluate(() => { 35 | const el = document.getElementById('test'); 36 | 37 | if (!el) { 38 | throw new Error('#test not found'); 39 | } 40 | 41 | return window.getComputedStyle(el).getPropertyValue('display'); 42 | }); 43 | 44 | expect(display).toBe('flex'); 45 | 46 | await server.close(); 47 | }); 48 | 49 | test('should build with tools.postcss with custom plugin', async ({ page }) => { 50 | const { default: tailwindcss } = await import('tailwindcss'); 51 | const { default: flexToGrid } = await import('./flex-to-grid.js'); 52 | const rsbuild = await createRsbuild({ 53 | cwd: __dirname, 54 | rsbuildConfig: { 55 | plugins: [pluginTailwindCSS()], 56 | tools: { 57 | postcss: { 58 | postcssOptions: { 59 | plugins: [flexToGrid()], 60 | }, 61 | }, 62 | }, 63 | server: { 64 | port: getRandomPort(), 65 | }, 66 | }, 67 | }); 68 | 69 | await rsbuild.build(); 70 | const { server, urls } = await rsbuild.preview(); 71 | 72 | await page.goto(urls[0]); 73 | 74 | const display = await page.evaluate(() => { 75 | const el = document.getElementById('test'); 76 | 77 | if (!el) { 78 | throw new Error('#test not found'); 79 | } 80 | 81 | return window.getComputedStyle(el).getPropertyValue('display'); 82 | }); 83 | 84 | expect(display).toBe('grid'); 85 | 86 | await server.close(); 87 | }); 88 | -------------------------------------------------------------------------------- /test/tools-postcss/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'flex'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /test/with-resource-query/index.test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'node:fs'; 2 | import { dirname, resolve } from 'node:path'; 3 | import { fileURLToPath } from 'node:url'; 4 | import { expect, test } from '@playwright/test'; 5 | import { createRsbuild } from '@rsbuild/core'; 6 | import { webpackProvider } from '@rsbuild/webpack'; 7 | import { pluginTailwindCSS } from '../../src'; 8 | import { getRandomPort } from '../helper'; 9 | 10 | const __dirname = dirname(fileURLToPath(import.meta.url)); 11 | 12 | test('should dev with resource query on rspack', async ({ page }) => { 13 | const rsbuild = await createRsbuild({ 14 | cwd: __dirname, 15 | rsbuildConfig: { 16 | source: { 17 | entry: { 18 | index: resolve(__dirname, './src/index.js?entry'), 19 | }, 20 | }, 21 | plugins: [pluginTailwindCSS()], 22 | server: { 23 | port: getRandomPort(), 24 | }, 25 | }, 26 | }); 27 | 28 | const { server, urls } = await rsbuild.startDevServer(); 29 | 30 | await page.goto(urls[0]); 31 | 32 | const display = await page.evaluate(() => { 33 | const el = document.getElementById('test'); 34 | 35 | if (!el) { 36 | throw new Error('#test not found'); 37 | } 38 | 39 | return window.getComputedStyle(el).getPropertyValue('display'); 40 | }); 41 | 42 | expect(display).toBe('flex'); 43 | 44 | await server.close(); 45 | }); 46 | 47 | test('should build with resource query on rspack', async ({ page }) => { 48 | const rsbuild = await createRsbuild({ 49 | cwd: __dirname, 50 | rsbuildConfig: { 51 | source: { 52 | entry: { 53 | index: resolve(__dirname, './src/index.js?entry'), 54 | }, 55 | }, 56 | server: { 57 | port: getRandomPort(), 58 | }, 59 | plugins: [pluginTailwindCSS()], 60 | }, 61 | }); 62 | 63 | await rsbuild.build(); 64 | const { server, urls } = await rsbuild.preview(); 65 | 66 | await page.goto(urls[0]); 67 | 68 | const display = await page.evaluate(() => { 69 | const el = document.getElementById('test'); 70 | 71 | if (!el) { 72 | throw new Error('#test not found'); 73 | } 74 | 75 | return window.getComputedStyle(el).getPropertyValue('display'); 76 | }); 77 | 78 | expect(display).toBe('flex'); 79 | 80 | await server.close(); 81 | }); 82 | 83 | test('should dev with resource query on webpack', async ({ page }) => { 84 | const rsbuild = await createRsbuild({ 85 | cwd: __dirname, 86 | rsbuildConfig: { 87 | provider: webpackProvider, 88 | source: { 89 | entry: { 90 | index: resolve(__dirname, './src/index.js?entry'), 91 | }, 92 | }, 93 | plugins: [pluginTailwindCSS()], 94 | server: { 95 | port: getRandomPort(), 96 | }, 97 | }, 98 | }); 99 | 100 | const { server, urls } = await rsbuild.startDevServer(); 101 | 102 | await page.goto(urls[0]); 103 | 104 | const display = await page.evaluate(() => { 105 | const el = document.getElementById('test'); 106 | 107 | if (!el) { 108 | throw new Error('#test not found'); 109 | } 110 | 111 | return window.getComputedStyle(el).getPropertyValue('display'); 112 | }); 113 | 114 | expect(display).toBe('flex'); 115 | 116 | await server.close(); 117 | }); 118 | 119 | test('should build with resource query on webpack', async ({ page }) => { 120 | const rsbuild = await createRsbuild({ 121 | cwd: __dirname, 122 | rsbuildConfig: { 123 | source: { 124 | entry: { 125 | index: resolve(__dirname, './src/index.js?entry'), 126 | }, 127 | }, 128 | server: { 129 | port: getRandomPort(), 130 | }, 131 | provider: webpackProvider, 132 | plugins: [pluginTailwindCSS()], 133 | }, 134 | }); 135 | 136 | await rsbuild.build(); 137 | const { server, urls } = await rsbuild.preview(); 138 | 139 | await page.goto(urls[0]); 140 | 141 | const display = await page.evaluate(() => { 142 | const el = document.getElementById('test'); 143 | 144 | if (!el) { 145 | throw new Error('#test not found'); 146 | } 147 | 148 | return window.getComputedStyle(el).getPropertyValue('display'); 149 | }); 150 | 151 | expect(display).toBe('flex'); 152 | 153 | await server.close(); 154 | }); 155 | -------------------------------------------------------------------------------- /test/with-resource-query/src/index.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/utilities.css'; 2 | 3 | function className() { 4 | return 'flex'; 5 | } 6 | 7 | const root = document.getElementById('root'); 8 | const element = document.createElement('div'); 9 | element.id = 'test'; 10 | element.className = className(); 11 | root.appendChild(element); 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "baseUrl": "./", 5 | "target": "ES2021", 6 | "lib": ["DOM", "ES2021", "ESNext.Collection"], 7 | "module": "Node16", 8 | "moduleResolution": "Node16", 9 | "strict": true, 10 | "declaration": true, 11 | "isolatedModules": true, 12 | "isolatedDeclarations": true, 13 | "esModuleInterop": true, 14 | "skipLibCheck": true, 15 | "exactOptionalPropertyTypes": true, 16 | "resolveJsonModule": true 17 | }, 18 | "include": ["src"] 19 | } 20 | --------------------------------------------------------------------------------