From 5968becf5970125b90b503a53208e2dff29b02bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Risoud?= Date: Mon, 6 Mar 2023 18:58:14 +0100 Subject: [PATCH] feat(css): add preprocessor option to define stylus vars & funcs (#7227) Co-authored-by: bluwy --- docs/config/shared-options.md | 17 +++++++++++++++-- packages/vite/src/node/plugins/css.ts | 18 +++++++++++++++++- playground/css/__tests__/css.spec.ts | 4 ++++ playground/css/index.html | 8 ++++++++ playground/css/stylus.styl | 8 ++++++++ playground/css/vite.config.js | 5 +++++ 6 files changed, 57 insertions(+), 3 deletions(-) diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md index 3fb77ec43..7dacf0e82 100644 --- a/docs/config/shared-options.md +++ b/docs/config/shared-options.md @@ -226,7 +226,15 @@ Note if an inline config is provided, Vite will not search for other PostCSS con - **Type:** `Record` -Specify options to pass to CSS pre-processors. The file extensions are used as keys for the options. Example: +Specify options to pass to CSS pre-processors. The file extensions are used as keys for the options. The supported options for each preprocessors can be found in their respective documentation: + +- `sass`/`scss` - [Options](https://sass-lang.com/documentation/js-api/interfaces/LegacyStringOptions). +- `less` - [Options](https://lesscss.org/usage/#less-options). +- `styl`/`stylus` - Only [`define`](https://stylus-lang.com/docs/js.html#define-name-node) is supported, which can be passed as an object. + +All preprocessor options also support the `additionalData` option, which can be used to inject extra code for each style content. + +Example: ```js export default defineConfig({ @@ -235,8 +243,13 @@ export default defineConfig({ scss: { additionalData: `$injectedColor: orange;`, }, + less: { + math: 'parens-division', + }, styl: { - additionalData: `$injectedColor ?= orange`, + define: { + $specialColor: new stylus.nodes.RGBA(51, 197, 255, 1), + }, }, }, }, diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 38ca4cac2..810498df1 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1453,6 +1453,10 @@ type StylePreprocessorOptions = { type SassStylePreprocessorOptions = StylePreprocessorOptions & Sass.Options +type StylusStylePreprocessorOptions = StylePreprocessorOptions & { + define?: Record +} + type StylePreprocessor = ( source: string, root: string, @@ -1467,6 +1471,13 @@ type SassStylePreprocessor = ( resolvers: CSSAtImportResolvers, ) => StylePreprocessorResults | Promise +type StylusStylePreprocessor = ( + source: string, + root: string, + options: StylusStylePreprocessorOptions, + resolvers: CSSAtImportResolvers, +) => StylePreprocessorResults | Promise + export interface StylePreprocessorResults { code: string map?: ExistingRawSourceMap | undefined @@ -1847,7 +1858,7 @@ function createViteLessPlugin( } // .styl -const styl: StylePreprocessor = async (source, root, options) => { +const styl: StylusStylePreprocessor = async (source, root, options) => { const nodeStylus = loadPreprocessor(PreprocessLang.stylus, root) // Get source with preprocessor options.additionalData. Make sure a new line separator // is added to avoid any render error, as added stylus content may not have semi-colon separators @@ -1865,6 +1876,11 @@ const styl: StylePreprocessor = async (source, root, options) => { ) try { const ref = nodeStylus(content, options) + if (options.define) { + for (const key in options.define) { + ref.define(key, options.define[key]) + } + } if (options.enableSourcemap) { ref.set('sourcemap', { comment: false, diff --git a/playground/css/__tests__/css.spec.ts b/playground/css/__tests__/css.spec.ts index c3ae17f0e..9951558fa 100644 --- a/playground/css/__tests__/css.spec.ts +++ b/playground/css/__tests__/css.spec.ts @@ -146,6 +146,8 @@ test('stylus', async () => { const relativeImportAlias = await page.$('.stylus-import-alias') const optionsRelativeImport = await page.$('.stylus-options-relative-import') const optionsAbsoluteImport = await page.$('.stylus-options-absolute-import') + const optionsDefineVar = await page.$('.stylus-options-define-var') + const optionsDefineFunc = await page.$('.stylus-options-define-func') expect(await getColor(imported)).toBe('blue') expect(await getColor(additionalData)).toBe('orange') @@ -156,6 +158,8 @@ test('stylus', async () => { ) expect(await getColor(optionsRelativeImport)).toBe('green') expect(await getColor(optionsAbsoluteImport)).toBe('red') + expect(await getColor(optionsDefineVar)).toBe('rgb(51, 197, 255)') + expect(await getColor(optionsDefineFunc)).toBe('rgb(255, 0, 98)') editFile('stylus.styl', (code) => code.replace('$color ?= blue', '$color ?= red'), diff --git a/playground/css/index.html b/playground/css/index.html index f520d6514..a90c5dd7e 100644 --- a/playground/css/index.html +++ b/playground/css/index.html @@ -72,6 +72,14 @@ Stylus import (absolute path) via vite config preprocessor options: This should be red

+

+ Stylus define variable via vite config preprocessor options: This should be + rgb(51, 197, 255) +

+

+ Stylus define function via vite config preprocessor options: This should be + rgb(255, 0, 98) +

Imported Stylus string:


 
diff --git a/playground/css/stylus.styl b/playground/css/stylus.styl
index d43ba92d7..a4e61e6c0 100644
--- a/playground/css/stylus.styl
+++ b/playground/css/stylus.styl
@@ -8,3 +8,11 @@ $color ?= blue
 .stylus-additional-data
   /* injected via vite.config.js */
   color $injectedColor
+
+.stylus-options-define-var
+  /* defined in vite.config.js */
+  color $definedColor
+
+.stylus-options-define-func
+  /* defined in vite.config.js */
+  color definedFunction()
diff --git a/playground/css/vite.config.js b/playground/css/vite.config.js
index 33a99cf50..aa905db51 100644
--- a/playground/css/vite.config.js
+++ b/playground/css/vite.config.js
@@ -1,4 +1,5 @@
 import path from 'node:path'
+import stylus from 'stylus'
 import { defineConfig } from 'vite'
 
 // trigger scss bug: https://github.com/sass/dart-sass/issues/710
@@ -68,6 +69,10 @@ export default defineConfig({
           './options/relative-import.styl',
           path.join(__dirname, 'options/absolute-import.styl'),
         ],
+        define: {
+          $definedColor: new stylus.nodes.RGBA(51, 197, 255, 1),
+          definedFunction: () => new stylus.nodes.RGBA(255, 0, 98, 1),
+        },
       },
     },
   },