diff --git a/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/index.js b/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/index.js new file mode 100644 index 00000000000..911b88fa446 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/index.js @@ -0,0 +1,6 @@ +import * as styles from './index.module.css' + +it("should transform css correct", () => { + expect(styles).toHaveProperty('used'); + expect('unused' in styles).toBeFalsy(); +}); diff --git a/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/index.module.css b/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/index.module.css new file mode 100644 index 00000000000..238878c89d8 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/index.module.css @@ -0,0 +1,9 @@ +body { + .used { + color: blue + } + + .unused { + color: red + } +} \ No newline at end of file diff --git a/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/rspack.config.js b/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/rspack.config.js new file mode 100644 index 00000000000..a72f61f30ce --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/builtin-lightningcss-loader/basic-include/rspack.config.js @@ -0,0 +1,35 @@ +const rspack = require('@rspack/core') +const browserslist = require('browserslist') + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + module: { + parser: { + 'css/auto': { + namedExports: true + } + }, + rules: [ + { + test: /\.css$/, + use: [ + { + loader: "builtin:lightningcss-loader", + /** @type {import("@rspack/core").LightningcssLoaderOptions} */ + options: { + unusedSymbols: ['unused'], + targets: 'ie 10', + include: { + nesting: true + } + } + } + ], + type: "css/auto" + } + ] + }, + experiments: { + css: true + } +}; diff --git a/packages/rspack/etc/api.md b/packages/rspack/etc/api.md index 67342dbcb2c..55024a4cfe9 100644 --- a/packages/rspack/etc/api.md +++ b/packages/rspack/etc/api.md @@ -728,9 +728,6 @@ export type BaseUri = z.infer; // @public (undocumented) const baseUri: z.ZodString; -// @public (undocumented) -function browserslistToTargets(browserslist: string[]): Record; - // @public (undocumented) type CacheHookMap = Map[]>; @@ -3373,58 +3370,6 @@ export type Falsy = z.infer; // @public (undocumented) const falsy: z.ZodUnion<[z.ZodLiteral, z.ZodLiteral<0>, z.ZodLiteral<"">, z.ZodNull, z.ZodUndefined]>; -// @public (undocumented) -enum Features { - // (undocumented) - ClampFunction = 512, - // (undocumented) - Color = 64512, - // (undocumented) - ColorFunction = 1024, - // (undocumented) - CustomMediaQueries = 256, - // (undocumented) - DirSelector = 4, - // (undocumented) - DoublePositionGradients = 131072, - // (undocumented) - Empty = 0, - // (undocumented) - FontFamilySystemUi = 65536, - // (undocumented) - HexAlphaColors = 16384, - // (undocumented) - IsSelector = 16, - // (undocumented) - LabColors = 4096, - // (undocumented) - LangSelectorList = 8, - // (undocumented) - LogicalProperties = 524288, - // (undocumented) - MediaIntervalSyntax = 64, - // (undocumented) - MediaQueries = 448, - // (undocumented) - MediaRangeSyntax = 128, - // (undocumented) - Nesting = 1, - // (undocumented) - NotSelectorList = 2, - // (undocumented) - OklabColors = 2048, - // (undocumented) - P3Colors = 8192, - // (undocumented) - Selectors = 31, - // (undocumented) - SpaceSeparatedColorNotation = 32768, - // (undocumented) - TextDecorationThicknessPercent = 32, - // (undocumented) - VendorPrefixes = 262144 -} - // @public (undocumented) const FetchCompileAsyncWasmPlugin: { new (): { @@ -4848,25 +4793,39 @@ export type LibraryType = z.infer; // @public (undocumented) const libraryType: z.ZodUnion<[z.ZodEnum<["var", "module", "assign", "assign-properties", "this", "window", "self", "global", "commonjs", "commonjs2", "commonjs-module", "commonjs-static", "amd", "amd-require", "umd", "umd2", "jsonp", "system"]>, z.ZodString]>; -declare namespace lightningcss { - export { - browserslistToTargets, - Features, - Targets, - Drafts, - NonStandard, - PseudoClasses, - LightningcssLoaderOptions as LoaderOptions - } -} -export { lightningcss } +// @public (undocumented) +export type LightningcssFeatureOptions = { + nesting?: boolean; + notSelectorList?: boolean; + dirSelector?: boolean; + langSelectorList?: boolean; + isSelector?: boolean; + textDecorationThicknessPercent?: boolean; + mediaIntervalSyntax?: boolean; + mediaRangeSyntax?: boolean; + customMediaQueries?: boolean; + clampFunction?: boolean; + colorFunction?: boolean; + oklabColors?: boolean; + labColors?: boolean; + p3Colors?: boolean; + hexAlphaColors?: boolean; + spaceSeparatedColorNotation?: boolean; + fontFamilySystemUi?: boolean; + doublePositionGradients?: boolean; + vendorPrefixes?: boolean; + logicalProperties?: boolean; + selectors?: boolean; + mediaQueries?: boolean; + color?: boolean; +}; // @public (undocumented) export type LightningcssLoaderOptions = { errorRecovery?: boolean; targets?: Targets | string[] | string; - include?: Features; - exclude?: Features; + include?: LightningcssFeatureOptions; + exclude?: LightningcssFeatureOptions; draft?: Drafts; nonStandard?: NonStandard; pseudoClasses?: PseudoClasses; @@ -8792,7 +8751,7 @@ declare namespace rspackExports { SwcLoaderTransformConfig, SwcLoaderTsParserConfig, LightningcssLoaderOptions, - lightningcss, + LightningcssFeatureOptions, experiments, getRawResolve, getRawLibrary, diff --git a/packages/rspack/src/builtin-loader/lightningcss/index.ts b/packages/rspack/src/builtin-loader/lightningcss/index.ts index 67a304cc539..64d9a211d6b 100644 --- a/packages/rspack/src/builtin-loader/lightningcss/index.ts +++ b/packages/rspack/src/builtin-loader/lightningcss/index.ts @@ -60,6 +60,87 @@ export function browserslistToTargets( return targets; } +export function toFeatures(featureOptions: FeatureOptions): Features { + let feature = 0; + for (const key of Reflect.ownKeys(featureOptions)) { + if (featureOptions[key as keyof FeatureOptions] !== true) { + continue; + } + switch (key as keyof FeatureOptions) { + case "nesting": + feature |= Features.Nesting; + break; + case "notSelectorList": + feature |= Features.NotSelectorList; + break; + case "dirSelector": + feature |= Features.DirSelector; + break; + case "langSelectorList": + feature |= Features.LangSelectorList; + break; + case "isSelector": + feature |= Features.IsSelector; + break; + case "textDecorationThicknessPercent": + feature |= Features.TextDecorationThicknessPercent; + break; + case "mediaIntervalSyntax": + feature |= Features.MediaIntervalSyntax; + break; + case "mediaRangeSyntax": + feature |= Features.MediaRangeSyntax; + break; + case "customMediaQueries": + feature |= Features.CustomMediaQueries; + break; + case "clampFunction": + feature |= Features.ClampFunction; + break; + case "colorFunction": + feature |= Features.ColorFunction; + break; + case "oklabColors": + feature |= Features.OklabColors; + break; + case "labColors": + feature |= Features.LabColors; + break; + case "p3Colors": + feature |= Features.P3Colors; + break; + case "hexAlphaColors": + feature |= Features.HexAlphaColors; + break; + case "spaceSeparatedColorNotation": + feature |= Features.SpaceSeparatedColorNotation; + break; + case "fontFamilySystemUi": + feature |= Features.FontFamilySystemUi; + break; + case "doublePositionGradients": + feature |= Features.DoublePositionGradients; + break; + case "vendorPrefixes": + feature |= Features.VendorPrefixes; + break; + case "logicalProperties": + feature |= Features.LogicalProperties; + break; + case "selectors": + feature |= Features.Selectors; + break; + case "mediaQueries": + feature |= Features.MediaQueries; + break; + case "color": + feature |= Features.Color; + break; + } + } + return feature; +} + function parseVersion(version: string) { const [major, minor = 0, patch = 0] = version .split("-")[0] @@ -141,11 +222,37 @@ export interface PseudoClasses { focusWithin?: string; } +export type FeatureOptions = { + nesting?: boolean; + notSelectorList?: boolean; + dirSelector?: boolean; + langSelectorList?: boolean; + isSelector?: boolean; + textDecorationThicknessPercent?: boolean; + mediaIntervalSyntax?: boolean; + mediaRangeSyntax?: boolean; + customMediaQueries?: boolean; + clampFunction?: boolean; + colorFunction?: boolean; + oklabColors?: boolean; + labColors?: boolean; + p3Colors?: boolean; + hexAlphaColors?: boolean; + spaceSeparatedColorNotation?: boolean; + fontFamilySystemUi?: boolean; + doublePositionGradients?: boolean; + vendorPrefixes?: boolean; + logicalProperties?: boolean; + selectors?: boolean; + mediaQueries?: boolean; + color?: boolean; +}; + export type LoaderOptions = { errorRecovery?: boolean; targets?: Targets | string[] | string; - include?: Features; - exclude?: Features; + include?: FeatureOptions; + exclude?: FeatureOptions; draft?: Drafts; nonStandard?: NonStandard; pseudoClasses?: PseudoClasses; diff --git a/packages/rspack/src/config/adapterRuleUse.ts b/packages/rspack/src/config/adapterRuleUse.ts index da04c24bf96..89471c034ec 100644 --- a/packages/rspack/src/config/adapterRuleUse.ts +++ b/packages/rspack/src/config/adapterRuleUse.ts @@ -9,7 +9,11 @@ import type { Compilation } from "../Compilation"; import type { Compiler } from "../Compiler"; import type { Module } from "../Module"; import { resolvePluginImport } from "../builtin-loader"; -import { browserslistToTargets } from "../builtin-loader/lightningcss"; +import { + type FeatureOptions, + browserslistToTargets, + toFeatures +} from "../builtin-loader/lightningcss"; import { type LoaderObject, parsePathQueryFragment } from "../loader-runner"; import type { Logger } from "../logging/Logger"; import { isNil } from "../util"; @@ -220,6 +224,14 @@ const getLightningcssLoaderOptions: GetLoaderOptions = (o, _) => { if (o.targets && Array.isArray(o.targets)) { o.targets = browserslistToTargets(o.targets); } + + if (o.include) { + o.include = toFeatures(o.include as unknown as FeatureOptions); + } + + if (o.exclude) { + o.exclude = toFeatures(o.exclude as unknown as FeatureOptions); + } } return o; }; diff --git a/packages/rspack/src/exports.ts b/packages/rspack/src/exports.ts index bf4eb310cc1..c0da01b4a35 100644 --- a/packages/rspack/src/exports.ts +++ b/packages/rspack/src/exports.ts @@ -260,10 +260,10 @@ export type { SwcLoaderTsParserConfig } from "./builtin-loader/swc/index"; -import * as lightningcss from "./builtin-loader/lightningcss/index"; - -export { type LoaderOptions as LightningcssLoaderOptions } from "./builtin-loader/lightningcss/index"; -export { lightningcss }; +export { + type LoaderOptions as LightningcssLoaderOptions, + type FeatureOptions as LightningcssFeatureOptions +} from "./builtin-loader/lightningcss/index"; ///// Experiments Stuff ///// import { cleanupGlobalTrace, registerGlobalTrace } from "@rspack/binding"; diff --git a/website/docs/en/guide/features/builtin-lightningcss-loader.mdx b/website/docs/en/guide/features/builtin-lightningcss-loader.mdx index 8a6c549849e..659216fe6eb 100644 --- a/website/docs/en/guide/features/builtin-lightningcss-loader.mdx +++ b/website/docs/en/guide/features/builtin-lightningcss-loader.mdx @@ -66,11 +66,37 @@ module.exports = { Below are the configurations supported by `builtin:lightningcss-loader`. For detailed configuration, please refer to [lightningcss document](https://lightningcss.dev/transpilation.html) ```ts +type LightningcssFeatureOptions = { + nesting?: boolean; + notSelectorList?: boolean; + dirSelector?: boolean; + langSelectorList?: boolean; + isSelector?: boolean; + textDecorationThicknessPercent?: boolean; + mediaIntervalSyntax?: boolean; + mediaRangeSyntax?: boolean; + customMediaQueries?: boolean; + clampFunction?: boolean; + colorFunction?: boolean; + oklabColors?: boolean; + labColors?: boolean; + p3Colors?: boolean; + hexAlphaColors?: boolean; + spaceSeparatedColorNotation?: boolean; + fontFamilySystemUi?: boolean; + doublePositionGradients?: boolean; + vendorPrefixes?: boolean; + logicalProperties?: boolean; + selectors?: boolean; + mediaQueries?: boolean; + color?: boolean; +}; + type LightningcssLoaderOptions = { errorRecovery?: boolean; targets?: Targets | string[] | string; - include?: Features; - exclude?: Features; + include?: LightningcssFeatureOptions; + exclude?: LightningcssFeatureOptions; draft?: Drafts; nonStandard?: NonStandard; pseudoClasses?: PseudoClasses; @@ -78,13 +104,6 @@ type LightningcssLoaderOptions = { }; ``` -You can find the necessary `lightningcss` exports from the `lightningcss` property in the `@rspack/core` package, such as `Features`: - -```ts -const rspack = require('@rspack/core'); -const { Features } = rspack.lightningcss; -``` - The `targets` can be directly written as a `browserslist` query string, the result of a `browserslist` query, or the `targets` of lightningcss, for example: ```js diff --git a/website/docs/zh/guide/features/builtin-lightningcss-loader.mdx b/website/docs/zh/guide/features/builtin-lightningcss-loader.mdx index 1e24e9199ab..6c2a74f0ff9 100644 --- a/website/docs/zh/guide/features/builtin-lightningcss-loader.mdx +++ b/website/docs/zh/guide/features/builtin-lightningcss-loader.mdx @@ -66,11 +66,37 @@ module.exports = { 下面是 `builtin:lightningcss-loader` 支持的配置。详细的解释请查看 [lightningcss 文档](https://lightningcss.dev/transpilation.html) ```ts +type LightningcssFeatureOptions = { + nesting?: boolean; + notSelectorList?: boolean; + dirSelector?: boolean; + langSelectorList?: boolean; + isSelector?: boolean; + textDecorationThicknessPercent?: boolean; + mediaIntervalSyntax?: boolean; + mediaRangeSyntax?: boolean; + customMediaQueries?: boolean; + clampFunction?: boolean; + colorFunction?: boolean; + oklabColors?: boolean; + labColors?: boolean; + p3Colors?: boolean; + hexAlphaColors?: boolean; + spaceSeparatedColorNotation?: boolean; + fontFamilySystemUi?: boolean; + doublePositionGradients?: boolean; + vendorPrefixes?: boolean; + logicalProperties?: boolean; + selectors?: boolean; + mediaQueries?: boolean; + color?: boolean; +}; + type LightningcssLoaderOptions = { errorRecovery?: boolean; targets?: Targets | string[] | string; - include?: Features; - exclude?: Features; + include?: LightningcssFeatureOptions; + exclude?: LightningcssFeatureOptions; draft?: Drafts; nonStandard?: NonStandard; pseudoClasses?: PseudoClasses; @@ -78,13 +104,6 @@ type LightningcssLoaderOptions = { }; ``` -你可以从 `@rspack/core` 包中的 `lightningcss` 属性找到需要的 `lightningcss` 导出,例如 `Features`: - -```ts -const rspack = require('@rspack/core'); -const { Features } = rspack.lightningcss; -``` - 其中 `targets` 可以直接写 `browserslist` 查询字符串,`browserslist` 查询结果,或是 lightningcss 的 `targets`,例如 ```js