├── .gitignore ├── test ├── .gitignore ├── test-config.json └── test.js ├── config.json ├── package.json ├── LICENSE.md ├── generate.js ├── tools.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | grid.css -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | grid.css 2 | test.html -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "width": "960px", 3 | "gutter": "10px", 4 | "selectors": { 5 | "container": ".grid", 6 | "element": "" 7 | }, 8 | "attribute": "data-size", 9 | "collapse": "960px", 10 | "columns": 6, 11 | } -------------------------------------------------------------------------------- /test/test-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "width": "960px", 3 | "gutter": "10px", 4 | "selectors": { 5 | "container": ".grid", 6 | "element": "" 7 | }, 8 | "attribute": "data-size", 9 | "collapse": "960px", 10 | "columns": 6 11 | } -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var griderator = require('../generate.js'); 2 | 3 | griderator.css('test/test-config.json', 'test/grid.css', function(error, data, path) { 4 | if(error) throw error; 5 | 6 | console.log('griderator.css() test:'); 7 | console.log(data); 8 | 9 | console.log('successfully wrote above (' + data.length + ' bytes) to ' + path); 10 | console.log(); 11 | }); 12 | 13 | griderator.js('test/test-config.json', function(error, data) { 14 | if(error) throw error; 15 | 16 | console.log('griderator.js() test'); 17 | console.log(data); 18 | console.log(); 19 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "griderator", 3 | "version": "1.0.9", 4 | "description": "a node.js css grid generator", 5 | "main": "generate.js", 6 | "scripts": { 7 | "test": "node test/test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/mateogianolio/griderator.git" 12 | }, 13 | "keywords": [ 14 | "grid", 15 | "generator", 16 | "griderator", 17 | "css" 18 | ], 19 | "author": "Mateo Gianolio", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/mateogianolio/griderator/issues" 23 | }, 24 | "homepage": "https://github.com/mateogianolio/griderator" 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | #The MIT License (MIT) 2 | 3 | *Copyright (c) 2015 Mateo Gianolio* 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 | -------------------------------------------------------------------------------- /generate.js: -------------------------------------------------------------------------------- 1 | var tools = require('./tools.js'); 2 | 3 | exports.css = function(file, path, callback) { 4 | tools.load(file, function(error, data) { 5 | var selectors = tools.parse(data); 6 | 7 | var values, out = ''; 8 | selectors.forEach(function(selector) { 9 | for(key in selector) { 10 | values = JSON.stringify(selector[key]).replace(/'?"/g, '').replace(/,/g, ';\n'); 11 | 12 | if(key[0] === '@') 13 | values = values.replace(/:/, ' '); 14 | 15 | out += [key, values, '\n'].join('\n'); 16 | } 17 | }); 18 | 19 | if(!out) { 20 | callback('error: could not generate css', null, null); 21 | return; 22 | } 23 | 24 | if(path) { 25 | tools.save(path, out, function(error, data) { 26 | if(error || data === null) 27 | callback(error, null, null); 28 | else 29 | callback(null, out, data); 30 | }); 31 | } else 32 | callback(null, out, null); 33 | }); 34 | }; 35 | 36 | exports.js = function(file, callback) { 37 | tools.load(file, function(error, data) { 38 | var selectors = tools.parse(data); 39 | callback(null, selectors, null); 40 | }); 41 | }; -------------------------------------------------------------------------------- /tools.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | exports.parse = function(config) { 4 | var width = parseInt(config.width); 5 | var name, selector, selectors = []; 6 | 7 | selectors.push({ 8 | "html": { 9 | "font-size": "100%" 10 | } 11 | }); 12 | 13 | selectors.push({ 14 | "*": { 15 | "margin": 0, 16 | "padding": 0, 17 | "position": "relative", 18 | "-webkit-box-sizing": "border-box", 19 | "-moz-box-sizing": "border-box", 20 | "box-sizing": "border-box" 21 | } 22 | }); 23 | 24 | name = config.selectors.container; 25 | selector = {}; 26 | selector[name] = { 27 | "width": config.width, 28 | "margin": "0 auto" 29 | }; 30 | selectors.push(selector); 31 | 32 | name = '[' + config.attribute + ']'; 33 | selector = {}; 34 | selector[name] = { 35 | "width": config.width, 36 | "padding-right": config.gutter, 37 | "display": "inline-block", 38 | "*display": "inline", 39 | "*zoom": 1, 40 | "vertical-align": "top", 41 | "overflow": "hidden", 42 | "*overflow": "visible" 43 | }; 44 | selectors.push(selector); 45 | 46 | var media = '@media screen and (max-width: ' + config.collapse + ')'; 47 | selector = {}; 48 | selector[media] = {}; 49 | selector[media][name] = { 50 | "width": "100% !important" 51 | }; 52 | selectors.push(selector); 53 | 54 | for(var i = 1; i <= config.columns; i++) { 55 | for(var j = i; j <= config.columns; j++) { 56 | if(i == j) continue; 57 | if(i > 1 && !(j % i)) continue; 58 | 59 | name = config.selectors.element + '['; 60 | name += config.attribute; 61 | name += '~="' + i + '/' + j + '"]'; 62 | 63 | selector = {}; 64 | selector[name] = { 65 | "width": ((i / j) * width) + (config.width.split(/(\d+)(?!.*\d)/).pop()), 66 | }; 67 | 68 | selectors.push(selector); 69 | } 70 | } 71 | 72 | return selectors; 73 | } 74 | 75 | exports.load = function(file, callback) { 76 | fs.readFile(file, function(error, data) { 77 | if(error || data === null) 78 | callback(error, null); 79 | else 80 | callback(null, JSON.parse(data)); 81 | }); 82 | } 83 | 84 | exports.save = function(file, data, callback) { 85 | fs.writeFile(file, data, function(error) { 86 | if(error) 87 | callback(error, null); 88 | else 89 | callback(null, file); 90 | }); 91 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Griderator 2 | 3 | [![npm](https://img.shields.io/npm/dm/griderator.svg?style=flat-square)]() 4 | 5 | A simple CSS grid generator for Node.js that supports 6 | 7 | * any width unit (```px```, ```%```, ```em```, you name it). 8 | * any amount of columns. 9 | * gutters (currently in the form of ```padding```). 10 | * collapsing at given width. 11 | 12 | Generates CSS to a file, to a string or to a javascript array. 13 | 14 | ## Installation 15 | 16 | Clone or install via ```npm``` 17 | 18 | ```bash 19 | $ npm install griderator 20 | ``` 21 | 22 | Test with 23 | 24 | ```bash 25 | $ npm test 26 | ``` 27 | 28 | ## Usage 29 | 30 | Include in your project with 31 | 32 | ```javascript 33 | var griderator = require('griderator'); 34 | ``` 35 | 36 | ## Methods 37 | 38 | ```javascript 39 | griderator.css = function(file, path, callback) 40 | ``` 41 | 42 | * **```file```** 43 | * Path to ```config.json```. 44 | * **```path```** (optional) 45 | * Output path. 46 | * **```callback(error, data, path)```** 47 | * ```error``` 48 | * Error message or ```null```. 49 | * ```data``` 50 | * A string with the generated CSS. 51 | * ```path``` 52 | * Output path. 53 | 54 | ```javascript 55 | griderator.js = function(file, callback) 56 | ``` 57 | 58 | * **```file```** 59 | * Path to ```config.json```. 60 | * **```callback(error, data)```** 61 | * ```error``` 62 | * Error message or ```null```. 63 | * ```data``` 64 | * A javascript array containing the generated CSS. 65 | 66 | ## Tools 67 | 68 | ```javascript 69 | /* @returns 70 | * an array containing the generated CSS. */ 71 | griderator.parse = function(config) 72 | ``` 73 | 74 | * **```config```** 75 | * A javascript array containing data from ```config.json```. 76 | 77 | ```javascript 78 | griderator.load = function(file, callback) 79 | ``` 80 | 81 | * **```file```** 82 | * Path to ```config.json```. 83 | * **```callback(error, data, path)```** 84 | * ```error``` 85 | * Error message or ```null```. 86 | * ```data``` 87 | * An array with the loaded data. 88 | 89 | ```javascript 90 | griderator.save = function(file, data, callback) 91 | ``` 92 | 93 | * **```file```** 94 | * Output path. 95 | * **```callback(error, path)```** 96 | * ```error``` 97 | * Error message or ```null```. 98 | * ```path``` 99 | * Output path. 100 | 101 | ## Example 102 | 103 | **config.json** 104 | ```json 105 | { 106 | "width": "960px", 107 | "gutter": "10px", 108 | "selectors": { 109 | "container": ".grid", 110 | "element": "" 111 | }, 112 | "attribute": "data-size", 113 | "collapse": "960px", 114 | "columns": 6 115 | } 116 | 117 | ``` 118 | 119 | ```collapse``` is optional. If set, a ```@media``` query will be added making the grid collapse at that width. 120 | 121 | Above configuration yields the following CSS: 122 | 123 | ```css 124 | * 125 | {margin:0; 126 | padding:0; 127 | position:relative; 128 | -webkit-box-sizing:border-box; 129 | -moz-box-sizing:border-box; 130 | box-sizing:border-box} 131 | 132 | .grid 133 | {width:960px; 134 | margin:0 auto} 135 | 136 | [data-size] 137 | {width:960px; 138 | padding-right:10px; 139 | display:inline-block; 140 | *display:inline; 141 | *zoom:1; 142 | vertical-align:top; 143 | overflow:hidden; 144 | *overflow:visible} 145 | 146 | @media screen and (max-width: 960px) 147 | {[data-size] {width:100% !important}} 148 | 149 | [data-size~="1/2"] 150 | {width:480px} 151 | 152 | [data-size~="1/3"] 153 | {width:320px} 154 | 155 | [data-size~="1/4"] 156 | {width:240px} 157 | 158 | [data-size~="1/5"] 159 | {width:192px} 160 | 161 | [data-size~="1/6"] 162 | {width:160px} 163 | 164 | [data-size~="2/3"] 165 | {width:640px} 166 | 167 | [data-size~="2/5"] 168 | {width:384px} 169 | 170 | [data-size~="3/4"] 171 | {width:720px} 172 | 173 | [data-size~="3/5"] 174 | {width:576px} 175 | 176 | [data-size~="4/5"] 177 | {width:768px} 178 | 179 | [data-size~="4/6"] 180 | {width:640px} 181 | 182 | [data-size~="5/6"] 183 | {width:800px} 184 | ``` 185 | 186 | Or this Javascript array: 187 | 188 | ```javascript 189 | [ { html: { 'font-size': '100%' } }, 190 | { '*': 191 | { margin: 0, 192 | padding: 0, 193 | position: 'relative', 194 | '-webkit-box-sizing': 'border-box', 195 | '-moz-box-sizing': 'border-box', 196 | 'box-sizing': 'border-box' } }, 197 | { '.grid': { width: '960px', margin: '0 auto' } }, 198 | { '[data-size]': 199 | { width: '960px', 200 | 'padding-right': '10px', 201 | display: 'inline-block', 202 | '*display': 'inline', 203 | '*zoom': 1, 204 | 'vertical-align': 'top', 205 | overflow: 'hidden', 206 | '*overflow': 'visible' } }, 207 | { '@media screen and (max-width: 960px)': { '[data-size]': [Object] } }, 208 | { '[data-size~="1/2"]': { width: '480px' } }, 209 | { '[data-size~="1/3"]': { width: '320px' } }, 210 | { '[data-size~="1/4"]': { width: '240px' } }, 211 | { '[data-size~="1/5"]': { width: '192px' } }, 212 | { '[data-size~="1/6"]': { width: '160px' } }, 213 | { '[data-size~="2/3"]': { width: '640px' } }, 214 | { '[data-size~="2/5"]': { width: '384px' } }, 215 | { '[data-size~="3/4"]': { width: '720px' } }, 216 | { '[data-size~="3/5"]': { width: '576px' } }, 217 | { '[data-size~="4/5"]': { width: '768px' } }, 218 | { '[data-size~="4/6"]': { width: '640px' } }, 219 | { '[data-size~="5/6"]': { width: '800px' } } ] 220 | ``` 221 | 222 | ## Todo 223 | 224 | * Add support for CSS preprocessors? 225 | 226 | ## Contribute 227 | 228 | Feel free to submit pull requests :) 229 | --------------------------------------------------------------------------------