├── .gitignore ├── .npmignore ├── lerna.json ├── package.json ├── packages ├── scope-css-loader │ ├── package.json │ ├── index.js │ └── README.md └── scope-jsx-loader │ ├── package.json │ ├── index.js │ └── README.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.1", 3 | "npmClient": "npm", 4 | "packages": [ 5 | "packages/*" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsx-style-scoped", 3 | "version": "1.0.0", 4 | "description": "jsx样式作用域解决方案", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "test" 8 | }, 9 | "repository": { 10 | "type": "http", 11 | "url": "https://github.com/NealST/jsx-style-scoped.git" 12 | }, 13 | "keywords": [ 14 | "jsx", 15 | "css", 16 | "scoped" 17 | ], 18 | "author": "NealST", 19 | "license": "ISC" 20 | } 21 | -------------------------------------------------------------------------------- /packages/scope-css-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scope-css-loader", 3 | "version": "1.0.2", 4 | "description": "jsx样式作用域css-loader", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "test" 8 | }, 9 | "publishConfig": { 10 | "registry": "https://registry.npmjs.org/" 11 | }, 12 | "repository": { 13 | "type": "http", 14 | "url": "https://github.com/NealST/jsx-style-scoped.git" 15 | }, 16 | "keywords": [ 17 | "jsx", 18 | "css", 19 | "scoped" 20 | ], 21 | "dependencies": { 22 | "qs": "^6.9.4" 23 | }, 24 | "author": "NealST", 25 | "license": "ISC", 26 | "gitHead": "6957ea0fbdae21721385704d05a460c0d35229bd" 27 | } 28 | -------------------------------------------------------------------------------- /packages/scope-jsx-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scope-jsx-loader", 3 | "version": "1.0.3", 4 | "description": "样式作用域的jsx loader", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "test" 8 | }, 9 | "publishConfig": { 10 | "registry": "https://registry.npmjs.org" 11 | }, 12 | "repository": { 13 | "type": "http", 14 | "url": "https://github.com/NealST/jsx-style-scoped.git" 15 | }, 16 | "keywords": [ 17 | "jsx", 18 | "css", 19 | "scoped" 20 | ], 21 | "dependencies": { 22 | "md5": "^2.2.1" 23 | }, 24 | "author": "NealST", 25 | "license": "ISC", 26 | "gitHead": "6957ea0fbdae21721385704d05a460c0d35229bd" 27 | } 28 | -------------------------------------------------------------------------------- /packages/scope-css-loader/index.js: -------------------------------------------------------------------------------- 1 | const qs = require('qs'); 2 | 3 | module.exports = function(source) { 4 | // @ts-ignore 5 | const resourceQuery = qs.parse(this.resource.split('?')[1]); 6 | const classNameReg = /\.([^{]+)(\s*)\{/g; 7 | const scopeId = resourceQuery.scopeId; 8 | const classnames = resourceQuery.classnames && resourceQuery.classnames.split('($$)'); 9 | if (scopeId && classnames) { 10 | return source.replace(classNameReg, (matchItem) => { 11 | const theClassName = matchItem.match(/\.([^{]+)(\s*)\{/)[1].trim(); 12 | // 兼容css的后代选择器模式,比如 .a .b{} 13 | const classValues = theClassName.split(/(\s+)/); 14 | const ultiClassName = classValues.map((item, index) => { 15 | const checkValue = index === 0 ? `.${item}` : item; 16 | return classnames.indexOf(checkValue) >= 0 ? `${checkValue}-${scopeId}` : checkValue; 17 | }).join(" "); 18 | return `${ultiClassName} {`; 19 | }) 20 | } 21 | return source 22 | } -------------------------------------------------------------------------------- /packages/scope-jsx-loader/index.js: -------------------------------------------------------------------------------- 1 | const styleReg = /\.(c|sc|sa|le)ss/g; 2 | 3 | const classNameReg = /className=\"([^"]+)\"/g; 4 | 5 | const md5 = require('md5'); 6 | 7 | const path = require("path"); 8 | 9 | const computedHash = {}; 10 | 11 | const computeHash = (pkgName) => { 12 | if (computedHash[pkgName]) { 13 | return computedHash[pkgName] 14 | } 15 | const hash = md5(pkgName).substr(0, 8); 16 | computedHash[pkgName] = hash; 17 | return hash; 18 | } 19 | 20 | module.exports = function(source) { 21 | const cwd = process.cwd(); 22 | const pkgName = require(path.join(cwd, 'package.json')).name; 23 | const hash = computeHash(pkgName); 24 | let classnames = []; 25 | 26 | return source.replace(classNameReg, (match) => { 27 | const classValues = match.match(/className=\"([^"]+)\"/)[1].trim().split(" "); 28 | // 转化成带.的选择器 29 | classnames = classnames.concat(classValues.map(item => `.${item}`)); 30 | return `className="${classValues.map(item => `${item.trim()}-${hash}`).join(" ")}"`; 31 | }).replace(styleReg, (match) => { 32 | return `${match}?scopeId=${hash}&classnames=${classnames.join('($$)')}`; 33 | }); 34 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jsx-style-scoped 2 | 3 | ## Description 4 | 5 | > jsx-style-scoped提供jsx编码模式下进行样式隔离的最佳解决方案,你可以告别css in js, css modules等不够优雅的开发方式。jsx-style-scoped提供了两个webpack-loader,分别是处理jsx或者tsx的scope-jsx-loader和处理样式文件的scope-css-loader。 6 | 7 | ## Install 8 | 9 | > 使用之前需要先安装两个loader: 10 | 11 | ``` 12 | npm i scope-jsx-loader --save-dev 13 | 14 | npm i scope-css-loader --save-dev 15 | ``` 16 | 17 | ## Usage 18 | 19 | > 需要在webpack配置中进行使用,示例如下: 20 | 21 | ``` javascript 22 | module.exports = { 23 | module: { 24 | rules: [ 25 | { 26 | test: /\.ts(x?)$/i, 27 | exclude: /node_modules/, 28 | use: [ 29 | { 30 | loader: 'babel-loader' 31 | }, 32 | { 33 | loader: 'ts-loader' 34 | }, 35 | { 36 | loader: 'scope-jsx-loader' 37 | } 38 | ], 39 | }, 40 | { 41 | test: /\.(c|sc|sa)ss$/i, 42 | use: [ 43 | { 44 | loader: 'style-loader', 45 | }, 46 | { 47 | loader: 'css-loader', 48 | }, 49 | { 50 | loader: 'sass-loader', 51 | }, 52 | { 53 | loader: 'scope-css-loader' 54 | } 55 | ], 56 | } 57 | ] 58 | } 59 | } 60 | ``` 61 | 62 | ## TODO 63 | 64 | * 增加其他构建工具的支持 65 | 66 | ## Contributing 67 | 68 | NealST(email: m13710224694@163.com) -------------------------------------------------------------------------------- /packages/scope-css-loader/README.md: -------------------------------------------------------------------------------- 1 | # jsx-style-scoped 2 | 3 | ## Description 4 | 5 | > jsx-style-scoped提供jsx编码模式下进行样式隔离的最佳解决方案,你可以告别css in js, css modules等不够优雅的开发方式。jsx-style-scoped提供了两个webpack-loader,分别是处理jsx或者tsx的scope-jsx-loader和处理样式文件的scope-css-loader。 6 | 7 | ## Install 8 | 9 | > 使用之前需要先安装两个loader: 10 | 11 | ``` 12 | npm i scope-jsx-loader --save-dev 13 | 14 | npm i scope-css-loader --save-dev 15 | ``` 16 | 17 | ## Usage 18 | 19 | > 需要在webpack配置中进行使用,示例如下: 20 | 21 | ``` javascript 22 | module.exports = { 23 | module: { 24 | rules: [ 25 | { 26 | test: /\.ts(x?)$/i, 27 | exclude: /node_modules/, 28 | use: [ 29 | { 30 | loader: 'babel-loader' 31 | }, 32 | { 33 | loader: 'ts-loader' 34 | }, 35 | { 36 | loader: 'scope-jsx-loader' 37 | } 38 | ], 39 | }, 40 | { 41 | test: /\.(c|sc|sa)ss$/i, 42 | use: [ 43 | { 44 | loader: 'style-loader', 45 | }, 46 | { 47 | loader: 'css-loader', 48 | }, 49 | { 50 | loader: 'sass-loader', 51 | }, 52 | { 53 | loader: 'scope-css-loader' 54 | } 55 | ], 56 | } 57 | ] 58 | } 59 | } 60 | ``` 61 | 62 | ## TODO 63 | 64 | * 增加其他构建工具的支持 65 | 66 | ## Contributing 67 | 68 | NealST(email: m13710224694@163.com) -------------------------------------------------------------------------------- /packages/scope-jsx-loader/README.md: -------------------------------------------------------------------------------- 1 | # jsx-style-scoped 2 | 3 | ## Description 4 | 5 | > jsx-style-scoped提供jsx编码模式下进行样式隔离的最佳解决方案,你可以告别css in js, css modules等不够优雅的开发方式。jsx-style-scoped提供了两个webpack-loader,分别是处理jsx或者tsx的scope-jsx-loader和处理样式文件的scope-css-loader。 6 | 7 | ## Install 8 | 9 | > 使用之前需要先安装两个loader: 10 | 11 | ``` 12 | npm i scope-jsx-loader --save-dev 13 | 14 | npm i scope-css-loader --save-dev 15 | ``` 16 | 17 | ## Usage 18 | 19 | > 需要在webpack配置中进行使用,示例如下: 20 | 21 | ``` javascript 22 | module.exports = { 23 | module: { 24 | rules: [ 25 | { 26 | test: /\.ts(x?)$/i, 27 | exclude: /node_modules/, 28 | use: [ 29 | { 30 | loader: 'babel-loader' 31 | }, 32 | { 33 | loader: 'ts-loader' 34 | }, 35 | { 36 | loader: 'scope-jsx-loader' 37 | } 38 | ], 39 | }, 40 | { 41 | test: /\.(c|sc|sa)ss$/i, 42 | use: [ 43 | { 44 | loader: 'style-loader', 45 | }, 46 | { 47 | loader: 'css-loader', 48 | }, 49 | { 50 | loader: 'sass-loader', 51 | }, 52 | { 53 | loader: 'scope-css-loader' 54 | } 55 | ], 56 | } 57 | ] 58 | } 59 | } 60 | ``` 61 | 62 | ## TODO 63 | 64 | * 增加其他构建工具的支持 65 | 66 | ## Contributing 67 | 68 | NealST(email: m13710224694@163.com) --------------------------------------------------------------------------------