weapp-tailwindcss
Version:
把 tailwindcss 原子化样式思想,带给小程序开发者们! bring tailwindcss to miniprogram developers!
696 lines (689 loc) • 24.4 kB
TypeScript
import { ParserOptions, ParseError } from '@babel/parser';
import { CssPreflightOptions, CssCalcOptions, Rem2rpxOptions, Px2rpxOptions, PresetEnvOptions, LoadedPostcssOptions, IStyleHandlerOptions } from '@weapp-tailwindcss/postcss';
export { CssPreflightOptions, IStyleHandlerOptions } from '@weapp-tailwindcss/postcss';
import { SourceMap } from 'magic-string';
import { Result, Root, Document } from 'postcss';
import { TailwindcssPatchOptions, ILengthUnitsPatchOptions, TailwindcssPatcher } from 'tailwindcss-patch';
import { Buffer } from 'node:buffer';
import { sources } from 'webpack';
import { LRUCache } from 'lru-cache';
interface HashMapValue {
hash: string;
changed: boolean;
}
type HashMapKey = string | number;
type CacheValue = sources.Source | string;
interface CacheProcessResult<T extends CacheValue> {
result: T;
cacheValue?: CacheValue;
}
interface CacheProcessOptions<T extends CacheValue> {
key: string;
hashKey?: HashMapKey;
rawSource?: string | Buffer;
hash?: string;
resolveCache?: () => T | undefined;
transform: () => Promise<CacheProcessResult<T> | T>;
onCacheHit?: (value: T) => void | Promise<void>;
}
interface ICreateCacheReturnType {
readonly hashMap: Map<HashMapKey, HashMapValue>;
readonly instance: LRUCache<string, CacheValue>;
hasHashKey: (key: HashMapKey) => boolean;
getHashValue: (key: HashMapKey) => HashMapValue | undefined;
setHashValue: (key: HashMapKey, value: HashMapValue) => Map<HashMapKey, HashMapValue>;
computeHash: (message: string | Buffer) => string;
get: <V extends CacheValue = sources.Source>(key: string) => V | undefined;
set: <V extends CacheValue = sources.Source>(key: string, value: V) => LRUCache<string, CacheValue>;
has: (key: string) => boolean;
calcHashValueChanged: (key: HashMapKey, hash: string) => ICreateCacheReturnType;
process: <T extends CacheValue>(options: CacheProcessOptions<T>) => Promise<T>;
}
/**
* 禁用插件功能的细粒度选项。
*
* @group 0.重要配置
* @since ^4.2.0
* @remarks
* 适用于需要仅关闭部分行为(例如主插件流程),但保留其他预处理能力(如 Tailwind v4 的 `@import "tailwindcss"` 重写)。
*/
interface DisabledOptions {
/**
* 禁用主插件流程,等同于 `disabled: true`。
*
* @default false
*/
plugin?: boolean;
/**
* 禁用对 `@import "tailwindcss"` 的预处理重写。
*
* @default false
*/
rewriteCssImports?: boolean;
}
interface UserDefinedOptions {
/**
* 是否禁用此插件。
*
* @group 0.重要配置
* @remarks
* 在多平台构建场景下常用:小程序构建保持默认,非小程序环境(H5、App)传入 `true` 即可跳过转换。
* @example
* ```ts
* // uni-app vue3 vite
* import process from 'node:process'
*
* const isH5 = process.env.UNI_PLATFORM === 'h5'
* const isApp = process.env.UNI_PLATFORM === 'app'
* const disabled = isH5 || isApp
*
* import { UnifiedViteWeappTailwindcssPlugin as uvtw } from 'weapp-tailwindcss/vite'
*
* uvtw({
* disabled,
* })
* ```
*/
disabled?: boolean | DisabledOptions;
/**
* 自定义 `wxml` 标签属性的转换规则。
*
* @group 0.重要配置
* @remarks
* 默认会转换所有标签上的 `class` 与 `hover-class`。此配置允许通过 `Map` 或对象为特定标签指定需要转换的属性字符串或正则表达式数组。
* - 使用 `'*'` 作为键可为所有标签追加通用规则。
* - 支持传入 `Map<string | RegExp, (string | RegExp)[]>` 以满足复杂匹配需求。
* - 常见场景包括通过组件 `prop` 传递类名,或对三方组件的自定义属性做匹配,更多讨论见 [issue#129](https://github.com/sonofmagic/weapp-tailwindcss/issues/129#issuecomment-1340914688) 与 [issue#134](https://github.com/sonofmagic/weapp-tailwindcss/issues/134#issuecomment-1351288238)。
* 如果自定义规则已经覆盖默认的 `class`/`hover-class`,可开启 [`disabledDefaultTemplateHandler`](/docs/api/interfaces/UserDefinedOptions#disableddefaulttemplatehandler) 以关闭内置模板处理器。
* @example
* ```js
* const customAttributes = {
* '*': [/[A-Za-z]?[A-Za-z-]*[Cc]lass/],
* 'van-image': ['custom-class'],
* 'ice-button': ['testClass'],
* }
* ```
*/
customAttributes?: ICustomAttributes;
/**
* 自定义 class 名称的替换字典。
*
* @group 0.重要配置
* @remarks
* 默认策略会将小程序不允许的字符映射为等长度的替代字符串,因此无法通过结果反推出原始类名。如需完全自定义,可传入 `Record<string, string>`,只需确保生成的类名不会与已有样式冲突。示例参考 [dic.ts](https://github.com/sonofmagic/weapp-core/blob/main/packages/escape/src/dic.ts)。
* @default MappingChars2String
*/
customReplaceDictionary?: Record<string, string>;
/**
* 忽略指定标签模板表达式中的标识符。
*
* @since ^4.0.0
* @group 0.重要配置
* @remarks
* 当模板字符串被这些标识符包裹时,将跳过转义处理。
* @default ['weappTwIgnore']
*/
ignoreTaggedTemplateExpressionIdentifiers?: (string | RegExp)[];
/**
* 忽略指定调用表达式中的标识符。
*
* @since ^4.0.0
* @group 0.重要配置
* @remarks
* 使用这些方法包裹的模板字符串或字符串字面量会跳过转义,常与 `@weapp-tailwindcss/merge` 配合(如 `['twMerge', 'twJoin', 'cva']`)。
*/
ignoreCallExpressionIdentifiers?: (string | RegExp)[];
/**
* @internal
*/
replaceRuntimePackages?: boolean | Record<string, string>;
/**
* 控制在视图节点上注入的 CSS 预设。
*
* @group 0.重要配置
* @see https://github.com/sonofmagic/weapp-tailwindcss/issues/7
* @remarks
* 默认会向所有 `view`/`text` 元素注入 Tailwind 风格的基础样式,可通过此配置禁用、调整或补充规则,受 `cssPreflightRange` 影响。
* @example
* ```js
* cssPreflight: {
* 'box-sizing': 'border-box',
* 'border-width': '0',
* 'border-style': 'solid',
* 'border-color': 'currentColor',
* }
*
* cssPreflight: false
*
* cssPreflight: {
* 'box-sizing': false,
* background: 'black',
* }
* ```
*/
cssPreflight?: CssPreflightOptions;
/**
* 控制 `cssPreflight` 注入的 DOM 选择器范围。
*
* @group 0.重要配置
* @see https://github.com/sonofmagic/weapp-tailwindcss/pull/62
* @remarks
* 仅 `view`、`text` 及其伪元素会受影响。设置为 `'all'` 可以覆盖所有元素,此时需自行处理与宿主默认样式的冲突。
*/
cssPreflightRange?: 'all';
/**
* 预计算 CSS 变量或 `calc` 表达式的结果。
*
* @group 0.重要配置
* @since ^4.3.0
* @remarks
* 解决部分机型对 `calc` 计算不一致的问题,可传入布尔值、选项对象或自定义匹配列表(支持正则)。在启用计算后,可通过 `includeCustomProperties` 指定需要保留的变量。
* @example
* ```css
* // 原始输出
* page,
* :root {
* --spacing: 8rpx;
* }
* .h-2 {
* height: calc(var(--spacing) * 2);
* }
* ```
*
* ```css
* // 启用 cssCalc 后
* .h-2 {
* height: 16rpx;
* height: calc(var(--spacing) * 2);
* }
* ```
*
* ```js
* cssCalc: ['--spacing']
* cssCalc: { includeCustomProperties: ['--spacing'] }
* ```
*/
cssCalc?: boolean | CssCalcOptions | (string | RegExp)[];
/**
* 是否额外注入 `tailwindcss css var scope`。
*
* @group 0.重要配置
* @since ^2.6.0
* @remarks
* 当构建链路(例如 `@tarojs/plugin-html`)移除了包含 `*` 的选择器时,可启用该选项重新写入变量作用域,以避免渐变等功能失效。
* @default false
*/
injectAdditionalCssVarScope?: boolean;
/**
* 是否在 webpack/vite 阶段自动把 CSS 中的 `@import 'tailwindcss'` 映射为 `weapp-tailwindcss`。
*
* @group 0.重要配置
* @remarks
* 开启后打包链路只会在处理样式时拦截 `tailwindcss` 的导入路径(JS/TS `import 'tailwindcss'` 不会被修改),让源码可以继续写 `@import 'tailwindcss';`,同时输出 weapp-tailwindcss 的样式。传入 `false` 可完全关闭该行为。
* @default true
*/
rewriteCssImports?: boolean;
/**
* 控制 CSS 选择器的替换规则。
*
* @group 0.重要配置
*/
cssSelectorReplacement?: {
/**
* 将全局选择器 `:root` 替换为指定值。
*
* @default `'page'` <br/>
* @remarks
* 设置为 `false` 时不再替换,可根据宿主环境(例如 RootPortal)传入数组值。
* @example
* root: ['page', 'wx-root-content']
*/
root?: string | string[] | false;
/**
* 将全局选择器 `*` 替换为指定值。
*
* @see https://github.com/sonofmagic/weapp-tailwindcss/issues/81 <br/>
* @default `['view','text']` <br/>
* @remarks
* 小程序环境不支持 `*`,因此默认转换为 `view`、`text`;设置为 `false` 会留下原始选择器。
*/
universal?: string | string[] | false;
};
/**
* rem 到 rpx 的转换配置。
*
* @since ^3.0.0
* @group 0.重要配置
* @remarks
* 传入 `true` 使用默认配置,或提供 [postcss-rem-to-responsive-pixel](https://www.npmjs.com/package/postcss-rem-to-responsive-pixel) 支持的完整选项。
* ```ts
* {
* rootValue: 32,
* propList: ['*'],
* transformUnit: 'rpx',
* }
* ```
*/
rem2rpx?: boolean | Rem2rpxOptions;
/**
* px 到 rpx 的转换配置。
*
* @group 0.重要配置
* @since ^4.3.0
* @remarks
* 传入 `true` 启用默认映射(`1px = 1rpx`),或通过对象自定义更多行为。
*/
px2rpx?: boolean | Px2rpxOptions;
/**
* `postcss-preset-env` 的配置项。
*
* @since ^4.0.0
* @group 0.重要配置
* @see https://preset-env.cssdb.org/
* @see https://github.com/csstools/postcss-plugins/tree/main/plugin-packs/postcss-preset-env#readme
*/
cssPresetEnv?: PresetEnvOptions;
/**
* 为不同版本的 Tailwind 配置行为。
*
* @since ^4.0.0
* @group 0.重要配置
*/
tailwindcss?: TailwindcssPatchOptions['tailwind'];
/**
* 指定 tailwindcss@4 的入口 CSS。
*
* @since ^4.2.6
* @group 0.重要配置
* @remarks
* 未配置时无法加载自定义插件,等价于设置 `tailwindcss.v4.cssEntries`。
*/
cssEntries?: string[];
/**
* 配置 uni-app x 场景的行为。
*
* @since ^4.2.0
* @group 0.重要配置
* @ignore
*/
uniAppX?: boolean;
}
interface UserDefinedOptions {
/**
* 匹配需要处理的 `wxml` 等模板文件。
*
* @group 1.文件匹配
*/
htmlMatcher?: (name: string) => boolean;
/**
* 匹配需要处理的 `wxss` 等样式文件。
*
* @group 1.文件匹配
*/
cssMatcher?: (name: string) => boolean;
/**
* 匹配需要处理的编译后 `js` 文件。
*
* @group 1.文件匹配
*/
jsMatcher?: (name: string) => boolean;
/**
* 匹配负责注入 Tailwind CSS 变量作用域的 CSS Bundle。
*
* @group 1.文件匹配
* @remarks
* 在处理 `::before`/`::after` 等不兼容选择器时,建议手动指定文件位置。
*/
mainCssChunkMatcher?: (name: string, appType?: AppType) => boolean;
/**
* 匹配各端的 `wxs`/`sjs`/`.filter.js` 文件。
*
* @group 1.文件匹配
* @experimental 实验性质,有可能会改变
* @remarks
* 配置前请确保在 `tailwind.config.js` 的 `content` 中包含对应格式。
* @default ()=>false
*/
wxsMatcher?: (name: string) => boolean;
/**
* 是否转义 `wxml` 中的内联 `wxs`。
*
* @group 1.文件匹配
* @experimental 实验性质,有可能会改变
* @remarks
* 使用前同样需要在 `tailwind.config.js` 中声明 `wxs` 格式。
* @example
* ```html
* <!-- index.wxml -->
* <wxs module="inline">
// 我是内联wxs
// 下方的类名会被转义
var className = "after:content-['我是className']"
module.exports = {
className: className
}
</wxs>
<wxs src="./index.wxs" module="outside"/>
<view><view class="{{inline.className}}"></view><view class="{{outside.className}}"></view></view>
* ```
* @default false
*/
inlineWxs?: boolean;
}
interface UserDefinedOptions {
/**
* 插件 `apply` 初始调用时触发。
*
* @group 2.生命周期
*/
onLoad?: () => void;
/**
* 开始处理前触发。
*
* @group 2.生命周期
*/
onStart?: () => void;
/**
* 匹配并修改文件内容前触发。
*
* @group 2.生命周期
*/
/**
* 匹配并修改文件后触发。
*
* @group 2.生命周期
*/
onUpdate?: (filename: string, oldVal: string, newVal: string) => void;
/**
* 结束处理时触发。
*
* @group 2.生命周期
*/
onEnd?: () => void;
}
interface UserDefinedOptions {
/**
* 控制 Tailwind 自定义长度单位补丁。
*
* @group 3.一般配置
* @see https://github.com/sonofmagic/weapp-tailwindcss/issues/110
* @remarks
* TailwindCSS 3.2.0 起对任意值执行长度单位校验,会将未声明的 `rpx` 识别为颜色。本选项默认开启以注入 `rpx` 支持。当 Node.js 在插件执行前已缓存 `tailwindcss` 模块时,首轮运行可能未生效,可通过在 `postinstall` 中执行 `weapp-tw patch` 提前打补丁。
* ```diff
* "scripts": {
* + "postinstall": "weapp-tw patch"
* }
* ```
*/
supportCustomLengthUnitsPatch?: ILengthUnitsPatchOptions | boolean;
/**
* 声明所使用的框架类型。
*
* @group 3.一般配置
* @remarks
* 用于辅助定位主要的 CSS bundle,以便默认的 `mainCssChunkMatcher` 做出更准确的匹配,未传入时将尝试自动猜测变量注入位置。
*/
appType?: AppType;
/**
* TailwindCSS 任意值的相关配置。
*
* @group 3.一般配置
*/
arbitraryValues?: IArbitraryValues;
/**
* 控制 JS 字面量是否需要保留。
*
* @group 3.一般配置
* @since ^2.6.1
* @remarks
* 当 Tailwind 与 JS 字面量冲突时,可通过回调返回 `true` 保留当前值,返回 `false` 或 `undefined` 则继续转义。默认保留所有带 `*` 的字符串字面量。
*/
jsPreserveClass?: (keyword: string) => boolean | undefined;
/**
* 禁用默认的 `wxml` 模板替换器。
*
* @group 3.一般配置
* @since ^2.6.2
* @remarks
* 启用后模板匹配完全交由 [`customAttributes`](/docs/api/interfaces/UserDefinedOptions#customattributes) 管理,需要自行覆盖默认的 `class` / `hover-class` 等匹配规则。
* @default false
*/
disabledDefaultTemplateHandler?: boolean;
/**
* 内部使用的运行时加载器路径。
*
* @ignore
* @internal
*/
runtimeLoaderPath?: string;
/**
* 内部使用的 CSS import 重写加载器路径。
*
* @ignore
* @internal
*/
runtimeCssImportRewriteLoaderPath?: string;
/**
* 指定用于获取 Tailwind 上下文的路径。
*
* @group 3.一般配置
* @since ^2.9.3
* @remarks
* 在 linked 或 monorepo 场景下可手动指向目标项目的 `package.json` 所在目录。
*/
tailwindcssBasedir?: string;
/**
* 控制缓存策略。
*
* @group 3.一般配置
* @since ^3.0.11
*/
cache?: boolean | ICreateCacheReturnType;
/**
* `@babel/parser` 的配置选项。
*
* @since ^3.2.0
* @group 3.一般配置
*/
babelParserOptions?: ParserOptions & {
cache?: boolean;
cacheKey?: string;
};
/**
* 自定义 Tailwind 子组合器的替换值。
*
* @group 3.一般配置
* @remarks
* 为兼容小程序缺乏 `:not([hidden])~` 支持的限制,默认会将 `.space-x-4` 等选择器替换为 `view + view`。可传入字符串或字符串数组以扩展适用标签。
* ```css
* // 数组示例
* .space-y-4>view + view,text + text{}
*
* // 字符串示例
* .space-y-4>view,text,button,input ~ view,text,button,input{}
* ```
* @default 'view + view'
*/
cssChildCombinatorReplaceValue?: string | string[];
/**
* `postcss` 的配置选项。
*
* @since ^3.2.0
* @group 3.一般配置
*/
postcssOptions?: LoadedPostcssOptions;
/**
* 是否移除 CSS 中的 `:hover` 选择器。
*
* @since ^3.2.1
* @group 3.一般配置
* @see https://github.com/sonofmagic/weapp-tailwindcss/issues/293
* @remarks
* 小程序不支持 `:hover`,需要使用组件的 `hover-class`,因此默认删除相关节点。
* @default `true`
*/
cssRemoveHoverPseudoClass?: boolean;
/**
* 是否移除 `@property` 节点。
*
* @since ^4.1.2
* @group 3.一般配置
* @remarks
* 微信小程序可识别 `@property`,但支付宝暂不支持,默认移除以避免构建失败。
* @default `true`
*/
cssRemoveProperty?: boolean;
/**
* 自定义 patcher 参数。
*
* @group 3.一般配置
*/
tailwindcssPatcherOptions?: TailwindcssPatchOptions;
/**
* 控制命令行日志输出级别。
*
* @group 3.一般配置
* @remarks
* 默认 `info`,可设置为 `silent` 屏蔽全部输出。
*/
logLevel?: 'info' | 'warn' | 'error' | 'silent';
}
type ItemOrItemArray<T> = T | T[];
type AsyncableMethod<T> = T extends (...args: infer A) => infer R ? (...args: A) => Promise<Awaited<R>> | Awaited<R> : never;
type AppType = 'uni-app' | 'uni-app-vite' | 'taro' | 'remax' | 'rax' | 'native' | 'kbone' | 'mpx' | 'weapp-vite';
interface LinkedJsModuleResult {
code: string;
}
interface JsHandlerResult {
code: string;
map?: SourceMap;
error?: ParseError;
/**
* 因跨文件分析而被转换的额外模块,使用绝对文件路径作为键。
*/
linked?: Record<string, LinkedJsModuleResult>;
}
type ICustomAttributes = Record<string, ItemOrItemArray<string | RegExp>> | Map<string | RegExp, ItemOrItemArray<string | RegExp>>;
type ICustomAttributesEntities = [string | RegExp, ItemOrItemArray<string | RegExp>][];
interface TailwindcssPatcherLike {
packageInfo: TailwindcssPatcher['packageInfo'];
majorVersion?: TailwindcssPatcher['majorVersion'];
patch: TailwindcssPatcher['patch'];
getClassSet: AsyncableMethod<TailwindcssPatcher['getClassSet']>;
getClassSetSync?: TailwindcssPatcher['getClassSetSync'];
extract: TailwindcssPatcher['extract'];
collectContentTokens?: TailwindcssPatcher['collectContentTokens'];
options?: TailwindcssPatcher['options'];
}
interface RefreshTailwindcssPatcherOptions {
clearCache?: boolean;
}
interface IJsHandlerOptions {
escapeMap?: Record<string, string>;
classNameSet?: Set<string>;
arbitraryValues?: IArbitraryValues;
jsPreserveClass?: (keyword: string) => boolean | undefined;
needEscaped?: boolean;
generateMap?: boolean;
alwaysEscape?: boolean;
unescapeUnicode?: boolean;
babelParserOptions?: ParserOptions;
ignoreTaggedTemplateExpressionIdentifiers?: (string | RegExp)[];
ignoreCallExpressionIdentifiers?: (string | RegExp)[];
uniAppX?: boolean;
moduleSpecifierReplacements?: Record<string, string>;
/**
* 为 `true` 时将输入视作独立表达式,而非完整的程序。
* 适用于 `:class="{ 'foo bar': cond }"` 等模板绑定场景。
*/
wrapExpression?: boolean;
/**
* 当前正在转换的模块绝对路径。
* 启用跨文件分析时必须提供。
*/
filename?: string;
/**
* 配置跨文件模块图分析行为。
*/
moduleGraph?: JsModuleGraphOptions;
}
interface IArbitraryValues {
/**
* 是否允许在类名里,使用双引号。
* 建议不要开启,因为有些框架,比如 `vue3` 它针对有些静态模板会直接编译成 `html` 字符串,此时开启这个配置很有可能导致转义出错
*
* @example
* ```html
* <!-- 开启前默认只允许单引号 -->
* <view class="after:content-['对酒当歌,人生几何']"></view>
* <!-- 开启后 -->
* <view class="after:content-[\"对酒当歌,人生几何\"]"></view>
* ```
*
* @default `false`
*/
allowDoubleQuotes?: boolean;
}
interface JsHandler {
(rawSource: string, set?: Set<string>, options?: CreateJsHandlerOptions): JsHandlerResult;
}
interface ICommonReplaceOptions {
keepEOL?: boolean;
escapeMap?: Record<string, string>;
}
interface ITemplateHandlerOptions extends ICommonReplaceOptions {
customAttributesEntities?: ICustomAttributesEntities;
escapeMap?: Record<string, string>;
inlineWxs?: boolean;
jsHandler?: JsHandler;
runtimeSet?: Set<string>;
disabledDefaultTemplateHandler?: boolean;
quote?: string | null;
ignoreHead?: boolean;
wrapExpression?: boolean;
}
type InternalUserDefinedOptions = Required<Omit<UserDefinedOptions, 'supportCustomLengthUnitsPatch' | 'customReplaceDictionary' | 'cache'> & {
supportCustomLengthUnitsPatch: ILengthUnitsPatchOptions | boolean;
templateHandler: (rawSource: string, options?: ITemplateHandlerOptions) => Promise<string>;
styleHandler: (rawSource: string, options?: IStyleHandlerOptions) => Promise<Result<Root | Document>>;
jsHandler: JsHandler;
escapeMap: Record<string, string>;
customReplaceDictionary: Record<string, string>;
cache: ICreateCacheReturnType;
twPatcher: TailwindcssPatcherLike;
refreshTailwindcssPatcher: (options?: RefreshTailwindcssPatcherOptions) => Promise<TailwindcssPatcherLike>;
}>;
type InternalPostcssOptions = Pick<UserDefinedOptions, 'cssMatcher' | 'mainCssChunkMatcher' | 'cssPreflight' | 'cssPreflightRange' | 'disabled'>;
interface IBaseWebpackPlugin {
options: InternalUserDefinedOptions;
appType?: AppType;
apply: (compiler: any) => void;
}
/**
* @description InternalPatchResult
*/
interface InternalPatchResult {
dataTypes?: string;
processTailwindFeatures?: string;
plugin?: string;
}
type CreateJsHandlerOptions = Omit<IJsHandlerOptions, 'classNameSet'>;
interface JsModuleGraphOptions {
/**
* 将导入的标识符解析为绝对文件路径。
*/
resolve: (specifier: string, importer: string) => string | undefined;
/**
* 同步加载模块源码。
*/
load: (id: string) => string | undefined;
/**
* 可选过滤器,用于跳过特定模块。
*/
filter?: (id: string, specifier: string, importer: string) => boolean;
/**
* 最大遍历深度,默认无限制(`Infinity`)。
*/
maxDepth?: number;
}
export type { AppType, CreateJsHandlerOptions, DisabledOptions, IArbitraryValues, IBaseWebpackPlugin, ICommonReplaceOptions, ICustomAttributes, ICustomAttributesEntities, IJsHandlerOptions, ITemplateHandlerOptions, InternalPatchResult, InternalPostcssOptions, InternalUserDefinedOptions, ItemOrItemArray, JsHandler, JsHandlerResult, JsModuleGraphOptions, LinkedJsModuleResult, RefreshTailwindcssPatcherOptions, TailwindcssPatcherLike, UserDefinedOptions };