Skip to content

Commit

Permalink
feat(): create vite-plugin-theme-preprocessor
Browse files Browse the repository at this point in the history
  • Loading branch information
zougt committed Apr 1, 2021
0 parents commit 7aa1e47
Show file tree
Hide file tree
Showing 24 changed files with 564 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# editorconfig.org

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/coverage
/dist
/node_modules
/test/fixtures
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ["@webpack-contrib/eslint-config-webpack", "prettier"],
};
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package-lock.json -diff
* text=auto
bin/* eol=lf
yarn.lock -diff
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
logs
*.log
npm-debug.log*
.eslintcache

/coverage
/dist
/local
/reports
/node_modules
index.js

.DS_Store
Thumbs.db
.idea
*.iml
.vscode
*.sublime-project
*.sublime-workspace
.nyc_output
test/outputs
7 changes: 7 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/coverage
/dist
/node_modules
/test/fixtures
CHANGELOG.md
/test/sass
/test/scss
20 changes: 20 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright JS Foundation and other contributors

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
184 changes: 184 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# @zougt/vite-plugin-theme-preprocessor

一个[vite v2.0+](https://cn.vitejs.dev/)插件,用于实现多个 `less``sass` 变量文件编译出多主题的 css

使得基于`less``sass`以及`css modules`的主题样式在线动态切换变得很简单

使用了插件钩子:

- config
- configResolved
- buildStart
- generateBundle
- transformIndexHtml

> 注:由于 vite 内置 css 插件未提供外接`less``sass`的口子(类似[`webpack-contrib/less-loader`](https://github.com/webpack-contrib/less-loader)`implementation`),在`@zougt/vite-plugin-theme-preprocessor`的 buildStart 内替换了相对于根目录的 node_modules 里面的`less``sass`
## 安装与使用

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

**vite.config.js**

```js
import themePreprocessorPlugin, {
getModulesScopeGenerater,
} from "@zougt/vite-plugin-theme-preprocessor";
export default {
plugins: [
themePreprocessorPlugin({
scss: {
multipleScopeVars: [
{
scopeName: "theme-default",
path: path.resolve("src/theme/default-vars.scss"),
},
{
scopeName: "theme-mauve",
path: path.resolve("src/theme/mauve-vars.scss"),
},
],
// 默认取 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"),
// },
// ],
// },
}),
],
};
```

## 多主题编译示例(以 sass 为例)

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

```scss
//src/theme/mauve-vars.scss
$primary-color: #9c26b0;
```

```scss
//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

```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 类似:

```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;
}
```

## 在线切换主题 css 文件

```js
const toggleTheme = (scopeName = "theme-default") => {
let styleLink = document.getElementById("theme-link-tag");
if (styleLink) {
// 假如存在id为theme-link-tag 的link标签,直接修改其href
styleLink.href = `/${scopeName}.css`;
// 注:如果是removeCssScopeName:true移除了主题文件的权重类名,就可以不用修改className 操作
document.documentElement.className = scopeName;
} else {
// 不存在的话,则新建一个
styleLink = document.createElement("link");
styleLink.type = "text/css";
styleLink.rel = "stylesheet";
styleLink.id = "theme-link-tag";
styleLink.href = `/${scopeName}.css`;
// 注:如果是removeCssScopeName:true移除了主题文件的权重类名,就可以不用修改className 操作
document.documentElement.className = scopeName;
document.head.append(styleLink);
}
};
```

webpack 版本的实现方案请查看[`@zougt/some-loader-utils`](https://github.com/GitOfZGT/some-loader-utils#getSass)
19 changes: 19 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const MIN_BABEL_VERSION = 7;

module.exports = (api) => {
api.assertVersion(MIN_BABEL_VERSION);
api.cache(true);

return {
presets: [
[
"@babel/preset-env",
{
targets: {
node: "12.0.0",
},
},
],
],
};
};
3 changes: 3 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
extends: ["@commitlint/config-conventional"],
};
6 changes: 6 additions & 0 deletions husky.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
hooks: {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
},
};
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
testEnvironment: "node",
};
4 changes: 4 additions & 0 deletions lint-staged.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
"*.js": ["eslint --fix", "prettier --write"],
"*.{json,md,yml,css,ts}": ["prettier --write"],
};
76 changes: 76 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"name": "@zougt/vite-plugin-theme-preprocessor",
"version": "1.0.0",
"description": "css theme preprocessor plugin for vite",
"license": "MIT",
"repository": "GitOfZGT/vite-plugin-theme-preprocessor",
"author": "zougt",
"homepage": "https://github.com/GitOfZGT/vite-plugin-theme-preprocessor",
"bugs": "https://github.com/GitOfZGT/vite-plugin-theme-preprocessor/issues",
"main": "dist/index.js",
"engines": {
"node": ">= 12.0.0"
},
"scripts": {
"start": "npm run build -- -w",
"clean": "del-cli dist",
"prebuild": "npm run clean",
"build": "cross-env NODE_ENV=production babel src -d dist --copy-files",
"commitlint": "commitlint --from=master",
"security": "npm audit",
"lint:prettier": "prettier --list-different .",
"lint:js": "eslint --cache .",
"lint": "npm-run-all -l -p \"lint:**\"",
"pretest": "npm run lint",
"prepare": "npm run build",
"release": "standard-version"
},
"files": [
"dist"
],
"dependencies": {
"@zougt/some-loader-utils": "^1.1.0",
"fs-extra": "^9.1.0",
"string-hash": "^1.1.3"
},
"devDependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@commitlint/cli": "^11.0.0",
"@commitlint/config-conventional": "^11.0.0",
"@webpack-contrib/defaults": "^6.3.0",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-jest": "^26.6.3",
"cross-env": "^7.0.3",
"del": "^6.0.0",
"del-cli": "^3.0.1",
"enhanced-resolve": "^5.5.0",
"eslint": "^7.13.0",
"eslint-config-prettier": "^7.1.0",
"eslint-plugin-import": "^2.22.1",
"foundation-sites": "^6.6.3",
"husky": "^4.3.6",
"jest": "^26.6.3",
"less": "^4.1.1",
"lint-staged": "^10.5.4",
"npm-run-all": "^4.1.5",
"prettier": "^2.2.1",
"sass": "^1.32.8",
"semver": "^7.3.4",
"standard-version": "^9.1.0",
"stylus": "^0.54.8"
},
"keywords": [
"vite-plugin",
"theme",
"css",
"less",
"sass",
"stylus",
"preprocessor"
],
"publishConfig": {
"registry": "https://registry.npmjs.org"
}
}
4 changes: 4 additions & 0 deletions src/substitute/less/bin/lessc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env node

// eslint-disable-next-line import/no-unresolved
require("@zougt/vite-plugin-theme-preprocessor/original/less/bin/lessc");
2 changes: 2 additions & 0 deletions src/substitute/less/dist/less.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line import/no-unresolved
export * from "@zougt/vite-plugin-theme-preprocessor/original/less/dist/less";
2 changes: 2 additions & 0 deletions src/substitute/less/dist/less.min.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line import/no-unresolved
export * from "@zougt/vite-plugin-theme-preprocessor/original/less/dist/less.min";
Loading

0 comments on commit 7aa1e47

Please sign in to comment.