npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mega-apps/postcss-theme-helper

v1.0.0-rc.9

Published

Postcss theme helper

Readme

@mega-apps/postcss-theme-helper

PostCSS 主题助手

是基于PostCSS框架提供的PostCSS插件,主要解决主题切换的问题。

特性

  • [x] 支持主题颜色替换
  • [ ] (路线)支持主题字体替换
  • [ ] (路线)支持主题布局替换
  • [ ] (路线)支持主题特效(动画)替换
  • [x] 与前端JS框架无关(支持React, Vue2/3, Angular, SolidJS ...)
  • [x] 支持对Vue ElementUI Ver2.x 组件的主题颜色替换(可选用:内置预设)
  • [x] 支持对Vue ElementUI-Plus Ver1.x 组件的主题颜色替换(可选用:内置预设)
  • [x] 支持对Vue Ant Design Ver1.x 组件的主题颜色替换(可选用:内置预设)
  • [x] 支持多主题组颜色替换及单独颜色替换
  • [x] 支持CSS选择器过滤多种方式:如:数组包含,正则匹配,glob模式匹配,函数调用
  • [x] 支持初始化默认匹配颜色,用于替换默认颜色
  • [x] 支持针对颜色值的严格模式和非严格模式指定,例如:匹配颜色,rgb(255,255,255),rgba(255,255,255,0.5)在严模式下,只会处理完全匹配的一种,使用非严格模式,都会处理。
  • [x] 支持指定挂载的DOM节点的选择器,
  • [x] 支持指定颜色变量的包裹器,如::root, div, .class, #id 等;
  • [x] 支持排除指定的CSS选择器
  • [x] 支持排除指定的颜色CSS属性,如:color, background-color, border-color
  • [x] 支持调试模式,调试模式下,会在控制台输出颜色变更的信息
  • [x] 提供Webpack插件,自动注入主题替换代码
  • [x] 提供Vite插件,自动注入主题替换代码
  • [x] 性能较 @mega-apps/webpack-theme-color-replacerwebpack-theme-color-replacer,大幅度提升。提升较基线至少 100X
  • [x] 代码基于TDDE2E模式开发,版本迭代,质量有保证

安装

yarn add @mega-apps/postcss-theme-helper --dev

# 或使用 pnpm
pnpm add -D @mega-apps/postcss-theme-helper

使用说明

Vite 项目

配置示例

  • vite.config.js 文件

    // vite.config.js
      
    import { defineConfig } from 'vite';
      
    // 引入主题助手Unplugin
    import themePluginBuilder from '@mega-apps/postcss-theme-helper/unplugin';
      
    // 定义配置
    export default defineConfig({
      // 加载主题的vite插件
      plugins: [themePluginBuilder.vite({debug: false})],
    });
  • postcss.config.js 文件

const themePlugin = require("@mega-apps/postcss-theme-helper");
const themeOptions = {
  debug: false,
  useShareColorVariableReplaceBuilder: true,
  colorVariableReplacer: [
    // 类似于CSS的解析,从上而下,最小优先级最高
    {
      matchColors: ["#409EFF","rgb(239, 68, 68)"],
      matchSelectors: [{ type: "RegExpMatch", data: [/.custom/i] }],
      initVarColors: ["red","blue"],
      strict: true,
      cssVarPrefix: "--eColor",
      wrapper: ":root",
      debug: false,
    },
    // {
    //   matchColors: ["black" ],
    //   matchSelectors: [{ type: "RegExpMatch", data: [/.my-color/i] }],
    //   initVarColors: ["yellow"],
    //   strict: true,
    //   cssVarPrefix: "--hiColor",
    //   wrapper: "div",
    // },
    // {
    //   matchColors: ["#0ea8d0"],
    //   matchSelectors: [],
    //   initVarColors: ["green"],
    //   strict: true,
    //   cssVarPrefix: "--antColor",
    // }
  ],
}

module.exports = {
  plugins: [require('tailwindcss'), require('autoprefixer'), themePlugin.default(themeOptions)],
};

Nuxt.js 项目

配置实例1

// nuxt.config.js

build: {
  plugins: [
    // 引入自动注入代码
    require('@mega-apps/postcss-theme-helper/unplugin').default.webpack({debug: false})
  ],
  postcss: {
        postcss: {
          plugins: {
            "@mega-apps/postcss-theme-helper": {
              debug: false,
              colorVariableReplacer: [
                // 类似于CSS的解析,从上而下,最小优先级最高
                {
                  matchColors: ["#409EFF","rgb(239, 68, 68)"],
                  matchSelectors: [],
                  initVarColors: ["red","blue"],
                  strict: true,
                  cssVarPrefix: "--eColor",
                  wrapper: ":root",
                },
                {
                  matchColors: ["black" ],
                  matchSelectors: [{ type: "RegExpMatch", data: [/.my-color/i] }],
                  initVarColors: ["yellow"],
                  strict: true,
                  cssVarPrefix: "--hiColor",
                  wrapper: "div",
                },
                {
                  matchColors: ["#0ea8d0"],
                  matchSelectors: [],
                  initVarColors: ["green"],
                  strict: true,
                  cssVarPrefix: "--antColor",
                }
              ],
              // 预设值
              colorVariableReplacerPresets: ['VueElementUI_V2', 'VueAntdUI_V1']
            },
          },
          // 调整postcss插件的次序,参照文档:https://nuxtjs.org/docs/configuration-glossary/configuration-build#postcss
          // 插件必须在 tailwindcss 之后,这样才能对tailwindcss的样式进行处理替换
          order: ["tailwindcss", "@mega-apps/postcss-theme-helper"],
        },
  }
}

浏览器客户端

JS 代码示例

/**
 * 获得全局主题样式助手
 */
export function getThemeHelper() {
  // @ts-ignore
  return window["@mega-apps/theme-helper"];
}

/**
 * 获得主题颜色的配置
 * @param key 唯一ID,一般特指挂载在Style中的id
 * @returns {Object}
 */
export function getColorThemeConfig(key = "config-for-theme") {
  const themeHelper = getThemeHelper();
  if (themeHelper) {
    const configMap = themeHelper.getColorThemeConfigMap();
    if (configMap) {
      return configMap[key];
    }
  }
  return {};
}

/**
 * 获得主题颜色的详细的配置项,组Key列表
 * @param key
 * @returns
 */
export function getColorConfigGroupKeys(key = "config-for-theme") {
  const config = getColorThemeConfig(key);
  return Object.keys(config);
}

/**
 * 改变指定GroupKey的主题颜色
 * @note:groupKey = `wrapper + "#*#" + cssVarPrefix` 的格式
 */
export function changeColorsWithGroupKey(
  groupKey,
  configKey = "config-for-theme"
) {
  const themeHelper = getThemeHelper();
  console.log("themeHelper = ", themeHelper);
  const config = getColorThemeConfig(configKey);
  const { themeChange } = themeHelper;
  // 获得参数设置的匹配颜色
  const matchColors = config[groupKey]?.options?.matchColors || [];

  const rColor = () => Math.floor(Math.random() * 256);

  // 生成随机替换颜色
  const withColors = [];
  matchColors.forEach(() => {
    const newColor = `rgb(${rColor()}, ${rColor()}, ${rColor()})`;
    withColors.push(newColor);
  });

  // 根据匹配的颜色,随机生成替换的颜色
  themeChange.changeColors({
    matchColors,
    withColors,
    // filterWrappers: [":root"], // 过滤包裹器的样式
    // filterCssVarPrefixes: [],  // 过滤指定的cssVarPrefix
    debug: true,
  });
}

window.changeColorsWithGroupKey = changeColorsWithGroupKey;

// 调用示例
changeColorsWithGroupKey(':root#*#--eColor');

Typescript 代码示例

获得全局主题样式助手
/**
 * 获得全局主题样式助手
 */
export function getThemeHelper(): any {
  // @ts-ignore
  return window["@mega-apps/theme-helper"];
}
获得主题颜色的配置
/**
 * 获得主题颜色的配置
 * @param key 唯一ID,一般特指挂载在Style中的id
 * @returns {Object}
 */
export function getColorThemeConfig(key = "config-for-theme"): any {
  const themeHelper = getThemeHelper();
  if (themeHelper) {
    const configMap = themeHelper.getColorThemeConfigMap();
    if (configMap) {
      return configMap[key];
    }
  }
  return {};
}
获得主题颜色的详细的配置项,组Key列表
/**
 * 获得主题颜色的详细的配置项,组Key列表
 * @param key
 * @returns
 */
export function getColorConfigGroupKeys(key = "config-for-theme"): string[] {
  const config = getColorThemeConfig(key);
  return Object.keys(config);
}
改变指定GroupKey的主题颜色
/**
 * 改变指定GroupKey的主题颜色
 * @note:groupKey = `wrapper + "#*#" + cssVarPrefix` 的格式
 */
export function changeColorsWithGroupKey(
  groupKey: string,
  configKey = "config-for-theme"
) {
  const themeHelper = getThemeHelper();
  const config = getColorThemeConfig(configKey);
  const { themeChange } = themeHelper;
  // 获得参数设置的匹配颜色
  const matchColors: string[] = config[groupKey]?.options?.matchColors || [];

  const rColor = () => Math.floor(Math.random() * 256);

  // 生成随机替换颜色
  const withColors: string[] = [];
  matchColors.forEach(() => {
    const newColor = `rgb(${rColor()}, ${rColor()}, ${rColor()})`;
    withColors.push(newColor);
  });

  // 根据匹配的颜色,随机生成替换的颜色
  themeChange.changeColors({
    matchColors,
    withColors,
    // filterWrappers: [":root"], // 过滤包裹器的样式
    // filterCssVarPrefixes: [],  // 过滤指定的cssVarPrefix
    debug: true,
  });
}

参数说明

Webpack 注入插件参数

/**
 * 主题注入代码选项
 */
export interface IInjectThemeCodeOptions {
  /**
   * 注入样式元素的唯一ID值
   *
   * @example
   *
   * ``` html
   * <html>
   * <head>
   *   <style id="theme-style-element" type="text/css">
   *     :root {--myColor-cef4444-b: 18;--myColor-cef4444-g: 10;--myColor-cef4444-r: 239;--myColor-cef4444: blue;--myColor-c000000: red;}div {--hiColor-c000000: yellow;}
   *   </style>
   * </head>
   * <body></body>
   * </html>
   * ```
   * 关联主题样式的元素ID 为 "theme-style-element";
   */
  injectStyleElementId: string;

  /**
   * 挂载在window对象上的变量名称
   *
   * @example
   *
   * ``` typescript
   * const windowGlobVarName = "___HELP";
   *
   * // 最终的结果是 window.___HELP 将被占用赋值
   * ```
   */
  windowGlobVarName?: string;
}

主题颜色替换参数

参数接口原型


export enum EMatchFilterItemType {
  ArrayIncludes = "ArrayIncludes", // 数组包含
  RegExpMatch = "RegExpMatch", // 正则匹配
  GlobMatch = "GlobMatch", // glob匹配
  Function = "Function", // 函数调用
}
export type TMatchFilterItemType =
  | EMatchFilterItemType
  | keyof typeof EMatchFilterItemType
  | [EMatchFilterItemType.ArrayIncludes, EMatchFilterItemType.RegExpMatch];

export type TMatchBaseSupportFilter =
  | string
  | readonly string[]
  | RegExp
  | readonly RegExp[];

export interface IMatchFilterBaseItem {
  type: TMatchFilterItemType;
  data: TMatchBaseSupportFilter;
}

export type TMatchSupportFilterBuilder = (
  ...args: any[]
) => IMatchFilterBaseItem[];
export type TMatchSupportFilter =
  | TMatchBaseSupportFilter
  | TMatchSupportFilterBuilder;

export interface IMatchFilterItem extends IMatchFilterBaseItem {
  data: TMatchBaseSupportFilter;
}



export enum EColorVariablesReplacerPreset {
  VueElementUI_V2, // vue element-ui v2.x 系列
  VueElementUI_Plus_V1, // vue element-ui plus v1.x 系列
  VueAntdUI_V1, // vue antd (ant-design-vue) v1.x 系列
  VueAntdUI_V3, // vue antd (ant-design-vue) v3.x 系列
}

export type TColorVariablesReplacerPresetName = keyof typeof EColorVariablesReplacerPreset;


/**################### 主题替换 ####################**/
/**
 * 主题配置选项
 */
export interface IThemeHelperOptions {
  /**
   * 是否输出调试日志信息
   * @default false, 不输出调试日志信息
   * */
  debug?: boolean;

  /**
   * 是否开启性能跟踪
   * @default false, 不开启性能跟踪
   */
  tracePerformance?: boolean;

  /**
  * 是否使用共享的颜色变量替换构建器(单一实例)
  */
  useShareColorVariableReplaceBuilder?: boolean;

  /**
   * 颜色替换, 支持单一配置,多个配置, 也支持关闭
   */
  colorVariableReplacer?:
    | IColorVariablesReplacerOptions
    | IColorVariablesReplacerOptions[]
    | boolean;

  colorVariableReplacerPresets?: EColorVariablesReplacerPreset[] | TColorVariablesReplacerPresetName[];
}

示例代码


// 示例代码
plugins: {
  "@mega-apps/postcss-theme-helper": {
      debug: false,//
      // tracePerformance: false,
      // useShareColorVariableReplaceBuilder: false,
      colorVariableReplacer: [
        // 类似于CSS的解析,从上而下,优先级高低:按序降低
        {
          matchColors: ["black", "rgb(239, 68, 68)"],
          initVarColors: ["red", "blue"],
          strict: true,
          cssVarPrefix: "--myColor",
          wrapper: ":root",
        },
        {
          matchColors: ["black"],
          initVarColors: ["yellow"],
          strict: true,
          cssVarPrefix: "--hiColor",
          wrapper: "div",
        }
     ],
     colorVariableReplacerPresets: [], //   VueElementUI_V2, VueElementUI_Plus_V1, VueAntdUI_V1,
  }
}

参数:matchColors

特指要匹配的颜色值数组; 这些颜色值将支持主题替换

  • 支持颜色值的模式:
    • 主要:
      • 16进制(3位,4位,6位,8位):#fff, #ffff, #ffffff, #ffffffff
      • RGB/RGBA 字符串:rgb(192, 192, 192), rgba(192, 192, 192, 0.5)
      • HSL/HSLA 字符串: hsl(0, 50%, 50%), hsl(0, 50%, 50%, 0.25)
      • 颜色名称: red, black, blue, green
    • 其他:
      • HWB 字符串
      • CMYK 字符串
      • LCH 字符串
      • LAB 字符串
      • XYZ 字符串
  • 自动去重

参数:matchProps

特指需要匹配的包含颜色的属性名称

  • 默认值为: [DEFAULT_COLOR_PROPS], 表示所有CSS属性都会被遍历
  • 可以指定自己的默认的属性包含, 如:background, color
  // 注意,匹配模式,要求指定过滤方式,否则无法匹配:如:ArrayIncludes,
  matchProps: [{ type: "ArrayIncludes", data: DEFAULT_COLOR_PROPS }] // 只查找css样式中,包含background的规则

参数:excludeProps

特指需要排除的属性名称

  • 默认值: [], 表示不排除任何项
  • 支持的值形式:字符串数组、正则表达式、正则表达式数组、函数
  excludeProps: [{ type: "RegExpMatch", data: [/^border/i] }] // 以border开头的全部排除在外

参数:matchSelectors

特指需要匹配的选择器

  • 默认值为: []
  • 支持的值形式:字符串数组、正则表达式、正则表达式数组、函数

// 字符串数组形式,使用glob形式,参见:https://www.npmjs.com/package/micromatch
['ele-*']

// 正则表达式形式
/ele/gi

// 正则表达式数组
[/^ele/gi, /^ant/gi]

// 函数形式
(...args) => { return []}

matchSelectors: [{ type: "RegExpMatch", data: [/.my-color/i] }]

参数:excludeSelectors

特指需要排除的CSS选择器

  • 默认:[], 表示不排除任何项
  • 支持的值形式:字符串数组、正则表达式、正则表达式数组、函数
  • matchSelectors 的匹配规则雷同
  excludeSelectors: [{ type: "RegExpMatch", data: [/^ele/gi] }] // 以ele开头的全部排除在外

参数:initVarColors

特指:默认初始化颜色, 例如:匹配到 black,可以让生成的颜色变成 red 默认替换颜色与matchColors成对出现

matchColors: ['black', 'rgb(22,22,22)', 'rgb(44,44,23)']
initVarColors: ['red', 'green']

// 转换结果: black -> red; rgb(22,22,22) -> green; rgb(44,44,23) -> green

参数:strict

特指是否严格模式,如果为true,则忽略alpha的颜色相近处理

  • 默认是true
// 设置strict: false
matchColors: ['black']
strict: false

// 结果
// rgba(0,0,0, 0.5) 也会被匹配上
// 设置strict: true
matchColors: ['black']
strict: true

// 结果
// rgba(0,0,0, 0.5) 不会被匹配上

参数:cssVarPrefix

生成的css变量的前缀

/* cssVarPrefix: --myVar */
:root {
  --myVar-name: 'black'
}

参数:useMatchColorValueForCssVar

cssVar 使用matchColors中的颜色值

  • 默认:true
/* useMatchColorValueForCssVar: true*/
:root {
  --myVar-black: 'black'
}

/* useMatchColorValueForCssVar: false */
:root {
  --myVar-black: '#000'
}

参数:wrapper

定义的css变量值,外部包装器,例如: :root

/* wrapper: ':root' */
:root {
  --myVar-black: 'black'
}

/* wrapper: 'body > div' */
body > div {
  --myVar-black: 'black'
}

参数:debug

是否单独输出调试日志

  • 默认值:false

示例

启用 Ant Design Vue 主题替换

当前内置预设,支持的 Ant Design Vue版本是:

  • "VueAntdUI_V1": 对应 "ant-design-vue": "^1.x"
  • "VueAntdUI_V3": 对应 "ant-design-vue": "^3.x"
// postcss plugins
plugins: {
  "@mega-apps/postcss-theme-helper": {
    colorVariableReplacer: [
      // 类似于CSS的解析,从上而下,优先级高低:按序降低
      {
        matchColors: ["black", "rgb(239, 68, 68)"],
        initVarColors: ["red", "blue"],
        strict: true,
        cssVarPrefix: "--myColor",
        wrapper: ":root",
      }
    ],
    colorVariableReplacerPresets: ['VueAntdUI_V1'], // 预设为数组,可以将 'vue-antd-ui.v1' 添加进来
  }
}

启用 Element UI 主题替换

当前内置预设,支持的 Element UI版本是:

  • "VueElementUI_V2": 对应 "element-ui": "^2.x"
  • "VueElementUI_Plus_V1": 对应 "element-plus": "^1.3.0"
// postcss plugins
plugins: {
  "@mega-apps/postcss-theme-helper": {
    colorVariableReplacer: [
      // 类似于CSS的解析,从上而下,优先级高低:按序降低
      {
        matchColors: ["black", "rgb(239, 68, 68)"],
        initVarColors: ["red", "blue"],
        strict: true,
        cssVarPrefix: "--myColor",
        wrapper: ":root",
        preset: ['vue-element-ui.v2'], // 预设为数组,可以将 'vue-element-ui.v2' 添加进来
      }
    ],
    colorVariableReplacerPresets: ['VueElementUI_V2'], // 预设为数组,可以将 'element-ui.v2' 添加进来
  }
}

启用多个UI库主题替换

// postcss plugins
plugins: {
  "@mega-apps/postcss-theme-helper": {
    colorVariableReplacer: [
      // 类似于CSS的解析,从上而下,优先级高低:按序降低
      {
        matchColors: ["black", "rgb(239, 68, 68)"],
        initVarColors: ["red", "blue"],
        strict: true,
        cssVarPrefix: "--myColor",
        wrapper: ":root"
      }
    ],
    colorVariableReplacerPresets: ['VueElementUI_V2', 'VueAntdUI_V1']
  }
}

启用多组主题替换

postcss: {
  plugins: {
    "@mega-apps/postcss-theme-helper": {
      useShareColorVariableReplaceBuilder: true, // 开启共享CSS变量
      colorVariableReplacer: [
        // 类似于CSS的解析,从上而下,优先级高低:按序降低
        {
          matchColors: ["#409EFF","rgb(239, 68, 68)"],
          matchSelectors: [],
          initVarColors: ["red","blue"],
          strict: true,
          cssVarPrefix: "--myColor",
          // wrapper: ":root",
        },
        {
          matchColors: ["black" ],
          matchSelectors: [{ type: "RegExpMatch", data: [/.my-color/i] }],
          initVarColors: ["yellow"],
          strict: true,
          cssVarPrefix: "--hiColor",
          // wrapper: "div"
        },
        {
          matchColors: ["#0ea8d0"],
          matchSelectors: [],
          initVarColors: ["green"],
          strict: true,
          cssVarPrefix: "--antColor",
          // wrapper: "div"
        }
      ],
      colorVariableReplacerPresets: ['VueElementUI_V2', 'VueAntdUI_V1']
    },
  },
  // 调整postcss插件的次序,参照文档:https://nuxtjs.org/docs/configuration-glossary/configuration-build#postcss
  // 插件必须在 tailwindcss 之后,这样才能对tailwindcss的样式进行处理替换
  order: ["tailwindcss","@mega-apps/postcss-theme-helper"],
},

Demo

变更日志

CHANGELOG