Skip to content

Commit

Permalink
feat: implement include and exclude option (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
colinaaa authored Nov 23, 2024
1 parent 0f1cc6c commit f02a9f1
Show file tree
Hide file tree
Showing 18 changed files with 536 additions and 21 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@playwright/test": "^1.48.2",
"@rollup/pluginutils": "^5.1.3",
"@rsbuild/core": "^1.1.0",
"@rslib/core": "^0.0.16",
"@types/node": "^22.9.0",
Expand Down
28 changes: 28 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 77 additions & 14 deletions src/TailwindCSSRspackPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { tmpdir } from 'node:os';
import path from 'node:path';
import { pathToFileURL } from 'node:url';

import { createFilter } from '@rollup/pluginutils';
import type { PostCSSLoaderOptions, Rspack } from '@rsbuild/core';

/**
Expand Down Expand Up @@ -56,6 +57,61 @@ interface TailwindRspackPluginOptions {
*/
config: string;

/**
* The modules to be excluded.
*
* If {@link include} is omitted or empty,
* all modules that do not match any of the {@link exclude} patterns will be included.
* Otherwise, only modules that match one or more of the {@link include} patterns
* and do not match any of the {@link exclude} patterns will be included.
*
* @example
*
* ```js
* // rspack.config.js
* import { TailwindRspackPlugin } from 'rsbuild-plugin-tailwindcss'
*
* export default {
* plugins: [
* new TailwindRspackPlugin({
* exclude: [
* './src/store/**',
* /[\\/]node_modules[\\/]/,
* ],
* }),
* ],
* }
* ```
*/
exclude?: FilterPattern | undefined;

/**
* The modules to be included using `picomatch` patterns.
*
* If {@link include} is omitted or empty,
* all modules that do not match any of the {@link exclude} patterns will be included.
* Otherwise, only modules that match one or more of the {@link include} patterns
* and do not match any of the {@link exclude} patterns will be included.
*
* @example
*
* ```js
* // rspack.config.js
* import { TailwindRspackPlugin } from 'rsbuild-plugin-tailwindcss'
*
* export default {
* plugins: [
* new TailwindRspackPlugin({
* include: [
* /\.[jt]sx?/,
* ],
* }),
* ],
* }
* ```
*/
include?: FilterPattern | undefined;

/**
* The postcss options to be applied.
*
Expand Down Expand Up @@ -86,6 +142,16 @@ interface TailwindRspackPluginOptions {
>;
}

// From `@rollup/pluginutils`
/**
* A valid `picomatch` glob pattern, or array of patterns.
*/
export type FilterPattern =
| ReadonlyArray<string | RegExp>
| string
| RegExp
| null;

/**
* The Rspack plugin for Tailwind integration.
*
Expand All @@ -94,17 +160,6 @@ interface TailwindRspackPluginOptions {
class TailwindRspackPlugin {
constructor(private readonly options: TailwindRspackPluginOptions) {}

/**
* `defaultOptions` is the default options that the {@link TailwindRspackPlugin} uses.
*
* @public
*/
static defaultOptions: Readonly<Required<TailwindRspackPluginOptions>> =
Object.freeze<Required<TailwindRspackPluginOptions>>({
config: 'tailwind.config.js',
postcssOptions: {},
});

/**
* The entry point of a Rspack plugin.
* @param compiler - the Rspack compiler
Expand All @@ -124,6 +179,11 @@ class TailwindRspackPluginImpl {
private compiler: Rspack.Compiler,
private options: TailwindRspackPluginOptions,
) {
const filter = createFilter(options.include, options.exclude, {
// biome-ignore lint/style/noNonNullAssertion: context should exist
resolve: compiler.options.context!,
});

const { RawSource } = compiler.webpack.sources;
compiler.hooks.thisCompilation.tap(this.name, (compilation) => {
compilation.hooks.processAssets.tapPromise(this.name, async () => {
Expand Down Expand Up @@ -159,7 +219,10 @@ class TailwindRspackPluginImpl {
] = await Promise.all([
import('postcss'),
import('tailwindcss'),
this.#prepareTailwindConfig(entryName, entryModules),
this.#prepareTailwindConfig(
entryName,
Array.from(entryModules).filter(filter),
),
]);

const postcssTransform = postcss([
Expand Down Expand Up @@ -203,7 +266,7 @@ class TailwindRspackPluginImpl {

async #prepareTailwindConfig(
entryName: string,
entryModules: Set<string>,
entryModules: Array<string>,
): Promise<string> {
const userConfig = path.isAbsolute(this.options.config)
? this.options.config
Expand All @@ -225,7 +288,7 @@ class TailwindRspackPluginImpl {

const configPath = path.resolve(outputDir, 'tailwind.config.mjs');

const content = JSON.stringify(Array.from(entryModules));
const content = JSON.stringify(entryModules);

await writeFile(
configPath,
Expand Down
75 changes: 68 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import type {
} from '@rsbuild/core';

import { TailwindRspackPlugin } from './TailwindCSSRspackPlugin.js';
import type { FilterPattern } from './TailwindCSSRspackPlugin.js';

export type PluginTailwindCSSOptions = {
export type { FilterPattern };

export interface PluginTailwindCSSOptions {
/**
* The path to the configuration of Tailwind CSS.
*
Expand Down Expand Up @@ -54,7 +57,62 @@ export type PluginTailwindCSSOptions = {
* ```
*/
config?: string;
};

/**
* The modules to be excluded using `picomatch` patterns.
*
* If {@link include} is omitted or empty,
* all modules that do not match any of the {@link exclude} patterns will be included.
* Otherwise, only modules that match one or more of the {@link include} patterns
* and do not match any of the {@link exclude} patterns will be included.
*
* @example
*
* ```js
* // rsbuild.config.ts
* import { pluginTailwindCSS } from '@byted-lynx/plugin-tailwindcss'
*
* export default {
* plugins: [
* pluginTailwindCSS({
* exclude: [
* './src/store/**',
* /[\\/]node_modules[\\/]/,
* ],
* }),
* ],
* }
* ```
*/
exclude?: FilterPattern | undefined;

/**
* The modules to be included using `picomatch` patterns.
*
* If {@link include} is omitted or empty,
* all modules that do not match any of the {@link exclude} patterns will be included.
* Otherwise, only modules that match one or more of the {@link include} patterns
* and do not match any of the {@link exclude} patterns will be included.
*
* @example
*
* ```js
* // rsbuild.config.ts
* import { pluginTailwindCSS } from '@byted-lynx/plugin-tailwindcss'
*
* export default {
* plugins: [
* pluginTailwindCSS({
* include: [
* /\.[jt]sx?/,
* ],
* }),
* ],
* }
* ```
*/
include?: FilterPattern | undefined;
}

export const pluginTailwindCSS = (
options: PluginTailwindCSSOptions = {},
Expand Down Expand Up @@ -97,11 +155,14 @@ export const pluginTailwindCSS = (
api.modifyBundlerChain({
order: 'post',
handler(chain) {
chain
.plugin('tailwindcss')
.use(TailwindRspackPlugin, [
{ config: options.config ?? 'tailwind.config.js', postcssOptions },
]);
chain.plugin('tailwindcss').use(TailwindRspackPlugin, [
{
config: options.config ?? 'tailwind.config.js',
include: options.include,
exclude: options.exclude,
postcssOptions,
},
]);
},
});
},
Expand Down
Loading

0 comments on commit f02a9f1

Please sign in to comment.