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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@masonjs/theme

v0.0.3

Published

css theme preprocessor plugin for vite

Downloads

36

Readme

@zougt/vite-plugin-theme-preprocessor

一个vite v2.0+插件,让你轻松实现基于lesssass的 web 应用在线动态主题切换。

动态主题模式预设主题模式

特点:

  • 使用成本很低
  • 不限 ui 框架,Element-ui、iview、Ant-design 等等等(只要基于 less/sass)
  • 不依赖 css3 vars
  • 浏览器兼容性良好(IE9+ ?,待验证 ,但 vite 构建的产物最低 Polyfill 到 IE11,需更低的,你可以用 webpack 版本的插件@masonjs/theme-utils,所以兼容性问题取决用的框架)

demo repositories

动态主题模式

v1.4.0 + 支持

可用颜色板选择任意的主题色,这里以less为例,同样适用于scss。

one inline demo

one demo repository

效果图

安装与使用

# use pnpm (or npm)
pnpm install color @zougt/vite-plugin-theme-preprocessor @masonjs/theme-utils -D
# use yarn
yarn add  color @zougt/vite-plugin-theme-preprocessor @masonjs/theme-utils -D

vite.config.js

注意:以下的配置只适用于 动态主题模式 , 预设主题模式 请往文档下面对应的看。

import { defineConfig } from "vite";
import {
  themePreprocessorPlugin,
  themePreprocessorHmrPlugin,
} from "@zougt/vite-plugin-theme-preprocessor";
import path from "path";
export default defineConfig({
  plugins: [
    // 创建动态主题切换
    themePreprocessorPlugin({
      less: {
        // 启用任意主题色模式
        arbitraryMode: true,
        // 默认的主题色,用于对其他颜色值形成对比值,通常与 src/theme/theme-vars.less 中的一个主题色相同,也可以不相同,就看是不是你想要的效果
        defaultPrimaryColor: "#512da7",
        // 只需提供一组变量文件,变量文件内容不应该夹带样式代码,设定上只需存在变量
        multipleScopeVars: [
          {
            // 必需
            scopeName: "theme-default",
            // path 和 varsContent 必选一个
            path: path.resolve("src/theme/theme-vars.less"),
            // varsContent参数等效于 path文件的内容 ,可以让 defaultPrimaryColor 与 "@primary-color"值只写一遍, varsContent 与 path 选一个使用
            // varsContent:`@primary-color:${defaultPrimaryColor};`
          },
        ],
        // css中不是由主题色变量生成的颜色,也让它抽取到主题css内,可以提高权重
        includeStyleWithColors: [
            {
                    // color也可以是array,如 ["#ffffff","#000"]
                    color: '#ffffff',
                    // 排除属性,如 不提取背景色的#ffffff
                    // excludeCssProps:["background","background-color"]
                    // 排除选择器,如 不提取以下选择器的 #ffffff
                    // excludeSelectors: [
                    //   ".ant-btn-link:hover, .ant-btn-link:focus, .ant-btn-link:active",
                    // ],
                },
        ],
      },
      // scss:{

      // },
    }),
    // 主题热更新,不得已分开插件,因为需要vite插件顺序enforce
    themePreprocessorHmrPlugin(),
  ],
});

src/theme/theme-vars.less

/*说明:此文件不应该被其他@import,此文件的变量并不是来设置项目的主题(当然,你可以作为加载时的默认主题),主要作用是,这里的变量值只要与项目的原变量值有差别,编译后就会抽取跟随主题色梯度变化的css*/

/*注意(重要):此文件的内容一旦固定下来就不需要改,在线动态切换主题,调用setCustomTheme方法即可*/

/*注意(强调):变量值改动会影响 gradientReplacer 和 targetValueReplacer 的可用属性的变化,所以内容一旦固定下来就不需要改(强调)*/

/*主题色,通常与 themePreprocessorPlugin 的 defaultPrimaryColor 相同, 使用setCustomTheme({primaryColor})切换*/
@primary-color: #512da7;

/*与此颜色对应的样式,默认情况也会跟主色变化的,要切换它对应的梯度颜色,使用setCustomTheme({gradientReplacer:{"#F7D06B"}})切换 */
@alert-success-bg-color: #F7D06B;

/*圆角值,尽量与原值差别大一点,方便分析 targetValueReplacer 的可用属性,非颜色值的切换,可以使用 setCustomTheme({targetValueReplacer:{"6px"}}) 精准替换*/
@border-radius-base: 6px;

在线切换主题

动态主题切换必须使用的 "@setCustomTheme" 模块,会自动处理项目中包括组件库涉及的梯度颜色替换

import Color from "color";
// "@setCustomTheme" 是 themePreprocessorPlugin 提供的模块,setCustomTheme的参数必须提供Color模块,至于为什么不把 Color 直接依赖进去是有原因的
import setCustomTheme from "@setCustomTheme";
// 设置任意主题色既可
setCustomTheme({
  Color,
  primaryColor: "#FF005A",
  //gradientReplacer:{},
  //targetValueReplacer:{}
});

setCustomTheme 的可选参数 gradientReplacer 与 targetValueReplacer 的可用属性会跟随 .less 内容变化的,所以整个项目动态主题的模型应该最开始固化下来

# npm run dev 之后
# 可以在终端使用 z-theme 命令查看  gradientReplacer 与 targetValueReplacer 的可用属性
npx z-theme inspect

动态主题模式的原理

一言难尽

预设主题模式

预设多种主题,其实也可以用动态主题模式来做,如需类似效果图中有暗黑主题的,可能使用此模式更加方便

one inline demo

one demo repository

效果图

安装与使用

# use npm
npm install @zougt/vite-plugin-theme-preprocessor -D
# use yarn
yarn add @zougt/vite-plugin-theme-preprocessor -D

vite.config.js

注意:以下的配置只适用于 预设主题模式。文档的参数值都是默认值。

import themePreprocessorPlugin from "@zougt/vite-plugin-theme-preprocessor";
export default {
  plugins: [
    themePreprocessorPlugin({
      scss: {
        // 是否启用任意主题色模式,这里不启用
        arbitraryMode: false,
        // 提供多组变量文件
        multipleScopeVars: [
          {
            scopeName: "theme-default",
            // 变量文件内容不应该夹带样式代码,设定上只需存在变量
            path: path.resolve("src/theme/default-vars.scss"),
          },
          {
            scopeName: "theme-mauve",
            path: path.resolve("src/theme/mauve-vars.scss"),
          },
        ],
        // css中不是由主题色变量生成的颜色,也让它抽取到主题css内,可以提高权重
        includeStyleWithColors: [
          {
            color: "#ffffff",
            // 此类颜色的是否跟随主题色梯度变化,默认false
            // inGradient: true,
          },
        ],
        // 默认取 multipleScopeVars[0].scopeName
        defaultScopeName: "",
        // 在生产模式是否抽取独立的主题css文件,extract为true以下属性有效
        extract: true,
        // 独立主题css文件的输出路径,默认取 viteConfig.build.assetsDir 相对于 (viteConfig.build.outDir)
        outputDir: "",
        // 会选取defaultScopeName对应的主题css文件在html添加link
        themeLinkTagId: "theme-link-tag",
        // "head"||"head-prepend" || "body" ||"body-prepend"
        themeLinkTagInjectTo: "head",
        // 是否对抽取的css文件内对应scopeName的权重类名移除
        removeCssScopeName: false,
        // 可以自定义css文件名称的函数
        customThemeCssFileName: (scopeName) => scopeName,
      },
      // less: {
      //   multipleScopeVars: [
      //     {
      //       scopeName: "theme-default",
      //       path: path.resolve("src/theme/default-vars.less"),
      //     },
      //     {
      //       scopeName: "theme-mauve",
      //       path: path.resolve("src/theme/mauve-vars.less"),
      //     },
      //   ],
      // },
    }),
  ],
};

在线切换主题

预设主题切换,需要做的事情

1、开发时只需,html标签的calss添加对应的scopeName,移除上个scopeName
2、打包后,如果开启extract: true,需要切换对应的link标签的href

可以选择使用如下封装好的方法,默认做好了这些事情。

import { toggleTheme } from "@zougt/vite-plugin-theme-preprocessor/dist/browser-utils";

toggleTheme({
  scopeName: "theme-default",
  // 可选,link的href处理,看情况用, 当启用 themePreprocessorPlugin 的 extract后才需要
  // customLinkHref: (href) => href,
  // 可选,默认对应 themePreprocessorPlugin 的 themeLinkTagId
  // themeLinkTagId: "theme-link-tag",
  // 可选 "head" || "body"
  // themeLinkTagInjectTo: "head",
  // 可选,对应 themePreprocessorPlugin 的 multipleScopeVars
  // multipleScopeVars
});

预设多主题编译原理示例(以 sass 为例)

变量文件内容不应该夹带样式代码,设定上只需存在变量

//src/theme/default-vars.scss
/**
*此scss变量文件作为multipleScopeVars去编译时,会自动移除!default以达到变量提升
*同时此scss变量文件作为默认主题变量文件,被其他.scss通过 @import 时,必需 !default
*/
$primary-color: #0081ff !default;
//src/theme/mauve-vars.scss
$primary-color: #9c26b0;

其他使用了变量的文件

//src/components/Button/style.scss
@import "../../theme/default-vars";
.un-btn {
  position: relative;
  display: inline-block;
  font-weight: 400;
  white-space: nowrap;
  text-align: center;
  border: 1px solid transparent;
  background-color: $primary-color;
  .anticon {
    line-height: 1;
  }
}

编译之后

src/components/Button/style.css

.un-btn {
  position: relative;
  display: inline-block;
  font-weight: 400;
  white-space: nowrap;
  text-align: center;
  border: 1px solid transparent;
}
.theme-default .un-btn {
  background-color: #0081ff;
}
.theme-mauve .un-btn {
  background-color: #9c26b0;
}
.un-btn .anticon {
  line-height: 1;
}

并且支持 Css Modules

对于*.module.scss,得到的 css 类似:

.src-components-Button-style_un-btn-1n85E {
  position: relative;
  display: inline-block;
  font-weight: 400;
  white-space: nowrap;
  text-align: center;
  border: 1px solid transparent;
}
.theme-default .src-components-Button-style_un-btn-1n85E {
  background-color: #0081ff;
}
.theme-mauve .src-components-Button-style_un-btn-1n85E {
  background-color: #9c26b0;
}
.src-components-Button-style_un-btn-1n85E
  .src-components-Button-style_anticon-1n85E {
  line-height: 1;
}

一些说明

使用了插件钩子:

  • config
  • configResolved
  • buildStart
  • generateBundle
  • transformIndexHtml

核心功能是 @masonjs/theme-utils提供的 getLessgetSass ,目前没有 stylus的需求

includeStyleWithColors

可以将某种不是由主题变量生成的颜色都抽取到主题 css 中,可能比 multipleScopeVars[].includeStyles 更加方便解决一些样式权重问题

v1.4.0+ , 动态主题模式和预设主题模式均可用

themePreprocessorPlugin({
  // css中不是由主题色变量生成的颜色,也让它抽取到主题css内,可以提高权重
  includeStyleWithColors: [
    {
      color: "#ffffff",
    },
  ],
});

multipleScopeVars[].includeStyles

只能用在预设主题模式

Type: Object

当存在以下情况时,可以用这个属性处理

.theme-blue .el-button:focus,
.theme-blue .el-button:hover {
  /*这里的color值由 $primary-color 编译得来的,所以选择器前面加了 .theme-blue 提高了权重*/
  color: #0281ff;
  border-color: #b3d9ff;
  background-color: #e6f2ff;
}
.el-button--primary:focus,
.el-button--primary:hover {
  /*这里的color值不是由 变量 编译得来的,这时就会被上面那个 color 覆盖了, 实际上这里的color才是需要的效果*/
  color: #fff;
}
const includeStyles = {
  ".el-button--primary:hover, .el-button--primary:focus": {
    color: "#FFFFFF",
  },
};
const multipleScopeVars = [
  {
    scopeName: "theme-default",
    path: path.resolve("src/theme/default-vars.less"),
    includeStyles,
  },
  {
    scopeName: "theme-mauve",
    path: path.resolve("src/theme/mauve-vars.less"),
    includeStyles,
  },
];

得到

.theme-blue .el-button:focus,
.theme-blue .el-button:hover {
  /*这里的color值由 $primary-color 编译得来的,所以选择器前面加了 .theme-blue 提高了权重*/
  color: #0281ff;
  border-color: #b3d9ff;
  background-color: #e6f2ff;
}
.theme-blue .el-button--primary:focus,
.theme-blue .el-button--primary:hover {
  /*这里的color值不是由 变量 编译得来的,通过includeStyles也提高了权重得到实际的效果*/
  color: #ffffff;
}

出现权重问题效果图

includeStyles

使用了 includeStyles 的效果图

includeStyles

webpack 版本的实现方案请查看@masonjs/theme-utils

resetStylePreprocessor

注:由于 vite 内置 css 插件未提供外接lesssass的口子(类似webpack-contrib/less-loaderimplementation),在@zougt/vite-plugin-theme-preprocessor的 buildStart 内替换了相对于根目录的 node_modules 里面的lesssass

所以想要复原lesssass包的位置,可以重新安装依赖,也可以调用 resetStylePreprocessor 方法

// resetLess.js
import { resetStylePreprocessor } from "@zougt/vite-plugin-theme-preprocessor";
resetStylePreprocessor({ langs: ["less"] });
node resetLess.js