├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bin └── cli.js ├── example ├── more.css └── style.css ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | example/style.js 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - 0.10 5 | - 0.12 6 | 7 | # Use container-based Travis infrastructure. 8 | # See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/ 9 | sudo: false 10 | 11 | branches: 12 | only: 13 | - master 14 | 15 | script: 16 | # Build environment. 17 | - node --version 18 | - npm --version 19 | # Simple execution tests. 20 | - bin/cli.js < example/style.css > example/style.js 21 | - cat example/style.css | bin/cli.js > example/style.js 22 | - cat example/style.css | bin/cli.js example/style.js 23 | - bin/cli.js --input example/style.css > example/style.js 24 | - bin/cli.js --input example/style.css example/style.js 25 | - bin/cli.js --input example/style.css --input example/more.css example/style.js 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Formidable Labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Maintenance Status][maintenance-image]](#maintenance-status) 2 | 3 | 4 | # CSS to Radium 5 | 6 | A CLI utility to convert the contents of a CSS file to a Radium-compatible JS object. 7 | 8 | ## Installation 9 | 10 | ``` 11 | $ npm install css-to-radium 12 | ``` 13 | 14 | ## Usage 15 | 16 | By default, `css-to-radium` works with `stdin` and `stdout`: 17 | 18 | ``` 19 | $ css-to-radium < example/style.css > example/style.js 20 | ``` 21 | 22 | You can also target a source file directly with the `--input` flag and return a converted file by specifying the target path after any options: 23 | 24 | ``` 25 | $ css-to-radium --input style.css style.js 26 | ``` 27 | 28 | Or you can mix and match the two: 29 | 30 | ``` 31 | $ css-to-radium --input example/style.css > example/style.js 32 | ``` 33 | 34 | It turns a file like this: 35 | 36 | ```css 37 | /* style.css */ 38 | .btn { 39 | background: #ccc; 40 | padding: 10px; 41 | font-size: 16px; 42 | } 43 | 44 | .btn-primary { 45 | background: orange; 46 | color: #fff; 47 | } 48 | ``` 49 | 50 | into one like this: 51 | 52 | ```js 53 | // style.js 54 | 55 | module.exports = { 56 | ".btn": { 57 | background: "#ccc", 58 | padding: 10, 59 | fontSize: 16 60 | }, 61 | ".btn-primary": { 62 | background: "orange", 63 | color: "white" 64 | } 65 | } 66 | ``` 67 | 68 | ## Options 69 | 70 | ### input 71 | 72 | `--input [inputSrc]` 73 | 74 | A source file to use as input. To process multiple files at once, include this 75 | flag multiple times: 76 | 77 | ``` 78 | $ css-to-radium --input style.css --input more.css 79 | ``` 80 | 81 | ### quote 82 | 83 | `--quote [type]` 84 | 85 | Type of quote used in generated JS. Defaults to `single`. 86 | 87 | ``` 88 | css-to-radium style.css style.js --quote double 89 | ``` 90 | 91 | ### indentSize 92 | 93 | `--indentSize [int]` 94 | 95 | Number of space characters to use for indents in generated JS. If this flag is not included, defaults to a single tab character (`\t`). 96 | 97 | ``` 98 | css-to-radium style.css style.js --indentSize=2 99 | ``` 100 | 101 | ## Webpack 102 | 103 | Using Webpack? Check out [radium-loader](https://github.com/dminkovsky/radium-loader). 104 | 105 | ## Maintenance Status 106 | 107 | **Archived:** This project is no longer maintained by Formidable. We are no longer responding to issues or pull requests unless they relate to security concerns. We encourage interested developers to fork this project and make it their own! 108 | 109 | [maintenance-image]: https://img.shields.io/badge/maintenance-archived-red.svg 110 | -------------------------------------------------------------------------------- /bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | var through2 = require('through2'); 5 | var minimist = require('minimist'); 6 | var stringifyObject = require('stringify-object'); 7 | var Kat = require('kat'); 8 | 9 | var convertCss = require('../index.js'); 10 | 11 | // ---------------------------------------------------------------------------- 12 | // Arguments 13 | // ---------------------------------------------------------------------------- 14 | var cliArgs = minimist(process.argv.slice(2)); 15 | 16 | var inputs = cliArgs.input; 17 | 18 | if (inputs) { 19 | inputs = Array.isArray(inputs) ? inputs : [ inputs ]; 20 | } 21 | 22 | // Index 0 (file path) else stdin output arguments in remainder. 23 | if (cliArgs._.length > 1) { 24 | throw new Error('Must have 0 or 1 output paths specified'); 25 | } 26 | 27 | var output = cliArgs._[0] || null; // Remaining argument. 28 | 29 | // ---------------------------------------------------------------------------- 30 | // Helpers 31 | // ---------------------------------------------------------------------------- 32 | var stringifyResult = function (data) { 33 | return stringifyObject(data, { 34 | singleQuotes: cliArgs.quote !== 'double', 35 | indent: cliArgs.indentSize ? (new Array(cliArgs.indentSize)).join(' ') : '\t' 36 | }); 37 | }; 38 | 39 | // ---------------------------------------------------------------------------- 40 | // Streams 41 | // ---------------------------------------------------------------------------- 42 | // Converter stream. 43 | var _buffer = []; 44 | var convertStream = through2(function (chunk, enc, callback) { 45 | _buffer.push(chunk.toString('utf8')); 46 | callback(); 47 | }, function (callback) { 48 | var data = _buffer.join(''); 49 | var cssObj = convertCss(data); 50 | var converted = new Buffer(stringifyResult(cssObj)); 51 | this.push(converted); 52 | callback(); 53 | }); 54 | 55 | // Encoding. 56 | process.stdin.setEncoding('utf8'); 57 | 58 | // Input: Files or stdin. 59 | var inputStream = process.stdin; 60 | 61 | if (inputs) { 62 | inputStream = new Kat(); 63 | inputs.forEach(function (input) { 64 | inputStream.add(input); 65 | }); 66 | } 67 | 68 | // Output: File or stdout. 69 | var outputStream = output ? 70 | fs.createWriteStream(output) : 71 | process.stdout; 72 | 73 | // Pipe it! 74 | inputStream 75 | .pipe(convertStream) 76 | .pipe(outputStream); 77 | -------------------------------------------------------------------------------- /example/more.css: -------------------------------------------------------------------------------- 1 | .foobar { 2 | background: black; 3 | } 4 | -------------------------------------------------------------------------------- /example/style.css: -------------------------------------------------------------------------------- 1 | .btn { 2 | background: #ccc; 3 | padding: 10px 20px; 4 | font-size: 16px; 5 | 6 | -webkit-transition: none; 7 | -moz-transition: none; 8 | -ms-transition: none; 9 | -o-transition: none; 10 | transition: none; 11 | 12 | flex: 0; 13 | 14 | line-height: 2.4; 15 | } 16 | 17 | .btn-primary { 18 | background: orange; 19 | color: #fff; 20 | -webkit-font-smoothing: antialiased; 21 | } 22 | 23 | .btn { 24 | margin: 12px; 25 | } 26 | 27 | .btn { 28 | color: red; 29 | } 30 | 31 | .btn { 32 | background: blue; 33 | } 34 | 35 | @media only screen and (min-width: 1200px) { 36 | body { 37 | background: green; 38 | } 39 | 40 | .btn { 41 | padding: 24; 42 | } 43 | } 44 | 45 | @media (max-width: 600px) { 46 | body { 47 | background: red; 48 | } 49 | } 50 | 51 | @media only screen and (min-width: 1200px) { 52 | .foobar { 53 | color: orange; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var postcss = require('postcss'); 3 | var camelCase = require('camelcase'); 4 | 5 | var sanitizeSelector = function (selector) { 6 | return selector.replace(/\n/gi, ' '); 7 | }; 8 | 9 | var convertValue = function (value) { 10 | var result = value; 11 | var resultNumber = Number(result); 12 | 13 | // Handle single pixel values (font-size: 16px) 14 | if (result.indexOf(' ') === -1 && result.indexOf('px') !== -1) { 15 | result = parseInt(result.replace('px', ''), 10); 16 | // Handle numeric values 17 | } else if (_.isNaN(resultNumber) === false) { 18 | result = resultNumber; 19 | } 20 | 21 | return result; 22 | }; 23 | 24 | var convertProp = function (prop) { 25 | var result = camelCase(prop); 26 | 27 | // Handle vendor prefixes 28 | if (prop.indexOf('-webkit') === 0) { 29 | result = result.replace('webkit', 'Webkit'); 30 | } else if (prop.indexOf('-moz') === 0) { 31 | result = result.replace('moz', 'Moz'); 32 | } else if (prop.indexOf('-o') === 0) { 33 | result = result.replace('o', 'O'); 34 | } 35 | 36 | return result; 37 | }; 38 | 39 | var convertDecl = function (decl) { 40 | return { 41 | property: convertProp(decl.prop), 42 | value: convertValue(decl.value) 43 | }; 44 | }; 45 | 46 | var convertRule = function (rule) { 47 | var returnObj = {}; 48 | var selector = sanitizeSelector(rule.selector); 49 | 50 | returnObj[selector] = _.transform(rule.nodes, function (convertedDecls, decl) { 51 | if (decl.type === 'decl') { 52 | var convertedDecl = convertDecl(decl); 53 | 54 | convertedDecls[convertedDecl.property] = convertedDecl.value; 55 | } 56 | }, {}) 57 | 58 | return returnObj; 59 | }; 60 | 61 | var convertMedia = function (media) { 62 | var returnObj = { mediaQueries: {} }; 63 | returnObj.mediaQueries[media.params] = {}; 64 | 65 | _.forEach(media.nodes, function (node) { 66 | if (node.type !== 'rule') { 67 | return; 68 | } 69 | 70 | _.merge(returnObj.mediaQueries[media.params], convertRule(node)); 71 | }); 72 | 73 | return returnObj; 74 | }; 75 | 76 | var convertCss = function (sourceCss) { 77 | var source = postcss.parse(sourceCss).nodes; 78 | 79 | return _.transform(source, function (convertedObj, node) { 80 | node.type === 'rule' && _.merge(convertedObj, convertRule(node)); 81 | node.name === 'media' && _.merge(convertedObj, convertMedia(node)); 82 | }, {}); 83 | }; 84 | 85 | module.exports = convertCss; 86 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-to-radium", 3 | "version": "1.0.4", 4 | "description": "Radium migration CLI, converts CSS to Radium-compatible JS objects", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/FormidableLabs/css-to-radium.git" 9 | }, 10 | "keywords": [ 11 | "radium", 12 | "react", 13 | "css" 14 | ], 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/FormidableLabs/css-to-radium/issues" 18 | }, 19 | "homepage": "https://github.com/FormidableLabs/css-to-radium", 20 | "dependencies": { 21 | "camelcase": "^1.0.2", 22 | "kat": "^0.3.0", 23 | "lodash": "^4.17.5", 24 | "minimist": "^1.1.0", 25 | "postcss": "^4.0.6", 26 | "stringify-object": "^1.0.0", 27 | "through2": "^0.6.3" 28 | }, 29 | "bin": { 30 | "css-to-radium": "bin/cli.js" 31 | } 32 | } 33 | --------------------------------------------------------------------------------