Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions e2e/cases/stylus/inline-query/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { build, dev, rspackOnlyTest } from '@e2e/helper';
import { expect } from '@playwright/test';

rspackOnlyTest(
'should allow to import inline Stylus files in development mode',
async ({ page }) => {
const rsbuild = await dev({
cwd: __dirname,
page,
});

const aInline: string = await page.evaluate('window.aInline');
const bInline: string = await page.evaluate('window.bInline');

expect(
aInline.includes('.header-class') && aInline.includes('color: red'),
).toBe(true);
expect(
bInline.includes('.title-class') && bInline.includes('font-size: 14px'),
).toBe(true);

await rsbuild.close();
},
);

rspackOnlyTest(
'should allow to import inline Stylus files in production mode',
async ({ page }) => {
const rsbuild = await build({
cwd: __dirname,
page,
});

expect(await page.evaluate('window.aInline')).toBe(
'.header-class{color:red}',
);
expect(await page.evaluate('window.bInline')).toBe(
'.title-class{font-size:14px}',
);

await rsbuild.close();
},
);
5 changes: 5 additions & 0 deletions e2e/cases/stylus/inline-query/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import aInline from './a.styl?inline';
import bInline from './b.module.styl?inline';

window.aInline = aInline;
window.bInline = bInline;
5 changes: 5 additions & 0 deletions e2e/cases/stylus/raw-query/rsbuild.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { pluginStylus } from '@rsbuild/plugin-stylus';

export default {
plugins: [pluginStylus()],
};
3 changes: 3 additions & 0 deletions e2e/cases/stylus/raw-query/src/a.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.header
&-class
color red
3 changes: 3 additions & 0 deletions e2e/cases/stylus/raw-query/src/b.module.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.title
&-class
font-size 14px
2 changes: 2 additions & 0 deletions packages/core/src/configChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export const CHAIN_ID = {
STYLUS: 'stylus',
/** Rule for raw stylus */
STYLUS_RAW: 'stylus-raw',
/** Rule for inline stylus */
STYLUS_INLINE: 'stylus-inline',
/** Rule for svg */
SVG: 'svg',
/** Rule for pug */
Expand Down
8 changes: 8 additions & 0 deletions packages/core/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,14 @@ declare module '*.less?inline' {
const content: string;
export default content;
}
declare module '*.styl?inline' {
const content: string;
export default content;
}
declare module '*.stylus?inline' {
const content: string;
export default content;
}

/**
* Raw CSS
Expand Down
59 changes: 38 additions & 21 deletions packages/plugin-stylus/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createRequire } from 'node:module';
import type { RsbuildPlugin } from '@rsbuild/core';
import type { RsbuildPlugin, RspackChain } from '@rsbuild/core';
import deepmerge from 'deepmerge';
import { reduceConfigs } from 'reduce-configs';

Expand Down Expand Up @@ -54,11 +54,16 @@ export const pluginStylus = (options?: PluginStylusOptions): RsbuildPlugin => ({
const rule = chain.module
.rule(CHAIN_ID.RULE.STYLUS)
.test(test)
// exclude `import './foo.styl?raw'` and `import './foo.stylus?inline'`
.resourceQuery({ not: /raw|inline/ })
.sideEffects(true)
.resolve.preferRelative(true)
.end()
// exclude `import './foo.styl?raw'`
.resourceQuery({ not: /raw/ });
.end();

const inlineRule = chain.module
.rule(CHAIN_ID.RULE.STYLUS_INLINE)
.test(test)
.resourceQuery(/inline/);

// Support for importing raw Stylus files
chain.module
Expand All @@ -67,27 +72,39 @@ export const pluginStylus = (options?: PluginStylusOptions): RsbuildPlugin => ({
.type('asset/source')
.resourceQuery(/raw/);

// Copy the builtin CSS rules
const cssRule = chain.module.rules.get(CHAIN_ID.RULE.CSS);
rule.dependency(cssRule.get('dependency'));
// Update the normal rule and the inline rule
const updateRules = (
callback: (rule: RspackChain.Rule, type: 'normal' | 'inline') => void,
) => {
callback(rule, 'normal');
callback(inlineRule, 'inline');
};

for (const id of Object.keys(cssRule.uses.entries())) {
const loader = cssRule.uses.get(id);
const options = loader.get('options') ?? {};
const clonedOptions = deepmerge<Record<string, any>>({}, options);
updateRules((rule, type) => {
// Copy the builtin CSS rules
const cssRule = chain.module.rules.get(
type === 'normal' ? CHAIN_ID.RULE.CSS : CHAIN_ID.RULE.CSS_INLINE,
);
rule.dependency(cssRule.get('dependency'));

if (id === CHAIN_ID.USE.CSS) {
// add stylus-loader
clonedOptions.importLoaders += 1;
}
for (const id of Object.keys(cssRule.uses.entries())) {
const loader = cssRule.uses.get(id);
const options = loader.get('options') ?? {};
const clonedOptions = deepmerge<Record<string, any>>({}, options);

rule.use(id).loader(loader.get('loader')).options(clonedOptions);
}
if (id === CHAIN_ID.USE.CSS) {
// add stylus-loader
clonedOptions.importLoaders += 1;
}

rule
.use(CHAIN_ID.USE.STYLUS)
.loader(require.resolve('stylus-loader'))
.options(mergedOptions);
rule.use(id).loader(loader.get('loader')).options(clonedOptions);
}

rule
.use(CHAIN_ID.USE.STYLUS)
.loader(require.resolve('stylus-loader'))
.options(mergedOptions);
});
});
},
});
71 changes: 69 additions & 2 deletions packages/plugin-stylus/tests/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ exports[`plugin-stylus > should add stylus loader config correctly 1`] = `
"preferRelative": true,
},
"resourceQuery": {
"not": /raw/,
"not": /raw\\|inline/,
},
"sideEffects": true,
"test": /\\\\\\.styl\\(us\\)\\?\\$/,
Expand Down Expand Up @@ -51,6 +51,38 @@ exports[`plugin-stylus > should add stylus loader config correctly 1`] = `
},
],
},
{
"resourceQuery": /inline/,
"test": /\\\\\\.styl\\(us\\)\\?\\$/,
"use": [
{
"loader": "<ROOT>/packages/core/compiled/css-loader/index.js",
"options": {
"exportType": "string",
"importLoaders": 2,
"modules": false,
"sourceMap": false,
},
},
{
"loader": "builtin:lightningcss-loader",
"options": {
"targets": [
"chrome >= 87",
"edge >= 88",
"firefox >= 78",
"safari >= 14",
],
},
},
{
"loader": "<ROOT>/node_modules/<PNPM_INNER>/stylus-loader/dist/cjs.js",
"options": {
"sourceMap": false,
},
},
],
},
{
"resourceQuery": /raw/,
"test": /\\\\\\.styl\\(us\\)\\?\\$/,
Expand All @@ -69,7 +101,7 @@ exports[`plugin-stylus > should allow to configure stylus options 1`] = `
"preferRelative": true,
},
"resourceQuery": {
"not": /raw/,
"not": /raw\\|inline/,
},
"sideEffects": true,
"test": /\\\\\\.styl\\(us\\)\\?\\$/,
Expand Down Expand Up @@ -113,6 +145,41 @@ exports[`plugin-stylus > should allow to configure stylus options 1`] = `
},
],
},
{
"resourceQuery": /inline/,
"test": /\\\\\\.styl\\(us\\)\\?\\$/,
"use": [
{
"loader": "<ROOT>/packages/core/compiled/css-loader/index.js",
"options": {
"exportType": "string",
"importLoaders": 2,
"modules": false,
"sourceMap": false,
},
},
{
"loader": "builtin:lightningcss-loader",
"options": {
"targets": [
"chrome >= 87",
"edge >= 88",
"firefox >= 78",
"safari >= 14",
],
},
},
{
"loader": "<ROOT>/node_modules/<PNPM_INNER>/stylus-loader/dist/cjs.js",
"options": {
"sourceMap": false,
"stylusOptions": {
"lineNumbers": false,
},
},
},
],
},
{
"resourceQuery": /raw/,
"test": /\\\\\\.styl\\(us\\)\\?\\$/,
Expand Down
Loading