Skip to content

Commit

Permalink
feat(css): add preprocessor option to define stylus vars & funcs (#7227)
Browse files Browse the repository at this point in the history
Co-authored-by: bluwy <bjornlu.dev@gmail.com>
  • Loading branch information
qnp and bluwy committed Mar 6, 2023
1 parent cc92da9 commit 5968bec
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 3 deletions.
17 changes: 15 additions & 2 deletions docs/config/shared-options.md
Expand Up @@ -226,7 +226,15 @@ Note if an inline config is provided, Vite will not search for other PostCSS con

- **Type:** `Record<string, object>`

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({
Expand All @@ -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),
},
},
},
},
Expand Down
18 changes: 17 additions & 1 deletion packages/vite/src/node/plugins/css.ts
Expand Up @@ -1453,6 +1453,10 @@ type StylePreprocessorOptions = {

type SassStylePreprocessorOptions = StylePreprocessorOptions & Sass.Options

type StylusStylePreprocessorOptions = StylePreprocessorOptions & {
define?: Record<string, any>
}

type StylePreprocessor = (
source: string,
root: string,
Expand All @@ -1467,6 +1471,13 @@ type SassStylePreprocessor = (
resolvers: CSSAtImportResolvers,
) => StylePreprocessorResults | Promise<StylePreprocessorResults>

type StylusStylePreprocessor = (
source: string,
root: string,
options: StylusStylePreprocessorOptions,
resolvers: CSSAtImportResolvers,
) => StylePreprocessorResults | Promise<StylePreprocessorResults>

export interface StylePreprocessorResults {
code: string
map?: ExistingRawSourceMap | undefined
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions playground/css/__tests__/css.spec.ts
Expand Up @@ -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')
Expand All @@ -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'),
Expand Down
8 changes: 8 additions & 0 deletions playground/css/index.html
Expand Up @@ -72,6 +72,14 @@ <h1>CSS</h1>
Stylus import (absolute path) via vite config preprocessor options: This
should be red
</p>
<p class="stylus-options-define-var">
Stylus define variable via vite config preprocessor options: This should be
rgb(51, 197, 255)
</p>
<p class="stylus-options-define-func">
Stylus define function via vite config preprocessor options: This should be
rgb(255, 0, 98)
</p>
<p>Imported Stylus string:</p>
<pre class="imported-stylus"></pre>

Expand Down
8 changes: 8 additions & 0 deletions playground/css/stylus.styl
Expand Up @@ -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()
5 changes: 5 additions & 0 deletions 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
Expand Down Expand Up @@ -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),
},
},
},
},
Expand Down

0 comments on commit 5968bec

Please sign in to comment.