├── .gitignore ├── README.md ├── index.js ├── package.json ├── parser.js ├── styles.css ├── tests └── test.js └── util.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # styletron-loader 2 | Webpack loader to load CSS into a [styletron](https://github.com/rtsao/styletron/) compatible CSS object by specifying a string with CSS selectors. 3 | 4 | Very much inspired by: 5 | - https://github.com/pl12133/css-object-loader 6 | - https://github.com/rtsao/styletron/issues/108 7 | 8 | # Install 9 | `npm install -D styletron-loader` 10 | 11 | or 12 | 13 | `yarn add --dev styletron-loader` 14 | 15 | ## Usage 16 | [Documentation: Using loaders](https://webpack.js.org/concepts/loaders/) 17 | Create an entry to load `.css` files in your webpack.config: 18 | 19 | ```js 20 | module: { 21 | loaders: [{ 22 | test: /\.css$/, 23 | loaders: [ 'styletron-loader' ], 24 | exclude: /node_modules/ 25 | } 26 | ] 27 | } 28 | ``` 29 | 30 | Requiring CSS rules: 31 | 32 | ```css 33 | .button { 34 | font-size: 1.5em; 35 | color: fuchsia; 36 | } 37 | .button:hover, 38 | .button:focus { 39 | color: crimson; 40 | } 41 | @media screen and (max-width: 768px) { 42 | .button { 43 | font-size: 2em; 44 | } 45 | } 46 | .red-bg { 47 | background-color: red 48 | } 49 | ``` 50 | 51 | ```js 52 | var util = require('styletron-loader/util'); 53 | var parsedCSS = require('./styles.css'); 54 | 55 | parsedCSS['.button'] 56 | /* 57 | { 'font-size': '1.5em', 58 | color: 'fuchsia', 59 | ':hover': { color: 'crimson' }, 60 | ':focus': { color: 'crimson' }, 61 | '@media screen and (max-width: 768px)': { 'font-size': '2em' } 62 | } 63 | */ 64 | 65 | var styles = util(parsedCSS); 66 | 67 | styles('.button .red-bg'); 68 | /* 69 | { 'font-size': '1.5em', 70 | color: 'fuchsia', 71 | ':hover': { color: 'crimson' }, 72 | ':focus': { color: 'crimson' }, 73 | '@media screen and (max-width: 768px)': { 'font-size': '2em' }, 74 | 'background-color': 'red' 75 | } 76 | */ 77 | ``` -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var parser = require("./parser"); 2 | 3 | module.exports = function(source) { 4 | this.cacheable && this.cacheable(); 5 | 6 | return "module.exports = " + JSON.stringify(parser(source)) + ";"; 7 | }; 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "styletron-loader", 3 | "version": "0.6.0", 4 | "author": "deamme", 5 | "description": "Webpack loader to load a CSS object compatible with styletron", 6 | "main": "index.js", 7 | "license": "MIT", 8 | "files": [ 9 | "index.js", 10 | "parser.js", 11 | "util.js" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/deamme/styletron-loader" 16 | }, 17 | "dependencies": { 18 | "css": "^2.2.1", 19 | "lodash": "^4.17.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /parser.js: -------------------------------------------------------------------------------- 1 | var css = require("css"); 2 | var _ = require("lodash"); 3 | 4 | function getStyles(decl) { 5 | var stylesObj = {}; 6 | decl.forEach(function(obj) { 7 | stylesObj[obj.property] = obj.value; 8 | }); 9 | return stylesObj; 10 | } 11 | 12 | function normalizeParsedStyles(selectors, block, media) { 13 | block.selectors.forEach(function(selector) { 14 | var pseudo = selector.split(":")[1]; 15 | selector = selector.split(":")[0]; 16 | 17 | if (!selectors[selector]) { 18 | selectors[selector] = {}; 19 | } 20 | 21 | if (pseudo) { 22 | selectors[selector][":" + pseudo] = _.assign( 23 | selectors[selector][":" + pseudo], 24 | getStyles(block.declarations) 25 | ); 26 | } else if (media) { 27 | selectors[selector]["@media " + media] = _.assign( 28 | selectors[selector][media], 29 | getStyles(block.declarations) 30 | ); 31 | } else { 32 | selectors[selector] = _.assign( 33 | selectors[selector], 34 | getStyles(block.declarations) 35 | ); 36 | } 37 | }); 38 | } 39 | 40 | module.exports = function(source) { 41 | var parsedStyles = css.parse(source).stylesheet.rules; 42 | 43 | var selectors = {}; 44 | 45 | parsedStyles.forEach(function(block) { 46 | if (block.type == "rule") { 47 | normalizeParsedStyles(selectors, block); 48 | } else if (block.type == "media") { 49 | block.rules.forEach(function(rules) { 50 | normalizeParsedStyles(selectors, rules, block.media); 51 | }); 52 | } 53 | }); 54 | 55 | return selectors; 56 | }; 57 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | .button { 2 | font-size: 1.5em; 3 | color: fuchsia; 4 | } 5 | .button:hover, 6 | .button:focus { 7 | color: crimson; 8 | } 9 | @media screen and (max-width: 768px) { 10 | .button { 11 | font-size: 2em; 12 | } 13 | } 14 | .red-bg { 15 | background-color: red 16 | } -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var path = require("path"); 3 | var css = require("css"); 4 | var parser = require("../src/parser"); 5 | var _ = require("lodash"); 6 | 7 | var source = fs.readFileSync(path.resolve("styles.css"), "utf-8"); 8 | 9 | console.log(parser(source)); 10 | -------------------------------------------------------------------------------- /util.js: -------------------------------------------------------------------------------- 1 | var get = require("lodash/get"); 2 | var assign = require("lodash/assign"); 3 | 4 | module.exports = function(selectors) { 5 | return function() { 6 | var stylesObj = {}; 7 | var splittedArgs = arguments[0].split(" "); 8 | if (splittedArgs.length > 1) { 9 | for (var i = 0; i < splittedArgs.length; i++) { 10 | assign(stylesObj, get(selectors, splittedArgs[i])); 11 | } 12 | } else { 13 | for (var i = 0; i < arguments.length; i++) { 14 | assign(stylesObj, get(selectors, arguments[i])); 15 | } 16 | } 17 | return stylesObj; 18 | }; 19 | }; 20 | --------------------------------------------------------------------------------