From a64481a759da19ddf23f546421352e69f327de19 Mon Sep 17 00:00:00 2001 From: "gaoyuan.1226" Date: Tue, 14 May 2024 18:54:20 +0800 Subject: [PATCH 1/3] feat: extract the CSS Modules declaration plugin as a standalone plugin --- e2e/cases/css/css-modules-dom/index.test.ts | 8 +- .../css-modules-ts-declaration/index.test.ts | 11 +- e2e/cases/stylus/index.test.ts | 28 +++- e2e/package.json | 1 + packages/core/package.json | 1 - packages/core/prebundle.config.mjs | 4 - packages/core/src/config.ts | 1 - packages/core/src/plugins/css.ts | 12 -- .../core/tests/__snapshots__/css.test.ts.snap | 79 ----------- packages/core/tests/css.test.ts | 13 -- packages/plugin-typed-css-modules/LICENSE | 21 +++ packages/plugin-typed-css-modules/README.md | 19 +++ .../plugin-typed-css-modules/modern.config.ts | 13 ++ .../plugin-typed-css-modules/package.json | 48 +++++++ .../prebundle.config.mjs | 10 ++ .../plugin-typed-css-modules/src/index.ts | 57 ++++++++ .../src/loader.ts} | 6 +- .../tests/__snapshots__/index.test.ts.snap | 134 ++++++++++++++++++ .../tests/index.test.ts | 48 +++++++ .../tests/loader.test.ts} | 3 +- .../plugin-typed-css-modules/tsconfig.json | 18 +++ packages/shared/src/types/config/output.ts | 5 - pnpm-lock.yaml | 28 +++- 23 files changed, 432 insertions(+), 136 deletions(-) create mode 100644 packages/plugin-typed-css-modules/LICENSE create mode 100644 packages/plugin-typed-css-modules/README.md create mode 100644 packages/plugin-typed-css-modules/modern.config.ts create mode 100644 packages/plugin-typed-css-modules/package.json create mode 100644 packages/plugin-typed-css-modules/prebundle.config.mjs create mode 100644 packages/plugin-typed-css-modules/src/index.ts rename packages/{core/src/rspack/cssModulesTypescriptLoader.ts => plugin-typed-css-modules/src/loader.ts} (97%) create mode 100644 packages/plugin-typed-css-modules/tests/__snapshots__/index.test.ts.snap create mode 100644 packages/plugin-typed-css-modules/tests/index.test.ts rename packages/{core/tests/wrapQuotes.test.ts => plugin-typed-css-modules/tests/loader.test.ts} (88%) create mode 100644 packages/plugin-typed-css-modules/tsconfig.json diff --git a/e2e/cases/css/css-modules-dom/index.test.ts b/e2e/cases/css/css-modules-dom/index.test.ts index efac8feb42..f911c10897 100644 --- a/e2e/cases/css/css-modules-dom/index.test.ts +++ b/e2e/cases/css/css-modules-dom/index.test.ts @@ -2,6 +2,7 @@ import { join, resolve } from 'node:path'; import { build, gotoPage } from '@e2e/helper'; import { expect, test } from '@playwright/test'; import { pluginReact } from '@rsbuild/plugin-react'; +import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules'; import { fse } from '@rsbuild/shared'; const fixtures = resolve(__dirname); @@ -12,12 +13,7 @@ test('enableCssModuleTSDeclaration', async () => { await build({ cwd: fixtures, - plugins: [pluginReact()], - rsbuildConfig: { - output: { - enableCssModuleTSDeclaration: true, - }, - }, + plugins: [pluginReact(), pluginTypedCSSModules()], }); expect( diff --git a/e2e/cases/css/css-modules-ts-declaration/index.test.ts b/e2e/cases/css/css-modules-ts-declaration/index.test.ts index ed4dbfb249..0831af3c06 100644 --- a/e2e/cases/css/css-modules-ts-declaration/index.test.ts +++ b/e2e/cases/css/css-modules-ts-declaration/index.test.ts @@ -1,6 +1,7 @@ import { join, resolve } from 'node:path'; import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; +import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules'; import { fse } from '@rsbuild/shared'; const fixtures = __dirname; @@ -18,13 +19,11 @@ test('should generator ts declaration correctly for css modules auto true', asyn await build({ cwd: __dirname, + plugins: [pluginTypedCSSModules()], rsbuildConfig: { source: { entry: { index: resolve(testDir, 'index.js') }, }, - output: { - enableCssModuleTSDeclaration: true, - }, }, }); @@ -51,12 +50,12 @@ test('should generator ts declaration correctly for css modules auto function', await build({ cwd: __dirname, + plugins: [pluginTypedCSSModules()], rsbuildConfig: { source: { entry: { index: resolve(testDir, 'index.js') }, }, output: { - enableCssModuleTSDeclaration: true, cssModules: { auto: (path) => { return path.endsWith('.less'); @@ -80,12 +79,12 @@ test('should generator ts declaration correctly for css modules auto Regexp', as await build({ cwd: __dirname, + plugins: [pluginTypedCSSModules()], rsbuildConfig: { source: { entry: { index: resolve(testDir, 'index.js') }, }, output: { - enableCssModuleTSDeclaration: true, cssModules: { auto: /\.module\./i, }, @@ -107,12 +106,12 @@ test('should generator ts declaration correctly for custom exportLocalsConventio await build({ cwd: __dirname, + plugins: [pluginTypedCSSModules()], rsbuildConfig: { source: { entry: { index: resolve(testDir, 'index.js') }, }, output: { - enableCssModuleTSDeclaration: true, cssModules: { auto: /\.module\./i, exportLocalsConvention: 'asIs', diff --git a/e2e/cases/stylus/index.test.ts b/e2e/cases/stylus/index.test.ts index d34cd7c8d0..9cc171a5e4 100644 --- a/e2e/cases/stylus/index.test.ts +++ b/e2e/cases/stylus/index.test.ts @@ -1,11 +1,31 @@ +import { join, resolve } from 'node:path'; import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; import { pluginStylus } from '@rsbuild/plugin-stylus'; +import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules'; +import { fse } from '@rsbuild/shared'; + +const fixtures = __dirname; + +const generatorTempDir = async (testDir: string) => { + await fse.emptyDir(testDir); + await fse.copy(join(fixtures, 'src'), testDir); + + return () => fse.remove(testDir); +}; + +test('should compile stylus correctly with ts declaration', async () => { + const testDir = join(fixtures, 'test-temp-src-1'); + const clear = await generatorTempDir(testDir); -test('should compile stylus correctly', async () => { const rsbuild = await build({ cwd: __dirname, - plugins: [pluginStylus()], + plugins: [pluginStylus(), pluginTypedCSSModules()], + rsbuildConfig: { + source: { + entry: { index: resolve(testDir, 'index.js') }, + }, + }, }); const files = await rsbuild.unwrapOutputJSON(); @@ -15,4 +35,8 @@ test('should compile stylus correctly', async () => { expect(content).toMatch( /body{color:#f00;font:14px Arial,sans-serif}\.title-class-\w{6}{font-size:14px}/, ); + + expect(fse.existsSync(join(testDir, './b.module.styl.d.ts'))).toBeTruthy(); + + await clear(); }); diff --git a/e2e/package.json b/e2e/package.json index d37e215baf..bc1c1c06a2 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -50,6 +50,7 @@ "@rsbuild/plugin-vue": "workspace:*", "@rsbuild/plugin-vue-jsx": "workspace:*", "@rsbuild/plugin-vue2": "workspace:*", + "@rsbuild/plugin-typed-css-modules": "workspace:*", "@rsbuild/plugin-vue2-jsx": "workspace:*", "@rsbuild/plugin-yaml": "workspace:*", "@rsbuild/shared": "workspace:*", diff --git a/packages/core/package.json b/packages/core/package.json index e16ebc2390..bccae73f19 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -76,7 +76,6 @@ "less-loader": "12.2.0", "on-finished": "2.4.1", "open": "^8.4.0", - "line-diff": "2.1.1", "postcss-load-config": "5.1.0", "postcss-loader": "8.1.1", "postcss-value-parser": "4.2.0", diff --git a/packages/core/prebundle.config.mjs b/packages/core/prebundle.config.mjs index a74c3a5e0b..a5fda30117 100644 --- a/packages/core/prebundle.config.mjs +++ b/packages/core/prebundle.config.mjs @@ -41,10 +41,6 @@ export default { picocolors: '@rsbuild/shared/picocolors', }, }, - { - name: 'line-diff', - ignoreDts: true, - }, { name: 'postcss-value-parser', ignoreDts: true, diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index fb164af8b5..810de2ae32 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -145,7 +145,6 @@ const getDefaultOutputConfig = (): NormalizedOutputConfig => ({ css: false, }, filenameHash: true, - enableCssModuleTSDeclaration: false, inlineScripts: false, inlineStyles: false, cssModules: { diff --git a/packages/core/src/plugins/css.ts b/packages/core/src/plugins/css.ts index fd8b4ccb4c..267d004fb3 100644 --- a/packages/core/src/plugins/css.ts +++ b/packages/core/src/plugins/css.ts @@ -261,7 +261,6 @@ export async function applyCSSRule({ // 1. Check user config const enableExtractCSS = isUseCssExtract(config, target); - const enableCSSModuleTS = Boolean(config.output.enableCssModuleTSDeclaration); // 2. Prepare loader options const localIdentName = getCssModuleLocalIdentName(config, isProd); @@ -306,17 +305,6 @@ export async function applyCSSRule({ .options(styleLoaderOptions) .end(); } - - // use css-modules-typescript-loader - if (enableCSSModuleTS && cssLoaderOptions.modules) { - rule - .use(CHAIN_ID.USE.CSS_MODULES_TS) - .loader(path.resolve(__dirname, '../rspack/cssModulesTypescriptLoader')) - .options({ - modules: cssLoaderOptions.modules, - }) - .end(); - } } else { rule .use(CHAIN_ID.USE.IGNORE_CSS) diff --git a/packages/core/tests/__snapshots__/css.test.ts.snap b/packages/core/tests/__snapshots__/css.test.ts.snap index ea25fb5722..78830b0444 100644 --- a/packages/core/tests/__snapshots__/css.test.ts.snap +++ b/packages/core/tests/__snapshots__/css.test.ts.snap @@ -1,84 +1,5 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`plugin-css > should apply custom css-modules-typescript-loader when enableCssModuleTSDeclaration 1`] = ` -{ - "experiments": { - "css": false, - }, - "module": { - "rules": [ - { - "resolve": { - "preferRelative": true, - }, - "sideEffects": true, - "test": /\\\\\\.css\\$/, - "use": [ - { - "loader": "/node_modules//@rspack/core/dist/builtin-plugin/css-extract/loader.js", - }, - { - "loader": "/packages/core/src/rspack/cssModulesTypescriptLoader", - "options": { - "modules": { - "auto": true, - "exportLocalsConvention": "camelCase", - "localIdentName": "[path][name]__[local]-[hash:base64:6]", - "namedExport": false, - }, - }, - }, - { - "loader": "/packages/core/compiled/css-loader", - "options": { - "importLoaders": 1, - "modules": { - "auto": true, - "exportLocalsConvention": "camelCase", - "localIdentName": "[path][name]__[local]-[hash:base64:6]", - "namedExport": false, - }, - "sourceMap": false, - }, - }, - { - "loader": "/packages/core/compiled/postcss-loader", - "options": { - "postcssOptions": { - "config": false, - "plugins": [ - { - "browsers": [ - "chrome >= 87", - "edge >= 88", - "firefox >= 78", - "safari >= 14", - ], - "info": [Function], - "options": { - "flexbox": "no-2009", - "overrideBrowserslist": [ - "chrome >= 87", - "edge >= 88", - "firefox >= 78", - "safari >= 14", - ], - }, - "postcssPlugin": "autoprefixer", - "prepare": [Function], - }, - ], - }, - "sourceMap": false, - }, - }, - ], - }, - ], - }, -} -`; - exports[`plugin-css > should override browserslist of autoprefixer when using output.overrideBrowserslist config 1`] = ` { "experiments": { diff --git a/packages/core/tests/css.test.ts b/packages/core/tests/css.test.ts index 23101544f7..e00aa75688 100644 --- a/packages/core/tests/css.test.ts +++ b/packages/core/tests/css.test.ts @@ -139,19 +139,6 @@ describe('plugin-css', () => { const bundlerConfigs = await rsbuild.initConfigs(); expect(bundlerConfigs[0]).toMatchSnapshot(); }); - - it('should apply custom css-modules-typescript-loader when enableCssModuleTSDeclaration', async () => { - const rsbuild = await createStubRsbuild({ - plugins: [pluginCss()], - rsbuildConfig: { - output: { - enableCssModuleTSDeclaration: true, - }, - }, - }); - const bundlerConfigs = await rsbuild.initConfigs(); - expect(bundlerConfigs[0]).toMatchSnapshot(); - }); }); describe('plugin-css injectStyles', () => { diff --git a/packages/plugin-typed-css-modules/LICENSE b/packages/plugin-typed-css-modules/LICENSE new file mode 100644 index 0000000000..82d38c25b5 --- /dev/null +++ b/packages/plugin-typed-css-modules/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023-present Bytedance, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/plugin-typed-css-modules/README.md b/packages/plugin-typed-css-modules/README.md new file mode 100644 index 0000000000..92531b7215 --- /dev/null +++ b/packages/plugin-typed-css-modules/README.md @@ -0,0 +1,19 @@ +

+ Rsbuild Logo +

+ +# Rsbuild + +The Rspack-based build tool. It's fast, out-of-the-box and extensible. + +## Documentation + +https://rsbuild.dev/ + +## Contributing + +Please read the [Contributing Guide](https://github.com/web-infra-dev/rsbuild/blob/main/CONTRIBUTING.md). + +## License + +Rsbuild is [MIT licensed](https://github.com/web-infra-dev/rsbuild/blob/main/LICENSE). diff --git a/packages/plugin-typed-css-modules/modern.config.ts b/packages/plugin-typed-css-modules/modern.config.ts new file mode 100644 index 0000000000..89c9198934 --- /dev/null +++ b/packages/plugin-typed-css-modules/modern.config.ts @@ -0,0 +1,13 @@ +import { moduleTools } from '@modern-js/module-tools'; +import { buildConfigWithMjs } from '../../scripts/modern.base.config'; + +export default { + plugins: [moduleTools()], + buildConfig: buildConfigWithMjs.map((config) => { + if (config.format === 'cjs') { + // add loader to entry + config.input = ['src/index.ts', 'src/loader.ts']; + } + return config; + }), +}; diff --git a/packages/plugin-typed-css-modules/package.json b/packages/plugin-typed-css-modules/package.json new file mode 100644 index 0000000000..540c1b21ac --- /dev/null +++ b/packages/plugin-typed-css-modules/package.json @@ -0,0 +1,48 @@ +{ + "name": "@rsbuild/plugin-typed-css-modules", + "version": "0.6.15", + "description": "Generate TypeScript declaration file for CSS Modules", + "homepage": "https://rsbuild.dev", + "repository": { + "type": "git", + "url": "https://github.com/web-infra-dev/rsbuild", + "directory": "packages/plugin-typed-css-modules" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs" + } + }, + "main": "./dist/index.cjs", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "modern build", + "dev": "modern build --watch", + "prebundle": "prebundle" + }, + "dependencies": { + "@rsbuild/shared": "workspace:*" + }, + "devDependencies": { + "@rsbuild/core": "workspace:*", + "@scripts/test-helper": "workspace:*", + "typescript": "^5.4.2", + "line-diff": "2.1.1", + "prebundle": "1.1.0" + }, + "peerDependencies": { + "@rsbuild/core": "workspace:^0.6.15" + }, + "publishConfig": { + "access": "public", + "provenance": true, + "registry": "https://registry.npmjs.org/" + } +} diff --git a/packages/plugin-typed-css-modules/prebundle.config.mjs b/packages/plugin-typed-css-modules/prebundle.config.mjs new file mode 100644 index 0000000000..b18ce4184e --- /dev/null +++ b/packages/plugin-typed-css-modules/prebundle.config.mjs @@ -0,0 +1,10 @@ +// @ts-check +/** @type {import('prebundle').Config} */ +export default { + dependencies: [ + { + name: 'line-diff', + ignoreDts: true, + }, + ], +}; diff --git a/packages/plugin-typed-css-modules/src/index.ts b/packages/plugin-typed-css-modules/src/index.ts new file mode 100644 index 0000000000..36b6d2c6f4 --- /dev/null +++ b/packages/plugin-typed-css-modules/src/index.ts @@ -0,0 +1,57 @@ +import path from 'node:path'; +import type { RsbuildPlugin } from '@rsbuild/core'; +import type { CSSLoaderOptions } from '@rsbuild/shared'; + +const PLUGIN_NAME = 'rsbuild:typed-css-modules'; + +export const pluginTypedCSSModules = (): RsbuildPlugin => ({ + name: PLUGIN_NAME, + + setup(api) { + api.modifyBundlerChain({ + order: 'post', + handler: async (chain, { isServer, isWebWorker, CHAIN_ID }) => { + if (!isServer && !isWebWorker) { + const ruleIds = [ + CHAIN_ID.RULE.CSS, + CHAIN_ID.RULE.SASS, + CHAIN_ID.RULE.LESS, + CHAIN_ID.RULE.STYLUS, + ]; + + for (const ruleId of ruleIds) { + if (!chain.module.rules.has(ruleId)) { + continue; + } + + const rule = chain.module.rule(ruleId); + + if (!rule.uses.has(CHAIN_ID.USE.CSS)) { + continue; + } + + const cssLoaderOptions: CSSLoaderOptions = rule + .use(CHAIN_ID.USE.CSS) + .get('options'); + + if ( + !cssLoaderOptions.modules || + (typeof cssLoaderOptions.modules === 'object' && + cssLoaderOptions.modules.auto === false) + ) { + continue; + } + + rule + .use(CHAIN_ID.USE.CSS_MODULES_TS) + .loader(path.resolve(__dirname, './loader.cjs')) + .options({ + modules: cssLoaderOptions.modules, + }) + .before(CHAIN_ID.USE.CSS); + } + } + }, + }); + }, +}); diff --git a/packages/core/src/rspack/cssModulesTypescriptLoader.ts b/packages/plugin-typed-css-modules/src/loader.ts similarity index 97% rename from packages/core/src/rspack/cssModulesTypescriptLoader.ts rename to packages/plugin-typed-css-modules/src/loader.ts index 577f000c93..8415af4ca0 100644 --- a/packages/core/src/rspack/cssModulesTypescriptLoader.ts +++ b/packages/plugin-typed-css-modules/src/loader.ts @@ -14,11 +14,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { type CssLoaderModules, + type Rspack, isCssModules, isInNodeModules, } from '@rsbuild/shared'; -import type { LoaderContext } from '@rspack/core'; -import LineDiff from '../../compiled/line-diff'; +import LineDiff from '../compiled/line-diff'; const bannerMessage = '// This file is automatically generated.\n// Please do not change this file!'; @@ -132,7 +132,7 @@ const getCssModuleKeys = (content: string) => { }; export default function ( - this: LoaderContext<{ + this: Rspack.LoaderContext<{ mode: string; modules: CssLoaderModules; }> & { diff --git a/packages/plugin-typed-css-modules/tests/__snapshots__/index.test.ts.snap b/packages/plugin-typed-css-modules/tests/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000000..5ca01d4e8a --- /dev/null +++ b/packages/plugin-typed-css-modules/tests/__snapshots__/index.test.ts.snap @@ -0,0 +1,134 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`plugin-typed-css-modules > should apply css-modules-typescript-loader 1`] = ` +[ + { + "resolve": { + "preferRelative": true, + }, + "sideEffects": true, + "test": /\\\\\\.css\\$/, + "use": [ + { + "loader": "/node_modules//@rspack/core/dist/builtin-plugin/css-extract/loader.js", + }, + { + "loader": "/packages/plugin-typed-css-modules/src/loader.cjs", + "options": { + "modules": { + "auto": true, + "exportLocalsConvention": "camelCase", + "localIdentName": "[path][name]__[local]-[hash:base64:6]", + "namedExport": false, + }, + }, + }, + { + "loader": "/packages/core/compiled/css-loader", + "options": { + "importLoaders": 1, + "modules": { + "auto": true, + "exportLocalsConvention": "camelCase", + "localIdentName": "[path][name]__[local]-[hash:base64:6]", + "namedExport": false, + }, + "sourceMap": false, + }, + }, + { + "loader": "/packages/core/compiled/postcss-loader", + "options": { + "postcssOptions": { + "config": false, + "plugins": [ + { + "browsers": [ + "chrome >= 87", + "edge >= 88", + "firefox >= 78", + "safari >= 14", + ], + "info": [Function], + "options": { + "flexbox": "no-2009", + "overrideBrowserslist": [ + "chrome >= 87", + "edge >= 88", + "firefox >= 78", + "safari >= 14", + ], + }, + "postcssPlugin": "autoprefixer", + "prepare": [Function], + }, + ], + }, + "sourceMap": false, + }, + }, + ], + }, +] +`; + +exports[`plugin-typed-css-modules > should not apply css-modules-typescript-loader 1`] = ` +[ + { + "resolve": { + "preferRelative": true, + }, + "sideEffects": true, + "test": /\\\\\\.css\\$/, + "use": [ + { + "loader": "/node_modules//@rspack/core/dist/builtin-plugin/css-extract/loader.js", + }, + { + "loader": "/packages/core/compiled/css-loader", + "options": { + "importLoaders": 1, + "modules": { + "auto": false, + "exportLocalsConvention": "camelCase", + "localIdentName": "[path][name]__[local]-[hash:base64:6]", + "namedExport": false, + }, + "sourceMap": false, + }, + }, + { + "loader": "/packages/core/compiled/postcss-loader", + "options": { + "postcssOptions": { + "config": false, + "plugins": [ + { + "browsers": [ + "chrome >= 87", + "edge >= 88", + "firefox >= 78", + "safari >= 14", + ], + "info": [Function], + "options": { + "flexbox": "no-2009", + "overrideBrowserslist": [ + "chrome >= 87", + "edge >= 88", + "firefox >= 78", + "safari >= 14", + ], + }, + "postcssPlugin": "autoprefixer", + "prepare": [Function], + }, + ], + }, + "sourceMap": false, + }, + }, + ], + }, +] +`; diff --git a/packages/plugin-typed-css-modules/tests/index.test.ts b/packages/plugin-typed-css-modules/tests/index.test.ts new file mode 100644 index 0000000000..c35b07f983 --- /dev/null +++ b/packages/plugin-typed-css-modules/tests/index.test.ts @@ -0,0 +1,48 @@ +import type { RspackConfig, RspackRule } from '@rsbuild/shared'; +import { createStubRsbuild } from '@scripts/test-helper'; +import { describe, expect, it, vi } from 'vitest'; +import { pluginCss } from '../../core/src/plugins/css'; +import { pluginTypedCSSModules } from '../src'; + +function matchRules(config: RspackConfig, testFile: string): RspackRule[] { + if (!config.module?.rules) { + return []; + } + return config.module.rules.filter((rule) => { + if ( + rule && + typeof rule === 'object' && + rule.test && + rule.test instanceof RegExp && + rule.test.test(testFile) + ) { + return true; + } + return false; + }); +} + +describe('plugin-typed-css-modules', () => { + it('should apply css-modules-typescript-loader', async () => { + const rsbuild = await createStubRsbuild({ + plugins: [pluginCss(), pluginTypedCSSModules()], + }); + const bundlerConfigs = await rsbuild.initConfigs(); + expect(matchRules(bundlerConfigs[0], 'a.css')).toMatchSnapshot(); + }); + + it('should not apply css-modules-typescript-loader', async () => { + const rsbuild = await createStubRsbuild({ + plugins: [pluginCss(), pluginTypedCSSModules()], + rsbuildConfig: { + output: { + cssModules: { + auto: false, + }, + }, + }, + }); + const bundlerConfigs = await rsbuild.initConfigs(); + expect(matchRules(bundlerConfigs[0], 'a.css')).toMatchSnapshot(); + }); +}); diff --git a/packages/core/tests/wrapQuotes.test.ts b/packages/plugin-typed-css-modules/tests/loader.test.ts similarity index 88% rename from packages/core/tests/wrapQuotes.test.ts rename to packages/plugin-typed-css-modules/tests/loader.test.ts index 500e7ea9d9..d4506837b7 100644 --- a/packages/core/tests/wrapQuotes.test.ts +++ b/packages/plugin-typed-css-modules/tests/loader.test.ts @@ -1,4 +1,5 @@ -import { wrapQuotes } from '../src/rspack/cssModulesTypescriptLoader'; +import { expect, it } from 'vitest'; +import { wrapQuotes } from '../src/loader'; it('should wrap key correctly', () => { // do not need wrap diff --git a/packages/plugin-typed-css-modules/tsconfig.json b/packages/plugin-typed-css-modules/tsconfig.json new file mode 100644 index 0000000000..0caaa55ade --- /dev/null +++ b/packages/plugin-typed-css-modules/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "@rsbuild/tsconfig/base", + "compilerOptions": { + "outDir": "./dist", + "baseUrl": "./", + "rootDir": "src", + "composite": true + }, + "references": [ + { + "path": "../core" + }, + { + "path": "../shared" + } + ], + "include": ["src"] +} diff --git a/packages/shared/src/types/config/output.ts b/packages/shared/src/types/config/output.ts index cb2839803d..c6ef9db263 100644 --- a/packages/shared/src/types/config/output.ts +++ b/packages/shared/src/types/config/output.ts @@ -260,10 +260,6 @@ export interface OutputConfig { * Whether to add filename hash after production build. */ filenameHash?: boolean | string; - /** - * Whether to generate a TypeScript declaration file for CSS Modules. - */ - enableCssModuleTSDeclaration?: boolean; /** * Whether to inline output scripts files (.js files) into HTML with `